raycast vertex debugging
raycast가 intersect point를 표면의 어떤 구역이든 집을 수 있도록 만들었다
custom mesh 감지가 잘 되도록 bounding box가 아니라 bounding sphere를 사용해서 처리했다
이제 raycast가 그려내는 선이 vertex를 가리키도록 하고, 선이 해당 버텍스의 normal 방향으로 표시되도록 해보자
가장 가까운 vertex 찾기
이렇게 빨간 plane에는 작 동작하지만,
밑의 바닥 floor에는 제대로 적용되지 않았다
floor의 geometry 형태를 바꿔도 감지되는 closest vertex는 이상하게 2 곳만 가리킨다
잘 확인해보니 4곳이다 이 경우는 cube geometry라 그런것 같은데
plane으로 다시 바꾸면 (-1.5, -1.5, 0) (-1.5, 1.5, 0) 두 점만 감지된다
실제로는 12개의 vertex로 총 4점인텐데
이 중 0번, 3번 vertex만 감지된 것
왜 이러지?
일단 위치가 이상하게 나온 것은 local to world를 안해서 그런 것이었고,
두 개만 잡히는 이유는 뭘까
회전된 floor plane
... 아?
const plane = new Mesh(planeGeometry, planeMaterial)
plane.rotateX(Math.PI / 2)
plane.receiveShadow = true
plane.position.setY(floorHeight)
plane.name = 'floor'
scene.add(plane)
보면 floor plane의 경우 x축을 중심으로 이미 회전되어있는 상태이다
원래는 서있는 형태였고, 그 상태의 geometry정보가 있기 때문에 z좌표가 계속 0이었던 것이다
즉 축을 기준으로 원래는 오른쪽 그림처럼 되어있던 판을 돌린 것이다.
그렇기에 찍힌 point의 좌표와 비교하면 항상 저 두점만 가까운 점으로 나올 수 밖에 없었던 것
어떤지 y와 z좌표값이 이상하다 싶었다...
그럼 회전되어있다는 것을 반영해서 position을 구해야하는데..
geometry transform으로 world vertex 구하기
transform되어있는 mesh의 각 지점을 world 좌표계로 바꾸어서 연산해야한다
vertex.applyMatrix4(mesh.matrixWorld)
이렇게 mesh가 world에서 어떤 transform행렬이 곱해져있는 상태인지를 알아서
행렬 연산을 처리해주어야한다
export function findClosestVertex(intersectPoint: THREE.Vector3, mesh: THREE.Mesh): THREE.Vector3{
let closestVertex: THREE.Vector3 | null = null
let closestDistance = Infinity
const positionAttribute = mesh.geometry.attributes.position
const vertex = new THREE.Vector3()
const worldVertex = new THREE.Vector3();
const worldMatrix = mesh.matrixWorld;
for (let i = 0; i < positionAttribute.count; i++) {
vertex.fromBufferAttribute(positionAttribute, i)
// Transform vertex position to world space
worldVertex.copy(vertex).applyMatrix4(worldMatrix);
const distance = intersectPoint.distanceToSquared(worldVertex)
if (distance < closestDistance) {
closestDistance = distance
closestVertex = worldVertex.clone()
}
}
return closestVertex!
}
코드를 이렇게 수정하니까 해결되었다
먼저 mesh가 world에서 적용된 matrix인 matrixWorld를 가지고
geometry에서 뽑은 vertex에 apply해야지 우리가 보고있는 transform된 형태에서의 제대로된 좌표벡터가 나온다
이걸로 distance를 구하고 그 값으로 비교를 한 worldVertex를 반환해야 제대로된 world 좌표에서의 위치를 가져올 수 있다
솔직히 mesh에 이미 transformation되어있다는 것을 인지하지 못하고 이런 삽질을 했다는 것이 컴퓨터그래픽스를 공부한 사람으로써 부끄럽지만,
이로써 raycast로 vertex debugging을 만들었으니 gui에 현재 pick한 vertex 위치를 띄우자