2013-08-20 1 views
11

로드 된 three.js .obj에서 런타임에 이미지 텍스처를 스왑하려고합니다. 여기에 코드를 약간 수정과 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). 이 함수는 오류를 throw하지 않지만 .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; 
     } 
    }); 
    } 
+0

는 child.material.needsUpdate = true를'설정할 필요가 없습니다'이 경우. 'loadTexture()'에 의해 설정됩니다. 'needsUpdate'를 직접 설정하면 비동기 텍스처로드가 지연되면 문제가 발생할 수 있습니다. – WestLangley

+0

코드를 업데이트 해 주셔서 감사합니다 <3 –

답변

9

: 아래의 우수한 답변을 당 , 여기에 입력 필드을 통해 질감을 교환하기 위해 몇 가지 추가로 올바른 코드입니다 : 나는

업데이트가 .. 난 그냥 여기에 근본적인 뭔가를 누락 알고 여기서 문제는 object 변수에 여러 자식 메시가 있다는 것입니다. 오직 하나의 myMesh 전역 변수를 가짐으로써 마지막 자식 메쉬 만 저장하게됩니다. 따라서이 전역 변수를 사용하여 텍스처를 업데이트하려고하면 메시 중 하나만 텍스처 업데이트를 얻습니다. 분명히 보이지 않는 작은 숨겨진 부분 일 것입니다.

  • 저장하시오 myMeshes 배열 전역 변수와 그것으로 하나가 될 때마다 myMesh를 밀어 :

    솔루션 중 하나를하는 것입니다. 그런 다음 newTexture() 함수에서이 배열의 모든 항목을 반복하고 해당 맵/재료를 업데이트합니다.

  • 또는 변수 (OBJLoader의 콜백에서 반환 된 변수)를 하나의 단일 전역 변수로 저장하십시오. 그런 다음 newTexture() 함수에서 코드에서 완료되는 방식 (traverse()if 문 사용)과 같은 모든 메쉬를 반복하고지도/재료를 업데이트합니다. 어딘가에도 도움이 될 코드에서 newTexture()를 호출

마지막을)

+0

감사합니다! 나는 두 번째 옵션을 사용했다. 그리고 예, 콘솔에서 newTexture()를 호출하여 명확하지 않았습니다. 모든 사람들의 이익을 위해 위의 작업 코드를 게시했습니다. –

관련 문제