@francisdb/vpin-wasm 0.25.0 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -1
- package/package.json +1 -1
- package/vpin.d.ts +120 -0
- package/vpin.js +285 -20
- package/vpin_bg.wasm +0 -0
- package/vpin_bg.wasm.d.ts +10 -0
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install @francisdb/vpin-wasm
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import init, { extract, assemble } from '@francisdb/vpin-wasm';
|
|
14
|
+
import init, { extract, assemble, obj_to_mesh, mesh_to_obj } from '@francisdb/vpin-wasm';
|
|
15
15
|
|
|
16
16
|
await init();
|
|
17
17
|
```
|
|
@@ -62,6 +62,58 @@ const vpxBytes = assemble(files, (message) => {
|
|
|
62
62
|
|
|
63
63
|
**Returns:** `Uint8Array` - VPX file bytes
|
|
64
64
|
|
|
65
|
+
### obj_to_mesh(data) / mesh_to_obj(name, positions, texCoords, normals, indices)
|
|
66
|
+
|
|
67
|
+
Renderer-friendly mesh I/O. `obj_to_mesh` parses any flavor of OBJ
|
|
68
|
+
(n-gons fan-triangulated, mismatched `v/vt/vn` corners deduplicated)
|
|
69
|
+
into typed arrays you can hand straight to WebGL or Three.js. No
|
|
70
|
+
JS-side OBJ parser needed.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const objBytes = files['/vpx/gameitems/Primitive.MyMesh.obj'];
|
|
74
|
+
const mesh = obj_to_mesh(objBytes);
|
|
75
|
+
|
|
76
|
+
// mesh.name: string
|
|
77
|
+
// mesh.positions: Float32Array (length = 3 * vertCount, x,y,z,...)
|
|
78
|
+
// mesh.texCoords: Float32Array (length = 2 * vertCount, u,v,...)
|
|
79
|
+
// mesh.normals: Float32Array (length = 3 * vertCount, nx,ny,nz,...)
|
|
80
|
+
// mesh.indices: Uint32Array (length = 3 * triCount)
|
|
81
|
+
|
|
82
|
+
// Three.js example:
|
|
83
|
+
const geom = new THREE.BufferGeometry();
|
|
84
|
+
geom.setAttribute('position', new THREE.BufferAttribute(mesh.positions, 3));
|
|
85
|
+
geom.setAttribute('uv', new THREE.BufferAttribute(mesh.texCoords, 2));
|
|
86
|
+
geom.setAttribute('normal', new THREE.BufferAttribute(mesh.normals, 3));
|
|
87
|
+
geom.setIndex(new THREE.BufferAttribute(mesh.indices, 1));
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`mesh_to_obj` does the inverse - serializes typed arrays back to OBJ
|
|
91
|
+
bytes you can save into the file map and feed to `assemble`.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const obj = mesh_to_obj(mesh.name, mesh.positions, mesh.texCoords, mesh.normals, mesh.indices);
|
|
95
|
+
files['/vpx/gameitems/Primitive.MyMesh.obj'] = obj;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The published wasm bundle is built with `wasm-bindgen --weak-refs`, so
|
|
99
|
+
the Rust-owned memory backing each `mesh` is reclaimed automatically
|
|
100
|
+
via `FinalizationRegistry` when the JS wrapper is garbage-collected.
|
|
101
|
+
You may call `mesh.free()` explicitly for deterministic cleanup of
|
|
102
|
+
large meshes, but it is not required.
|
|
103
|
+
|
|
104
|
+
**Coordinate convention:** the mesh data is in vpx-internal form -
|
|
105
|
+
`obj_to_mesh` applies the same transforms as `assemble`'s read path
|
|
106
|
+
(vertex Z negated, normal Z negated, V coordinate flipped, per-triangle
|
|
107
|
+
corner order reversed), and `mesh_to_obj` applies the inverse, matching
|
|
108
|
+
`extract`'s write path. Round-trip
|
|
109
|
+
`obj_to_mesh -> edit -> mesh_to_obj -> assemble` preserves vpx data by
|
|
110
|
+
construction. If your renderer uses a different convention than
|
|
111
|
+
vpinball's left-handed +Z up, apply a transform matrix on the JS side.
|
|
112
|
+
|
|
113
|
+
**Animation frames:** primitives with vertex animation extract as
|
|
114
|
+
sibling files `Primitive.MyMesh_00000.obj`, `Primitive.MyMesh_00001.obj`,
|
|
115
|
+
... Call `obj_to_mesh` per file and drive the timeline yourself.
|
|
116
|
+
|
|
65
117
|
### Exporting from Blender
|
|
66
118
|
|
|
67
119
|
`assemble` accepts Blender's OBJ output directly - n-gons are
|
package/package.json
CHANGED
package/vpin.d.ts
CHANGED
|
@@ -1,18 +1,138 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Mesh data for a single primitive: positions, texture coordinates,
|
|
6
|
+
* normals and triangle indices, packed as flat typed arrays for direct
|
|
7
|
+
* upload into a WebGL / Three.js / GPU buffer.
|
|
8
|
+
*
|
|
9
|
+
* All vertex data is aligned: `positions[3*i..3*i+3]`, `tex_coords[2*i..2*i+2]`
|
|
10
|
+
* and `normals[3*i..3*i+3]` describe corner `i`. Triangles are 0-based
|
|
11
|
+
* indices into that aligned array.
|
|
12
|
+
*
|
|
13
|
+
* Coordinates are in vpx-internal convention (the same form `read_fs`
|
|
14
|
+
* produces and `write_fs` consumes), not raw OBJ values - see
|
|
15
|
+
* [`obj_to_mesh`] / [`mesh_to_obj`] for the transform details.
|
|
16
|
+
*
|
|
17
|
+
* The published wasm package is built with `wasm-bindgen --weak-refs`,
|
|
18
|
+
* so the Rust-owned vectors backing this struct are reclaimed
|
|
19
|
+
* automatically via `FinalizationRegistry` when the JS wrapper is
|
|
20
|
+
* garbage-collected. Calling `.free()` manually is still allowed for
|
|
21
|
+
* deterministic cleanup of large meshes.
|
|
22
|
+
*/
|
|
23
|
+
export class PrimitiveMesh {
|
|
24
|
+
private constructor();
|
|
25
|
+
free(): void;
|
|
26
|
+
[Symbol.dispose](): void;
|
|
27
|
+
readonly indices: Uint32Array;
|
|
28
|
+
/**
|
|
29
|
+
* Bounding-box midpoint of the mesh's positions, in the same
|
|
30
|
+
* coordinate space as `positions` (vpx-internal). Returns
|
|
31
|
+
* `[mid_x, mid_y, mid_z]`. Used by editor flows that center the
|
|
32
|
+
* mesh on origin or move the primitive to the mesh's absolute
|
|
33
|
+
* position - both need to know the midpoint to shift vertices
|
|
34
|
+
* (and, for the absolute-position case, to set the primitive's
|
|
35
|
+
* `vPosition` field). Mirrors vpinball's `Mesh::middlePoint`,
|
|
36
|
+
* which is used by `IDC_CENTER_MESH` / `IDC_ABS_POSITION_RADIO`
|
|
37
|
+
* in the mesh-import dialog (`primitive.cpp:1729-1745`).
|
|
38
|
+
*
|
|
39
|
+
* Returns `[0, 0, 0]` for an empty mesh.
|
|
40
|
+
*/
|
|
41
|
+
readonly midpoint: Float32Array;
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly normals: Float32Array;
|
|
44
|
+
readonly positions: Float32Array;
|
|
45
|
+
readonly texCoords: Float32Array;
|
|
46
|
+
}
|
|
47
|
+
|
|
4
48
|
export function assemble(files: object, callback?: Function | null): Uint8Array;
|
|
5
49
|
|
|
6
50
|
export function extract(data: Uint8Array, callback?: Function | null): object;
|
|
7
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Generate the procedural mesh used by vpinball primitives that
|
|
54
|
+
* don't load a `.obj` file (`use_3d_mesh = false`). Mirrors
|
|
55
|
+
* `Primitive::CalculateBuiltinOriginal` from vpinball: a regular
|
|
56
|
+
* polygon prism with `sides` faces, top and bottom caps, fitting
|
|
57
|
+
* in `[-r, r] x [-r, r] x [-0.5, 0.5]`.
|
|
58
|
+
*
|
|
59
|
+
* Use this to render the placeholder shape for a primitive that
|
|
60
|
+
* has `use_3d_mesh = false`, or to seed the editor's "Add
|
|
61
|
+
* Primitive" workflow.
|
|
62
|
+
*
|
|
63
|
+
* `sides` must be at least 3; otherwise the call errors out
|
|
64
|
+
* (vpinball clamps to 3 in its own editor).
|
|
65
|
+
*
|
|
66
|
+
* `draw_textures_inside = true` doubles the index count so back
|
|
67
|
+
* faces are also rendered (matches vpinball's flag of the same
|
|
68
|
+
* name on `Primitive`). Vertex / texcoord / normal arrays are
|
|
69
|
+
* unaffected.
|
|
70
|
+
*/
|
|
71
|
+
export function generate_builtin_primitive(sides: number, draw_textures_inside: boolean): PrimitiveMesh;
|
|
72
|
+
|
|
8
73
|
export function init(): void;
|
|
9
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Serialize a mesh as a Wavefront OBJ.
|
|
77
|
+
*
|
|
78
|
+
* `name` becomes the `o` directive; pass an empty string to use
|
|
79
|
+
* `"object"`. Vertex / texcoord / normal arrays must have aligned
|
|
80
|
+
* lengths (`positions.len() / 3 == tex_coords.len() / 2 ==
|
|
81
|
+
* normals.len() / 3`); index values must be valid 0-based offsets into
|
|
82
|
+
* that vertex array.
|
|
83
|
+
*
|
|
84
|
+
* `convert_to_left_handed` is the symmetric inverse of the same flag
|
|
85
|
+
* on [`obj_to_mesh`]:
|
|
86
|
+
*
|
|
87
|
+
* - `true` (matches `extract`'s write path): the input is treated as
|
|
88
|
+
* vpx-internal data and converted out: vertex Z is negated, normal Z
|
|
89
|
+
* is negated, V is flipped (`obj_v = 1 - vpx_tv`), and per-triangle
|
|
90
|
+
* corner order is reversed. The result is a vpinball-format OBJ
|
|
91
|
+
* that `assemble` (or `obj_to_mesh(.., true)`) reads back identically.
|
|
92
|
+
* - `false`: the input vpx-internal data is written out verbatim, no
|
|
93
|
+
* transforms applied. Round-trips with `obj_to_mesh(.., false)`.
|
|
94
|
+
*/
|
|
95
|
+
export function mesh_to_obj(name: string, positions: Float32Array, tex_coords: Float32Array, normals: Float32Array, indices: Uint32Array, convert_to_left_handed: boolean): Uint8Array;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Parse a Wavefront OBJ into a [`PrimitiveMesh`].
|
|
99
|
+
*
|
|
100
|
+
* Accepts any OBJ flavor (vpinball-format from `extract`, Blender-format,
|
|
101
|
+
* anything in between): n-gons are fan-triangulated and `(position, uv,
|
|
102
|
+
* normal)` corners are deduplicated so the result is renderer-ready.
|
|
103
|
+
*
|
|
104
|
+
* `convert_to_left_handed` mirrors vpinball's `ObjLoader::Load` flag of
|
|
105
|
+
* the same name (the "Convert coordinate system" checkbox in the
|
|
106
|
+
* vpinball mesh-import dialog):
|
|
107
|
+
*
|
|
108
|
+
* - `true` (matches `assemble`'s read path and vpinball's dialog
|
|
109
|
+
* default): the input is treated as right-handed (Blender / standard
|
|
110
|
+
* convention). Vertex Z is negated, normal Z is negated, V is flipped
|
|
111
|
+
* (`vpx_tv = 1 - obj_v`), and the per-triangle corner order is
|
|
112
|
+
* reversed. The returned mesh data ends up in vpx-internal,
|
|
113
|
+
* left-handed convention.
|
|
114
|
+
* - `false`: the input is assumed to already be in vpx-internal
|
|
115
|
+
* convention (e.g. produced by a previous `mesh_to_obj` with the same
|
|
116
|
+
* flag). The transforms are skipped and values pass through verbatim.
|
|
117
|
+
*/
|
|
118
|
+
export function obj_to_mesh(data: Uint8Array, convert_to_left_handed: boolean): PrimitiveMesh;
|
|
119
|
+
|
|
10
120
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
11
121
|
|
|
12
122
|
export interface InitOutput {
|
|
13
123
|
readonly memory: WebAssembly.Memory;
|
|
124
|
+
readonly __wbg_primitivemesh_free: (a: number, b: number) => void;
|
|
14
125
|
readonly assemble: (a: any, b: number) => [number, number, number, number];
|
|
15
126
|
readonly extract: (a: number, b: number, c: number) => [number, number, number];
|
|
127
|
+
readonly generate_builtin_primitive: (a: number, b: number) => [number, number, number];
|
|
128
|
+
readonly mesh_to_obj: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => [number, number, number, number];
|
|
129
|
+
readonly obj_to_mesh: (a: number, b: number, c: number) => [number, number, number];
|
|
130
|
+
readonly primitivemesh_indices: (a: number) => any;
|
|
131
|
+
readonly primitivemesh_midpoint: (a: number) => any;
|
|
132
|
+
readonly primitivemesh_name: (a: number) => [number, number];
|
|
133
|
+
readonly primitivemesh_normals: (a: number) => any;
|
|
134
|
+
readonly primitivemesh_positions: (a: number) => any;
|
|
135
|
+
readonly primitivemesh_texCoords: (a: number) => any;
|
|
16
136
|
readonly init: () => void;
|
|
17
137
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
18
138
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
package/vpin.js
CHANGED
|
@@ -1,5 +1,105 @@
|
|
|
1
1
|
/* @ts-self-types="./vpin.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Mesh data for a single primitive: positions, texture coordinates,
|
|
5
|
+
* normals and triangle indices, packed as flat typed arrays for direct
|
|
6
|
+
* upload into a WebGL / Three.js / GPU buffer.
|
|
7
|
+
*
|
|
8
|
+
* All vertex data is aligned: `positions[3*i..3*i+3]`, `tex_coords[2*i..2*i+2]`
|
|
9
|
+
* and `normals[3*i..3*i+3]` describe corner `i`. Triangles are 0-based
|
|
10
|
+
* indices into that aligned array.
|
|
11
|
+
*
|
|
12
|
+
* Coordinates are in vpx-internal convention (the same form `read_fs`
|
|
13
|
+
* produces and `write_fs` consumes), not raw OBJ values - see
|
|
14
|
+
* [`obj_to_mesh`] / [`mesh_to_obj`] for the transform details.
|
|
15
|
+
*
|
|
16
|
+
* The published wasm package is built with `wasm-bindgen --weak-refs`,
|
|
17
|
+
* so the Rust-owned vectors backing this struct are reclaimed
|
|
18
|
+
* automatically via `FinalizationRegistry` when the JS wrapper is
|
|
19
|
+
* garbage-collected. Calling `.free()` manually is still allowed for
|
|
20
|
+
* deterministic cleanup of large meshes.
|
|
21
|
+
*/
|
|
22
|
+
export class PrimitiveMesh {
|
|
23
|
+
static __wrap(ptr) {
|
|
24
|
+
const obj = Object.create(PrimitiveMesh.prototype);
|
|
25
|
+
obj.__wbg_ptr = ptr;
|
|
26
|
+
PrimitiveMeshFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
27
|
+
return obj;
|
|
28
|
+
}
|
|
29
|
+
__destroy_into_raw() {
|
|
30
|
+
const ptr = this.__wbg_ptr;
|
|
31
|
+
this.__wbg_ptr = 0;
|
|
32
|
+
PrimitiveMeshFinalization.unregister(this);
|
|
33
|
+
return ptr;
|
|
34
|
+
}
|
|
35
|
+
free() {
|
|
36
|
+
const ptr = this.__destroy_into_raw();
|
|
37
|
+
wasm.__wbg_primitivemesh_free(ptr, 0);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @returns {Uint32Array}
|
|
41
|
+
*/
|
|
42
|
+
get indices() {
|
|
43
|
+
const ret = wasm.primitivemesh_indices(this.__wbg_ptr);
|
|
44
|
+
return ret;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Bounding-box midpoint of the mesh's positions, in the same
|
|
48
|
+
* coordinate space as `positions` (vpx-internal). Returns
|
|
49
|
+
* `[mid_x, mid_y, mid_z]`. Used by editor flows that center the
|
|
50
|
+
* mesh on origin or move the primitive to the mesh's absolute
|
|
51
|
+
* position - both need to know the midpoint to shift vertices
|
|
52
|
+
* (and, for the absolute-position case, to set the primitive's
|
|
53
|
+
* `vPosition` field). Mirrors vpinball's `Mesh::middlePoint`,
|
|
54
|
+
* which is used by `IDC_CENTER_MESH` / `IDC_ABS_POSITION_RADIO`
|
|
55
|
+
* in the mesh-import dialog (`primitive.cpp:1729-1745`).
|
|
56
|
+
*
|
|
57
|
+
* Returns `[0, 0, 0]` for an empty mesh.
|
|
58
|
+
* @returns {Float32Array}
|
|
59
|
+
*/
|
|
60
|
+
get midpoint() {
|
|
61
|
+
const ret = wasm.primitivemesh_midpoint(this.__wbg_ptr);
|
|
62
|
+
return ret;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
get name() {
|
|
68
|
+
let deferred1_0;
|
|
69
|
+
let deferred1_1;
|
|
70
|
+
try {
|
|
71
|
+
const ret = wasm.primitivemesh_name(this.__wbg_ptr);
|
|
72
|
+
deferred1_0 = ret[0];
|
|
73
|
+
deferred1_1 = ret[1];
|
|
74
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
75
|
+
} finally {
|
|
76
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* @returns {Float32Array}
|
|
81
|
+
*/
|
|
82
|
+
get normals() {
|
|
83
|
+
const ret = wasm.primitivemesh_normals(this.__wbg_ptr);
|
|
84
|
+
return ret;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @returns {Float32Array}
|
|
88
|
+
*/
|
|
89
|
+
get positions() {
|
|
90
|
+
const ret = wasm.primitivemesh_positions(this.__wbg_ptr);
|
|
91
|
+
return ret;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @returns {Float32Array}
|
|
95
|
+
*/
|
|
96
|
+
get texCoords() {
|
|
97
|
+
const ret = wasm.primitivemesh_texCoords(this.__wbg_ptr);
|
|
98
|
+
return ret;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (Symbol.dispose) PrimitiveMesh.prototype[Symbol.dispose] = PrimitiveMesh.prototype.free;
|
|
102
|
+
|
|
3
103
|
/**
|
|
4
104
|
* @param {object} files
|
|
5
105
|
* @param {Function | null} [callback]
|
|
@@ -30,24 +130,135 @@ export function extract(data, callback) {
|
|
|
30
130
|
return takeFromExternrefTable0(ret[0]);
|
|
31
131
|
}
|
|
32
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Generate the procedural mesh used by vpinball primitives that
|
|
135
|
+
* don't load a `.obj` file (`use_3d_mesh = false`). Mirrors
|
|
136
|
+
* `Primitive::CalculateBuiltinOriginal` from vpinball: a regular
|
|
137
|
+
* polygon prism with `sides` faces, top and bottom caps, fitting
|
|
138
|
+
* in `[-r, r] x [-r, r] x [-0.5, 0.5]`.
|
|
139
|
+
*
|
|
140
|
+
* Use this to render the placeholder shape for a primitive that
|
|
141
|
+
* has `use_3d_mesh = false`, or to seed the editor's "Add
|
|
142
|
+
* Primitive" workflow.
|
|
143
|
+
*
|
|
144
|
+
* `sides` must be at least 3; otherwise the call errors out
|
|
145
|
+
* (vpinball clamps to 3 in its own editor).
|
|
146
|
+
*
|
|
147
|
+
* `draw_textures_inside = true` doubles the index count so back
|
|
148
|
+
* faces are also rendered (matches vpinball's flag of the same
|
|
149
|
+
* name on `Primitive`). Vertex / texcoord / normal arrays are
|
|
150
|
+
* unaffected.
|
|
151
|
+
* @param {number} sides
|
|
152
|
+
* @param {boolean} draw_textures_inside
|
|
153
|
+
* @returns {PrimitiveMesh}
|
|
154
|
+
*/
|
|
155
|
+
export function generate_builtin_primitive(sides, draw_textures_inside) {
|
|
156
|
+
const ret = wasm.generate_builtin_primitive(sides, draw_textures_inside);
|
|
157
|
+
if (ret[2]) {
|
|
158
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
159
|
+
}
|
|
160
|
+
return PrimitiveMesh.__wrap(ret[0]);
|
|
161
|
+
}
|
|
162
|
+
|
|
33
163
|
export function init() {
|
|
34
164
|
wasm.init();
|
|
35
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Serialize a mesh as a Wavefront OBJ.
|
|
169
|
+
*
|
|
170
|
+
* `name` becomes the `o` directive; pass an empty string to use
|
|
171
|
+
* `"object"`. Vertex / texcoord / normal arrays must have aligned
|
|
172
|
+
* lengths (`positions.len() / 3 == tex_coords.len() / 2 ==
|
|
173
|
+
* normals.len() / 3`); index values must be valid 0-based offsets into
|
|
174
|
+
* that vertex array.
|
|
175
|
+
*
|
|
176
|
+
* `convert_to_left_handed` is the symmetric inverse of the same flag
|
|
177
|
+
* on [`obj_to_mesh`]:
|
|
178
|
+
*
|
|
179
|
+
* - `true` (matches `extract`'s write path): the input is treated as
|
|
180
|
+
* vpx-internal data and converted out: vertex Z is negated, normal Z
|
|
181
|
+
* is negated, V is flipped (`obj_v = 1 - vpx_tv`), and per-triangle
|
|
182
|
+
* corner order is reversed. The result is a vpinball-format OBJ
|
|
183
|
+
* that `assemble` (or `obj_to_mesh(.., true)`) reads back identically.
|
|
184
|
+
* - `false`: the input vpx-internal data is written out verbatim, no
|
|
185
|
+
* transforms applied. Round-trips with `obj_to_mesh(.., false)`.
|
|
186
|
+
* @param {string} name
|
|
187
|
+
* @param {Float32Array} positions
|
|
188
|
+
* @param {Float32Array} tex_coords
|
|
189
|
+
* @param {Float32Array} normals
|
|
190
|
+
* @param {Uint32Array} indices
|
|
191
|
+
* @param {boolean} convert_to_left_handed
|
|
192
|
+
* @returns {Uint8Array}
|
|
193
|
+
*/
|
|
194
|
+
export function mesh_to_obj(name, positions, tex_coords, normals, indices, convert_to_left_handed) {
|
|
195
|
+
const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
196
|
+
const len0 = WASM_VECTOR_LEN;
|
|
197
|
+
const ptr1 = passArrayF32ToWasm0(positions, wasm.__wbindgen_malloc);
|
|
198
|
+
const len1 = WASM_VECTOR_LEN;
|
|
199
|
+
const ptr2 = passArrayF32ToWasm0(tex_coords, wasm.__wbindgen_malloc);
|
|
200
|
+
const len2 = WASM_VECTOR_LEN;
|
|
201
|
+
const ptr3 = passArrayF32ToWasm0(normals, wasm.__wbindgen_malloc);
|
|
202
|
+
const len3 = WASM_VECTOR_LEN;
|
|
203
|
+
const ptr4 = passArray32ToWasm0(indices, wasm.__wbindgen_malloc);
|
|
204
|
+
const len4 = WASM_VECTOR_LEN;
|
|
205
|
+
const ret = wasm.mesh_to_obj(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, convert_to_left_handed);
|
|
206
|
+
if (ret[3]) {
|
|
207
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
208
|
+
}
|
|
209
|
+
var v6 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
210
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
211
|
+
return v6;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Parse a Wavefront OBJ into a [`PrimitiveMesh`].
|
|
216
|
+
*
|
|
217
|
+
* Accepts any OBJ flavor (vpinball-format from `extract`, Blender-format,
|
|
218
|
+
* anything in between): n-gons are fan-triangulated and `(position, uv,
|
|
219
|
+
* normal)` corners are deduplicated so the result is renderer-ready.
|
|
220
|
+
*
|
|
221
|
+
* `convert_to_left_handed` mirrors vpinball's `ObjLoader::Load` flag of
|
|
222
|
+
* the same name (the "Convert coordinate system" checkbox in the
|
|
223
|
+
* vpinball mesh-import dialog):
|
|
224
|
+
*
|
|
225
|
+
* - `true` (matches `assemble`'s read path and vpinball's dialog
|
|
226
|
+
* default): the input is treated as right-handed (Blender / standard
|
|
227
|
+
* convention). Vertex Z is negated, normal Z is negated, V is flipped
|
|
228
|
+
* (`vpx_tv = 1 - obj_v`), and the per-triangle corner order is
|
|
229
|
+
* reversed. The returned mesh data ends up in vpx-internal,
|
|
230
|
+
* left-handed convention.
|
|
231
|
+
* - `false`: the input is assumed to already be in vpx-internal
|
|
232
|
+
* convention (e.g. produced by a previous `mesh_to_obj` with the same
|
|
233
|
+
* flag). The transforms are skipped and values pass through verbatim.
|
|
234
|
+
* @param {Uint8Array} data
|
|
235
|
+
* @param {boolean} convert_to_left_handed
|
|
236
|
+
* @returns {PrimitiveMesh}
|
|
237
|
+
*/
|
|
238
|
+
export function obj_to_mesh(data, convert_to_left_handed) {
|
|
239
|
+
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
|
240
|
+
const len0 = WASM_VECTOR_LEN;
|
|
241
|
+
const ret = wasm.obj_to_mesh(ptr0, len0, convert_to_left_handed);
|
|
242
|
+
if (ret[2]) {
|
|
243
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
244
|
+
}
|
|
245
|
+
return PrimitiveMesh.__wrap(ret[0]);
|
|
246
|
+
}
|
|
36
247
|
function __wbg_get_imports() {
|
|
37
248
|
const import0 = {
|
|
38
249
|
__proto__: null,
|
|
39
|
-
|
|
250
|
+
__wbg_Error_bce6d499ff0a4aff: function(arg0, arg1) {
|
|
40
251
|
const ret = Error(getStringFromWasm0(arg0, arg1));
|
|
41
252
|
return ret;
|
|
42
253
|
},
|
|
43
|
-
|
|
254
|
+
__wbg___wbindgen_debug_string_edece8177ad01481: function(arg0, arg1) {
|
|
44
255
|
const ret = debugString(arg1);
|
|
45
256
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
46
257
|
const len1 = WASM_VECTOR_LEN;
|
|
47
258
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
48
259
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
49
260
|
},
|
|
50
|
-
|
|
261
|
+
__wbg___wbindgen_string_get_d109740c0d18f4d7: function(arg0, arg1) {
|
|
51
262
|
const obj = arg1;
|
|
52
263
|
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
53
264
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
@@ -55,10 +266,10 @@ function __wbg_get_imports() {
|
|
|
55
266
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
56
267
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
57
268
|
},
|
|
58
|
-
|
|
269
|
+
__wbg___wbindgen_throw_9c31b086c2b26051: function(arg0, arg1) {
|
|
59
270
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
60
271
|
},
|
|
61
|
-
|
|
272
|
+
__wbg_call_dfde26266607c996: function() { return handleError(function (arg0, arg1, arg2) {
|
|
62
273
|
const ret = arg0.call(arg1, arg2);
|
|
63
274
|
return ret;
|
|
64
275
|
}, arguments); },
|
|
@@ -73,46 +284,54 @@ function __wbg_get_imports() {
|
|
|
73
284
|
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
74
285
|
}
|
|
75
286
|
},
|
|
76
|
-
|
|
77
|
-
const ret = Reflect.get(arg0, arg1);
|
|
78
|
-
return ret;
|
|
79
|
-
}, arguments); },
|
|
80
|
-
__wbg_get_652f640b3b0b6e3e: function(arg0, arg1) {
|
|
287
|
+
__wbg_get_98fdf51d029a75eb: function(arg0, arg1) {
|
|
81
288
|
const ret = arg0[arg1 >>> 0];
|
|
82
289
|
return ret;
|
|
83
290
|
},
|
|
84
|
-
|
|
291
|
+
__wbg_get_dcf82ab8aad1a593: function() { return handleError(function (arg0, arg1) {
|
|
292
|
+
const ret = Reflect.get(arg0, arg1);
|
|
293
|
+
return ret;
|
|
294
|
+
}, arguments); },
|
|
295
|
+
__wbg_keys_682010b680c9b1f8: function(arg0) {
|
|
85
296
|
const ret = Object.keys(arg0);
|
|
86
297
|
return ret;
|
|
87
298
|
},
|
|
88
|
-
|
|
299
|
+
__wbg_length_2591a0f4f659a55c: function(arg0) {
|
|
89
300
|
const ret = arg0.length;
|
|
90
301
|
return ret;
|
|
91
302
|
},
|
|
92
|
-
|
|
303
|
+
__wbg_length_56fcd3e2b7e0299d: function(arg0) {
|
|
93
304
|
const ret = arg0.length;
|
|
94
305
|
return ret;
|
|
95
306
|
},
|
|
307
|
+
__wbg_new_02d162bc6cf02f60: function() {
|
|
308
|
+
const ret = new Object();
|
|
309
|
+
return ret;
|
|
310
|
+
},
|
|
96
311
|
__wbg_new_227d7c05414eb861: function() {
|
|
97
312
|
const ret = new Error();
|
|
98
313
|
return ret;
|
|
99
314
|
},
|
|
100
|
-
|
|
101
|
-
const ret = new
|
|
315
|
+
__wbg_new_from_slice_269e35316ed2d061: function(arg0, arg1) {
|
|
316
|
+
const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
|
|
102
317
|
return ret;
|
|
103
318
|
},
|
|
104
|
-
|
|
105
|
-
const ret = new
|
|
319
|
+
__wbg_new_from_slice_7a419f18ea6472bf: function(arg0, arg1) {
|
|
320
|
+
const ret = new Float32Array(getArrayF32FromWasm0(arg0, arg1));
|
|
321
|
+
return ret;
|
|
322
|
+
},
|
|
323
|
+
__wbg_new_from_slice_f92bf65e9a895613: function(arg0, arg1) {
|
|
324
|
+
const ret = new Uint32Array(getArrayU32FromWasm0(arg0, arg1));
|
|
106
325
|
return ret;
|
|
107
326
|
},
|
|
108
|
-
|
|
327
|
+
__wbg_now_81363d44c96dd239: function() {
|
|
109
328
|
const ret = Date.now();
|
|
110
329
|
return ret;
|
|
111
330
|
},
|
|
112
|
-
|
|
331
|
+
__wbg_prototypesetcall_5f9bdc8d75e07276: function(arg0, arg1, arg2) {
|
|
113
332
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
114
333
|
},
|
|
115
|
-
|
|
334
|
+
__wbg_set_a0e911be3da02782: function() { return handleError(function (arg0, arg1, arg2) {
|
|
116
335
|
const ret = Reflect.set(arg0, arg1, arg2);
|
|
117
336
|
return ret;
|
|
118
337
|
}, arguments); },
|
|
@@ -144,6 +363,10 @@ function __wbg_get_imports() {
|
|
|
144
363
|
};
|
|
145
364
|
}
|
|
146
365
|
|
|
366
|
+
const PrimitiveMeshFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
367
|
+
? { register: () => {}, unregister: () => {} }
|
|
368
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_primitivemesh_free(ptr, 1));
|
|
369
|
+
|
|
147
370
|
function addToExternrefTable0(obj) {
|
|
148
371
|
const idx = wasm.__externref_table_alloc();
|
|
149
372
|
wasm.__wbindgen_externrefs.set(idx, obj);
|
|
@@ -215,6 +438,16 @@ function debugString(val) {
|
|
|
215
438
|
return className;
|
|
216
439
|
}
|
|
217
440
|
|
|
441
|
+
function getArrayF32FromWasm0(ptr, len) {
|
|
442
|
+
ptr = ptr >>> 0;
|
|
443
|
+
return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function getArrayU32FromWasm0(ptr, len) {
|
|
447
|
+
ptr = ptr >>> 0;
|
|
448
|
+
return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
449
|
+
}
|
|
450
|
+
|
|
218
451
|
function getArrayU8FromWasm0(ptr, len) {
|
|
219
452
|
ptr = ptr >>> 0;
|
|
220
453
|
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
@@ -228,10 +461,26 @@ function getDataViewMemory0() {
|
|
|
228
461
|
return cachedDataViewMemory0;
|
|
229
462
|
}
|
|
230
463
|
|
|
464
|
+
let cachedFloat32ArrayMemory0 = null;
|
|
465
|
+
function getFloat32ArrayMemory0() {
|
|
466
|
+
if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
|
|
467
|
+
cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
|
|
468
|
+
}
|
|
469
|
+
return cachedFloat32ArrayMemory0;
|
|
470
|
+
}
|
|
471
|
+
|
|
231
472
|
function getStringFromWasm0(ptr, len) {
|
|
232
473
|
return decodeText(ptr >>> 0, len);
|
|
233
474
|
}
|
|
234
475
|
|
|
476
|
+
let cachedUint32ArrayMemory0 = null;
|
|
477
|
+
function getUint32ArrayMemory0() {
|
|
478
|
+
if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
|
|
479
|
+
cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
|
|
480
|
+
}
|
|
481
|
+
return cachedUint32ArrayMemory0;
|
|
482
|
+
}
|
|
483
|
+
|
|
235
484
|
let cachedUint8ArrayMemory0 = null;
|
|
236
485
|
function getUint8ArrayMemory0() {
|
|
237
486
|
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
@@ -253,6 +502,13 @@ function isLikeNone(x) {
|
|
|
253
502
|
return x === undefined || x === null;
|
|
254
503
|
}
|
|
255
504
|
|
|
505
|
+
function passArray32ToWasm0(arg, malloc) {
|
|
506
|
+
const ptr = malloc(arg.length * 4, 4) >>> 0;
|
|
507
|
+
getUint32ArrayMemory0().set(arg, ptr / 4);
|
|
508
|
+
WASM_VECTOR_LEN = arg.length;
|
|
509
|
+
return ptr;
|
|
510
|
+
}
|
|
511
|
+
|
|
256
512
|
function passArray8ToWasm0(arg, malloc) {
|
|
257
513
|
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
258
514
|
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
@@ -260,6 +516,13 @@ function passArray8ToWasm0(arg, malloc) {
|
|
|
260
516
|
return ptr;
|
|
261
517
|
}
|
|
262
518
|
|
|
519
|
+
function passArrayF32ToWasm0(arg, malloc) {
|
|
520
|
+
const ptr = malloc(arg.length * 4, 4) >>> 0;
|
|
521
|
+
getFloat32ArrayMemory0().set(arg, ptr / 4);
|
|
522
|
+
WASM_VECTOR_LEN = arg.length;
|
|
523
|
+
return ptr;
|
|
524
|
+
}
|
|
525
|
+
|
|
263
526
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
264
527
|
if (realloc === undefined) {
|
|
265
528
|
const buf = cachedTextEncoder.encode(arg);
|
|
@@ -338,6 +601,8 @@ function __wbg_finalize_init(instance, module) {
|
|
|
338
601
|
wasm = instance.exports;
|
|
339
602
|
wasmModule = module;
|
|
340
603
|
cachedDataViewMemory0 = null;
|
|
604
|
+
cachedFloat32ArrayMemory0 = null;
|
|
605
|
+
cachedUint32ArrayMemory0 = null;
|
|
341
606
|
cachedUint8ArrayMemory0 = null;
|
|
342
607
|
wasm.__wbindgen_start();
|
|
343
608
|
return wasm;
|
package/vpin_bg.wasm
CHANGED
|
Binary file
|
package/vpin_bg.wasm.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const __wbg_primitivemesh_free: (a: number, b: number) => void;
|
|
4
5
|
export const assemble: (a: any, b: number) => [number, number, number, number];
|
|
5
6
|
export const extract: (a: number, b: number, c: number) => [number, number, number];
|
|
7
|
+
export const generate_builtin_primitive: (a: number, b: number) => [number, number, number];
|
|
8
|
+
export const mesh_to_obj: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => [number, number, number, number];
|
|
9
|
+
export const obj_to_mesh: (a: number, b: number, c: number) => [number, number, number];
|
|
10
|
+
export const primitivemesh_indices: (a: number) => any;
|
|
11
|
+
export const primitivemesh_midpoint: (a: number) => any;
|
|
12
|
+
export const primitivemesh_name: (a: number) => [number, number];
|
|
13
|
+
export const primitivemesh_normals: (a: number) => any;
|
|
14
|
+
export const primitivemesh_positions: (a: number) => any;
|
|
15
|
+
export const primitivemesh_texCoords: (a: number) => any;
|
|
6
16
|
export const init: () => void;
|
|
7
17
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
8
18
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|