@woosh/meep-engine 2.37.2 → 2.37.3
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/geom/Quaternion.js +31 -0
- package/core/model/ModuleRegistry.d.ts +3 -0
- package/editor/ecs/component/ObjectEditor.js +0 -0
- package/editor/ecs/component/createObjectEditor.js +155 -0
- package/editor/tools/SelectionTool.js +22 -1
- package/engine/ecs/transform/Transform.js +106 -5
- package/engine/ecs/transform/TransformFlags.js +8 -0
- package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +1 -11
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +10 -35
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +6 -1
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +14 -1
- package/engine/graphics/ecs/mesh-v2/allocate_transform_m4.js +51 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +44 -4
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +4 -2
- package/engine/graphics/ecs/path/entity/EntityPathStyle.d.ts +2 -2
- package/package.json +1 -1
- package/core/model/ClassRegistry.d.ts +0 -3
package/core/geom/Quaternion.js
CHANGED
|
@@ -763,6 +763,7 @@ class Quaternion {
|
|
|
763
763
|
}
|
|
764
764
|
|
|
765
765
|
/**
|
|
766
|
+
* XYZ order
|
|
766
767
|
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
767
768
|
* @param {number} x angle in X axis in radians
|
|
768
769
|
* @param {number} y angle in Y axis in radians
|
|
@@ -788,6 +789,36 @@ class Quaternion {
|
|
|
788
789
|
this.set(_x, _y, _z, _w);
|
|
789
790
|
}
|
|
790
791
|
|
|
792
|
+
/**
|
|
793
|
+
* XYZ order
|
|
794
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
795
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
796
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
797
|
+
* @param {number} x angle in X axis in radians
|
|
798
|
+
* @param {number} y angle in Y axis in radians
|
|
799
|
+
* @param {number} z angle in Z axis in radians
|
|
800
|
+
*/
|
|
801
|
+
fromEulerAnglesXYZ(x, y, z) {
|
|
802
|
+
const scaled_x = x * 0.5;
|
|
803
|
+
const scaled_y = y * 0.5;
|
|
804
|
+
const scaled_z = z * 0.5;
|
|
805
|
+
|
|
806
|
+
const s1 = Math.sin(scaled_x);
|
|
807
|
+
const s2 = Math.sin(scaled_y);
|
|
808
|
+
const s3 = Math.sin(scaled_z);
|
|
809
|
+
|
|
810
|
+
const c1 = Math.cos(scaled_x);
|
|
811
|
+
const c2 = Math.cos(scaled_y);
|
|
812
|
+
const c3 = Math.cos(scaled_z);
|
|
813
|
+
|
|
814
|
+
const _x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
815
|
+
const _y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
816
|
+
const _z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
817
|
+
const _w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
818
|
+
|
|
819
|
+
this.set(_x, _y, _z, _w);
|
|
820
|
+
}
|
|
821
|
+
|
|
791
822
|
/**
|
|
792
823
|
* Writes Pitch(Y), Yaw(Z), Roll(X) to a given vector
|
|
793
824
|
* @source http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
|
|
File without changes
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import EmptyView from "../../../view/elements/EmptyView.js";
|
|
2
|
+
import LabelView from "../../../view/common/LabelView.js";
|
|
3
|
+
|
|
4
|
+
class FieldValueAdapter {
|
|
5
|
+
read(object, field_name) {
|
|
6
|
+
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
write(object, field_name, value) {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @template T
|
|
16
|
+
*/
|
|
17
|
+
class FieldDescriptor {
|
|
18
|
+
constructor() {
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {string}
|
|
22
|
+
*/
|
|
23
|
+
this.name = "";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* typeof field
|
|
27
|
+
* @type {Class<T>}
|
|
28
|
+
*/
|
|
29
|
+
this.type = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @type {FieldValueAdapter|null}
|
|
34
|
+
*/
|
|
35
|
+
this.adapter = null;
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @template T
|
|
42
|
+
* @param {T} value
|
|
43
|
+
*/
|
|
44
|
+
function objectToClass(value) {
|
|
45
|
+
const type = typeof value;
|
|
46
|
+
|
|
47
|
+
switch (type) {
|
|
48
|
+
case "object":
|
|
49
|
+
return value.__ptoto__.constructor;
|
|
50
|
+
case "boolean":
|
|
51
|
+
return Boolean;
|
|
52
|
+
case "function":
|
|
53
|
+
return Function;
|
|
54
|
+
case "string":
|
|
55
|
+
return String;
|
|
56
|
+
case "number":
|
|
57
|
+
return Number;
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported type '${type}'`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} object
|
|
66
|
+
* @param {string} field_name
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
function isPublicField(object, field_name) {
|
|
70
|
+
if (field_name.startsWith('_')) {
|
|
71
|
+
// private
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} object
|
|
81
|
+
* @returns {FieldDescriptor[]}
|
|
82
|
+
*/
|
|
83
|
+
function extractObjectFields(object) {
|
|
84
|
+
const result = [];
|
|
85
|
+
const keys = Object.keys(object);
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < keys.length; i++) {
|
|
88
|
+
const key = keys[i];
|
|
89
|
+
|
|
90
|
+
if (!isPublicField(object, key)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const field_type = objectToClass(object[key]);
|
|
95
|
+
|
|
96
|
+
if (field_type === undefined) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const descriptor = new FieldDescriptor();
|
|
101
|
+
descriptor.name = key;
|
|
102
|
+
descriptor.type = field_type;
|
|
103
|
+
|
|
104
|
+
result.push(descriptor);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
* @param {Object} object
|
|
113
|
+
* @param {FieldDescriptor} field
|
|
114
|
+
* @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
|
|
115
|
+
*/
|
|
116
|
+
export function createFieldEditor(object, field, registry) {
|
|
117
|
+
const vResult = new EmptyView({});
|
|
118
|
+
|
|
119
|
+
vResult.addChild(new LabelView(field.name));
|
|
120
|
+
|
|
121
|
+
let vValue;
|
|
122
|
+
|
|
123
|
+
const factory = registry.get(field.type);
|
|
124
|
+
|
|
125
|
+
if (factory !== undefined) {
|
|
126
|
+
vValue = factory(object, field);
|
|
127
|
+
} else {
|
|
128
|
+
vValue = createObjectEditor(object, registry);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
vResult.addChild(vValue);
|
|
132
|
+
|
|
133
|
+
return vResult;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param {Object} object
|
|
139
|
+
* @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
|
|
140
|
+
*/
|
|
141
|
+
export function createObjectEditor(object, registry) {
|
|
142
|
+
const fields = extractObjectFields(object);
|
|
143
|
+
|
|
144
|
+
const vResult = new EmptyView({});
|
|
145
|
+
|
|
146
|
+
for (let i = 0; i < fields.length; i++) {
|
|
147
|
+
const field = fields[i];
|
|
148
|
+
|
|
149
|
+
const vField = createFieldEditor(object, field, registry);
|
|
150
|
+
|
|
151
|
+
vResult.addChild(vField);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return vResult;
|
|
155
|
+
}
|
|
@@ -18,6 +18,7 @@ import EditorEntity from "../ecs/EditorEntity.js";
|
|
|
18
18
|
import Terrain from "../../engine/ecs/terrain/ecs/Terrain.js";
|
|
19
19
|
import { SurfacePoint3 } from "../../core/geom/3d/SurfacePoint3.js";
|
|
20
20
|
import { makeScreenScissorFrustum } from "../../engine/graphics/camera/makeScreenScissorFrustum.js";
|
|
21
|
+
import { ShadedGeometrySystem } from "../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
21
22
|
|
|
22
23
|
class SelectionView extends View {
|
|
23
24
|
constructor() {
|
|
@@ -220,7 +221,8 @@ function findEntityOfNode(node) {
|
|
|
220
221
|
*/
|
|
221
222
|
export function pickingEntitySelection(point, engine, camera) {
|
|
222
223
|
|
|
223
|
-
const
|
|
224
|
+
const em = engine.entityManager;
|
|
225
|
+
const dataset = em.dataset;
|
|
224
226
|
|
|
225
227
|
const graphicsEngine = engine.graphics;
|
|
226
228
|
|
|
@@ -262,6 +264,25 @@ export function pickingEntitySelection(point, engine, camera) {
|
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
267
|
+
/**
|
|
268
|
+
*
|
|
269
|
+
* @type {ShadedGeometrySystem|undefined}
|
|
270
|
+
*/
|
|
271
|
+
const sgm = em.getSystem(ShadedGeometrySystem);
|
|
272
|
+
|
|
273
|
+
if (sgm !== undefined) {
|
|
274
|
+
const hits = sgm.raycast(
|
|
275
|
+
source.x, source.y, source.y,
|
|
276
|
+
rayDirection.x, rayDirection.y, rayDirection.z
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
for (let i = 0; i < hits.length; i++) {
|
|
280
|
+
const hit = hits[i];
|
|
281
|
+
|
|
282
|
+
tryAddEntity(hit.entity, hit.contact.position);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
265
286
|
//query render layers
|
|
266
287
|
engine.graphics.layers.traverse(function (layer) {
|
|
267
288
|
/**
|
|
@@ -7,13 +7,16 @@ import Quaternion from "../../../core/geom/Quaternion.js";
|
|
|
7
7
|
import { decompose_matrix_4_array } from "../../../core/geom/3d/decompose_matrix_4_array.js";
|
|
8
8
|
import { mat4 } from "gl-matrix";
|
|
9
9
|
import { compose_matrix4_array } from "../../../core/geom/3d/compose_matrix4_array.js";
|
|
10
|
+
import { TransformFlags } from "./TransformFlags.js";
|
|
11
|
+
import { allocate_transform_m4 } from "../../graphics/ecs/mesh-v2/allocate_transform_m4.js";
|
|
10
12
|
|
|
11
13
|
const delta = new Vector3();
|
|
12
14
|
|
|
13
|
-
const scratch_buffer = new ArrayBuffer(
|
|
15
|
+
const scratch_buffer = new ArrayBuffer(16 * 4);
|
|
14
16
|
|
|
15
17
|
const m4_0 = new Float32Array(scratch_buffer, 0, 16);
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
const FLAGS_DEFAULT = TransformFlags.AutomaticChangeDetection;
|
|
17
20
|
|
|
18
21
|
export class Transform {
|
|
19
22
|
/**
|
|
@@ -43,6 +46,79 @@ export class Transform {
|
|
|
43
46
|
*/
|
|
44
47
|
this.scale = new Vector3(1, 1, 1);
|
|
45
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @readonly
|
|
51
|
+
* @type {Float32Array}
|
|
52
|
+
*/
|
|
53
|
+
this.matrix = allocate_transform_m4();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @protected
|
|
57
|
+
* @type {number}
|
|
58
|
+
*/
|
|
59
|
+
this.flags = FLAGS_DEFAULT;
|
|
60
|
+
|
|
61
|
+
// watch changes
|
|
62
|
+
this.position.onChanged.add(this.__handle_component_change, this);
|
|
63
|
+
this.rotation.onChanged.add(this.__handle_component_change, this);
|
|
64
|
+
this.scale.onChanged.add(this.__handle_component_change, this);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
__handle_component_change() {
|
|
72
|
+
if (this.getFlag(TransformFlags.AutomaticChangeDetection)) {
|
|
73
|
+
this.setFlag(TransformFlags.MatrixNeedsUpdate);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {number|TransformFlags} flag
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
82
|
+
setFlag(flag) {
|
|
83
|
+
this.flags |= flag;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {number|TransformFlags} flag
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
clearFlag(flag) {
|
|
92
|
+
this.flags &= ~flag;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @param {number|TransformFlags} flag
|
|
98
|
+
* @param {boolean} value
|
|
99
|
+
*/
|
|
100
|
+
writeFlag(flag, value) {
|
|
101
|
+
if (value) {
|
|
102
|
+
this.setFlag(flag);
|
|
103
|
+
} else {
|
|
104
|
+
this.clearFlag(flag);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @param {number|TransformFlags} flag
|
|
111
|
+
* @returns {boolean}
|
|
112
|
+
*/
|
|
113
|
+
getFlag(flag) {
|
|
114
|
+
return (this.flags & flag) === flag;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
updateMatrix() {
|
|
119
|
+
compose_matrix4_array(this.matrix, this.position, this.rotation, this.scale);
|
|
120
|
+
|
|
121
|
+
this.clearFlag(TransformFlags.MatrixNeedsUpdate);
|
|
46
122
|
}
|
|
47
123
|
|
|
48
124
|
/**
|
|
@@ -82,6 +158,8 @@ export class Transform {
|
|
|
82
158
|
} else {
|
|
83
159
|
this.scale.copy(Vector3.one);
|
|
84
160
|
}
|
|
161
|
+
|
|
162
|
+
this.setFlag(TransformFlags.MatrixNeedsUpdate);
|
|
85
163
|
}
|
|
86
164
|
|
|
87
165
|
toJSON() {
|
|
@@ -100,6 +178,10 @@ export class Transform {
|
|
|
100
178
|
this.position.copy(other.position);
|
|
101
179
|
this.rotation.copy(other.rotation);
|
|
102
180
|
this.scale.copy(other.scale);
|
|
181
|
+
|
|
182
|
+
this.matrix.set(other.matrix);
|
|
183
|
+
|
|
184
|
+
this.flags = other.flags;
|
|
103
185
|
}
|
|
104
186
|
|
|
105
187
|
/**
|
|
@@ -154,10 +236,15 @@ export class Transform {
|
|
|
154
236
|
* @param {Transform} b
|
|
155
237
|
*/
|
|
156
238
|
multiplyTransforms(a, b) {
|
|
157
|
-
|
|
158
|
-
|
|
239
|
+
if (a.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
240
|
+
a.updateMatrix();
|
|
241
|
+
}
|
|
159
242
|
|
|
160
|
-
|
|
243
|
+
if (b.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
244
|
+
b.updateMatrix();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
mat4.multiply(m4_0, a.matrix, b.matrix);
|
|
161
248
|
|
|
162
249
|
this.fromMatrix4(m4_0);
|
|
163
250
|
}
|
|
@@ -183,7 +270,17 @@ export class Transform {
|
|
|
183
270
|
* @param {mat4|number[]|Float32Array} m
|
|
184
271
|
*/
|
|
185
272
|
fromMatrix4(m) {
|
|
273
|
+
const ad = this.getFlag(TransformFlags.AutomaticChangeDetection);
|
|
274
|
+
|
|
275
|
+
this.clearFlag(TransformFlags.AutomaticChangeDetection);
|
|
276
|
+
|
|
277
|
+
this.matrix.set(m);
|
|
278
|
+
|
|
186
279
|
decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
|
|
280
|
+
|
|
281
|
+
this.clearFlag(TransformFlags.MatrixNeedsUpdate);
|
|
282
|
+
|
|
283
|
+
this.writeFlag(TransformFlags.AutomaticChangeDetection, ad);
|
|
187
284
|
}
|
|
188
285
|
|
|
189
286
|
/**
|
|
@@ -195,6 +292,10 @@ export class Transform {
|
|
|
195
292
|
}
|
|
196
293
|
}
|
|
197
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @readonly
|
|
297
|
+
* @type {string}
|
|
298
|
+
*/
|
|
198
299
|
Transform.typeName = "Transform";
|
|
199
300
|
|
|
200
301
|
/**
|
|
@@ -2,16 +2,6 @@ import { System } from "../System.js";
|
|
|
2
2
|
import { TransformAttachment, TransformAttachmentFlags } from "./TransformAttachment.js";
|
|
3
3
|
import { Transform } from "../transform/Transform.js";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {Transform} parent_transform
|
|
8
|
-
* @param {Transform} attachment_transform
|
|
9
|
-
* @param {Transform} child_transform
|
|
10
|
-
*/
|
|
11
|
-
function update(parent_transform, attachment_transform, child_transform) {
|
|
12
|
-
child_transform.multiplyTransforms(parent_transform, attachment_transform);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
5
|
class UpdateContext {
|
|
16
6
|
constructor() {
|
|
17
7
|
/**
|
|
@@ -40,7 +30,7 @@ class UpdateContext {
|
|
|
40
30
|
}
|
|
41
31
|
|
|
42
32
|
update() {
|
|
43
|
-
|
|
33
|
+
this.transform.multiplyTransforms(this.parent_transform, this.attachment.transform);
|
|
44
34
|
}
|
|
45
35
|
|
|
46
36
|
link() {
|
|
@@ -3,6 +3,8 @@ import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
|
3
3
|
import { DrawMode } from "./DrawMode.js";
|
|
4
4
|
import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
|
|
5
5
|
import { aabb3_matrix4_project } from "../../../../core/geom/3d/aabb/aabb3_matrix4_project.js";
|
|
6
|
+
import { allocate_transform_m4 } from "./allocate_transform_m4.js";
|
|
7
|
+
import { TransformFlags } from "../../../ecs/transform/TransformFlags.js";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @readonly
|
|
@@ -18,39 +20,6 @@ const FLAG_SET_EQUALITY = ShadedGeometryFlags.CastShadow
|
|
|
18
20
|
| ShadedGeometryFlags.ReceiveShadow
|
|
19
21
|
;
|
|
20
22
|
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* @type {number}
|
|
24
|
-
*/
|
|
25
|
-
const TRANSFORM_ALLOCATOR_BUCKET_CAPACITY = 16;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* @type {ArrayBuffer|null}
|
|
29
|
-
*/
|
|
30
|
-
let transform_bucket = null;
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
* @type {number}
|
|
34
|
-
*/
|
|
35
|
-
let transform_bucket_cursor = TRANSFORM_ALLOCATOR_BUCKET_CAPACITY;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* custom Float32Array allocator, allocated memory in continuous chunks
|
|
39
|
-
* @returns {Float32Array}
|
|
40
|
-
*/
|
|
41
|
-
function allocate_transform_m4() {
|
|
42
|
-
if (transform_bucket_cursor >= TRANSFORM_ALLOCATOR_BUCKET_CAPACITY) {
|
|
43
|
-
transform_bucket = new ArrayBuffer(TRANSFORM_ALLOCATOR_BUCKET_CAPACITY * 4 * 16);
|
|
44
|
-
transform_bucket_cursor = 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const result = new Float32Array(transform_bucket, transform_bucket_cursor * 16 * 4, 16);
|
|
48
|
-
|
|
49
|
-
transform_bucket_cursor++;
|
|
50
|
-
|
|
51
|
-
return result;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
23
|
export class ShadedGeometry {
|
|
55
24
|
constructor() {
|
|
56
25
|
/**
|
|
@@ -216,7 +185,7 @@ export class ShadedGeometry {
|
|
|
216
185
|
* @return {null|number[]}
|
|
217
186
|
*/
|
|
218
187
|
get transform() {
|
|
219
|
-
return this.
|
|
188
|
+
return this.__c_transform.matrix;
|
|
220
189
|
}
|
|
221
190
|
|
|
222
191
|
/**
|
|
@@ -270,8 +239,14 @@ export class ShadedGeometry {
|
|
|
270
239
|
}
|
|
271
240
|
|
|
272
241
|
updateTransform() {
|
|
242
|
+
const t = this.__c_transform;
|
|
243
|
+
|
|
244
|
+
if (t.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
245
|
+
t.updateMatrix();
|
|
246
|
+
}
|
|
247
|
+
|
|
273
248
|
//
|
|
274
|
-
this.
|
|
249
|
+
this.__transform.set(t.matrix);
|
|
275
250
|
|
|
276
251
|
this.update_bounds();
|
|
277
252
|
|
|
@@ -22,6 +22,7 @@ import TaskState from "../../../../core/process/task/TaskState.js";
|
|
|
22
22
|
import {
|
|
23
23
|
bvh_query_user_data_overlaps_frustum
|
|
24
24
|
} from "../../../../core/bvh2/bvh3/bvh_query_user_data_overlaps_frustum.js";
|
|
25
|
+
import { TransformFlags } from "../../../ecs/transform/TransformFlags.js";
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -250,7 +251,11 @@ export class ShadedGeometrySystem extends System {
|
|
|
250
251
|
t.rotation.onChanged.add(sg.updateTransform, sg);
|
|
251
252
|
t.scale.onChanged.add(sg.updateTransform, sg);
|
|
252
253
|
|
|
253
|
-
t.
|
|
254
|
+
if (t.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
255
|
+
t.updateMatrix();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
sg.__transform.set(t.matrix);
|
|
254
259
|
sg.update_bounds();
|
|
255
260
|
|
|
256
261
|
// remember entity for lookups
|
|
@@ -7,6 +7,7 @@ import { ShadedGeometry } from "../ShadedGeometry.js";
|
|
|
7
7
|
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
8
8
|
import { SGMeshEvents } from "./SGMeshEvents.js";
|
|
9
9
|
import { ParentEntity } from "../../../../ecs/parent/ParentEntity.js";
|
|
10
|
+
import { EntityNode } from "../../../../ecs/parent/EntityNode.js";
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -76,7 +77,19 @@ export class SGMeshSystem extends System {
|
|
|
76
77
|
|
|
77
78
|
// TODO check that entity still exists, as we get to this point asynchronously
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
let entity_node = three_object_to_entity_composition(asset.create());
|
|
81
|
+
|
|
82
|
+
if (asset.has_root_transform) {
|
|
83
|
+
// apply root transform
|
|
84
|
+
|
|
85
|
+
const new_root = new EntityNode();
|
|
86
|
+
|
|
87
|
+
entity_node.transform.copy(asset.root_transform);
|
|
88
|
+
|
|
89
|
+
new_root.addChild(entity_node);
|
|
90
|
+
|
|
91
|
+
entity_node = new_root;
|
|
92
|
+
}
|
|
80
93
|
|
|
81
94
|
// attach parent entity to link hierarchy to this entity
|
|
82
95
|
entity_node.entity.add(ParentEntity.from(entity));
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Larger bucket sizes provide better cache locality
|
|
3
|
+
* Larger bucket sizes also cause more hanging GC references, as if one matrix element is still held - ENTIRE bucket is still referenced
|
|
4
|
+
* @type {number}
|
|
5
|
+
*/
|
|
6
|
+
const TRANSFORM_ALLOCATOR_BUCKET_CAPACITY = 16;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @type {ArrayBuffer|null}
|
|
11
|
+
*/
|
|
12
|
+
let transform_bucket = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
let transform_bucket_cursor = TRANSFORM_ALLOCATOR_BUCKET_CAPACITY;
|
|
19
|
+
|
|
20
|
+
const MATRIX_BYTE_SIZE = 4 * 16;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {Float32Array}
|
|
25
|
+
*/
|
|
26
|
+
const MATRIX_IDENTITY = new Float32Array([
|
|
27
|
+
1, 0, 0, 0,
|
|
28
|
+
0, 1, 0, 0,
|
|
29
|
+
0, 0, 1, 0,
|
|
30
|
+
0, 0, 0, 1
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* custom Float32Array allocator, allocated memory in continuous chunks
|
|
35
|
+
* @returns {Float32Array}
|
|
36
|
+
*/
|
|
37
|
+
export function allocate_transform_m4() {
|
|
38
|
+
if (transform_bucket_cursor >= TRANSFORM_ALLOCATOR_BUCKET_CAPACITY) {
|
|
39
|
+
transform_bucket = new ArrayBuffer(TRANSFORM_ALLOCATOR_BUCKET_CAPACITY * MATRIX_BYTE_SIZE);
|
|
40
|
+
transform_bucket_cursor = 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const result = new Float32Array(transform_bucket, transform_bucket_cursor * MATRIX_BYTE_SIZE, 16);
|
|
44
|
+
|
|
45
|
+
// initialize matrix
|
|
46
|
+
result.set(MATRIX_IDENTITY);
|
|
47
|
+
|
|
48
|
+
transform_bucket_cursor++;
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
@@ -4,10 +4,14 @@ import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
|
4
4
|
import { EngineConfiguration } from "../../../../EngineConfiguration.js";
|
|
5
5
|
import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
|
|
6
6
|
import { three_object_to_entity_composition } from "../three_object_to_entity_composition.js";
|
|
7
|
-
import { AttachmentSystem } from "../../../../ecs/attachment/AttachmentSystem.js";
|
|
8
7
|
import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
|
|
9
8
|
import { Camera } from "../../camera/Camera.js";
|
|
10
9
|
import { MicronRenderPlugin } from "../../../micron/plugin/MicronRenderPlugin.js";
|
|
10
|
+
import { enableEditor } from "../../../../../editor/enableEditor.js";
|
|
11
|
+
import Mesh from "../../mesh/Mesh.js";
|
|
12
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.js";
|
|
13
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
14
|
+
import { MeshSystem } from "../../mesh/MeshSystem.js";
|
|
11
15
|
|
|
12
16
|
const eh = new EngineHarness();
|
|
13
17
|
|
|
@@ -22,14 +26,20 @@ async function init(harness) {
|
|
|
22
26
|
const config = new EngineConfiguration();
|
|
23
27
|
|
|
24
28
|
config.addSystem(new ShadedGeometrySystem(engine));
|
|
25
|
-
config.addSystem(new AttachmentSystem());
|
|
26
29
|
config.addSystem(new TransformAttachmentSystem());
|
|
27
|
-
config.
|
|
30
|
+
config.addSystem(new MeshSystem(engine));
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
const gltfAssetLoader = new GLTFAssetLoader();
|
|
33
|
+
|
|
34
|
+
config.addLoader(GameAssetType.ModelGLTF_JSON, gltfAssetLoader);
|
|
35
|
+
config.addLoader(GameAssetType.ModelGLTF, gltfAssetLoader);
|
|
36
|
+
|
|
37
|
+
config.addPlugin(MicronRenderPlugin);
|
|
30
38
|
|
|
31
39
|
await config.apply(engine);
|
|
32
40
|
|
|
41
|
+
enableEditor(engine);
|
|
42
|
+
|
|
33
43
|
eh.initialize().then(main);
|
|
34
44
|
}
|
|
35
45
|
|
|
@@ -51,12 +61,32 @@ async function load_gltf(path, engine) {
|
|
|
51
61
|
const composition = three_object_to_entity_composition(three_object);
|
|
52
62
|
console.timeEnd('composition conversion');
|
|
53
63
|
|
|
64
|
+
if (asset.has_root_transform) {
|
|
65
|
+
composition.transform.multiplyTransforms(composition.transform, asset.root_transform);
|
|
66
|
+
}
|
|
67
|
+
|
|
54
68
|
console.time('composition build');
|
|
55
69
|
// console.profile('composition build');
|
|
56
70
|
composition.build(ecd);
|
|
57
71
|
// console.profileEnd('composition build');
|
|
58
72
|
console.timeEnd('composition build');
|
|
59
73
|
|
|
74
|
+
|
|
75
|
+
// console.log(composition);
|
|
76
|
+
// console.log(three_object);
|
|
77
|
+
//
|
|
78
|
+
// new EntityBuilder()
|
|
79
|
+
// .add(Mesh.fromJSON({
|
|
80
|
+
// url: path
|
|
81
|
+
// }))
|
|
82
|
+
// .add(Transform.fromJSON({
|
|
83
|
+
// position: {
|
|
84
|
+
// x: 5,
|
|
85
|
+
// y: 0,
|
|
86
|
+
// z: 0
|
|
87
|
+
// }
|
|
88
|
+
// }))
|
|
89
|
+
// .build(ecd);
|
|
60
90
|
}
|
|
61
91
|
|
|
62
92
|
async function timeout(t = 1) {
|
|
@@ -88,6 +118,16 @@ async function main(engine) {
|
|
|
88
118
|
// load_gltf('moicon/06_04_hapro/05-ground-floor/model.gltf', engine);
|
|
89
119
|
// load_gltf('moicon/06_04_hapro/04-1st-floor/model.gltf', engine);
|
|
90
120
|
// load_gltf('moicon/06_04_hapro/03-2nd-floor/model.gltf', engine);
|
|
121
|
+
|
|
122
|
+
// for (let i = 1; i <= 6; i++) {
|
|
123
|
+
// load_gltf(`moicon/10_Feb_22_Demo/${i}/model.gltf`, engine);
|
|
124
|
+
// }
|
|
125
|
+
// load_gltf(`moicon/10_Feb_22_Demo/1/model.gltf`, engine);
|
|
126
|
+
// load_gltf(`moicon/10_Feb_22_Demo/2/model.gltf`, engine);
|
|
127
|
+
// load_gltf(`moicon/10_Feb_22_Demo/3/model.gltf`, engine);
|
|
128
|
+
|
|
129
|
+
// load_gltf(`data/models/samples/transform-hierarchy.glb`, engine);
|
|
130
|
+
|
|
91
131
|
}
|
|
92
132
|
|
|
93
133
|
init(eh);
|
|
@@ -15,8 +15,10 @@ export function three_object_to_entity_composition(root) {
|
|
|
15
15
|
// copy object transform
|
|
16
16
|
node_transform.position.copy(root.position);
|
|
17
17
|
node_transform.scale.copy(root.scale);
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
node_transform.rotation.copy(root.quaternion);
|
|
19
|
+
|
|
20
|
+
//
|
|
21
|
+
node_transform.matrix.set(root.matrix.elements);
|
|
20
22
|
|
|
21
23
|
const entity = node.entity;
|
|
22
24
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ModuleRegistry} from "../../../../../core/model/ModuleRegistry";
|
|
2
2
|
import {EntityPathMarkerDefinition} from "./EntityPathMarkerDefinition";
|
|
3
3
|
|
|
4
4
|
export class EntityPathStyle {
|
|
@@ -8,5 +8,5 @@ export class EntityPathStyle {
|
|
|
8
8
|
|
|
9
9
|
public spacing: number
|
|
10
10
|
|
|
11
|
-
fromJSON(json: { marker_start: any, marker_end: any, marker_main: any, spacing?: number }, registry:
|
|
11
|
+
fromJSON(json: { marker_start: any, marker_end: any, marker_main: any, spacing?: number }, registry: ModuleRegistry): void
|
|
12
12
|
}
|
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.37.
|
|
8
|
+
"version": "2.37.3",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|