如何检测网格上点亮的面数?

时间:2012-05-23 18:08:30

标签: webgl three.js

我有一些THREE.scene排列的对象,我想计算或检索一个相对值,表示每个对象从单个PointLight源接收的光量。简化示例:

block example

当灯光位于相机时,Block 1 的值可能为0.50,因为6个面中的3个完全暴露,而 2 为~0.33且 3 是~1.67。

我可以通过从光线向每个面的中心绘制光线并观察相交来做到这一点,但我认为可以直接检索每个面部的光线水平。

3 个答案:

答案 0 :(得分: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 ++;

    }

}

答案 1 :(得分: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 ++;

}

答案 2 :(得分:1)

(警告:蛮力方法!)

我将此作为参考,因为我正在使用它来满足问题中描述的所有要求。如果面部的中心不能从灯光的位置直接看到,则此功能会将面部视为熄灭。

我没有为我的应用程序考虑的旋转矩阵。

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