@@ -11,6 +11,7 @@
|
|
11
11
|
afterSerialize?(ext: BehaviorExtension, context: IContext): void;
|
12
12
|
}
|
13
13
|
|
14
|
+
/** internal USDZ behaviours extension */
|
14
15
|
export class BehaviorExtension implements IUSDExporterExtension {
|
15
16
|
|
16
17
|
get extensionName(): string {
|
@@ -116,7 +116,7 @@
|
|
116
116
|
margin-bottom: 5px;
|
117
117
|
`;
|
118
118
|
let licenseText = "Needle Engine — non commercial version";
|
119
|
-
console.log("%c" + licenseText, style)
|
119
|
+
console.log("%c " + licenseText, style)
|
120
120
|
}
|
121
121
|
|
122
122
|
function createLicenseElement() {
|
@@ -61,6 +61,8 @@
|
|
61
61
|
|
62
62
|
export class RapierPhysics implements IPhysicsEngine {
|
63
63
|
|
64
|
+
debugRenderColliders: boolean = false;
|
65
|
+
|
64
66
|
removeBody(obj: IComponent) {
|
65
67
|
if (!obj) return;
|
66
68
|
this.validate();
|
@@ -244,15 +246,12 @@
|
|
244
246
|
|
245
247
|
private rapierRay = new Ray({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 });
|
246
248
|
private raycastVectorsBuffer = new CircularBuffer(() => new Vector3(), 10);
|
247
|
-
|
248
|
-
* @param origin ray origin in screen or worldspace
|
249
|
-
* @param direction ray direction in worldspace
|
250
|
-
* @param maxDistance max distance to raycast
|
251
|
-
* @param solid if true it will also hit the collider if origin is already inside it
|
252
|
-
*/
|
253
|
-
public raycast(origin: Vec2 | Vec3, direction: Vec3 | undefined = undefined, maxDistance: number = Infinity, solid: boolean = true)
|
249
|
+
public raycast(origin?: Vec2 | Vec3, direction?: Vec3, maxDistance?: number, solid?: boolean)
|
254
250
|
: null | { point: Vector3, collider: ICollider } {
|
255
251
|
|
252
|
+
if (maxDistance === undefined) maxDistance = Infinity;
|
253
|
+
if (solid === undefined) solid = true;
|
254
|
+
|
256
255
|
const ray = this.getPhysicsRay(this.rapierRay, origin, direction);
|
257
256
|
if (!ray) return null;
|
258
257
|
|
@@ -270,9 +269,12 @@
|
|
270
269
|
return null;
|
271
270
|
}
|
272
271
|
|
273
|
-
public raycastAndGetNormal(origin
|
272
|
+
public raycastAndGetNormal(origin?: Vec2 | Vec3, direction?: Vec3, maxDistance?: number, solid?: boolean)
|
274
273
|
: null | { point: Vector3, normal: Vector3, collider: ICollider } {
|
275
274
|
|
275
|
+
if (maxDistance === undefined) maxDistance = Infinity;
|
276
|
+
if (solid === undefined) solid = true;
|
277
|
+
|
276
278
|
const ray = this.getPhysicsRay(this.rapierRay, origin, direction);
|
277
279
|
if (!ray) return null;
|
278
280
|
|
@@ -292,8 +294,13 @@
|
|
292
294
|
return null;
|
293
295
|
}
|
294
296
|
|
295
|
-
private getPhysicsRay(ray: Ray, origin
|
297
|
+
private getPhysicsRay(ray: Ray, origin?: Vec2 | Vec3, direction?: Vec3): Ray | null {
|
296
298
|
const cam = this.context?.mainCamera;
|
299
|
+
if (origin === undefined) {
|
300
|
+
const pos = this.context?.input.getPointerPosition(0);
|
301
|
+
if (pos) origin = pos;
|
302
|
+
else return null;
|
303
|
+
}
|
297
304
|
// if we get origin in 2d space we need to project it to 3d space
|
298
305
|
if (origin["z"] === undefined) {
|
299
306
|
if (!cam) {
|
@@ -306,6 +313,7 @@
|
|
306
313
|
vec3.z = 0;
|
307
314
|
// if the origin is in screen space we need to convert it to raycaster space
|
308
315
|
if (vec3.x > 1 || vec3.y > 1 || vec3.y < -1 || vec3.x < -1) {
|
316
|
+
if (debugPhysics) console.warn("Converting screenspace to raycast space", vec3)
|
309
317
|
this.context?.input.convertScreenspaceToRaycastSpace(vec3);
|
310
318
|
}
|
311
319
|
vec3.unproject(cam);
|
@@ -742,20 +750,27 @@
|
|
742
750
|
}
|
743
751
|
|
744
752
|
private updateDebugRendering(world: World) {
|
745
|
-
if (debugPhysics || debugColliderPlacement || showColliders) {
|
753
|
+
if (debugPhysics || debugColliderPlacement || showColliders || this.debugRenderColliders === true) {
|
746
754
|
if (!this.lines) {
|
747
755
|
const material = new LineBasicMaterial({
|
748
756
|
color: 0x227700,
|
757
|
+
fog: false,
|
749
758
|
// vertexColors: THREE.VertexColors
|
750
759
|
});
|
751
760
|
const geometry = new BufferGeometry();
|
752
761
|
this.lines = new LineSegments(geometry, material);
|
762
|
+
}
|
763
|
+
if (this.lines.parent !== this.context?.scene)
|
753
764
|
this.context?.scene.add(this.lines);
|
754
|
-
}
|
755
765
|
const buffers = world.debugRender();
|
756
766
|
this.lines.geometry.setAttribute('position', new BufferAttribute(buffers.vertices, 3));
|
757
767
|
this.lines.geometry.setAttribute('color', new BufferAttribute(buffers.colors, 4));
|
758
768
|
}
|
769
|
+
else {
|
770
|
+
if (this.lines) {
|
771
|
+
this.context?.scene.remove(this.lines);
|
772
|
+
}
|
773
|
+
}
|
759
774
|
}
|
760
775
|
|
761
776
|
public postStep() {
|
@@ -270,20 +270,20 @@
|
|
270
270
|
let fn: CallInfo | undefined;
|
271
271
|
let args = call.argument;
|
272
272
|
|
273
|
-
|
274
|
-
const eventMethod = hasMethod ? this.createEventMethod(target, call.method, args) : undefined;
|
275
|
-
|
276
|
-
if (call.argument !== undefined) {
|
273
|
+
if (args !== undefined) {
|
277
274
|
if (typeof args === "object") {
|
278
|
-
|
279
|
-
|
275
|
+
// Try to deserialize the call argument to either a object or a component reference
|
276
|
+
let argRes = objectSerializer.onDeserialize(call.argument, context);
|
277
|
+
if (!argRes) argRes = componentSerializer.onDeserialize(call.argument, context);
|
278
|
+
if (argRes) args = argRes;
|
280
279
|
}
|
281
|
-
fn = new CallInfo(eventMethod, call.enabled);
|
282
280
|
}
|
283
|
-
else
|
284
|
-
fn = new CallInfo(eventMethod, call.enabled);
|
285
281
|
|
282
|
+
// This is the final method we pass to the call info (or undefined if the method couldnt be resolved)
|
283
|
+
const eventMethod = hasMethod ? this.createEventMethod(target, call.method, args) : undefined;
|
284
|
+
fn = new CallInfo(eventMethod, call.enabled);
|
286
285
|
|
286
|
+
|
287
287
|
if (!fn.method)
|
288
288
|
fn[$eventListDebugInfo] = context.object?.name;
|
289
289
|
if (!target || !fn.method) {
|
@@ -32,6 +32,7 @@
|
|
32
32
|
|
33
33
|
export interface IInput {
|
34
34
|
convertScreenspaceToRaycastSpace(vec: Vec2): void;
|
35
|
+
getPointerPosition(i: number): Vec2 | null;
|
35
36
|
}
|
36
37
|
|
37
38
|
export interface IPhysics {
|
@@ -375,10 +376,15 @@
|
|
375
376
|
clearCaches();
|
376
377
|
|
377
378
|
// raycasting
|
378
|
-
/**
|
379
|
-
|
379
|
+
/** Fast raycast against physics colliders
|
380
|
+
* @param origin ray origin in screen or worldspace
|
381
|
+
* @param direction ray direction in worldspace
|
382
|
+
* @param maxDistance max distance to raycast
|
383
|
+
* @param solid if true it will also hit the collider if origin is already inside it
|
384
|
+
*/
|
385
|
+
raycast(origin?: Vec2 | Vec3, direction?: Vec3, maxDistance?: number, solid?: boolean): RaycastResult;
|
380
386
|
/** raycast that also gets the normal vector. If you don't need it use raycast() */
|
381
|
-
raycastAndGetNormal(origin
|
387
|
+
raycastAndGetNormal(origin?: Vec2 | Vec3, direction?: Vec3, maxDistance?: number, solid?: boolean): RaycastResult;
|
382
388
|
sphereOverlap(point: Vector3, radius: number): Array<SphereOverlapResult>;
|
383
389
|
|
384
390
|
// Collider methods
|
@@ -403,6 +409,8 @@
|
|
403
409
|
removeBody(body: IComponent);
|
404
410
|
|
405
411
|
// Joints
|
406
|
-
addFixedJoint(body1: IRigidbody, body2: IRigidbody)
|
407
|
-
addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3)
|
412
|
+
addFixedJoint(body1: IRigidbody, body2: IRigidbody);
|
413
|
+
addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3);
|
414
|
+
|
415
|
+
debugRenderColliders : boolean;
|
408
416
|
}
|
@@ -87,7 +87,9 @@
|
|
87
87
|
if (camGo && !this.setFromTargetPosition()) {
|
88
88
|
if (this.debugLog)
|
89
89
|
console.log("NO TARGET");
|
90
|
-
const
|
90
|
+
const worldPosition = getWorldPosition(camGo.cam);
|
91
|
+
const distanceToCenter = worldPosition.length();
|
92
|
+
const forward = new Vector3(0, 0, -distanceToCenter).applyMatrix4(camGo.cam.matrixWorld);
|
91
93
|
this.setTarget(forward, true);
|
92
94
|
}
|
93
95
|
}
|