Skip to content

Commit

Permalink
Add Mesh Quantization support (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
nevermemo authored Nov 22, 2023
1 parent d041015 commit 88b92fc
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 26 deletions.
1 change: 1 addition & 0 deletions serve/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ let app = new PIXI.Application({
backgroundColor: 0xdddddd, resizeTo: window, antialias: true
})
document.body.appendChild(app.view)
globalThis.__PIXI_APP__ = app

let control = new PIXI3D.CameraOrbitControl(app.view)
control.enableDamping = true
Expand Down
6 changes: 4 additions & 2 deletions src/gltf/animation/gltf-cubic-spline.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { glTFInterpolation } from "./gltf-interpolation"
import { glTFInterpolation, getDenormalizeFunction } from "./gltf-interpolation"

export class glTFCubicSpline implements glTFInterpolation {
private _data: Float32Array
private _denormalize: (data: Float32Array) => Float32Array

constructor(private _input: ArrayLike<number>, private _output: ArrayLike<number>, private _stride: number) {
this._data = new Float32Array(_stride)
this._denormalize = getDenormalizeFunction(this._output, this._stride)
}

interpolate(frame: number, position: number) {
Expand All @@ -15,7 +17,7 @@ export class glTFCubicSpline implements glTFInterpolation {
this._data[i] = glTFCubicSpline.calculate(
position, this._output[pos1 + i + 1 * this._stride], this._output[pos2 + i + 1 * this._stride], diff * this._output[pos2 + i], diff * this._output[pos1 + i + 2 * this._stride])
}
return this._data
return this._denormalize(this._data)
}

static calculate(t: number, p0: number, p1: number, m0: number, m1: number) {
Expand Down
69 changes: 69 additions & 0 deletions src/gltf/animation/gltf-interpolation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,73 @@ export interface glTFInterpolation {
* @param position The position within the animation frame (between 0-1).
*/
interpolate(frame: number, position: number): Float32Array
}

export function getDenormalizeFunction(output: ArrayLike<number>, stride: number): (data: Float32Array) => Float32Array {
switch ( output.constructor ) {

case Float32Array:

return (data: Float32Array) => data;

case Uint32Array:

return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = data[i] / 4294967295.0;
}
return data;
};

case Uint16Array:

return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = data[i] / 65535.0;
}
return data;
};

case Uint8Array:

return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = data[i] / 255.0;
}
return data;
};

case Int32Array:

return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = Math.max( data[i] / 2147483647.0, - 1.0 );
}
return data;
};

case Int16Array:

return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = Math.max( data[i] / 32767.0, - 1.0 );
}
return data;
};

case Int8Array:


return (data: Float32Array) => {
for (let i = 0; i < stride; i++) {
data[i] = Math.max( data[i] / 127.0, - 1.0 );
}
return data;
};

default:

throw new Error( 'Invalid component type.' );

}
}
6 changes: 4 additions & 2 deletions src/gltf/animation/gltf-linear.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { glTFInterpolation } from "./gltf-interpolation"
import { glTFInterpolation, getDenormalizeFunction } from "./gltf-interpolation"

export class glTFLinear implements glTFInterpolation {
private _data: Float32Array
private _denormalize: (data: Float32Array) => Float32Array

constructor(private _output: ArrayLike<number>, private _stride: number) {
this._data = new Float32Array(_stride)
this._denormalize = getDenormalizeFunction(this._output, this._stride)
}

interpolate(frame: number, position: number) {
Expand All @@ -17,6 +19,6 @@ export class glTFLinear implements glTFInterpolation {
this._data[i] = this._output[pos1 + i]
}
}
return this._data
return this._denormalize(this._data)
}
}
6 changes: 4 additions & 2 deletions src/gltf/animation/gltf-step.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { glTFInterpolation } from "./gltf-interpolation"
import { glTFInterpolation, getDenormalizeFunction } from "./gltf-interpolation"

