Javascript 如何在 Three.js 中更改面部颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11252592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change face color in Three.js
提问by adamsch1
I am attempting to change the color on a single face of a mesh. This is in a WebGL context. I can change the entire mesh color, just not a single Face. Relevant code below:
我正在尝试更改网格单个面上的颜色。这是在 WebGL 上下文中。我可以更改整个网格颜色,而不是单个 Face。相关代码如下:
// 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;
}
}
I also initialize the object, in this case a Cube as follows:
我还初始化了对象,在这种情况下是一个 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);
Changing the material makes the cube white regardless of the light color. The intersection logic still works, meaning i select the correct face, but alas the color does not change.
无论浅色如何,更改材质都会使立方体变白。交集逻辑仍然有效,这意味着我选择了正确的脸,但可惜颜色没有改变。
I'm new to Stackoverflow [well asking a question that is, so hopefully my edits are not confusing]
我是 Stackoverflow 的新手 [问一个问题,所以希望我的编辑不会混淆]
回答by Valay
- Update library to r53.
- Add
vertexColors: THREE.FaceColors
in material. And finally use
face.color.setRGB( Math.random(), Math.random(), Math.random())
.Now no need to traverse loop for 4 sides (a,b,c,d) for
THREE.Face4
or 3 sides (a,b,c) forTHREE.Face3
.This works in both WebGL and Canvas rendering.
- 将库更新到 r53。
- 加入
vertexColors: THREE.FaceColors
材料。 最后使用
face.color.setRGB( Math.random(), Math.random(), Math.random())
.现在不需要为 4 边 (a,b,c,d)
THREE.Face4
或 3 边 (a,b,c) 遍历循环THREE.Face3
。这适用于 WebGL 和 Canvas 渲染。
回答by Lee Stemkoski
Assuming that "myGeometry" is the geometry containing the face that you would like to change the color of, and "faceIndex" is the index of the particular face that you want to change the color of.
假设“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;
}
Then, the mesh needs to use the following material so that face colors are derived from the vertices:
然后,网格需要使用以下材质,以便从顶点派生面颜色:
// this material causes a mesh to use colors assigned to vertices
var cubeMaterial = new THREE.MeshBasicMaterial(
{ color: 0xffffff, shading: THREE.FlatShading,
vertexColors: THREE.VertexColors } );
回答by Gus
I'm rather new to three.js, but most of these examples seem overly long and complicated. The following code seems to color all 12 triangular faces for a cube... (WebGLRenderer r73).
我对three.js 比较陌生,但是这些示例中的大多数看起来都过于冗长和复杂。以下代码似乎为立方体的所有 12 个三角形面着色......(WebGLRenderer r73)。
One thing I noted when doing this is that the order of the faces is a little strange (to me as a novice at least).
这样做时我注意到的一件事是面孔的顺序有点奇怪(至少对我来说是新手)。
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
回答by Harish_N
As per Three JS GeometryDocument, To signal an update in this faces, Geometry.elementsNeedUpdate
needs to be set to true.
根据三个 JS 几何文档,要在此面中发出更新信号,Geometry.elementsNeedUpdate
需要将其设置为 true。
The following snippet changes the colors of all faces.
以下代码段更改了所有面的颜色。
mesh.material.vertexColors = THREE.FaceColors
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();
回答by user1691694
I think the method listed above only works in the WebGLRenderer
. If you're going for something that works in both the CanvasRenderer
and WebGLRenderer
it's a bit more complicated, but I suspect the end result is more efficient both in terms of memory use and performance.
我认为上面列出的方法仅适用于WebGLRenderer
. 如果你要的东西,在作品无论是CanvasRenderer
和WebGLRenderer
它更有点复杂,但我怀疑最终的结果无论是在内存使用和性能方面更加高效。
After going through the THREE.jS Projector.js source, this is how I did it:
通过 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);
This example is adapted from the working code I have, but I have to admit I haven't actually run this exact block of code and I don't have a great track record of getting everything right first go, but hopefully it will help anyone who's struggling
这个例子改编自我拥有的工作代码,但我不得不承认我实际上并没有运行这个确切的代码块,而且我没有把一切都做好的良好记录,但希望它会帮助任何人谁在挣扎