更改three.js在运行时的纹理加载的obj的 [英] Change texture of loaded .obj in three.js at runtime

查看:1970
本文介绍了更改three.js在运行时的纹理加载的obj的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图交换图像的纹理在运行时加载的three.js的obj。下面是three.js例子稍加修改code直:

  VAR容器,统计;
        VAR摄像,场景,渲染器;
        变种mouseX = 0,mouseY的= 0;
        变种windowHalfX = window.innerWidth / 2;
        变种windowHalfY = window.innerHeight / 2;


        在里面();
        动画();


        功能的init(){

            容器= document.createElement方法('格');
            document.body.appendChild(容器);

            摄像头=新THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,2000年);
            camera.position.z = 100;

            //现场
            现场=新THREE.Scene();

            VAR环境=新THREE.AmbientLight(0x101030);
            scene.add(环境);

            VAR平行光=新THREE.DirectionalLight(0xffeedd);
            directionalLight.position.set(0,0,1);
            scene.add(平行光);

            //经理
            VAR经理=新THREE.LoadingManager();
            manager.onProgress =函数(项目,装载,总数){

                的console.log(项目,装载,总数);

            };

            //模型
            VAR装载机=新THREE.OBJLoader(经理);
            loader.load('OBJ / female02 / female02.obj',函数(对象){
                object.traverse(函数(子){

                    如果(孩子的instanceof THREE.Mesh){
                        //改变纹理时创建一个全局变量以后参考
                        myMesh =子女;
                        //应用纹理
                        myMesh.material.map = THREE.ImageUtils.loadTexture('纹理/ ash_uvgrid01.jpg');
                        myMesh.material.needsUpdate = TRUE;
                    }

                });


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

            });

            //渲染
            渲染器=新THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth,window.innerHeight);
            container.appendChild(renderer.domElement);

            document.addEventListener(鼠标移动,onDocumentMouseMove,假);
            window.addEventListener('调整',onWindowResize,假);

        }

        功能newTexture(){
            myMesh.material.map = THREE.ImageUtils.loadTexture('纹理/ land_ocean_ice_cloud_2048.jpg');
            myMesh.material.needsUpdate = TRUE;
        }

        功能onWindowResize(){

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

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

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

        }

        功能onDocumentMouseMove(事件){

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

        }

        //动画
        功能动画(){

            requestAnimationFrame(动画);
            渲染();

        }

        功能渲染(){

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

            camera.lookAt(scene.position);

            renderer.render(场景,摄像头);

        }
 

我说的唯一的事情就是newTexture功能和引用网格作为myMesh。这里是最初的例子( http://threejs.org/examples/webgl_loader_obj.html )。该功能不抛出任何错误,但.OBJ不会更新。我知道,我只是失去了一些东西根本在这里..

更新每下面的出色答卷,这里是正确的code添加了一些新通过输入域交换的质感

  VAR容器,统计;
  VAR摄像,场景,渲染器;
  变种mouseX = 0,mouseY的= 0;
  变种windowHalfX = window.innerWidth / 2;
  变种windowHalfY = window.innerHeight / 2;
  VAR globalObject;

  在里面();
  动画();

  功能的init(){
      容器= document.createElement方法('格');
      document.body.appendChild(容器);

      摄像头=新THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,2000年);
      camera.position.z = 100;

      //现场
      现场=新THREE.Scene();

      VAR环境=新THREE.AmbientLight(0x101030);
      scene.add(环境);

      VAR平行光=新THREE.DirectionalLight(0xffeedd);
      directionalLight.position.set(0,0,1);
      scene.add(平行光);

      //经理
      VAR经理=新THREE.LoadingManager();
      manager.onProgress =函数(项目,装载,总数){
        的console.log(项目,装载,总数);
      };

    //模型
    VAR装载机=新THREE.OBJLoader(经理);
    loader.load('OBJ / female02 / female02.obj',函数(对象){
        //存储全局引用.OBJ
        globalObject =对象;

      object.traverse(函数(子){
          如果(孩子的instanceof THREE.Mesh){
              child.material.map = THREE.ImageUtils.loadTexture('纹理/ grid.jpg');
              child.material.needsUpdate = TRUE;
          }
      });

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

    //渲染
    渲染器=新THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth,window.innerHeight);
    container.appendChild(renderer.domElement);

    document.addEventListener(鼠标移动,onDocumentMouseMove,假);
    window.addEventListener('调整',onWindowResize,假);
  }

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

  功能onDocumentMouseMove(事件){
    mouseX =(event.clientX  -  windowHalfX)/ 2;
    mouseY的=(event.clientY  -  windowHalfY)/ 2;
  }

  //动画
  功能动画(){
    requestAnimationFrame(动画);
    渲染();
  }

  功能渲染(){
    camera.position.x + =(mouseX  -  camera.position.x)* 0.05;
    camera.position.y + =( -  mouseY的 -  camera.position.y)* 0.05;
            camera.lookAt(scene.position);
            renderer.render(场景,摄像头);
  }

  功能newTexture(){
    。VAR newTexturePath =材质/+的document.getElementById(纹理)值+;

    globalObject.traverse(函数(子){
      如果(孩子的instanceof THREE.Mesh){
          //改变纹理时创建一个全局变量以后参考
          儿童;
          //应用纹理
          child.material.map = THREE.ImageUtils.loadTexture(newTexturePath);
          child.material.needsUpdate = TRUE;
      }
    });
  }
 

解决方案

这里的问题是,有多个子网格中的对象变量。通过只有一个 myMesh 全局变量,你只存储的最后一个子网。因此,当您尝试使用这个全局变量来更新纹理,只有一个网格得到纹理更新,可能是一个小的隐藏部分是不清晰可见。

的解决办法是将两种:

  • 存储一个 myMeshes 数组的全局变量,推动 myMesh 到它的每一次有一个。然后在你的 newTexture()功能,遍历此数组中的所有项目,并更新他们的地图/材料。
  • 或者,对象变量(从 OBJLoader 的回调之一返回)存储到一个单一的全局变量。然后在你的 newTexture()功能,通过像它是如何在code做了所有网(使用移动()如果语句),并更新他们的地图/材料。

最后,调用newTexture()放在你的code也有助于;)

I'm trying to swap image texture at runtime on a loaded three.js .obj. Here's the code straight from three.js examples with slight modification:

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

        }

The only thing I added was the newTexture function and a reference to the mesh as myMesh. Here's the original example (http://threejs.org/examples/webgl_loader_obj.html). The function doesn't throw any errors but the .obj does not update. I know I'm just missing something fundamental here..

Update: Per the excellent answer below, here's the correct code with some additions to swap texture via an input field:

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

解决方案

The problem here is that there are multiple child meshes in the object variable. By having only one myMesh global variable, you are storing only the last child mesh. Thus when you try to update the texture using this global variable, only one of the meshes gets a texture update, probably a small hidden part that is not clearly visible.

The solution would be to either:

  • Store a myMeshes array global variable and push myMesh into it every time there is one. Then in your newTexture() function, iterate through all items in this array and update their maps/materials.
  • Or, store the object variable (the one returned from OBJLoader's callback) into one single global variable. Then in your newTexture() function, iterate through all the meshes like how it is done in the code (using traverse() and if statement), and update their maps/materials.

Lastly, calling newTexture() somewhere in your code would also help ;)

这篇关于更改three.js在运行时的纹理加载的obj的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