2012-06-28 37 views
14

Ich versuche, die Farbe auf einer einzigen Seite eines Netzes zu ändern. Dies ist in einem WebGL-Kontext. Ich kann die gesamte Mesh-Farbe ändern, nur kein einziges Face. Relevante Code unten:So ändern Sie die Gesichtsfarbe in 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; 
    } 
} 

ich initialisieren auch das Objekt, in diesem Fall ein Würfel wie folgt:

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

das Material ändern macht der Würfel weiß, unabhängig von der Lichtfarbe. Die Intersektionslogik funktioniert immer noch, dh ich wähle das richtige Gesicht aus, aber die Farbe ändert sich nicht.

Ich bin neu zu Stackoverflow [auch eine Frage stellen, die ist, so hoffentlich meine Änderungen nicht verwirrend sind]

Antwort

21
  • Update-Bibliothek zu r53 kämpft.
  • Fügen Sie vertexColors: THREE.FaceColors in Material hinzu.
  • Und schließlich face.color.setRGB(Math.random(), Math.random(), Math.random()) verwenden.

    Nun zu durchlaufen keine Notwendigkeit Schleife für 4 Seiten (a, b, c, d) für THREE.Face4 oder 3 Seiten (a, b, c) für THREE.Face3.

    Dies funktioniert sowohl im WebGL-und Canvas-Rendering.

Example

three.js r53

+0

Arbeiten in r65. –

+6

Dies brachte mich in die Nähe, aber ich musste 'geometry.colorsNeedUpdate = true' hinzufügen – twmulloy

6

Unter der Annahme, dass „myGeometry“ ist die Geometrie des Gesichts enthält, die Sie möchten, dass die Farbe ändern, und "faceIndex" ist der Index des bestimmten Bereichs, in dem Sie die Farbe ändern möchten.

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

Dann muss das Netz das folgende Material verwenden, so dass die Gesichtsfarben aus den Eckpunkten ableiten:

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

Vielen Lee, ich pro Feedback meinen Code-Schnipsel aktualisiert. Leider ändert das Gesicht die Farbe nicht. Ich denke, dass ich Dinge außerhalb meiner Kreuzungslogik falsch einrichten werde, die verhindert, dass die Farbänderung bleibt. – adamsch1

1

Ich denke, die oben beschriebene Methode nur in den WebGLRenderer arbeitet aufgeführt. Wenn Sie nach etwas suchen, das sowohl in CanvasRenderer als auch in WebGLRenderer funktioniert, ist es etwas komplizierter, aber ich vermute, dass das Endergebnis effizienter ist, sowohl in Bezug auf den Speicherverbrauch als auch auf die Leistung.

Nachdem man durch die Three.js Projector.js Quelle, das ist, wie ich es tat:

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

Dieses Beispiel aus dem Arbeitscode angepasst ist, die ich habe, aber ich habe ich nicht zugeben laufen tatsächlich genau diesen Code-Block und ich habe nicht eine große Erfolgsgeschichte den alles immer gleich beim ersten gehen, aber es wird hoffentlich helfen, wer

1

Ich bin ziemlich neu zu three.js, aber die meisten dieser Beispiele scheinen zu lang und kompliziert. Der folgende Code scheint alle 12 dreieckigen Flächen für einen Würfel zu färben ... (WebGLRenderer r73).

Eine Sache, die ich dabei bemerkte, ist, dass die Reihenfolge der Gesichter ein wenig seltsam ist (für mich als Anfänger zumindest).

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

Keine Notwendigkeit, eine neue Farbe zu instanziieren. Verwende 'color.setHex (0xff0000)'; – WestLangley

+0

Cool thx für den Hinweis :) Ich machte das anhand eines Beispiels, das ich gesehen hatte. – Gus

2

Per Three JS Geometry Dokument, ein Update zu signalisieren in diesen Gesichtern, Geometry.elementsNeedUpdate muss auf true gesetzt werden.

Das folgende Snippet ändert die Farben aller Flächen.

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

NICHT eine neue 'THREE.Color' instanziieren, wenn bereits Flächenfarben vorhanden sind. Setzen Sie stattdessen 'faces [i] .color.setRGB (1, 0, 0);' und dann 'mesh.geometry.colorsNeedUpdate = true;'. Lies das referenzierte Dokument erneut. – WestLangley

Verwandte Themen