개발/three.js / / 2023. 2. 6. 19:53

[Capstone Project] 템플릿 vertex 적용 테스트 환경 만들기 - 1

반응형
※ 해당 글은 capstone 종합설계 프로젝트를 하면서 적었던 일지를 돌아보며 작성한 것입니다.

개발일지 2022.10.07

test용으로 만든 템플릿 모델을 vertex filter로 중복제거 vertex array를 추출하고, 인덱스를 지정해서 옮겨보는 테스트 환경을 만들어보자.

모델을 가져와서 scale을 조정하는 경우, 본래의 vertex에서 local to world 기능을 이용했을 떄 vertex position이 어떻게 바뀌는지 잘 모르겠다.

 이게 무슨 말이냐면, 처음 모델을 load 해왔을 때, vertex position은 바뀌지 않을 것이다. scale을 조정한다고 하여도, vertex의 값이 변경되는 게 아니라 mesh의 size가 변경되는 것이라고 생각했다.

intersects[0].object.localToWorld(
	new THREE.Vector3().fromBufferAttribute(positionAtt, intersects[0].face.a)
)

 그렇다면 위와 같이 fromBufferAttribute 와 localToWorld로 특정 인덱스의 vertex vector를 가져왔을 때,

scale을 조정한 world 좌표계에서 vertex를 가져왔을때 변경된 scale에 해당하는 vertex가 가져와 지는 것이 어떻게 가능한 것인지 헷갈린다.

분명 원본 vertex position 정보는 변하지 않고, scale은 mesh를 만드는 상위과정에서 이루어질 텐데 말이다.

 

cube로 우선 테스트를 해보자.

const geometry = new THREE.BoxGeometry(1)
const material = new THREE.MeshPhongMaterial({
    color: 0x156289,
    emissive: 0x072534, 
    flatShading: true
})
const cubeMesh = new THREE.Mesh(geometry, material);
scene.add(cubeMesh);
    
const scaleValue = 5
cubeMesh.scale.set(scaleValue, scaleValue, scaleValue)
// cubeMesh.position.set(scaleValue, scaleValue, scaleValue)

function onPointerClick(){
    console.log(cubeMesh.geometry.attributes)
    console.log(new THREE.Vector3().fromBufferAttribute(cubeMesh.geometry.attributes.position, cubeMesh.geometry.index.array[0]))
    console.log(cubeMesh.localToWorld(new THREE.Vector3().fromBufferAttribute(cubeMesh.geometry.attributes.position, cubeMesh.geometry.index.array[0])));
}

위와 같이 cube의 scale을 키운 상태에서 그냥 vertex position과 localToWorld를 적용한 vertex position을 뽑아보았다.

처음에는 onPointerClick에 있는 log들을 전역에서 호출하였는데, 이는 실수였다. scale이 적용되기 전 렌더링한 결과를 가지고 log를 출력하였기에,

console.log(new THREE.Vector3().fromBufferAttribute(cubeMesh.geometry.attributes.position, cubeMesh.geometry.index.array[0]))
console.log(cubeMesh.localToWorld(new THREE.Vector3().fromBufferAttribute(cubeMesh.geometry.attributes.position, cubeMesh.geometry.index.array[0])));

위 두 개가 동일하게 나왔다.

 

그 이유는

renderer.render( scene, camera );

를 실행하지 않은 상태에서는 mesh에 transform이 적용되지 않기 때문이다.

 

그래서 렌더링이 적용된 후에 뽑기 위해 click이벤트에 출력을 넣어서 실행해보니

이렇게 0.5에서 5배 증가한 2.5로 변해서 나왔다.

 

즉 localToWorld는 기존 vertex의 정보를 바탕으로 object가 translation scale roation 등 transform MVP행렬을 적용한 만큼 바꾸어 반환해준다.

반대로 worldToLocal이 있는데, 이는 Vector3 하나만을 매개변수로 받는다. 즉 Vector3좌표에다가 object에 MVP행렬을 적용한 반대의 순서로 연산해주어 local transform으로 변형해준다.

 

cube로 테스트하여서 확실히 알게되었다. scale을 변형한 후 render를 통해 mesh에 transform을 반영하면, localToWorld를 했을 때 변형된 vertex 좌표를 꺼내올 수 있다.

 

또한 본래 geometry의 vertex는 transform을 적용해도 변하지 않는 것이 맞다.

 

Issue

loader.load(testModelPath, function(glb){
    testModelObj = glb.scene.children[0]

    console.log(glb.scene.children)
    console.log(glb.scene.children[0])

 

loader.load에서 두 번째 인자가 onLoad 이벤트이다. 그런데 여기서 glb.scene안에 childern을 꺼냈을 때 이상하다.

 

console.log(glb.scene.children)
console.log(glb.scene.children[0])

children을 뽑으면 length가 1이 있어야하는데, 0이 나오고, 0번 인자에 접근하면 또 값이 나온다.

일단 loader.load안의 onLoad이벤트는 뭔가 문제가 있어 보이므로 이 안에서 처리하는 것은 지양해야할 것 같다.

loader의 문제에 대해서는 일단 넘기자.

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