@takram/three-geospatial 0.0.1-alpha.4 → 0.0.1-alpha.6

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 (45) hide show
  1. package/build/index.cjs +1 -43
  2. package/build/index.cjs.map +1 -1
  3. package/build/index.js +315 -772
  4. package/build/index.js.map +1 -1
  5. package/build/shaders.cjs +276 -0
  6. package/build/shaders.cjs.map +1 -0
  7. package/build/shaders.js +286 -0
  8. package/build/shaders.js.map +1 -0
  9. package/package.json +7 -3
  10. package/src/DataLoader.ts +107 -49
  11. package/src/Texture3DLoader.ts +81 -0
  12. package/src/TypedArrayLoader.ts +25 -9
  13. package/src/bufferGeometry.ts +2 -2
  14. package/src/constants.ts +3 -0
  15. package/src/index.ts +4 -10
  16. package/src/math.ts +1 -0
  17. package/src/r3f/index.ts +1 -0
  18. package/src/r3f/types.ts +64 -0
  19. package/src/resolveIncludes.test.ts +21 -0
  20. package/src/resolveIncludes.ts +22 -0
  21. package/src/shaders/depth.glsl +3 -1
  22. package/src/shaders/generators.glsl +9 -0
  23. package/src/shaders/index.ts +17 -0
  24. package/src/shaders/math.glsl +52 -0
  25. package/src/shaders/poissonDisk.glsl +21 -0
  26. package/src/shaders/raySphereIntersection.glsl +134 -0
  27. package/src/shaders/turbo.glsl +9 -0
  28. package/src/typedArray.ts +29 -52
  29. package/src/typedArrayParsers.ts +77 -0
  30. package/src/types.ts +5 -51
  31. package/src/unrollLoops.ts +23 -0
  32. package/types/DataLoader.d.ts +30 -60
  33. package/types/Texture3DLoader.d.ts +5 -0
  34. package/types/TypedArrayLoader.d.ts +10 -10
  35. package/types/constants.d.ts +3 -0
  36. package/types/index.d.ts +4 -3
  37. package/types/math.d.ts +1 -0
  38. package/types/r3f/index.d.ts +1 -0
  39. package/types/r3f/types.d.ts +22 -0
  40. package/types/resolveIncludes.d.ts +5 -0
  41. package/types/shaders/index.d.ts +8 -0
  42. package/types/typedArray.d.ts +2 -8
  43. package/types/typedArrayParsers.d.ts +11 -0
  44. package/types/types.d.ts +5 -20
  45. package/types/unrollLoops.d.ts +1 -0
