s3m-three 0.1.0 → 0.2.0

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 (44) hide show
  1. package/LICENSE +202 -202
  2. package/dist/render/DatasetManager.d.ts +10 -3
  3. package/dist/render/DatasetManager.d.ts.map +1 -1
  4. package/dist/render/DatasetManager.js +14 -5
  5. package/dist/render/DatasetManager.js.map +1 -1
  6. package/dist/render/EdgeLines.js +46 -46
  7. package/dist/render/GroundManager.d.ts +9 -0
  8. package/dist/render/GroundManager.d.ts.map +1 -1
  9. package/dist/render/GroundManager.js +13 -1
  10. package/dist/render/GroundManager.js.map +1 -1
  11. package/dist/render/Picker.js +66 -66
  12. package/dist/render/S3MViewer.d.ts +11 -3
  13. package/dist/render/S3MViewer.d.ts.map +1 -1
  14. package/dist/render/S3MViewer.js +18 -3
  15. package/dist/render/S3MViewer.js.map +1 -1
  16. package/dist/render/StyleMaterial.js +265 -265
  17. package/dist/vendor/meshopt_decoder.module.js +118 -118
  18. package/docs/API.md +20 -0
  19. package/package.json +1 -1
  20. package/src/core/BinaryReader.ts +116 -116
  21. package/src/core/DXTTextureDecode.ts +260 -260
  22. package/src/core/FeatureInfo.ts +150 -150
  23. package/src/core/MeshOpt.ts +401 -401
  24. package/src/core/S3MBParser.ts +590 -590
  25. package/src/core/types.ts +222 -222
  26. package/src/render/DatasetManager.ts +17 -6
  27. package/src/render/EdgeLines.ts +343 -343
  28. package/src/render/GeometryBuilder.ts +840 -840
  29. package/src/render/GroundManager.ts +14 -1
  30. package/src/render/Picker.ts +293 -293
  31. package/src/render/S3MViewer.ts +18 -3
  32. package/src/render/StyleMaterial.ts +602 -602
  33. package/src/render/TextureFactory.ts +134 -134
  34. package/src/tileset/S3MTileset.ts +552 -552
  35. package/src/vendor/meshopt_decoder.module.d.ts +31 -31
  36. package/src/vendor/meshopt_decoder.module.js +118 -118
  37. package/dist/render/CoordinateHelper.d.ts +0 -90
  38. package/dist/render/CoordinateHelper.d.ts.map +0 -1
  39. package/dist/render/CoordinateHelper.js +0 -85
  40. package/dist/render/CoordinateHelper.js.map +0 -1
  41. package/dist/render/S3MLayer.d.ts +0 -457
  42. package/dist/render/S3MLayer.d.ts.map +0 -1
  43. package/dist/render/S3MLayer.js +0 -1860
  44. package/dist/render/S3MLayer.js.map +0 -1
