4

我有许多对象排列在 aTHREE.scene中,我想计算或检索一个相对值,该值指示每个对象从单个光源接收到多少光PointLight。简化示例:

块示例

将光定位在相机上时,块1的值可能为 0.50,因为 6 个面中有 3 个完全曝光,而2为 ~0.33,3~1.67。

我可以通过从光线向每个面的中心绘制一条光线并查看相交点来实现这一点,但我假设可以直接检索每个面的光照水平。

4

3 回答 3

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

    }

}
于 2012-05-24T21:12:02.523 回答
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 ++;

}
于 2012-05-24T17:54:02.257 回答
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;
}
于 2012-05-25T17:09:44.657 回答