@@ -0,0 +1,286 @@
1
+ const n = `// cSpell:words logdepthbuf
2
+
3
+ float reverseLogDepth(const float depth, const float near, const float far) {
4
+ #ifdef USE_LOGDEPTHBUF
5
+ float d = pow(2.0, depth * log2(far + 1.0)) - 1.0;
6
+ float a = far / (far - near);
7
+ float b = far * near / (near - far);
8
+ return a + b / d;
9
+ #else // USE_LOGDEPTHBUF
10
+ return depth;
11
+ #endif // USE_LOGDEPTHBUF
12
+ }
13
+
14
+ float linearizeDepth(const float depth, const float near, const float far) {
15
+ float ndc = depth * 2.0 - 1.0;
16
+ return 2.0 * near * far / (far + near - ndc * (far - near));
17
+ }
18
+ `, e = `float checker(const vec2 uv, const vec2 repeats) {
19
+ vec2 c = floor(repeats * uv);
20
+ float result = mod(c.x + c.y, 2.0);
21
+ return sign(result);
22
+ }
23
+
24
+ float checker(const vec2 uv, const float repeats) {
25
+ return checker(uv, vec2(repeats));
26
+ }
27
+ `, t = `#if !defined(saturate)
28
+ #define saturate(a) clamp(a, 0.0, 1.0)
29
+ #endif // !defined(saturate)
30
+
31
+ float inverseLerp(const float x, const float y, const float a) {
32
+ return (a - x) / (y - x);
33
+ }
34
+
35
+ vec2 inverseLerp(const vec2 x, const vec2 y, const vec2 a) {
36
+ return (a - x) / (y - x);
37
+ }
38
+
39
+ vec3 inverseLerp(const vec3 x, const vec3 y, const vec3 a) {
40
+ return (a - x) / (y - x);
41
+ }
42
+
43
+ vec4 inverseLerp(const vec4 x, const vec4 y, const vec4 a) {
44
+ return (a - x) / (y - x);
45
+ }
46
+
47
+ float remap(const float x, const float min1, const float max1, const float min2, const float max2) {
48
+ return min2 + (x - min1) / (max1 - min1) * (max2 - min2);
49
+ }
50
+
51
+ vec2 remap(const vec2 x, const vec2 min1, const vec2 max1, const vec2 min2, const vec2 max2) {
52
+ return min2 + (x - min1) / (max1 - min1) * (max2 - min2);
53
+ }
54
+
55
+ vec3 remap(const vec3 x, const vec3 min1, const vec3 max1, const vec3 min2, const vec3 max2) {
56
+ return min2 + (x - min1) / (max1 - min1) * (max2 - min2);
57
+ }
58
+
59
+ vec4 remap(const vec4 x, const vec4 min1, const vec4 max1, const vec4 min2, const vec4 max2) {
60
+ return min2 + (x - min1) / (max1 - min1) * (max2 - min2);
61
+ }
62
+
63
+ // Implicitly remap to 0 and 1
64
+ float remap(const float x, const float min1, const float max1) {
65
+ return (x - min1) / (max1 - min1);
66
+ }
67
+
68
+ vec2 remap(const vec2 x, const vec2 min1, const vec2 max1) {
69
+ return (x - min1) / (max1 - min1);
70
+ }
71
+
72
+ vec3 remap(const vec3 x, const vec3 min1, const vec3 max1) {
73
+ return (x - min1) / (max1 - min1);
74
+ }
75
+
76
+ vec4 remap(const vec4 x, const vec4 min1, const vec4 max1) {
77
+ return (x - min1) / (max1 - min1);
78
+ }
79
+ `, c = `// Reference: https://jcgt.org/published/0003/02/01/paper.pdf
80
+
81
+ vec2 signNotZero(vec2 v) {
82
+ return vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0);
83
+ }
84
+
85
+ vec2 packNormalToVec2(vec3 v) {
86
+ vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
87
+ return v.z <= 0.0
88
+ ? (1.0 - abs(p.yx)) * signNotZero(p)
89
+ : p;
90
+ }
91
+
92
+ vec3 unpackVec2ToNormal(vec2 e) {
93
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
94
+ if (v.z < 0.0) {
95
+ v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
96
+ }
97
+ return normalize(v);
98
+ }
99
+ `, o = `// Taken from: https://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf
100
+ const vec2 poissonDisk[16] = vec2[16](
101
+ vec2(-0.94201624, -0.39906216),
102
+ vec2(0.94558609, -0.76890725),
103
+ vec2(-0.094184101, -0.9293887),
104
+ vec2(0.34495938, 0.2938776),
105
+ vec2(-0.91588581, 0.45771432),
106
+ vec2(-0.81544232, -0.87912464),
107
+ vec2(-0.38277543, 0.27676845),
108
+ vec2(0.97484398, 0.75648379),
109
+ vec2(0.44323325, -0.97511554),
110
+ vec2(0.53742981, -0.4737342),
111
+ vec2(-0.26496911, -0.41893023),
112
+ vec2(0.79197514, 0.19090188),
113
+ vec2(-0.2418884, 0.99706507),
114
+ vec2(-0.81409955, 0.9143759),
115
+ vec2(0.19984126, 0.78641367),
116
+ vec2(0.14383161, -0.1410079)
117
+ );
118
+
119
+ #define POISSON_DISK_COUNT (16)
120
+ `, r = `float raySphereFirstIntersection(
121
+ const vec3 origin,
122
+ const vec3 direction,
123
+ const vec3 center,
124
+ const float radius
125
+ ) {
126
+ vec3 a = origin - center;
127
+ float b = 2.0 * dot(direction, a);
128
+ float c = dot(a, a) - radius * radius;
129
+ float discriminant = b * b - 4.0 * c;
130
+ return discriminant < 0.0
131
+ ? -1.0
132
+ : (-b - sqrt(discriminant)) * 0.5;
133
+ }
134
+
135
+ float raySphereFirstIntersection(const vec3 origin, const vec3 direction, const float radius) {
136
+ return raySphereFirstIntersection(origin, direction, vec3(0.0), radius);
137
+ }
138
+
139
+ vec4 raySphereFirstIntersection(
140
+ const vec3 origin,
141
+ const vec3 direction,
142
+ const vec3 center,
143
+ const vec4 radius
144
+ ) {
145
+ vec3 a = origin - center;
146
+ float b = 2.0 * dot(direction, a);
147
+ vec4 c = dot(a, a) - radius * radius;
148
+ vec4 discriminant = b * b - 4.0 * c;
149
+ vec4 mask = step(discriminant, vec4(0.0));
150
+ return mix((-b - sqrt(max(vec4(0.0), discriminant))) * 0.5, vec4(-1.0), mask);
151
+ }
152
+
153
+ vec4 raySphereFirstIntersection(const vec3 origin, const vec3 direction, const vec4 radius) {
154
+ return raySphereFirstIntersection(origin, direction, vec3(0.0), radius);
155
+ }
156
+
157
+ float raySphereSecondIntersection(
158
+ const vec3 origin,
159
+ const vec3 direction,
160
+ const vec3 center,
161
+ const float radius
162
+ ) {
163
+ vec3 a = origin - center;
164
+ float b = 2.0 * dot(direction, a);
165
+ float c = dot(a, a) - radius * radius;
166
+ float discriminant = b * b - 4.0 * c;
167
+ return discriminant < 0.0
168
+ ? -1.0
169
+ : (-b + sqrt(discriminant)) * 0.5;
170
+ }
171
+
172
+ float raySphereSecondIntersection(const vec3 origin, const vec3 direction, const float radius) {
173
+ return raySphereSecondIntersection(origin, direction, vec3(0.0), radius);
174
+ }
175
+
176
+ vec4 raySphereSecondIntersection(
177
+ const vec3 origin,
178
+ const vec3 direction,
179
+ const vec3 center,
180
+ const vec4 radius
181
+ ) {
182
+ vec3 a = origin - center;
183
+ float b = 2.0 * dot(direction, a);
184
+ vec4 c = dot(a, a) - radius * radius;
185
+ vec4 discriminant = b * b - 4.0 * c;
186
+ vec4 mask = step(discriminant, vec4(0.0));
187
+ return mix((-b + sqrt(max(vec4(0.0), discriminant))) * 0.5, vec4(-1.0), mask);
188
+ }
189
+
190
+ vec4 raySphereSecondIntersection(const vec3 origin, const vec3 direction, const vec4 radius) {
191
+ return raySphereSecondIntersection(origin, direction, vec3(0.0), radius);
192
+ }
193
+
194
+ void raySphereIntersections(
195
+ const vec3 origin,
196
+ const vec3 direction,
197
+ const vec3 center,
198
+ const float radius,
199
+ out float intersection1,
200
+ out float intersection2
201
+ ) {
202
+ vec3 a = origin - center;
203
+ float b = 2.0 * dot(direction, a);
204
+ float c = dot(a, a) - radius * radius;
205
+ float discriminant = b * b - 4.0 * c;
206
+ if (discriminant < 0.0) {
207
+ intersection1 = -1.0;
208
+ intersection2 = -1.0;
209
+ return;
210
+ } else {
211
+ float Q = sqrt(discriminant);
212
+ intersection1 = (-b - Q) * 0.5;
213
+ intersection2 = (-b + Q) * 0.5;
214
+ }
215
+ }
216
+
217
+ void raySphereIntersections(
218
+ const vec3 origin,
219
+ const vec3 direction,
220
+ const float radius,
221
+ out float intersection1,
222
+ out float intersection2
223
+ ) {
224
+ raySphereIntersections(origin, direction, vec3(0.0), radius, intersection1, intersection2);
225
+ }
226
+
227
+ void raySphereIntersections(
228
+ const vec3 origin,
229
+ const vec3 direction,
230
+ const vec3 center,
231
+ const vec4 radius,
232
+ out vec4 intersection1,
233
+ out vec4 intersection2
234
+ ) {
235
+ vec3 a = origin - center;
236
+ float b = 2.0 * dot(direction, a);
237
+ vec4 c = dot(a, a) - radius * radius;
238
+ vec4 discriminant = b * b - 4.0 * c;
239
+ vec4 mask = step(discriminant, vec4(0.0));
240
+ vec4 Q = sqrt(max(vec4(0.0), discriminant));
241
+ intersection1 = mix((-b - Q) * 0.5, vec4(-1.0), mask);
242
+ intersection2 = mix((-b + Q) * 0.5, vec4(-1.0), mask);
243
+ }
244
+
245
+ void raySphereIntersections(
246
+ const vec3 origin,
247
+ const vec3 direction,
248
+ const vec4 radius,
249
+ out vec4 intersection1,
250
+ out vec4 intersection2
251
+ ) {
252
+ raySphereIntersections(origin, direction, vec3(0.0), radius, intersection1, intersection2);
253
+ }
254
+ `, i = `vec3 screenToView(
255
+ const vec2 uv,
256
+ const float depth,
257
+ const float viewZ,
258
+ const mat4 projectionMatrix,
259
+ const mat4 inverseProjectionMatrix
260
+ ) {
261
+ vec4 clip = vec4(vec3(uv, depth) * 2.0 - 1.0, 1.0);
262
+ float clipW = projectionMatrix[2][3] * viewZ + projectionMatrix[3][3];
263
+ clip *= clipW;
264
+ return (inverseProjectionMatrix * clip).xyz;
265
+ }
266
+ `, s = `// A fifth-order polynomial approximation of Turbo color map.
267
+ // See: https://observablehq.com/@mbostock/turbo
268
+ // prettier-ignore
269
+ vec3 turbo(const float x) {
270
+ float r = 0.1357 + x * (4.5974 - x * (42.3277 - x * (130.5887 - x * (150.5666 - x * 58.1375))));
271
+ float g = 0.0914 + x * (2.1856 + x * (4.8052 - x * (14.0195 - x * (4.2109 + x * 2.7747))));
272
+ float b = 0.1067 + x * (12.5925 - x * (60.1097 - x * (109.0745 - x * (88.5066 - x * 26.8183))));
273
+ return vec3(r, g, b);
274
+ }
275
+ `, a = n, v = e, d = t, m = c, f = o, x = r, l = i, p = s;
276
+ export {
277
+ a as depth,
278
+ v as generators,
279
+ d as math,
280
+ m as packing,
281
+ f as poissonDisk,
282
+ x as raySphereIntersection,
283
+ l as transform,
284
+ p as turbo
285
+ };
286
+ //# sourceMappingURL=shaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shaders.js","sources":["../src/shaders/depth.glsl?raw","../src/shaders/generators.glsl?raw","../src/shaders/math.glsl?raw","../src/shaders/packing.glsl?raw","../src/shaders/poissonDisk.glsl?raw","../src/shaders/raySphereIntersection.glsl?raw","../src/shaders/transform.glsl?raw","../src/shaders/turbo.glsl?raw","../src/shaders/index.ts"],"sourcesContent":null,"names":["_depth","_generators","_math","_packing","_poissonDisk","_raySphereIntersection","_transform","_turbo","depth","generators","math","packing","poissonDisk","raySphereIntersection","transform","turbo"],"mappings":"AAAA,MAAeA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAAC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCSFC,IAAgBR,GAChBS,IAAqBR,GACrBS,IAAeR,GACfS,IAAkBR,GAClBS,IAAsBR,GACtBS,IAAgCR,GAChCS,IAAoBR,GACpBS,IAAgBR;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takram/three-geospatial",
3
- "version": "0.0.1-alpha.4",
3
+ "version": "0.0.1-alpha.6",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,6 +13,11 @@
13
13
  "import": "./build/r3f.js",
