【问题标题】:How to change face color in Three.js如何在 Three.js 中更改面部颜色
【发布时间】:2012-06-30 10:37:07
【问题描述】:

我正在尝试更改网格单个面上的颜色。这是在 WebGL 上下文中。我可以更改整个网格颜色,但不能更改单个面。相关代码如下:

// Updated Per Lee!

var camera = _this.camera;      
var projector = new THREE.Projector();
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1,                                  - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );

var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
var intersects = ray.intersectObjects( kage.scene.children );

if ( intersects.length > 0 ) {
    face = intersects[0].face;
    var faceIndices = ['a', 'b', 'c', 'd'];         
    var numberOfSides = ( face instanceof THREE.Face3 ) ? 3 : 4;
    // assign color to each vertex of current face
    for( var j = 0; j < numberOfSides; j++ )  {
        var vertexIndex = face[ faceIndices[ j ] ];
    // initialize color variable
    var color = new THREE.Color( 0xffffff );
    color.setRGB( Math.random(), 0, 0 );
    face.vertexColors[ j ] = color;
    }
}

我还初始化了对象,在本例中是一个 Cube,如下所示:

// this material causes a mesh to use colors assigned to vertices
var material = new THREE.MeshBasicMaterial( { 
    color: 0xf0f0f0, 
    shading: THREE.FlatShading,
    vertexColors: THREE.VertexColors 
});

var directionalLight = new THREE.DirectionalLight(0xEEEEEE);
directionalLight.position.set(10, 1, 1).normalize();
kage.scene.add(directionalLight);

var cube = new THREE.Mesh(new THREE.CubeGeometry(300, 300, 300,1,1,1), material);
cube.dynamic = true;
kage.scene.add(cube);

无论灯光颜色如何,更改材质都会使立方体变为白色。 相交逻辑仍然有效,这意味着我选择了正确的脸,但可惜颜色没有改变。

