14

ロードされた three.js .obj で実行時にイメージ テクスチャを交換しようとしています。これは、three.js の例を少し変更したコードです。

        var container, stats;
        var camera, scene, renderer;
        var mouseX = 0, mouseY = 0;
        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;


        init();
        animate();


        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
            camera.position.z = 100;

            //scene
            scene = new THREE.Scene();

            var ambient = new THREE.AmbientLight( 0x101030 );
            scene.add( ambient );

            var directionalLight = new THREE.DirectionalLight( 0xffeedd );
            directionalLight.position.set( 0, 0, 1 );
            scene.add( directionalLight );

            //manager
            var manager = new THREE.LoadingManager();
            manager.onProgress = function ( item, loaded, total ) {

                console.log( item, loaded, total );

            };

            //model
            var loader = new THREE.OBJLoader( manager );
            loader.load( 'obj/female02/female02.obj', function ( object ) {
                object.traverse( function ( child ) {

                    if ( child instanceof THREE.Mesh ) {
                        //create a global var to reference later when changing textures
                        myMesh = child;
                        //apply texture
                        myMesh.material.map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg');
                        myMesh.material.needsUpdate = true;
                    }

                } );


                object.position.y = - 80;
                scene.add( object );

            } );

            //render
            renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            window.addEventListener( 'resize', onWindowResize, false );

        }

        function newTexture() {
            myMesh.material.map = THREE.ImageUtils.loadTexture( 'textures/land_ocean_ice_cloud_2048.jpg');
            myMesh.material.needsUpdate = true;
        }

        function onWindowResize() {

            windowHalfX = window.innerWidth / 2;
            windowHalfY = window.innerHeight / 2;

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        function onDocumentMouseMove( event ) {

            mouseX = ( event.clientX - windowHalfX ) / 2;
            mouseY = ( event.clientY - windowHalfY ) / 2;

        }

        //animate
        function animate() {

            requestAnimationFrame( animate );
            render();

        }

        function render() {

            camera.position.x += ( mouseX - camera.position.x ) * .05;
            camera.position.y += ( - mouseY - camera.position.y ) * .05;

            camera.lookAt( scene.position );

            renderer.render( scene, camera );

        }

私が追加したのは、newTexture 関数と myMesh としてのメッシュへの参照だけでした。これが元の例です ( http://threejs.org/examples/webgl_loader_obj.html )。関数はエラーをスローしませんが、.obj は更新されません。私はここで基本的な何かが欠けていることを知っています..

更新:以下の優れた回答に従って、入力フィールドを介してテクスチャをスワップするためのいくつかの追加を含む正しいコードを次に示します

  var container, stats;
  var camera, scene, renderer;
  var mouseX = 0, mouseY = 0;
  var windowHalfX = window.innerWidth / 2;
  var windowHalfY = window.innerHeight / 2;
  var globalObject;

  init();
  animate();

  function init() {
      container = document.createElement('div');
      document.body.appendChild(container);

      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
      camera.position.z = 100;

      //scene
      scene = new THREE.Scene();

      var ambient = new THREE.AmbientLight( 0x101030 );
      scene.add( ambient );

      var directionalLight = new THREE.DirectionalLight( 0xffeedd );
      directionalLight.position.set( 0, 0, 1 );
      scene.add( directionalLight );

      //manager
      var manager = new THREE.LoadingManager();
      manager.onProgress = function (item, loaded, total) {
        console.log( item, loaded, total );
      };

    //model
    var loader = new THREE.OBJLoader( manager );
    loader.load( 'obj/female02/female02.obj', function (object) {
        //store global reference to .obj
        globalObject = object;

      object.traverse( function (child) {
          if ( child instanceof THREE.Mesh ) {
              child.material.map = THREE.ImageUtils.loadTexture( 'textures/grid.jpg');
              child.material.needsUpdate = true;
          }
      });

      object.position.y = - 80;
      scene.add( object );
    });

    //render
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );

    document.addEventListener( 'mousemove', onDocumentMouseMove, false );
    window.addEventListener( 'resize', onWindowResize, false );
  }

  function onWindowResize() {
    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
  }

  function onDocumentMouseMove( event ) {
    mouseX = ( event.clientX - windowHalfX ) / 2;
    mouseY = ( event.clientY - windowHalfY ) / 2;
  }

  //animate
  function animate() {
    requestAnimationFrame( animate );
    render();
  }

  function render() {
    camera.position.x += ( mouseX - camera.position.x ) * .05;
    camera.position.y += ( - mouseY - camera.position.y ) * .05;
            camera.lookAt( scene.position );
            renderer.render( scene, camera );
  }

  function newTexture() {
    var newTexturePath = "textures/" + document.getElementById("texture").value + "";

    globalObject.traverse( function ( child ) {
      if (child instanceof THREE.Mesh) {
          //create a global var to reference later when changing textures
          child;
          //apply texture
          child.material.map = THREE.ImageUtils.loadTexture(newTexturePath);
          child.material.needsUpdate = true;
      }
    });
  }
4

1 に答える 1

12

ここでの問題は、object変数に複数の子メッシュがあることです。myMeshグローバル変数を1 つだけ持つことで、最後の子メッシュのみを保存しています。したがって、このグローバル変数を使用してテクスチャを更新しようとすると、メッシュの 1 つだけがテクスチャ更新されます。おそらく、はっきりと見えない小さな隠れた部分です。

解決策は次のいずれかです。

  • 配列myMeshesグローバル変数を保存myMeshし、存在するたびにプッシュします。次に、newTexture()関数で、この配列内のすべてのアイテムを反復処理し、それらのマップ/マテリアルを更新します。
  • objectまたは、変数 ( のコールバックから返されたOBJLoaderもの) を 1 つのグローバル変数に格納します。次に、newTexture()関数で、コードで行われるようにすべてのメッシュを反復処理し ( traverse()andifステートメントを使用)、それらのマップ/マテリアルを更新します。

最後に、コードのどこかで newTexture() を呼び出すことも役に立ちます ;)

于 2013-08-22T06:21:10.777 に答える