Pytanie Zmień tekst załadowanego pliku .obj w pliku three.js w środowisku wykonawczym


Próbuję zamienić teksturę obrazu w środowisku wykonawczym na wczytanym pliku three.js .obj. Oto kod prosto z przykładów three.js z niewielkimi modyfikacjami:

        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 );

        }

Dodałem tylko funkcję newTexture i odwołanie do siatki jako myMesh. Oto oryginalny przykład (http://threejs.org/examples/webgl_loader_obj.html). Funkcja nie generuje żadnych błędów, ale .obj nie aktualizuje się. Wiem, że po prostu brakuje mi czegoś fundamentalnego ...

Aktualizacja: Poniżej znajduje się doskonała odpowiedź, oto poprawny kod z kilkoma dodatkami do zamiany tekstur za pośrednictwem pola wejściowego:

  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;
      }
    });
  }

11
2017-08-20 00:02


pochodzenie


Nie ma potrzeby ustawiania child.material.needsUpdate = true; w tym przypadku. Jest ustawiony dla Ciebie loadTexture(). Oprawa needsUpdate sam możesz powodować problemy, jeśli asynchroniczne ładowanie tekstur jest opóźnione. - WestLangley
Dziękujemy za zaktualizowanie kodu <3 - Peter Pint


Odpowiedzi:


Problem polega na tym, że w sieci istnieje wiele siatek potomnych object zmienna. Posiadanie tylko jednego myMesh zmienna globalna, przechowujesz tylko ostatnią siatkę potomną. Dlatego przy próbie aktualizacji tekstury przy użyciu tej zmiennej globalnej tylko jedna z siatek otrzymuje aktualizację tekstury, prawdopodobnie małą ukrytą część, która nie jest wyraźnie widoczna.

Rozwiązaniem byłoby:

  • Przechowuj a myMeshes zmień globalną zmienną i wciśnij myMesh do niego za każdym razem, gdy jest jeden. Następnie w swoim newTexture() funkcja, iteruj przez wszystkie elementy w tej tablicy i aktualizuj swoje mapy / materiały.
  • Lub, zapisz object zmienna (zwrócony z OBJLoader'callback) w jedną pojedynczą zmienną globalną. Następnie w swoim newTexture() funkcja, iteracja po wszystkich siatkach, podobnie jak w kodzie (przy użyciu traverse() i if oświadczenie) i zaktualizować swoje mapy / materiały.

Wreszcie, wywołanie newTexture () gdzieś w twoim kodzie również pomogłoby;)


9
2017-08-22 06:21



Działa teraz dzięki! Użyłem drugiej opcji. Tak, nazwałem newTexture () w konsoli, więc nie było to jasne. Wysłałem powyższy kod roboczy dla dobra wszystkich. - Brian LoCicero