Stop generating so much garbage during mesh expansion.

Avoids a slow script dialog in the 3D demo.
This commit is contained in:
Patrick Walton 2017-09-28 10:47:16 -07:00
parent 1675944dfb
commit 6217577674
1 changed files with 34 additions and 17 deletions

View File

@ -36,6 +36,8 @@ export const B_QUAD_LOWER_CONTROL_POINT_VERTEX_OFFSET: number = 4 * 6;
export const B_QUAD_UPPER_INDICES_OFFSET: number = B_QUAD_UPPER_LEFT_VERTEX_OFFSET; export const B_QUAD_UPPER_INDICES_OFFSET: number = B_QUAD_UPPER_LEFT_VERTEX_OFFSET;
export const B_QUAD_LOWER_INDICES_OFFSET: number = B_QUAD_LOWER_LEFT_VERTEX_OFFSET; export const B_QUAD_LOWER_INDICES_OFFSET: number = B_QUAD_LOWER_LEFT_VERTEX_OFFSET;
const B_QUAD_FIELD_COUNT: number = B_QUAD_SIZE / UINT32_SIZE;
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER'; type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
export interface Meshes<T> { export interface Meshes<T> {
@ -71,7 +73,7 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
} }
expand(pathIDs: number[]): PathfinderMeshData { expand(pathIDs: number[]): PathfinderMeshData {
const bQuads = _.chunk(new Uint32Array(this.bQuads), B_QUAD_SIZE / UINT32_SIZE); const bQuads = new Uint32Array(this.bQuads);
const bVertexPositions = new Float32Array(this.bVertexPositions); const bVertexPositions = new Float32Array(this.bVertexPositions);
const bVertexPathIDs = new Uint16Array(this.bVertexPathIDs); const bVertexPathIDs = new Uint16Array(this.bVertexPathIDs);
const bVertexLoopBlinnData = new Uint32Array(this.bVertexLoopBlinnData); const bVertexLoopBlinnData = new Uint32Array(this.bVertexLoopBlinnData);
@ -83,6 +85,11 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
for (let indexIndex = 3; indexIndex < edgeLowerCurveIndices.length; indexIndex += 4) for (let indexIndex = 3; indexIndex < edgeLowerCurveIndices.length; indexIndex += 4)
edgeLowerCurveIndices[indexIndex] = 0; edgeLowerCurveIndices[indexIndex] = 0;
const coverInteriorIndices = new Uint32Array(this.coverInteriorIndices);
const coverCurveIndices = new Uint32Array(this.coverCurveIndices);
const edgeUpperLineIndices = new Uint32Array(this.edgeUpperLineIndices);
const edgeLowerLineIndices = new Uint32Array(this.edgeLowerLineIndices);
const expandedBQuads: number[] = []; const expandedBQuads: number[] = [];
const expandedBVertexPositions: number[] = []; const expandedBVertexPositions: number[] = [];
const expandedBVertexPathIDs: number[] = []; const expandedBVertexPathIDs: number[] = [];
@ -114,51 +121,50 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
// Copy over indices. // Copy over indices.
copyIndices(expandedCoverInteriorIndices, copyIndices(expandedCoverInteriorIndices,
new Uint32Array(this.coverInteriorIndices), coverInteriorIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex); bVertexIndex);
copyIndices(expandedCoverCurveIndices, copyIndices(expandedCoverCurveIndices,
new Uint32Array(this.coverCurveIndices), coverCurveIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex); bVertexIndex);
copyIndices(expandedEdgeUpperLineIndices, copyIndices(expandedEdgeUpperLineIndices,
new Uint32Array(this.edgeUpperLineIndices), edgeUpperLineIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex); bVertexIndex);
copyIndices(expandedEdgeUpperCurveIndices, copyIndices(expandedEdgeUpperCurveIndices,
new Uint32Array(edgeUpperCurveIndices), edgeUpperCurveIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex, bVertexIndex,
indexIndex => indexIndex % 4 < 3); indexIndex => indexIndex % 4 < 3);
copyIndices(expandedEdgeLowerLineIndices, copyIndices(expandedEdgeLowerLineIndices,
new Uint32Array(this.edgeLowerLineIndices), edgeLowerLineIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex); bVertexIndex);
copyIndices(expandedEdgeLowerCurveIndices, copyIndices(expandedEdgeLowerCurveIndices,
new Uint32Array(edgeLowerCurveIndices), edgeLowerCurveIndices,
firstExpandedBVertexIndex, firstExpandedBVertexIndex,
firstBVertexIndex, firstBVertexIndex,
bVertexIndex, bVertexIndex,
indexIndex => indexIndex % 4 < 3); indexIndex => indexIndex % 4 < 3);
// Copy over B-quads. // Copy over B-quads.
let firstBQuadIndex = _.findIndex(bQuads, let firstBQuadIndex = findFirstBQuadIndex(bQuads, pathID);
bQuad => bVertexPathIDs[bQuad[0]] === pathID); if (firstBQuadIndex == null)
if (firstBQuadIndex < 0)
firstBQuadIndex = bQuads.length; firstBQuadIndex = bQuads.length;
const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex; const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex;
for (let bQuadIndex = firstBQuadIndex; bQuadIndex < bQuads.length; bQuadIndex++) { for (let bQuadIndex = firstBQuadIndex; bQuadIndex < bQuads.length; bQuadIndex++) {
const bQuad = bQuads[bQuadIndex]; const bQuad = bQuads[bQuadIndex];
if (bVertexPathIDs[bQuad[0]] !== pathID) if (bVertexPathIDs[bQuads[bQuadIndex * B_QUAD_FIELD_COUNT]] !== pathID)
break; break;
for (let indexIndex = 0; indexIndex < B_QUAD_SIZE / UINT32_SIZE; indexIndex++) { for (let indexIndex = 0; indexIndex < B_QUAD_FIELD_COUNT; indexIndex++) {
const srcIndex = bQuad[indexIndex]; const srcIndex = bQuads[bQuadIndex * B_QUAD_FIELD_COUNT + indexIndex];
if (srcIndex === UINT32_MAX) if (srcIndex === UINT32_MAX)
expandedBQuads.push(srcIndex); expandedBQuads.push(srcIndex);
else else
@ -239,10 +245,8 @@ function copyIndices(destIndices: number[],
if (firstIndex === lastIndex) if (firstIndex === lastIndex)
return; return;
// FIXME(pcwalton): Use binary search instead of linear search. // FIXME(pcwalton): Speed this up somehow.
let indexIndex = _.findIndex(srcIndices, srcIndex => { let indexIndex = srcIndices.findIndex(index => index >= firstIndex && index < lastIndex);
return srcIndex >= firstIndex && srcIndex < lastIndex;
});
if (indexIndex < 0) if (indexIndex < 0)
return; return;
@ -259,3 +263,16 @@ function copyIndices(destIndices: number[],
indexIndex++; indexIndex++;
} }
} }
function findFirstBQuadIndex(bQuads: Uint32Array, queryPathID: number): number | null {
let low = 0, high = bQuads.length / B_QUAD_FIELD_COUNT;
while (low < high) {
const mid = low + (high - low) / 2;
const thisPathID = bQuads[mid * B_QUAD_FIELD_COUNT];
if (queryPathID <= thisPathID)
high = mid;
else
low = mid + 1;
}
return bQuads[low * B_QUAD_FIELD_COUNT] === queryPathID ? low : null;
}