如何使用遍历将不同的纹理应用于子对象?

时间:2016-12-06 15:06:01

标签: javascript three.js traversal

我有一个通过THREE.ObjectLoader()加载的对象,然后我遍历它。该物体由许多不同的元素组成,基本上是由面板和木棍组成的盒子,没什么复杂的。

我需要为一些子对象分配不同的纹理。

不幸的是,所有对象的纹理(material.map)都从循环中获取最后一组map。请参阅示例代码:

var objectLoader = new THREE.ObjectLoader();
objectLoader.load("carport-scene-nocolor.json", function ( object ) {

    var textureLoader = new THREE.TextureLoader();
    var glass = textureLoader.load('glass2.jpg');
    var crate = textureLoader.load('crate.gif');

    object.traverse( function ( child )
    {
        child.receiveShadow = true;
        child.castShadow = true;

        if ( child instanceof THREE.Mesh ) { 
            console.log(child.name);

            child.material.shininess = 100;
            child.material.wireframe = false;
            child.material.normalScale = new THREE.Vector2( 1, 1 );

            if( child.name === 'wooden_slats3' ) {
                child.material.map = glass;
                child.material.needsUpdate = true;
            } else {
                child.material.map = crate;
                child.material.needsUpdate = true;
            }
        }
    });
    object.position.y = -1;
    object.position.x = 0;
    object.receiveShadow = true;
    object.castShadow = true;

    scene.add( object );
    scene.fog = new THREE.Fog( 0xffffff, 50, 100 );
} );

如果我检查控制台,我可以看到遍历中的最后一个元素叫做“wooden_slats4”。我希望'wooden_slats3'为glass纹理,但事实并非如此,一切都在使用crate纹理贴图。

如果我玩这些值并更改if语句以检查child.name === 'wooden_slats4',那么它会将其应用于所有内容,因为这是对象中的最后一个子项。

我认为这可能是object.traverse如何运作的问题,但从我在网上看到的,我的方法是正确的。

作为参考,控制台输出是:

pCube1
pCube2
pCube3
pCube4
wooden_slats2
wooden_slats3
wooden_slats4

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:2)

显然编辑child.material编辑全局材质,而不仅仅是编辑子/ JS对象。

我需要克隆孩子的材料,然后应用它:

var objectLoader = new THREE.ObjectLoader();
objectLoader.load("carport-scene-nocolor.json", function ( object ) {

    var textureLoader = new THREE.TextureLoader();
    var glass = textureLoader.load('glass2.jpg');
    var crate = textureLoader.load('crate.gif');

    object.traverse( function ( child )
    {
        if ( child instanceof THREE.Mesh ) { 
            console.log(child.name);

            var material = child.material.clone();

            material.shininess = 100;
            material.wireframe = false;
            material.normalScale = new THREE.Vector2( 1, 1 );

            if( child.name === 'wooden_slats3' ) {
                material.map = glass;
            } else {
                material.map = crate;
            }
            child.material = material;
        }
    });
    object.position.y = -1;
    object.position.x = 0;
    object.receiveShadow = true;
    object.castShadow = true;

    scene.add( object );
    scene.fog = new THREE.Fog( 0xffffff, 50, 100 );
} );