@needle-tools/engine 2.35.4-pre → 2.36.0-pre
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/CHANGELOG.md +26 -0
- package/dist/needle-engine.d.ts +213 -144
- package/dist/needle-engine.js +414 -358
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +99 -43
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/api.d.ts +3 -0
- package/lib/engine/api.js +3 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.d.ts +3 -0
- package/lib/engine/debug/debug.js +8 -0
- package/lib/engine/debug/debug.js.map +1 -0
- package/lib/engine/debug/debug_overlay.d.ts +7 -0
- package/lib/engine/debug/debug_overlay.js +213 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/engine/engine.js.map +1 -1
- package/lib/engine/engine_element_loading.js +1 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +1 -0
- package/lib/engine/engine_gameobject.js +13 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +4 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.d.ts +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -3
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +29 -28
- package/lib/engine/engine_physics.js +85 -86
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +43 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +1 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +1 -0
- package/lib/engine/engine_time.js +1 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +6 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_typestore.d.ts +1 -0
- package/lib/engine/engine_typestore.js +1 -0
- package/lib/engine/engine_typestore.js.map +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_render_objects.d.ts +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +5 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +5 -1
- package/lib/engine-components/Animation.js +21 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +1 -0
- package/lib/engine-components/AnimatorController.js +14 -7
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -1
- package/lib/engine-components/AudioSource.js +2 -2
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.d.ts +2 -2
- package/lib/engine-components/BoxHelperComponent.js +27 -9
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +11 -5
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +2 -0
- package/lib/engine-components/GroundProjection.js +18 -6
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +22 -0
- package/lib/engine-components/ReflectionProbe.js +134 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -0
- package/lib/engine-components/Renderer.d.ts +16 -4
- package/lib/engine-components/Renderer.js +96 -45
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +7 -7
- package/lib/engine-components/WebARSessionRoot.js +7 -7
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +9 -8
- package/lib/engine-components/WebXR.js +40 -24
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +4 -5
- package/lib/engine-components/WebXRAvatar.js +9 -8
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.d.ts +21 -21
- package/lib/engine-components/WebXRController.js +83 -63
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRGrabRendering.d.ts +3 -3
- package/lib/engine-components/WebXRGrabRendering.js +2 -2
- package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
- package/lib/engine-components/WebXRSync.d.ts +8 -8
- package/lib/engine-components/WebXRSync.js +15 -15
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +1 -0
- package/lib/engine-components/ui/EventSystem.js +21 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/api.ts +3 -0
- package/src/engine/codegen/register_types.js +293 -0
- package/src/engine/debug/debug.ts +9 -0
- package/src/engine/debug/debug_overlay.ts +224 -0
- package/src/engine/engine.ts +1 -1
- package/src/engine/engine_element_loading.ts +1 -1
- package/src/engine/engine_gameobject.ts +17 -4
- package/src/engine/engine_gltf_builtin_components.ts +5 -1
- package/src/engine/engine_mainloop_utils.ts +7 -3
- package/src/engine/engine_physics.ts +130 -130
- package/src/engine/engine_serialization_core.ts +41 -0
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_time.ts +2 -0
- package/src/engine/engine_types.ts +7 -1
- package/src/engine/engine_typestore.ts +2 -0
- package/src/engine/engine_utils.ts +3 -2
- package/src/engine/extensions/EXT_texture_exr.js +1 -1
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +2 -1
- package/src/engine/extensions/NEEDLE_render_objects.ts +4 -4
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +7 -0
- package/src/engine-components/Animation.ts +16 -1
- package/src/engine-components/AnimatorController.ts +19 -9
- package/src/engine-components/AudioSource.ts +3 -3
- package/src/engine-components/BoxHelperComponent.ts +29 -9
- package/src/engine-components/Component.ts +11 -5
- package/src/engine-components/GroundProjection.ts +22 -7
- package/src/engine-components/ReflectionProbe.ts +141 -0
- package/src/engine-components/Renderer.ts +116 -54
- package/src/engine-components/WebARSessionRoot.ts +16 -16
- package/src/engine-components/WebXR.ts +53 -48
- package/src/engine-components/WebXRAvatar.ts +16 -16
- package/src/engine-components/WebXRController.ts +133 -107
- package/src/engine-components/WebXRGrabRendering.ts +6 -6
- package/src/engine-components/WebXRSync.ts +20 -20
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/js-extensions/ExtensionUtils.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +26 -3
- package/lib/engine/debug/error_overlay.d.ts +0 -1
- package/lib/engine/debug/error_overlay.js +0 -114
- package/lib/engine/debug/error_overlay.js.map +0 -1
- package/src/engine/debug/error_overlay.ts +0 -126
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { Body, Box, Constraint, Vec3, World, Sphere as PhysicsSphere, Quaternion as PhysicsQuaternion } from 'cannon-es'
|
|
2
|
+
import { Box3, Camera, Intersection, Layers, Matrix4, Mesh, Object3D, Quaternion, Ray, Raycaster, Sphere, Vector2, Vector3 } from 'three'
|
|
3
3
|
import { Context } from './engine_setup';
|
|
4
4
|
import cannonDebugger from 'cannon-es-debugger'
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import { getParam } from "./engine_utils"
|
|
6
|
+
import { getWorldPosition, getWorldQuaternion, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils"
|
|
7
7
|
import {
|
|
8
8
|
IComponent as Component,
|
|
9
9
|
IGameObject as GameObject,
|
|
10
10
|
ICollider,
|
|
11
|
-
IRigidbody as Rigidbody,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
IRigidbody as Rigidbody,
|
|
12
|
+
$physicsKey,
|
|
13
|
+
Collision,
|
|
14
|
+
CannonCollision,
|
|
15
|
+
ICollisionContext
|
|
16
|
+
} from './engine_types';
|
|
17
17
|
import { Shape } from 'cannon-es';
|
|
18
18
|
import { InstancingUtil } from './engine_instancing';
|
|
19
19
|
import { foreachComponent } from './engine_gameobject';
|
|
20
|
-
import { getComponentInChildren } from './engine_components';
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
const debugPhysics =
|
|
24
|
-
const debugCollisions =
|
|
22
|
+
const debugPhysics = getParam("debugphysics");
|
|
23
|
+
const debugCollisions = getParam("debugcollisions");
|
|
25
24
|
|
|
26
25
|
export class BodyOptions {
|
|
27
26
|
mass: number = 1;
|
|
@@ -35,16 +34,16 @@ export class BodyOptions {
|
|
|
35
34
|
|
|
36
35
|
// TODO: refactor to return some kind of handle for adding/removing
|
|
37
36
|
class PhysicsObject {
|
|
38
|
-
obj:
|
|
39
|
-
parent:
|
|
40
|
-
body:
|
|
37
|
+
obj: Object3D;
|
|
38
|
+
parent: Object3D | null;
|
|
39
|
+
body: Body | null;
|
|
41
40
|
shapes: Array<Shape> = [];
|
|
42
41
|
collisonCallback: Function | null = null;
|
|
43
42
|
|
|
44
43
|
_hasRigidbody: boolean = false;
|
|
45
44
|
_didSleepLastStep: boolean = false;
|
|
46
45
|
|
|
47
|
-
constructor(obj:
|
|
46
|
+
constructor(obj: Object3D, body: Body | null) {
|
|
48
47
|
this.obj = obj;
|
|
49
48
|
this.parent = obj.parent;
|
|
50
49
|
this.body = body;
|
|
@@ -54,28 +53,28 @@ class PhysicsObject {
|
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
export class RaycastOptions {
|
|
57
|
-
ray:
|
|
58
|
-
cam:
|
|
59
|
-
screenPoint:
|
|
60
|
-
raycaster:
|
|
61
|
-
results: Array<
|
|
62
|
-
targets: Array<
|
|
56
|
+
ray: Ray | undefined = undefined;
|
|
57
|
+
cam: Camera | undefined | null = undefined;
|
|
58
|
+
screenPoint: Vector2 | undefined = undefined;
|
|
59
|
+
raycaster: Raycaster | undefined = undefined;
|
|
60
|
+
results: Array<Intersection> | undefined = undefined;
|
|
61
|
+
targets: Array<Object3D> | undefined = undefined;
|
|
63
62
|
recursive: boolean | undefined = true;
|
|
64
63
|
minDistance: number | undefined = undefined;
|
|
65
64
|
maxDistance: number | undefined = undefined;
|
|
66
65
|
lineThreshold: number | undefined = undefined;
|
|
67
|
-
layerMask:
|
|
68
|
-
ignore:
|
|
66
|
+
layerMask: Layers | number | undefined = undefined;
|
|
67
|
+
ignore: Object3D[] | undefined = undefined;
|
|
69
68
|
|
|
70
69
|
screenPointFromOffset(ox: number, oy: number) {
|
|
71
|
-
if (this.screenPoint === undefined) this.screenPoint = new
|
|
70
|
+
if (this.screenPoint === undefined) this.screenPoint = new Vector2();
|
|
72
71
|
this.screenPoint.x = ox / window.innerWidth * 2 - 1;
|
|
73
72
|
this.screenPoint.y = -(oy / window.innerHeight) * 2 + 1;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
setMask(mask: number) {
|
|
77
|
-
if (!this.layerMask) this.layerMask = new
|
|
78
|
-
const lm = this.layerMask as
|
|
76
|
+
if (!this.layerMask) this.layerMask = new Layers();
|
|
77
|
+
const lm = this.layerMask as Layers;
|
|
79
78
|
if (lm)
|
|
80
79
|
lm.mask = mask;
|
|
81
80
|
else this.layerMask = mask;
|
|
@@ -84,11 +83,11 @@ export class RaycastOptions {
|
|
|
84
83
|
public static AllLayers = 0xFFFFFFFF;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
export class SphereIntersection implements
|
|
86
|
+
export class SphereIntersection implements Intersection {
|
|
88
87
|
distance: number;
|
|
89
|
-
point:
|
|
90
|
-
object:
|
|
91
|
-
constructor(object:
|
|
88
|
+
point: Vector3;
|
|
89
|
+
object: Object3D;
|
|
90
|
+
constructor(object: Object3D, distance: number, point: Vector3) {
|
|
92
91
|
this.object = object;
|
|
93
92
|
this.distance = distance;
|
|
94
93
|
this.point = point;
|
|
@@ -99,9 +98,9 @@ export class Physics {
|
|
|
99
98
|
|
|
100
99
|
// raycasting
|
|
101
100
|
|
|
102
|
-
private readonly raycaster:
|
|
101
|
+
private readonly raycaster: Raycaster = new Raycaster();
|
|
103
102
|
private readonly defaultRaycastOptions: RaycastOptions = new RaycastOptions();
|
|
104
|
-
private readonly targetBuffer: Array<
|
|
103
|
+
private readonly targetBuffer: Array<Object3D> = new Array<Object3D>(1);
|
|
105
104
|
private readonly defaultThresholds = {
|
|
106
105
|
Mesh: {},
|
|
107
106
|
Line: { threshold: 0 },
|
|
@@ -111,60 +110,56 @@ export class Physics {
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
|
|
114
|
-
private sphereResults: Array<
|
|
115
|
-
private sphereMask:
|
|
116
|
-
public sphereOverlap(spherePos:
|
|
113
|
+
private sphereResults: Array<Intersection> = new Array<Intersection>();
|
|
114
|
+
private sphereMask: Layers = new Layers();
|
|
115
|
+
public sphereOverlap(spherePos: Vector3, radius: number, traverseChildsAfterHit: boolean = true): Array<Intersection> {
|
|
117
116
|
this.sphereResults.length = 0;
|
|
118
117
|
if (!this.context.scene) return this.sphereResults;
|
|
119
|
-
const sphere = new
|
|
118
|
+
const sphere = new Sphere(spherePos, radius);
|
|
120
119
|
const mask = this.sphereMask;
|
|
121
120
|
mask.enableAll();
|
|
122
121
|
mask.disable(2);
|
|
123
|
-
// mask testing
|
|
124
|
-
// const dummy = new THREE.Layers();
|
|
125
|
-
// dummy.set(2);
|
|
126
|
-
// console.log(dummy.mask, mask.test(dummy))
|
|
127
122
|
for (const ch of this.context.scene.children) {
|
|
128
|
-
|
|
129
|
-
if (i) this.sphereResults.push(i);
|
|
123
|
+
this.onSphereOverlap(ch, sphere, mask, this.sphereResults, traverseChildsAfterHit);
|
|
130
124
|
}
|
|
131
125
|
return this.sphereResults.sort((a, b) => a.distance - b.distance);
|
|
132
126
|
}
|
|
133
|
-
private tempBoundingBox:
|
|
134
|
-
private onSphereOverlap(obj:
|
|
135
|
-
if (obj.type === "Mesh") {
|
|
136
|
-
|
|
137
|
-
const mesh = obj as THREE.Mesh;
|
|
127
|
+
private tempBoundingBox: Box3 = new Box3();
|
|
128
|
+
private onSphereOverlap(obj: Object3D, sp: Sphere, mask: Layers, results: Array<Intersection>, traverseChildsAfterHit: boolean): void {
|
|
129
|
+
if (obj.type === "Mesh" && obj.layers.test(mask)) {
|
|
130
|
+
const mesh = obj as Mesh;
|
|
138
131
|
const geo = mesh.geometry;
|
|
139
132
|
if (!geo.boundingBox)
|
|
140
133
|
geo.computeBoundingBox();
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
134
|
+
if (geo.boundingBox) {
|
|
135
|
+
if (mesh.matrixWorldNeedsUpdate) mesh.updateMatrixWorld();
|
|
136
|
+
const test = this.tempBoundingBox.copy(geo.boundingBox).applyMatrix4(mesh.matrixWorld);
|
|
137
|
+
if (sp.intersectsBox(test)) {
|
|
138
|
+
// console.log(obj, obj.layers.test(mask), obj.layers.mask, mask.mask);
|
|
139
|
+
const wp = getWorldPosition(obj);
|
|
140
|
+
const dist = wp.distanceTo(sp.center);
|
|
141
|
+
const int = new SphereIntersection(obj, dist, sp.center.clone());
|
|
142
|
+
results.push(int);
|
|
143
|
+
if (!traverseChildsAfterHit) return;
|
|
144
|
+
}
|
|
150
145
|
}
|
|
151
146
|
}
|
|
152
|
-
|
|
147
|
+
if (obj.children) {
|
|
153
148
|
for (const ch of obj.children) {
|
|
154
|
-
const
|
|
155
|
-
|
|
149
|
+
const len = results.length;
|
|
150
|
+
this.onSphereOverlap(ch, sp, mask, results, traverseChildsAfterHit);
|
|
151
|
+
if (len != results.length && !traverseChildsAfterHit) return;
|
|
156
152
|
}
|
|
157
153
|
}
|
|
158
|
-
return null;
|
|
159
154
|
}
|
|
160
155
|
|
|
161
|
-
public raycastFromRay(ray:
|
|
156
|
+
public raycastFromRay(ray: Ray, options: RaycastOptions | null = null): Array<Intersection> {
|
|
162
157
|
const opts = options ?? this.defaultRaycastOptions;
|
|
163
158
|
opts.ray = ray;
|
|
164
159
|
return this.raycast(opts);
|
|
165
160
|
}
|
|
166
161
|
|
|
167
|
-
public raycast(options: RaycastOptions | null = null): Array<
|
|
162
|
+
public raycast(options: RaycastOptions | null = null): Array<Intersection> {
|
|
168
163
|
if (!options) options = this.defaultRaycastOptions;
|
|
169
164
|
const mp = options.screenPoint ?? this.context.input.mousePositionRC;
|
|
170
165
|
const rc = options.raycaster ?? this.raycaster;
|
|
@@ -194,14 +189,14 @@ export class Physics {
|
|
|
194
189
|
let results = options.results;
|
|
195
190
|
if (!results) {
|
|
196
191
|
if (!this.defaultRaycastOptions.results)
|
|
197
|
-
this.defaultRaycastOptions.results = new Array<
|
|
192
|
+
this.defaultRaycastOptions.results = new Array<Intersection>();
|
|
198
193
|
results = this.defaultRaycastOptions.results;
|
|
199
194
|
}
|
|
200
195
|
|
|
201
196
|
// layermask
|
|
202
|
-
// https://github.com/mrdoob/
|
|
197
|
+
// https://github.com/mrdoob/js/blob/master/src/core/Layers.js
|
|
203
198
|
if (options.layerMask !== undefined) {
|
|
204
|
-
if (options.layerMask instanceof
|
|
199
|
+
if (options.layerMask instanceof Layers)
|
|
205
200
|
rc.layers.mask = options.layerMask.mask;
|
|
206
201
|
else
|
|
207
202
|
rc.layers.mask = options.layerMask;
|
|
@@ -236,11 +231,11 @@ export class Physics {
|
|
|
236
231
|
|
|
237
232
|
private context: Context;
|
|
238
233
|
|
|
239
|
-
private world:
|
|
234
|
+
private world: World = new World();
|
|
240
235
|
private objects: Array<PhysicsObject> = [];
|
|
241
236
|
|
|
242
|
-
private tempPosition:
|
|
243
|
-
private tempQuaternion:
|
|
237
|
+
private tempPosition: Vector3 = new Vector3();
|
|
238
|
+
private tempQuaternion: Quaternion = new Quaternion();
|
|
244
239
|
|
|
245
240
|
constructor(context: Context) {
|
|
246
241
|
this.context = context;
|
|
@@ -248,7 +243,7 @@ export class Physics {
|
|
|
248
243
|
if (debugPhysics) {
|
|
249
244
|
// https://www.npmjs.com/package/cannon-es-debugger
|
|
250
245
|
const opts = {};
|
|
251
|
-
opts["onInit"] = (_body:
|
|
246
|
+
opts["onInit"] = (_body: Body, mesh: Mesh, _shape: Shape) => {
|
|
252
247
|
// ignore in raycast
|
|
253
248
|
mesh.layers.set(-1);
|
|
254
249
|
};
|
|
@@ -267,21 +262,21 @@ export class Physics {
|
|
|
267
262
|
this.world.addEventListener("postStep", listener);
|
|
268
263
|
}
|
|
269
264
|
|
|
270
|
-
public addConstraint(constraint:
|
|
265
|
+
public addConstraint(constraint: Constraint) {
|
|
271
266
|
this.world.addConstraint(constraint);
|
|
272
267
|
}
|
|
273
268
|
|
|
274
|
-
public setGravity(vec:
|
|
269
|
+
public setGravity(vec: Vector3) {
|
|
275
270
|
this.world.gravity.set(vec.x, vec.y, vec.z);
|
|
276
271
|
}
|
|
277
272
|
|
|
278
|
-
public multiplyGravity(vec:
|
|
273
|
+
public multiplyGravity(vec: Vector3) {
|
|
279
274
|
this.world.gravity.x *= vec.x;
|
|
280
275
|
this.world.gravity.y *= vec.y;
|
|
281
276
|
this.world.gravity.z *= vec.z;
|
|
282
277
|
}
|
|
283
278
|
|
|
284
|
-
public addBody(go: GameObject, body:
|
|
279
|
+
public addBody(go: GameObject, body: Body) {
|
|
285
280
|
for (let i = 0; i < this.objects.length; i++) {
|
|
286
281
|
const reg = this.objects[i];
|
|
287
282
|
if (reg.obj === go) {
|
|
@@ -295,7 +290,7 @@ export class Physics {
|
|
|
295
290
|
this.world.addBody(body);
|
|
296
291
|
}
|
|
297
292
|
|
|
298
|
-
public removeBody(go: GameObject, body:
|
|
293
|
+
public removeBody(go: GameObject, body: Body, removeCompletely: boolean = true) {
|
|
299
294
|
this.world.removeBody(body);
|
|
300
295
|
for (let i = 0; i < this.objects.length; i++) {
|
|
301
296
|
const reg = this.objects[i];
|
|
@@ -308,7 +303,7 @@ export class Physics {
|
|
|
308
303
|
}
|
|
309
304
|
}
|
|
310
305
|
|
|
311
|
-
public removeShape(obj:
|
|
306
|
+
public removeShape(obj: Object3D, shape: Shape) {
|
|
312
307
|
for (const reg of this.objects) {
|
|
313
308
|
if (reg.obj === obj) {
|
|
314
309
|
if (reg.body) {
|
|
@@ -321,13 +316,13 @@ export class Physics {
|
|
|
321
316
|
}
|
|
322
317
|
|
|
323
318
|
// TODO: make it work with rigibody in parent
|
|
324
|
-
public createBody(obj:
|
|
319
|
+
public createBody(obj: Object3D, settings: BodyOptions): Body {
|
|
325
320
|
const body = this.internalCreateBody(obj, null);
|
|
326
321
|
if (settings.mass)
|
|
327
322
|
body.mass = settings.mass;
|
|
328
323
|
if (settings.kinematic)
|
|
329
|
-
body.type =
|
|
330
|
-
else body.type =
|
|
324
|
+
body.type = Body.KINEMATIC;
|
|
325
|
+
else body.type = Body.DYNAMIC;
|
|
331
326
|
if (settings.drag)
|
|
332
327
|
body.linearDamping = settings.drag;
|
|
333
328
|
if (settings.angularDrag)
|
|
@@ -351,17 +346,17 @@ export class Physics {
|
|
|
351
346
|
return body;
|
|
352
347
|
}
|
|
353
348
|
|
|
354
|
-
public addBoxCollider(obj:
|
|
349
|
+
public addBoxCollider(obj: Object3D, trigger: boolean, center: Vector3, size: Vector3, rb: Rigidbody | null): Shape {
|
|
355
350
|
|
|
356
351
|
const scale = this.tempPosition;
|
|
357
352
|
obj.getWorldScale(scale);
|
|
358
353
|
|
|
359
|
-
const pos = new
|
|
354
|
+
const pos = new Vec3(
|
|
360
355
|
.5 * scale.x * size.x,
|
|
361
356
|
.5 * scale.y * size.y,
|
|
362
357
|
.5 * scale.z * size.z
|
|
363
358
|
);
|
|
364
|
-
const shape = new
|
|
359
|
+
const shape = new Box(pos);
|
|
365
360
|
shape.collisionResponse = !trigger;
|
|
366
361
|
|
|
367
362
|
center = center.clone();
|
|
@@ -377,12 +372,12 @@ export class Physics {
|
|
|
377
372
|
return shape;
|
|
378
373
|
}
|
|
379
374
|
|
|
380
|
-
public addSphereCollider(obj:
|
|
375
|
+
public addSphereCollider(obj: Object3D, center: Vector3, radius: number, rb: Rigidbody | null): Shape {
|
|
381
376
|
const scale = this.tempPosition;
|
|
382
377
|
obj.getWorldScale(scale);
|
|
383
378
|
|
|
384
379
|
const factor = Math.max(scale.x, scale.y, scale.z);
|
|
385
|
-
const shape = new
|
|
380
|
+
const shape = new PhysicsSphere(radius * factor);
|
|
386
381
|
// shape.collisionResponse = !trigger;
|
|
387
382
|
|
|
388
383
|
center = center.clone();
|
|
@@ -398,11 +393,11 @@ export class Physics {
|
|
|
398
393
|
return shape;
|
|
399
394
|
}
|
|
400
395
|
|
|
401
|
-
public addMeshCollider(_obj:
|
|
402
|
-
// see https://github.com/schteppe/
|
|
396
|
+
public addMeshCollider(_obj: Object3D) {
|
|
397
|
+
// see https://github.com/schteppe/js/blob/master/demos/bunny.html
|
|
403
398
|
if (debugPhysics)
|
|
404
399
|
console.warn("TODO mesh collider not yet supported")
|
|
405
|
-
// const geometry:
|
|
400
|
+
// const geometry: BufferGeometry = obj["geometry"];
|
|
406
401
|
// console.log(geometry);
|
|
407
402
|
// const size = geometry.boundingBox.max.clone();
|
|
408
403
|
// size.sub(geometry.boundingBox.min);
|
|
@@ -418,31 +413,31 @@ export class Physics {
|
|
|
418
413
|
// const i0 = geometry.index.array[i];
|
|
419
414
|
// const i1 = geometry.index.array[i + 1];
|
|
420
415
|
// const i2 = geometry.index.array[i + 2];
|
|
421
|
-
// const v0 = new
|
|
422
|
-
// const v1 = new
|
|
423
|
-
// const v2 = new
|
|
416
|
+
// const v0 = new Vector3(verts[i0 * 3], verts[i0 * 3 + 1], verts[i0 * 3 + 2]);
|
|
417
|
+
// const v1 = new Vector3(verts[i1 * 3], verts[i1 * 3 + 1], verts[i1 * 3 + 2]);
|
|
418
|
+
// const v2 = new Vector3(verts[i2 * 3], verts[i2 * 3 + 1], verts[i2 * 3 + 2]);
|
|
424
419
|
// const face = [v0, v1, v2];
|
|
425
420
|
// faces.push(face);
|
|
426
421
|
// }
|
|
427
|
-
// const convex = new
|
|
422
|
+
// const convex = new ConvexBufferGeometry(faces);
|
|
428
423
|
|
|
429
|
-
// var shape = new
|
|
424
|
+
// var shape = new ConvexPolyhedron({ verts, faces });
|
|
430
425
|
// this.addShape(obj, shape);
|
|
431
426
|
}
|
|
432
427
|
|
|
433
|
-
private isAlreadyRegistered(body:
|
|
428
|
+
private isAlreadyRegistered(body: Body): boolean {
|
|
434
429
|
for (const obj of this.objects) {
|
|
435
430
|
if (obj.body === body) return true;
|
|
436
431
|
}
|
|
437
432
|
return false;
|
|
438
433
|
}
|
|
439
434
|
|
|
440
|
-
private readonly tempMat1:
|
|
441
|
-
private readonly tempMat2:
|
|
435
|
+
private readonly tempMat1: Matrix4 = new Matrix4();
|
|
436
|
+
private readonly tempMat2: Matrix4 = new Matrix4();
|
|
442
437
|
|
|
443
|
-
private addShape(obj:
|
|
438
|
+
private addShape(obj: Object3D, shape: Shape, center: Vector3, rb: Rigidbody | null): Body | null {
|
|
444
439
|
|
|
445
|
-
let body:
|
|
440
|
+
let body: Body | null = null;
|
|
446
441
|
|
|
447
442
|
if (rb) {
|
|
448
443
|
// if (debugPhysics)
|
|
@@ -454,7 +449,7 @@ export class Physics {
|
|
|
454
449
|
else {
|
|
455
450
|
// console.log("has no rb", obj);
|
|
456
451
|
body = this.internalCreateBody(obj, null);
|
|
457
|
-
body.type =
|
|
452
|
+
body.type = Body.KINEMATIC;
|
|
458
453
|
}
|
|
459
454
|
|
|
460
455
|
if (body) {
|
|
@@ -476,14 +471,14 @@ export class Physics {
|
|
|
476
471
|
this.tempMat1.decompose(wp, wr, this.tempPosition);
|
|
477
472
|
}
|
|
478
473
|
else {
|
|
479
|
-
wp =
|
|
474
|
+
wp = getWorldPosition(obj);
|
|
480
475
|
const bp = body.position;
|
|
481
476
|
wp.x -= bp.x;
|
|
482
477
|
wp.y -= bp.y;
|
|
483
478
|
wp.z -= bp.z;
|
|
484
479
|
|
|
485
|
-
wr =
|
|
486
|
-
const r = new
|
|
480
|
+
wr = getWorldQuaternion(obj);
|
|
481
|
+
const r = new Quaternion(body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w);
|
|
487
482
|
wr.multiply(r.invert());
|
|
488
483
|
}
|
|
489
484
|
// get rotation difference
|
|
@@ -497,14 +492,14 @@ export class Physics {
|
|
|
497
492
|
// this.tempMat.setPosition(wp);
|
|
498
493
|
// this.tempMat.makeRotationFromQuaternion(wr);
|
|
499
494
|
// this.tempMat.multiplyMatrices(this.tempMat, rb?.gameObject.matrix);
|
|
500
|
-
// this.tempMat.decompose(this.tempPosition, this.tempQuaternion, new
|
|
495
|
+
// this.tempMat.decompose(this.tempPosition, this.tempQuaternion, new Vector3());
|
|
501
496
|
// wp.copy(this.tempPosition);
|
|
502
497
|
// }
|
|
503
498
|
|
|
504
499
|
// wp.applyQuaternion(wr);
|
|
505
500
|
|
|
506
|
-
const pos = new
|
|
507
|
-
const rot = new
|
|
501
|
+
const pos = new Vec3(wp.x, wp.y, wp.z);
|
|
502
|
+
const rot = new PhysicsQuaternion(wr.x, wr.y, wr.z, wr.w);
|
|
508
503
|
body.addShape(shape, pos, rot);
|
|
509
504
|
body.updateMassProperties();
|
|
510
505
|
this.world.addBody(body);
|
|
@@ -524,8 +519,8 @@ export class Physics {
|
|
|
524
519
|
}
|
|
525
520
|
}
|
|
526
521
|
|
|
527
|
-
private temp:
|
|
528
|
-
private tempQuat:
|
|
522
|
+
private temp: Vector3 = new Vector3();
|
|
523
|
+
private tempQuat: Quaternion = new Quaternion();
|
|
529
524
|
|
|
530
525
|
public postStep() {
|
|
531
526
|
this._isUpdatingPhysicsWorld = true;
|
|
@@ -533,43 +528,48 @@ export class Physics {
|
|
|
533
528
|
const entry = this.objects[i];
|
|
534
529
|
const body = entry.body;
|
|
535
530
|
if (!body || !body.world) continue;
|
|
531
|
+
const obj = entry.obj;
|
|
536
532
|
|
|
537
533
|
body.sleepTick(this.context.time.time);
|
|
538
534
|
|
|
539
535
|
if (debugPhysics) {
|
|
540
|
-
if (!entry._didSleepLastStep && body.sleepState ===
|
|
536
|
+
if (!entry._didSleepLastStep && body.sleepState === Body.SLEEPING) {
|
|
541
537
|
console.log("BODY SLEEPING", body);
|
|
542
538
|
}
|
|
543
|
-
else if (entry._didSleepLastStep && body.sleepState !==
|
|
539
|
+
else if (entry._didSleepLastStep && body.sleepState !== Body.SLEEPING) {
|
|
544
540
|
console.log("BODY WOKE UP", body);
|
|
545
541
|
}
|
|
546
542
|
}
|
|
547
|
-
entry._didSleepLastStep = body.sleepState ===
|
|
548
|
-
// if(body.sleepState ===
|
|
543
|
+
entry._didSleepLastStep = body.sleepState === Body.SLEEPING;
|
|
544
|
+
// if(body.sleepState === Body.SLEEPING) {
|
|
549
545
|
// console.log("SLEEP", body.name);
|
|
550
546
|
// }
|
|
551
|
-
// if (body.type ==
|
|
552
|
-
const obj = entry.obj;
|
|
547
|
+
// if (body.type == Body.KINEMATIC) continue;
|
|
553
548
|
|
|
554
|
-
if (body.type ===
|
|
555
|
-
const wp =
|
|
549
|
+
if (body.type === Body.KINEMATIC) {
|
|
550
|
+
const wp = getWorldPosition(obj, this.temp);
|
|
556
551
|
body.position.set(wp.x, wp.y, wp.z);
|
|
557
|
-
const rot =
|
|
552
|
+
const rot = getWorldQuaternion(obj, this.tempQuat);
|
|
558
553
|
body.quaternion.set(rot.x, rot.y, rot.z, rot.w);
|
|
559
554
|
continue;
|
|
560
555
|
}
|
|
561
556
|
|
|
557
|
+
if ((isNaN(body.position.x) || isNaN(body.position.y) || isNaN(body.position.z))) {
|
|
558
|
+
console.error("body position is NaN on", obj.name, "this usually means some colliders are overlapping", body.previousPosition, obj.position);
|
|
559
|
+
this.world.removeBody(body);
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
562
|
|
|
563
563
|
|
|
564
564
|
// when reparenting (e.g. attached to controller) I think it doesnt work with previous parent? need to test again, to tired now
|
|
565
565
|
if (entry.parent && obj.parent === entry.parent) {
|
|
566
566
|
|
|
567
|
-
|
|
567
|
+
setWorldQuaternionXYZW(obj,
|
|
568
568
|
body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w
|
|
569
569
|
);
|
|
570
570
|
|
|
571
571
|
const p = body.position;
|
|
572
|
-
|
|
572
|
+
setWorldPositionXYZ(obj, p.x, p.y, p.z);
|
|
573
573
|
|
|
574
574
|
if (body.velocity.length() > body.sleepSpeedLimit) {
|
|
575
575
|
InstancingUtil.markDirty(obj);
|
|
@@ -597,20 +597,20 @@ export class Physics {
|
|
|
597
597
|
this._isUpdatingPhysicsWorld = false;
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
-
private internalCreateBody(obj:
|
|
600
|
+
private internalCreateBody(obj: Object3D, shape: Shape | undefined | null): Body {
|
|
601
601
|
|
|
602
|
-
const body = new
|
|
602
|
+
const body = new Body();
|
|
603
603
|
body["_owner"] = obj;
|
|
604
604
|
body["_name"] = obj.name;
|
|
605
605
|
obj.getWorldPosition(this.tempPosition);
|
|
606
606
|
const pos = this.tempPosition;
|
|
607
|
-
body.position = new
|
|
607
|
+
body.position = new Vec3(pos.x, pos.y, pos.z);
|
|
608
608
|
|
|
609
609
|
const quat = this.tempQuaternion;
|
|
610
610
|
obj.getWorldQuaternion(quat);
|
|
611
|
-
body.quaternion = new
|
|
611
|
+
body.quaternion = new PhysicsQuaternion(quat.x, quat.y, quat.z, quat.w);
|
|
612
612
|
|
|
613
|
-
body.type =
|
|
613
|
+
body.type = Body.KINEMATIC;
|
|
614
614
|
if (shape) {
|
|
615
615
|
body.addShape(shape);
|
|
616
616
|
body.updateMassProperties();
|
|
@@ -618,7 +618,7 @@ export class Physics {
|
|
|
618
618
|
return body;
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
// private findObject(obj:
|
|
621
|
+
// private findObject(obj: Object3D): PhysicsObject | null {
|
|
622
622
|
// for (let i = 0; i < this.objects.length; i++) {
|
|
623
623
|
// const entry = this.objects[i];
|
|
624
624
|
// if (entry.obj == obj)
|
|
@@ -648,7 +648,7 @@ export class Physics {
|
|
|
648
648
|
|
|
649
649
|
private readonly collisionContext: ICollisionContext = new CollisionContext();
|
|
650
650
|
|
|
651
|
-
private raiseCollisionEvents(obj:
|
|
651
|
+
private raiseCollisionEvents(obj: Object3D, event: CannonCollision) {
|
|
652
652
|
const collision = new Collision(obj, event, this.collisionContext);
|
|
653
653
|
if (debugCollisions)
|
|
654
654
|
console.log("collision between", event.contact.bi, event.contact.bj, obj, event);
|
|
@@ -665,9 +665,9 @@ export class Physics {
|
|
|
665
665
|
}
|
|
666
666
|
}
|
|
667
667
|
|
|
668
|
-
private onEndContact(args: { bodyA:
|
|
669
|
-
// if(args.bodyB.sleepState !==
|
|
670
|
-
// console.log("END",
|
|
668
|
+
private onEndContact(args: { bodyA: Body, bodyB: Body }) {
|
|
669
|
+
// if(args.bodyB.sleepState !== Body.AWAKE) return;
|
|
670
|
+
// console.log("END", BODY_SLEEP_STATES, args.bodyB.sleepState);
|
|
671
671
|
const obj1 = args.bodyA[$physicsKey];
|
|
672
672
|
const obj2 = args.bodyB[$physicsKey];
|
|
673
673
|
// console.log(obj2);
|
|
@@ -690,7 +690,7 @@ export class Physics {
|
|
|
690
690
|
}
|
|
691
691
|
|
|
692
692
|
export interface IColliderProvider {
|
|
693
|
-
getCollider(obj:
|
|
693
|
+
getCollider(obj: Object3D): ICollider;
|
|
694
694
|
}
|
|
695
695
|
|
|
696
696
|
let colliderProvider: IColliderProvider | null = null;
|
|
@@ -700,7 +700,7 @@ export function registerColliderProvider(prov: IColliderProvider) {
|
|
|
700
700
|
|
|
701
701
|
class CollisionContext implements ICollisionContext {
|
|
702
702
|
|
|
703
|
-
getCollider(obj:
|
|
703
|
+
getCollider(obj: Object3D<Event>): ICollider {
|
|
704
704
|
return colliderProvider!.getCollider(obj);
|
|
705
705
|
}
|
|
706
706
|
|
|
@@ -5,6 +5,9 @@ import { Context } from "./engine_setup";
|
|
|
5
5
|
import { isPersistentAsset } from "./extensions/NEEDLE_persistent_assets";
|
|
6
6
|
import { SourceIdentifier } from "./engine_types";
|
|
7
7
|
import { debugExtension } from "../engine/engine_default_parameters";
|
|
8
|
+
import { LogType, showBalloonMessage } from "./debug/debug";
|
|
9
|
+
import { isLocalNetwork } from "./engine_networking_utils";
|
|
10
|
+
import { $BuiltInTypeFlag } from "./engine_typestore";
|
|
8
11
|
|
|
9
12
|
const debug = getParam("debugserializer");
|
|
10
13
|
|
|
@@ -312,6 +315,8 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
312
315
|
implictlyAssignPrimitiveTypes(obj, serializedData);
|
|
313
316
|
}
|
|
314
317
|
|
|
318
|
+
checkObjectAssignments(obj, serializedData);
|
|
319
|
+
|
|
315
320
|
if (obj.onAfterDeserialize !== undefined) {
|
|
316
321
|
obj.onAfterDeserialize(serializedData, context);
|
|
317
322
|
}
|
|
@@ -320,6 +325,42 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
320
325
|
return true;
|
|
321
326
|
}
|
|
322
327
|
|
|
328
|
+
const blockChecks = getParam("noerrors");
|
|
329
|
+
function checkObjectAssignments(obj: any, _serializedData?: any) {
|
|
330
|
+
if(blockChecks) return;
|
|
331
|
+
if (isLocalNetwork() === false) return;
|
|
332
|
+
if (!obj) return;
|
|
333
|
+
|
|
334
|
+
// ignore builtin components that we dont want to check
|
|
335
|
+
if(obj.constructor && obj.constructor[$BuiltInTypeFlag] === true) return;
|
|
336
|
+
|
|
337
|
+
const typeName = obj.constructor?.name as string;
|
|
338
|
+
// test if any object reference is missing serializable
|
|
339
|
+
const ownKeys = Object.getOwnPropertyNames(obj);
|
|
340
|
+
for (const key of ownKeys) {
|
|
341
|
+
if (key === "sourceId") continue;
|
|
342
|
+
const value = obj[key];
|
|
343
|
+
if (value === undefined || value === null) continue;
|
|
344
|
+
if (typeof value === "object") {
|
|
345
|
+
if (!value.isObject3D) {
|
|
346
|
+
if (typeof value["node"] === "number" || typeof value["guid"] === "string") {
|
|
347
|
+
const hasOtherKeys = Object.keys(value).length > 1;
|
|
348
|
+
if (!hasOtherKeys) {
|
|
349
|
+
showBalloonMessage(`<strong>Missing serialization for object reference!</strong>\n\nPlease change to: \n@serializable(Object3D)\n${key}? : Object3D;\n\nin script ${typeName}.ts\n<a href="https://docs.needle.tools/serializeable" target="_blank">documentation</a>`, LogType.Warn);
|
|
350
|
+
console.warn(typeName, key, obj[key], obj);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
else if (typeof value === "string") {
|
|
356
|
+
if (value.endsWith(".gltf") || value.endsWith(".glb")) {
|
|
357
|
+
showBalloonMessage(`<strong>Missing serialization for object reference!</strong>\n\nPlease change to: \n@serializable(AssetReference)\n${key}? : AssetReference;\n\nin script ${typeName}.ts\n<a href="https://docs.needle.tools/serializeable" target="_blank">documentation</a>`, LogType.Warn);
|
|
358
|
+
console.warn(typeName, key, obj[key], obj);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
323
364
|
function implictlyAssignPrimitiveTypes(obj: any, serializedData: any) {
|
|
324
365
|
// implictly assign serialized primitive fields
|
|
325
366
|
for (const key of Object.keys(serializedData)) {
|
|
@@ -600,7 +600,7 @@ export class Context {
|
|
|
600
600
|
this._isRendering = true;
|
|
601
601
|
this.renderRequiredTextures();
|
|
602
602
|
if (!this.isManagedExternally) {
|
|
603
|
-
if (this.composer) {
|
|
603
|
+
if (this.composer && !this.isInXR) {
|
|
604
604
|
this.composer.render();
|
|
605
605
|
}
|
|
606
606
|
else if (this.mainCamera) {
|