@@ -1,260 +1,260 @@
1
- /**
2
- * DXT1 / DXT3 / DXT5 纹理解码(squish 算法的 JS 移植)
3
- *
4
- * 来源:SuperMap iClient3D S3M SDK(Apache-2.0)。
5
- * 迁移到 TS 时做了两件事,算法本身未改:
6
- * 1. 补齐类型;
7
- * 2. 修掉 `DecompressAlphaDxt3` 里把 `block` 误写成未定义全局 `bytes` 的笔误
8
- * (DXT3 纹理此前会直接 ReferenceError)。
9
- */
10
-
11
- const kDxt1 = 1 << 0;
12
- const kDxt3 = 1 << 1;
13
- const kDxt5 = 1 << 2;
14
- const krgb565 = 1 << 5;
15
-
16
- function Unpack565(packed0: number, packed1: number, colour: Uint8Array, offset: number): number {
17
- const value = packed0 | (packed1 << 8);
18
-
19
- const red = (value >> 11) & 0x1f;
20
- const green = (value >> 5) & 0x3f;
21
- const blue = value & 0x1f;
22
-
23
- colour[offset + 0] = (red << 3) | (red >> 2);
24
- colour[offset + 1] = (green << 2) | (green >> 4);
25
- colour[offset + 2] = (blue << 3) | (blue >> 2);
26
- colour[offset + 3] = 255;
27
-
28
- return value;
29
- }
30
-
31
- function DecompressColour(rgba: Uint8Array, block: Uint8Array, nOffset: number, isDxt1: boolean): void {
32
- const codes = new Uint8Array(16);
33
-
34
- const a = Unpack565(block[nOffset + 0], block[nOffset + 1], codes, 0);
35
- const b = Unpack565(block[nOffset + 2], block[nOffset + 3], codes, 4);
36
-
37
- for (let i = 0; i < 3; i++) {
38
- const c = codes[i];
39
- const d = codes[4 + i];
40
-
41
- if (isDxt1 && a <= b) {
42
- codes[8 + i] = (c + d) / 2;
43
- codes[12 + i] = 0;
44
- } else {
45
- codes[8 + i] = (2 * c + d) / 3;
46
- codes[12 + i] = (c + 2 * d) / 3;
47
- }
48
- }
49
-
50
- codes[8 + 3] = 255;
51
- codes[12 + 3] = isDxt1 && a <= b ? 0 : 255;
52
-
53
- const indices = new Uint8Array(16);
54
- for (let i = 0; i < 4; ++i) {
55
- const packed = block[nOffset + 4 + i];
56
-
57
- indices[4 * i + 0] = packed & 0x3;
58
- indices[4 * i + 1] = (packed >> 2) & 0x3;
59
- indices[4 * i + 2] = (packed >> 4) & 0x3;
60
- indices[4 * i + 3] = (packed >> 6) & 0x3;
61
- }
62
-
63
- for (let i = 0; i < 16; ++i) {
64
- const offset = 4 * indices[i];
65
- for (let j = 0; j < 4; ++j) rgba[4 * i + j] = codes[offset + j];
66
- }
67
- }
68
-
69
- function DecompressAlphaDxt3(rgba: Uint8Array, block: Uint8Array, nOffset: number): void {
70
- // unpack the alpha values pairwise
71
- for (let i = 0; i < 8; ++i) {
72
- // quantise down to 4 bits
73
- const quant = block[nOffset + i];
74
-
75
- // unpack the values
76
- const lo = quant & 0x0f;
77
- const hi = quant & 0xf0;
78
-
79
- // convert back up to bytes
80
- rgba[8 * i + 3] = lo | (lo << 4);
81
- rgba[8 * i + 7] = hi | (hi >> 4);
82
- }
83
- }
84
-
85
- function DecompressAlphaDxt5(rgba: Uint8Array, block: Uint8Array, start: number): void {
86
- const alpha0 = block[start + 0];
87
- const alpha1 = block[start + 1];
88
-
89
- const codes = new Uint8Array(8);
90
-
91
- codes[0] = alpha0;
92
- codes[1] = alpha1;
93
- if (alpha0 <= alpha1) {
94
- // use 5-alpha codebook
95
- for (let i = 1; i < 5; ++i) codes[1 + i] = ((5 - i) * alpha0 + i * alpha1) / 5;
96
- codes[6] = 0;
97
- codes[7] = 255;
98
- } else {
99
- // use 7-alpha codebook
100
- for (let i = 1; i < 7; ++i) codes[1 + i] = ((7 - i) * alpha0 + i * alpha1) / 7;
101
- }
102
-
103
- const indices = new Uint8Array(16);
104
- let nOffset = start + 2;
105
- let nBegin = 0;
106
- for (let i = 0; i < 2; ++i) {
107
- // grab 3 bytes
108
- let value = 0;
109
- for (let j = 0; j < 3; ++j) {
110
- const byte = block[nOffset++];
111
- value |= byte << (8 * j);
112
- }
113
-
114
- // unpack 8 3-bit values from it
115
- for (let j = 0; j < 8; ++j) {
116
- const index = (value >> (3 * j)) & 0x7;
117
- indices[nBegin++] = index;
118
- }
119
- }
120
-
121
- for (let i = 0; i < 16; ++i) rgba[4 * i + 3] = codes[indices[i]];
122
- }
123
-
124
- function Decompress(rgba: Uint8Array, block: Uint8Array, nOffset: number, flags: number): void {
125
- let nOffset2 = 0;
126
- if ((flags & (kDxt3 | kDxt5)) !== 0) nOffset2 = 8;
127
-
128
- DecompressColour(rgba, block, nOffset + nOffset2, (flags & kDxt1) !== 0);
129
-
130
- if ((flags & kDxt3) !== 0) {
131
- DecompressAlphaDxt3(rgba, block, nOffset);
132
- } else if ((flags & kDxt5) !== 0) {
133
- DecompressAlphaDxt5(rgba, block, nOffset);
134
- }
135
- }
136
-
137
- /** 把 block 视为 uint16 数组:DXT1 的 565 快路径需要按 16 位读 */
138
- function asU16(view: Uint8Array): Uint16Array {
139
- const start = view.byteOffset & ~1;
140
- const len = (view.byteLength + (view.byteOffset & 1)) >> 1;
141
- return new Uint16Array(view.buffer, start, len);
142
- }
143
-
144
- function DecompressImage565(rgb565: Uint16Array, width: number, height: number, blocks: Uint16Array): Uint16Array {
145
- const c = new Uint16Array(4);
146
- const dst = rgb565;
147
- let m = 0;
148
- let dstI = 0;
149
- let i = 0;
150
- let r0 = 0;
151
- let g0 = 0;
152
- let b0 = 0;
153
- let r1 = 0;
154
- let g1 = 0;
155
- let b1 = 0;
156
-
157
- const blockWidth = width / 4;
158
- const blockHeight = height / 4;
159
- for (let blockY = 0; blockY < blockHeight; blockY++) {
160
- for (let blockX = 0; blockX < blockWidth; blockX++) {
161
- i = 4 * ((blockHeight - blockY) * blockWidth + blockX);
162
- c[0] = blocks[i];
163
- c[1] = blocks[i + 1];
164
- r0 = c[0] & 0x1f;
165
- g0 = c[0] & 0x7e0;
166
- b0 = c[0] & 0xf800;
167
- r1 = c[1] & 0x1f;
168
- g1 = c[1] & 0x7e0;
169
- b1 = c[1] & 0xf800;
170
- // Interpolate between c0 and c1 to get c2 and c3.
171
- // 1/3 用 3/8 近似、2/3 用 5/8 近似 —— 这也是多数 GPU 硬件解码器的做法
172
- c[2] = ((5 * r0 + 3 * r1) >> 3) | (((5 * g0 + 3 * g1) >> 3) & 0x7e0) | (((5 * b0 + 3 * b1) >> 3) & 0xf800);
173
- c[3] = ((5 * r1 + 3 * r0) >> 3) | (((5 * g1 + 3 * g0) >> 3) & 0x7e0) | (((5 * b1 + 3 * b0) >> 3) & 0xf800);
174
- m = blocks[i + 2];
175
- dstI = blockY * 4 * width + blockX * 4;
176
- dst[dstI] = c[m & 0x3];
177
- dst[dstI + 1] = c[(m >> 2) & 0x3];
178
- dst[dstI + 2] = c[(m >> 4) & 0x3];
179
- dst[dstI + 3] = c[(m >> 6) & 0x3];
180
- dstI += width;
181
- dst[dstI] = c[(m >> 8) & 0x3];
182
- dst[dstI + 1] = c[(m >> 10) & 0x3];
183
- dst[dstI + 2] = c[(m >> 12) & 0x3];
184
- dst[dstI + 3] = c[(m >> 14) & 0x3];
185
- m = blocks[i + 3];
186
- dstI += width;
187
- dst[dstI] = c[m & 0x3];
188
- dst[dstI + 1] = c[(m >> 2) & 0x3];
189
- dst[dstI + 2] = c[(m >> 4) & 0x3];
190
- dst[dstI + 3] = c[(m >> 6) & 0x3];
191
- dstI += width;
192
- dst[dstI] = c[(m >> 8) & 0x3];
193
- dst[dstI + 1] = c[(m >> 10) & 0x3];
194
- dst[dstI + 2] = c[(m >> 12) & 0x3];
195
- dst[dstI + 3] = c[(m >> 14) & 0x3];
196
- }
197
- }
198
- return dst;
199
- }
200
-
201
- /**
202
- * 解压整张 DXT 图。
203
- *
204
- * 解出的像素按 `{ r1,g1,b1,a1, ... , rn,gn,bn,an }`(n = width*height)连续写入 `rgba`。
205
- */
206
- function DecompressImage(rgba: Uint8Array, width: number, height: number, blocks: Uint8Array, flags: number): void {
207
- const bytesPerBlock = (flags & kDxt1) !== 0 ? 8 : 16;
208
-
209
- let nOffset = 0;
210
- for (let y = 0; y < height; y += 4) {
211
- for (let x = 0; x < width; x += 4) {
212
- const targetRgba = new Uint8Array(4 * 16);
213
- Decompress(targetRgba, blocks, nOffset, flags);
214
-
215
- let nOffsetTarget = 0;
216
- for (let py = 0; py < 4; ++py) {
217
- for (let px = 0; px < 4; ++px) {
218
- const sx = x + px;
219
- const sy = y + py;
220
- if (sx < width && sy < height) {
221
- // flip Y
222
- let nBegin = 4 * (width * (height - sy) + sx);
223
-
224
- for (let i = 0; i < 4; ++i) rgba[nBegin++] = targetRgba[nOffsetTarget++];
225
- } else {
226
- nOffsetTarget += 4;
227
- }
228
- }
229
- }
230
-
231
- // advance
232
- nOffset += bytesPerBlock;
233
- }
234
- }
235
- }
236
-
237
- const DXTTextureDecode = {
238
- /**
239
- * @param out 输出缓冲,长度须为 width*height*4
240
- * @param width 像素宽
241
- * @param height 像素高
242
- * @param block 压缩块
243
- * @param format S3M pixelFormat(>11 或 5 走 DXT5,其余走 DXT1)
244
- */
245
- decode(out: Uint8Array, width: number, height: number, block: Uint8Array, format: number): void {
246
- if (out == null || block == null || height === 0 || width === 0) return;
247
-
248
- // 有 alpha 通道 → RGBA,否则走 rgb565
249
- // S3MPixelFormat.BGR -> 11 / LUMINANCE_ALPHA -> 5
250
- const flags = format > 11 || format === 5 ? kDxt5 : kDxt1 | krgb565;
251
-
252
- if (flags & kDxt1 && flags & krgb565) {
253
- DecompressImage565(asU16(out), width, height, asU16(block));
254
- } else {
255
- DecompressImage(out, width, height, block, flags);
256
- }
257
- },
258
- };
259
-
260
- export default DXTTextureDecode;
1
+ /**
2
+ * DXT1 / DXT3 / DXT5 纹理解码(squish 算法的 JS 移植)
3
+ *
4
+ * 来源:SuperMap iClient3D S3M SDK(Apache-2.0)。
5
+ * 迁移到 TS 时做了两件事,算法本身未改:
6
+ * 1. 补齐类型;
7
+ * 2. 修掉 `DecompressAlphaDxt3` 里把 `block` 误写成未定义全局 `bytes` 的笔误
8
+ * (DXT3 纹理此前会直接 ReferenceError)。
9
+ */
10
+
11
+ const kDxt1 = 1 << 0;
12
+ const kDxt3 = 1 << 1;
13
+ const kDxt5 = 1 << 2;
14
+ const krgb565 = 1 << 5;
15
+
16
+ function Unpack565(packed0: number, packed1: number, colour: Uint8Array, offset: number): number {
17
+ const value = packed0 | (packed1 << 8);
18
+
19
+ const red = (value >> 11) & 0x1f;
20
+ const green = (value >> 5) & 0x3f;
21
+ const blue = value & 0x1f;
22
+
23
+ colour[offset + 0] = (red << 3) | (red >> 2);
24
+ colour[offset + 1] = (green << 2) | (green >> 4);
25
+ colour[offset + 2] = (blue << 3) | (blue >> 2);
26
+ colour[offset + 3] = 255;
27
+
28
+ return value;
29
+ }
30
+
31
+ function DecompressColour(rgba: Uint8Array, block: Uint8Array, nOffset: number, isDxt1: boolean): void {
32
+ const codes = new Uint8Array(16);
33
+
34
+ const a = Unpack565(block[nOffset + 0], block[nOffset + 1], codes, 0);
35
+ const b = Unpack565(block[nOffset + 2], block[nOffset + 3], codes, 4);
36
+
37
+ for (let i = 0; i < 3; i++) {
38
+ const c = codes[i];
39
+ const d = codes[4 + i];
40
+
41
+ if (isDxt1 && a <= b) {
42
+ codes[8 + i] = (c + d) / 2;
43
+ codes[12 + i] = 0;
44
+ } else {
45
+ codes[8 + i] = (2 * c + d) / 3;
46
+ codes[12 + i] = (c + 2 * d) / 3;
47
+ }
48
+ }
49
+
50
+ codes[8 + 3] = 255;
51
+ codes[12 + 3] = isDxt1 && a <= b ? 0 : 255;
52
+
53
+ const indices = new Uint8Array(16);
54
+ for (let i = 0; i < 4; ++i) {
55
+ const packed = block[nOffset + 4 + i];
56
+
57
+ indices[4 * i + 0] = packed & 0x3;
58
+ indices[4 * i + 1] = (packed >> 2) & 0x3;
59
+ indices[4 * i + 2] = (packed >> 4) & 0x3;
60
+ indices[4 * i + 3] = (packed >> 6) & 0x3;
61
+ }
62
+
63
+ for (let i = 0; i < 16; ++i) {
64
+ const offset = 4 * indices[i];
65
+ for (let j = 0; j < 4; ++j) rgba[4 * i + j] = codes[offset + j];
66
+ }
67
+ }
68
+
69
+ function DecompressAlphaDxt3(rgba: Uint8Array, block: Uint8Array, nOffset: number): void {
70
+ // unpack the alpha values pairwise
71
+ for (let i = 0; i < 8; ++i) {
72
+ // quantise down to 4 bits
73
+ const quant = block[nOffset + i];
74
+
75
+ // unpack the values
76
+ const lo = quant & 0x0f;
77
+ const hi = quant & 0xf0;
78
+
79
+ // convert back up to bytes
80
+ rgba[8 * i + 3] = lo | (lo << 4);
81
+ rgba[8 * i + 7] = hi | (hi >> 4);
82
+ }
83
+ }
84
+
85
+ function DecompressAlphaDxt5(rgba: Uint8Array, block: Uint8Array, start: number): void {
86
+ const alpha0 = block[start + 0];
87
+ const alpha1 = block[start + 1];
88
+
89
+ const codes = new Uint8Array(8);
90
+
91
+ codes[0] = alpha0;
92
+ codes[1] = alpha1;
93
+ if (alpha0 <= alpha1) {
94
+ // use 5-alpha codebook
95
+ for (let i = 1; i < 5; ++i) codes[1 + i] = ((5 - i) * alpha0 + i * alpha1) / 5;
96
+ codes[6] = 0;
97
+ codes[7] = 255;
98
+ } else {
99
+ // use 7-alpha codebook
100
+ for (let i = 1; i < 7; ++i) codes[1 + i] = ((7 - i) * alpha0 + i * alpha1) / 7;
101
+ }
102
+
103
+ const indices = new Uint8Array(16);
104
+ let nOffset = start + 2;
105
+ let nBegin = 0;
106
+ for (let i = 0; i < 2; ++i) {
107
+ // grab 3 bytes
108
+ let value = 0;
109
+ for (let j = 0; j < 3; ++j) {
110
+ const byte = block[nOffset++];
111
+ value |= byte << (8 * j);
112
+ }
113
+
114
+ // unpack 8 3-bit values from it
115
+ for (let j = 0; j < 8; ++j) {
116
+ const index = (value >> (3 * j)) & 0x7;
117
+ indices[nBegin++] = index;
118
+ }
119
+ }
120
+
121
+ for (let i = 0; i < 16; ++i) rgba[4 * i + 3] = codes[indices[i]];
122
+ }
123
+
124
+ function Decompress(rgba: Uint8Array, block: Uint8Array, nOffset: number, flags: number): void {
125
+ let nOffset2 = 0;
126
+ if ((flags & (kDxt3 | kDxt5)) !== 0) nOffset2 = 8;
127
+
128
+ DecompressColour(rgba, block, nOffset + nOffset2, (flags & kDxt1) !== 0);
129
+
130
+ if ((flags & kDxt3) !== 0) {
131
+ DecompressAlphaDxt3(rgba, block, nOffset);
132
+ } else if ((flags & kDxt5) !== 0) {
133
+ DecompressAlphaDxt5(rgba, block, nOffset);
134
+ }
135
+ }
136
+
137
+ /** 把 block 视为 uint16 数组:DXT1 的 565 快路径需要按 16 位读 */
138
+ function asU16(view: Uint8Array): Uint16Array {
139
+ const start = view.byteOffset & ~1;
140
+ const len = (view.byteLength + (view.byteOffset & 1)) >> 1;
141
+ return new Uint16Array(view.buffer, start, len);
142
+ }
143
+
144
+ function DecompressImage565(rgb565: Uint16Array, width: number, height: number, blocks: Uint16Array): Uint16Array {
145
+ const c = new Uint16Array(4);
146
+ const dst = rgb565;
147
+ let m = 0;
148
+ let dstI = 0;
149
+ let i = 0;
150
+ let r0 = 0;
151
+ let g0 = 0;
152
+ let b0 = 0;
153
+ let r1 = 0;
154
+ let g1 = 0;
155
+ let b1 = 0;
156
+
157
+ const blockWidth = width / 4;
158
+ const blockHeight = height / 4;
159
+ for (let blockY = 0; blockY < blockHeight; blockY++) {
160
+ for (let blockX = 0; blockX < blockWidth; blockX++) {
161
+ i = 4 * ((blockHeight - blockY) * blockWidth + blockX);
162
+ c[0] = blocks[i];
163
+ c[1] = blocks[i + 1];
164
+ r0 = c[0] & 0x1f;
165
+ g0 = c[0] & 0x7e0;
166
+ b0 = c[0] & 0xf800;
167
+ r1 = c[1] & 0x1f;
168
+ g1 = c[1] & 0x7e0;
169
+ b1 = c[1] & 0xf800;
170
+ // Interpolate between c0 and c1 to get c2 and c3.
171
+ // 1/3 用 3/8 近似、2/3 用 5/8 近似 —— 这也是多数 GPU 硬件解码器的做法
172
+ c[2] = ((5 * r0 + 3 * r1) >> 3) | (((5 * g0 + 3 * g1) >> 3) & 0x7e0) | (((5 * b0 + 3 * b1) >> 3) & 0xf800);
173
+ c[3] = ((5 * r1 + 3 * r0) >> 3) | (((5 * g1 + 3 * g0) >> 3) & 0x7e0) | (((5 * b1 + 3 * b0) >> 3) & 0xf800);
174
+ m = blocks[i + 2];
175
+ dstI = blockY * 4 * width + blockX * 4;
176
+ dst[dstI] = c[m & 0x3];
177
+ dst[dstI + 1] = c[(m >> 2) & 0x3];
178
+ dst[dstI + 2] = c[(m >> 4) & 0x3];
179
+ dst[dstI + 3] = c[(m >> 6) & 0x3];
180
+ dstI += width;
181
+ dst[dstI] = c[(m >> 8) & 0x3];
182
+ dst[dstI + 1] = c[(m >> 10) & 0x3];
183
+ dst[dstI + 2] = c[(m >> 12) & 0x3];
184
+ dst[dstI + 3] = c[(m >> 14) & 0x3];
185
+ m = blocks[i + 3];
186
+ dstI += width;
187
+ dst[dstI] = c[m & 0x3];
188
+ dst[dstI + 1] = c[(m >> 2) & 0x3];
189
+ dst[dstI + 2] = c[(m >> 4) & 0x3];
190
+ dst[dstI + 3] = c[(m >> 6) & 0x3];
191
+ dstI += width;
192
+ dst[dstI] = c[(m >> 8) & 0x3];
193
+ dst[dstI + 1] = c[(m >> 10) & 0x3];
194
+ dst[dstI + 2] = c[(m >> 12) & 0x3];
195
+ dst[dstI + 3] = c[(m >> 14) & 0x3];
196
+ }
197
+ }
198
+ return dst;
199
+ }
200
+
201
+ /**
202
+ * 解压整张 DXT 图。
203
+ *
204
+ * 解出的像素按 `{ r1,g1,b1,a1, ... , rn,gn,bn,an }`(n = width*height)连续写入 `rgba`。
205
+ */
206
+ function DecompressImage(rgba: Uint8Array, width: number, height: number, blocks: Uint8Array, flags: number): void {
207
+ const bytesPerBlock = (flags & kDxt1) !== 0 ? 8 : 16;
208
+
209
+ let nOffset = 0;
210
+ for (let y = 0; y < height; y += 4) {
211
+ for (let x = 0; x < width; x += 4) {
212
+ const targetRgba = new Uint8Array(4 * 16);
213
+ Decompress(targetRgba, blocks, nOffset, flags);
214
+
215
+ let nOffsetTarget = 0;
216
+ for (let py = 0; py < 4; ++py) {
217
+ for (let px = 0; px < 4; ++px) {
218
+ const sx = x + px;
219
+ const sy = y + py;
220
+ if (sx < width && sy < height) {
221
+ // flip Y
222
+ let nBegin = 4 * (width * (height - sy) + sx);
223
+
224
+ for (let i = 0; i < 4; ++i) rgba[nBegin++] = targetRgba[nOffsetTarget++];
225
+ } else {
226
+ nOffsetTarget += 4;
227
+ }
228
+ }
229
+ }
230
+
231
+ // advance
232
+ nOffset += bytesPerBlock;
233
+ }
234
+ }
235
+ }
236
+
237
+ const DXTTextureDecode = {
238
+ /**
239
+ * @param out 输出缓冲,长度须为 width*height*4
240
+ * @param width 像素宽
241
+ * @param height 像素高
242
+ * @param block 压缩块
243
+ * @param format S3M pixelFormat(>11 或 5 走 DXT5,其余走 DXT1)
244
+ */
245
+ decode(out: Uint8Array, width: number, height: number, block: Uint8Array, format: number): void {
246
+ if (out == null || block == null || height === 0 || width === 0) return;
247
+
248
+ // 有 alpha 通道 → RGBA,否则走 rgb565
249
+ // S3MPixelFormat.BGR -> 11 / LUMINANCE_ALPHA -> 5
250
+ const flags = format > 11 || format === 5 ? kDxt5 : kDxt1 | krgb565;
251
+
252
+ if (flags & kDxt1 && flags & krgb565) {
253
+ DecompressImage565(asU16(out), width, height, asU16(block));
254
+ } else {
255
+ DecompressImage(out, width, height, block, flags);
256
+ }
257
+ },
258
+ };
259
+
260
+ export default DXTTextureDecode;