three.js의 scene 구성 요소들 확인하기

3차원에서는 다양한 3차원 객체가 Scene Graph 형태로 구성되어 있습니다. 렌더링하는 결과에 따라 그 형태가 매우 복잡하게 구성될 수 있는데.. Scene Graph의 구성 요소를 확인하기 위한 간단한 함수입니다.

dumpVec3(v3, precision = 3) {
    return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
}

dumpObject(obj, lines = [], isLast = true, prefix = '') {
    const localPrefix = isLast ? '└─' : '├─';
    lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
    const dataPrefix = obj.children.length
        ? (isLast ? '  │ ' : '│ │ ')
        : (isLast ? '    ' : '│   ');
    lines.push(`${prefix}${dataPrefix} pos: ${this.dumpVec3(obj.position)}`);
    lines.push(`${prefix}${dataPrefix} rot: ${this.dumpVec3(obj.rotation)}`);
    lines.push(`${prefix}${dataPrefix} scl: ${this.dumpVec3(obj.scale)}`);
    const newPrefix = prefix + (isLast ? '  ' : '│ ');
    const lastNdx = obj.children.length - 1;
    obj.children.forEach((child, ndx) => {
        const isLast = ndx === lastNdx;
        this.dumpObject(child, lines, isLast, newPrefix);
    });
    return lines;
}

사용은 다음과 같습니다.

console.log(this.dumpObject(root).join('\n'));

결과 예는 다음과 같습니다.

*no-name* [Scene]
  │  pos: 0.000, 0.000, 0.000
  │  rot: 0.000, 0.000, 0.000
  │  scl: 1.000, 1.000, 1.000
  ├─*no-name* [DirectionalLight]
  │    pos: -250.000, 800.000, -850.000
  │    rot: 0.000, 0.000, 0.000
  │    scl: 1.000, 1.000, 1.000
  ├─*no-name* [Object3D]
  │    pos: -550.000, 40.000, -450.000
  │    rot: 0.000, 0.000, 0.000
  │    scl: 1.000, 1.000, 1.000

... 

  ├─*no-name* [Object3D]
  │ │  pos: 571.897, -76.040, -1163.608
  │ │  rot: 0.000, 0.000, 0.000
  │ │  scl: 1.000, 1.000, 1.000
  │ └─CAR_03_3 [Object3D]
  │   │  pos: 0.000, 33.000, 0.000
  │   │  rot: 0.000, 3.142, 0.000
  │   │  scl: 1.500, 1.500, 1.500
  │   └─CAR_03_3_World_ap_0 [Mesh]
  │        pos: 0.000, 0.000, 0.000
  │        rot: 0.000, 0.000, 0.000
  │        scl: 1.000, 1.000, 1.000
  └─*no-name* [Line]
       pos: 0.000, -621.000, 0.000
       rot: 0.000, 0.000, 0.000
       scl: 100.000, 100.000, 100.000

three.js에서 기본 정육면체(BoxGeometry)에 텍스쳐 맵핑하기

three.js에서 제공하는 기본 정육면체에 대해 텍스쳐 맵핑을 하는 코드는 다음과 같습니다.

const geometry = new THREE.BoxGeometry(1, 1, 1);
const loader = new THREE.TextureLoader();
const material = new THREE.MeshBasicMaterial({
    map: loader.load("flower-5.jpg", undefined, undefined, function(err) {
        alert('Error');
    }),
});
const cube = new THREE.Mesh(geometry, material);
this.scene.add(cube);

실행하면 다음과 같은 결과를 얻을 수 있습니다.

그런데 이 THREE.BoxGeometry는 각 면에 대해 다른 텍스쳐 맵핑을 지정할 수 있습니다. 아래처럼요.

const geometry = new THREE.BoxGeometry(1, 1, 1);
const loader = new THREE.TextureLoader();
const materials = [
    new THREE.MeshBasicMaterial({ map: loader.load("flower-1.jpg") }),
    new THREE.MeshBasicMaterial({ map: loader.load("flower-2.jpg") }),
    new THREE.MeshBasicMaterial({ map: loader.load("flower-3.jpg") }),
    new THREE.MeshBasicMaterial({ map: loader.load("flower-4.jpg") }),
    new THREE.MeshBasicMaterial({ map: loader.load("flower-5.jpg") }),
    new THREE.MeshBasicMaterial({ map: loader.load("flower-6.jpg") }),
];

const cube = new THREE.Mesh(geometry, materials);
this.scene.add(cube);

결과는 다음과 같습니다.

이 글은 three.js의 전체 코드가 아닌 정육면체에 텍스쳐 맵핑에 대한 코드만을 언급하고 있습니다. 전체 코드에 대한 뼈대는 아래 글을 참고 하시기 바랍니다. 위의 코드들은 모두 _setupModel 함수의 코드입니다.

three.js start project 코드