javascript three.js

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) por THREE.Face3 . THREE.Face3 .

    Esto funciona tanto en WebGL como en Canvas.

Example

tres.js r53