@loaders.gl/math
Version:
Experimental math classes for loaders.gl
45 lines (44 loc) • 1.92 kB
JavaScript
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;
}