개발 · 컴퓨터공학/three.js / / 2024. 6. 23. 09:09

Threejs Cloth Tailor 개발일지 - mesh transformation world matrix

728x90
반응형

 

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 위치를 띄우자 

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유