javascript - Cómo cambiar el color de la cara en Three.js
(5)
Estoy intentando cambiar el color en una sola cara de una malla. Esto está en un contexto de WebGL. Puedo cambiar todo el color de la malla, pero no una sola cara. Código relevante a continuación:
// 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;
}
}
También inicializo el objeto, en este caso un Cubo como sigue:
// 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);
Cambiar el material hace que el cubo sea blanco, independientemente del color de la luz. La lógica de intersección aún funciona, lo que significa que seleccioné la cara correcta, pero lamentablemente el color no cambia.
Soy nuevo en Stackoverflow [bueno, es una pregunta, así que espero que mis ediciones no sean confusas]
Creo que el método listado arriba solo funciona en el WebGLRenderer
. Si busca algo que funcione tanto en CanvasRenderer
como en WebGLRenderer
, es un poco más complicado, pero sospecho que el resultado final es más eficiente tanto en términos de uso de memoria como de rendimiento.
Después de revisar la fuente de THREE.jS Projector.js, así es como lo hice:
// 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);
Este ejemplo está adaptado del código de trabajo que tengo, pero debo admitir que en realidad no he ejecutado este bloque de código exacto y que no tengo un gran historial de haberlo hecho todo bien, pero espero que ayude a cualquiera quien esta luchando
Según el Documento de geometría JS tres , para señalar una actualización en estas caras, Geometry.elementsNeedUpdate
debe configurarse en verdadero.
El siguiente fragmento de código cambia los colores de todas las caras.
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();
Soy bastante nuevo en three.js, pero la mayoría de estos ejemplos parecen demasiado largos y complicados. El siguiente código parece colorear las 12 caras triangulares de un cubo ... (WebGLRenderer r73).
Una cosa que noté al hacer esto es que el orden de las caras es un poco extraño (al menos para mí como novicio).
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
Suponiendo que "myGeometry" es la geometría que contiene la cara de la que desea cambiar el color, e "faceIndex" es el índice de la cara en particular en la que desea cambiar el color.
// 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;
}
Luego, la malla debe usar el siguiente material para que los colores de las caras se deriven de los vértices:
// this material causes a mesh to use colors assigned to vertices
var cubeMaterial = new THREE.MeshBasicMaterial(
{ color: 0xffffff, shading: THREE.FlatShading,
vertexColors: THREE.VertexColors } );
- Actualizar la librería a r53.
- Agregue
vertexColors: THREE.FaceColors
en material. Y finalmente use
face.color.setRGB( Math.random(), Math.random(), Math.random())
.Ahora no hay necesidad de atravesar el bucle por 4 lados (a, b, c, d) por
THREE.Face4
4 o 3 lados (a, b, c) porTHREE.Face3
.THREE.Face3
.Esto funciona tanto en WebGL como en Canvas.