我是 Stackoverflow 的新手 [很好地提出一个问题,所以希望我的编辑不会令人困惑]

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    根据Three JS Geometry 文档,要在此面孔中发出更新信号,Geometry.elementsNeedUpdate 需要设置为 true。

    下面的sn-p改变所有面的颜色。

    mesh.material.vertexColors = THREE.FaceColors

    var faces = mesh.geometry.faces;
    
    for(var i = 0 ; i < faces.length; i++){
      var face = faces[i];
      var color = new THREE.Color("rgb(255, 0, 0)");
      face.color = color;
    }
    
    mesh.geometry.elementsNeedUpdate = true;
    
    render();
    

    【讨论】:

    • 如果面部颜色已经存在,不要实例化一个新的THREE.Color。而是先做faces[ i ].color.setRGB( 1, 0, 0 );,然后再做mesh.geometry.colorsNeedUpdate = true;。重新阅读引用的文档。
    【解决方案2】:

    我对 three.js 还比较陌生,但是这些示例中的大多数看起来都过于冗长和复杂。以下代码似乎为立方体的所有 12 个三角形面着色......(WebGLRenderer r73)。

    这样做时我注意到的一件事是面部的顺序有点奇怪(至少对我来说是新手)。

    var geometry = new THREE.BoxGeometry( 1, 1, 1 );
    console.log(geometry.faces.length); // 12 triangles
    geometry.faces[0].color = new THREE.Color(0x000000); //Right 1
    geometry.faces[1].color = new THREE.Color(0xFF0000); //Right 2
    geometry.faces[2].color = new THREE.Color(0xFF8C08); //Left 1
    geometry.faces[3].color = new THREE.Color(0xFFF702); //Left 2
    geometry.faces[4].color = new THREE.Color(0x00FF00); //Top 1
    geometry.faces[5].color = new THREE.Color(0x0000FF); //Top 2
    geometry.faces[6].color = new THREE.Color(0x6F00FF); //Bottom 1
    geometry.faces[7].color = new THREE.Color(0x530070); //Bottom 2
    geometry.faces[8].color = new THREE.Color(0x3F3F3F); //Front 1
    geometry.faces[9].color = new THREE.Color(0x6C6C6C); //Front 2
    geometry.faces[10].color = new THREE.Color(0xA7A7A7);//Rear 1
    geometry.faces[11].color = new THREE.Color(0xFFFFFF);//Rear 2
    

    【讨论】:

    • 无需实例化新颜色。使用color.setHex( 0xff0000 );
    • Cool thx for the hint :) 我是根据我看到的一个例子来做的。
    【解决方案3】:

    我认为上面列出的方法只适用于WebGLRenderer。如果您想要在CanvasRendererWebGLRenderer 中都可以使用的东西,那就有点复杂了,但我怀疑最终结果在内存使用和性能方面都更有效。

    在浏览了 THREE.jS Projector.js 源码后,我是这样做的:

    // create the face materials
    var material_1 = new THREE.MeshLambertMaterial(
        {color : 0xff0000, shading: THREE.FlatShading, overdraw : true}
    );
    var material_2 = new THREE.MeshLambertMaterial(
        {color : 0x00ff00, shading: THREE.FlatShading, overdraw : true}
    );
    
    // create a geometry (any should do)
    var geom = new THREE.CubeGeometry(1,1,1);
    
    // add the materials directly to the geometry
    geom.materials.push(material_1);
    geom.materials.push(material_2);
    
    // assign the material to individual faces (note you assign the index in 
    // the geometry, not the material)
    for( var i in geom.faces ) {
        var face = geom.faces[i];
        face.materialIndex = i%geom.materials.length;
    }
    
    // create a special material for your mesh that tells the renderer to use the 
    // face materials
    var material = new THREE.MeshFaceMaterial();
    var mesh = new THREE.Mesh(geom, material);
    

    这个例子改编自我的工作代码,但我不得不承认我并没有真正运行过这个确切的代码块,而且我没有很好的记录来让一切都正确,但希望它将帮助任何正在苦苦挣扎的人

    【讨论】:

      【解决方案4】:
      • 将库更新到 r53。
      • 添加vertexColors: THREE.FaceColors 材料。
      • 最后使用face.color.setRGB( Math.random(), Math.random(), Math.random())

        现在不需要遍历循环 4 THREE.Face4 的边 (a,b,c,d) 或 3 边 (a,b,c) THREE.Face3.

        这适用于 WebGL 和 Canvas 渲染。

      Example

      three.js r53

      【讨论】:

      • 这让我很接近,但需要添加geometry.colorsNeedUpdate = true
      • 由于这是最佳答案,我会注意到docs 同时具有colorsNeedUpdateelementsNeedUpdate。我认为您需要两者,但 elementsNeedUpdate 是真正导致颜色显示给我的原因。编辑:啊,我更仔细地阅读了documentation。看起来这取决于你把颜色放在哪里。
      【解决方案5】:

      假设“myGeometry”是包含您要更改颜色的面的几何图形,而“faceIndex”是您要更改颜色的特定面的索引。

      // the face's indices are labeled with these characters 
      var faceIndices = ['a', 'b', 'c', 'd'];  
      
      var face = myGeometry.faces[ faceIndex ];   
      
      // determine if face is a tri or a quad
      var numberOfSides = ( face instanceof THREE.Face3 ) ? 3 : 4;
      
      // assign color to each vertex of current face
      for( var j = 0; j < numberOfSides; j++ )  
      {
          var vertexIndex = face[ faceIndices[ j ] ];
          // initialize color variable
          var color = new THREE.Color( 0xffffff );
          color.setRGB( Math.random(), 0, 0 );
          face.vertexColors[ j ] = color;
      }
      

      然后,网格需要使用以下材质,以便从顶点导出面颜色:

      // this material causes a mesh to use colors assigned to vertices
      var cubeMaterial = new THREE.MeshBasicMaterial( 
          { color: 0xffffff, shading: THREE.FlatShading, 
          vertexColors: THREE.VertexColors } );
      

      【讨论】:

      • 感谢 Lee,我根据您的反馈更新了我的代码 sn-p。唉,脸没有变颜色。我想我可能在交叉点逻辑之外设置不正确,这会阻止颜色变化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多