May 20, 2023
Three.js journey 강의를 듣고 공부한 것들을 기록합니다.
scene을 animation하기 앞서, scene에서 어떻게 물체들을 변형시킬 수 있는지 알아야합니다. scene에서 물체를 변경시키기 위한 4가지 프로퍼티들이 있습니다.
position
은 3개의 필수적인 프로퍼티들을 가지고 있습니다.
바로 x,y,z
인데, 이는 3D 스페이스에서 무언가를 위치시키기 위한 3개의 중요한 축입니다.
Three.js에서는 y축
은 위로 가는 것이고, z축
은 뒤로 가는 것, x축
은 오른쪽으로 가는 것입니다.
1 unit의 의미는 개발하는 사람에게 달려있습니다. 1은 1 centimeter일수도, 1 meter,또는 1 kilometer일 수도 있습니다. 무엇을 만들지에 따라 unit을 그에 맞게 적용하면 됩니다. 만약 집을 만든다면 1unit은 1 meter로 생각하는 것이 좋습니다. mesh에 포지션 프로퍼티를 추가하여, 만든 큐브가 어디로 갈지 정할 수 있습니다.
const geometry = new THREE.BoxGeometry(1,1,1)
const meterial = new THREE.MeshBasicMeterial({color:0xff0000})
const mesh = new THREE.Mesh(geometry,material)
mesh.position.x=0.7
mesh.position.y =-0.6
mesh.position.z=3
scene.add(mesh)
position
프로퍼티는 Vector3
클래스의 인스턴스입니다.
이 클래스는 x,y,z 프로퍼티를 갖고 또한 많은 유용한 메서드를 가지고 있습니다.
//scene의 센터와 object의 위치를 계산하고 싶다면 아래처럼 콘솔을 찍어보면 됩니다.
console.log(mesh.position.length())
object와 카메라 사이 거리도 아래코드를 사용하면 구할 수 있습니다. 카메라 코드 아래 작성이 되어야 합니다.
console.log(mesh.position.distanceTo(camera.position))
그리고 값을 normalize할 수 있습니다. 이것의 의미는 멀리있는 vector에서 1unit으로 길이를 줄일 수 있다는 것입니다.
console.log(mesh.positon.normalize())
value를 변경하기 위해서는 x,y,z를 각각 사용해도 되지만, set 메서드를 이용해 사용할 수도 있습니다.
mesh.position.set(0.7,-0.6,1)
공간에서 positioning을 하는 것은 매우 어려운 일입니다. 이때,축에 line이 생기게 하는 AxesHelper를 사용하면 매우 좋은 솔루션이 됩니다.
const axesHelper = new THREE.AxesHelper(2)
scene.add(axesHelper)
scale또한 Vector3
입니다. 기본값으로 x,y,z는 1과 동일합니다. 이는 object에 아무런 scale이 적용되지 않았음을 의미합니다.
0.5를 value로 넣으면 object는 축에서 사이즈의 절반이될 것이고 2를 value로 넣으면 축에서 2배의 사이즈로 될 것입니다.
mesh.scale.x = 2
mesh.scale.y = 0.25
mesh.scale.z = 0.5
Rotation을 다루는 방법에는 2가지가 있습니다.
말 그대로 많이 알려진 rotation
프로퍼티를 사용하는 것이고 또 다른 방법으론 quternion
프로퍼티를 사용하는 것입니다.
rotation
프로퍼티는 x,y,z 프로퍼티들을 가집니다. 그러나 Vector3 대신 Euler
입니다.
Euler의 프로퍼티인 x,y,z를 변경하는 것은 object의 가운데에 stick을 넣고 이 stick에 object를 돌린다고 생각하면 됩니다.
y축
을 돌리는 것은 carousel과 비슷한 것이라고 생각하면 됩니다.x축
을 돌리는 것은 차의 바퀴가 돌아가는 것과 같은 것이라고 생각하면 됩니다.z축
을 돌리는 것은 비행기 propeller가 회전하는 것과 같은 것이라고 생각하면 됩니다.mesh.rotation.x = Math.PI * 0.25
mesh.rotation.y = Math.PI * 0.25
그러나, 이렇게 rotation을 섞어 쓰면, 이상한 결과를 만나게 될 수도 있습니다.
왜일까요? x축을 회전하는 동안, 다른 축의 orientaion을 변경할 수 있기 때문입니다.
rotaion은 x,y,z 이 순서대로 적용이 됩니다.
이는 axis가 더이상 동작하지 않는, gimbal lock
이라는 이상한 결과를 주기도 합니다.
이 rotation순서는reorder
메서드를 사용하여 변경될 수 있습니다.
mesh.rotation.reorder('YXZ')
mesh.rotation.x = Math.PI * 0.25
mesh.rotation.y = Math.PI * 0.25
Euler는 이해하기 쉬운 반면, order 문제가 있을 수 있습니다.
그래서 많은 엔진, 3D소프트웨어에서 다른 솔루션인 Quternion
을 사용하는 이유입니다.
Quternion
프로퍼티는 rotation을 할 수 있게 하나 order 문제를 해결하기 위한 더 수학적인 방법입니다.
그렇기에 이는 rotation
보다 더 이해하기 어렵습니다.
object3D
인스턴스는 lookAt
이라고 불리는 메서드가 있습니다.
이것을 사용하면 -z가 제공한 타겟을 마주할 수 있게 object가 자동적으로 회전합니다.
파라미터에 넣은 값이 타겟이며 이 타겟은 Vector3
여야 합니다.
camera.lookAt(new THREE.Vector3(0, - 1, 0))
position
,rotation
,scale
혼합하여 사용할 수 있습니다.
mesh.position.x = 0.7
mesh.position.y = - 0.6
mesh.position.z = 1
mesh.scale.x = 2
mesh.scale.y = 0.25
mesh.scale.z = 0.5
mesh.rotation.x = Math.PI * 0.25
mesh.rotation.y = Math.PI * 0.25
벽과 문,창문,지붕등과 함께 집을 짓는다고 해봅시다.
집을 다 만들었는데 집이 너무 작다면, 각 object를 re-scale하고 position또한 업데이트해야할 것입니다.
이 때, 모든 object를 한 컨테이너에 그룹화하여 하면 좋은 대안이 될 것입니다.
이것을 하기 위해서 Group
클래스를 사용할 수 있습니다.
const cube1 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
)
group.add(cube1)
const cube2 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0x00ff00 })
)
cube2.position.x = -2
group.add(cube2)
const cube3 = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({ color: 0x0000ff })
)
cube3.position.x = 2
group.add(cube3)
const group = new THREE.Group()
group.position.y=1
group.scale.y = 2
group.rotation.y = 0.2
scene.add(group)
위와 같이 그룹을 추가해주면 아래같이 변경됩니다.
이번에는 object의 위치를 변경하고 rotation하는 방법에 대해 알아보았습니다. 강의를 들으며 아직 이해하기 어렵고 복잡하다고 느낀 부분들이 있는데요. 나중에 복습을 하며 더 공부가 필요할 것 같네요 !-!