Spaces:
Running
Running
| import { Vector3 } from "../math/Vector3"; | |
| import { Quaternion } from "../math/Quaternion"; | |
| import { Matrix3 } from "../math/Matrix3"; | |
| class SplatData { | |
| static RowLength = 3 * 4 + 3 * 4 + 4 + 4; | |
| public changed = false; | |
| public detached = false; | |
| private _vertexCount: number; | |
| private _positions: Float32Array; | |
| private _rotations: Float32Array; | |
| private _scales: Float32Array; | |
| private _colors: Uint8Array; | |
| private _selection: Uint8Array; | |
| translate: (translation: Vector3) => void; | |
| rotate: (rotation: Quaternion) => void; | |
| scale: (scale: Vector3) => void; | |
| serialize: () => Uint8Array; | |
| reattach: ( | |
| positions: ArrayBufferLike, | |
| rotations: ArrayBufferLike, | |
| scales: ArrayBufferLike, | |
| colors: ArrayBufferLike, | |
| selection: ArrayBufferLike, | |
| ) => void; | |
| constructor( | |
| vertexCount: number = 0, | |
| positions: Float32Array | null = null, | |
| rotations: Float32Array | null = null, | |
| scales: Float32Array | null = null, | |
| colors: Uint8Array | null = null, | |
| ) { | |
| this._vertexCount = vertexCount; | |
| this._positions = positions || new Float32Array(0); | |
| this._rotations = rotations || new Float32Array(0); | |
| this._scales = scales || new Float32Array(0); | |
| this._colors = colors || new Uint8Array(0); | |
| this._selection = new Uint8Array(this.vertexCount); | |
| this.translate = (translation: Vector3) => { | |
| for (let i = 0; i < this.vertexCount; i++) { | |
| this.positions[3 * i + 0] += translation.x; | |
| this.positions[3 * i + 1] += translation.y; | |
| this.positions[3 * i + 2] += translation.z; | |
| } | |
| this.changed = true; | |
| }; | |
| this.rotate = (rotation: Quaternion) => { | |
| const R = Matrix3.RotationFromQuaternion(rotation).buffer; | |
| for (let i = 0; i < this.vertexCount; i++) { | |
| const x = this.positions[3 * i + 0]; | |
| const y = this.positions[3 * i + 1]; | |
| const z = this.positions[3 * i + 2]; | |
| this.positions[3 * i + 0] = R[0] * x + R[1] * y + R[2] * z; | |
| this.positions[3 * i + 1] = R[3] * x + R[4] * y + R[5] * z; | |
| this.positions[3 * i + 2] = R[6] * x + R[7] * y + R[8] * z; | |
| const currentRotation = new Quaternion( | |
| this.rotations[4 * i + 1], | |
| this.rotations[4 * i + 2], | |
| this.rotations[4 * i + 3], | |
| this.rotations[4 * i + 0], | |
| ); | |
| const newRot = rotation.multiply(currentRotation); | |
| this.rotations[4 * i + 1] = newRot.x; | |
| this.rotations[4 * i + 2] = newRot.y; | |
| this.rotations[4 * i + 3] = newRot.z; | |
| this.rotations[4 * i + 0] = newRot.w; | |
| } | |
| this.changed = true; | |
| }; | |
| this.scale = (scale: Vector3) => { | |
| for (let i = 0; i < this.vertexCount; i++) { | |
| this.positions[3 * i + 0] *= scale.x; | |
| this.positions[3 * i + 1] *= scale.y; | |
| this.positions[3 * i + 2] *= scale.z; | |
| this.scales[3 * i + 0] *= scale.x; | |
| this.scales[3 * i + 1] *= scale.y; | |
| this.scales[3 * i + 2] *= scale.z; | |
| } | |
| this.changed = true; | |
| }; | |
| this.serialize = () => { | |
| const data = new Uint8Array(this.vertexCount * SplatData.RowLength); | |
| const f_buffer = new Float32Array(data.buffer); | |
| const u_buffer = new Uint8Array(data.buffer); | |
| for (let i = 0; i < this.vertexCount; i++) { | |
| f_buffer[8 * i + 0] = this.positions[3 * i + 0]; | |
| f_buffer[8 * i + 1] = this.positions[3 * i + 1]; | |
| f_buffer[8 * i + 2] = this.positions[3 * i + 2]; | |
| u_buffer[32 * i + 24 + 0] = this.colors[4 * i + 0]; | |
| u_buffer[32 * i + 24 + 1] = this.colors[4 * i + 1]; | |
| u_buffer[32 * i + 24 + 2] = this.colors[4 * i + 2]; | |
| u_buffer[32 * i + 24 + 3] = this.colors[4 * i + 3]; | |
| f_buffer[8 * i + 3 + 0] = this.scales[3 * i + 0]; | |
| f_buffer[8 * i + 3 + 1] = this.scales[3 * i + 1]; | |
| f_buffer[8 * i + 3 + 2] = this.scales[3 * i + 2]; | |
| u_buffer[32 * i + 28 + 0] = (this.rotations[4 * i + 0] * 128 + 128) & 0xff; | |
| u_buffer[32 * i + 28 + 1] = (this.rotations[4 * i + 1] * 128 + 128) & 0xff; | |
| u_buffer[32 * i + 28 + 2] = (this.rotations[4 * i + 2] * 128 + 128) & 0xff; | |
| u_buffer[32 * i + 28 + 3] = (this.rotations[4 * i + 3] * 128 + 128) & 0xff; | |
| } | |
| return data; | |
| }; | |
| this.reattach = ( | |
| positions: ArrayBufferLike, | |
| rotations: ArrayBufferLike, | |
| scales: ArrayBufferLike, | |
| colors: ArrayBufferLike, | |
| selection: ArrayBufferLike, | |
| ) => { | |
| console.assert( | |
| positions.byteLength === this.vertexCount * 3 * 4, | |
| `Expected ${this.vertexCount * 3 * 4} bytes, got ${positions.byteLength} bytes`, | |
| ); | |
| this._positions = new Float32Array(positions); | |
| this._rotations = new Float32Array(rotations); | |
| this._scales = new Float32Array(scales); | |
| this._colors = new Uint8Array(colors); | |
| this._selection = new Uint8Array(selection); | |
| this.detached = false; | |
| }; | |
| } | |
| static Deserialize(data: Uint8Array): SplatData { | |
| const vertexCount = data.length / SplatData.RowLength; | |
| const positions = new Float32Array(3 * vertexCount); | |
| const rotations = new Float32Array(4 * vertexCount); | |
| const scales = new Float32Array(3 * vertexCount); | |
| const colors = new Uint8Array(4 * vertexCount); | |
| const f_buffer = new Float32Array(data.buffer); | |
| const u_buffer = new Uint8Array(data.buffer); | |
| for (let i = 0; i < vertexCount; i++) { | |
| positions[3 * i + 0] = f_buffer[8 * i + 0]; | |
| positions[3 * i + 1] = f_buffer[8 * i + 1]; | |
| positions[3 * i + 2] = f_buffer[8 * i + 2]; | |
| rotations[4 * i + 0] = (u_buffer[32 * i + 28 + 0] - 128) / 128; | |
| rotations[4 * i + 1] = (u_buffer[32 * i + 28 + 1] - 128) / 128; | |
| rotations[4 * i + 2] = (u_buffer[32 * i + 28 + 2] - 128) / 128; | |
| rotations[4 * i + 3] = (u_buffer[32 * i + 28 + 3] - 128) / 128; | |
| scales[3 * i + 0] = f_buffer[8 * i + 3 + 0]; | |
| scales[3 * i + 1] = f_buffer[8 * i + 3 + 1]; | |
| scales[3 * i + 2] = f_buffer[8 * i + 3 + 2]; | |
| colors[4 * i + 0] = u_buffer[32 * i + 24 + 0]; | |
| colors[4 * i + 1] = u_buffer[32 * i + 24 + 1]; | |
| colors[4 * i + 2] = u_buffer[32 * i + 24 + 2]; | |
| colors[4 * i + 3] = u_buffer[32 * i + 24 + 3]; | |
| } | |
| return new SplatData(vertexCount, positions, rotations, scales, colors); | |
| } | |
| get vertexCount() { | |
| return this._vertexCount; | |
| } | |
| get positions() { | |
| return this._positions; | |
| } | |
| get rotations() { | |
| return this._rotations; | |
| } | |
| get scales() { | |
| return this._scales; | |
| } | |
| get colors() { | |
| return this._colors; | |
| } | |
| get selection() { | |
| return this._selection; | |
| } | |
| clone() { | |
| return new SplatData( | |
| this.vertexCount, | |
| new Float32Array(this.positions), | |
| new Float32Array(this.rotations), | |
| new Float32Array(this.scales), | |
| new Uint8Array(this.colors), | |
| ); | |
| } | |
| } | |
| export { SplatData }; | |