@woosh/meep-engine 2.35.13 → 2.35.16
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/collection/array/typed/uint_array_for_count.js +17 -0
- package/core/geom/3d/ray/ray3_array_apply_matrix4.js +42 -0
- package/core/geom/3d/ray/ray3_array_compose.js +19 -0
- package/core/geom/3d/ray/ray3_array_compose.spec.js +14 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +18 -24
- package/engine/graphics/ecs/mesh-v2/sample/prototype_sg_raycast.js +212 -0
- package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +0 -1
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +16 -0
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +1 -18
- package/engine/graphics/micron/format/MicronGeometry.js +7 -4
- package/engine/graphics/micron/format/micron_build_proxy_geometry.js +203 -0
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +21 -0
- package/engine/graphics/micron/prototypeMicronProxyBuild.js +227 -0
- package/engine/graphics/util/composeMatrix4RotationScale.js +4 -27
- package/engine/navigation/grid/FastBinaryHeap.js +13 -2
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number} count
|
|
4
|
+
* @returns {function}
|
|
5
|
+
*/
|
|
6
|
+
export function UintArrayForCount(count) {
|
|
7
|
+
|
|
8
|
+
if (count <= 256) {
|
|
9
|
+
return Uint8Array;
|
|
10
|
+
} else if (count <= 65536) {
|
|
11
|
+
return Uint16Array;
|
|
12
|
+
} else if (count <= 4294967295) {
|
|
13
|
+
return Uint32Array;
|
|
14
|
+
} else {
|
|
15
|
+
throw new Error(`Unsupported size ${count}`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]|ArrayLike<number>|Float32Array} output 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
4
|
+
* @param {number[]|ArrayLike<number>|Float32Array} input 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
5
|
+
* @param {number[]|ArrayLike<number>|Float32Array} m4 4x4 matrix
|
|
6
|
+
*/
|
|
7
|
+
export function ray3_array_apply_matrix4(output, input, m4) {
|
|
8
|
+
const origin_x = input[0];
|
|
9
|
+
const origin_y = input[1];
|
|
10
|
+
const origin_z = input[2];
|
|
11
|
+
|
|
12
|
+
const direction_x = input[3];
|
|
13
|
+
const direction_y = input[4];
|
|
14
|
+
const direction_z = input[5];
|
|
15
|
+
|
|
16
|
+
// transform ray to local space (inlined for speed)
|
|
17
|
+
const inv_w = 1 / (m4[3] * origin_x + m4[7] * origin_y + m4[11] * origin_z + m4[15]);
|
|
18
|
+
|
|
19
|
+
const out_origin_x = (m4[0] * origin_x + m4[4] * origin_y + m4[8] * origin_z + m4[12]) * inv_w;
|
|
20
|
+
const out_origin_y = (m4[1] * origin_x + m4[5] * origin_y + m4[9] * origin_z + m4[13]) * inv_w;
|
|
21
|
+
const out_origin_z = (m4[2] * origin_x + m4[6] * origin_y + m4[10] * origin_z + m4[14]) * inv_w;
|
|
22
|
+
|
|
23
|
+
const out_direction_x = m4[0] * direction_x + m4[4] * direction_y + m4[8] * direction_z;
|
|
24
|
+
const out_direction_y = m4[1] * direction_x + m4[5] * direction_y + m4[9] * direction_z;
|
|
25
|
+
const out_direction_z = m4[2] * direction_x + m4[6] * direction_y + m4[10] * direction_z;
|
|
26
|
+
|
|
27
|
+
// normalize direction
|
|
28
|
+
const out_direction_magnitude = Math.hypot(out_direction_x, out_direction_y, out_direction_z);
|
|
29
|
+
const out_direction_magnitude_inverse = 1 / out_direction_magnitude;
|
|
30
|
+
|
|
31
|
+
const out_direction_normalized_x = out_direction_x * out_direction_magnitude_inverse;
|
|
32
|
+
const out_direction_normalized_y = out_direction_y * out_direction_magnitude_inverse;
|
|
33
|
+
const out_direction_normalized_z = out_direction_z * out_direction_magnitude_inverse;
|
|
34
|
+
|
|
35
|
+
output[0] = out_origin_x;
|
|
36
|
+
output[1] = out_origin_y;
|
|
37
|
+
output[2] = out_origin_z;
|
|
38
|
+
|
|
39
|
+
output[3] = out_direction_normalized_x;
|
|
40
|
+
output[4] = out_direction_normalized_y;
|
|
41
|
+
output[5] = out_direction_normalized_z;
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]|ArrayLike<number>|Float32Array} output
|
|
4
|
+
* @param {number} origin_x
|
|
5
|
+
* @param {number} origin_y
|
|
6
|
+
* @param {number} origin_z
|
|
7
|
+
* @param {number} direction_x
|
|
8
|
+
* @param {number} direction_y
|
|
9
|
+
* @param {number} direction_z
|
|
10
|
+
*/
|
|
11
|
+
export function ray3_array_compose(output, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z) {
|
|
12
|
+
output[0] = origin_x;
|
|
13
|
+
output[1] = origin_y;
|
|
14
|
+
output[2] = origin_z;
|
|
15
|
+
|
|
16
|
+
output[3] = direction_x;
|
|
17
|
+
output[4] = direction_y;
|
|
18
|
+
output[5] = direction_z;
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ray3_array_compose } from "./ray3_array_compose.js";
|
|
2
|
+
|
|
3
|
+
test('correctness', () => {
|
|
4
|
+
const result = [];
|
|
5
|
+
ray3_array_compose(result, 1, -3, 7, -11, 13, -17);
|
|
6
|
+
|
|
7
|
+
expect(result[0]).toBe(1);
|
|
8
|
+
expect(result[1]).toBe(-3);
|
|
9
|
+
expect(result[2]).toBe(7);
|
|
10
|
+
|
|
11
|
+
expect(result[3]).toBe(-11);
|
|
12
|
+
expect(result[4]).toBe(13);
|
|
13
|
+
expect(result[5]).toBe(-17);
|
|
14
|
+
});
|
|
@@ -10,6 +10,8 @@ import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersec
|
|
|
10
10
|
import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
|
|
11
11
|
import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
|
|
12
12
|
import { assert } from "../../../../core/assert.js";
|
|
13
|
+
import { ray3_array_compose } from "../../../../core/geom/3d/ray/ray3_array_compose.js";
|
|
14
|
+
import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
*
|
|
@@ -35,6 +37,9 @@ const scratch_point = new SurfacePoint3();
|
|
|
35
37
|
*/
|
|
36
38
|
const scratch_m4 = new Float32Array(16);
|
|
37
39
|
|
|
40
|
+
const scratch_ray_0 = new Float32Array(6);
|
|
41
|
+
const scratch_ray_1 = new Float32Array(6);
|
|
42
|
+
|
|
38
43
|
export class ShadedGeometrySystem extends System {
|
|
39
44
|
/**
|
|
40
45
|
*
|
|
@@ -332,29 +337,19 @@ export class ShadedGeometrySystem extends System {
|
|
|
332
337
|
// get transform in local space
|
|
333
338
|
mat4.invert(scratch_m4, m4);
|
|
334
339
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const local_origin_z = (scratch_m4[2] * origin_x + scratch_m4[6] * origin_y + scratch_m4[10] * origin_z + scratch_m4[14]) * inv_w;
|
|
341
|
-
|
|
342
|
-
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
343
|
-
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
344
|
-
const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
|
|
345
|
-
|
|
346
|
-
const local_direction_magnitude = Math.hypot(local_direction_x, local_direction_y, local_direction_z);
|
|
347
|
-
const local_direction_magnitude_inverse = 1 / local_direction_magnitude;
|
|
340
|
+
ray3_array_compose(
|
|
341
|
+
scratch_ray_0,
|
|
342
|
+
origin_x, origin_y, origin_z,
|
|
343
|
+
direction_x, direction_y, direction_z
|
|
344
|
+
);
|
|
348
345
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
|
|
346
|
+
// transform ray to local space
|
|
347
|
+
ray3_array_apply_matrix4(scratch_ray_0, scratch_ray_0, scratch_m4);
|
|
352
348
|
|
|
353
|
-
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.
|
|
349
|
+
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_array(
|
|
354
350
|
scratch_point,
|
|
355
351
|
sg.geometry,
|
|
356
|
-
|
|
357
|
-
local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
|
|
352
|
+
scratch_ray_0
|
|
358
353
|
);
|
|
359
354
|
|
|
360
355
|
if (!geometry_hit_found) {
|
|
@@ -373,13 +368,12 @@ export class ShadedGeometrySystem extends System {
|
|
|
373
368
|
origin_x, origin_y, origin_z
|
|
374
369
|
);
|
|
375
370
|
|
|
376
|
-
if (distance_sqr
|
|
377
|
-
|
|
378
|
-
|
|
371
|
+
if (distance_sqr < best_distance) {
|
|
372
|
+
contact.copy(scratch_point);
|
|
373
|
+
best_result = sg;
|
|
374
|
+
best_distance = distance_sqr;
|
|
379
375
|
}
|
|
380
376
|
|
|
381
|
-
contact.copy(scratch_point);
|
|
382
|
-
best_result = sg;
|
|
383
377
|
}
|
|
384
378
|
}
|
|
385
379
|
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
+
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
|
|
3
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.js";
|
|
4
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
5
|
+
import { ShadedGeometry } from "../ShadedGeometry.js";
|
|
6
|
+
import {
|
|
7
|
+
BoxBufferGeometry,
|
|
8
|
+
MeshBasicMaterial,
|
|
9
|
+
MeshStandardMaterial,
|
|
10
|
+
OctahedronGeometry,
|
|
11
|
+
SphereBufferGeometry
|
|
12
|
+
} from "three";
|
|
13
|
+
import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
|
|
14
|
+
import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
|
|
15
|
+
import ViewportPosition from "../../../../ecs/gui/position/ViewportPosition.js";
|
|
16
|
+
import GUIElement from "../../../../ecs/gui/GUIElement.js";
|
|
17
|
+
import ButtonView from "../../../../../view/elements/button/ButtonView.js";
|
|
18
|
+
import { downloadAsFile } from "../../../../../core/binary/ByteArrayTools.js";
|
|
19
|
+
import { convert_bvh_to_dot_format_string } from "../../../../../core/bvh2/visual/convert_bvh_to_dot_format_string.js";
|
|
20
|
+
import ViewportPositionSystem from "../../../../ecs/gui/position/ViewportPositionSystem.js";
|
|
21
|
+
import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
|
|
22
|
+
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
23
|
+
import Quaternion from "../../../../../core/geom/Quaternion.js";
|
|
24
|
+
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
25
|
+
import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
|
|
26
|
+
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
27
|
+
import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
|
|
28
|
+
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
29
|
+
import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
|
|
30
|
+
import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
|
|
31
|
+
import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
|
|
32
|
+
import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
33
|
+
import { SurfacePoint3 } from "../../../../../core/geom/3d/SurfacePoint3.js";
|
|
34
|
+
|
|
35
|
+
const eh = new EngineHarness();
|
|
36
|
+
|
|
37
|
+
const DRAW_METHOD_PLAIN = 0;
|
|
38
|
+
const DRAW_METHOD_INSTANCED = 1;
|
|
39
|
+
|
|
40
|
+
function makeMovingShadedGeometry() {
|
|
41
|
+
const b = new OrbitingBehavior();
|
|
42
|
+
b.offset.set(4, 1, 4);
|
|
43
|
+
b.radius = 2;
|
|
44
|
+
b.rate = 1;
|
|
45
|
+
|
|
46
|
+
const sg = ShadedGeometry.from(new OctahedronGeometry(0.5, 5), new MeshStandardMaterial({ color: 0xFF0000 }));
|
|
47
|
+
|
|
48
|
+
sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
49
|
+
|
|
50
|
+
return new EntityBuilder()
|
|
51
|
+
.add(new Transform())
|
|
52
|
+
.add(sg)
|
|
53
|
+
.add(BehaviorComponent.fromOne(b));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {Engine} engine
|
|
59
|
+
*/
|
|
60
|
+
async function main(engine) {
|
|
61
|
+
|
|
62
|
+
const em = engine.entityManager;
|
|
63
|
+
|
|
64
|
+
const sgs = new ShadedGeometrySystem(engine);
|
|
65
|
+
|
|
66
|
+
const mrc = new MicronRenderContext();
|
|
67
|
+
sgs.register_render_adapter(2, () => {
|
|
68
|
+
const adapter = new MicronShadedGeometryRenderAdapter();
|
|
69
|
+
adapter.ctx = mrc;
|
|
70
|
+
|
|
71
|
+
return adapter;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await em.addSystem(sgs);
|
|
75
|
+
await em.addSystem(new BehaviorSystem(engine));
|
|
76
|
+
|
|
77
|
+
EngineHarness.buildBasics({
|
|
78
|
+
engine,
|
|
79
|
+
yaw: -0.8,
|
|
80
|
+
pitch: 1,
|
|
81
|
+
distance: 46,
|
|
82
|
+
focus: new Vector3(10, 0, 10)
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
const ecd = em.dataset;
|
|
87
|
+
|
|
88
|
+
const material = new MeshStandardMaterial({
|
|
89
|
+
color: 0xFFFFFF,
|
|
90
|
+
transparent: true,
|
|
91
|
+
opacity: 0.5
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// material.visible = false;
|
|
95
|
+
|
|
96
|
+
window.material = material;
|
|
97
|
+
|
|
98
|
+
const random = seededRandom(0);
|
|
99
|
+
|
|
100
|
+
const INSTANCE_COUNT = 100;
|
|
101
|
+
|
|
102
|
+
const geometries = [];
|
|
103
|
+
|
|
104
|
+
for (let i = 0; i < 1; i++) {
|
|
105
|
+
geometries.push(new BoxBufferGeometry());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < INSTANCE_COUNT; i++) {
|
|
109
|
+
const geometry = randomFromArray(random, geometries);
|
|
110
|
+
const sg = ShadedGeometry.from(geometry, material);
|
|
111
|
+
|
|
112
|
+
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
113
|
+
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
114
|
+
// sg.draw_method = 2;
|
|
115
|
+
sg.draw_method = randomIntegerBetween(random, 0, 2);
|
|
116
|
+
// sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
|
|
117
|
+
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
118
|
+
|
|
119
|
+
new EntityBuilder()
|
|
120
|
+
.add(Transform.fromJSON({
|
|
121
|
+
position: {
|
|
122
|
+
x: randomFloatBetween(random, 0, 20),
|
|
123
|
+
y: randomFloatBetween(random, 0, 10),
|
|
124
|
+
z: randomFloatBetween(random, 0, 20)
|
|
125
|
+
},
|
|
126
|
+
rotation: Quaternion.random(random),
|
|
127
|
+
scale: 1
|
|
128
|
+
}))
|
|
129
|
+
.add(sg)
|
|
130
|
+
.build(ecd);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// makeMovingShadedGeometry().build(ecd);
|
|
134
|
+
|
|
135
|
+
debug_button(engine, () => {
|
|
136
|
+
const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
|
|
137
|
+
downloadAsFile(dot, 'bvh.dot', 'text');
|
|
138
|
+
|
|
139
|
+
}, 'save dot file');
|
|
140
|
+
|
|
141
|
+
const raycast_marker = new EntityBuilder()
|
|
142
|
+
.add(ShadedGeometry.from(new SphereBufferGeometry(1), new MeshBasicMaterial({
|
|
143
|
+
color: 0xFF0000
|
|
144
|
+
})))
|
|
145
|
+
.add(Transform.fromJSON({
|
|
146
|
+
scale: 0.07
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
raycast_marker.build(engine.entityManager.dataset);
|
|
150
|
+
|
|
151
|
+
engine.devices.pointer.position.onChanged.add((p_x, p_y) => {
|
|
152
|
+
const p = new Vector2(p_x, p_y);
|
|
153
|
+
const ndc = new Vector2();
|
|
154
|
+
const ray_origin = new Vector3();
|
|
155
|
+
const ray_direction = new Vector3();
|
|
156
|
+
|
|
157
|
+
engine.graphics.normalizeViewportPoint(p, ndc);
|
|
158
|
+
engine.graphics.viewportProjectionRay(ndc.x, ndc.y, ray_origin, ray_direction);
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* @type {ShadedGeometrySystem}
|
|
163
|
+
*/
|
|
164
|
+
const sgm = engine.entityManager.getSystem(ShadedGeometrySystem);
|
|
165
|
+
|
|
166
|
+
const sp = new SurfacePoint3();
|
|
167
|
+
|
|
168
|
+
sgm.raycastNearest(sp, ray_origin.x, ray_origin.y, ray_origin.z, ray_direction.x, ray_direction.y, ray_direction.z, ((entity, mesh) => {
|
|
169
|
+
return (entity !== raycast_marker.entity);
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
const t = raycast_marker.getComponent(Transform);
|
|
173
|
+
|
|
174
|
+
t.position.copy(sp.position);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
const entityManager = engine.entityManager;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
*
|
|
183
|
+
* @param {Engine} engine
|
|
184
|
+
* @param {function} action
|
|
185
|
+
* @param {string} [name]
|
|
186
|
+
* @param {EntityComponentDataset} ecd
|
|
187
|
+
*/
|
|
188
|
+
function debug_button(engine, action, name = "Button", ecd = entityManager.dataset) {
|
|
189
|
+
if (entityManager.getSystem(ViewportPositionSystem) === null) {
|
|
190
|
+
entityManager.addSystem(new ViewportPositionSystem(engine.graphics.viewport.size));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (entityManager.getSystem(GUIElementSystem) === null) {
|
|
194
|
+
entityManager.addSystem(new GUIElementSystem(engine.gui.view, engine));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
new EntityBuilder()
|
|
198
|
+
.add(ViewportPosition.fromJSON({}))
|
|
199
|
+
.add(GUIElement.fromView(new ButtonView({
|
|
200
|
+
action,
|
|
201
|
+
name,
|
|
202
|
+
css: {
|
|
203
|
+
background: 'rgba(255,255,255,0.8)',
|
|
204
|
+
border: '1px solid black',
|
|
205
|
+
borderRadius: '4px',
|
|
206
|
+
padding: '2px',
|
|
207
|
+
}
|
|
208
|
+
})))
|
|
209
|
+
.build(ecd);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
eh.initialize().then(main);
|
|
@@ -56,6 +56,22 @@ export class GeometrySpatialQueryAccelerator {
|
|
|
56
56
|
return this.__visitor_clip.getContainment();
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param {SurfacePoint3} destination
|
|
62
|
+
* @param {THREE.BufferGeometry} geometry
|
|
63
|
+
* @param {number[]|ArrayLike<number>|Float32Array} ray 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
64
|
+
* @return {boolean}
|
|
65
|
+
*/
|
|
66
|
+
queryRaycastNearest_array(destination, geometry, ray) {
|
|
67
|
+
return this.queryRaycastNearest_primitive(
|
|
68
|
+
destination,
|
|
69
|
+
geometry,
|
|
70
|
+
ray[0], ray[1], ray[2],
|
|
71
|
+
ray[3], ray[4], ray[5]
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
/**
|
|
60
76
|
*
|
|
61
77
|
* @param {SurfacePoint3} destination
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {number} count
|
|
4
|
-
* @returns {Function}
|
|
5
|
-
* @constructor
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
1
|
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
9
2
|
import { passThrough } from "../../../../core/function/Functions.js";
|
|
10
3
|
import { to_half_float_uint16 } from "../../../../core/binary/to_half_float_uint16.js";
|
|
@@ -12,17 +5,7 @@ import { compute_micron_buffer_array_constructor } from "./compute_micron_buffer
|
|
|
12
5
|
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
13
6
|
import { dataTypeByteSize } from "../../../../core/collection/table/DataTypeByteSizes.js";
|
|
14
7
|
import { clamp } from "../../../../core/math/clamp.js";
|
|
15
|
-
|
|
16
|
-
function UintArrayForCount(count) {
|
|
17
|
-
|
|
18
|
-
if (count <= 256) {
|
|
19
|
-
return Uint8Array;
|
|
20
|
-
} else if (count <= 65536) {
|
|
21
|
-
return Uint16Array;
|
|
22
|
-
} else {
|
|
23
|
-
throw new Error(`Unsupported size ${count}`)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
8
|
+
import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
26
9
|
|
|
27
10
|
/**
|
|
28
11
|
* @param {number} vertex_count
|
|
@@ -5,6 +5,7 @@ import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
|
|
|
5
5
|
import { aabb3_array_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_array_intersects_ray.js";
|
|
6
6
|
import { sphere_array_intersects_ray } from "../../../../core/geom/3d/sphere/sphere_array_intersects_ray.js";
|
|
7
7
|
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
8
|
+
import { micron_build_proxy_geometry } from "./micron_build_proxy_geometry.js";
|
|
8
9
|
|
|
9
10
|
let id_counter = 0;
|
|
10
11
|
|
|
@@ -286,11 +287,13 @@ export class MicronGeometry {
|
|
|
286
287
|
|
|
287
288
|
/**
|
|
288
289
|
* Build geometry proxy from the patches
|
|
289
|
-
* @param {number} fraction percentage of the original geometry to keep
|
|
290
|
-
* @param {number} min minimum number of triangles to keep, this will be respected first before percentage value
|
|
290
|
+
* @param {number} [fraction] percentage of the original geometry to keep
|
|
291
|
+
* @param {number} [min] minimum number of triangles to keep, this will be respected first before percentage value
|
|
291
292
|
*/
|
|
292
|
-
buildProxy(fraction, min) {
|
|
293
|
-
|
|
293
|
+
buildProxy(fraction = 0.05, min = 2048) {
|
|
294
|
+
const bufferGeometry = micron_build_proxy_geometry(this, fraction, min);
|
|
295
|
+
|
|
296
|
+
this.__proxy = bufferGeometry;
|
|
294
297
|
}
|
|
295
298
|
|
|
296
299
|
computeByteSize() {
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import BinaryHeap from "../../../navigation/grid/FastBinaryHeap.js";
|
|
4
|
+
import { BufferAttribute, BufferGeometry } from "three";
|
|
5
|
+
import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
6
|
+
import { compute_typed_array_constructor_from_data_type } from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
7
|
+
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
8
|
+
import { min2 } from "../../../../core/math/min2.js";
|
|
9
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {MicronGeometry} micron_geometry
|
|
14
|
+
* @param {number} fraction
|
|
15
|
+
* @param {number} min_face_count
|
|
16
|
+
* @returns {MicronGeometryPatch[]}
|
|
17
|
+
*/
|
|
18
|
+
function collect_patches(micron_geometry, fraction, min_face_count) {
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {BinaryHeap<MicronGeometryPatch>}
|
|
22
|
+
*/
|
|
23
|
+
const heap = new BinaryHeap(patch => {
|
|
24
|
+
// LOD is a good proxy for how much detail there is in a patch
|
|
25
|
+
return -patch.lod;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let closed_set = new BitSet();
|
|
29
|
+
|
|
30
|
+
let current_polycount = 0;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {MicronGeometryPatch} patch
|
|
35
|
+
*/
|
|
36
|
+
function add(patch) {
|
|
37
|
+
|
|
38
|
+
closed_set.set(patch.id, true);
|
|
39
|
+
|
|
40
|
+
heap.push(patch);
|
|
41
|
+
|
|
42
|
+
current_polycount += patch.polygon_count;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {MicronGeometryPatch} patch
|
|
48
|
+
*/
|
|
49
|
+
function refine(patch) {
|
|
50
|
+
const children = patch.children;
|
|
51
|
+
const child_count = children.length;
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < child_count; i++) {
|
|
55
|
+
const child = children[i];
|
|
56
|
+
|
|
57
|
+
if (closed_set.get(child.id)) {
|
|
58
|
+
// already refined
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
add(child);
|
|
63
|
+
|
|
64
|
+
const parents = child.parents;
|
|
65
|
+
|
|
66
|
+
const parent_count = parents.length;
|
|
67
|
+
for (let j = 0; j < parent_count; j++) {
|
|
68
|
+
const parent = parents[j];
|
|
69
|
+
|
|
70
|
+
if (parent === parent) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// remove and refine other patches in the same group
|
|
75
|
+
if (heap.delete(parent)) {
|
|
76
|
+
refine(parent);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
add(micron_geometry.root);
|
|
83
|
+
|
|
84
|
+
const target_polycount_threshold = max2(
|
|
85
|
+
micron_geometry.source_triangle_count * fraction,
|
|
86
|
+
min2(
|
|
87
|
+
min_face_count,
|
|
88
|
+
micron_geometry.source_triangle_count
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
while (current_polycount < target_polycount_threshold) {
|
|
93
|
+
const p = heap.peek();
|
|
94
|
+
|
|
95
|
+
if (p === undefined || p.lod === 0) {
|
|
96
|
+
// no refinement possible
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
heap.pop();
|
|
101
|
+
|
|
102
|
+
current_polycount -= p.polygon_count;
|
|
103
|
+
|
|
104
|
+
refine(p);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const result = [];
|
|
108
|
+
|
|
109
|
+
// collect
|
|
110
|
+
while (!heap.isEmpty()) {
|
|
111
|
+
result.push(heap.pop());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param {MicronGeometryPatch[]} patches
|
|
120
|
+
* @param {VertexDataSpec} vertex_spec
|
|
121
|
+
* @returns {THREE.BufferGeometry}
|
|
122
|
+
*/
|
|
123
|
+
function assemble_patches_to_geometry(patches, vertex_spec) {
|
|
124
|
+
const geo = new BufferGeometry();
|
|
125
|
+
|
|
126
|
+
//compute total number of vertices and faces
|
|
127
|
+
let total_faces = 0;
|
|
128
|
+
let total_vertices = 0;
|
|
129
|
+
|
|
130
|
+
for (let i = 0; i < patches.length; i++) {
|
|
131
|
+
const patch = patches[i];
|
|
132
|
+
|
|
133
|
+
total_faces += patch.polygon_count;
|
|
134
|
+
total_vertices += patch.vertex_count;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const index_data = new (UintArrayForCount(total_vertices))(total_faces * 3);
|
|
138
|
+
|
|
139
|
+
geo.setIndex(new BufferAttribute(index_data, 1, false));
|
|
140
|
+
|
|
141
|
+
const attribute_arrays = [];
|
|
142
|
+
|
|
143
|
+
const attribute_specs = vertex_spec.attributes;
|
|
144
|
+
const attribute_count = attribute_specs.length;
|
|
145
|
+
for (let i = 0; i < attribute_count; i++) {
|
|
146
|
+
const attribute = attribute_specs[i];
|
|
147
|
+
|
|
148
|
+
const TA = compute_typed_array_constructor_from_data_type(attribute.type);
|
|
149
|
+
|
|
150
|
+
const attribute_data = new TA(total_vertices * 3);
|
|
151
|
+
|
|
152
|
+
attribute_arrays[i] = attribute_data;
|
|
153
|
+
|
|
154
|
+
geo.setAttribute(attribute.name, new BufferAttribute(attribute_data, attribute.itemSize, attribute.normalized));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let index_cursor = 0;
|
|
158
|
+
let vertex_cursor = 0;
|
|
159
|
+
|
|
160
|
+
// add patches to resulting geometry
|
|
161
|
+
for (let i = 0; i < patches.length; i++) {
|
|
162
|
+
const patch = patches[i];
|
|
163
|
+
|
|
164
|
+
const local_index_size = patch.polygon_count * 3;
|
|
165
|
+
|
|
166
|
+
// copy transformed indices
|
|
167
|
+
for (let j = 0; j < local_index_size; j++) {
|
|
168
|
+
const local_index = patch.face_indices[j];
|
|
169
|
+
|
|
170
|
+
index_data[index_cursor + j] = local_index + vertex_cursor;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// copy vertex data
|
|
174
|
+
|
|
175
|
+
for (let j = 0; j < attribute_count; j++) {
|
|
176
|
+
const attribute_destination = attribute_arrays[j];
|
|
177
|
+
|
|
178
|
+
const attribute_source = patch.vertex_attribute_arrays[j];
|
|
179
|
+
const destination_offset = vertex_cursor * attribute_specs[j].itemSize;
|
|
180
|
+
|
|
181
|
+
attribute_destination.set(attribute_source, destination_offset);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
vertex_cursor += patch.vertex_count;
|
|
185
|
+
index_cursor += local_index_size;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return geo;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
*
|
|
194
|
+
* @param {MicronGeometry} micron_geometry
|
|
195
|
+
* @param {number} fraction
|
|
196
|
+
* @param {number} [min_face_count]
|
|
197
|
+
* @returns {THREE.BufferGeometry}
|
|
198
|
+
*/
|
|
199
|
+
export function micron_build_proxy_geometry(micron_geometry, fraction, min_face_count = 128) {
|
|
200
|
+
const patches = collect_patches(micron_geometry, fraction, min_face_count);
|
|
201
|
+
|
|
202
|
+
return assemble_patches_to_geometry(patches, micron_geometry.vertex_spec);
|
|
203
|
+
}
|
|
@@ -35,6 +35,25 @@ function max_polycount(object) {
|
|
|
35
35
|
return r;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {THREE.Object3D} object
|
|
41
|
+
*/
|
|
42
|
+
function ensureProxy(object) {
|
|
43
|
+
if (object.isMicronMesh) {
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @type {MicronGeometry}
|
|
47
|
+
*/
|
|
48
|
+
const micron_geo = object.geometry;
|
|
49
|
+
|
|
50
|
+
if (micron_geo.proxy === null) {
|
|
51
|
+
// proxy geometry doesn't exist, build one
|
|
52
|
+
micron_geo.buildProxy();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
38
57
|
export class GLTFAssetTransformer extends AssetTransformer {
|
|
39
58
|
/**
|
|
40
59
|
*
|
|
@@ -171,6 +190,8 @@ export class GLTFAssetTransformer extends AssetTransformer {
|
|
|
171
190
|
|
|
172
191
|
source.override_mesh = micron_root;
|
|
173
192
|
|
|
193
|
+
traverseThreeObject(micron_root, ensureProxy);
|
|
194
|
+
|
|
174
195
|
return source;
|
|
175
196
|
}
|
|
176
197
|
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
|
|
2
|
+
import {
|
|
3
|
+
AmbientLight,
|
|
4
|
+
CubeTextureLoader,
|
|
5
|
+
DirectionalLight,
|
|
6
|
+
FrontSide,
|
|
7
|
+
Mesh,
|
|
8
|
+
MeshBasicMaterial,
|
|
9
|
+
MeshStandardMaterial,
|
|
10
|
+
PerspectiveCamera,
|
|
11
|
+
PointLight,
|
|
12
|
+
RepeatWrapping,
|
|
13
|
+
Scene,
|
|
14
|
+
SphereGeometry,
|
|
15
|
+
sRGBEncoding,
|
|
16
|
+
TextureLoader,
|
|
17
|
+
VSMShadowMap,
|
|
18
|
+
WebGLRenderer
|
|
19
|
+
} from "three";
|
|
20
|
+
import Stats from "three/examples/jsm/libs/stats.module.js";
|
|
21
|
+
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
22
|
+
import { buildMicronGeometryFromBufferGeometry } from "./build/buildMicronGeometryFromBufferGeometry.js";
|
|
23
|
+
|
|
24
|
+
const background = new TextureLoader().load('data/textures/utility/checkers_white_grey_256x256.png');
|
|
25
|
+
background.repeat.set(50, 30);
|
|
26
|
+
background.wrapS = RepeatWrapping;
|
|
27
|
+
background.wrapT = RepeatWrapping;
|
|
28
|
+
|
|
29
|
+
let container, stats;
|
|
30
|
+
|
|
31
|
+
let camera, scene, renderer;
|
|
32
|
+
let directionalLight;
|
|
33
|
+
let pointLight;
|
|
34
|
+
|
|
35
|
+
let windowHalfX = window.innerWidth / 2;
|
|
36
|
+
let windowHalfY = window.innerHeight / 2;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
function init() {
|
|
40
|
+
|
|
41
|
+
container = document.createElement("div");
|
|
42
|
+
document.body.appendChild(container);
|
|
43
|
+
|
|
44
|
+
camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000000);
|
|
45
|
+
camera.position.z = -4000;
|
|
46
|
+
|
|
47
|
+
//
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
scene = new Scene();
|
|
51
|
+
|
|
52
|
+
window.scene = scene;
|
|
53
|
+
|
|
54
|
+
// LIGHTS
|
|
55
|
+
|
|
56
|
+
const ambient = new AmbientLight(0xffffff, 0.1);
|
|
57
|
+
scene.add(ambient);
|
|
58
|
+
|
|
59
|
+
pointLight = new PointLight(0x6666ff, 0.5);
|
|
60
|
+
pointLight.position.y = 1000;
|
|
61
|
+
scene.add(pointLight);
|
|
62
|
+
|
|
63
|
+
// light representation
|
|
64
|
+
|
|
65
|
+
const sphere = new SphereGeometry(100, 16, 8);
|
|
66
|
+
|
|
67
|
+
const mesh = new Mesh(sphere, new MeshBasicMaterial({ color: 0xffffff }));
|
|
68
|
+
mesh.scale.set(0.5, 0.5, 0.5);
|
|
69
|
+
pointLight.add(mesh);
|
|
70
|
+
|
|
71
|
+
// add directional light
|
|
72
|
+
directionalLight = new DirectionalLight(0xFFAAAA, 0.8);
|
|
73
|
+
directionalLight.position.set(-500, 1000, 300);
|
|
74
|
+
directionalLight.castShadow = true;
|
|
75
|
+
const shadow_camera = directionalLight.shadow.camera;
|
|
76
|
+
// small bias to prevent shadow acne
|
|
77
|
+
directionalLight.shadow.bias = -0.0001;
|
|
78
|
+
// directionalLight.shadow.mapSize.set(4096, 4096);
|
|
79
|
+
directionalLight.shadow.mapSize.set(1024, 1024);
|
|
80
|
+
directionalLight.shadow.autoUpdate = false;
|
|
81
|
+
|
|
82
|
+
window.light = directionalLight;
|
|
83
|
+
// directionalLight.shadow.autoUpdate = true;
|
|
84
|
+
|
|
85
|
+
shadow_camera.near = 0.1;
|
|
86
|
+
shadow_camera.far = 2000;
|
|
87
|
+
|
|
88
|
+
const shadow_camera_size = 15;
|
|
89
|
+
|
|
90
|
+
shadow_camera.left = -shadow_camera_size / 2;
|
|
91
|
+
shadow_camera.right = shadow_camera_size / 2;
|
|
92
|
+
|
|
93
|
+
shadow_camera.bottom = -shadow_camera_size / 2;
|
|
94
|
+
shadow_camera.top = shadow_camera_size / 2;
|
|
95
|
+
|
|
96
|
+
shadow_camera.updateProjectionMatrix();
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
scene.add(directionalLight);
|
|
100
|
+
// material samples
|
|
101
|
+
|
|
102
|
+
const cubeMaterial1 = new MeshStandardMaterial({
|
|
103
|
+
wireframe: false,
|
|
104
|
+
side: FrontSide,
|
|
105
|
+
color: 0xffffff
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
//
|
|
109
|
+
|
|
110
|
+
renderer = new WebGLRenderer({
|
|
111
|
+
antialias: true,
|
|
112
|
+
preserveDrawingBuffer: true,
|
|
113
|
+
stencil: false
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
renderer.shadowMap.enabled = true;
|
|
117
|
+
renderer.shadowMap.type = VSMShadowMap;
|
|
118
|
+
// renderer.shadowMap.type = BasicShadowMap;
|
|
119
|
+
renderer.sortObjects = false;
|
|
120
|
+
|
|
121
|
+
renderer.setPixelRatio(window.devicePixelRatio);
|
|
122
|
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
123
|
+
container.appendChild(renderer.domElement);
|
|
124
|
+
|
|
125
|
+
stats = new Stats();
|
|
126
|
+
container.appendChild(stats.dom);
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
window.addEventListener("resize", onWindowResize);
|
|
130
|
+
|
|
131
|
+
// envmap
|
|
132
|
+
const genCubeUrls = function (prefix, postfix) {
|
|
133
|
+
|
|
134
|
+
return [
|
|
135
|
+
prefix + "posx" + postfix, prefix + "negx" + postfix,
|
|
136
|
+
prefix + "posy" + postfix, prefix + "negy" + postfix,
|
|
137
|
+
prefix + "posz" + postfix, prefix + "negz" + postfix
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const urls = genCubeUrls("data/textures/cubemaps/hip_miramar/32/", ".png");
|
|
143
|
+
|
|
144
|
+
new CubeTextureLoader().load(urls, function (cubeTexture) {
|
|
145
|
+
|
|
146
|
+
cubeTexture.encoding = sRGBEncoding;
|
|
147
|
+
|
|
148
|
+
// scene.background = new Color(0.1, 0.1, 0.1);
|
|
149
|
+
// scene.background = new ThreeColor(1, 0.3, 0.3);
|
|
150
|
+
// scene.background = new Color(0.3, 1, 0.3);
|
|
151
|
+
|
|
152
|
+
scene.background = background;
|
|
153
|
+
scene.environment = cubeTexture;
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
// const lightProbe = new LightProbe();
|
|
157
|
+
//
|
|
158
|
+
// lightProbe.copy(LightProbeGenerator.fromCubeTexture(cubeTexture));
|
|
159
|
+
// lightProbe.intensity = 1.2;
|
|
160
|
+
|
|
161
|
+
// scene.add(lightProbe);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
onWindowResize();
|
|
165
|
+
|
|
166
|
+
new PLYLoader().load("data/models/stanford/Lucy100k.ply", async geometry => {
|
|
167
|
+
geometry.computeVertexNormals();
|
|
168
|
+
|
|
169
|
+
const source = new Mesh(geometry, new MeshStandardMaterial({ color: 0xFFFFFF }));
|
|
170
|
+
|
|
171
|
+
const micron_g = await buildMicronGeometryFromBufferGeometry(geometry);
|
|
172
|
+
|
|
173
|
+
micron_g.buildProxy();
|
|
174
|
+
|
|
175
|
+
const proxy = new Mesh(micron_g.proxy, new MeshStandardMaterial({ color: 0xFF0000 }));
|
|
176
|
+
|
|
177
|
+
source.position.x += 700;
|
|
178
|
+
proxy.position.x -= 700;
|
|
179
|
+
|
|
180
|
+
console.warn(geometry, micron_g);
|
|
181
|
+
|
|
182
|
+
scene.add(source);
|
|
183
|
+
scene.add(proxy);
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function onWindowResize() {
|
|
188
|
+
|
|
189
|
+
const w = window.innerWidth;
|
|
190
|
+
const h = window.innerHeight;
|
|
191
|
+
|
|
192
|
+
windowHalfX = w / 2;
|
|
193
|
+
windowHalfY = h / 2;
|
|
194
|
+
|
|
195
|
+
camera.aspect = w / h;
|
|
196
|
+
camera.updateProjectionMatrix();
|
|
197
|
+
|
|
198
|
+
renderer.setSize(w, h);
|
|
199
|
+
|
|
200
|
+
background.repeat.set(w / 20, h / 20);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function animate() {
|
|
204
|
+
|
|
205
|
+
requestAnimationFrame(animate);
|
|
206
|
+
|
|
207
|
+
render();
|
|
208
|
+
stats.update();
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function render() {
|
|
213
|
+
if (orbitControls !== undefined) {
|
|
214
|
+
orbitControls.update();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const timer = -0.0002 * Date.now();
|
|
218
|
+
|
|
219
|
+
pointLight.position.x = 10000 * Math.cos(timer);
|
|
220
|
+
pointLight.position.z = 10000 * Math.sin(timer);
|
|
221
|
+
|
|
222
|
+
renderer.render(scene, camera);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
init();
|
|
226
|
+
const orbitControls = new OrbitControls(camera, container);
|
|
227
|
+
animate();
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { compose_matrix4_array } from "./composeMatrix4.js";
|
|
2
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
*
|
|
3
6
|
* @param {Matrix4} result
|
|
@@ -7,31 +10,5 @@
|
|
|
7
10
|
export function composeMatrix4RotationScale(result, rotation, scale) {
|
|
8
11
|
const te = result.elements;
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
const x2 = x + x, y2 = y + y, z2 = z + z;
|
|
12
|
-
const xx = x * x2, xy = x * y2, xz = x * z2;
|
|
13
|
-
const yy = y * y2, yz = y * z2, zz = z * z2;
|
|
14
|
-
const wx = w * x2, wy = w * y2, wz = w * z2;
|
|
15
|
-
|
|
16
|
-
const sx = scale.x, sy = scale.y, sz = scale.z;
|
|
17
|
-
|
|
18
|
-
te[0] = (1 - (yy + zz)) * sx;
|
|
19
|
-
te[1] = (xy + wz) * sx;
|
|
20
|
-
te[2] = (xz - wy) * sx;
|
|
21
|
-
te[3] = 0;
|
|
22
|
-
|
|
23
|
-
te[4] = (xy - wz) * sy;
|
|
24
|
-
te[5] = (1 - (xx + zz)) * sy;
|
|
25
|
-
te[6] = (yz + wx) * sy;
|
|
26
|
-
te[7] = 0;
|
|
27
|
-
|
|
28
|
-
te[8] = (xz + wy) * sz;
|
|
29
|
-
te[9] = (yz - wx) * sz;
|
|
30
|
-
te[10] = (1 - (xx + yy)) * sz;
|
|
31
|
-
te[11] = 0;
|
|
32
|
-
|
|
33
|
-
te[12] = 0;
|
|
34
|
-
te[13] = 0;
|
|
35
|
-
te[14] = 0;
|
|
36
|
-
te[15] = 1;
|
|
13
|
+
compose_matrix4_array(te, Vector3.zero, rotation, scale);
|
|
37
14
|
}
|
|
@@ -6,12 +6,15 @@ import { assert } from "../../../core/assert.js";
|
|
|
6
6
|
*/
|
|
7
7
|
class BinaryHeap {
|
|
8
8
|
/**
|
|
9
|
-
* @
|
|
10
|
-
* @param {function(T):number} scoreFunction
|
|
9
|
+
* @param {(T)=>number} scoreFunction
|
|
11
10
|
* @constructor
|
|
12
11
|
*/
|
|
13
12
|
constructor(scoreFunction) {
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {function(T): number}
|
|
17
|
+
*/
|
|
15
18
|
this.scoreFunction = scoreFunction;
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -165,6 +168,14 @@ class BinaryHeap {
|
|
|
165
168
|
}
|
|
166
169
|
}
|
|
167
170
|
|
|
171
|
+
/**
|
|
172
|
+
*
|
|
173
|
+
* @returns {T|undefined}
|
|
174
|
+
*/
|
|
175
|
+
peek() {
|
|
176
|
+
return this.data[0];
|
|
177
|
+
}
|
|
178
|
+
|
|
168
179
|
/**
|
|
169
180
|
*
|
|
170
181
|
* @param {T} node
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.35.
|
|
8
|
+
"version": "2.35.16",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|