@woosh/meep-engine 2.34.30 → 2.34.34
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/assert.js +11 -0
- package/core/bvh2/BinaryNode.js +211 -25
- package/core/bvh2/aabb3/AABB3.js +4 -3
- package/core/bvh2/aabb3/AABB3Math.js +1 -1
- package/core/collection/list/List.js +0 -34
- package/core/collection/table/DataTypeByteSizes.js +16 -0
- package/engine/Engine.js +5 -0
- package/engine/development/performance/AbstractMetric.js +4 -0
- package/engine/development/performance/RingBufferMetric.js +4 -0
- package/engine/ecs/transform/Transform.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +16 -3
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +3 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +54 -0
- package/engine/graphics/ecs/mesh-v2/{prototypeShadedGeometry.js → sample/prototypeShadedGeometry.js} +5 -5
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +37 -0
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +15 -0
- package/engine/graphics/micron/build/compute_micron_buffer_array_constructor.js +2 -0
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +39 -5
- package/engine/graphics/micron/format/MicronGeometry.js +16 -20
- package/engine/graphics/micron/prototypeVirtualGeometry.js +7 -1
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +3 -0
- package/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +23 -0
- package/package.json +1 -1
package/core/assert.js
CHANGED
|
@@ -316,6 +316,17 @@ assert.defined = function (value, name = "value") {
|
|
|
316
316
|
|
|
317
317
|
};
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
*
|
|
321
|
+
* @param {*} value
|
|
322
|
+
* @param {String} [name]
|
|
323
|
+
*/
|
|
324
|
+
assert.isNull = function (value, name){
|
|
325
|
+
if (value !== null) {
|
|
326
|
+
throw new Error(`${name} is NOT null`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
319
330
|
/**
|
|
320
331
|
*
|
|
321
332
|
* @param {*} value
|
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -8,7 +8,7 @@ import { arrayQuickSort } from "../collection/array/arrayQuickSort.js";
|
|
|
8
8
|
import { max2 } from "../math/max2.js";
|
|
9
9
|
import { min2 } from "../math/min2.js";
|
|
10
10
|
import { computeSampleStandardDeviation } from "../math/statistics/computeSampleStandardDeviation.js";
|
|
11
|
-
import { aabb3_intersect_aabb3, boxSurfaceArea2 } from "./aabb3/AABB3Math.js";
|
|
11
|
+
import { _boxSurfaceArea2, aabb3_intersect_aabb3, boxSurfaceArea2 } from "./aabb3/AABB3Math.js";
|
|
12
12
|
import { isLeaf, LeafNode } from "./LeafNode.js";
|
|
13
13
|
import { Node } from "./Node.js";
|
|
14
14
|
import { surfaceAreaHeuristic } from "./sah/surfaceAreaHeuristic.js";
|
|
@@ -139,13 +139,135 @@ BinaryNode.prototype.setChildren = function (left, right) {
|
|
|
139
139
|
right.parentNode = this;
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param {Node} child
|
|
145
|
+
*/
|
|
146
|
+
BinaryNode.prototype.setChildLeft = function (child) {
|
|
147
|
+
assert.isNull(this.left, 'left');
|
|
148
|
+
|
|
149
|
+
this.left = child;
|
|
150
|
+
|
|
151
|
+
this.updateLeafNodeCount();
|
|
152
|
+
|
|
153
|
+
this.refit();
|
|
154
|
+
|
|
155
|
+
child.parentNode = this;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @param {Node} child
|
|
161
|
+
*/
|
|
162
|
+
BinaryNode.prototype.setChildRight = function (child) {
|
|
163
|
+
assert.isNull(this.right, 'right');
|
|
164
|
+
|
|
165
|
+
this.right = child;
|
|
166
|
+
|
|
167
|
+
this.updateLeafNodeCount();
|
|
168
|
+
|
|
169
|
+
this.refit();
|
|
170
|
+
|
|
171
|
+
child.parentNode = this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @see "Dynamic BVH" by Erin Catto / Blizzard
|
|
176
|
+
* @param {AABB3} node
|
|
177
|
+
* @param {AABB3} addition
|
|
178
|
+
* @returns {number}
|
|
179
|
+
*/
|
|
180
|
+
function inclusion_surface_area_heuristic(node, addition) {
|
|
181
|
+
const x0 = min2(node.x0, addition.x0);
|
|
182
|
+
const y0 = min2(node.y0, addition.y0);
|
|
183
|
+
const z0 = min2(node.z0, addition.z0);
|
|
184
|
+
|
|
185
|
+
const x1 = max2(node.x1, addition.x1);
|
|
186
|
+
const y1 = max2(node.y1, addition.y1);
|
|
187
|
+
const z1 = max2(node.z1, addition.z1);
|
|
188
|
+
|
|
189
|
+
return _boxSurfaceArea2(x0, y0, z0, x1, y1, z1) - boxSurfaceArea2(node);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
*
|
|
194
|
+
* @param {BinaryNode|LeafNode} node
|
|
195
|
+
* @param {AABB3} addition
|
|
196
|
+
*/
|
|
197
|
+
function inclusion_cost_lower_bound(node, addition) {
|
|
198
|
+
let n = node;
|
|
199
|
+
let r = boxSurfaceArea2(addition);
|
|
200
|
+
|
|
201
|
+
while (n !== null) {
|
|
202
|
+
|
|
203
|
+
r += n.costForInclusion(addition);
|
|
204
|
+
|
|
205
|
+
n = n.parentNode;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return r;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
|
|
213
|
+
* @param {AABB3} box
|
|
214
|
+
* @returns {BinaryNode|LeafNode}
|
|
215
|
+
*/
|
|
216
|
+
BinaryNode.prototype.__insertion_findSiblingFor = function (box) {
|
|
217
|
+
|
|
218
|
+
const open_set = [this];
|
|
219
|
+
let cursor = 1;
|
|
220
|
+
|
|
221
|
+
let best_cost = Infinity;
|
|
222
|
+
let best_node = this;
|
|
223
|
+
|
|
224
|
+
while (cursor > 0) {
|
|
225
|
+
const node = open_set[--cursor];
|
|
226
|
+
|
|
227
|
+
const cost = inclusion_surface_area_heuristic(node, box);
|
|
228
|
+
|
|
229
|
+
if (cost < best_cost) {
|
|
230
|
+
best_cost = cost;
|
|
231
|
+
best_node = node;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (node.isBinaryNode) {
|
|
235
|
+
|
|
236
|
+
if (node.isProtected()) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// consider pushing children into the queue
|
|
241
|
+
|
|
242
|
+
// compute lower bound for cost
|
|
243
|
+
const c_low = inclusion_cost_lower_bound(node, box);
|
|
244
|
+
|
|
245
|
+
if (c_low < best_cost) {
|
|
246
|
+
// worth-while to explore children
|
|
247
|
+
if (node.left !== null) {
|
|
248
|
+
open_set[cursor++] = node.left;
|
|
249
|
+
}
|
|
250
|
+
if (node.right !== null) {
|
|
251
|
+
open_set[cursor++] = node.right
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return best_node;
|
|
260
|
+
}
|
|
261
|
+
|
|
142
262
|
/**
|
|
143
263
|
*
|
|
144
264
|
* @param {AABB3} box
|
|
145
|
-
* @returns {Node}
|
|
265
|
+
* @returns {Node|BinaryNode|LeafNode}
|
|
146
266
|
*/
|
|
147
267
|
BinaryNode.prototype.findParentFor = function (box) {
|
|
148
268
|
let n = this;
|
|
269
|
+
let aCost = 0;
|
|
270
|
+
let bCost = 0;
|
|
149
271
|
|
|
150
272
|
for (; ;) {
|
|
151
273
|
|
|
@@ -181,8 +303,8 @@ BinaryNode.prototype.findParentFor = function (box) {
|
|
|
181
303
|
}
|
|
182
304
|
}
|
|
183
305
|
|
|
184
|
-
|
|
185
|
-
|
|
306
|
+
aCost = a.costForInclusion(box);
|
|
307
|
+
bCost = b.costForInclusion(box);
|
|
186
308
|
|
|
187
309
|
if (aCost === bCost) {
|
|
188
310
|
|
|
@@ -196,9 +318,9 @@ BinaryNode.prototype.findParentFor = function (box) {
|
|
|
196
318
|
|
|
197
319
|
}
|
|
198
320
|
|
|
199
|
-
//change costs to be
|
|
200
|
-
aCost = a.
|
|
201
|
-
bCost = b.
|
|
321
|
+
//change costs to be based on balance
|
|
322
|
+
aCost = a.leafNodeCount / boxSurfaceArea2(a);
|
|
323
|
+
bCost = b.leafNodeCount / boxSurfaceArea2(b);
|
|
202
324
|
}
|
|
203
325
|
|
|
204
326
|
if (aCost === bCost) {
|
|
@@ -518,26 +640,29 @@ function countLeaves(node) {
|
|
|
518
640
|
}
|
|
519
641
|
|
|
520
642
|
/**
|
|
521
|
-
*
|
|
643
|
+
* @deprecated Incorrect usage of SAH
|
|
522
644
|
* @return {number}
|
|
523
645
|
*/
|
|
524
646
|
BinaryNode.prototype.computeSAH = function () {
|
|
525
647
|
let leftLeaves, rightLeaves, leftArea, rightArea;
|
|
526
648
|
|
|
527
|
-
|
|
649
|
+
const left = this.left;
|
|
650
|
+
|
|
651
|
+
if (left === null) {
|
|
528
652
|
leftArea = 0;
|
|
529
653
|
leftLeaves = 0;
|
|
530
654
|
} else {
|
|
531
|
-
leftArea = boxSurfaceArea2(
|
|
532
|
-
leftLeaves =
|
|
655
|
+
leftArea = boxSurfaceArea2(left);
|
|
656
|
+
leftLeaves = left.leafNodeCount;
|
|
533
657
|
}
|
|
534
658
|
|
|
535
|
-
|
|
659
|
+
const right = this.right;
|
|
660
|
+
if (right === null) {
|
|
536
661
|
rightArea = 0;
|
|
537
662
|
rightLeaves = 0;
|
|
538
663
|
} else {
|
|
539
|
-
rightArea = boxSurfaceArea2(
|
|
540
|
-
rightLeaves =
|
|
664
|
+
rightArea = boxSurfaceArea2(right);
|
|
665
|
+
rightLeaves = right.leafNodeCount;
|
|
541
666
|
}
|
|
542
667
|
|
|
543
668
|
const thisArea = boxSurfaceArea2(this);
|
|
@@ -1065,34 +1190,96 @@ function transplantNewCommonParent(node, child) {
|
|
|
1065
1190
|
|
|
1066
1191
|
parent.bubbleExpandToFit(bNode);
|
|
1067
1192
|
|
|
1193
|
+
parent.updateLeafNodeCount();
|
|
1194
|
+
|
|
1068
1195
|
return bNode;
|
|
1069
1196
|
}
|
|
1070
1197
|
|
|
1198
|
+
|
|
1071
1199
|
/**
|
|
1072
1200
|
*
|
|
1073
1201
|
* @param {Node|BinaryNode|LeafNode} child
|
|
1074
1202
|
*/
|
|
1075
1203
|
BinaryNode.prototype.insertNode = function (child) {
|
|
1076
|
-
|
|
1077
|
-
assert.
|
|
1078
|
-
assert.
|
|
1204
|
+
|
|
1205
|
+
assert.notNull(child, "child");
|
|
1206
|
+
assert.defined(child, "child");
|
|
1207
|
+
assert.isInstanceOf(child, Node, 'child', "Node");
|
|
1208
|
+
assert.equal(child.parentNode, null, "parentNode must be null, otherwise Node still belongs to another tree");
|
|
1209
|
+
|
|
1210
|
+
const sibling = this.__insertion_findSiblingFor(child);
|
|
1211
|
+
|
|
1212
|
+
const sibling_parent = sibling.parentNode;
|
|
1213
|
+
if (sibling_parent === null) {
|
|
1214
|
+
// root node
|
|
1215
|
+
|
|
1216
|
+
if (sibling.left === null) {
|
|
1217
|
+
sibling.setChildLeft(child);
|
|
1218
|
+
} else if (sibling.right === null) {
|
|
1219
|
+
sibling.setChildRight(child);
|
|
1220
|
+
} else {
|
|
1221
|
+
const parent = new BinaryNode();
|
|
1222
|
+
|
|
1223
|
+
parent.setChildren(sibling.right, child);
|
|
1224
|
+
sibling.right = parent;
|
|
1225
|
+
parent.parentNode = sibling;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
} else {
|
|
1229
|
+
|
|
1230
|
+
// non-root
|
|
1231
|
+
|
|
1232
|
+
if (sibling_parent.left === sibling && sibling_parent.right === null) {
|
|
1233
|
+
|
|
1234
|
+
// right node is free, take it
|
|
1235
|
+
sibling_parent.setChildRight(child);
|
|
1236
|
+
|
|
1237
|
+
} else if (sibling_parent.right === sibling && sibling_parent.left === null) {
|
|
1238
|
+
|
|
1239
|
+
// left node is free, take it
|
|
1240
|
+
sibling_parent.setChildLeft(child);
|
|
1241
|
+
|
|
1242
|
+
} else {
|
|
1243
|
+
|
|
1244
|
+
transplantNewCommonParent(sibling, child)
|
|
1245
|
+
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
sibling_parent.bubbleRefit();
|
|
1249
|
+
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* @deprecated
|
|
1255
|
+
* @param {Node|BinaryNode|LeafNode} child
|
|
1256
|
+
*/
|
|
1257
|
+
BinaryNode.prototype.insertNode_old = function (child) {
|
|
1258
|
+
assert.notNull(child, "child");
|
|
1259
|
+
assert.defined(child, "child");
|
|
1260
|
+
assert.isInstanceOf(child, Node, 'child', "Node");
|
|
1079
1261
|
assert.equal(child.parentNode, null, "parentNode must be null, otherwise Node still belongs to another tree");
|
|
1080
1262
|
|
|
1081
1263
|
const node = this.findParentFor(child);
|
|
1082
1264
|
|
|
1083
1265
|
let bNode;
|
|
1084
1266
|
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1267
|
+
if (
|
|
1268
|
+
node.isBinaryNode &&
|
|
1269
|
+
!(node.isProtected() && node !== this) // protected node, can't insert into this subtree
|
|
1270
|
+
) {
|
|
1271
|
+
|
|
1272
|
+
if (node.left === null) {
|
|
1089
1273
|
node.left = child;
|
|
1090
1274
|
child.parentNode = node;
|
|
1091
1275
|
node.bubbleExpandToFit(child);
|
|
1276
|
+
|
|
1092
1277
|
} else if (node.right === null) {
|
|
1278
|
+
|
|
1093
1279
|
node.right = child;
|
|
1094
1280
|
child.parentNode = node;
|
|
1095
1281
|
node.bubbleExpandToFit(child);
|
|
1282
|
+
|
|
1096
1283
|
} else {
|
|
1097
1284
|
//take right child and insert another binary node there
|
|
1098
1285
|
bNode = new BinaryNode();
|
|
@@ -1106,18 +1293,17 @@ BinaryNode.prototype.insertNode = function (child) {
|
|
|
1106
1293
|
node.updateLeafNodeCount();
|
|
1107
1294
|
} else {
|
|
1108
1295
|
//need to do transplanting and introduce a new common parent
|
|
1109
|
-
|
|
1296
|
+
transplantNewCommonParent(node, child);
|
|
1110
1297
|
|
|
1111
|
-
bNode.updateLeafNodeCount();
|
|
1112
1298
|
}
|
|
1113
1299
|
|
|
1114
1300
|
};
|
|
1115
1301
|
|
|
1116
1302
|
/**
|
|
1117
|
-
*
|
|
1303
|
+
* @param {boolean} deep
|
|
1118
1304
|
* @returns {BinaryNode}
|
|
1119
1305
|
*/
|
|
1120
|
-
BinaryNode.prototype.clone = function (deep) {
|
|
1306
|
+
BinaryNode.prototype.clone = function (deep = false) {
|
|
1121
1307
|
const clone = new BinaryNode();
|
|
1122
1308
|
|
|
1123
1309
|
clone.x0 = this.x0;
|
package/core/bvh2/aabb3/AABB3.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { aabb3_computeDistanceAbovePlane } from "../../geom/3d/aabb/aabb3_computeDistanceAbovePlane.js";
|
|
7
7
|
import { computeAABB3PlaneSide } from "../../geom/3d/aabb/computeAABB3PlaneSide.js";
|
|
8
8
|
import computeMortonCode from "../../geom/3d/morton/Morton.js";
|
|
9
|
-
import {
|
|
9
|
+
import { boxSurfaceArea, intersectRay, intersectSegment } from "./AABB3Math.js";
|
|
10
10
|
import { aabb3_build_corners } from "../../geom/3d/aabb/aabb3_build_corners.js";
|
|
11
11
|
import { assert } from "../../assert.js";
|
|
12
12
|
|
|
@@ -81,7 +81,7 @@ AABB3.prototype.computeMortonCode = function () {
|
|
|
81
81
|
* @returns {number}
|
|
82
82
|
*/
|
|
83
83
|
AABB3.prototype.computeSurfaceArea = function () {
|
|
84
|
-
return
|
|
84
|
+
return boxSurfaceArea(this.x0, this.y0, this.z0, this.x1, this.y1, this.z1);
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
/**
|
|
@@ -296,7 +296,8 @@ AABB3.prototype.costForInclusion = function (other) {
|
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
|
-
*
|
|
299
|
+
* Surface area delta when including a given AABB
|
|
300
|
+
* 0 means that including a given AABB would not cause any change to total surface area
|
|
300
301
|
* @param {number} x0
|
|
301
302
|
* @param {number} y0
|
|
302
303
|
* @param {number} z0
|
|
@@ -540,7 +540,7 @@ function boxSurfaceArea(x0, y0, z0, x1, y1, z1) {
|
|
|
540
540
|
const dx = x1 - x0;
|
|
541
541
|
const dy = y1 - y0;
|
|
542
542
|
const dz = z1 - z0;
|
|
543
|
-
return (
|
|
543
|
+
return (dy * (dx + dz) + dz * dx) * 2; //2 of each side
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
/**
|
|
@@ -719,40 +719,6 @@ List.prototype.copy = function (other) {
|
|
|
719
719
|
}
|
|
720
720
|
};
|
|
721
721
|
|
|
722
|
-
/**
|
|
723
|
-
*
|
|
724
|
-
* @param {List} other
|
|
725
|
-
* @param {function} elementComparator
|
|
726
|
-
* @returns {number} -1, 0 or 1
|
|
727
|
-
*/
|
|
728
|
-
List.prototype.compare = function (other, elementComparator) {
|
|
729
|
-
const thisLength = this.length;
|
|
730
|
-
const otherLength = other.length;
|
|
731
|
-
|
|
732
|
-
const deltaLength = thisLength - otherLength;
|
|
733
|
-
|
|
734
|
-
if (deltaLength !== 0) {
|
|
735
|
-
return deltaLength;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
for (let i = 0; i < thisLength; i++) {
|
|
739
|
-
const thisElement = this.get(i);
|
|
740
|
-
const otherElement = other.get(i);
|
|
741
|
-
|
|
742
|
-
if (thisElement === otherElement) {
|
|
743
|
-
continue;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const elementDelta = elementComparator(thisElement, otherElement);
|
|
747
|
-
|
|
748
|
-
if (elementDelta !== 0) {
|
|
749
|
-
return elementDelta;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
return 0;
|
|
754
|
-
};
|
|
755
|
-
|
|
756
722
|
/**
|
|
757
723
|
* NOTE: do not modify resulting array
|
|
758
724
|
* @returns {T[]}
|
|
@@ -19,3 +19,19 @@ export const DataTypeByteSizes = {
|
|
|
19
19
|
[DataType.Float32]: 4,
|
|
20
20
|
[DataType.Float64]: 8
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {DataType} type
|
|
27
|
+
* @return {number}
|
|
28
|
+
*/
|
|
29
|
+
export function dataTypeByteSize(type) {
|
|
30
|
+
const size = DataTypeByteSizes[type];
|
|
31
|
+
|
|
32
|
+
if (size === undefined) {
|
|
33
|
+
throw new Error(`Unsupported type '${type}'`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return size;
|
|
37
|
+
}
|
package/engine/Engine.js
CHANGED
|
@@ -125,16 +125,29 @@ export class ShadedGeometry {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
__build_object() {
|
|
128
|
+
/**
|
|
129
|
+
* @type {THREE.Object3D}
|
|
130
|
+
*/
|
|
131
|
+
let object;
|
|
132
|
+
|
|
128
133
|
const mode = this.mode;
|
|
134
|
+
const shader = this.material;
|
|
135
|
+
const geo = this.geometry;
|
|
136
|
+
|
|
129
137
|
if (mode === DrawMode.Triangles) {
|
|
130
|
-
|
|
138
|
+
object = new Mesh(geo, shader);
|
|
131
139
|
} else if (mode === DrawMode.Lines) {
|
|
132
|
-
|
|
140
|
+
object = new Line(geo, shader);
|
|
133
141
|
} else if (mode === DrawMode.LineSegments) {
|
|
134
|
-
|
|
142
|
+
object = new LineSegments(geo, shader);
|
|
135
143
|
} else {
|
|
136
144
|
throw new Error(`Unsupported draw mode '${mode}'`);
|
|
137
145
|
}
|
|
146
|
+
|
|
147
|
+
object.matrixAutoUpdate = false;
|
|
148
|
+
object.frustumCulled = false;
|
|
149
|
+
|
|
150
|
+
this.__cached_object = object;
|
|
138
151
|
}
|
|
139
152
|
|
|
140
153
|
get bvh() {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
+
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
|
|
3
|
+
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
4
|
+
import { EngineConfiguration } from "../../../../EngineConfiguration.js";
|
|
5
|
+
import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
|
|
6
|
+
import { three_object_to_entity_composition } from "../three_object_to_entity_composition.js";
|
|
7
|
+
import { AttachmentSystem } from "../../../../ecs/attachment/AttachmentSystem.js";
|
|
8
|
+
|
|
9
|
+
const eh = new EngineHarness();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {EngineHarness} harness
|
|
14
|
+
* @return {Promise<void>}
|
|
15
|
+
*/
|
|
16
|
+
async function init(harness) {
|
|
17
|
+
const engine = harness.engine;
|
|
18
|
+
|
|
19
|
+
const config = new EngineConfiguration();
|
|
20
|
+
|
|
21
|
+
config.addSystem(new ShadedGeometrySystem(engine));
|
|
22
|
+
config.addSystem(new AttachmentSystem());
|
|
23
|
+
config.addLoader(GameAssetType.ModelGLTF_JSON, new GLTFAssetLoader());
|
|
24
|
+
|
|
25
|
+
await config.apply(engine);
|
|
26
|
+
|
|
27
|
+
eh.initialize().then(main);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {Engine} engine
|
|
33
|
+
*/
|
|
34
|
+
async function main(engine) {
|
|
35
|
+
|
|
36
|
+
const em = engine.entityManager;
|
|
37
|
+
|
|
38
|
+
EngineHarness.buildBasics({
|
|
39
|
+
engine,
|
|
40
|
+
enableWater: false
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const ecd = em.dataset;
|
|
44
|
+
|
|
45
|
+
const asset = await engine.assetManager.promise('moicon/06_04_hapro/08-clickable-assets-new/model.gltf', GameAssetType.ModelGLTF_JSON);
|
|
46
|
+
|
|
47
|
+
const three_object = asset.create();
|
|
48
|
+
|
|
49
|
+
const composition = three_object_to_entity_composition(three_object);
|
|
50
|
+
|
|
51
|
+
composition.build(ecd);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
init(eh);
|
package/engine/graphics/ecs/mesh-v2/{prototypeShadedGeometry.js → sample/prototypeShadedGeometry.js}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { EngineHarness } from "
|
|
2
|
-
import { ShadedGeometrySystem } from "
|
|
3
|
-
import EntityBuilder from "
|
|
4
|
-
import { Transform } from "
|
|
5
|
-
import { ShadedGeometry } from "
|
|
1
|
+
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
+
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.d.ts";
|
|
3
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.d.ts";
|
|
4
|
+
import { Transform } from "../../../../ecs/transform/Transform.d.ts";
|
|
5
|
+
import { ShadedGeometry } from "../ShadedGeometry.d.ts";
|
|
6
6
|
import { BoxBufferGeometry, MeshBasicMaterial } from "three";
|
|
7
7
|
|
|
8
8
|
const eh = new EngineHarness();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EntityNode } from "../../../ecs/parent/EntityNode.js";
|
|
2
|
+
import { Transform } from "../../../ecs/transform/Transform.js";
|
|
3
|
+
import { ShadedGeometry } from "./ShadedGeometry.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {THREE.Object3D} root
|
|
8
|
+
* @returns {EntityNode}
|
|
9
|
+
*/
|
|
10
|
+
export function three_object_to_entity_composition(root) {
|
|
11
|
+
const node = new EntityNode();
|
|
12
|
+
|
|
13
|
+
node.transform.fromMatrix4(root.matrix.elements);
|
|
14
|
+
|
|
15
|
+
node.entity.add(new Transform());
|
|
16
|
+
|
|
17
|
+
if (root.isMesh) {
|
|
18
|
+
if (root.isSkinnedMesh) {
|
|
19
|
+
throw new Error(`Skinned meshes are not supported`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
node.entity.add(ShadedGeometry.from(root.geometry, root.material));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const children = root.children;
|
|
26
|
+
const child_count = children.length;
|
|
27
|
+
for (let i = 0; i < child_count; i++) {
|
|
28
|
+
const child = children[i];
|
|
29
|
+
|
|
30
|
+
const child_node = three_object_to_entity_composition(child);
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
node.addChild(child_node);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return node;
|
|
37
|
+
}
|
|
@@ -51,6 +51,17 @@ function custom_attribute_format_uv(spec, source) {
|
|
|
51
51
|
spec.type = DataType.Float16;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @param {AttributeSpec} spec
|
|
57
|
+
* @param {THREE.BufferAttribute} source
|
|
58
|
+
*/
|
|
59
|
+
function custom_attribute_format_color(spec, source) {
|
|
60
|
+
// crush color data to 8 bit
|
|
61
|
+
spec.type = DataType.Uint8;
|
|
62
|
+
spec.normalized = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
/**
|
|
55
66
|
*
|
|
56
67
|
* @param {AttributeSpec} spec
|
|
@@ -70,7 +81,11 @@ function format_attribute(spec, source, name) {
|
|
|
70
81
|
case 'normal':
|
|
71
82
|
custom_attribute_format_normal(spec, source);
|
|
72
83
|
break;
|
|
84
|
+
case 'color':
|
|
85
|
+
custom_attribute_format_color(spec, source);
|
|
86
|
+
break;
|
|
73
87
|
default:
|
|
88
|
+
spec.normalized = source.normalized;
|
|
74
89
|
spec.type = typedArrayToDataType(source.array)
|
|
75
90
|
}
|
|
76
91
|
|
|
@@ -9,6 +9,9 @@ import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
|
9
9
|
import { passThrough } from "../../../../core/function/Functions.js";
|
|
10
10
|
import { to_half_float_uint16 } from "../../../../core/binary/to_half_float_uint16.js";
|
|
11
11
|
import { compute_micron_buffer_array_constructor } from "./compute_micron_buffer_array_constructor.js";
|
|
12
|
+
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
13
|
+
import { dataTypeByteSize } from "../../../../core/collection/table/DataTypeByteSizes.js";
|
|
14
|
+
import { clamp } from "../../../../core/math/clamp.js";
|
|
12
15
|
|
|
13
16
|
function UintArrayForCount(count) {
|
|
14
17
|
|
|
@@ -90,6 +93,17 @@ function copy_attribute_data(vertex_count, index_map_backward, itemSize, attribu
|
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* @param {number} value
|
|
99
|
+
* @returns {number}
|
|
100
|
+
*/
|
|
101
|
+
function resample_normalized_uint16_to_uint8(value) {
|
|
102
|
+
const normalized = clamp(value / 65535, 0, 1);
|
|
103
|
+
|
|
104
|
+
return Math.round(normalized * 255);
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
/**
|
|
94
108
|
*
|
|
95
109
|
* @param {number} value
|
|
@@ -105,7 +119,8 @@ function normalize_to_int8(value) {
|
|
|
105
119
|
const DataConverterType = {
|
|
106
120
|
None: passThrough,
|
|
107
121
|
Number2HalfFloat: to_half_float_uint16,
|
|
108
|
-
Normalize2Int8: normalize_to_int8
|
|
122
|
+
Normalize2Int8: normalize_to_int8,
|
|
123
|
+
ResampleNormalized_Uint16_to_Uint8: resample_normalized_uint16_to_uint8
|
|
109
124
|
};
|
|
110
125
|
|
|
111
126
|
/**
|
|
@@ -115,17 +130,36 @@ const DataConverterType = {
|
|
|
115
130
|
* @returns {DataConverterType}
|
|
116
131
|
*/
|
|
117
132
|
function compute_attribute_data_converter(source, spec) {
|
|
118
|
-
|
|
133
|
+
const target_type = spec.type;
|
|
134
|
+
if (target_type === DataType.Float16) {
|
|
119
135
|
return DataConverterType.Number2HalfFloat;
|
|
120
136
|
} else if (spec.normalized && !source.normalized) {
|
|
121
137
|
// source data can be normalized but isn't
|
|
122
|
-
if (
|
|
138
|
+
if (target_type === DataType.Int8) {
|
|
123
139
|
return DataConverterType.Normalize2Int8;
|
|
124
140
|
} else {
|
|
125
|
-
throw new Error(`Unsupported normalized type '${
|
|
141
|
+
throw new Error(`Unsupported normalized type '${target_type}'`);
|
|
126
142
|
}
|
|
127
143
|
} else {
|
|
128
|
-
|
|
144
|
+
const source_array = source.array;
|
|
145
|
+
|
|
146
|
+
const source_type = typedArrayToDataType(source_array);
|
|
147
|
+
|
|
148
|
+
const target_byte_size = dataTypeByteSize(target_type);
|
|
149
|
+
const source_byte_size = dataTypeByteSize(source_type)
|
|
150
|
+
|
|
151
|
+
if (target_byte_size !== source_byte_size) {
|
|
152
|
+
// wrong data size
|
|
153
|
+
|
|
154
|
+
if (target_type === DataType.Uint8 && source_type === DataType.Uint16) {
|
|
155
|
+
return DataConverterType.ResampleNormalized_Uint16_to_Uint8;
|
|
156
|
+
} else {
|
|
157
|
+
throw new Error(`Unsupported conversion ${source_type} -> ${target_type}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
} else {
|
|
161
|
+
return DataConverterType.None;
|
|
162
|
+
}
|
|
129
163
|
}
|
|
130
164
|
}
|
|
131
165
|
|
|
@@ -3,6 +3,7 @@ import { assert } from "../../../../core/assert.js";
|
|
|
3
3
|
import { computeTriangleRayIntersection } from "../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js";
|
|
4
4
|
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
|
+
import { sphere_array_intersects_ray } from "../../../../core/geom/3d/sphere/sphere_array_intersects_ray.js";
|
|
6
7
|
|
|
7
8
|
let id_counter = 0;
|
|
8
9
|
|
|
@@ -105,25 +106,18 @@ export class MicronGeometry {
|
|
|
105
106
|
|
|
106
107
|
const patch = stack[stack_cursor];
|
|
107
108
|
|
|
108
|
-
// using group bounds because it's conservative, as we want to be able to hit LOD_0
|
|
109
|
-
|
|
110
|
-
// sphere test
|
|
111
|
-
|
|
112
|
-
|
|
113
109
|
if (patch.lod === 0) {
|
|
114
110
|
// LOD 0 - source geometry
|
|
115
111
|
|
|
116
112
|
// cast against bounds
|
|
117
113
|
|
|
118
114
|
// sphere test
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// continue;
|
|
126
|
-
// }
|
|
115
|
+
if (!sphere_array_intersects_ray(patch.bounding_sphere,
|
|
116
|
+
origin_x, origin_y, origin_z,
|
|
117
|
+
direction_x, direction_y, direction_z
|
|
118
|
+
)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
127
121
|
|
|
128
122
|
// box test
|
|
129
123
|
if (!aabb3_array_intersects_ray(
|
|
@@ -183,13 +177,15 @@ export class MicronGeometry {
|
|
|
183
177
|
|
|
184
178
|
} else {
|
|
185
179
|
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
180
|
+
// using group bounds because it's conservative, as we want to be able to hit LOD_0
|
|
181
|
+
|
|
182
|
+
// sphere test
|
|
183
|
+
if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
|
|
184
|
+
origin_x, origin_y, origin_z,
|
|
185
|
+
direction_x, direction_y, direction_z
|
|
186
|
+
)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
193
189
|
|
|
194
190
|
|
|
195
191
|
// box test (more expensive, different volume)
|
|
@@ -455,7 +455,7 @@ function init() {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
// sample_gltf_sponza();
|
|
458
|
-
gltf_sample('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf');
|
|
458
|
+
// gltf_sample('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf');
|
|
459
459
|
// sample_lucy();
|
|
460
460
|
// sample_gltf_hapro_2();
|
|
461
461
|
// sample_gltf_hapro_1();
|
|
@@ -468,6 +468,12 @@ function init() {
|
|
|
468
468
|
// gltf_sample('moicon/29_Dec_2021_Nammo/1/model.gltf');
|
|
469
469
|
// gltf_sample('moicon/29_Dec_2021_Nammo/1-onematerial/model.gltf');
|
|
470
470
|
// gltf_sample('moicon/29_Dec_2021_Nammo/2/model.gltf');
|
|
471
|
+
// gltf_sample('moicon/03_Jan_22_Demo/1-ground_floor/model.gltf');
|
|
472
|
+
// gltf_sample('moicon/03_Jan_22_Demo/2-1st_floor/model.gltf');
|
|
473
|
+
// gltf_sample('moicon/03_Jan_22_Demo/3-area_ground_floor/model.gltf');
|
|
474
|
+
// gltf_sample('moicon/03_Jan_22_Demo/4-area_1st_floor/model.gltf');
|
|
475
|
+
// gltf_sample('moicon/03_Jan_22_Demo/8-assets/model.gltf');
|
|
476
|
+
gltf_sample('moicon/03_Jan_22_Demo/worker_test/model.gltf');
|
|
471
477
|
|
|
472
478
|
document.addEventListener("mousemove", onDocumentMouseMove);
|
|
473
479
|
|
|
@@ -160,6 +160,29 @@ export function shader_rewrite_standard(shader, uniforms, spec, column_count) {
|
|
|
160
160
|
|
|
161
161
|
if (attribute_spec_color !== undefined) {
|
|
162
162
|
// using color
|
|
163
|
+
const vx_color_value = `texelFetch(${gen_micron_vertex_attribute_texture_name('color')}, micron_vertex_uv, 0)`
|
|
164
|
+
|
|
165
|
+
rewrittenVertexShader = rewrittenVertexShader.replace(
|
|
166
|
+
'#include <color_vertex>',
|
|
167
|
+
`
|
|
168
|
+
#if defined( USE_COLOR_ALPHA )
|
|
169
|
+
vColor = vec4( 1.0 );
|
|
170
|
+
#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
|
|
171
|
+
vColor = vec3( 1.0 );
|
|
172
|
+
#endif
|
|
173
|
+
|
|
174
|
+
#ifdef USE_COLOR
|
|
175
|
+
|
|
176
|
+
#ifdef USE_COLOR_ALPHA
|
|
177
|
+
vColor *= ${vx_color_value}.rgba;
|
|
178
|
+
#else
|
|
179
|
+
vColor *= ${vx_color_value}.rgb;
|
|
180
|
+
#endif
|
|
181
|
+
|
|
182
|
+
#endif
|
|
183
|
+
|
|
184
|
+
`
|
|
185
|
+
);
|
|
163
186
|
|
|
164
187
|
}
|
|
165
188
|
|
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.34.
|
|
8
|
+
"version": "2.34.34",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|