@woosh/meep-engine 2.33.62 → 2.33.67
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/FilePath.js +28 -2
- package/core/binary/BinaryBuffer.js +13 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +3 -2
- package/ecs/grid/pick.js +44 -0
- package/editor/tools/GridPaintTool.js +1 -1
- package/editor/tools/paint/TerrainPaintTool.js +1 -1
- package/editor/view/GridPickCoordinateView.js +1 -1
- package/engine/asset/AssetManager.js +1 -1
- package/engine/asset/AssetTransformer.js +2 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +5 -21
- package/engine/asset/loaders/async_traverse_three_object.js +24 -0
- package/engine/ecs/attachment/AttachmentSystem.js +3 -51
- package/engine/ecs/fow/FogOfWarRevealerSystem.js +1 -1
- package/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +2 -10
- package/engine/ecs/grid/NormalMap2AOMap.js +10 -13
- package/engine/ecs/team/Team.js +82 -0
- package/engine/ecs/terrain/ecs/BuildLightTexture.js +106 -0
- package/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +59 -0
- package/engine/ecs/terrain/ecs/Terrain.js +14 -153
- package/engine/ecs/tooltip/TooltipComponentSystem.js +1 -1
- package/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +10 -0
- package/engine/graphics/filter/ImageFilter.js +6 -2
- package/engine/graphics/geometry/AttributeSpec.d.ts +8 -0
- package/engine/graphics/geometry/VertexDataSpec.d.ts +15 -0
- package/engine/graphics/geometry/buffered/deinterleaveBufferAttribute.js +39 -0
- package/engine/graphics/geometry/buffered/deinterleaveBufferGeometry.js +50 -0
- package/engine/graphics/micron/MICRON_GEOMETRY_FIELD.js +1 -0
- package/engine/graphics/micron/MICRON_URI_FIELD.js +1 -0
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +10 -7
- package/engine/graphics/micron/convert_three_object_to_micron.js +31 -5
- package/engine/graphics/micron/format/MicronGeometry.d.ts +4 -0
- package/engine/graphics/micron/format/MicronGeometry.js +6 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +110 -6
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +4 -2
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/engine/graphics/render/webgpu/sample/MeshInstance.js +21 -0
- package/engine/graphics/render/webgpu/sample/main.js +2 -2
- package/engine/graphics/shaders/AmbientOcclusionShader.js +57 -77
- package/engine/graphics/shaders/DenoiseShader.js +119 -0
- package/engine/graphics/texture/noise_octaves.js +33 -0
- package/engine/graphics/texture/sampler/Sampler2D2Texture.js +7 -18
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +8 -5
- package/engine/graphics/texture/sampler/sampler2DToFloat32Texture.js +10 -3
- package/engine/graphics/util/modelHitTest.js +63 -0
- package/generation/example/filters/SampleGroundMoistureFilter.js +2 -1
- package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +29 -13
- package/generation/grid/GridData.js +17 -2
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
2
|
+
import { deserializeTexture } from "../../../graphics/texture/sampler/TextureBinaryBufferSerializer.js";
|
|
3
|
+
import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
|
|
4
|
+
import { GameAssetType } from "../../../asset/GameAssetType.js";
|
|
5
|
+
import rgbaData2valueSampler2D from "../../../graphics/texture/sampler/rgbaData2valueSampler2D.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param zRange
|
|
10
|
+
* @param heightMapURL
|
|
11
|
+
* @param {AssetManager} assetManager
|
|
12
|
+
* @returns {Promise<any>}
|
|
13
|
+
*/
|
|
14
|
+
export function promiseSamplerHeight(zRange, heightMapURL, assetManager) {
|
|
15
|
+
return new Promise(function (fulfill, reject) {
|
|
16
|
+
|
|
17
|
+
function assetObtained(asset) {
|
|
18
|
+
const array = asset.create();
|
|
19
|
+
|
|
20
|
+
const binaryBuffer = new BinaryBuffer();
|
|
21
|
+
//
|
|
22
|
+
// binaryBuffer.writeUint32(2560);
|
|
23
|
+
// binaryBuffer.writeUint32(2560);
|
|
24
|
+
//
|
|
25
|
+
// binaryBuffer.writeUint8(1);
|
|
26
|
+
//
|
|
27
|
+
// binaryBuffer.writeUint8(6);
|
|
28
|
+
|
|
29
|
+
binaryBuffer.writeBytes(new Uint8Array(array), 0, array.length);
|
|
30
|
+
|
|
31
|
+
binaryBuffer.position = 0;
|
|
32
|
+
|
|
33
|
+
const sampler2D = deserializeTexture(binaryBuffer);
|
|
34
|
+
fulfill(sampler2D);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if (heightMapURL === undefined) {
|
|
39
|
+
console.warn('Height map is not specified');
|
|
40
|
+
const defaultSampler = new Sampler2D(new Uint8Array(1), 1, 1, 1);
|
|
41
|
+
fulfill(defaultSampler);
|
|
42
|
+
} else if (heightMapURL.endsWith('.bin')) {
|
|
43
|
+
//load texture from a binary file
|
|
44
|
+
assetManager.get(heightMapURL, GameAssetType.ArrayBuffer, assetObtained, reject);
|
|
45
|
+
} else {
|
|
46
|
+
assetManager.get(heightMapURL, GameAssetType.Image, function (asset) {
|
|
47
|
+
const image = asset.create();
|
|
48
|
+
|
|
49
|
+
// plane
|
|
50
|
+
const imgWidth = image.width;
|
|
51
|
+
const imgHeight = image.height;
|
|
52
|
+
|
|
53
|
+
const samplerHeight = rgbaData2valueSampler2D(image.data, imgWidth, imgHeight, zRange, -zRange / 2);
|
|
54
|
+
|
|
55
|
+
fulfill(samplerHeight);
|
|
56
|
+
}, reject);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -14,9 +14,6 @@ import {
|
|
|
14
14
|
} from 'three';
|
|
15
15
|
import { clamp } from "../../../../core/math/clamp.js";
|
|
16
16
|
import { Sampler2D } from '../../../graphics/texture/sampler/Sampler2D.js';
|
|
17
|
-
import heightMap2NormalMap from '../../grid/HeightMap2NormalMap.js';
|
|
18
|
-
import normalMap2AOMap from '../../grid/NormalMap2AOMap.js';
|
|
19
|
-
import rgbaData2valueSampler2D from '../../../graphics/texture/sampler/rgbaData2valueSampler2D.js';
|
|
20
17
|
import { BinaryNode } from '../../../../core/bvh2/BinaryNode.js';
|
|
21
18
|
import Vector2 from '../../../../core/geom/Vector2.js';
|
|
22
19
|
import { TerrainOverlay } from '../overlay/TerrainOverlay.js';
|
|
@@ -24,13 +21,9 @@ import { TerrainOverlay } from '../overlay/TerrainOverlay.js';
|
|
|
24
21
|
import Clouds from '../TerrainClouds.js';
|
|
25
22
|
|
|
26
23
|
import TerrainTileManager from '../tiles/TerrainTileManager.js';
|
|
27
|
-
import { WebGLRendererPool } from "../../../graphics/render/RendererPool.js";
|
|
28
|
-
import { deserializeTexture } from "../../../graphics/texture/sampler/TextureBinaryBufferSerializer.js";
|
|
29
|
-
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
30
24
|
import { TerrainPreview } from "../TerrainPreview.js";
|
|
31
25
|
import { assert } from "../../../../core/assert.js";
|
|
32
26
|
import { GameAssetType } from "../../../asset/GameAssetType.js";
|
|
33
|
-
import { writeSample2DDataToDataTexture } from "../../../graphics/texture/sampler/writeSampler2DDataToDataTexture.js";
|
|
34
27
|
import { TerrainLayers } from "./layers/TerrainLayers.js";
|
|
35
28
|
import { SplatMaterial } from "../../../graphics/material/SplatMaterial.js";
|
|
36
29
|
import { loadLegacyTerrainSplats, SplatMapping } from "./splat/SplatMapping.js";
|
|
@@ -41,147 +34,8 @@ import { MeepSettings } from "../../../MeepSettings.js";
|
|
|
41
34
|
import { loadLegacyTerrainLayers } from "./layers/loadLegacyTerrainLayers.js";
|
|
42
35
|
import { TerrainFlags } from "./TerrainFlags.js";
|
|
43
36
|
import { IllegalStateException } from "../../../../core/fsm/exceptions/IllegalStateException.js";
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
* @param zRange
|
|
48
|
-
* @param heightMapURL
|
|
49
|
-
* @param {AssetManager} assetManager
|
|
50
|
-
* @returns {Promise<any>}
|
|
51
|
-
*/
|
|
52
|
-
function promiseSamplerHeight(zRange, heightMapURL, assetManager) {
|
|
53
|
-
return new Promise(function (fulfill, reject) {
|
|
54
|
-
|
|
55
|
-
function assetObtained(asset) {
|
|
56
|
-
const array = asset.create();
|
|
57
|
-
|
|
58
|
-
const binaryBuffer = new BinaryBuffer();
|
|
59
|
-
//
|
|
60
|
-
// binaryBuffer.writeUint32(2560);
|
|
61
|
-
// binaryBuffer.writeUint32(2560);
|
|
62
|
-
//
|
|
63
|
-
// binaryBuffer.writeUint8(1);
|
|
64
|
-
//
|
|
65
|
-
// binaryBuffer.writeUint8(6);
|
|
66
|
-
|
|
67
|
-
binaryBuffer.writeBytes(new Uint8Array(array), 0, array.length);
|
|
68
|
-
|
|
69
|
-
binaryBuffer.position = 0;
|
|
70
|
-
|
|
71
|
-
const sampler2D = deserializeTexture(binaryBuffer);
|
|
72
|
-
fulfill(sampler2D);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (heightMapURL === undefined) {
|
|
77
|
-
console.warn('Height map is not specified');
|
|
78
|
-
const defaultSampler = new Sampler2D(new Uint8Array(1), 1, 1, 1);
|
|
79
|
-
fulfill(defaultSampler);
|
|
80
|
-
} else if (heightMapURL.endsWith('.bin')) {
|
|
81
|
-
//load texture from a binary file
|
|
82
|
-
assetManager.get(heightMapURL, GameAssetType.ArrayBuffer, assetObtained, reject);
|
|
83
|
-
} else {
|
|
84
|
-
assetManager.get(heightMapURL, GameAssetType.Image, function (asset) {
|
|
85
|
-
const image = asset.create();
|
|
86
|
-
|
|
87
|
-
// plane
|
|
88
|
-
const imgWidth = image.width;
|
|
89
|
-
const imgHeight = image.height;
|
|
90
|
-
|
|
91
|
-
const samplerHeight = rgbaData2valueSampler2D(image.data, imgWidth, imgHeight, zRange, -zRange / 2);
|
|
92
|
-
|
|
93
|
-
fulfill(samplerHeight);
|
|
94
|
-
}, reject);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
* @param {WebGLRenderer} renderer
|
|
102
|
-
* @param {Sampler2D} sampler
|
|
103
|
-
* @returns {Promise<Sampler2D>}
|
|
104
|
-
*/
|
|
105
|
-
function promiseSamplerNormal(renderer, sampler) {
|
|
106
|
-
|
|
107
|
-
console.time("generating normal map");
|
|
108
|
-
const normalSampler = heightMap2NormalMap(renderer, sampler);
|
|
109
|
-
console.timeEnd("generating normal map");
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return Promise.resolve(normalSampler);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
*
|
|
117
|
-
* @param {WebGLRenderer} renderer
|
|
118
|
-
* @param {Promise<Sampler2D>} pSamplerNormal
|
|
119
|
-
* @param {Sampler2D} samplerHeight
|
|
120
|
-
* @param {Vector2} resolution
|
|
121
|
-
* @param {number} rayLength
|
|
122
|
-
* @returns {Promise<unknown>}
|
|
123
|
-
*/
|
|
124
|
-
function promiseSamplerAO(
|
|
125
|
-
renderer,
|
|
126
|
-
pSamplerNormal,
|
|
127
|
-
samplerHeight,
|
|
128
|
-
resolution,
|
|
129
|
-
rayLength
|
|
130
|
-
) {
|
|
131
|
-
return new Promise(function (resolve, reject) {
|
|
132
|
-
Promise.all([pSamplerNormal]).then(function (values) {
|
|
133
|
-
const samplerNormal = values[0];
|
|
134
|
-
console.time("generating AO map");
|
|
135
|
-
const occlusionSampler = normalMap2AOMap(
|
|
136
|
-
renderer,
|
|
137
|
-
samplerHeight,
|
|
138
|
-
samplerNormal,
|
|
139
|
-
resolution,
|
|
140
|
-
rayLength
|
|
141
|
-
);
|
|
142
|
-
console.timeEnd("generating AO map");
|
|
143
|
-
//console.info(occlusionSampler);
|
|
144
|
-
//
|
|
145
|
-
// paintSamplerOnHTML(samplerHeight, 0, 0, 40, 3);
|
|
146
|
-
// paintSamplerOnHTML(samplerNormal, 1, 0, 128, 1);
|
|
147
|
-
// paintSamplerOnHTML(occlusionSampler, 2, 0, 1, 0);
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
resolve(occlusionSampler);
|
|
151
|
-
}, reject);
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
*
|
|
157
|
-
* @param {DataTexture} texture
|
|
158
|
-
* @param {Vector2} resolution
|
|
159
|
-
* @param {Sampler2D} heightSampler
|
|
160
|
-
* @param {number} heightRange
|
|
161
|
-
* @param {number} [rayLength]
|
|
162
|
-
* @returns {Promise}
|
|
163
|
-
*/
|
|
164
|
-
function buildLightTexture({ texture, heightSampler, resolution, rayLength = 17 }) {
|
|
165
|
-
|
|
166
|
-
const renderer = WebGLRendererPool.global.get();
|
|
167
|
-
|
|
168
|
-
if (resolution === undefined) {
|
|
169
|
-
resolution = new Vector2(texture.image.width, texture.image.height);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const normal = promiseSamplerNormal(renderer, heightSampler);
|
|
173
|
-
const ao = promiseSamplerAO(renderer, normal, heightSampler, resolution, rayLength);
|
|
174
|
-
|
|
175
|
-
const promise = ao.then(sampler => {
|
|
176
|
-
writeSample2DDataToDataTexture(sampler, texture);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
Promise.all([normal, ao]).finally(() => {
|
|
180
|
-
WebGLRendererPool.global.release(renderer);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
return promise;
|
|
184
|
-
}
|
|
37
|
+
import { buildLightTexture } from "./BuildLightTexture.js";
|
|
38
|
+
import { promiseSamplerHeight } from "./PromiseSamplerHeight.js";
|
|
185
39
|
|
|
186
40
|
let idCounter = 0;
|
|
187
41
|
|
|
@@ -903,13 +757,13 @@ class Terrain {
|
|
|
903
757
|
this.updateWorkerHeights();
|
|
904
758
|
}
|
|
905
759
|
|
|
906
|
-
updateWorkerHeights() {
|
|
760
|
+
async updateWorkerHeights() {
|
|
907
761
|
const s = this.samplerHeight;
|
|
908
762
|
const worker = this.buildWorker;
|
|
909
763
|
|
|
910
|
-
worker.setHeightSampler(s.data, s.itemSize, s.width, s.height);
|
|
764
|
+
await worker.setHeightSampler(s.data, s.itemSize, s.width, s.height);
|
|
911
765
|
|
|
912
|
-
|
|
766
|
+
return await worker.computeHeightRange()
|
|
913
767
|
.then(({ min, max }) => {
|
|
914
768
|
this.tiles.setHeightRange(min, max);
|
|
915
769
|
});
|
|
@@ -1012,7 +866,12 @@ class Terrain {
|
|
|
1012
866
|
this.setFlag(TerrainFlags.Built);
|
|
1013
867
|
}
|
|
1014
868
|
|
|
1015
|
-
|
|
869
|
+
/**
|
|
870
|
+
*
|
|
871
|
+
* @param {number} quality resolution in texels per grid cell (4 = 4x4 light map texels per single grid cell)
|
|
872
|
+
* @return {Promise<DataTexture>}
|
|
873
|
+
*/
|
|
874
|
+
buildLightMap(quality = 4) {
|
|
1016
875
|
|
|
1017
876
|
|
|
1018
877
|
const size_x = this.size.x;
|
|
@@ -1035,7 +894,9 @@ class Terrain {
|
|
|
1035
894
|
|
|
1036
895
|
const promise = buildLightTexture({
|
|
1037
896
|
texture,
|
|
1038
|
-
heightSampler: this.samplerHeight
|
|
897
|
+
heightSampler: this.samplerHeight,
|
|
898
|
+
worldSize: new Vector2(size_x * this.gridScale, size_y * this.gridScale),
|
|
899
|
+
resolution: new Vector2(size_x * quality, size_y *quality)
|
|
1039
900
|
});
|
|
1040
901
|
|
|
1041
902
|
|
|
@@ -2,10 +2,10 @@ import { System } from "../System.js";
|
|
|
2
2
|
import { TooltipComponent } from "./TooltipComponent.js";
|
|
3
3
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
4
4
|
import { MeshSystem } from "../../graphics/ecs/mesh/MeshSystem.js";
|
|
5
|
-
import { modelHitTest } from "../../../../model/game/util/ScreenGridPicker.js";
|
|
6
5
|
import { SurfacePoint3 } from "../../../core/geom/3d/SurfacePoint3.js";
|
|
7
6
|
import { VisualTip } from "../../../view/tooltip/VisualTip.js";
|
|
8
7
|
import Rectangle from "../../../core/geom/Rectangle.js";
|
|
8
|
+
import { modelHitTest } from "../../graphics/util/modelHitTest.js";
|
|
9
9
|
|
|
10
10
|
const ray_source = new Vector3();
|
|
11
11
|
const ray_direction = new Vector3();
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
import { LinearFilter, Mesh, OrthographicCamera, Scene, ShaderMaterial, WebGLRenderTarget } from 'three';
|
|
7
7
|
import { FULL_SCREEN_TRIANGLE_GEOMETRY } from "../geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js";
|
|
8
|
+
import { FULL_SCREEN_QUAD_VERTEX_SHADER } from "../FULL_SCREEN_QUAD_VERTEX_SHADER.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
*
|
|
11
12
|
* @param {WebGLRenderer} renderer
|
|
12
13
|
* @param {number} width
|
|
13
14
|
* @param {number} height
|
|
14
|
-
* @param {{vertexShader
|
|
15
|
+
* @param {{vertexShader?:string,fragmentShader:string, uniforms?:Object, defines?:Object}} processShader
|
|
15
16
|
* @param {Uint8Array} [destination]
|
|
16
17
|
* @return {{array: Uint8Array, renderer: WebGLRenderer}}
|
|
17
18
|
*/
|
|
@@ -34,9 +35,12 @@ function processTexture(
|
|
|
34
35
|
scene.add(camera);
|
|
35
36
|
|
|
36
37
|
//make a quad to render
|
|
37
|
-
const material = new ShaderMaterial(processShader);
|
|
38
|
+
const material = new ShaderMaterial(Object.assign({ vertexShader: FULL_SCREEN_QUAD_VERTEX_SHADER }, processShader));
|
|
39
|
+
|
|
38
40
|
material.lights = false;
|
|
39
41
|
material.fog = false;
|
|
42
|
+
material.uniformsNeedUpdate = true;
|
|
43
|
+
material.needsUpdate = true;
|
|
40
44
|
|
|
41
45
|
const quad = new Mesh(FULL_SCREEN_TRIANGLE_GEOMETRY, material);
|
|
42
46
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {AttributeSpec} from "./AttributeSpec";
|
|
2
|
+
|
|
3
|
+
export class VertexDataSpec {
|
|
4
|
+
readonly attributes: AttributeSpec[]
|
|
5
|
+
|
|
6
|
+
getAttributeByName(name: string): AttributeSpec | undefined
|
|
7
|
+
|
|
8
|
+
add(attribute: AttributeSpec): this
|
|
9
|
+
|
|
10
|
+
setAttributes(attributes: AttributeSpec[]): void
|
|
11
|
+
|
|
12
|
+
equals(other: VertexDataSpec): boolean
|
|
13
|
+
|
|
14
|
+
hash(): number
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { BufferAttribute } from "three";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
|
|
7
|
+
* @returns {THREE.BufferAttribute}
|
|
8
|
+
*/
|
|
9
|
+
export function deinterleaveBufferAttribute(source_attribute) {
|
|
10
|
+
if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
|
|
11
|
+
return source_attribute;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const source_data = source_attribute.data;
|
|
15
|
+
const source_data_array = source_data.array;
|
|
16
|
+
const stride = source_data.stride;
|
|
17
|
+
|
|
18
|
+
const item_count = source_attribute.count;
|
|
19
|
+
const itemSize = source_attribute.itemSize;
|
|
20
|
+
const array_size = item_count * itemSize;
|
|
21
|
+
|
|
22
|
+
const offset = source_attribute.offset;
|
|
23
|
+
|
|
24
|
+
const destination_array = new source_data_array.constructor(array_size);
|
|
25
|
+
|
|
26
|
+
const attribute = new BufferAttribute(destination_array, itemSize);
|
|
27
|
+
|
|
28
|
+
attribute.normalized = source_attribute.normalized;
|
|
29
|
+
attribute.name = source_attribute.name;
|
|
30
|
+
|
|
31
|
+
// copy data
|
|
32
|
+
for (let i = 0; i < item_count; i++) {
|
|
33
|
+
for (let j = 0; j < itemSize; j++) {
|
|
34
|
+
destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return attribute;
|
|
39
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { BufferGeometry } from "three";
|
|
2
|
+
import { deinterleaveBufferAttribute } from "./deinterleaveBufferAttribute.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {THREE.BufferGeometry} geometry
|
|
7
|
+
* @returns {THREE.BufferGeometry}
|
|
8
|
+
*/
|
|
9
|
+
export function deinterleaveBufferGeometry(geometry) {
|
|
10
|
+
const result = new BufferGeometry();
|
|
11
|
+
|
|
12
|
+
if (geometry.getIndex() !== null) {
|
|
13
|
+
result.setIndex(deinterleaveBufferAttribute(geometry.getIndex()));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const attribute_key in geometry.attributes) {
|
|
17
|
+
const source_attribute = geometry.attributes[attribute_key];
|
|
18
|
+
|
|
19
|
+
result.setAttribute(attribute_key, deinterleaveBufferAttribute(source_attribute));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// copy other bits
|
|
23
|
+
result.name = geometry.name;
|
|
24
|
+
|
|
25
|
+
result.morphTargetsRelative = geometry.morphTargetsRelative;
|
|
26
|
+
|
|
27
|
+
for (const attribute_key in geometry.morphAttributes) {
|
|
28
|
+
const source_attributes = geometry.morphAttributes[attribute_key];
|
|
29
|
+
|
|
30
|
+
const result_attributes = [];
|
|
31
|
+
|
|
32
|
+
result.morphAttributes[attribute_key] = result_attributes;
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < source_attributes.length; i++) {
|
|
35
|
+
const source_attribute = source_attributes[i];
|
|
36
|
+
result_attributes[i] = deinterleaveBufferAttribute(source_attribute);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
result.groups = geometry.groups.slice();
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
result.boundingBox = geometry.boundingBox !== null ? geometry.boundingBox.clone() : null;
|
|
44
|
+
result.boundingSphere = geometry.boundingSphere !== null ? geometry.boundingSphere.clone() : null;
|
|
45
|
+
result.drawRange.start = geometry.drawRange.start;
|
|
46
|
+
result.drawRange.count = geometry.drawRange.count;
|
|
47
|
+
result.userData = JSON.parse(JSON.stringify(geometry.userData));
|
|
48
|
+
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MICRON_GEOMETRY_FIELD = '@micron_geometry';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MICRON_URI_FIELD = '@micron_path';
|
|
@@ -12,6 +12,7 @@ import { expandConnectivityByLocality } from "../../../../core/geom/3d/topology/
|
|
|
12
12
|
import { build_geometry_info } from "./build_geometry_info.js";
|
|
13
13
|
import { build_leaf_patches_metis } from "./clustering/build_leaf_patches_metis.js";
|
|
14
14
|
import { compute_buffer_geometry_byte_size } from "../../geometry/buffered/compute_buffer_geometry_byte_size.js";
|
|
15
|
+
import { deinterleaveBufferGeometry } from "../../geometry/buffered/deinterleaveBufferGeometry.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Returns current time in milliseconds
|
|
@@ -105,11 +106,13 @@ const PRINT_VERBOSE_STATS = false;
|
|
|
105
106
|
* @returns {MicronGeometry}
|
|
106
107
|
*/
|
|
107
108
|
export async function buildMicronGeometryFromBufferGeometry(input) {
|
|
109
|
+
const source_geometry = deinterleaveBufferGeometry(input);
|
|
110
|
+
|
|
108
111
|
// build topology representation
|
|
109
112
|
const topoMesh = new TopoMesh();
|
|
110
113
|
|
|
111
|
-
const position_attribute =
|
|
112
|
-
const index_attribute =
|
|
114
|
+
const position_attribute = source_geometry.getAttribute("position");
|
|
115
|
+
const index_attribute = source_geometry.index;
|
|
113
116
|
|
|
114
117
|
const face_index_array = index_attribute.array;
|
|
115
118
|
const vertex_position_array = position_attribute.array;
|
|
@@ -183,18 +186,18 @@ export async function buildMicronGeometryFromBufferGeometry(input) {
|
|
|
183
186
|
|
|
184
187
|
const r = new MicronGeometry();
|
|
185
188
|
|
|
186
|
-
r.proxy =
|
|
189
|
+
r.proxy = source_geometry; // TODO use r.buildProxy(1) instead
|
|
187
190
|
|
|
188
191
|
r.source_triangle_count = index_attribute.count / 3;
|
|
189
|
-
r.source_vertex_count =
|
|
190
|
-
r.source_byte_size = compute_buffer_geometry_byte_size(
|
|
192
|
+
r.source_vertex_count = source_geometry.getAttribute('position').count;
|
|
193
|
+
r.source_byte_size = compute_buffer_geometry_byte_size(source_geometry);
|
|
191
194
|
|
|
192
195
|
// console.time('build geometry');
|
|
193
196
|
|
|
194
|
-
const vertex_attributes = attributes_from_buffer_geometry(
|
|
197
|
+
const vertex_attributes = attributes_from_buffer_geometry(source_geometry);
|
|
195
198
|
|
|
196
199
|
r.vertex_spec.setAttributes(vertex_attributes);
|
|
197
|
-
r.root = compilePatchGraph(root,
|
|
200
|
+
r.root = compilePatchGraph(root, source_geometry, r.vertex_spec);
|
|
198
201
|
|
|
199
202
|
r.initialize();
|
|
200
203
|
|
|
@@ -4,6 +4,7 @@ import { computeGeometryEquality } from "../../asset/loaders/geometry/geometry/c
|
|
|
4
4
|
import { buildMicronGeometryFromBufferGeometry } from "./build/buildMicronGeometryFromBufferGeometry.js";
|
|
5
5
|
import { ThreeMicronMesh } from "./format/ThreeMicronMesh.js";
|
|
6
6
|
import { AsyncMapWrapper } from "../../../core/collection/map/AsyncMapWrapper.js";
|
|
7
|
+
import { MICRON_GEOMETRY_FIELD } from "./MICRON_GEOMETRY_FIELD.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
@@ -19,7 +20,6 @@ const pending_cache = new HashMap({
|
|
|
19
20
|
keyEqualityFunction: computeGeometryEquality
|
|
20
21
|
});
|
|
21
22
|
|
|
22
|
-
|
|
23
23
|
/**
|
|
24
24
|
*
|
|
25
25
|
* @param {THREE.Object3D} object
|
|
@@ -36,10 +36,22 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
|
|
|
36
36
|
* @returns {MicronGeometry}
|
|
37
37
|
*/
|
|
38
38
|
async function obtain_geometry(g) {
|
|
39
|
-
const
|
|
39
|
+
const attached_micron = g[MICRON_GEOMETRY_FIELD];
|
|
40
40
|
|
|
41
|
-
if (
|
|
42
|
-
|
|
41
|
+
if (attached_micron !== undefined && attached_micron.isMicronGeometry) {
|
|
42
|
+
// micron geometry is already attached, use it
|
|
43
|
+
return attached_micron;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const cached_micron = await micron_cache.get(g);
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if (cached_micron !== undefined && cached_micron !== null) {
|
|
50
|
+
|
|
51
|
+
// set proxy
|
|
52
|
+
cached_micron.proxy = g;
|
|
53
|
+
|
|
54
|
+
return cached_micron;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
const pending = pending_cache.get(g);
|
|
@@ -54,8 +66,14 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
|
|
|
54
66
|
|
|
55
67
|
promises.push(micron_geometry_promise);
|
|
56
68
|
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @type {MicronGeometry}
|
|
72
|
+
*/
|
|
57
73
|
const micron_geometry = await micron_geometry_promise;
|
|
58
74
|
|
|
75
|
+
micron_geometry.proxy = g;
|
|
76
|
+
|
|
59
77
|
await micron_cache.set(g, micron_geometry);
|
|
60
78
|
|
|
61
79
|
return micron_geometry;
|
|
@@ -90,7 +108,15 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
|
|
|
90
108
|
&& !mesh.isSkinnedMesh // skinned meshes not supported
|
|
91
109
|
) {
|
|
92
110
|
|
|
93
|
-
|
|
111
|
+
let micronGeometry;
|
|
112
|
+
try {
|
|
113
|
+
micronGeometry = await obtain_geometry(mesh.geometry);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.error(`Failed to convert geometry to micron, skipping : ${e}`);
|
|
116
|
+
|
|
117
|
+
// return original
|
|
118
|
+
return mesh;
|
|
119
|
+
}
|
|
94
120
|
|
|
95
121
|
const micron_mesh = new ThreeMicronMesh(micronGeometry, mesh.material);
|
|
96
122
|
|