@woosh/meep-engine 2.33.2 → 2.33.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.
- package/core/bvh2/aabb3/AABB3.js +18 -0
- package/core/bvh2/aabb3/aabb3_intersects_frustum.js +38 -0
- package/core/collection/RingBuffer.js +40 -10
- package/core/collection/array/copyArray.js +2 -2
- package/core/collection/array/typed/typed_array_copy.js +2 -2
- package/core/collection/table/RowFirstTableSpec.js +8 -0
- package/core/geom/3d/aabb/aabb3_compute_projected_area.js +16 -14
- package/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +59 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +33 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +41 -0
- package/core/geom/3d/plane/plane3_lerp.js +2 -2
- package/core/geom/3d/topology/TopoTriangle.js +2 -2
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/Matrix4.js +4 -4
- package/core/geom/Vector3.js +5 -5
- package/core/model/reactive/model/terminal/ReactiveReference.js +7 -1
- package/core/process/undo/ActionProcessor.d.ts +2 -0
- package/core/process/undo/ActionProcessor.js +59 -1
- package/core/process/undo/ActionProcessor.spec.js +59 -0
- package/core/process/undo/Mark.js +2 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +3 -3
- package/engine/asset/loaders/material/TextureAttachmensByMaterialType.js +11 -1
- package/engine/asset/loaders/material/TextureAttachment.js +12 -1
- package/engine/asset/loaders/material/bitmap2sampler_gl.js +19 -0
- package/engine/asset/loaders/material/computeImageBitmapEquality.js +7 -19
- package/engine/asset/loaders/material/computeTextureEquality.js +1 -1
- package/engine/asset/loaders/material/computeTextureHash.js +16 -14
- package/engine/asset/loaders/material/traverseMaterialTextures.js +2 -2
- package/engine/ecs/animation/OneBoneSurfaceAlignmentSolver.js +2 -2
- package/engine/ecs/animation/TwoBoneInverseKinematicsSolver.js +4 -4
- package/engine/graphics/GraphicsEngine.d.ts +2 -2
- package/engine/graphics/GraphicsEngine.js +20 -62
- package/engine/graphics/filter/FlipArrayInPlace.js +25 -0
- package/engine/graphics/filter/FlipArrayViaCanvas.js +13 -0
- package/engine/graphics/filter/ImageFilter.js +20 -51
- package/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +2 -2
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +25 -16
- package/engine/graphics/material/SplatMaterial.js +4 -97
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +598 -0
- package/engine/graphics/micron/build/PatchRepresentation.js +4 -43
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +4 -75
- package/engine/graphics/micron/build/compute_buffer_geometry_byte_size.js +16 -0
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +2 -0
- package/engine/graphics/micron/format/MicronGeometryBufferAttributeSpec.js +1 -1
- package/engine/graphics/micron/format/MicronGeometryPatch.js +17 -5
- package/engine/graphics/micron/format/MicronVertexDataSpec.js +25 -3
- package/engine/graphics/micron/prototypeVirtualGeometry.js +19 -12
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +34 -27
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +2 -4
- package/engine/graphics/micron/render/instanced/PatchDataTextures.js +1 -0
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -29
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +43 -159
- package/engine/graphics/micron/render/refinement/ActivePatchRecord.js +4 -2
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +98 -0
- package/engine/graphics/micron/render/refinement/array_normalize_plane.js +25 -0
- package/engine/graphics/micron/render/refinement/array_setFromProjectionMatrix.js +60 -0
- package/engine/graphics/micron/render/refinement/is_patch_facing_back.js +43 -0
- package/engine/graphics/micron/render/refinement/is_patch_visible.js +37 -0
- package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +21 -0
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +12 -9
- package/engine/graphics/micron/util/unit_hemioct.spec.js +2 -2
- package/engine/graphics/render/buffer/buffers/ColorAndDepthFrameBuffer.js +5 -3
- package/engine/graphics/render/buffer/buffers/NormalFrameBuffer.js +12 -2
- package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +8 -10
- package/engine/graphics/render/forward_plus/LightManager.js +5 -7
- package/engine/graphics/render/forward_plus/data/NumericType.js +9 -0
- package/engine/graphics/render/forward_plus/{TextureBackedMemoryRegion.js → data/TextureBackedMemoryRegion.js} +11 -190
- package/engine/graphics/render/forward_plus/data/channelCountToThreIntegerTextureType.js +16 -0
- package/engine/graphics/render/forward_plus/data/computeDataType.js +36 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureFormat.js +18 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureInternalFormatFromDataType.js +63 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureTypeFromDataType.js +41 -0
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/engine/graphics/render/forward_plus/prototypeLightManager.js +1 -1
- package/engine/graphics/render/utils/ThreeBypassRenderer.js +1 -3
- package/engine/graphics/render/visibility/hiz/buffer/HierarchicalZBuffer.js +198 -0
- package/engine/graphics/render/visibility/hiz/buffer/ReductionShader.js +51 -0
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +179 -0
- package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +435 -0
- package/engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js +174 -0
- package/engine/graphics/render/visibility/hiz/query/QueryShader.js +173 -0
- package/engine/graphics/shadows/ShadowMapRenderer.js +12 -2
- package/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
- package/engine/graphics/texture/cubemap/buildCubeURLs.js +13 -0
- package/engine/graphics/texture/cubemap/load_environment_map.d.ts +8 -0
- package/engine/graphics/texture/cubemap/load_environment_map.js +163 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +18 -62
- package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +8 -4
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +3 -2
- package/engine/graphics/texture/sampler/differenceSampler.js +31 -0
- package/engine/graphics/texture/sampler/typedArrayConstructorByInstance.js +25 -0
- package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +3 -2
- package/engine/graphics/texture/virtual/v2/ShaderUsage.js +6 -5
- package/engine/graphics/texture/virtual/v2/prototype.js +16 -6
- package/package.json +1 -1
- package/view/elements/progress/segmented/SegmentedResourceBarView.js +50 -15
- package/view/minimap/gl/MinimapMarkersGL.js +2 -2
- package/engine/graphics/micron/render/RefinementSpec.js +0 -110
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
|
|
2
|
+
import { TextureAttachmentsByMaterialType } from "../../../asset/loaders/material/TextureAttachmensByMaterialType.js";
|
|
3
|
+
import { HashMap } from "../../../../core/collection/HashMap.js";
|
|
4
|
+
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
5
|
+
import { traverseMaterialTextures } from "../../../asset/loaders/material/traverseMaterialTextures.js";
|
|
6
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
7
|
+
import AABB2 from "../../../../core/geom/AABB2.js";
|
|
8
|
+
import { MaxRectanglesPacker } from "../../../../core/geom/packing/MaxRectangles.js";
|
|
9
|
+
import { Sampler2D } from "../../texture/sampler/Sampler2D.js";
|
|
10
|
+
import { array_push_if_unique } from "../../../../core/collection/array/array_push_if_unique.js";
|
|
11
|
+
import { computeMaterialHash } from "../../../asset/loaders/material/computeMaterialHash.js";
|
|
12
|
+
import { computeMaterialEquality } from "../../../asset/loaders/material/computeMaterialEquality.js";
|
|
13
|
+
import { collectIteratorValueToArray } from "../../../../core/collection/IteratorUtils.js";
|
|
14
|
+
import {
|
|
15
|
+
ClampToEdgeWrapping,
|
|
16
|
+
DataTexture,
|
|
17
|
+
LinearEncoding,
|
|
18
|
+
LinearFilter,
|
|
19
|
+
LinearMipmapLinearFilter,
|
|
20
|
+
Matrix3,
|
|
21
|
+
sRGBEncoding,
|
|
22
|
+
UnsignedByteType
|
|
23
|
+
} from "three";
|
|
24
|
+
import { convertTexture2Sampler2D } from "../../texture/sampler/convertTexture2Sampler2D.js";
|
|
25
|
+
|
|
26
|
+
const ATLAS_PATCH_BORDER = 4;
|
|
27
|
+
|
|
28
|
+
const BUFFER_GEOMETRY_UVS = [
|
|
29
|
+
{
|
|
30
|
+
name: 'uv',
|
|
31
|
+
index: 0,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'uv2',
|
|
35
|
+
index: 1
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
class TextureReference {
|
|
40
|
+
constructor() {
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @type {TextureAttachment|null}
|
|
44
|
+
*/
|
|
45
|
+
this.attachment = null;
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {THREE.Material|null}
|
|
49
|
+
*/
|
|
50
|
+
this.material = null;
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {THREE.Texture|null}
|
|
54
|
+
*/
|
|
55
|
+
this.source_texture = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param {THREE.Mesh} mesh
|
|
62
|
+
* @returns {boolean}
|
|
63
|
+
*/
|
|
64
|
+
function is_compliant_mesh(mesh) {
|
|
65
|
+
const material = mesh.material;
|
|
66
|
+
|
|
67
|
+
const attachments = TextureAttachmentsByMaterialType[material.type];
|
|
68
|
+
|
|
69
|
+
const uv_scales = [1, 1, 1, 1];
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
72
|
+
const attachment = attachments[i];
|
|
73
|
+
|
|
74
|
+
const texture = attachment.read(material);
|
|
75
|
+
if (texture === undefined || texture === null) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const uv_index = attachment.uv_index;
|
|
80
|
+
|
|
81
|
+
uv_scales[uv_index * 2] = max2(uv_scales[uv_index * 2], texture.repeat.x)
|
|
82
|
+
uv_scales[uv_index * 2 + 1] = max2(uv_scales[uv_index * 2 + 1], texture.repeat.y)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const geometry = mesh.geometry;
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < BUFFER_GEOMETRY_UVS.length; i++) {
|
|
88
|
+
const uv_metadata = BUFFER_GEOMETRY_UVS[i];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @type {THREE.BufferAttribute }
|
|
93
|
+
*/
|
|
94
|
+
const attribute = geometry.attributes[uv_metadata.name];
|
|
95
|
+
|
|
96
|
+
if (attribute === undefined) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const attribute_data = attribute.array;
|
|
101
|
+
const n = attribute_data.length;
|
|
102
|
+
|
|
103
|
+
const uv_index = uv_metadata.index;
|
|
104
|
+
const uv_index_2 = uv_index * 2;
|
|
105
|
+
|
|
106
|
+
for (let j = 0; j < n; j += 2) {
|
|
107
|
+
const x = attribute_data[j];
|
|
108
|
+
const y = attribute_data[j + 1];
|
|
109
|
+
|
|
110
|
+
const scaled_u = x * uv_scales[uv_index_2];
|
|
111
|
+
const scaled_v = y * uv_scales[uv_index_2 + 1];
|
|
112
|
+
|
|
113
|
+
if (scaled_u > 1 || scaled_u < 0 || scaled_v > 1 || scaled_v < 0) {
|
|
114
|
+
// repeating/negative UV value
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
class UvContext {
|
|
126
|
+
constructor() {
|
|
127
|
+
|
|
128
|
+
this.resolution = new Vector2(1, 1);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
* @type {AABB2}
|
|
133
|
+
*/
|
|
134
|
+
this.atlas_patch = new AABB2();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
*
|
|
140
|
+
* @param {Texture} texture
|
|
141
|
+
* @param {string} attachment_name
|
|
142
|
+
*/
|
|
143
|
+
function prepare_atlas_texture(texture, attachment_name) {
|
|
144
|
+
|
|
145
|
+
switch (attachment_name) {
|
|
146
|
+
case 'diffuse':
|
|
147
|
+
texture.encoding = sRGBEncoding;
|
|
148
|
+
break;
|
|
149
|
+
default:
|
|
150
|
+
texture.encoding = LinearEncoding;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
texture.minFilter = LinearMipmapLinearFilter;
|
|
154
|
+
texture.magFilter = LinearFilter;
|
|
155
|
+
|
|
156
|
+
texture.generateMipmaps = true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class MaterialDescriptor {
|
|
161
|
+
constructor() {
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
*
|
|
165
|
+
* @type {THREE.Material|null}
|
|
166
|
+
*/
|
|
167
|
+
this.source_material = null;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
* @type {UvContext[]}
|
|
172
|
+
*/
|
|
173
|
+
this.uvs = [];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
build_uvs() {
|
|
177
|
+
|
|
178
|
+
traverseMaterialTextures(this.source_material, (t, attachment) => {
|
|
179
|
+
const uv_index = attachment.uv_index;
|
|
180
|
+
|
|
181
|
+
let uv_context = this.uvs[uv_index];
|
|
182
|
+
|
|
183
|
+
if (uv_context === undefined) {
|
|
184
|
+
uv_context = new UvContext();
|
|
185
|
+
uv_context.resolution.set(1, 1);
|
|
186
|
+
|
|
187
|
+
this.uvs[uv_index] = uv_context;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const image = t.image;
|
|
191
|
+
|
|
192
|
+
if (image !== undefined && image.width !== undefined) {
|
|
193
|
+
uv_context.resolution.x = max2(uv_context.resolution.x, image.width);
|
|
194
|
+
uv_context.resolution.y = max2(uv_context.resolution.y, image.height);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export class MaterialOptimizationContext {
|
|
204
|
+
constructor() {
|
|
205
|
+
/**
|
|
206
|
+
*
|
|
207
|
+
* @type {THREE.Texture[]}
|
|
208
|
+
*/
|
|
209
|
+
this.textures = [];
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
*
|
|
213
|
+
* @type {THREE.Mesh[]}
|
|
214
|
+
*/
|
|
215
|
+
this.meshes = [];
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
*
|
|
220
|
+
* @type {Map<string,Sampler2D>}
|
|
221
|
+
*/
|
|
222
|
+
this.atlases = new Map();
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
*
|
|
226
|
+
* @type {Vector2[]}
|
|
227
|
+
*/
|
|
228
|
+
this.atlas_size = [];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
*
|
|
233
|
+
* @param {MaterialDescriptor[]} materials
|
|
234
|
+
*/
|
|
235
|
+
pack_atlas(materials) {
|
|
236
|
+
const uv_indices = [];
|
|
237
|
+
// figure out UV sets
|
|
238
|
+
materials.forEach(m => {
|
|
239
|
+
for (let i = 0; i < m.uvs.length; i++) {
|
|
240
|
+
if (m.uvs[i] !== undefined) {
|
|
241
|
+
array_push_if_unique(uv_indices, i);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
for (let i = 0; i < uv_indices.length; i++) {
|
|
247
|
+
const uv_index = uv_indices[i];
|
|
248
|
+
|
|
249
|
+
const packer = new MaxRectanglesPacker(1, 1);
|
|
250
|
+
|
|
251
|
+
let pow_x = 0;
|
|
252
|
+
let pow_y = 0;
|
|
253
|
+
|
|
254
|
+
const uv_relevant_materials = materials.filter(d => d.uvs[uv_index] !== undefined);
|
|
255
|
+
|
|
256
|
+
const rectangles = uv_relevant_materials.map(d => {
|
|
257
|
+
const uv_context = d.uvs[uv_index];
|
|
258
|
+
|
|
259
|
+
const resolution = uv_context.resolution;
|
|
260
|
+
|
|
261
|
+
return new AABB2(0, 0, resolution.x + ATLAS_PATCH_BORDER * 2, resolution.y + ATLAS_PATCH_BORDER * 2);
|
|
262
|
+
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
let cycle_index = 0;
|
|
266
|
+
|
|
267
|
+
while (!packer.addMany(rectangles)) {
|
|
268
|
+
cycle_index++;
|
|
269
|
+
|
|
270
|
+
if (cycle_index % 2 !== 0) {
|
|
271
|
+
pow_x++;
|
|
272
|
+
} else {
|
|
273
|
+
pow_y++;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const size_x = Math.pow(2, pow_x);
|
|
277
|
+
const size_y = Math.pow(2, pow_y);
|
|
278
|
+
|
|
279
|
+
const max_texture_size = MaterialOptimizationContext.MAX_TEXTURE_SIZE;
|
|
280
|
+
|
|
281
|
+
if (size_x > max_texture_size || size_y > max_texture_size) {
|
|
282
|
+
throw new Error(`Maximum texture size exceeded '${max_texture_size}'`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
packer.resize(size_x, size_y);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
this.atlas_size[uv_index] = packer.size.clone();
|
|
289
|
+
|
|
290
|
+
// all packed, write back bounds
|
|
291
|
+
rectangles.forEach((r, i) => {
|
|
292
|
+
const materialDescriptor = uv_relevant_materials[i];
|
|
293
|
+
|
|
294
|
+
const p = materialDescriptor.uvs[uv_index].atlas_patch;
|
|
295
|
+
|
|
296
|
+
p.set(r.x0 + ATLAS_PATCH_BORDER, r.y0 + ATLAS_PATCH_BORDER, r.x1 - ATLAS_PATCH_BORDER, r.y1 - ATLAS_PATCH_BORDER);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
*
|
|
303
|
+
* @param {MaterialDescriptor[]} materials
|
|
304
|
+
*/
|
|
305
|
+
build_atlas_samplers(materials) {
|
|
306
|
+
|
|
307
|
+
this.atlases.clear();
|
|
308
|
+
|
|
309
|
+
const names = [];
|
|
310
|
+
const uv_indices = [];
|
|
311
|
+
|
|
312
|
+
for (let i = 0; i < materials.length; i++) {
|
|
313
|
+
const material = materials[i];
|
|
314
|
+
|
|
315
|
+
const source_material = material.source_material;
|
|
316
|
+
const materialType = source_material.type;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
*
|
|
320
|
+
* @type {TextureAttachment[]}
|
|
321
|
+
*/
|
|
322
|
+
const attachments = TextureAttachmentsByMaterialType[materialType];
|
|
323
|
+
|
|
324
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
325
|
+
const attachment = attachments[i];
|
|
326
|
+
|
|
327
|
+
if (array_push_if_unique(names, attachment.name)) {
|
|
328
|
+
// added
|
|
329
|
+
uv_indices[names.length - 1] = attachment.uv_index;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
for (let i = 0; i < names.length; i++) {
|
|
336
|
+
const name = names[i];
|
|
337
|
+
const uv_index = uv_indices[i];
|
|
338
|
+
|
|
339
|
+
const size = this.atlas_size[uv_index];
|
|
340
|
+
|
|
341
|
+
this.atlases.set(name, Sampler2D.uint8(4, size.x, size.y));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
*
|
|
347
|
+
* @param {MaterialDescriptor} material
|
|
348
|
+
*/
|
|
349
|
+
write_material_to_atlas(material) {
|
|
350
|
+
//patch textures
|
|
351
|
+
const source_material = material.source_material;
|
|
352
|
+
const materialType = source_material.type;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
*
|
|
356
|
+
* @type {TextureAttachment[]}
|
|
357
|
+
*/
|
|
358
|
+
const attachments = TextureAttachmentsByMaterialType[materialType];
|
|
359
|
+
|
|
360
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
361
|
+
const attachment = attachments[i];
|
|
362
|
+
|
|
363
|
+
const uv_context = material.uvs[attachment.uv_index];
|
|
364
|
+
|
|
365
|
+
if (uv_context === undefined) {
|
|
366
|
+
// material does not participate in this UV set
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
let source_sampler;
|
|
371
|
+
|
|
372
|
+
const texture = attachment.read(source_material);
|
|
373
|
+
|
|
374
|
+
const texture_width = uv_context.resolution.x;
|
|
375
|
+
const texture_height = uv_context.resolution.y;
|
|
376
|
+
if (texture !== undefined && texture !== null) {
|
|
377
|
+
// source_sampler = Sampler2D.uint8(5, texture_width, texture_height);
|
|
378
|
+
//
|
|
379
|
+
// source_sampler.fill(0, 0, texture_width, texture_height, [255, 255, 255, 255]);
|
|
380
|
+
|
|
381
|
+
source_sampler = convertTexture2Sampler2D(texture, texture_width, texture_height, false);
|
|
382
|
+
} else {
|
|
383
|
+
// TODO proper defaults when a texture is missing
|
|
384
|
+
source_sampler = Sampler2D.uint8(4, texture_width, texture_height);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const atlas = this.atlases.get(attachment.name);
|
|
388
|
+
|
|
389
|
+
const patch = uv_context.atlas_patch;
|
|
390
|
+
|
|
391
|
+
atlas.copy_sameItemSize(
|
|
392
|
+
source_sampler,
|
|
393
|
+
0, 0,
|
|
394
|
+
patch.x0, patch.y0, patch.getWidth(), patch.getHeight()
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
*
|
|
401
|
+
* @param {THREE.Mesh} mesh
|
|
402
|
+
*/
|
|
403
|
+
addMesh(mesh) {
|
|
404
|
+
const material = mesh.material;
|
|
405
|
+
|
|
406
|
+
if (material.isMeshStandardMaterial) {
|
|
407
|
+
this.meshes.push(mesh);
|
|
408
|
+
} else {
|
|
409
|
+
throw new Error(`Unsupported material type '${material.type}'`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
*
|
|
415
|
+
* @param {THREE.Object} o
|
|
416
|
+
*/
|
|
417
|
+
addObject(o) {
|
|
418
|
+
traverseThreeObject(o, (o) => {
|
|
419
|
+
if (o.isMesh) {
|
|
420
|
+
this.addMesh(o);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Update materials and geometries
|
|
427
|
+
*/
|
|
428
|
+
update() {
|
|
429
|
+
// collect unique materials and their geometries
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
*
|
|
433
|
+
* @type {Map<MaterialDescriptor, THREE.BufferGeometry[]>}
|
|
434
|
+
*/
|
|
435
|
+
const material_to_geometry_map = new Map();
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
*
|
|
439
|
+
* @type {Map<MaterialDescriptor, THREE.Mesh[]>}
|
|
440
|
+
*/
|
|
441
|
+
const material_to_mesh_map = new Map();
|
|
442
|
+
|
|
443
|
+
const unique_materials = new HashMap({
|
|
444
|
+
keyHashFunction: computeMaterialHash,
|
|
445
|
+
keyEqualityFunction: computeMaterialEquality
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const input_meshes = this.meshes;
|
|
449
|
+
const input_mesh_count = input_meshes.length;
|
|
450
|
+
|
|
451
|
+
for (let i = 0; i < input_mesh_count; i++) {
|
|
452
|
+
const mesh = input_meshes[i];
|
|
453
|
+
|
|
454
|
+
if (!is_compliant_mesh(mesh)) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const material = mesh.material;
|
|
459
|
+
|
|
460
|
+
let material_descriptor = unique_materials.get(material);
|
|
461
|
+
|
|
462
|
+
if (material_descriptor === undefined) {
|
|
463
|
+
material_descriptor = new MaterialDescriptor();
|
|
464
|
+
material_descriptor.source_material = material;
|
|
465
|
+
|
|
466
|
+
material_descriptor.build_uvs();
|
|
467
|
+
|
|
468
|
+
unique_materials.set(material, material_descriptor);
|
|
469
|
+
|
|
470
|
+
material_to_geometry_map.set(material_descriptor, []);
|
|
471
|
+
material_to_mesh_map.set(material_descriptor, []);
|
|
472
|
+
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const geometries = material_to_geometry_map.get(material_descriptor);
|
|
476
|
+
|
|
477
|
+
array_push_if_unique(geometries, mesh.geometry);
|
|
478
|
+
|
|
479
|
+
const mesh_bucket = material_to_mesh_map.get(material_descriptor);
|
|
480
|
+
mesh_bucket.push(mesh);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// collect materials
|
|
484
|
+
/**
|
|
485
|
+
*
|
|
486
|
+
* @type {MaterialDescriptor[]}
|
|
487
|
+
*/
|
|
488
|
+
const unique_material_array = [];
|
|
489
|
+
collectIteratorValueToArray(unique_material_array, unique_materials.values());
|
|
490
|
+
|
|
491
|
+
if (unique_material_array.length <= 4) {
|
|
492
|
+
// no point in atlasing
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
this.pack_atlas(unique_material_array);
|
|
497
|
+
|
|
498
|
+
this.build_atlas_samplers(unique_material_array);
|
|
499
|
+
|
|
500
|
+
const textures = new Map();
|
|
501
|
+
//build new textures
|
|
502
|
+
for (const [name, sampler] of this.atlases) {
|
|
503
|
+
const texture = new DataTexture();
|
|
504
|
+
|
|
505
|
+
texture.image = {
|
|
506
|
+
data: sampler.data,
|
|
507
|
+
width: sampler.width,
|
|
508
|
+
height: sampler.height
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
texture.wrapS = ClampToEdgeWrapping;
|
|
512
|
+
texture.wrapT = ClampToEdgeWrapping;
|
|
513
|
+
texture.type = UnsignedByteType;
|
|
514
|
+
texture.anisotropy = 4;
|
|
515
|
+
|
|
516
|
+
prepare_atlas_texture(texture, name);
|
|
517
|
+
|
|
518
|
+
textures.set(name, texture);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
for (let i = 0; i < unique_material_array.length; i++) {
|
|
522
|
+
const mat = unique_material_array[i];
|
|
523
|
+
|
|
524
|
+
this.write_material_to_atlas(mat);
|
|
525
|
+
|
|
526
|
+
// get all associated geometries
|
|
527
|
+
const geometries = material_to_geometry_map.get(mat);
|
|
528
|
+
|
|
529
|
+
for (let j = 0; j < geometries.length; j++) {
|
|
530
|
+
const bufferGeometry = geometries[j];
|
|
531
|
+
|
|
532
|
+
for (let k = 0; k < BUFFER_GEOMETRY_UVS.length; k++) {
|
|
533
|
+
const uv_metadata = BUFFER_GEOMETRY_UVS[k];
|
|
534
|
+
|
|
535
|
+
// update UVs
|
|
536
|
+
const uv_attribute = bufferGeometry.attributes[uv_metadata.name];
|
|
537
|
+
|
|
538
|
+
if (uv_attribute === undefined) {
|
|
539
|
+
// no UVs, nothing to update
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
const uv_index = uv_metadata.index;
|
|
545
|
+
const uv_context = mat.uvs[uv_index];
|
|
546
|
+
|
|
547
|
+
if (uv_context === undefined) {
|
|
548
|
+
// no UV context present
|
|
549
|
+
// TODO need to force context to exist in this case or remove the attribute
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
const atlas_size = this.atlas_size[uv_index];
|
|
554
|
+
|
|
555
|
+
const atlas_width = atlas_size.x;
|
|
556
|
+
const atlas_height = atlas_size.y;
|
|
557
|
+
|
|
558
|
+
const patch = uv_context.atlas_patch;
|
|
559
|
+
|
|
560
|
+
const matrix3 = new Matrix3();
|
|
561
|
+
matrix3.setUvTransform(
|
|
562
|
+
patch.x0 / atlas_width,
|
|
563
|
+
patch.y0 / atlas_height,
|
|
564
|
+
patch.getWidth() / atlas_width,
|
|
565
|
+
patch.getHeight() / atlas_height,
|
|
566
|
+
0,
|
|
567
|
+
0, 0
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
uv_attribute.applyMatrix3(matrix3);
|
|
571
|
+
|
|
572
|
+
uv_attribute.needsUpdate = true;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// build material
|
|
577
|
+
const new_material = mat.source_material.clone();
|
|
578
|
+
|
|
579
|
+
traverseMaterialTextures(new_material, (old_texture, attachment) => {
|
|
580
|
+
attachment.write(new_material, textures.get(attachment.name));
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
// set new material to all associated meshes
|
|
584
|
+
const meshes = material_to_mesh_map.get(mat);
|
|
585
|
+
for (let j = 0; j < meshes.length; j++) {
|
|
586
|
+
const mesh = meshes[j];
|
|
587
|
+
mesh.material = new_material;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
*
|
|
596
|
+
* @type {number}
|
|
597
|
+
*/
|
|
598
|
+
MaterialOptimizationContext.MAX_TEXTURE_SIZE = 4096;
|
|
@@ -397,9 +397,11 @@ export class PatchRepresentation {
|
|
|
397
397
|
result.polygon_count = topology.getFaces().size;
|
|
398
398
|
|
|
399
399
|
// copy bounding_box
|
|
400
|
-
|
|
400
|
+
this.bounding_box.writeToArray(result.bounding_box, 0);
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
this.group_aabb.writeToArray(result.group_bounding_box, 0);
|
|
403
|
+
|
|
404
|
+
this.group_aabb.getCorners(result.group_bounding_box_corners);
|
|
403
405
|
|
|
404
406
|
vec4.copy(result.group_bounding_sphere, this.group_bounding_sphere);
|
|
405
407
|
|
|
@@ -414,45 +416,4 @@ export class PatchRepresentation {
|
|
|
414
416
|
// optimize index buffer for better caching
|
|
415
417
|
meshopt_optimizeVertexCache(result.face_indices, result.face_indices, result.face_indices.length, result.vertex_count);
|
|
416
418
|
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
*
|
|
420
|
-
* @param {THREE.BufferGeometry} source_geometry
|
|
421
|
-
* @param {MicronVertexDataSpec} vertex_data_spec
|
|
422
|
-
* @returns {MicronGeometryPatch}
|
|
423
|
-
*/
|
|
424
|
-
buildGeometryPatch(source_geometry, vertex_data_spec) {
|
|
425
|
-
|
|
426
|
-
const result = new MicronGeometryPatch();
|
|
427
|
-
|
|
428
|
-
this.buildMicronGeometryPatch(result, source_geometry, vertex_data_spec);
|
|
429
|
-
|
|
430
|
-
// patch children
|
|
431
|
-
result.children = [];
|
|
432
|
-
|
|
433
|
-
const rep_children = this.children;
|
|
434
|
-
const child_count = rep_children.length;
|
|
435
|
-
|
|
436
|
-
for (let i = 0; i < child_count; i++) {
|
|
437
|
-
const child = rep_children[i];
|
|
438
|
-
|
|
439
|
-
const child_patch = child.buildGeometryPatch(source_geometry, vertex_data_spec);
|
|
440
|
-
|
|
441
|
-
child_patch.parent = result;
|
|
442
|
-
|
|
443
|
-
result.children[i] = child_patch;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// write dependencies
|
|
447
|
-
result.dependencies = [];
|
|
448
|
-
|
|
449
|
-
const rep_dependencies = this.dependencies;
|
|
450
|
-
const dependency_count = rep_dependencies.length;
|
|
451
|
-
for (let i = 0; i < dependency_count; i++) {
|
|
452
|
-
const rep_dep = rep_dependencies[i];
|
|
453
|
-
result.dependencies.push(rep_dep.id);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
return result;
|
|
457
|
-
}
|
|
458
419
|
}
|