Skip to content

Commit

Permalink
Add BitArray and use it in OptimizeIndices (#16012)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryantrem authored Dec 17, 2024
1 parent d772959 commit aa9c855
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 5 deletions.
11 changes: 6 additions & 5 deletions packages/dev/core/src/Meshes/mesh.vertexData.functions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { IndicesArray } from "core/types";
import { BitArray } from "core/Misc/bitArray";

/**
* Sort (in place) the index array so that faces with common indices are close
Expand Down Expand Up @@ -26,7 +27,7 @@ export function OptimizeIndices(indices: IndicesArray) {
});

// Step 3: Traverse faces using DFS to ensure connected faces are close
const visited = new Array(faceCount).fill(false);
const visited = new BitArray(faceCount);
const sortedFaces: Array<number[]> = [];

// Using a stack and not a recursive version to avoid call stack overflow
Expand All @@ -36,10 +37,10 @@ export function OptimizeIndices(indices: IndicesArray) {
while (stack.length > 0) {
const currentFaceIndex = stack.pop()!;

if (visited[currentFaceIndex]) {
if (visited.get(currentFaceIndex)) {
continue;
}
visited[currentFaceIndex] = true;
visited.set(currentFaceIndex, true);
sortedFaces.push(faces[currentFaceIndex]);

// Push unvisited neighbors (faces sharing a vertex) onto the stack
Expand All @@ -51,7 +52,7 @@ export function OptimizeIndices(indices: IndicesArray) {
}

neighbors.forEach((neighborFaceIndex) => {
if (!visited[neighborFaceIndex]) {
if (!visited.get(neighborFaceIndex)) {
stack.push(neighborFaceIndex);
}
});
Expand All @@ -61,7 +62,7 @@ export function OptimizeIndices(indices: IndicesArray) {

// Start DFS from the first face
for (let i = 0; i < faceCount; i++) {
if (!visited[i]) {
if (!visited.get(i)) {
deepFirstSearchStack(i);
}
}
Expand Down
56 changes: 56 additions & 0 deletions packages/dev/core/src/Misc/bitArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
function getByteIndex(bitIndex: number): number {
return Math.floor(bitIndex / 8);
}

function getBitMask(bitIndex: number): number {
return 1 << bitIndex % 8;
}

/**
* An fixed size array that effectively stores boolean values where each value is a single bit of backing data.
* @remarks
* All bits are initialized to false.
*/
export class BitArray {
private readonly _byteArray: Uint8Array;

/**
* Creates a new bit array with a fixed size.
* @param size The number of bits to store.
*/
public constructor(public readonly size: number) {
this._byteArray = new Uint8Array(Math.ceil(this.size / 8));
}

/**
* Gets the current value at the specified index.
* @param bitIndex The index to get the value from.
* @returns The value at the specified index.
*/
public get(bitIndex: number): boolean {
if (bitIndex >= this.size) {
throw new RangeError("Bit index out of range");
}
const byteIndex = getByteIndex(bitIndex);
const bitMask = getBitMask(bitIndex);
return (this._byteArray[byteIndex] & bitMask) !== 0;
}

/**
* Sets the value at the specified index.
* @param bitIndex The index to set the value at.
* @param value The value to set.
*/
public set(bitIndex: number, value: boolean): void {
if (bitIndex >= this.size) {
throw new RangeError("Bit index out of range");
}
const byteIndex = getByteIndex(bitIndex);
const bitMask = getBitMask(bitIndex);
if (value) {
this._byteArray[byteIndex] |= bitMask;
} else {
this._byteArray[byteIndex] &= ~bitMask;
}
}
}
1 change: 1 addition & 0 deletions packages/dev/core/src/Misc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export * from "./greasedLineTools";
export * from "./equirectangularCapture";
export * from "./decorators.serialization";
export * from "./asyncLock";
export * from "./bitArray";

// RGBDTextureTools
export * from "../Shaders/rgbdDecode.fragment";
Expand Down

0 comments on commit aa9c855

Please sign in to comment.