export class glTFStep implements glTFInterpolation {
private _data: Float32Array
private _denormalize: (data: Float32Array) => Float32Array

constructor(private _output: ArrayLike<number>, private _stride: number) {
this._data = new Float32Array(_stride)
this._denormalize = getDenormalizeFunction(this._output, this._stride)
}

interpolate(frame: number) {
for (let i = 0; i < this._stride; i++) {
this._data[i] = this._output[frame * this._stride + i]
}
return this._data
return this._denormalize(this._data)
}
}
16 changes: 8 additions & 8 deletions src/gltf/gltf-attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
* Represents data for a specific geometry attribute.
*/
export class glTFAttribute {
constructor(public buffer: Uint32Array | Float32Array | Int8Array | Uint8Array | Int16Array | Uint16Array, public componentType: number, public stride = 0, public componentCount: number, public min?: number[], public max?: number[]) {
constructor(public buffer: Uint32Array | Float32Array | Int8Array | Uint8Array | Int16Array | Uint16Array, public componentType: number, public stride = 0, public componentCount: number, public normalized: boolean = false, public min?: number[], public max?: number[]) {
}

static from(componentType: number, componentCount: number, buffer: ArrayBuffer, offset: number, size: number, stride?: number, min?: number[], max?: number[]) {
static from(componentType: number, componentCount: number, buffer: ArrayBuffer, offset: number, size: number, stride?: number, normalized: boolean = false, min?: number[], max?: number[]) {
switch (componentType) {
case 5125: return new glTFAttribute(
new Uint32Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Uint32Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
case 5126: return new glTFAttribute(
new Float32Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Float32Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
case 5120: return new glTFAttribute(
new Int8Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Int8Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
case 5121: return new glTFAttribute(
new Uint8Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Uint8Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
case 5122: return new glTFAttribute(
new Int16Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Int16Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
case 5123: return new glTFAttribute(
new Uint16Array(buffer, offset, size), componentType, stride, componentCount, min, max)
new Uint16Array(buffer, offset, size), componentType, stride, componentCount, normalized, min, max)
default: {
throw new Error(`PIXI3D: Unknown component type "${componentType}".`)
}
Expand Down
3 changes: 2 additions & 1 deletion src/gltf/gltf-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ export class glTFParser {
size = bufferView.byteStride / componentSize[accessor.componentType] * (accessor.count - 1) + componentCount[accessor.type]
}
let buffer = this._asset.buffers[bufferView.buffer]
const normalized = accessor.normalized === true;

return glTFAttribute.from(
accessor.componentType, componentCount[accessor.type], buffer, offset, size, bufferView.byteStride, accessor.min, accessor.max)
accessor.componentType, componentCount[accessor.type], buffer, offset, size, bufferView.byteStride, normalized, accessor.min, accessor.max)
}

/**
Expand Down
12 changes: 6 additions & 6 deletions src/material/standard/standard-shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,31 @@ export class StandardShader extends MeshShader {
let positions = geometry.targets[i].positions
if (positions) {
result.addAttribute(`a_Target_Position${i}`, new Buffer(positions.buffer),
3, false, positions.componentType, positions.stride)
3, positions.normalized, positions.componentType, positions.stride)
}
let normals = geometry.targets[i].normals
if (normals) {
result.addAttribute(`a_Target_Normal${i}`, new Buffer(normals.buffer),
3, false, normals.componentType, normals.stride)
3, normals.normalized, normals.componentType, normals.stride)
}
let tangents = geometry.targets[i].tangents
if (tangents) {
result.addAttribute(`a_Target_Tangent${i}`, new Buffer(tangents.buffer),
3, false, tangents.componentType, tangents.stride)
3, tangents.normalized, tangents.componentType, tangents.stride)
}
}
}
if (geometry.uvs && geometry.uvs[1]) {
result.addAttribute("a_UV2", new Buffer(geometry.uvs[1].buffer),
2, false, geometry.uvs[1].componentType, geometry.uvs[1].stride)
2, geometry.uvs[1].normalized, geometry.uvs[1].componentType, geometry.uvs[1].stride)
}
if (geometry.joints) {
result.addAttribute("a_Joint1", new Buffer(geometry.joints.buffer),
4, false, geometry.joints.componentType, geometry.joints.stride)
4, geometry.joints.normalized, geometry.joints.componentType, geometry.joints.stride)
}
if (geometry.weights) {
result.addAttribute("a_Weight1", new Buffer(geometry.weights.buffer),
4, false, geometry.weights.componentType, geometry.weights.stride)
4, geometry.weights.normalized, geometry.weights.componentType, geometry.weights.stride)
}
return result
}
Expand Down
4 changes: 4 additions & 0 deletions src/mesh/geometry/mesh-geometry-attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ export interface MeshGeometryAttribute {
* The number of elements in this attribute.
*/
componentCount?: number
/**
* Is buffer data normalized in this attribute.
*/
normalized: boolean
}
10 changes: 5 additions & 5 deletions src/mesh/mesh-shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,23 @@ export class MeshShader extends Shader {
}
if (geometry.positions) {
result.addAttribute("a_Position", new Buffer(geometry.positions.buffer),
3, false, geometry.positions.componentType, geometry.positions.stride)
3, geometry.positions.normalized, geometry.positions.componentType, geometry.positions.stride)
}
if (geometry.uvs && geometry.uvs[0]) {
result.addAttribute("a_UV1", new Buffer(geometry.uvs[0].buffer),
2, false, geometry.uvs[0].componentType, geometry.uvs[0].stride)
2, geometry.uvs[0].normalized, geometry.uvs[0].componentType, geometry.uvs[0].stride)
}
if (geometry.normals) {
result.addAttribute("a_Normal", new Buffer(geometry.normals.buffer),
3, false, geometry.normals.componentType, geometry.normals.stride)
3, geometry.normals.normalized, geometry.normals.componentType, geometry.normals.stride)
}
if (geometry.tangents) {
result.addAttribute("a_Tangent", new Buffer(geometry.tangents.buffer),
4, false, geometry.tangents.componentType, geometry.tangents.stride)
4, geometry.tangents.normalized, geometry.tangents.componentType, geometry.tangents.stride)
}
if (geometry.colors) {
result.addAttribute("a_Color", new Buffer(geometry.colors.buffer),
geometry.colors.componentCount, true, geometry.colors.componentType, geometry.colors.stride)
geometry.colors.componentCount, geometry.colors.normalized, geometry.colors.componentType, geometry.colors.stride)
}
return result
}
Expand Down

0 comments on commit 88b92fc

Please sign in to comment.