2012-06-28 25 views
14

Estoy intentando cambiar el color de una sola cara de una malla. Esto está en un contexto WebGL. Puedo cambiar todo el color de la malla, solo una cara. código correspondiente a continuación:Cómo cambiar el color de la cara en Three.js

// 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 inicializar el objeto, en este caso un cubo de la siguiente manera:

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

Cambio del material hace que el cubo blanco sin importar el color de la luz. La lógica de intersección sigue funcionando, lo que significa que selecciono la cara correcta, pero desafortunadamente el color no cambia.

Soy nuevo en Stackoverflow [así haciendo una pregunta que es, así que espero que mis ediciones no son confusas]

Respuesta

21
  • Actualizar biblioteca a r53.
  • Agregar vertexColors: THREE.FaceColors en material.
  • Y finalmente use face.color.setRGB(Math.random(), Math.random(), Math.random()).

    Ahora hay necesidad de atravesar bucle para 4 lados (a, b, c, d) para THREE.Face4 o 3 lados (a, b, c) para THREE.Face3.

    Esto funciona tanto en WebGL como en el procesamiento de Lienzos.

Example

three.js r53

+0

Trabajando en r65. –

+6

Esto me acercó, pero necesitaba agregar 'geometry.colorsNeedUpdate = true' – twmulloy

6

Suponiendo que "myGeometry" es la geometría que contiene la cara que le gustaría cambiar el color de y "faceIndex" es el índice de la cara 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; 
} 

Entonces, la malla tiene que utilizar el siguiente material de modo que los colores de la cara se derivan 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 }); 
+0

gracias a Lee, he actualizado mi fragmento de código por sus comentarios. Por desgracia, la cara no está cambiando de color. Creo que podría estar configurando cosas incorrectamente fuera de mi lógica de intersección, lo que impide que el cambio de color se mantenga. – adamsch1

1

creo que el método mencionado anteriormente sólo funciona en el WebGLRenderer. Si busca algo que funcione tanto en el CanvasRenderer como en el 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 pasar por la fuente Three.js Projector.js, esto es cómo 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 es una adaptación del código de trabajo que tengo, pero tengo que admitir que no tengo en realidad ejecuto este bloque exacto de código y no tengo un gran historial de conseguir todo bien primero, pero espero que ayude a cualquiera que tenga dificultades

1

Soy bastante nuevo en three.js, pero la mayoría de estos ejemplos parecen excesivamente largo y complicado. 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 (para mí, como novato al menos).

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 
+7

No es necesario crear una instancia de un nuevo color. Use 'color.setHex (0xff0000)'; – WestLangley

+0

Cool thx por la pista :) Estaba haciendo eso en base a un ejemplo que había visto. – Gus

2

Según Three JS Geometry documento, para señalar una actualización en este enfrenta, Geometry.elementsNeedUpdate necesita ser establecido en true.

El siguiente fragmento 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(); 
+3

NO crea una instancia de un nuevo 'THREE.Color' si los colores de la cara ya existen. En su lugar, haga 'faces [i] .color.setRGB (1, 0, 0);' y luego 'mesh.geometry.colorsNeedUpdate = true;'. Vuelva a leer el documento al que se hace referencia. – WestLangley

Cuestiones relacionadas