@cesium/engine
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
109 lines (95 loc) • 3.84 kB
JavaScript
import createTaskProcessorWorker from "./createTaskProcessorWorker.js";
import Matrix4 from "../Core/Matrix4.js";
import Cartesian3 from "../Core/Cartesian3.js";
import AxisAlignedBoundingBox from "../Core/AxisAlignedBoundingBox.js";
const scratchAABBCornerMin = new Cartesian3();
const scratchAABBCornerMax = new Cartesian3();
const scratchTrianglePoints = [
new Cartesian3(),
new Cartesian3(),
new Cartesian3(),
];
const scratchTriangleAABB = new AxisAlignedBoundingBox();
/**
* Builds the next layer of the terrain picker's quadtree by determining which triangles intersect
* each of the four child nodes. (Essentially distributing the parent's triangles to its children.)
*
* Takes in the AABBs of the four child nodes in the tree's local space, an inverse transform
* to convert triangle positions to the tree's local space, and the parent node's triangle indices and positions.
*
* Returns an four arrays - one for each child node - containing the indices of the triangles that intersect each node.
*/
function incrementallyBuildTerrainPicker(parameters, transferableObjects) {
// Rehydrate worker inputs
const aabbs = new Float64Array(parameters.aabbs);
const nodeAABBs = Array.from({ length: 4 }, (_, i) => {
const min = Cartesian3.unpack(aabbs, i * 6, scratchAABBCornerMin);
const max = Cartesian3.unpack(aabbs, i * 6 + 3, scratchAABBCornerMax);
return AxisAlignedBoundingBox.fromCorners(
min,
max,
new AxisAlignedBoundingBox(),
);
});
const inverseTransformArray = new Float64Array(parameters.inverseTransform);
const inverseTransform = Matrix4.unpack(
inverseTransformArray,
0,
new Matrix4(),
);
const triangleIndices = new Uint32Array(parameters.triangleIndices);
const trianglePositions = new Float32Array(parameters.trianglePositions);
const intersectingTrianglesArrays = Array.from({ length: 4 }, () => []);
for (let j = 0; j < triangleIndices.length; j++) {
Cartesian3.unpack(trianglePositions, j * 9, scratchTrianglePoints[0]);
Cartesian3.unpack(trianglePositions, j * 9 + 3, scratchTrianglePoints[1]);
Cartesian3.unpack(trianglePositions, j * 9 + 6, scratchTrianglePoints[2]);
const triangleAABB = createAABBFromTriangle(
inverseTransform,
scratchTrianglePoints,
);
for (let i = 0; i < 4; i++) {
const aabbsIntersect =
nodeAABBs[i].intersectAxisAlignedBoundingBox(triangleAABB);
if (!aabbsIntersect) {
continue;
}
intersectingTrianglesArrays[i].push(triangleIndices[j]);
}
}
const intersectingTrianglesTypedArrays = intersectingTrianglesArrays.map(
(array) => {
const uintArray = new Uint32Array(array);
transferableObjects.push(uintArray.buffer);
return uintArray.buffer;
},
);
return {
intersectingTrianglesArrays: intersectingTrianglesTypedArrays,
};
}
/**
* Creates a tree-space axis-aligned bounding box from the given triangle points and inverse transform (from world to tree space).
* @param {Matrix4} inverseTransform transform from world space to tree local space
* @param {Cartesian3[]} trianglePoints array of 3 Cartesian3 points representing the triangle
* @returns {AxisAlignedBoundingBox} the axis-aligned bounding box enclosing the triangle in tree local space
*/
function createAABBFromTriangle(inverseTransform, trianglePoints) {
Matrix4.multiplyByPoint(
inverseTransform,
trianglePoints[0],
trianglePoints[0],
);
Matrix4.multiplyByPoint(
inverseTransform,
trianglePoints[1],
trianglePoints[1],
);
Matrix4.multiplyByPoint(
inverseTransform,
trianglePoints[2],
trianglePoints[2],
);
return AxisAlignedBoundingBox.fromPoints(trianglePoints, scratchTriangleAABB);
}
export default createTaskProcessorWorker(incrementallyBuildTerrainPicker);