import { Vector3 } from '@math.gl/core'; import { GL } from "../constants.js"; import { assert } from "../utils/assert.js"; import { makePrimitiveIterator } from "../iterators/primitive-iterator.js"; import { getPrimitiveModeType } from "../primitives/modes.js"; import { getPositions } from "./get-attribute-from-geometry.js"; /** * Computes vertex normals for a geometry * @param param0 * @returns */ // eslint-disable-next-line max-statements export function computeVertexNormals(geometry) { // Only support GL.TRIANGLES, GL.TRIANGLE_STRIP, GL.TRIANGLE_FAN assert(getPrimitiveModeType(geometry.mode) === GL.TRIANGLES, 'TRIANGLES required'); const { values: positions } = getPositions(geometry); const normals = new Float32Array(positions.length); const vectorA = new Vector3(); const vectorB = new Vector3(); const vectorC = new Vector3(); const vectorCB = new Vector3(); const vectorAB = new Vector3(); for (const primitive of makePrimitiveIterator(geometry)) { vectorA.fromArray(positions, primitive.i1 * 3); vectorB.fromArray(positions, primitive.i2 * 3 + 3); vectorC.fromArray(positions, primitive.i3 * 3 + 6); vectorCB.subVectors(vectorC, vectorB); vectorAB.subVectors(vectorA, vectorB); const normal = vectorCB.cross(vectorAB); normal.normalize(); // @ts-ignore const { primitiveIndex } = primitive; normals[primitiveIndex * 9 + 0] = normal.x; normals[primitiveIndex * 9 + 1] = normal.y; normals[primitiveIndex * 9 + 2] = normal.z; normals[primitiveIndex * 9 + 3] = normal.x; normals[primitiveIndex * 9 + 4] = normal.y; normals[primitiveIndex * 9 + 5] = normal.z; normals[primitiveIndex * 9 + 6] = normal.x; normals[primitiveIndex * 9 + 7] = normal.y; normals[primitiveIndex * 9 + 8] = normal.z; } return normals; }