Three.js:如何在负标度后翻转法线

Mar*_*her 5 flip normals scaletransform three.js

我克隆并使用负刻度翻转对象,这会导致我的单面朝向反转.我的问题是,我怎样才能翻转法线呢?

我不想使用material.side = THREE.DoubleSide,原因是:1)没有正常工作(一些阴影是从内部绘制的)和2)想保持尽可能多的性能.所以DoubleSide对我来说不是一个选择.

这是我的对象如何翻转.

mesh.scale.x = - scale_width;
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Paw*_*wel 6

只是把这个扔在这里。我在某个地方找到了 FlipNormals 并将其翻译为 BufferGeometry

翻转法线、翻转 UV、反面缠绕

索引 BufferGeometry 的版本

function flipBufferGeometryNormalsIndexed(geometry) {
    const index = geometry.index.array
    for (let i = 0, il = index.length / 3; i < il; i++) {
        let x = index[i * 3]
        index[i * 3] = index[i * 3 + 2]
        index[i * 3 + 2] = x
    }
    geometry.index.needsUpdate = true
}
Run Code Online (Sandbox Code Playgroud)

非索引 BufferGeometry 的版本

export function flipBufferGeometryNormals(geometry) {
    const tempXYZ = [0, 0, 0];

    // flip normals
    for (let i = 0; i < geometry.attributes.normal.array.length / 9; i++) {
        // cache a coordinates
        tempXYZ[0] = geometry.attributes.normal.array[i * 9];
        tempXYZ[1] = geometry.attributes.normal.array[i * 9 + 1];
        tempXYZ[2] = geometry.attributes.normal.array[i * 9 + 2];

        // overwrite a with c
        geometry.attributes.normal.array[i * 9] =
            geometry.attributes.normal.array[i * 9 + 6];
        geometry.attributes.normal.array[i * 9 + 1] =
            geometry.attributes.normal.array[i * 9 + 7];
        geometry.attributes.normal.array[i * 9 + 2] =
            geometry.attributes.normal.array[i * 9 + 8];

        // overwrite c with stored a values
        geometry.attributes.normal.array[i * 9 + 6] = tempXYZ[0];
        geometry.attributes.normal.array[i * 9 + 7] = tempXYZ[1];
        geometry.attributes.normal.array[i * 9 + 8] = tempXYZ[2];
    }

    // change face winding order
    for (let i = 0; i < geometry.attributes.position.array.length / 9; i++) {
        // cache a coordinates
        tempXYZ[0] = geometry.attributes.position.array[i * 9];
        tempXYZ[1] = geometry.attributes.position.array[i * 9 + 1];
        tempXYZ[2] = geometry.attributes.position.array[i * 9 + 2];

        // overwrite a with c
        geometry.attributes.position.array[i * 9] =
            geometry.attributes.position.array[i * 9 + 6];
        geometry.attributes.position.array[i * 9 + 1] =
            geometry.attributes.position.array[i * 9 + 7];
        geometry.attributes.position.array[i * 9 + 2] =
            geometry.attributes.position.array[i * 9 + 8];

        // overwrite c with stored a values
        geometry.attributes.position.array[i * 9 + 6] = tempXYZ[0];
        geometry.attributes.position.array[i * 9 + 7] = tempXYZ[1];
        geometry.attributes.position.array[i * 9 + 8] = tempXYZ[2];
    }

    // flip UV coordinates
    for (let i = 0; i < geometry.attributes.uv.array.length / 6; i++) {
        // cache a coordinates
        tempXYZ[0] = geometry.attributes.uv.array[i * 6];
        tempXYZ[1] = geometry.attributes.uv.array[i * 6 + 1];

        // overwrite a with c
        geometry.attributes.uv.array[i * 6] =
            geometry.attributes.uv.array[i * 6 + 4];
        geometry.attributes.uv.array[i * 6 + 1] =
            geometry.attributes.uv.array[i * 6 + 5];

        // overwrite c with stored a values
        geometry.attributes.uv.array[i * 6 + 4] = tempXYZ[0];
        geometry.attributes.uv.array[i * 6 + 5] = tempXYZ[1];
    }

    geometry.attributes.normal.needsUpdate = true;
    geometry.attributes.position.needsUpdate = true;
    geometry.attributes.uv.needsUpdate = true;
}
Run Code Online (Sandbox Code Playgroud)

对于旧式几何

export function flipNormals(geometry) {
    let temp = 0;
    let face;

    // flip every vertex normal in geometry by multiplying normal by -1
    for (let i = 0; i < geometry.faces.length; i++) {
        face = geometry.faces[i];
        face.normal.x = -1 * face.normal.x;
        face.normal.y = -1 * face.normal.y;
        face.normal.z = -1 * face.normal.z;
    }

    // change face winding order
    for (let i = 0; i < geometry.faces.length; i++) {
        const face = geometry.faces[i];
        temp = face.a;
        face.a = face.c;
        face.c = temp;
    }

    // flip UV coordinates
    const faceVertexUvs = geometry.faceVertexUvs[0];
    for (let i = 0; i < faceVertexUvs.length; i++) {
        temp = faceVertexUvs[i][0];
        faceVertexUvs[i][0] = faceVertexUvs[i][2];
        faceVertexUvs[i][2] = temp;
    }

    geometry.verticesNeedUpdate = true;
    geometry.normalsNeedUpdate = true;

    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    geometry.computeBoundingSphere();
}
Run Code Online (Sandbox Code Playgroud)


Wes*_*ley 5

出于各种原因,我建议反对负比例,如以下链接所述:在三个.js中转换顶点法线

您可以改为将反演矩阵应用于几何体

geometry.scale( - 1, 1, 1 );
Run Code Online (Sandbox Code Playgroud)

正如链接中所解释的那样,这样做的结果是,几何面将不再具有逆时针绕组顺序,而是顺时针方向.

您可以手动遍历几何体并翻转每个面的缠绕顺序.这可能适合您 - 如果您没有应用纹理并且没有使用UV.如果要对几何体进行纹理处理,则还需要校正UV.

实际上,几何反演实用程序将是three.js的一个很好的补充.目前,库不支持您要执行的操作.

three.js r.72