2012-05-23 4 views
4

У меня есть ряд объектов, расположенных в THREE.scene, и я хочу рассчитать или получить относительное значение, указывающее, сколько света каждый объект получает от одного источника PointLight. Упрощенный пример:Как определить количество освещенных лиц на сетке?

block example

С света, расположенным на камеру, значение Блок «ы может быть 0,50, так как 3 из 6 граней полностью открытыми, в то время как составляет ~ 0,33 и составляет ~ 1,67.

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

ответ

7

Этот код принимает во внимание глобальную матрицу объекта.

var amount = 0; 

var rotationMatrix = new THREE.Matrix4(); 
var vector = new THREE.Vector3(); 
var centroid = new THREE.Vector3(); 
var normal = new THREE.Vector3(); 

for (var i = 0; i < objects.length; i ++) { 

    var object = objects[ i ]; 

    rotationMatrix.extractRotation(object.matrixWorld); 

    for (var j = 0; j < object.geometry.faces.length; j ++) { 

     var face = object.geometry.faces[ j ]; 

     centroid.copy(face.centroid); 
     object.matrixWorld.multiplyVector3(centroid); 

     normal.copy(face.normal); 
     rotationMatrix.multiplyVector3(normal); 

     vector.sub(light.position, centroid).normalize(); 

     if (normal.dot(vector) > 0) amount ++; 

    } 

} 
+0

Похоже, что он установит 'amount' на сумму подсвеченных лиц для * всех * объектов (пожалуйста, исправьте меня, если я ошибаюсь), но информация здесь по-прежнему чрезвычайно полезна, и тест' normal' действительно отвечает титульный вопрос красиво. См. Мой ответ за то, что я использую, чтобы считать только открытые лица. –

+0

Да, это сумма всех объектов. Похоже, я немного запутался в своих требованиях. Приятно видеть, что вам удалось получить правильный код из этого. – mrdoob

4

Я думаю, что что-то вроде этого должно сделать трюк.

var amount = 0; 
var faces = mesh.geometry.faces; 
for (var i = 0; i < geometry.faces.length; i ++) { 

    if (geometry.faces[ i ].normal.dot(light.position) > 0) amount ++; 

} 
+1

Это хорошо работает для одного объекта, но в моем примере оно будет возвращать одинаковое значение для всех трех кубов. Мне нужно исключить лица из графа, которые (в основном) заблокированы от света другими объектами. Имеет ли смысл указывать «Луч» от света к каждому центроиду лица и проверять, что первый пересеченный объект === 'mesh'? –

1

(Внимание: Brute метод сила!)

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

У меня нет матрицы вращения для рассмотрения для моего приложения.

function getLightLevel(obj) { 
    /* Return percentage of obj.geometry faces exposed to light */ 
    var litCount = 0; 

    var faces = obj.geometry.faces; 
    var faceCount = faces.length; 
    var direction = new THREE.Vector3(); 
    var centroid = new THREE.Vector3(); 

    for (var i=0; i < faceCount; i++) { 
     // Test only light-facing faces (from mrdoob's first answer). 
     if (faces[i].normal.dot(light.position) > 0) { 
      centroid.add(obj.position, faces[i].centroid); 
      direction.sub(centroid, light.position).normalize(); 

      // Exclude face if centroid is obscured by another object. 
      var ray = new THREE.Ray(light.position, direction); 
      var intersects = ray.intersectObjects(objects); 

      if (intersects.length > 0 && intersects[0].face === faces[i]) { 
       litCount ++; 
      } 
     } 
    } 
    return litCount/faceCount; 
} 
+1

Это нехорошо ... Попытайтесь обойти мой предложенный код. С помощью этого кода вы делаете^2 проверки (для каждого лица вы снова проверяете все лица с помощью Ray). – mrdoob

+0

@mrdoob Это разовая проверка небольшого количества объектов, но я все еще ищу лучший способ справиться с этим. Для меня важно знать, какие лица заблокированы от света другими, и я надеялся, что может быть способ получить доступ к некоторым значениям непосредственно из системы освещения, когда тени включены. –

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

  • Нет связанных вопросов^_^