🎯 Raycaster座標変換プロセス
ステップ1: マウス座標を正規化
画面座標を-1~1の範囲に変換
const mouse = new THREE.Vector2(
((clientX - rect.left) / rect.width) * 2 - 1,
-((clientY - rect.top) / rect.height) * 2 + 1
);
↓
ステップ2: Raycasterで交差判定
カメラからレイを飛ばして、メッシュとの交点を取得
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(mesh);
↓
ステップ3: ワールド座標→ローカル座標
メッシュの逆行列を使ってローカル座標に変換
const inverseMatrix = new THREE.Matrix4()
.copy(mesh.matrixWorld)
.invert();
const localPoint = intersection.point
.clone()
.applyMatrix4(inverseMatrix);
↓
ステップ4: ローカル座標→SVG座標
メッシュのサイズに合わせてSVG座標(0~width, 0~height)に変換
const xSVG = ((localPoint.x + planeWidth/2) / planeWidth) * width;
const ySVG = ((planeHeight/2 - localPoint.y) / planeHeight) * height;
↓
ステップ5: HTML要素の判定
SVG座標がどのHTML要素に含まれるかチェック
for (let element of interactiveElements) {
if (element.contains(xSVG, ySVG)) {
element.elem.dispatchEvent(clonedEvent);
break;
}
}