해결된 질문
작성
·
529
·
수정됨
0
강의 너무 재밌게 잘 듣고 있습니다!
roatation에서 reorder를 했을때 어떻게 동작하는 것인지 정확히 이해가 가지 않아서 질문 남겨봅니다~
reorder('YXZ') 는 어떤 것을 위해 설정한 것인지, YXZ 순서가 무엇을 의미하는지 궁금합니다~ (rotation.x, rotation.y 로 값을 설정하는데, YXZ 순서는 어떤 것을 설정해주는 것인지요?)
아래 코드처럼 테스트했을때, 1,2번 위치에 설정했을때는 잘 동작하고, 마지막에 설정했을때는 기존처럼 동작하는데, reorder() 해주는 위치도 궁금합니다. (한번 설정하면 계속 동작하는 것인지?)
// 1. 회전 전에 설정
mesh.rotation.reorder('YXZ');
mesh.rotation.y = THREE.MathUtils.degToRad(45);
// 2. 중간에 설정
mesh.rotation.reorder('YXZ');
mesh.rotation.x = THREE.MathUtils.degToRad(20);
// 3. 마지막에 설정
mesh.rotation.reorder('YXZ');
답변 1
1
안녕하세요! 제가 강사님은 아니지만 수강생으로써 똑같은 고민을 해서 답변드립니다.
XYZ일 경우 매트릭스에 업데이트 되기 전까지 코드 상의 순서와 상관없이
rotation.x -> rotation.y -> rotation.z 순으로 적용됩니다.
예를 들어 rotaion.x, rotation.y 를 각각 90도 돌리는 상황에서
XYZ 순서일 경우 육면체에서 x방향 회전으로 윗면이 정면으로 오고,
그 상태에서 y축 방향으로 90도를 돌게 되겠죠
최종적으로는 최초 위치 기준 오른쪽면이 정면으로 오게됩니다.
반면 YXZ 순서일 경우 y방향 회전이 먼저 되서 오른쪽면이 정면으로 먼저 오고,
그 후 x축 방향으로 회전이 되어 최초 위치 기준 윗면이 정면으로 오게 됩니다.
reorder 위치는 저도 잘 모르겠네요.. 실험이 필요해보입니다 ㅠ
오오 nureongi0214님, 감사합니다!
답변해주신 부분 바탕으로 조금더 찾아보고 실험해보고 깨달음을 얻었습니다ㅎㅎ
제가 헷갈렸던 부분은 회전축이었는데요~ rotation 은 world 좌표계가 아니라, object 내부좌표계를 사용하기 때문에, 한번 회전하고 나면 축이 변경되서, 회전하는 순서를 잘 정해주는 게 필요하다는 것을 알았습니다!
예로 들어주신 부분 또한 아래처럼 테스트해보았는데요~
1번째줄: 육면체 색상 확인
2번째줄: x 축으로 90도씩 회전
3번째줄: y 축으로 90도씩 회전
4번째줄: z 축으로 30도씩 회전
5번째줄: x, y 축으로 90도 회전
6번째줄: 수업 예제
2,3,4 번째 줄에서 회전 후에 object 내부 축이 변경되는 것을 확인할 수 있었습니다.
그리고 5번째 줄에서 말씀주신 예제로 테스트 했을 때, 아래와 같이 동작하는 것을 확인했습니다~
XYZ 순서: x 회전(윗면-연두색이 정면) -> y 회전 (y축이 변경되었기 때문에 그대로 윗면-연두색이 정면)
YXZ 순서: y 회전(왼쪽면-파랑색이 정면) -> x 회전 (x축이 변경되었기 때문에 왼쪽면-파랑색이 정면)
import * as THREE from 'three'; // ----- 주제: transform export default function example() { // Renderer const canvas = document.querySelector('#three-canvas'); const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1); // Scene const scene = new THREE.Scene(); // Camera const camera = new THREE.OrthographicCamera( -(window.innerWidth / window.innerHeight), // left window.innerWidth / window.innerHeight, // right 1, // top -1, // bottom 0.1, // near 1000 // far ); camera.position.y = 1; camera.position.z = 10; camera.zoom = 0.1; camera.updateProjectionMatrix(); scene.add(camera); // Light const ambientLight = new THREE.AmbientLight('white', 0.5); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight('white', 1); directionalLight.position.x = 1; directionalLight.position.z = 2; scene.add(directionalLight); // Mesh const geometry = new THREE.BoxGeometry(1, 1, 1); const material = [ new THREE.MeshStandardMaterial({ color: 'red' }), // wireframe: true new THREE.MeshStandardMaterial({ color: 'dodgerblue' }), new THREE.MeshStandardMaterial({ color: 'yellowgreen' }), new THREE.MeshStandardMaterial({ color: 'purple' }), new THREE.MeshStandardMaterial({ color: 'pink' }), new THREE.MeshStandardMaterial({ color: 'orange' }), ]; // AxesHelper const axesHelper = new THREE.AxesHelper(3); scene.add(axesHelper); function createMesh() { const mesh = new THREE.Mesh(geometry, material); const axis = new THREE.AxesHelper(1); mesh.add(axis); // object의 axis 표시 scene.add(mesh); return mesh; } const meshes = []; for (let i = 0; i < 6; i++) { const mesh_column = []; for (let j = 0; j < 10; j++) { const mesh = createMesh(); mesh.position.set(i * -2 + 5, j * -3 + 10, 0); mesh_column.push(mesh); } meshes.unshift(mesh_column); } meshes[0][0].rotation.set(THREE.MathUtils.degToRad(20), THREE.MathUtils.degToRad(20), 0); meshes[1][0].rotation.set(THREE.MathUtils.degToRad(20), THREE.MathUtils.degToRad(110), 0); meshes[2][0].rotation.set(THREE.MathUtils.degToRad(20), THREE.MathUtils.degToRad(200), 0); meshes[3][0].rotation.set(THREE.MathUtils.degToRad(20), THREE.MathUtils.degToRad(290), 0); meshes[4][0].rotation.set(THREE.MathUtils.degToRad(200), THREE.MathUtils.degToRad(-20), 0); // x축 회전 meshes[1][1].rotation.x = THREE.MathUtils.degToRad(90); meshes[2][1].rotation.x = THREE.MathUtils.degToRad(180); meshes[3][1].rotation.x = THREE.MathUtils.degToRad(270); meshes[4][1].rotation.x = THREE.MathUtils.degToRad(360); // y축 회전 meshes[1][2].rotation.y = THREE.MathUtils.degToRad(90); meshes[2][2].rotation.y = THREE.MathUtils.degToRad(180); meshes[3][2].rotation.y = THREE.MathUtils.degToRad(270); meshes[4][2].rotation.y = THREE.MathUtils.degToRad(360); // z축 회전 meshes[1][3].rotation.z = THREE.MathUtils.degToRad(30); meshes[2][3].rotation.z = THREE.MathUtils.degToRad(60); meshes[3][3].rotation.z = THREE.MathUtils.degToRad(90); meshes[4][3].rotation.z = THREE.MathUtils.degToRad(120); meshes[5][3].rotation.z = THREE.MathUtils.degToRad(150); // x, y 90도 회전 meshes[0][4].rotation.x = THREE.MathUtils.degToRad(90); meshes[0][4].rotation.y = THREE.MathUtils.degToRad(90); meshes[1][4].rotation.y = THREE.MathUtils.degToRad(90); meshes[1][4].rotation.x = THREE.MathUtils.degToRad(90); meshes[2][4].rotation.reorder('YXZ'); meshes[2][4].rotation.x = THREE.MathUtils.degToRad(90); meshes[2][4].rotation.y = THREE.MathUtils.degToRad(90); meshes[3][4].rotation.reorder('YXZ'); meshes[3][4].rotation.y = THREE.MathUtils.degToRad(90); meshes[3][4].rotation.x = THREE.MathUtils.degToRad(90); // 수업 예제 meshes[0][5].rotation.x = THREE.MathUtils.degToRad(20); meshes[1][5].rotation.y = THREE.MathUtils.degToRad(45); meshes[2][5].rotation.x = THREE.MathUtils.degToRad(20); meshes[2][5].rotation.y = THREE.MathUtils.degToRad(45); meshes[3][5].rotation.reorder('YXZ'); meshes[3][5].rotation.x = THREE.MathUtils.degToRad(20); meshes[3][5].rotation.y = THREE.MathUtils.degToRad(45); function draw() { renderer.render(scene, camera); } function setSize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.render(scene, camera); } // 이벤트 window.addEventListener('resize', setSize); draw(); }
참고
https://stackoverflow.com/questions/17517937/three-js-camera-tilt-up-or-down-and-keep-horizon-level