@flighthq/texture 0.3.0-next.1032.e2b99fc → 0.3.0-next.1220.6982c21
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/dist/contract.d.ts +1 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -0
- package/dist/contract.js.map +1 -1
- package/dist/cubeTexture.d.ts +2 -2
- package/dist/cubeTexture.d.ts.map +1 -1
- package/dist/cubeTexture.js +11 -13
- package/dist/cubeTexture.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/renderTexture.d.ts.map +1 -1
- package/dist/renderTexture.js +18 -19
- package/dist/renderTexture.js.map +1 -1
- package/dist/texture.d.ts +28 -5
- package/dist/texture.d.ts.map +1 -1
- package/dist/texture.js +124 -83
- package/dist/texture.js.map +1 -1
- package/dist/videoTexture.d.ts.map +1 -1
- package/dist/videoTexture.js +18 -14
- package/dist/videoTexture.js.map +1 -1
- package/dist/voxelGrid.d.ts +3 -0
- package/dist/voxelGrid.d.ts.map +1 -0
- package/dist/voxelGrid.js +5 -0
- package/dist/voxelGrid.js.map +1 -0
- package/package.json +4 -4
- package/src/cubeTexture.test.ts +31 -31
- package/src/renderTexture.test.ts +3 -6
- package/src/texture.test.ts +107 -86
- package/src/videoTexture.test.ts +15 -13
- package/src/voxelGrid.test.ts +37 -0
package/src/texture.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createEntity } from '@flighthq/entity/contract';
|
|
1
2
|
import { createMatrix3, createVector2, inverseMatrix3 } from '@flighthq/geometry/contract';
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
3
|
+
import type { Image, RenderTarget, Texture2D } from '@flighthq/types/contract';
|
|
4
|
+
import { ImageTextureSourceKind, RenderTargetTextureSourceKind } from '@flighthq/types/contract';
|
|
4
5
|
|
|
5
6
|
import { createSampler, equalsSampler } from './sampler';
|
|
6
7
|
import {
|
|
@@ -8,17 +9,18 @@ import {
|
|
|
8
9
|
copyTexture,
|
|
9
10
|
createTexture,
|
|
10
11
|
equalsTexture,
|
|
11
|
-
|
|
12
|
+
getTextureSource,
|
|
13
|
+
getTextureSourceKind,
|
|
12
14
|
getTextureHeight,
|
|
13
15
|
getTextureInverseUvMatrix,
|
|
14
16
|
getTextureUvMatrix,
|
|
15
17
|
getTextureWidth,
|
|
16
|
-
|
|
18
|
+
hasTextureSource,
|
|
17
19
|
hasTextureUvTransform,
|
|
18
20
|
isTextureReady,
|
|
19
21
|
resetTextureUvTransform,
|
|
20
22
|
setTextureFlip,
|
|
21
|
-
|
|
23
|
+
setTextureSource,
|
|
22
24
|
setTextureUvOffset,
|
|
23
25
|
setTextureUvFromPixelRect,
|
|
24
26
|
setTextureUvRotation,
|
|
@@ -26,7 +28,16 @@ import {
|
|
|
26
28
|
transformTextureUv,
|
|
27
29
|
} from './texture';
|
|
28
30
|
|
|
29
|
-
const fakeImage = { height: 64, kind:
|
|
31
|
+
const fakeImage = { height: 64, kind: ImageTextureSourceKind, width: 32 } as Image;
|
|
32
|
+
|
|
33
|
+
function makeRenderTarget(width: number, height: number): RenderTarget {
|
|
34
|
+
return createEntity({
|
|
35
|
+
height,
|
|
36
|
+
kind: RenderTargetTextureSourceKind,
|
|
37
|
+
version: 0,
|
|
38
|
+
width,
|
|
39
|
+
}) as RenderTarget;
|
|
40
|
+
}
|
|
30
41
|
|
|
31
42
|
// Applies a column-major 3×3 uv matrix to (u, v, 1), writing the transformed coordinate into out.
|
|
32
43
|
function multiplyMatrix3Uv(out: { x: number; y: number }, matrix: { m: ArrayLike<number> }, u: number, v: number) {
|
|
@@ -39,7 +50,8 @@ describe('cloneTexture', () => {
|
|
|
39
50
|
it('shares the image but deep-clones the sampler and uv vectors', () => {
|
|
40
51
|
const source = createTexture({
|
|
41
52
|
colorSpace: 'linear',
|
|
42
|
-
|
|
53
|
+
dimension: '2d',
|
|
54
|
+
source: fakeImage,
|
|
43
55
|
uvRotation: 0.5,
|
|
44
56
|
});
|
|
45
57
|
source.uvOffset.x = 0.25;
|
|
@@ -48,8 +60,8 @@ describe('cloneTexture', () => {
|
|
|
48
60
|
const copy = cloneTexture(source);
|
|
49
61
|
|
|
50
62
|
expect(copy).not.toBe(source);
|
|
51
|
-
expect(copy.
|
|
52
|
-
expect(copy
|
|
63
|
+
expect(copy.dimension).toBe('2d');
|
|
64
|
+
expect(getTextureSource(copy)).toBe(fakeImage);
|
|
53
65
|
expect(copy.colorSpace).toStrictEqual('linear');
|
|
54
66
|
expect(copy.uvRotation).toStrictEqual(0.5);
|
|
55
67
|
expect(copy.sampler).not.toBe(source.sampler);
|
|
@@ -63,18 +75,13 @@ describe('cloneTexture', () => {
|
|
|
63
75
|
});
|
|
64
76
|
|
|
65
77
|
it('preserves a render-target descriptor while cloning sampling state', () => {
|
|
66
|
-
const target =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
kind: RenderTextureBackingKind,
|
|
70
|
-
width: 64,
|
|
71
|
-
};
|
|
72
|
-
const source = createTexture({ storage: { dimension: '2d', image: null, target } });
|
|
78
|
+
const target = makeRenderTarget(64, 32);
|
|
79
|
+
target.colorSpace = 'linear';
|
|
80
|
+
const source = createTexture({ dimension: '2d', source: target });
|
|
73
81
|
|
|
74
82
|
const copy = cloneTexture(source);
|
|
75
83
|
|
|
76
|
-
expect(copy
|
|
77
|
-
expect(copy.storage).not.toBe(source.storage);
|
|
84
|
+
expect(getTextureSource(copy)).toBe(target);
|
|
78
85
|
expect(copy.sampler).not.toBe(source.sampler);
|
|
79
86
|
});
|
|
80
87
|
});
|
|
@@ -83,30 +90,30 @@ describe('copyTexture', () => {
|
|
|
83
90
|
it('writes every field from source into a distinct out, preserving out entity identities', () => {
|
|
84
91
|
const source = createTexture({
|
|
85
92
|
colorSpace: 'linear',
|
|
86
|
-
|
|
93
|
+
dimension: '2d',
|
|
94
|
+
source: fakeImage,
|
|
87
95
|
uvRotation: 1,
|
|
88
96
|
});
|
|
89
97
|
source.uvScale.x = 4;
|
|
90
98
|
const out = createTexture();
|
|
91
99
|
const outSampler = out.sampler;
|
|
92
100
|
const outOffset = out.uvOffset;
|
|
93
|
-
const outStorage = out.storage;
|
|
94
101
|
|
|
95
102
|
copyTexture(out, source);
|
|
96
103
|
|
|
97
|
-
expect(out
|
|
104
|
+
expect(getTextureSource(out)).toBe(fakeImage);
|
|
98
105
|
expect(out.colorSpace).toStrictEqual('linear');
|
|
99
106
|
expect(out.uvRotation).toStrictEqual(1);
|
|
100
107
|
expect(out.uvScale.x).toStrictEqual(4);
|
|
101
108
|
expect(out.sampler).toBe(outSampler);
|
|
102
|
-
expect(out.storage).toBe(outStorage);
|
|
103
109
|
expect(out.uvOffset).toBe(outOffset);
|
|
104
110
|
});
|
|
105
111
|
|
|
106
112
|
it('is safe when out aliases source', () => {
|
|
107
113
|
const source = createTexture({
|
|
108
114
|
colorSpace: 'linear',
|
|
109
|
-
|
|
115
|
+
dimension: '2d',
|
|
116
|
+
source: fakeImage,
|
|
110
117
|
uvRotation: 2,
|
|
111
118
|
});
|
|
112
119
|
source.uvScale.x = 7;
|
|
@@ -114,18 +121,30 @@ describe('copyTexture', () => {
|
|
|
114
121
|
copyTexture(source, source);
|
|
115
122
|
|
|
116
123
|
expect(source.colorSpace).toStrictEqual('linear');
|
|
117
|
-
expect(source
|
|
124
|
+
expect(getTextureSource(source)).toBe(fakeImage);
|
|
118
125
|
expect(source.uvRotation).toStrictEqual(2);
|
|
119
126
|
expect(source.uvScale.x).toStrictEqual(7);
|
|
120
127
|
});
|
|
128
|
+
|
|
129
|
+
it('refuses to change the creation-time dimension', () => {
|
|
130
|
+
const out = createTexture();
|
|
131
|
+
const cube = createTexture({ dimension: 'cube' });
|
|
132
|
+
|
|
133
|
+
expect(() => copyTexture(out, cube)).toThrow('copyTexture requires matching dimensions');
|
|
134
|
+
expect(out.dimension).toBe('2d');
|
|
135
|
+
expect(out.source).toBeNull();
|
|
136
|
+
});
|
|
121
137
|
});
|
|
122
138
|
|
|
123
139
|
describe('createTexture', () => {
|
|
124
|
-
it('
|
|
140
|
+
it('creates a flat Texture2D with the default unbound, srgb, identity-transform state', () => {
|
|
125
141
|
const texture = createTexture();
|
|
126
142
|
|
|
127
|
-
|
|
128
|
-
expect(texture.
|
|
143
|
+
expectTypeOf(texture).toEqualTypeOf<Texture2D>();
|
|
144
|
+
expect(texture).not.toHaveProperty('storage');
|
|
145
|
+
expect(texture.dimension).toStrictEqual('2d');
|
|
146
|
+
expect(texture.source).toBeNull();
|
|
147
|
+
expect(getTextureSource(texture)).toBeNull();
|
|
129
148
|
expect(texture.colorSpace).toStrictEqual('srgb');
|
|
130
149
|
expect(texture.version).toStrictEqual(0);
|
|
131
150
|
expect(texture.uvRotation).toStrictEqual(0);
|
|
@@ -147,17 +166,17 @@ describe('createTexture', () => {
|
|
|
147
166
|
|
|
148
167
|
describe('equalsTexture', () => {
|
|
149
168
|
it('is true for textures with identical state and same image reference', () => {
|
|
150
|
-
const a = createTexture({ colorSpace: 'linear',
|
|
151
|
-
const b = createTexture({ colorSpace: 'linear',
|
|
169
|
+
const a = createTexture({ colorSpace: 'linear', dimension: '2d', source: fakeImage });
|
|
170
|
+
const b = createTexture({ colorSpace: 'linear', dimension: '2d', source: fakeImage });
|
|
152
171
|
|
|
153
172
|
expect(equalsTexture(a, b)).toBe(true);
|
|
154
173
|
expect(equalsTexture(a, a)).toBe(true);
|
|
155
174
|
});
|
|
156
175
|
|
|
157
176
|
it('is false when the image reference differs', () => {
|
|
158
|
-
const other = { width: 4, height: 4 } as
|
|
159
|
-
const a = createTexture({
|
|
160
|
-
const b = createTexture({
|
|
177
|
+
const other = { width: 4, height: 4 } as Image;
|
|
178
|
+
const a = createTexture({ dimension: '2d', source: fakeImage });
|
|
179
|
+
const b = createTexture({ dimension: '2d', source: other });
|
|
161
180
|
|
|
162
181
|
expect(equalsTexture(a, b)).toBe(false);
|
|
163
182
|
});
|
|
@@ -208,29 +227,9 @@ describe('equalsTexture', () => {
|
|
|
208
227
|
});
|
|
209
228
|
});
|
|
210
229
|
|
|
211
|
-
describe('getTextureBackingKind', () => {
|
|
212
|
-
it('reads the key from the active image or target backing', () => {
|
|
213
|
-
expect(getTextureBackingKind(createTexture())).toBeNull();
|
|
214
|
-
expect(getTextureBackingKind(createTexture({ storage: { dimension: '2d', image: fakeImage } }))).toBe(
|
|
215
|
-
ImageTextureBackingKind,
|
|
216
|
-
);
|
|
217
|
-
expect(
|
|
218
|
-
getTextureBackingKind(
|
|
219
|
-
createTexture({
|
|
220
|
-
storage: {
|
|
221
|
-
dimension: '2d',
|
|
222
|
-
image: null,
|
|
223
|
-
target: { height: 8, kind: RenderTextureBackingKind, width: 8 },
|
|
224
|
-
},
|
|
225
|
-
}),
|
|
226
|
-
),
|
|
227
|
-
).toBe(RenderTextureBackingKind);
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
|
|
231
230
|
describe('getTextureHeight', () => {
|
|
232
231
|
it('returns the image height when an image is bound', () => {
|
|
233
|
-
const texture = createTexture({
|
|
232
|
+
const texture = createTexture({ dimension: '2d', source: fakeImage });
|
|
234
233
|
|
|
235
234
|
expect(getTextureHeight(texture)).toStrictEqual(64);
|
|
236
235
|
});
|
|
@@ -241,13 +240,10 @@ describe('getTextureHeight', () => {
|
|
|
241
240
|
expect(getTextureHeight(texture)).toStrictEqual(-1);
|
|
242
241
|
});
|
|
243
242
|
|
|
244
|
-
it('returns the render
|
|
243
|
+
it('returns the render-target source height', () => {
|
|
245
244
|
const texture = createTexture({
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
image: null,
|
|
249
|
-
target: { height: 48, kind: RenderTextureBackingKind, width: 96 },
|
|
250
|
-
},
|
|
245
|
+
dimension: '2d',
|
|
246
|
+
source: makeRenderTarget(96, 48),
|
|
251
247
|
});
|
|
252
248
|
|
|
253
249
|
expect(getTextureHeight(texture)).toStrictEqual(48);
|
|
@@ -289,6 +285,36 @@ describe('getTextureInverseUvMatrix', () => {
|
|
|
289
285
|
});
|
|
290
286
|
});
|
|
291
287
|
|
|
288
|
+
describe('getTextureSource', () => {
|
|
289
|
+
it('returns the direct source and the first bound source in a layered texture', () => {
|
|
290
|
+
const direct = createTexture({ dimension: '2d', source: fakeImage });
|
|
291
|
+
const layered = createTexture({ dimension: '2d-array', sources: [null, fakeImage] });
|
|
292
|
+
|
|
293
|
+
expect(getTextureSource(direct)).toBe(fakeImage);
|
|
294
|
+
expect(getTextureSource(layered)).toBe(fakeImage);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('returns null when every source slot is unbound', () => {
|
|
298
|
+
expect(getTextureSource(createTexture())).toBeNull();
|
|
299
|
+
expect(getTextureSource(createTexture({ dimension: '2d-array', sources: [null] }))).toBeNull();
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
describe('getTextureSourceKind', () => {
|
|
304
|
+
it('reads the key from the active source', () => {
|
|
305
|
+
expect(getTextureSourceKind(createTexture())).toBeNull();
|
|
306
|
+
expect(getTextureSourceKind(createTexture({ dimension: '2d', source: fakeImage }))).toBe(ImageTextureSourceKind);
|
|
307
|
+
expect(
|
|
308
|
+
getTextureSourceKind(
|
|
309
|
+
createTexture({
|
|
310
|
+
dimension: '2d',
|
|
311
|
+
source: makeRenderTarget(8, 8),
|
|
312
|
+
}),
|
|
313
|
+
),
|
|
314
|
+
).toBe(RenderTargetTextureSourceKind);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
292
318
|
describe('getTextureUvMatrix', () => {
|
|
293
319
|
it('produces the identity matrix for the default uv transform', () => {
|
|
294
320
|
const texture = createTexture();
|
|
@@ -385,7 +411,7 @@ describe('getTextureUvMatrix', () => {
|
|
|
385
411
|
|
|
386
412
|
describe('getTextureWidth', () => {
|
|
387
413
|
it('returns the image width when an image is bound', () => {
|
|
388
|
-
const texture = createTexture({
|
|
414
|
+
const texture = createTexture({ dimension: '2d', source: fakeImage });
|
|
389
415
|
|
|
390
416
|
expect(getTextureWidth(texture)).toStrictEqual(32);
|
|
391
417
|
});
|
|
@@ -396,31 +422,25 @@ describe('getTextureWidth', () => {
|
|
|
396
422
|
expect(getTextureWidth(texture)).toStrictEqual(-1);
|
|
397
423
|
});
|
|
398
424
|
|
|
399
|
-
it('returns the render
|
|
425
|
+
it('returns the render-target source width', () => {
|
|
400
426
|
const texture = createTexture({
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
image: null,
|
|
404
|
-
target: { height: 48, kind: RenderTextureBackingKind, width: 96 },
|
|
405
|
-
},
|
|
427
|
+
dimension: '2d',
|
|
428
|
+
source: makeRenderTarget(96, 48),
|
|
406
429
|
});
|
|
407
430
|
|
|
408
431
|
expect(getTextureWidth(texture)).toStrictEqual(96);
|
|
409
432
|
});
|
|
410
433
|
});
|
|
411
434
|
|
|
412
|
-
describe('
|
|
413
|
-
it('detects
|
|
414
|
-
expect(
|
|
415
|
-
expect(
|
|
435
|
+
describe('hasTextureSource', () => {
|
|
436
|
+
it('detects CPU and GPU sources through the same field', () => {
|
|
437
|
+
expect(hasTextureSource(createTexture())).toBe(false);
|
|
438
|
+
expect(hasTextureSource(createTexture({ dimension: '2d', source: fakeImage }))).toBe(true);
|
|
416
439
|
expect(
|
|
417
|
-
|
|
440
|
+
hasTextureSource(
|
|
418
441
|
createTexture({
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
image: null,
|
|
422
|
-
target: { height: 8, kind: RenderTextureBackingKind, width: 8 },
|
|
423
|
-
},
|
|
442
|
+
dimension: '2d',
|
|
443
|
+
source: makeRenderTarget(8, 8),
|
|
424
444
|
}),
|
|
425
445
|
),
|
|
426
446
|
).toBe(true);
|
|
@@ -473,14 +493,14 @@ describe('isTextureReady', () => {
|
|
|
473
493
|
|
|
474
494
|
expect(isTextureReady(texture)).toBe(false);
|
|
475
495
|
|
|
476
|
-
texture
|
|
496
|
+
setTextureSource(texture, fakeImage);
|
|
477
497
|
expect(isTextureReady(texture)).toBe(true);
|
|
478
498
|
});
|
|
479
499
|
});
|
|
480
500
|
|
|
481
501
|
describe('resetTextureUvTransform', () => {
|
|
482
502
|
it('restores the identity transform while leaving image, color space, and sampler untouched', () => {
|
|
483
|
-
const texture = createTexture({ colorSpace: 'linear',
|
|
503
|
+
const texture = createTexture({ colorSpace: 'linear', dimension: '2d', source: fakeImage });
|
|
484
504
|
const sampler = texture.sampler;
|
|
485
505
|
setTextureUvOffset(texture, 0.4, 0.6);
|
|
486
506
|
setTextureUvRotation(texture, Math.PI);
|
|
@@ -494,7 +514,7 @@ describe('resetTextureUvTransform', () => {
|
|
|
494
514
|
expect(texture.uvScale.x).toStrictEqual(1);
|
|
495
515
|
expect(texture.uvScale.y).toStrictEqual(1);
|
|
496
516
|
expect(texture.colorSpace).toStrictEqual('linear');
|
|
497
|
-
expect(texture
|
|
517
|
+
expect(getTextureSource(texture)).toBe(fakeImage);
|
|
498
518
|
expect(texture.sampler).toBe(sampler);
|
|
499
519
|
});
|
|
500
520
|
});
|
|
@@ -512,19 +532,19 @@ describe('setTextureFlip', () => {
|
|
|
512
532
|
});
|
|
513
533
|
});
|
|
514
534
|
|
|
515
|
-
describe('
|
|
535
|
+
describe('setTextureSource', () => {
|
|
516
536
|
it('binds and clears the image in place and advances the u32 version', () => {
|
|
517
537
|
const texture = createTexture();
|
|
518
538
|
|
|
519
|
-
|
|
520
|
-
expect(texture
|
|
539
|
+
setTextureSource(texture, fakeImage);
|
|
540
|
+
expect(getTextureSource(texture)).toBe(fakeImage);
|
|
521
541
|
expect(texture.version).toStrictEqual(1);
|
|
522
542
|
|
|
523
|
-
|
|
543
|
+
setTextureSource(texture, fakeImage);
|
|
524
544
|
expect(texture.version).toStrictEqual(1);
|
|
525
545
|
|
|
526
|
-
|
|
527
|
-
expect(texture
|
|
546
|
+
setTextureSource(texture, null);
|
|
547
|
+
expect(getTextureSource(texture)).toBeNull();
|
|
528
548
|
expect(texture.version).toStrictEqual(2);
|
|
529
549
|
});
|
|
530
550
|
});
|
|
@@ -532,7 +552,8 @@ describe('setTextureImage', () => {
|
|
|
532
552
|
describe('setTextureUvFromPixelRect', () => {
|
|
533
553
|
it('normalizes a pixel rectangle against the texture dimensions', () => {
|
|
534
554
|
const texture = createTexture({
|
|
535
|
-
|
|
555
|
+
dimension: '2d',
|
|
556
|
+
source: { height: 100, width: 200 } as Image,
|
|
536
557
|
});
|
|
537
558
|
setTextureUvFromPixelRect(texture, 20, 10, 50, 25);
|
|
538
559
|
expect(texture.uvOffset.x).toBeCloseTo(0.1);
|
package/src/videoTexture.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createMatrix3, createVector2 } from '@flighthq/geometry/contract';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Image, VideoResource } from '@flighthq/types/contract';
|
|
3
3
|
|
|
4
|
+
import { getTextureSource } from './texture';
|
|
4
5
|
import {
|
|
5
6
|
advanceVideoTexture,
|
|
6
7
|
cloneVideoTexture,
|
|
@@ -19,27 +20,28 @@ import {
|
|
|
19
20
|
function makeVideoResource(readyState = 4, videoWidth = 320, videoHeight = 240): VideoResource {
|
|
20
21
|
return {
|
|
21
22
|
element: { readyState, videoWidth, videoHeight } as unknown as HTMLVideoElement,
|
|
23
|
+
objectUrl: null,
|
|
22
24
|
};
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
describe('advanceVideoTexture', () => {
|
|
26
|
-
it('bumps the
|
|
28
|
+
it('bumps the source and Texture versions and returns the new value', () => {
|
|
27
29
|
const vt = createVideoTexture(makeVideoResource());
|
|
28
30
|
expect(vt.version).toBe(0xffffffff);
|
|
29
31
|
expect(advanceVideoTexture(vt)).toBe(0);
|
|
30
32
|
expect(advanceVideoTexture(vt)).toBe(1);
|
|
31
33
|
expect(vt.version).toBe(1);
|
|
32
|
-
expect(vt
|
|
34
|
+
expect(getTextureSource(vt)?.version).toBe(1);
|
|
33
35
|
});
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
describe('cloneVideoTexture', () => {
|
|
37
|
-
it('shares the
|
|
39
|
+
it('shares the source but deep-clones sampler and uv vectors', () => {
|
|
38
40
|
const source = makeVideoResource();
|
|
39
41
|
const vt = createVideoTexture(source, { uvOffset: createVector2(2, 3) });
|
|
40
42
|
advanceVideoTexture(vt);
|
|
41
43
|
const clone = cloneVideoTexture(vt);
|
|
42
|
-
expect(clone
|
|
44
|
+
expect(getTextureSource(clone)).toBe(getTextureSource(vt));
|
|
43
45
|
expect(clone.sampler).not.toBe(vt.sampler);
|
|
44
46
|
expect(clone.uvOffset).not.toBe(vt.uvOffset);
|
|
45
47
|
expect(clone.uvOffset.x).toBe(2);
|
|
@@ -55,7 +57,7 @@ describe('copyVideoTexture', () => {
|
|
|
55
57
|
copyVideoTexture(b, a);
|
|
56
58
|
expect(b.colorSpace).toBe('linear');
|
|
57
59
|
expect(b.version).toBe(0);
|
|
58
|
-
expect(b
|
|
60
|
+
expect(getTextureSource(b)).toBe(getTextureSource(a));
|
|
59
61
|
expect(b.uvScale.x).toBe(4);
|
|
60
62
|
copyVideoTexture(a, a);
|
|
61
63
|
expect(a.uvScale.x).toBe(4);
|
|
@@ -63,11 +65,11 @@ describe('copyVideoTexture', () => {
|
|
|
63
65
|
});
|
|
64
66
|
|
|
65
67
|
describe('createVideoTexture', () => {
|
|
66
|
-
it('returns a universal srgb Texture with a borrowed host-image
|
|
68
|
+
it('returns a universal srgb Texture with a borrowed host-image source', () => {
|
|
67
69
|
const source = makeVideoResource();
|
|
68
70
|
const vt = createVideoTexture(source);
|
|
69
71
|
expect(vt.colorSpace).toBe('srgb');
|
|
70
|
-
expect((vt
|
|
72
|
+
expect((getTextureSource(vt) as Image).source).toBe(source.element);
|
|
71
73
|
expect(vt.version).toBe(0xffffffff);
|
|
72
74
|
expect(vt.uvOffset.x).toBe(0);
|
|
73
75
|
expect(vt.uvScale.x).toBe(1);
|
|
@@ -79,7 +81,7 @@ describe('getVideoTextureHeight', () => {
|
|
|
79
81
|
it('returns the element videoHeight when a frame is decoded, else -1', () => {
|
|
80
82
|
expect(getVideoTextureHeight(createVideoTexture(makeVideoResource(4, 320, 240)))).toBe(240);
|
|
81
83
|
expect(getVideoTextureHeight(createVideoTexture(makeVideoResource(0, 0, 0)))).toBe(-1);
|
|
82
|
-
expect(getVideoTextureHeight(createVideoTexture({ element: null }))).toBe(-1);
|
|
84
|
+
expect(getVideoTextureHeight(createVideoTexture({ element: null, objectUrl: null }))).toBe(-1);
|
|
83
85
|
});
|
|
84
86
|
});
|
|
85
87
|
|
|
@@ -122,7 +124,7 @@ describe('getVideoTextureWidth', () => {
|
|
|
122
124
|
it('returns the element videoWidth when a frame is decoded, else -1', () => {
|
|
123
125
|
expect(getVideoTextureWidth(createVideoTexture(makeVideoResource(4, 320, 240)))).toBe(320);
|
|
124
126
|
expect(getVideoTextureWidth(createVideoTexture(makeVideoResource(0, 0, 0)))).toBe(-1);
|
|
125
|
-
expect(getVideoTextureWidth(createVideoTexture({ element: null }))).toBe(-1);
|
|
127
|
+
expect(getVideoTextureWidth(createVideoTexture({ element: null, objectUrl: null }))).toBe(-1);
|
|
126
128
|
});
|
|
127
129
|
});
|
|
128
130
|
|
|
@@ -131,7 +133,7 @@ describe('isVideoTextureFrameReady', () => {
|
|
|
131
133
|
expect(isVideoTextureFrameReady(createVideoTexture(makeVideoResource(4, 320, 240)))).toBe(true);
|
|
132
134
|
expect(isVideoTextureFrameReady(createVideoTexture(makeVideoResource(1, 320, 240)))).toBe(false);
|
|
133
135
|
expect(isVideoTextureFrameReady(createVideoTexture(makeVideoResource(4, 0, 0)))).toBe(false);
|
|
134
|
-
expect(isVideoTextureFrameReady(createVideoTexture({ element: null }))).toBe(false);
|
|
136
|
+
expect(isVideoTextureFrameReady(createVideoTexture({ element: null, objectUrl: null }))).toBe(false);
|
|
135
137
|
});
|
|
136
138
|
});
|
|
137
139
|
|
|
@@ -142,7 +144,7 @@ describe('resetVideoTextureFrame', () => {
|
|
|
142
144
|
advanceVideoTexture(vt);
|
|
143
145
|
resetVideoTextureFrame(vt);
|
|
144
146
|
expect(vt.version).toBe(0xffffffff);
|
|
145
|
-
expect(vt
|
|
147
|
+
expect(getTextureSource(vt)?.version).toBe(0xffffffff);
|
|
146
148
|
});
|
|
147
149
|
});
|
|
148
150
|
|
|
@@ -152,7 +154,7 @@ describe('setVideoTextureSource', () => {
|
|
|
152
154
|
advanceVideoTexture(vt);
|
|
153
155
|
const next = makeVideoResource(4, 640, 480);
|
|
154
156
|
setVideoTextureSource(vt, next);
|
|
155
|
-
expect((vt
|
|
157
|
+
expect((getTextureSource(vt) as Image).source).toBe(next.element);
|
|
156
158
|
expect(vt.version).toBe(0xffffffff);
|
|
157
159
|
expect(getVideoTextureWidth(vt)).toBe(640);
|
|
158
160
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createEntity } from '@flighthq/entity/contract';
|
|
2
|
+
import type { VoxelGrid } from '@flighthq/types/contract';
|
|
3
|
+
import { VoxelGridTextureSourceKind } from '@flighthq/types/contract';
|
|
4
|
+
|
|
5
|
+
import { invalidateVoxelGrid } from './voxelGrid';
|
|
6
|
+
|
|
7
|
+
function voxelGrid(version: number): VoxelGrid {
|
|
8
|
+
return createEntity({
|
|
9
|
+
data: new Uint8Array(32),
|
|
10
|
+
depth: 2,
|
|
11
|
+
format: 'rgba8unorm' as const,
|
|
12
|
+
height: 2,
|
|
13
|
+
kind: VoxelGridTextureSourceKind,
|
|
14
|
+
version,
|
|
15
|
+
width: 2,
|
|
16
|
+
}) as VoxelGrid;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('invalidateVoxelGrid', () => {
|
|
20
|
+
it('advances the shared content version without replacing voxel bytes', () => {
|
|
21
|
+
const grid = voxelGrid(0);
|
|
22
|
+
const data = grid.data;
|
|
23
|
+
|
|
24
|
+
invalidateVoxelGrid(grid);
|
|
25
|
+
|
|
26
|
+
expect(grid.version).toBe(1);
|
|
27
|
+
expect(grid.data).toBe(data);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('wraps the content version as u32', () => {
|
|
31
|
+
const grid = voxelGrid(0xffffffff);
|
|
32
|
+
|
|
33
|
+
invalidateVoxelGrid(grid);
|
|
34
|
+
|
|
35
|
+
expect(grid.version).toBe(0);
|
|
36
|
+
});
|
|
37
|
+
});
|