2013-08-20 12 views
11

Ich versuche, Bildtextur zur Laufzeit auf eine geladene three.js .obj zu tauschen. Hier ist der Code direkt aus three.js Beispielen mit geringfügiger Änderung:Ändern der Textur der geladenen .obj in three.js zur Laufzeit

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

     } 

Das einzige, was ich hinzugefügt war die newTexture Funktion und ein Verweis auf das Netz als myMesh. Hier ist das Originalbeispiel (http://threejs.org/examples/webgl_loader_obj.html). Die Funktion wirft keine Fehler, aber die OBJ-Datei wird nicht aktualisiert. Ich weiß, ich bin fehlt nur etwas Grundsätzliches hier ..

aktualisieren: Pro die ausgezeichnete Antwort unten, hier ist der richtige Code mit einigen Ergänzungen Textur über ein Eingabefeld zu tauschen:

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

Es besteht keine Notwendigkeit 'child.material.needsUpdate = true gesetzt,' in diesem Fall. Es wird für Sie mit 'loadTexture()' gesetzt. Wenn Sie 'needsUpdate' selbst einstellen, kann dies zu Problemen führen, wenn das Laden der asynchronen Textur verzögert wird. – WestLangley

+0

Vielen Dank für die Aktualisierung des Codes <3 –

Antwort

9

Das Problem besteht darin, dass in der Variablen object mehrere untergeordnete Netze vorhanden sind. Wenn Sie nur eine globale Variable haben, speichern Sie nur das letzte untergeordnete Netz. Wenn Sie also versuchen, die Textur mit dieser globalen Variable zu aktualisieren, erhält nur eines der Meshes ein Textur-Update, wahrscheinlich ein kleiner versteckter Teil, der nicht klar sichtbar ist.

  • Shop eine myMeshes Array globale Variable und myMesh hinein schiebt jedes Mal, es ist:

    Die Lösung entweder sein würde. Dann iterieren Sie in Ihrer newTexture() Funktion alle Elemente in diesem Array und aktualisieren Sie ihre Karten/Materialien.

  • Oder speichern Sie die object Variable (die von OBJLoader Callback zurückgegeben) in eine einzige globale Variable. Dann, in Ihrer newTexture() Funktion, durchlaufen Sie alle Maschen wie, wie es im Code getan wird (unter Verwendung traverse() und if Anweisung), und aktualisieren Sie ihre Karten/Materialien.

Schließlich ruft newTexture() irgendwo im Code würde auch helfen;)

+0

Es funktioniert jetzt danke! Ich habe die zweite Option benutzt. Und ja, ich rief newTexture() in der Konsole an, so dass es nicht klar war. Ich habe den obigen Arbeitscode zum Wohle aller veröffentlicht. –

Verwandte Themen