@caspertech/node-metaverse 0.7.55 → 0.8.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.
Files changed (30) hide show
  1. package/dist/lib/classes/InventoryFolder.js +3 -1
  2. package/dist/lib/classes/InventoryFolder.js.map +1 -1
  3. package/dist/lib/classes/LLAnimation.d.ts +32 -0
  4. package/dist/lib/classes/LLAnimation.js +90 -0
  5. package/dist/lib/classes/LLAnimation.js.map +1 -0
  6. package/dist/lib/classes/LLAnimationJoint.d.ts +13 -0
  7. package/dist/lib/classes/LLAnimationJoint.js +56 -0
  8. package/dist/lib/classes/LLAnimationJoint.js.map +1 -0
  9. package/dist/lib/classes/LLAnimationJointKeyFrame.d.ts +5 -0
  10. package/dist/lib/classes/LLAnimationJointKeyFrame.js +7 -0
  11. package/dist/lib/classes/LLAnimationJointKeyFrame.js.map +1 -0
  12. package/dist/lib/classes/LLWearable.js +0 -1
  13. package/dist/lib/classes/LLWearable.js.map +1 -1
  14. package/dist/lib/classes/Matrix3.d.ts +28 -0
  15. package/dist/lib/classes/Matrix3.js +348 -0
  16. package/dist/lib/classes/Matrix3.js.map +1 -0
  17. package/dist/lib/classes/Matrix4.d.ts +34 -0
  18. package/dist/lib/classes/Matrix4.js +396 -0
  19. package/dist/lib/classes/Matrix4.js.map +1 -0
  20. package/dist/lib/classes/ObjectStoreFull.js +1 -0
  21. package/dist/lib/classes/ObjectStoreFull.js.map +1 -1
  22. package/dist/lib/classes/Utils.d.ts +3 -2
  23. package/dist/lib/classes/Utils.js +17 -6
  24. package/dist/lib/classes/Utils.js.map +1 -1
  25. package/dist/lib/classes/public/LLMesh.d.ts +36 -14
  26. package/dist/lib/classes/public/LLMesh.js +468 -204
  27. package/dist/lib/classes/public/LLMesh.js.map +1 -1
  28. package/dist/lib/classes/public/interfaces/LLSkin.d.ts +5 -5
  29. package/dist/lib/classes/public/interfaces/LLSubMesh.d.ts +2 -2
  30. package/package.json +1 -1
@@ -1,92 +1,329 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LLMesh = void 0;
4
- const LLSD = require("@caspertech/llsd");
5
4
  const UUID_1 = require("../UUID");
6
5
  const Vector3_1 = require("../Vector3");
7
6
  const Vector2_1 = require("../Vector2");
8
7
  const Utils_1 = require("../Utils");
