web-dev-qa-db-fra.com

Comment changer la couleur du visage dans Three.js

J'essaye de changer la couleur sur une seule face d'un maillage. C'est dans un contexte WebGL. Je peux changer toute la couleur du maillage, mais pas une seule face. Code pertinent ci-dessous:

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

J'initialise également l'objet, dans ce cas un Cube comme suit:

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

Le changement de matériau rend le cube blanc quelle que soit la couleur de la lumière. La logique d'intersection fonctionne toujours, ce qui signifie que je sélectionne la bonne face, mais hélas la couleur ne change pas.

Je suis nouveau sur Stackoverflow [je pose une question, donc j'espère que mes modifications ne prêtent pas à confusion]

18
adamsch1
  • Mettez à jour la bibliothèque vers r53.
  • Ajoutez vertexColors: THREE.FaceColors Dans le matériel.
  • Et enfin, utilisez face.color.setRGB( Math.random(), Math.random(), Math.random()).

    Plus besoin de parcourir la boucle pour 4 côtés (a, b, c, d) pour THREE.Face4 Ou 3 côtés (a, b, c) pour THREE.Face3.

    Cela fonctionne à la fois dans le rendu WebGL et Canvas.

Exemple

trois.js r5

24
Valay

En supposant que "myGeometry" est la géométrie contenant la face dont vous souhaitez changer la couleur, et "faceIndex" est l'index de la face particulière dont vous voulez changer la couleur.

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

Ensuite, le maillage doit utiliser le matériau suivant afin que les couleurs de face soient dérivées des sommets:

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

Je suis plutôt nouveau sur three.js, mais la plupart de ces exemples semblent trop longs et compliqués. Le code suivant semble colorer les 12 faces triangulaires d'un cube ... (WebGLRenderer r73).

Une chose que j'ai notée en faisant cela est que l'ordre des visages est un peu étrange (pour moi en tant que novice au moins).

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
4
Gus

Selon Trois géométrie JS Document, Pour signaler une mise à jour dans ces faces, Geometry.elementsNeedUpdate doit être défini sur true.

L'extrait suivant modifie les couleurs de tous les visages.

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();
2
Harish_N

Je pense que la méthode listée ci-dessus ne fonctionne que dans le WebGLRenderer. Si vous optez pour quelque chose qui fonctionne à la fois dans CanvasRenderer et WebGLRenderer, c'est un peu plus compliqué, mais je suppose que le résultat final est plus efficace en termes d'utilisation de la mémoire et de performances.

Après avoir parcouru la source THREE.jS Projector.js, voici comment je l'ai fait:

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

Cet exemple est adapté du code de travail que j'ai, mais je dois admettre que je n'ai pas réellement exécuté ce bloc de code exact et que je n'ai pas une excellente expérience pour tout faire du premier coup, mais j'espère que cela aidera n'importe qui qui lutte

1
user1691694