Three.js射线投射相交物体返回奇怪的面法线

4
我有一个模型和一个射线投射器相交。射线投射器返回正确的点,但是面法线向量与我的期望不同。Three.js内置了VertexNormalsHelper,当我使用它时显示正确的法线,但是当我创建两个立方体时,一个将位于交点位置,另一个将位于法向量位置,就像这样:
红色立方体是射线投射器的交点,蓝色立方体是面法线。
我的代码很简单,只是一个射线投射器,并将点的位置复制到立方体中。当我加载我的模型时,我更新了几何体上的一切。我使用Orbitcontrols进行相机移动。
var intersects = this.checkIntersection(this.surfaceModel);

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

    var p = intersects[ 0 ].point;

    var normal = intersects[ 0 ].face.normal.clone();

    //Red & Blue cube position update
    this.pointHelper_A.position.copy(p);
    this.pointHelper_B.position.copy(normal);

这是一个开启VertexNormalsHelper后的图片,你可以看到法线在这里很好:

enter image description here

3个回答

1
我学习了一些向量数学,因此法向量位于正确的位置。当您需要在射线交点处获得垂直于相交面的点时,您需要将faceNormalVector乘以标量,这将是面和新点之间的距离,然后将此新向量添加到交点。

0
我已经阅读了VertexNormalsHelper的源代码,并从中创建了一个函数,可以给出面的法向量。因此,它可以告诉您该点,但我不认为这是主要问题的真正解决方案,而且它有许多操作。
以下是代码:
(object: THREE.Mesh, face: THREE.Face3)
this.getFaceNormalPosition = function (object, face) {

    var v1 = new THREE.Vector3();

    var keys = ['a', 'b', 'c', 'd'];

    object.updateMatrixWorld(true);

    var size = (size !== undefined) ? size : 1;

    var normalMatrix = new THREE.Matrix3();

    normalMatrix.getNormalMatrix(object.matrixWorld);

    var vertices = new THREE.Vector3();

    var verts = object.geometry.vertices;

    var faces = object.geometry.faces;

    var worldMatrix = object.matrixWorld;


    for (var j = 0, jl = face.vertexNormals.length; j < jl; j++) {

        var vertexId = face[ keys[ j ] ];
        var vertex = verts[ vertexId ];

        var normal = face.vertexNormals[ j ];

        vertices.copy(vertex).applyMatrix4(worldMatrix);

        v1.copy(normal).applyMatrix3(normalMatrix).normalize().multiplyScalar(size);

        v1.add(vertices);
    }

    return v1;
};

0

我曾经遇到过同样的问题,无法理解我得到的正常面。对我来说,解决方案是将法向量与物体的法线矩阵相乘(我不知道那是什么)。这里有一个用Typescript编写的简单帮助类,将其移植到Javascript上也不应该太难:

import { Vector3, Object3D, Matrix3, Face3 } from 'three';

export class Face3Utils {
    private static _matrix3: Matrix3;

    private static get matrix3(): Matrix3 {
        if(this._matrix3 === undefined) {
            this._matrix3 = new Matrix3();
        }
        return this._matrix3;
    }

    public static getWorldNormal(face: Face3, object: Object3D, normalVector?: Vector3): Vector3 {
        if(normalVector === null || normalVector === undefined) {
            normalVector = new Vector3();
        }

        object.updateMatrixWorld( true );
        Face3Utils.matrix3.getNormalMatrix( object.matrixWorld );

        normalVector.copy(face.normal).applyMatrix3( Face3Utils.matrix3 ).normalize();
        return normalVector;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接