@forgeax/engine-geometry 0.1.33 → 0.1.35

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.
@@ -1 +1 @@
1
- {"version":3,"file":"vertex-attribute-layout.d.ts","sourceRoot":"","sources":["../src/vertex-attribute-layout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vertex-attribute-layout.d.ts","sourceRoot":"","sources":["../src/vertex-attribute-layout.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-geometry",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,10 +22,10 @@
22
22
  "LICENSE"
23
23
  ],
24
24
  "dependencies": {
25
- "@forgeax/engine-ecs": "0.1.33",
26
- "@forgeax/engine-math": "0.1.33",
27
- "@forgeax/engine-pack": "0.1.33",
28
- "@forgeax/engine-types": "0.1.33"
25
+ "@forgeax/engine-ecs": "0.1.35",
26
+ "@forgeax/engine-math": "0.1.35",
27
+ "@forgeax/engine-pack": "0.1.35",
28
+ "@forgeax/engine-types": "0.1.35"
29
29
  },
30
30
  "forgeax": {
31
31
  "metrics": {
@@ -33,6 +33,22 @@ function makeCompleteAttributeMap(): VertexAttributeMap {
33
33
  }
34
34
 
35
35
  describe('vertex attribute layout owner', () => {
36
+ it('shares immutable layouts by attribute presence while observing mutable map edits', () => {
37
+ const map = { position: makeBuffer(), normal: makeBuffer() };
38
+ const first = deriveVertexLayoutProjection(map);
39
+ const sibling = deriveVertexLayoutProjection({ normal: makeBuffer(), position: makeBuffer() });
40
+ expect(sibling).toBe(first);
41
+ expect(deriveVertexLayoutProjectionFromMask(first.mask).unwrap()).toBe(first);
42
+ expect(Object.isFrozen(first.attributes[0])).toBe(true);
43
+ const edited: Record<string, Float32Array> = map;
44
+ edited.color = makeBuffer();
45
+ const colored = deriveVertexLayoutProjection(edited);
46
+ expect(colored).not.toBe(first);
47
+ expect(colored.arrayStride).toBe(first.arrayStride + 16);
48
+ delete edited.color;
49
+ expect(deriveVertexLayoutProjection(edited)).toBe(first);
50
+ });
51
+
36
52
  it('publishes the ordinary and skinned maps from the same geometry owner', () => {
37
53
  expect(Object.keys(DEFAULT_VERTEX_ATTRIBUTE_MAP)).toEqual([
38
54
  'position',
@@ -315,24 +315,31 @@ function fnv1a(input: string): string {
315
315
  return `vlp-v1-${(hash >>> 0).toString(16).padStart(8, '0')}`;
316
316
  }
317
317
 
318
+ // The finite canonical mask is the complete layout identity. Do not key this
319
+ // cache by a mesh/map object: authoring maps may change in place.
320
+ const layoutsByMask = new Map<number, VertexLayoutProjection>();
321
+
318
322
  /** Derive the one canonical immutable layout projection for a vertex map. */
319
323
  export function deriveVertexLayoutProjection(map: VertexAttributeMap): VertexLayoutProjection {
324
+ let mask = 0;
325
+ for (let index = 0; index < CANONICAL_KEYS.length; index += 1) {
326
+ const key = CANONICAL_KEYS[index];
327
+ if (key !== undefined && map[key] !== undefined) mask |= 1 << index;
328
+ }
329
+ return layoutFromMask(mask);
330
+ }
331
+
332
+ function layoutFromMask(mask: number): VertexLayoutProjection {
333
+ const cached = layoutsByMask.get(mask);
334
+ if (cached !== undefined) return cached;
320
335
  const attributes: VertexLayoutProjectionAttribute[] = [];
321
336
  let offset = 0;
322
- let mask = 0;
323
- for (const key of CANONICAL_KEYS) {
324
- const value = map[key];
325
- if (value === undefined) continue;
337
+ for (let index = 0; index < CANONICAL_KEYS.length; index += 1) {
338
+ const key = CANONICAL_KEYS[index];
339
+ if (key === undefined || (mask & (1 << index)) === 0) continue;
326
340
  const format = ATTRIBUTE_FORMAT_MAP[key];
327
341
  const byteLength = bytesForFormat(format);
328
- attributes.push({
329
- key,
330
- shaderLocation: CANONICAL_KEYS.indexOf(key),
331
- offset,
332
- format,
333
- byteLength,
334
- });
335
- mask |= 1 << CANONICAL_KEYS.indexOf(key);
342
+ attributes.push(Object.freeze({ key, shaderLocation: index, offset, format, byteLength }));
336
343
  offset += byteLength;
337
344
  }
338
345
  const digestInput = [
@@ -343,13 +350,15 @@ export function deriveVertexLayoutProjection(map: VertexAttributeMap): VertexLay
343
350
  (entry) => `${entry.key},${entry.shaderLocation},${entry.offset},${entry.format}`,
344
351
  ),
345
352
  ].join('|');
346
- return Object.freeze({
353
+ const projection: VertexLayoutProjection = Object.freeze({
347
354
  schemaVersion: 1,
348
355
  attributes: Object.freeze(attributes),
349
356
  mask,
350
357
  arrayStride: offset,
351
358
  digest: fnv1a(digestInput),
352
359
  });
360
+ layoutsByMask.set(mask, projection);
361
+ return projection;
353
362
  }
354
363
 
355
364
  export interface PackedVertexAttributes {
@@ -405,14 +414,7 @@ export function deriveVertexLayoutProjectionFromMask(
405
414
  detail: { mask, knownMask, unknownMask, reason: 'unknown-bits' },
406
415
  });
407
416
  }
408
- const map: Record<string, Float32Array | Uint16Array> = {};
409
- for (let index = 0; index < CANONICAL_KEYS.length; index += 1) {
410
- if ((mask & (1 << index)) === 0) continue;
411
- const key = CANONICAL_KEYS[index];
412
- if (key !== undefined)
413
- map[key] = key === 'skinIndex' ? new Uint16Array(0) : new Float32Array(0);
414
- }
415
- return ok(deriveVertexLayoutProjection(map as VertexAttributeMap));
417
+ return ok(layoutFromMask(unsignedMask));
416
418
  }
417
419
 
418
420
  /** Pack tightly-owned attributes into the projection's canonical interleaved bytes. */