在 TypeScript 中为 3d 引擎计算三角形法线时出错

问题描述 投票:0回答:0

我正在尝试使用 TypeScript 计算三角形的法线,但我得到了意想不到的结果。以下是使用的顶点和三角形的详细信息:

let vertices: Vertex[] = [
  { x: 0, y: 0, z: 0 },
  { x: 1, y: 0, z: 0 },
  { x: 1, y: 1, z: 0 },
  { x: 0, y: 1, z: 0 },
  { x: 0, y: 0, z: 1 },
  { x: 1, y: 0, z: 1 },
  { x: 1, y: 1, z: 1 },
  { x: 0, y: 1, z: 1 },
];

const triangles: Triangle[] = [
  { v1: 0, v2: 1, v3: 2 }, { v1: 0, v2: 2, v3: 3 }, // Front face
  { v1: 4, v2: 5, v3: 6 }, { v1: 4, v2: 6, v3: 7 }, // Back face
  { v1: 0, v2: 1, v3: 5 }, { v1: 0, v2: 5, v3: 4 }, // Bottom face
  { v1: 2, v2: 3, v3: 7 }, { v1: 2, v2: 7, v3: 6 }, // Top face
  { v1: 0, v2: 3, v3: 7 }, { v1: 0, v2: 7, v3: 4 }, // Left face
  { v1: 1, v2: 2, v3: 6 }, { v1: 1, v2: 6, v3: 5 }  // Right face
];

我还对顶点应用了一些旋转和平移,它们工作正常。但是,当我尝试使用

calculateNormal()
函数计算三角形的法线时,结果似乎不正确。

这里是旋转和平移的实现:

const angle = 1;
const rotationX = rotationMatrixX(angle);
const rotationY = rotationMatrixY(angle); 
vertices = vertices.map((vertex) => {
    let [x, y, z, w] = multiplyMatrixVector(rotationX, [
        vertex.x,
        vertex.y,
        vertex.z,
        1,
    ]);
    return {x, y, z};
})
vertices = vertices.map((vertex) => {
    let [x, y, z, w] = multiplyMatrixVector(rotationY, [
        vertex.x,
        vertex.y,
        vertex.z,
        1,
    ]);
    return {x, y, z};
})
const translatedVertices = transformVertices(vertices, translationMatrix);
const culledTriangles = [];
const normals = [];
for (let i = 0; i < triangles.length; i++) {
    const { v1, v2, v3 } = triangles[i];
    const p1 = translatedVertices[v1];
    const p2 = translatedVertices[v2];
    const p3 = translatedVertices[v3];

    const normal = calculateNormal(p1, p2, p3);

    if (normal.z > 0) {
        culledTriangles.push(triangles[i]);
        normals.push(normal);
    }
}
// Transform and project the rotated vertices
const transformedVertices = transformVertices(translatedVertices, perspectiveProjectionMatrix());
const scaledVertices = scaleAndNormalizeVertices(transformedVertices);

// Draw the rotated cube
drawWireframe(ctx, scaledVertices, culledTriangles, normals);


这里是

calculateNormal()
函数的实现:

function calculateNormal(a: Vertex, b: Vertex, c: Vertex): Vertex {
  const line1: Vertex = {
    x: b.x - a.x,
    y: b.y - a.y,
    z: b.z - a.z,
  };

  const line2: Vertex = {
    x: c.x - a.x,
    y: c.y - a.y,
    z: c.z - a.z,
  };

  const normal: Vertex = {
    x: line1.y * line2.z - line1.z * line2.y,
    y: line1.z * line2.x - line1.x * line2.z,
    z: line1.x * line2.y - line1.y * line2.x,
  };

  const length = Math.sqrt(normal.x ** 2 + normal.y ** 2 + normal.z ** 2);
  normal.x /= length;
  normal.y /= length;
  normal.z /= length;

  return normal;
}

我已验证每个三角形都正确调用了

calculateNormal()
函数,但生成的法线似乎不正确。

这里是立方体的例子(图中红线代表法线的方向): cube

对于我可能做错了什么以及如何解决它的任何建议或建议,我将不胜感激。

typescript graphics 3d game-engine normals
© www.soinside.com 2019 - 2024. All rights reserved.