9
- const mat4_1 = require("../../tsm/mat4");
8
+ const buffer_1 = require("buffer");
9
+ const LLSD_1 = require("../llsd/LLSD");
10
+ const LLSDMap_1 = require("../llsd/LLSDMap");
11
+ const LLSDInteger_1 = require("../llsd/LLSDInteger");
12
+ const LLSDReal_1 = require("../llsd/LLSDReal");
13
+ const Matrix4_1 = require("../Matrix4");
10
14
  class LLMesh {
11
15
  constructor() {
12
16
  this.lodLevels = {};
13
17
  }
14
18
  static async from(buf) {
15
19
  const llmesh = new LLMesh();
16
- const binData = new LLSD.Binary(Array.from(buf), 'BASE64');
17
- let obj = LLSD.LLSD.parseBinary(binData);
18
- if (obj.result === undefined) {
19
- throw new Error('Failed to decode header');
20
- }
21
- if (obj.position === undefined) {
22
- throw new Error('Position not reported');
23
- }
24
- const startPos = parseInt(obj.position, 10);
25
- obj = obj.result;
26
- if (obj.creator !== undefined) {
27
- llmesh.creatorID = new UUID_1.UUID(obj.creator.toString());
28
- }
29
- if (obj.date !== undefined) {
30
- llmesh.date = obj.date;
31
- }
32
- if (obj.version !== undefined) {
33
- llmesh.version = parseInt(obj.version, 10);
34
- }
35
- for (const key of Object.keys(obj)) {
36
- const o = obj[key];
37
- if (typeof o === 'object' && o !== null && o.offset !== undefined) {
38
- const bufFrom = startPos + parseInt(o.offset, 10);
39
- const bufTo = startPos + parseInt(o.offset, 10) + parseInt(o.size, 10);
40
- const partBuf = buf.subarray(bufFrom, bufTo);
41
- const deflated = await Utils_1.Utils.inflate(partBuf);
42
- const mesh = LLSD.LLSD.parseBinary(new LLSD.Binary(Array.from(deflated), 'BASE64'));
43
- if (mesh.result === undefined) {
44
- throw new Error('Failed to parse compressed submesh data');
45
- }
46
- if (key === 'physics_convex') {
47
- llmesh.physicsConvex = this.parsePhysicsConvex(mesh.result);
48
- }
49
- else if (key === 'skin') {
50
- llmesh.skin = this.parseSkin(mesh.result);
51
- }
52
- else if (key === 'physics_havok' || key === 'physics_cost_data') {
53
- }
54
- else {
55
- llmesh.lodLevels[key] = this.parseLODLevel(mesh.result);
56
- }
20
+ const metadata = {
21
+ readPos: 0
22
+ };
23
+ const obj = LLSD_1.LLSD.parseBinary(buf, metadata);
24
+ if (!(obj instanceof LLSDMap_1.LLSDMap)) {
25
+ throw new Error('Invalid mesh');
26
+ }
27
+ for (const key of obj.keys()) {
28
+ switch (key) {
29
+ case 'creator':
30
+ {
31
+ const u = obj[key];
32
+ if (u instanceof UUID_1.UUID) {
33
+ llmesh.creatorID = u;
34
+ }
35
+ break;
36
+ }
37
+ case 'version':
38
+ {
39
+ const int = obj[key];
40
+ if (int instanceof LLSDInteger_1.LLSDInteger) {
41
+ llmesh.version = int.valueOf();
42
+ }
43
+ break;
44
+ }
45
+ case 'date':
46
+ {
47
+ const dt = obj[key];
48
+ if (dt instanceof Date) {
49
+ llmesh.date = dt;
50
+ }
51
+ break;
52
+ }
53
+ case 'physics_cost_data':
54
+ {
55
+ const map = obj[key];
56
+ if (map instanceof LLSDMap_1.LLSDMap) {
57
+ llmesh.costData = {
58
+ hull: 0,
59
+ hull_discounted_vertices: 0,
60
+ mesh: [],
61
+ mesh_triangles: 0
62
+ };
63
+ if (map.hull instanceof LLSDReal_1.LLSDReal) {
64
+ llmesh.costData.hull = map.hull.valueOf();
65
+ }
66
+ if (map.hull_discounted_vertices instanceof LLSDInteger_1.LLSDInteger) {
67
+ llmesh.costData.hull_discounted_vertices = map.hull_discounted_vertices.valueOf();
68
+ }
69
+ if (Array.isArray(map.mesh)) {
70
+ for (const num of map.mesh) {
71
+ if (num instanceof LLSDReal_1.LLSDReal) {
72
+ llmesh.costData.mesh.push(num.valueOf());
73
+ }
74
+ }
75
+ }
76
+ if (map.mesh_triangles instanceof LLSDInteger_1.LLSDInteger) {
77
+ llmesh.costData.mesh_triangles = map.mesh_triangles.valueOf();
78
+ }
79
+ }
80
+ break;
81
+ }
82
+ case 'physics_shape':
83
+ case 'physics_mesh':
84
+ case 'high_lod':
85
+ case 'medium_lod':
86
+ case 'low_lod':
87
+ case 'lowest_lod':
88
+ case 'physics_convex':
89
+ case 'physics_havok':
90
+ case 'skin':
91
+ {
92
+ const skin = obj[key];
93
+ if (skin instanceof LLSDMap_1.LLSDMap) {
94
+ const hash = skin.get('hash');
95
+ const offset = skin.get('offset');
96
+ const size = skin.get('size');
97
+ if (offset instanceof LLSDInteger_1.LLSDInteger && size instanceof LLSDInteger_1.LLSDInteger) {
98
+ const offsetVal = offset.valueOf();
99
+ const sizeVal = size.valueOf();
100
+ const startPos = metadata.readPos + offsetVal;
101
+ const endPos = offsetVal + sizeVal + metadata.readPos;
102
+ const bufSlice = buf.subarray(startPos, endPos);
103
+ if (hash instanceof buffer_1.Buffer) {
104
+ const inflatedHash = Utils_1.Utils.MD5String(bufSlice);
105
+ if (inflatedHash !== hash.toString('hex')) {
106
+ throw new Error('Hash mismatch');
107
+ }
108
+ }
109
+ const inflated = await Utils_1.Utils.inflate(bufSlice);
110
+ const parsed = LLSD_1.LLSD.parseBinary(inflated);
111
+ if (key === 'physics_havok') {
112
+ if (parsed instanceof LLSDMap_1.LLSDMap) {
113
+ llmesh.physicsHavok = {
114
+ weldingData: buffer_1.Buffer.alloc(0),
115
+ hullMassProps: {
116
+ CoM: [],
117
+ inertia: [],
118
+ mass: 0,
119
+ volume: 0
120
+ },
121
+ meshDecompMassProps: {
122
+ CoM: [],
123
+ inertia: [],
124
+ mass: 0,
125
+ volume: 0
126
+ }
127
+ };
128
+ if (parsed.HullMassProps instanceof LLSDMap_1.LLSDMap) {
129
+ if (Array.isArray(parsed.HullMassProps.CoM)) {
130
+ for (const num of parsed.HullMassProps.CoM) {
131
+ if (num instanceof LLSDReal_1.LLSDReal) {
132
+ llmesh.physicsHavok.hullMassProps.CoM.push(num.valueOf());
133
+ }
134
+ }
135
+ }
136
+ if (Array.isArray(parsed.HullMassProps.inertia)) {
137
+ for (const num of parsed.HullMassProps.inertia) {
138
+ if (num instanceof LLSDReal_1.LLSDReal) {
139
+ llmesh.physicsHavok.hullMassProps.inertia.push(num.valueOf());
140
+ }
141
+ }
142
+ }
143
+ if (parsed.HullMassProps.mass instanceof LLSDReal_1.LLSDReal) {
144
+ llmesh.physicsHavok.hullMassProps.mass = parsed.HullMassProps.mass.valueOf();
145
+ }
146
+ if (parsed.HullMassProps.volume instanceof LLSDReal_1.LLSDReal) {
147
+ llmesh.physicsHavok.hullMassProps.volume = parsed.HullMassProps.volume.valueOf();
148
+ }
149
+ }
150
+ if (parsed.MeshDecompMassProps instanceof LLSDMap_1.LLSDMap) {
151
+ if (Array.isArray(parsed.MeshDecompMassProps.CoM)) {
152
+ for (const num of parsed.MeshDecompMassProps.CoM) {
153
+ if (num instanceof LLSDReal_1.LLSDReal) {
154
+ llmesh.physicsHavok.meshDecompMassProps.CoM.push(num.valueOf());
155
+ }
156
+ }
157
+ }
158
+ if (Array.isArray(parsed.MeshDecompMassProps.inertia)) {
159
+ for (const num of parsed.MeshDecompMassProps.inertia) {
160
+ if (num instanceof LLSDReal_1.LLSDReal) {
161
+ llmesh.physicsHavok.meshDecompMassProps.inertia.push(num.valueOf());
162
+ }
163
+ }
164
+ }
165
+ if (parsed.MeshDecompMassProps.mass instanceof LLSDReal_1.LLSDReal) {
166
+ llmesh.physicsHavok.meshDecompMassProps.mass = parsed.MeshDecompMassProps.mass.valueOf();
167
+ }
168
+ if (parsed.MeshDecompMassProps.volume instanceof LLSDReal_1.LLSDReal) {
169
+ llmesh.physicsHavok.meshDecompMassProps.volume = parsed.MeshDecompMassProps.volume.valueOf();
170
+ }
171
+ }
172
+ if (parsed.WeldingData instanceof buffer_1.Buffer) {
173
+ llmesh.physicsHavok.weldingData = parsed.WeldingData;
174
+ }
175
+ }
176
+ }
177
+ else if (key === 'skin') {
178
+ if (parsed instanceof LLSDMap_1.LLSDMap) {
179
+ llmesh.skin = this.parseSkin(parsed);
180
+ }
181
+ }
182
+ else if (key === 'physics_convex') {
183
+ if (parsed instanceof LLSDMap_1.LLSDMap) {
184
+ llmesh.physicsConvex = this.parsePhysicsConvex(parsed);
185
+ }
186
+ }
187
+ else {
188
+ if (Array.isArray(parsed)) {
189
+ const subMeshes = [];
190
+ for (const sm of parsed) {
191
+ if (sm instanceof LLSDMap_1.LLSDMap) {
192
+ subMeshes.push(sm);
193
+ }
194
+ }
195
+ llmesh.lodLevels[key] = this.parseLODLevel(subMeshes);
196
+ }
197
+ }
198
+ }
199
+ }
200
+ break;
201
+ }
202
+ default:
203
+ {
204
+ console.warn('Unrecognised mesh property: ' + key);
205
+ }
57
206
  }
58
207
  }
59
208
  return llmesh;
60
209
  }
61
- static parseSkin(mesh) {
62
- if (mesh.joint_names === undefined) {
63
- throw new Error('Joint names missing from skin');
210
+ async toAsset() {
211
+ const llsd = new LLSDMap_1.LLSDMap();
212
+ if (this.creatorID) {
213
+ llsd.add('creator', this.creatorID);
214
+ }
215
+ if (this.version !== undefined) {
216
+ llsd.add('version', new LLSDInteger_1.LLSDInteger(this.version));
217
+ }
218
+ if (this.date !== undefined) {
219
+ llsd.add('date', this.date);
220
+ }
221
+ let offset = 0;
222
+ const bufs = [];
223
+ for (const lod of Object.keys(this.lodLevels)) {
224
+ const lodBlob = await this.encodeLODLevel(lod, this.lodLevels[lod]);
225
+ llsd.add(lod, new LLSDMap_1.LLSDMap([
226
+ ['offset', new LLSDInteger_1.LLSDInteger(offset)],
227
+ ['size', new LLSDInteger_1.LLSDInteger(lodBlob.length)]
228
+ ]));
229
+ offset += lodBlob.length;
230
+ bufs.push(lodBlob);
231
+ }
232
+ if (this.costData) {
233
+ llsd.add('physics_cost_data', new LLSDMap_1.LLSDMap([
234
+ ['hull', new LLSDReal_1.LLSDReal(this.costData.hull)],
235
+ ['hull_discounted_vertices', new LLSDInteger_1.LLSDInteger(this.costData.hull_discounted_vertices)],
236
+ ['mesh', LLMesh.toLLSDReal(this.costData.mesh)],
237
+ ['mesh_triangles', new LLSDInteger_1.LLSDInteger(this.costData.mesh_triangles)]
238
+ ]));
239
+ }
240
+ if (this.physicsHavok) {
241
+ const physHavok = await this.encodePhysicsHavok();
242
+ llsd.add('physics_havok', new LLSDMap_1.LLSDMap([
243
+ ['offset', new LLSDInteger_1.LLSDInteger(offset)],
244
+ ['size', new LLSDInteger_1.LLSDInteger(physHavok.length)]
245
+ ]));
246
+ offset += physHavok.length;
247
+ bufs.push(physHavok);
64
248
  }
65
- if (mesh.bind_shape_matrix === undefined) {
66
- throw new Error('Bind shape matrix missing from skin');
249
+ if (this.physicsConvex) {
250
+ const physBlob = await this.encodePhysicsConvex(this.physicsConvex);
251
+ llsd.add('physics_convex', new LLSDMap_1.LLSDMap([
252
+ ['offset', new LLSDInteger_1.LLSDInteger(offset)],
253
+ ['size', new LLSDInteger_1.LLSDInteger(physBlob.length)]
254
+ ]));
255
+ offset += physBlob.length;
256
+ bufs.push(physBlob);
67
257
  }
68
- if (mesh.inverse_bind_matrix === undefined) {
69
- throw new Error('Inverse bind matrix missing from skin');
258
+ if (this.skin) {
259
+ const skinBlob = await this.encodeSkin(this.skin);
260
+ llsd.add('skin', new LLSDMap_1.LLSDMap([
261
+ ['offset', new LLSDInteger_1.LLSDInteger(offset)],
262
+ ['size', new LLSDInteger_1.LLSDInteger(skinBlob.length)]
263
+ ]));
264
+ bufs.push(skinBlob);
70
265
  }
266
+ bufs.unshift(LLSD_1.LLSD.toBinary(llsd));
267
+ return buffer_1.Buffer.concat(bufs);
268
+ }
269
+ static parseSkin(mesh) {
71
270
  const skin = {
72
- jointNames: mesh.joint_names,
73
- bindShapeMatrix: new mat4_1.TSMMat4(mesh.bind_shape_matrix),
271
+ jointNames: [],
272
+ bindShapeMatrix: new Matrix4_1.Matrix4(),
74
273
  inverseBindMatrix: []
75
274
  };
76
- if (mesh.inverse_bind_matrix !== undefined) {
275
+ if (Array.isArray(mesh.joint_names)) {
276
+ for (const joint of mesh.joint_names) {
277
+ if (typeof joint === 'string') {
278
+ skin.jointNames.push(joint);
279
+ }
280
+ }
281
+ }
282
+ if (Array.isArray(mesh.bind_shape_matrix)) {
283
+ const params = [];
284
+ for (const num of mesh.bind_shape_matrix) {
285
+ if (num instanceof LLSDReal_1.LLSDReal) {
286
+ params.push(num.valueOf());
287
+ }
288
+ }
289
+ skin.bindShapeMatrix = new Matrix4_1.Matrix4(params);
290
+ }
291
+ if (Array.isArray(mesh.inverse_bind_matrix)) {
77
292
  skin.inverseBindMatrix = [];
78
293
  for (const inv of mesh.inverse_bind_matrix) {
79
- skin.inverseBindMatrix.push(new mat4_1.TSMMat4(inv));
294
+ const mtrx = [];
295
+ if (Array.isArray(inv)) {
296
+ for (const num of inv) {
297
+ if (num instanceof LLSDReal_1.LLSDReal) {
298
+ mtrx.push(num.valueOf());
299
+ }
300
+ }
301
+ }
302
+ skin.inverseBindMatrix.push(new Matrix4_1.Matrix4(mtrx));
80
303
  }
81
304
  }
82
- if (mesh.alt_inverse_bind_matrix !== undefined) {
305
+ if (Array.isArray(mesh.alt_inverse_bind_matrix)) {
83
306
  skin.altInverseBindMatrix = [];
84
307
  for (const inv of mesh.alt_inverse_bind_matrix) {
85
- skin.altInverseBindMatrix.push(new mat4_1.TSMMat4(inv));
308
+ const mtrx = [];
309
+ if (Array.isArray(inv)) {
310
+ for (const num of inv) {
311
+ if (num instanceof LLSDReal_1.LLSDReal) {
312
+ mtrx.push(num.valueOf());
313
+ }
314
+ }
315
+ }
316
+ skin.altInverseBindMatrix.push(new Matrix4_1.Matrix4(mtrx));
86
317
  }
87
318
  }
88
- if (mesh.pelvis_offset !== undefined) {
89
- skin.pelvisOffset = new mat4_1.TSMMat4(mesh.pelvis_offset);
319
+ if (Array.isArray(mesh.pelvis_offset)) {
320
+ const mtrx = [];
321
+ for (const num of mesh.pelvis_offset) {
322
+ if (num instanceof LLSDReal_1.LLSDReal) {
323
+ mtrx.push(num.valueOf());
324
+ }
325
+ }
326
+ skin.pelvisOffset = new Matrix4_1.Matrix4(mtrx);
90
327
  }
91
328
  return skin;
92
329
  }
@@ -100,6 +337,16 @@ class LLMesh {
100
337
  }
101
338
  return newArr;
102
339
  }
340
+ static fixRealLLSD(arr) {
341
+ const newArr = [];
342
+ for (let num of arr) {
343
+ if ((num >> 0) === num && !((num === 0) && ((1 / num) === -Infinity))) {
344
+ num += 0.0000000001;
345
+ }
346
+ newArr.push(new LLSDReal_1.LLSDReal(num));
347
+ }
348
+ return newArr;
349
+ }
103
350
  static parsePhysicsConvex(mesh) {
104
351
  const conv = {
105
352
  boundingVerts: [],
@@ -108,39 +355,34 @@ class LLMesh {
108
355
  max: new Vector3_1.Vector3([0.5, 0.5, 0.5])
109
356
  }
110
357
  };
111
- if (mesh.Min !== undefined) {
112
- conv.domain.min.x = mesh.Min[0];
113
- conv.domain.min.y = mesh.Min[1];
114
- conv.domain.min.z = mesh.Min[2];
115
- }
116
- if (mesh.Max !== undefined) {
117
- conv.domain.max.x = mesh.Max[0];
118
- conv.domain.max.y = mesh.Max[1];
119
- conv.domain.max.z = mesh.Max[2];
120
- }
121
- if (mesh.HullList !== undefined) {
122
- if (mesh.Positions === undefined) {
358
+ if (Array.isArray(mesh.Min)) {
359
+ conv.domain.min.x = mesh.Min[0].valueOf();
360
+ conv.domain.min.y = mesh.Min[1].valueOf();
361
+ conv.domain.min.z = mesh.Min[2].valueOf();
362
+ }
363
+ if (Array.isArray(mesh.Max)) {
364
+ conv.domain.max.x = mesh.Max[0].valueOf();
365
+ conv.domain.max.y = mesh.Max[1].valueOf();
366
+ conv.domain.max.z = mesh.Max[2].valueOf();
367
+ }
368
+ if (mesh.HullList instanceof buffer_1.Buffer) {
369
+ if (!(mesh.Positions instanceof buffer_1.Buffer)) {
123
370
  throw new Error('Positions must be supplied if hull list is present');
124
371
  }
125
- conv.positions = this.decodeByteDomain3(mesh.Positions.toArray(), conv.domain.min, conv.domain.max);
126
- conv.hullList = mesh.HullList.toArray();
127
- if (conv.hullList === undefined) {
128
- throw new Error('HullList undefined');
372
+ conv.positions = this.decodeByteDomain3(mesh.Positions, conv.domain.min, conv.domain.max);
373
+ conv.hullList = Array.from(mesh.HullList);
374
+ let totalPoints = 0;
375
+ for (const hull of conv.hullList) {
376
+ totalPoints += hull;
129
377
  }
130
- else {
131
- let totalPoints = 0;
132
- for (const hull of conv.hullList) {
133
- totalPoints += hull;
134
- }
135
- if (conv.positions.length !== totalPoints) {
136
- throw new Error('Hull list expected number of points does not match number of positions: ' + totalPoints + ' vs ' + conv.positions.length);
137
- }
378
+ if (conv.positions.length !== totalPoints) {
379
+ throw new Error('Hull list expected number of points does not match number of positions: ' + totalPoints + ' vs ' + conv.positions.length);
138
380
  }
139
381
  }
140
- if (mesh.BoundingVerts === undefined) {
382
+ if (!(mesh.BoundingVerts instanceof buffer_1.Buffer)) {
141
383
  throw new Error('BoundingVerts is required');
142
384
  }
143
- conv.boundingVerts = this.decodeByteDomain3(mesh.BoundingVerts.toArray(), conv.domain.min, conv.domain.max);
385
+ conv.boundingVerts = this.decodeByteDomain3(mesh.BoundingVerts, conv.domain.min, conv.domain.max);
144
386
  return conv;
145
387
  }
146
388
  static parseLODLevel(mesh) {
@@ -152,64 +394,100 @@ class LLMesh {
152
394
  max: new Vector3_1.Vector3([0.5, 0.5, 0.5])
153
395
  }
154
396
  };
155
- if (submesh.NoGeometry) {
397
+ if (submesh.NoGeometry !== undefined) {
156
398
  decoded.noGeometry = true;
157
399
  list.push(decoded);
158
400
  }
159
401
  else {
160
402
  decoded.position = [];
161
- if (!submesh.Position) {
403
+ if (!(submesh.Position instanceof buffer_1.Buffer)) {
162
404
  throw new Error('Submesh does not contain position data');
163
405
  }
164
406
  if (decoded.positionDomain !== undefined) {
165
- if (submesh.PositionDomain) {
166
- if (submesh.PositionDomain.Max !== undefined) {
407
+ if (submesh.PositionDomain instanceof LLSDMap_1.LLSDMap) {
408
+ if (Array.isArray(submesh.PositionDomain.Max)) {
167
409
  const dom = submesh.PositionDomain.Max;
168
- decoded.positionDomain.max.x = dom[0];
169
- decoded.positionDomain.max.y = dom[1];
170
- decoded.positionDomain.max.z = dom[2];
410
+ if (dom[0] instanceof LLSDReal_1.LLSDReal) {
411
+ decoded.positionDomain.max.x = dom[0].valueOf();
412
+ }
413
+ if (dom[1] instanceof LLSDReal_1.LLSDReal) {
414
+ decoded.positionDomain.max.y = dom[1].valueOf();
415
+ }
416
+ if (dom[2] instanceof LLSDReal_1.LLSDReal) {
417
+ decoded.positionDomain.max.z = dom[2].valueOf();
418
+ }
171
419
  }
172
- if (submesh.PositionDomain.Min !== undefined) {
420
+ if (Array.isArray(submesh.PositionDomain.Min)) {
173
421
  const dom = submesh.PositionDomain.Min;
174
- decoded.positionDomain.min.x = dom[0];
175
- decoded.positionDomain.min.y = dom[1];
176
- decoded.positionDomain.min.z = dom[2];
422
+ if (dom[0] instanceof LLSDReal_1.LLSDReal) {
423
+ decoded.positionDomain.min.x = dom[0].valueOf();
424
+ }
425
+ if (dom[1] instanceof LLSDReal_1.LLSDReal) {
426
+ decoded.positionDomain.min.y = dom[1].valueOf();
427
+ }
428
+ if (dom[2] instanceof LLSDReal_1.LLSDReal) {
429
+ decoded.positionDomain.min.z = dom[2].valueOf();
430
+ }
177
431
  }
178
432
  }
179
- decoded.position = this.decodeByteDomain3(submesh.Position.toArray(), decoded.positionDomain.min, decoded.positionDomain.max);
433
+ decoded.position = this.decodeByteDomain3(submesh.Position, decoded.positionDomain.min, decoded.positionDomain.max);
180
434
  }
181
- if (submesh.Normal) {
182
- decoded.normal = this.decodeByteDomain3(submesh.Normal.toArray(), new Vector3_1.Vector3([-1.0, -1.0, -1.0]), new Vector3_1.Vector3([1.0, 1.0, 1.0]));
435
+ if (submesh.Normal instanceof buffer_1.Buffer) {
436
+ decoded.normal = this.decodeByteDomain3(submesh.Normal, new Vector3_1.Vector3([-1.0, -1.0, -1.0]), new Vector3_1.Vector3([1.0, 1.0, 1.0]));
183
437
  if (decoded.normal.length !== decoded.position.length) {
184
438
  throw new Error('Normal length does not match vertex position length');
185
439
  }
186
440
  }
187
- if (submesh.TexCoord0) {
441
+ if (submesh.TexCoord0 !== undefined) {
188
442
  decoded.texCoord0Domain = {
189
443
  min: new Vector2_1.Vector2([-0.5, -0.5]),
190
444
  max: new Vector2_1.Vector2([0.5, 0.5])
191
445
  };
192
- if (submesh.TexCoord0Domain) {
446
+ if (submesh.TexCoord0Domain instanceof LLSDMap_1.LLSDMap) {
193
447
  if (submesh.TexCoord0Domain.Max !== undefined) {
194
448
  const dom = submesh.TexCoord0Domain.Max;
195
- decoded.texCoord0Domain.max.x = dom[0];
196
- decoded.texCoord0Domain.max.y = dom[1];
449
+ if (Array.isArray(dom)) {
450
+ if (dom[0] instanceof LLSDReal_1.LLSDReal) {
451
+ decoded.texCoord0Domain.max.x = dom[0].valueOf();
452
+ }
453
+ else {
454
+ throw new Error('Unexpected type');
455
+ }
456
+ if (dom[1] instanceof LLSDReal_1.LLSDReal) {
457
+ decoded.texCoord0Domain.max.y = dom[1].valueOf();
458
+ }
459
+ else {
460
+ throw new Error('Unexpected type');
461
+ }
462
+ }
197
463
  }
198
- if (submesh.TexCoord0Domain.Min !== undefined) {
464
+ if (Array.isArray(submesh.TexCoord0Domain.Min)) {
199
465
  const dom = submesh.TexCoord0Domain.Min;
200
- decoded.texCoord0Domain.min.x = dom[0];
201
- decoded.texCoord0Domain.min.y = dom[1];
466
+ if (dom[0] instanceof LLSDReal_1.LLSDReal) {
467
+ decoded.texCoord0Domain.min.x = dom[0].valueOf();
468
+ }
469
+ else {
470
+ throw new Error('Unexpected type');
471
+ }
472
+ if (dom[1] instanceof LLSDReal_1.LLSDReal) {
473
+ decoded.texCoord0Domain.min.y = dom[1].valueOf();
474
+ }
475
+ else {
476
+ throw new Error('Unexpected type');
477
+ }
202
478
  }
203
479
  }
204
480
  else {
205
481
  throw new Error('TexCoord0Domain is required if Texcoord0 is present');
206
482
  }
207
- decoded.texCoord0 = this.decodeByteDomain2(submesh.TexCoord0.toArray(), decoded.texCoord0Domain.min, decoded.texCoord0Domain.max);
483
+ if (submesh.TexCoord0 instanceof buffer_1.Buffer) {
484
+ decoded.texCoord0 = this.decodeByteDomain2(submesh.TexCoord0, decoded.texCoord0Domain.min, decoded.texCoord0Domain.max);
485
+ }
208
486
  }
209
- if (!submesh.TriangleList) {
487
+ if (!(submesh.TriangleList instanceof buffer_1.Buffer)) {
210
488
  throw new Error('TriangleList is required');
211
489
  }
212
- const indexBuf = Buffer.from(submesh.TriangleList.toArray());
490
+ const indexBuf = buffer_1.Buffer.from(submesh.TriangleList);
213
491
  decoded.triangleList = [];
214
492
  for (let pos = 0; pos < indexBuf.length; pos = pos + 2) {
215
493
  const vertIndex = indexBuf.readUInt16LE(pos);
@@ -218,8 +496,8 @@ class LLMesh {
218
496
  }
219
497
  decoded.triangleList.push(vertIndex);
220
498
  }
221
- if (submesh.Weights) {
222
- const skinBuf = Buffer.from(submesh.Weights.toArray());
499
+ if (submesh.Weights instanceof buffer_1.Buffer) {
500
+ const skinBuf = submesh.Weights;
223
501
  decoded.weights = [];
224
502
  let pos = 0;
225
503
  while (pos < skinBuf.length) {
@@ -244,102 +522,70 @@ class LLMesh {
244
522
  }
245
523
  return list;
246
524
  }
247
- static decodeByteDomain3(posArray, minDomain, maxDomain) {
525
+ static decodeByteDomain3(buf, minDomain, maxDomain) {
248
526
  const result = [];
249
- const buf = Buffer.from(posArray);
250
- for (let idx = 0; idx < posArray.length; idx = idx + 6) {
251
- const posX = this.normalizeDomain(buf.readUInt16LE(idx), minDomain.x, maxDomain.x);
252
- const posY = this.normalizeDomain(buf.readUInt16LE(idx + 2), minDomain.y, maxDomain.y);
253
- const posZ = this.normalizeDomain(buf.readUInt16LE(idx + 4), minDomain.z, maxDomain.z);
527
+ for (let idx = 0; idx < buf.length; idx = idx + 6) {
528
+ const posX = Utils_1.Utils.UInt16ToFloat(buf.readUInt16LE(idx), minDomain.x, maxDomain.x, false);
529
+ const posY = Utils_1.Utils.UInt16ToFloat(buf.readUInt16LE(idx + 2), minDomain.y, maxDomain.y, false);
530
+ const posZ = Utils_1.Utils.UInt16ToFloat(buf.readUInt16LE(idx + 4), minDomain.z, maxDomain.z, false);
254
531
  result.push(new Vector3_1.Vector3([posX, posY, posZ]));
255
532
  }
256
533
  return result;
257
534
  }
258
- static decodeByteDomain2(posArray, minDomain, maxDomain) {
535
+ static decodeByteDomain2(buf, minDomain, maxDomain) {
259
536
  const result = [];
260
- const buf = Buffer.from(posArray);
261
- for (let idx = 0; idx < posArray.length; idx = idx + 4) {
262
- const posX = this.normalizeDomain(buf.readUInt16LE(idx), minDomain.x, maxDomain.x);
263
- const posY = this.normalizeDomain(buf.readUInt16LE(idx + 2), minDomain.y, maxDomain.y);
537
+ for (let idx = 0; idx < buf.length; idx = idx + 4) {
538
+ const posX = Utils_1.Utils.UInt16ToFloat(buf.readUInt16LE(idx), minDomain.x, maxDomain.x, false);
539
+ const posY = Utils_1.Utils.UInt16ToFloat(buf.readUInt16LE(idx + 2), minDomain.y, maxDomain.y, false);
264
540
  result.push(new Vector2_1.Vector2([posX, posY]));
265
541
  }
266
542
  return result;
267
543
  }
268
- static normalizeDomain(value, min, max) {
269
- return ((value / 65535) * (max - min)) + min;
270
- }
271
- async toAsset() {
272
- const llsd = {
273
- 'creator': new LLSD.UUID(this.creatorID.toString()),
274
- 'version': this.version,
275
- 'date': null
276
- };
277
- let offset = 0;
278
- const bufs = [];
279
- for (const lod of Object.keys(this.lodLevels)) {
280
- const lodBlob = await this.encodeLODLevel(lod, this.lodLevels[lod]);
281
- llsd[lod] = {
282
- 'offset': offset,
283
- 'size': lodBlob.length
284
- };
285
- offset += lodBlob.length;
286
- bufs.push(lodBlob);
544
+ static toLLSDReal(num) {
545
+ const real = [];
546
+ for (const n of num) {
547
+ real.push(new LLSDReal_1.LLSDReal(n));
287
548
  }
288
- if (this.physicsConvex) {
289
- const physBlob = await this.encodePhysicsConvex(this.physicsConvex);
290
- llsd.physics_convex = {
291
- 'offset': offset,
292
- 'size': physBlob.length
293
- };
294
- offset += physBlob.length;
295
- bufs.push(physBlob);
296
- }
297
- if (this.skin) {
298
- const skinBlob = await this.encodeSkin(this.skin);
299
- llsd.skin = {
300
- 'offset': offset,
301
- 'size': skinBlob.length
302
- };
303
- offset += skinBlob.length;
304
- bufs.push(skinBlob);
305
- }
306
- bufs.unshift(Buffer.from(LLSD.LLSD.formatBinary(llsd).toArray()));
307
- return Buffer.concat(bufs);
549
+ return real;
308
550
  }
309
551
  encodeSubMesh(mesh) {
310
- const data = {};
552
+ const data = new LLSDMap_1.LLSDMap();
311
553
  if (mesh.noGeometry === true) {
312
- data.noGeometry = true;
554
+ data.add('NoGeometry', true);
313
555
  return data;
314
556
  }
315
557
  if (!mesh.position) {
316
558
  throw new Error('No position data when encoding submesh');
317
559
  }
318
560
  if (mesh.positionDomain !== undefined) {
319
- data.position = new LLSD.Binary(Array.from(this.expandFromDomain(mesh.position, mesh.positionDomain.min, mesh.positionDomain.max)));
320
- data.positionDomain = {
321
- min: new Vector3_1.Vector3(LLMesh.fixReal(mesh.positionDomain.min.toArray())),
322
- max: new Vector3_1.Vector3(LLMesh.fixReal(mesh.positionDomain.max.toArray()))
323
- };
561
+ data.add('Position', this.expandFromDomain(mesh.position, mesh.positionDomain.min, mesh.positionDomain.max));
562
+ const min = new Vector3_1.Vector3(LLMesh.fixReal(mesh.positionDomain.min.toArray()));
563
+ const max = new Vector3_1.Vector3(LLMesh.fixReal(mesh.positionDomain.max.toArray()));
564
+ data.add('PositionDomain', new LLSDMap_1.LLSDMap([
565
+ ['Min', [new LLSDReal_1.LLSDReal(min.x), new LLSDReal_1.LLSDReal(min.y), new LLSDReal_1.LLSDReal(min.z)]],
566
+ ['Max', [new LLSDReal_1.LLSDReal(max.x), new LLSDReal_1.LLSDReal(max.y), new LLSDReal_1.LLSDReal(max.z)]]
567
+ ]));
324
568
  }
325
569
  if (mesh.texCoord0 && mesh.texCoord0Domain !== undefined) {
326
- data.texCoord0 = new LLSD.Binary(Array.from(this.expandFromDomain(mesh.texCoord0, mesh.texCoord0Domain.min, mesh.texCoord0Domain.max)));
327
- data.texCoord0Domain = {
328
- min: new Vector2_1.Vector2(LLMesh.fixReal(mesh.texCoord0Domain.min.toArray())),
329
- max: new Vector2_1.Vector2(LLMesh.fixReal(mesh.texCoord0Domain.max.toArray()))
330
- };
570
+ data.add('TexCoord0', this.expandFromDomain(mesh.texCoord0, mesh.texCoord0Domain.min, mesh.texCoord0Domain.max));
571
+ const domainMin = new Vector2_1.Vector2(LLMesh.fixReal(mesh.texCoord0Domain.min.toArray()));
572
+ const domainMax = new Vector2_1.Vector2(LLMesh.fixReal(mesh.texCoord0Domain.max.toArray()));
573
+ data.add('TexCoord0Domain', new LLSDMap_1.LLSDMap([
574
+ ['Min', [new LLSDReal_1.LLSDReal(domainMin.x), new LLSDReal_1.LLSDReal(domainMin.y)]],
575
+ ['Max', [new LLSDReal_1.LLSDReal(domainMax.x), new LLSDReal_1.LLSDReal(domainMax.y)]]
576
+ ]));
331
577
  }
332
578
  if (mesh.normal) {
333
- data.normal = new LLSD.Binary(Array.from(this.expandFromDomain(mesh.normal, new Vector3_1.Vector3([-1.0, -1.0, -1.0]), new Vector3_1.Vector3([1.0, 1.0, 1.0]))));
579
+ data.add('Normal', this.expandFromDomain(mesh.normal, new Vector3_1.Vector3([-1.0, -1.0, -1.0]), new Vector3_1.Vector3([1.0, 1.0, 1.0])));
334
580
  }
335
581
  if (mesh.triangleList) {
336
- const triangles = Buffer.allocUnsafe(mesh.triangleList.length * 2);
582
+ const triangles = buffer_1.Buffer.allocUnsafe(mesh.triangleList.length * 2);
337
583
  let pos = 0;
338
584
  for (const triangle of mesh.triangleList) {
339
585
  triangles.writeUInt16LE(triangle, pos);
340
586
  pos = pos + 2;
341
587
  }
342
- data.triangleList = new LLSD.Binary(Array.from(triangles));
588
+ data.add('TriangleList', triangles);
343
589
  }
344
590
  else {
345
591
  throw new Error('Triangle list is required');
@@ -353,7 +599,7 @@ class LLMesh {
353
599
  spaceNeeded = spaceNeeded + 1;
354
600
  }
355
601
  }
356
- const weightBuff = Buffer.allocUnsafe(spaceNeeded);
602
+ const weightBuff = buffer_1.Buffer.allocUnsafe(spaceNeeded);
357
603
  let pos = 0;
358
604
  for (const weight of mesh.weights) {
359
605
  const keys = Object.keys(weight);
@@ -366,7 +612,7 @@ class LLMesh {
366
612
  weightBuff.writeUInt8(0xFF, pos++);
367
613
  }
368
614
  }
369
- data.weights = new LLSD.Binary(Array.from(weightBuff));
615
+ data.add('Weights', weightBuff);
370
616
  }
371
617
  return data;
372
618
  }
@@ -375,7 +621,7 @@ class LLMesh {
375
621
  if (data.length > 0 && data[0] instanceof Vector3_1.Vector3) {
376
622
  length = 6;
377
623
  }
378
- const buf = Buffer.allocUnsafe(data.length * length);
624
+ const buf = buffer_1.Buffer.allocUnsafe(data.length * length);
379
625
  let pos = 0;
380
626
  for (const c of data) {
381
627
  const coord = c;
@@ -401,14 +647,32 @@ class LLMesh {
401
647
  for (const sub of submeshes) {
402
648
  smList.push(this.encodeSubMesh(sub));
403
649
  }
404
- const mesh = LLSD.LLSD.formatBinary(smList);
405
- return Utils_1.Utils.deflate(Buffer.from(mesh.toArray()));
650
+ return Utils_1.Utils.deflate(LLSD_1.LLSD.toBinary(smList));
651
+ }
652
+ async encodePhysicsHavok() {
653
+ if (!this.physicsHavok) {
654
+ return buffer_1.Buffer.alloc(0);
655
+ }
656
+ return Utils_1.Utils.deflate(LLSD_1.LLSD.toBinary(new LLSDMap_1.LLSDMap([
657
+ ['WeldingData', this.physicsHavok.weldingData],
658
+ ['HullMassProps', new LLSDMap_1.LLSDMap([
659
+ ['CoM', LLMesh.toLLSDReal(this.physicsHavok.hullMassProps.CoM)],
660
+ ['inertia', LLMesh.toLLSDReal(this.physicsHavok.hullMassProps.inertia)],
661
+ ['mass', new LLSDReal_1.LLSDReal(this.physicsHavok.hullMassProps.mass)],
662
+ ['volume', new LLSDReal_1.LLSDReal(this.physicsHavok.hullMassProps.volume)]
663
+ ])],
664
+ ['MeshDecompMassProps', new LLSDMap_1.LLSDMap([
665
+ ['CoM', LLMesh.toLLSDReal(this.physicsHavok.meshDecompMassProps.CoM)],
666
+ ['inertia', LLMesh.toLLSDReal(this.physicsHavok.meshDecompMassProps.inertia)],
667
+ ['mass', new LLSDReal_1.LLSDReal(this.physicsHavok.meshDecompMassProps.mass)],
668
+ ['volume', new LLSDReal_1.LLSDReal(this.physicsHavok.meshDecompMassProps.volume)]
669
+ ])]
670
+ ])));
406
671
  }
407
672
  async encodePhysicsConvex(conv) {
408
- const llsd = {
409
- Min: LLMesh.fixReal(conv.domain.min.toArray()),
410
- Max: LLMesh.fixReal(conv.domain.max.toArray())
411
- };
673
+ const llsd = new LLSDMap_1.LLSDMap();
674
+ llsd.add('Min', LLMesh.fixRealLLSD(conv.domain.min.toArray()));
675
+ llsd.add('Max', LLMesh.fixRealLLSD(conv.domain.max.toArray()));
412
676
  const sizeX = conv.domain.max.x - conv.domain.min.x;
413
677
  const sizeY = conv.domain.max.y - conv.domain.min.y;
414
678
  const sizeZ = conv.domain.max.z - conv.domain.min.z;
@@ -416,8 +680,8 @@ class LLMesh {
416
680
  if (!conv.positions) {
417
681
  throw new Error('Positions must be present if hullList is set.');
418
682
  }
419
- llsd.HullList = new LLSD.Binary(conv.hullList);
420
- const buf = Buffer.allocUnsafe(conv.positions.length * 6);
683
+ llsd.add('HullList', buffer_1.Buffer.from(conv.hullList));
684
+ const buf = buffer_1.Buffer.allocUnsafe(conv.positions.length * 6);
421
685
  let pos = 0;
422
686
  for (const vec of conv.positions) {
423
687
  buf.writeUInt16LE(Math.round(((vec.x - conv.domain.min.x) / sizeX) * 65535), pos);
@@ -427,43 +691,43 @@ class LLMesh {
427
691
  buf.writeUInt16LE(Math.round(((vec.z - conv.domain.min.z) / sizeZ) * 65535), pos);
428
692
  pos = pos + 2;
429
693
  }
430
- llsd.Positions = new LLSD.Binary(Array.from(buf));
694
+ llsd.add('Positions', buf);
431
695
  }
432
696
  {
433
- const buf = Buffer.allocUnsafe(conv.boundingVerts.length * 6);
697
+ const buf = buffer_1.Buffer.allocUnsafe(conv.boundingVerts.length * 6);
434
698
  let pos = 0;
435
699
  for (const vec of conv.boundingVerts) {
436
- buf.writeUInt16LE(Math.round(((vec.x - conv.domain.min.x) / sizeX)) * 65535, pos);
700
+ buf.writeUInt16LE(Math.round(((vec.x - conv.domain.min.x) / sizeX) * 65535), pos);
437
701
  pos = pos + 2;
438
- buf.writeUInt16LE(Math.round(((vec.y - conv.domain.min.y) / sizeY)) * 65535, pos);
702
+ buf.writeUInt16LE(Math.round(((vec.y - conv.domain.min.y) / sizeY) * 65535), pos);
439
703
  pos = pos + 2;
440
- buf.writeUInt16LE(Math.round(((vec.z - conv.domain.min.z) / sizeZ)) * 65535, pos);
704
+ buf.writeUInt16LE(Math.round(((vec.z - conv.domain.min.z) / sizeZ) * 65535), pos);
441
705
  pos = pos + 2;
442
706
  }
443
- llsd.BoundingVerts = new LLSD.Binary(Array.from(buf));
707
+ llsd.add('BoundingVerts', buf);
444
708
  }
445
- const mesh = LLSD.LLSD.formatBinary(llsd);
446
- return Utils_1.Utils.deflate(Buffer.from(mesh.toArray()));
709
+ return Utils_1.Utils.deflate(LLSD_1.LLSD.toBinary(llsd));
447
710
  }
448
711
  async encodeSkin(skin) {
449
- const llsd = {};
450
- llsd.joint_names = skin.jointNames;
451
- llsd.bind_shape_matrix = skin.bindShapeMatrix.toArray();
452
- llsd.inverse_bind_matrix = [];
712
+ const llsd = new LLSDMap_1.LLSDMap();
713
+ llsd.add('joint_names', skin.jointNames);
714
+ llsd.add('bind_shape_matrix', LLMesh.toLLSDReal(skin.bindShapeMatrix.toArray()));
715
+ const inverseBindMatrix = [];
453
716
  for (const matrix of skin.inverseBindMatrix) {
454
- llsd.inverse_bind_matrix.push(matrix.toArray());
717
+ inverseBindMatrix.push(LLMesh.toLLSDReal(matrix.toArray()));
455
718
  }
719
+ llsd.add('inverse_bind_matrix', inverseBindMatrix);
456
720
  if (skin.altInverseBindMatrix) {
457
- llsd.alt_inverse_bind_matrix = [];
721
+ const altInverseBindMatrix = [];
458
722
  for (const matrix of skin.altInverseBindMatrix) {
459
- llsd.alt_inverse_bind_matrix.push(matrix.toArray());
723
+ altInverseBindMatrix.push(LLMesh.toLLSDReal(matrix.toArray()));
460
724
  }
725
+ llsd.add('alt_inverse_bind_matrix', altInverseBindMatrix);
461
726
  }
462
727
  if (skin.pelvisOffset) {
463
- llsd.pelvis_offset = skin.pelvisOffset.toArray();
728
+ llsd.add('pelvis_offset', LLMesh.toLLSDReal(skin.pelvisOffset.toArray()));
464
729
  }
465
- const mesh = LLSD.LLSD.formatBinary(llsd);
466
- return Utils_1.Utils.deflate(Buffer.from(mesh.toArray()));
730
+ return Utils_1.Utils.deflate(LLSD_1.LLSD.toBinary(llsd));
467
731
  }
468
732
  }
469
733
  exports.LLMesh = LLMesh;