14
14
  "require": "./build/r3f.cjs",
15
15
  "types": "./types/r3f/index.d.ts"
16
+ },
17
+ "./shaders": {
18
+ "import": "./build/shaders.js",
19
+ "require": "./build/shaders.cjs",
20
+ "types": "./types/shaders/index.d.ts"
16
21
  }
17
22
  },
18
23
  "main": "./build/index.cjs",
@@ -26,10 +31,9 @@
26
31
  "README.md"
27
32
  ],
28
33
  "dependencies": {
29
- "lodash-es": "^4.17.21",
30
34
  "react-merge-refs": "^2.1.1",
31
35
  "tiny-invariant": "^1.3.3",
32
- "type-fest": "^4.28.0"
36
+ "type-fest": "^4.33.0"
33
37
  },
34
38
  "peerDependencies": {
35
39
  "@react-three/fiber": ">=8.17.10",
package/src/DataLoader.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ ByteType,
2
3
  ClampToEdgeWrapping,
3
4
  Data3DTexture,
4
5
  DataTexture,
@@ -6,31 +7,45 @@ import {
6
7
  LinearFilter,
7
8
  Loader,
8
9
  RGBAFormat,
9
- type Texture,
10
+ UnsignedByteType,
10
11
  type TypedArray
11
12
  } from 'three'
12
- import { type Class } from 'type-fest'
13
+ import { type Class, type WritableKeysOf } from 'type-fest'
13
14
 
15
+ import { getTypedArrayElementType } from './typedArray'
14
16
  import {
15
- Float32ArrayLoader,
16
- Int16ArrayLoader,
17
- Uint16ArrayLoader,
17
+ createTypedArrayLoaderClass,
18
18
  type TypedArrayLoader
19
19
  } from './TypedArrayLoader'
20
+ import {
21
+ parseFloat32Array,
22
+ parseInt16Array,
23
+ parseUint16Array,
24
+ type TypedArrayParser
25
+ } from './typedArrayParsers'
20
26
  import { type Callable } from './types'
21
27
 
22
- export interface ImageSize {
23
- width: number
24
- height: number
25
- depth?: number
28
+ // TODO: Move to types
29
+ type ParameterProperties<T> = {
30
+ [K in WritableKeysOf<T> as T[K] extends Callable ? never : K]: T[K]
26
31
  }
27
32
 
28
33
  export type DataTextureParameters = Omit<
29
- Partial<{
30
- [K in keyof Texture as Texture[K] extends Callable ? never : K]: Texture[K]
31
- }>,
34
+ Partial<ParameterProperties<DataTexture>>,
32
35
  'image'
33
- >
36
+ > & {
37
+ width?: number
38
+ height?: number
39
+ }
40
+
41
+ export type Data3DTextureParameters = Omit<
42
+ Partial<ParameterProperties<Data3DTexture>>,
43
+ 'image'
44
+ > & {
45
+ width?: number
46
+ height?: number
47
+ depth?: number
48
+ }
34
49
 
35
50
  const defaultDataTextureParameter = {
36
51
  format: RGBAFormat,
@@ -38,16 +53,16 @@ const defaultDataTextureParameter = {
38
53
  wrapT: ClampToEdgeWrapping,
39
54
  minFilter: LinearFilter,
40
55
  magFilter: LinearFilter
41
- } satisfies DataTextureParameters
56
+ } satisfies DataTextureParameters & Data3DTextureParameters
42
57
 
43
58
  export abstract class DataLoader<
44
- T extends DataTexture | Data3DTexture,
45
- U extends TypedArray
59
+ T extends DataTexture | Data3DTexture = DataTexture | Data3DTexture,
60
+ U extends TypedArray = TypedArray
46
61
  > extends Loader<T> {
47
62
  abstract readonly Texture: Class<T>
48
63
  abstract readonly TypedArrayLoader: Class<TypedArrayLoader<U>>
49
64
 
50
- readonly parameters?: DataTextureParameters
65
+ readonly parameters: DataTextureParameters & Data3DTextureParameters = {}
51
66
 
52
67
  override load(
53
68
  url: string,
@@ -64,7 +79,27 @@ export abstract class DataLoader<
64
79
  url,
65
80
  array => {
66
81
  texture.image.data = array as typeof texture.image.data
67
- Object.assign(texture, this.parameters)
82
+ const { width, height, depth, ...params } = this.parameters
83
+ if (width != null) {
84
+ texture.image.width = width
85
+ }
86
+ if (height != null) {
87
+ texture.image.height = height
88
+ }
89
+ if ('depth' in texture.image && depth != null) {
90
+ texture.image.depth = depth
91
+ }
92
+
93
+ // Populate the default texture type for the array type.
94
+ const type = getTypedArrayElementType(array)
95
+ texture.type =
96
+ type === 'uint8'
97
+ ? UnsignedByteType
98
+ : type === 'int8'
99
+ ? ByteType
100
+ : FloatType
101
+
102
+ Object.assign(texture, params)
68
103
  texture.needsUpdate = true
69
104
  onLoad(texture)
70
105
  },
@@ -74,41 +109,64 @@ export abstract class DataLoader<
74
109
  }
75
110
  }
76
111
 
77
- export class Int16Data2DLoader extends DataLoader<DataTexture, Int16Array> {
78
- readonly Texture = DataTexture
79
- readonly TypedArrayLoader = Int16ArrayLoader
80
- readonly parameters = {
81
- ...defaultDataTextureParameter,
82
- type: FloatType
83
- } satisfies DataTextureParameters
112
+ function createDataLoaderClass<
113
+ T extends DataTexture | Data3DTexture,
114
+ U extends TypedArray
115
+ >(
116
+ Texture: Class<T>,
117
+ parser: TypedArrayParser<U>,
118
+ parameters?: DataTextureParameters
119
+ ): Class<DataLoader<T, U>> {
120
+ return class extends DataLoader<T, U> {
121
+ readonly Texture = Texture
122
+ readonly TypedArrayLoader = createTypedArrayLoaderClass(parser)
123
+ readonly parameters = {
124
+ ...defaultDataTextureParameter,
125
+ ...parameters
126
+ }
127
+ }
84
128
  }
85
129
 
86
- export class Uint16Data2DLoader extends DataLoader<DataTexture, Uint16Array> {
87
- readonly Texture = DataTexture
88
- readonly TypedArrayLoader = Uint16ArrayLoader
89
- readonly parameters = {
90
- ...defaultDataTextureParameter,
91
- type: FloatType
92
- } satisfies DataTextureParameters
130
+ export function createData3DTextureLoaderClass<T extends TypedArray>(
131
+ parser: TypedArrayParser<T>,
132
+ parameters?: Data3DTextureParameters
133
+ ): Class<DataLoader<Data3DTexture, T>> {
134
+ return createDataLoaderClass(Data3DTexture, parser, parameters)
93
135
  }
94
136
 
95
- export class Float32Data2DLoader extends DataLoader<DataTexture, Float32Array> {
96
- readonly Texture = DataTexture
97
- readonly TypedArrayLoader = Float32ArrayLoader
98
- readonly parameters = {
99
- ...defaultDataTextureParameter,
100
- type: FloatType
101
- } satisfies DataTextureParameters
137
+ export function createDataTextureLoaderClass<T extends TypedArray>(
138
+ parser: TypedArrayParser<T>,
139
+ parameters?: DataTextureParameters
140
+ ): Class<DataLoader<DataTexture, T>> {
141
+ return createDataLoaderClass(DataTexture, parser, parameters)
102
142
  }
103
143
 
104
- export class Float32Data3DLoader extends DataLoader<
105
- Data3DTexture,
106
- Float32Array
107
- > {
108
- readonly Texture = Data3DTexture
109
- readonly TypedArrayLoader = Float32ArrayLoader
110
- readonly parameters = {
111
- ...defaultDataTextureParameter,
112
- type: FloatType
113
- } satisfies DataTextureParameters
144
+ export function createData3DTextureLoader<T extends TypedArray>(
145
+ parser: TypedArrayParser<T>,
146
+ parameters?: Data3DTextureParameters
147
+ ): DataLoader<Data3DTexture, T> {
148
+ return new (createData3DTextureLoaderClass(parser, parameters))()
149
+ }
150
+
151
+ export function createDataTextureLoader<T extends TypedArray>(
152
+ parser: TypedArrayParser<T>,
153
+ parameters?: DataTextureParameters
154
+ ): DataLoader<DataTexture, T> {
155
+ return new (createDataTextureLoaderClass(parser, parameters))()
114
156
  }
157
+
158
+ /** @deprecated Use createDataTextureLoaderClass instead. */
159
+ export const Int16Data2DLoader =
160
+ /*#__PURE__*/ createDataTextureLoaderClass(parseInt16Array)
161
+
162
+ /** @deprecated Use createDataTextureLoaderClass instead. */
163
+ export const Uint16Data2DLoader =
164
+ /*#__PURE__*/ createDataTextureLoaderClass(parseUint16Array)
165
+
166
+ /** @deprecated Use createDataTextureLoaderClass instead. */
167
+ export const Float32Data2DLoader =
168
+ /*#__PURE__*/ createDataTextureLoaderClass(parseFloat32Array)
169
+
170
+ /** @deprecated Use createData3DTextureLoaderClass instead. */
171
+ export const Float32Data3DLoader =
172
+ /*#__PURE__*/ createData3DTextureLoaderClass(parseFloat32Array)
@@ -0,0 +1,81 @@
1
+ import {
2
+ Data3DTexture,
3
+ ImageLoader,
4
+ LinearFilter,
5
+ Loader,
6
+ RepeatWrapping
7
+ } from 'three'
8
+
9
+ export class Texture3DLoader extends Loader<Data3DTexture> {
10
+ override load(
11
+ url: string,
12
+ onLoad: (data: Data3DTexture) => void,
13
+ onProgress?: (event: ProgressEvent) => void,
14
+ onError?: (error: unknown) => void
15
+ ): void {
16
+ const loader = new ImageLoader(this.manager)
17
+ loader.setRequestHeader(this.requestHeader)
18
+ loader.setPath(this.path)
19
+ loader.setWithCredentials(this.withCredentials)
20
+ loader.load(
21
+ url,
22
+ image => {
23
+ const canvas = document.createElement('canvas')
24
+ const context = canvas.getContext('2d')
25
+ if (context == null) {
26
+ onError?.(new Error('Could not obtain canvas context.'))
27
+ return
28
+ }
29
+
30
+ // Assume cubic 3D texture.
31
+ const { width, height } = image
32
+ const size = Math.min(width, height)
33
+ canvas.width = width
34
+ canvas.height = height
35
+ context.drawImage(image, 0, 0)
36
+ const imageData = context.getImageData(0, 0, width, height).data
37
+ let data: Uint8Array
38
+
39
+ if (width < height) {
40
+ data = new Uint8Array(imageData.buffer)
41
+ } else {
42
+ data = new Uint8Array(imageData.length)
43
+ const sizeSq = size ** 2
44
+ for (let z = 0; z < size; ++z) {
45
+ for (let y = 0; y < size; ++y) {
46
+ for (let x = 0; x < size; ++x) {
47
+ const src = (x + z * size + y * sizeSq) * 4
48
+ const dest = (x + y * size + z * sizeSq) * 4
49
+ data[dest + 0] = imageData[src + 0]
50
+ data[dest + 1] = imageData[src + 1]
51
+ data[dest + 2] = imageData[src + 2]
52
+ data[dest + 3] = imageData[src + 3]
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ const texture = new Data3DTexture(data, size, size, size)
59
+ texture.minFilter = LinearFilter
60
+ texture.magFilter = LinearFilter
61
+ texture.wrapS = RepeatWrapping
62
+ texture.wrapR = RepeatWrapping
63
+ texture.wrapT = RepeatWrapping
64
+ texture.needsUpdate = true
65
+
66
+ try {
67
+ onLoad(texture)
68
+ } catch (error) {
69
+ if (onError != null) {
70
+ onError(error)
71
+ } else {
72
+ console.error(error)
73
+ }
74
+ this.manager.itemError(url)
75
+ }
76
+ },
77
+ onProgress,
78
+ onError
79
+ )
80
+ }
81
+ }
@@ -1,11 +1,13 @@
1
1
  import { Loader, type TypedArray } from 'three'
2
+ import { type Class } from 'type-fest'
2
3
 
3
4
  import { ArrayBufferLoader } from './ArrayBufferLoader'
4
5
  import {
5
6
  parseFloat32Array,
6
7
  parseInt16Array,
7
- parseUint16Array
8
- } from './typedArray'
8
+ parseUint16Array,
9
+ type TypedArrayParser
10
+ } from './typedArrayParsers'
9
11
 
10
12
  export abstract class TypedArrayLoader<T extends TypedArray> extends Loader<T> {
11
13
  abstract parseTypedArray(buffer: ArrayBuffer): T
@@ -40,14 +42,28 @@ export abstract class TypedArrayLoader<T extends TypedArray> extends Loader<T> {
40
42
  }
41
43
  }
42
44
 
43
- export class Int16ArrayLoader extends TypedArrayLoader<Int16Array> {
44
- readonly parseTypedArray = parseInt16Array
45
+ export function createTypedArrayLoaderClass<T extends TypedArray>(
46
+ parser: TypedArrayParser<T>
47
+ ): Class<TypedArrayLoader<T>> {
48
+ return class extends TypedArrayLoader<T> {
49
+ readonly parseTypedArray = parser
50
+ }
45
51
  }
46
52
 
47
- export class Uint16ArrayLoader extends TypedArrayLoader<Uint16Array> {
48
- readonly parseTypedArray = parseUint16Array
53
+ export function createTypedArrayLoader<T extends TypedArray>(
54
+ parser: TypedArrayParser<T>
55
+ ): TypedArrayLoader<T> {
56
+ return new (createTypedArrayLoaderClass(parser))()
49
57
  }
50
58
 
51
- export class Float32ArrayLoader extends TypedArrayLoader<Float32Array> {
52
- readonly parseTypedArray = parseFloat32Array
53
- }
59
+ /** @deprecated Use createTypedArrayLoaderClass instead. */
60
+ export const Int16ArrayLoader =
61
+ /*#__PURE__*/ createTypedArrayLoaderClass(parseInt16Array)
62
+
63
+ /** @deprecated Use createTypedArrayLoaderClass instead. */
64
+ export const Uint16ArrayLoader =
65
+ /*#__PURE__*/ createTypedArrayLoaderClass(parseUint16Array)
66
+
67
+ /** @deprecated Use createTypedArrayLoaderClass instead. */
68
+ export const Float32ArrayLoader =
69
+ /*#__PURE__*/ createTypedArrayLoaderClass(parseFloat32Array)
@@ -1,4 +1,3 @@
1
- import { pick } from 'lodash-es'
2
1
  import { Box3, BufferAttribute, BufferGeometry, Sphere, Vector3 } from 'three'
3
2
 
4
3
  export type BufferGeometryLike = Pick<
@@ -9,8 +8,9 @@ export type BufferGeometryLike = Pick<
9
8
  export function toBufferGeometryLike(
10
9
  geometry: BufferGeometry
11
10
  ): [BufferGeometryLike, ArrayBuffer[]] {
11
+ const { attributes, index, boundingBox, boundingSphere } = geometry
12
12
  return [
13
- pick(geometry, ['attributes', 'index', 'boundingBox', 'boundingSphere']),
13
+ { attributes, index, boundingBox, boundingSphere },
14
14
  [
15
15
  ...Object.values(geometry.attributes).map(
16
16
  attribute => attribute.array.buffer
@@ -0,0 +1,3 @@
1
+ export const STBN_TEXTURE_WIDTH = 128
2
+ export const STBN_TEXTURE_HEIGHT = 128
3
+ export const STBN_TEXTURE_DEPTH = 64