2012-06-28 4 views
14

Я пытаюсь изменить цвет на одной грани сетки. Это в контексте WebGL. Я могу изменить весь цвет сетки, просто не один Лицо. Соответствующий код ниже:Как изменить цвет лица в 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; 
    } 
} 

Я также инициализировать объект, в данном случае куба следующим образом:

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

Изменение материала делает куб белый независимо от светлого цвета. Логика пересечения все еще работает, что означает, что я выбираю правильное лицо, но, увы цвет не меняется.

Я новичок в StackOverflow [хорошо задать вопрос, который, так что надеюсь, мои правки не запутанные]

ответ

21
  • Обновить библиотеку до r53.
  • Добавить vertexColors: THREE.FaceColors в материалы.
  • И, наконец, использовать face.color.setRGB(Math.random(), Math.random(), Math.random()).

    В настоящее время нет необходимости, чтобы пройти петлю на 4 сторон (а, б, в, г) для THREE.Face4 или 3-х сторон (а, б, в) для THREE.Face3.

    Это работает как для рендеринга WebGL, так и для Canvas.

Example

three.js r53

+0

Работает в r65. –

+6

Это меня близко, но нужно добавить 'geometry.colorsNeedUpdate = true' – twmulloy

6

Предполагая, что «myGeometry» является геометрией, содержащее лицо, которое вы хотели бы изменить цвет , а «faceIndex» - это индекс конкретного лица, которое вы хотите изменить цвет.

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

Затем сетка должна использовать следующий материал так, чтобы лицо цвета получаются из вершин:

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

Спасибо Ли, я обновил свой фрагмент кода за Ваш отзыв. Увы, лицо не меняет цвет. Я думаю, что я мог бы неправильно настраивать ситуацию вне моей логики пересечения, которая препятствует изменению цвета. – adamsch1

1

Я думаю, что метод, перечисленные выше работает только в WebGLRenderer. Если вы собираетесь использовать что-то, что работает как в CanvasRenderer, так и в WebGLRenderer, это немного сложнее, но я подозреваю, что конечный результат более эффективен как с точки зрения использования памяти, так и с точки зрения производительности.

После прохождения через источник three.js Projector.js, это то, как я это сделал:

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

Этот пример заимствован из рабочего кода у меня есть, но я должен признать, что я не на самом деле запустить этот точный блок кода, и у меня нет большого опыта в том, чтобы все сразу начиналось, но, надеюсь, это поможет любому, кто борется

1

Я довольно новый для three.js, но большинство из этих примеров, кажется слишком долгим и сложным. Следующий код, кажется, окрашивает все 12 треугольных граней для куба ... (WebGLRenderer r73).

Одна вещь, которую я заметил, когда это делается, заключается в том, что порядок лиц немного странный (по крайней мере, как новичок).

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

Не нужно создавать новый цвет. Используйте 'color.setHex (0xff0000)'; – WestLangley

+0

Прохладный thx для подсказки :) Я делал это на примере, который я видел. – Gus

2

В соответствии с Three JS Geometry документа, чтобы сигнал обновления в этом лица, Geometry.elementsNeedUpdate должен быть установлен верно.

Следующий фрагмент изменяет цвета всех лиц.

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

Не создавайте экземпляр нового 'THREE.Color', если цвета лица уже существуют. Вместо этого 'face [i] .color.setRGB (1, 0, 0);', а затем 'mesh.geometry.colorsNeedUpdate = true;'. Перечитайте ссылочный документ. – WestLangley

Смежные вопросы