mirror of
https://github.com/storytold/spark.git
synced 2026-10-17 00:12:59 +00:00
Reduce small memory allocations when loading ply files (#147)
* Replace for-of loops to reduce memory allocations in hot-path for ply loading * Use temporary THREE.Quaternion and THREE.Vector instances to avoid allocations
This commit is contained in:
+8
-8
@@ -239,8 +239,8 @@ export class PlyReader {
|
|||||||
// Parse all the items in the element
|
// Parse all the items in the element
|
||||||
const callback = elementCallback(element) ?? (() => {});
|
const callback = elementCallback(element) ?? (() => {});
|
||||||
for (let index = 0; index < count; index++) {
|
for (let index = 0; index < count; index++) {
|
||||||
for (const parser of parsers) {
|
for (let parserIndex = 0; parserIndex < parsers.length; parserIndex++) {
|
||||||
parser();
|
parsers[parserIndex]();
|
||||||
}
|
}
|
||||||
callback(index, item);
|
callback(index, item);
|
||||||
}
|
}
|
||||||
@@ -296,17 +296,17 @@ export class PlyReader {
|
|||||||
if (!sh1) {
|
if (!sh1) {
|
||||||
throw new Error("Missing sh1");
|
throw new Error("Missing sh1");
|
||||||
}
|
}
|
||||||
for (const [i, key] of sh1Props.entries()) {
|
for (let i = 0; i < sh1Props.length; i++) {
|
||||||
sh1[i] = ((item[key] as number) * 8) / 255 - 4;
|
sh1[i] = ((item[sh1Props[i]] as number) * 8) / 255 - 4;
|
||||||
}
|
}
|
||||||
if (sh2) {
|
if (sh2) {
|
||||||
for (const [i, key] of sh2Props.entries()) {
|
for (let i = 0; i < sh2Props.length; i++) {
|
||||||
sh2[i] = ((item[key] as number) * 8) / 255 - 4;
|
sh2[i] = ((item[sh2Props[i]] as number) * 8) / 255 - 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sh3) {
|
if (sh3) {
|
||||||
for (const [i, key] of sh3Props.entries()) {
|
for (let i = 0; i < sh3Props.length; i++) {
|
||||||
sh3[i] = ((item[key] as number) * 8) / 255 - 4;
|
sh3[i] = ((item[sh3Props[i]] as number) * 8) / 255 - 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shCallback?.(index, sh1, sh2, sh3);
|
shCallback?.(index, sh1, sh2, sh3);
|
||||||
|
|||||||
+14
-5
@@ -499,6 +499,10 @@ export function setPackedSplatScales(
|
|||||||
(packedSplats[i4 + 3] & 0xff000000);
|
(packedSplats[i4 + 3] & 0xff000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary storage used in `encodeQuatOCtXy88R8` and `decodeQuatOctXy88R8` to
|
||||||
|
// avoid allocation new Quaternions and Vector3 instances.
|
||||||
|
const tempQuaternion = new THREE.Quaternion();
|
||||||
|
|
||||||
// Encode the rotation quatX, quatY, quatZ, quatW in the packedSplats Uint32Array,
|
// Encode the rotation quatX, quatY, quatZ, quatW in the packedSplats Uint32Array,
|
||||||
// leaving all other fields as is.
|
// leaving all other fields as is.
|
||||||
export function setPackedSplatQuat(
|
export function setPackedSplatQuat(
|
||||||
@@ -510,7 +514,7 @@ export function setPackedSplatQuat(
|
|||||||
quatW: number,
|
quatW: number,
|
||||||
) {
|
) {
|
||||||
const uQuat = encodeQuatOctXy88R8(
|
const uQuat = encodeQuatOctXy88R8(
|
||||||
new THREE.Quaternion(quatX, quatY, quatZ, quatW),
|
tempQuaternion.set(quatX, quatY, quatZ, quatW),
|
||||||
);
|
);
|
||||||
// const uQuat = encodeQuatXyz888(new THREE.Quaternion(quatX, quatY, quatZ, quatW));
|
// const uQuat = encodeQuatXyz888(new THREE.Quaternion(quatX, quatY, quatZ, quatW));
|
||||||
// const uQuat = encodeQuatEulerXyz888(new THREE.Quaternion(quatX, quatY, quatZ, quatW));
|
// const uQuat = encodeQuatEulerXyz888(new THREE.Quaternion(quatX, quatY, quatZ, quatW));
|
||||||
@@ -960,6 +964,11 @@ export function decodeQuatXyz888(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary storage used in `encodeQuatOCtXy88R8` and `decodeQuatOctXy88R8` to
|
||||||
|
// avoid allocation new Quaternions and Vector3 instances.
|
||||||
|
const tempNormalizedQuaternion = new THREE.Quaternion();
|
||||||
|
const tempAxis = new THREE.Vector3();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a THREE.Quaternion into a 24‐bit integer.
|
* Encodes a THREE.Quaternion into a 24‐bit integer.
|
||||||
*
|
*
|
||||||
@@ -972,7 +981,7 @@ export function decodeQuatXyz888(
|
|||||||
*/
|
*/
|
||||||
export function encodeQuatOctXy88R8(q: THREE.Quaternion): number {
|
export function encodeQuatOctXy88R8(q: THREE.Quaternion): number {
|
||||||
// Force the minimal representation (q.w >= 0)
|
// Force the minimal representation (q.w >= 0)
|
||||||
const qnorm = q.clone().normalize();
|
const qnorm = tempNormalizedQuaternion.copy(q).normalize();
|
||||||
if (qnorm.w < 0) {
|
if (qnorm.w < 0) {
|
||||||
qnorm.set(-qnorm.x, -qnorm.y, -qnorm.z, -qnorm.w);
|
qnorm.set(-qnorm.x, -qnorm.y, -qnorm.z, -qnorm.w);
|
||||||
}
|
}
|
||||||
@@ -984,8 +993,8 @@ export function encodeQuatOctXy88R8(q: THREE.Quaternion): number {
|
|||||||
);
|
);
|
||||||
const axis =
|
const axis =
|
||||||
xyz_norm < 1e-6
|
xyz_norm < 1e-6
|
||||||
? new THREE.Vector3(1, 0, 0)
|
? tempAxis.set(1, 0, 0)
|
||||||
: new THREE.Vector3(qnorm.x, qnorm.y, qnorm.z).divideScalar(xyz_norm);
|
: tempAxis.set(qnorm.x, qnorm.y, qnorm.z).divideScalar(xyz_norm);
|
||||||
// const foldAxis = (axis.z < 0);
|
// const foldAxis = (axis.z < 0);
|
||||||
|
|
||||||
// --- Folded Octahedral Mapping (inline) ---
|
// --- Folded Octahedral Mapping (inline) ---
|
||||||
@@ -1036,7 +1045,7 @@ export function decodeQuatOctXy88R8(
|
|||||||
const t = Math.max(-f_z, 0);
|
const t = Math.max(-f_z, 0);
|
||||||
f_x += f_x >= 0 ? -t : t;
|
f_x += f_x >= 0 ? -t : t;
|
||||||
f_y += f_y >= 0 ? -t : t;
|
f_y += f_y >= 0 ? -t : t;
|
||||||
const axis = new THREE.Vector3(f_x, f_y, f_z).normalize();
|
const axis = tempAxis.set(f_x, f_y, f_z).normalize();
|
||||||
|
|
||||||
// Decode the angle: θ ∈ [0,π]
|
// Decode the angle: θ ∈ [0,π]
|
||||||
const theta = (angleInt / 255) * Math.PI;
|
const theta = (angleInt / 255) * Math.PI;
|
||||||
|
|||||||
Reference in New Issue
Block a user