@aura3d/physics 1.5.2 → 2.0.1
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/dist/ArcadeCharacterController.d.ts +53 -0
- package/dist/ArcadeCharacterController.d.ts.map +1 -0
- package/dist/ArcadeCharacterController.js +98 -0
- package/dist/ArcadeCharacterController.js.map +1 -0
- package/dist/{VehicleDynamics.d.ts → ArcadeVehicleTelemetry.d.ts} +14 -4
- package/dist/ArcadeVehicleTelemetry.d.ts.map +1 -0
- package/dist/{VehicleDynamics.js → ArcadeVehicleTelemetry.js} +37 -9
- package/dist/ArcadeVehicleTelemetry.js.map +1 -0
- package/dist/Constraint.d.ts +20 -4
- package/dist/Constraint.d.ts.map +1 -1
- package/dist/Constraint.js +34 -60
- package/dist/Constraint.js.map +1 -1
- package/dist/FightingCharacterController.d.ts +32 -0
- package/dist/FightingCharacterController.d.ts.map +1 -0
- package/dist/FightingCharacterController.js +76 -0
- package/dist/FightingCharacterController.js.map +1 -0
- package/dist/MeshBVH.d.ts +72 -0
- package/dist/MeshBVH.d.ts.map +1 -0
- package/dist/MeshBVH.js +244 -0
- package/dist/MeshBVH.js.map +1 -0
- package/dist/PhysicsDebugDraw.d.ts +40 -1
- package/dist/PhysicsDebugDraw.d.ts.map +1 -1
- package/dist/PhysicsDebugDraw.js +87 -17
- package/dist/PhysicsDebugDraw.js.map +1 -1
- package/dist/PhysicsWorld.d.ts +37 -18
- package/dist/PhysicsWorld.d.ts.map +1 -1
- package/dist/PhysicsWorld.js +231 -630
- package/dist/PhysicsWorld.js.map +1 -1
- package/dist/Raycast.d.ts +11 -0
- package/dist/Raycast.d.ts.map +1 -1
- package/dist/Raycast.js +62 -8
- package/dist/Raycast.js.map +1 -1
- package/dist/RigidBody.d.ts +16 -9
- package/dist/RigidBody.d.ts.map +1 -1
- package/dist/RigidBody.js +23 -75
- package/dist/RigidBody.js.map +1 -1
- package/dist/SurfaceQuery.d.ts +72 -0
- package/dist/SurfaceQuery.d.ts.map +1 -0
- package/dist/SurfaceQuery.js +89 -0
- package/dist/SurfaceQuery.js.map +1 -0
- package/dist/index.d.ts +62 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -17
- package/dist/index.js.map +1 -1
- package/dist/solverless.d.ts +37 -0
- package/dist/solverless.d.ts.map +1 -0
- package/dist/solverless.js +36 -0
- package/dist/solverless.js.map +1 -0
- package/dist/world.d.ts +18 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +17 -0
- package/dist/world.js.map +1 -0
- package/package.json +10 -2
- package/dist/CharacterController.d.ts +0 -83
- package/dist/CharacterController.d.ts.map +0 -1
- package/dist/CharacterController.js +0 -236
- package/dist/CharacterController.js.map +0 -1
- package/dist/ClothFixtures.d.ts +0 -87
- package/dist/ClothFixtures.d.ts.map +0 -1
- package/dist/ClothFixtures.js +0 -264
- package/dist/ClothFixtures.js.map +0 -1
- package/dist/Crowd.d.ts +0 -64
- package/dist/Crowd.d.ts.map +0 -1
- package/dist/Crowd.js +0 -209
- package/dist/Crowd.js.map +0 -1
- package/dist/FireSmokeFixtures.d.ts +0 -103
- package/dist/FireSmokeFixtures.d.ts.map +0 -1
- package/dist/FireSmokeFixtures.js +0 -271
- package/dist/FireSmokeFixtures.js.map +0 -1
- package/dist/FluidFixtures.d.ts +0 -75
- package/dist/FluidFixtures.d.ts.map +0 -1
- package/dist/FluidFixtures.js +0 -219
- package/dist/FluidFixtures.js.map +0 -1
- package/dist/FractureFixtures.d.ts +0 -68
- package/dist/FractureFixtures.d.ts.map +0 -1
- package/dist/FractureFixtures.js +0 -199
- package/dist/FractureFixtures.js.map +0 -1
- package/dist/NarrowPhase.d.ts +0 -11
- package/dist/NarrowPhase.d.ts.map +0 -1
- package/dist/NarrowPhase.js +0 -565
- package/dist/NarrowPhase.js.map +0 -1
- package/dist/Navigation.d.ts +0 -67
- package/dist/Navigation.d.ts.map +0 -1
- package/dist/Navigation.js +0 -261
- package/dist/Navigation.js.map +0 -1
- package/dist/PhysicsSandboxFixtures.d.ts +0 -53
- package/dist/PhysicsSandboxFixtures.d.ts.map +0 -1
- package/dist/PhysicsSandboxFixtures.js +0 -280
- package/dist/PhysicsSandboxFixtures.js.map +0 -1
- package/dist/PlatformerFixtures.d.ts +0 -70
- package/dist/PlatformerFixtures.d.ts.map +0 -1
- package/dist/PlatformerFixtures.js +0 -120
- package/dist/PlatformerFixtures.js.map +0 -1
- package/dist/SoftBodyFixtures.d.ts +0 -70
- package/dist/SoftBodyFixtures.d.ts.map +0 -1
- package/dist/SoftBodyFixtures.js +0 -272
- package/dist/SoftBodyFixtures.js.map +0 -1
- package/dist/Steering.d.ts +0 -161
- package/dist/Steering.d.ts.map +0 -1
- package/dist/Steering.js +0 -347
- package/dist/Steering.js.map +0 -1
- package/dist/VehicleDynamics.d.ts.map +0 -1
- package/dist/VehicleDynamics.js.map +0 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { KinematicBody } from "./KinematicBody.js";
|
|
2
|
+
/** Authored-unit fighting movement; this is not a physical-simulation controller. */
|
|
3
|
+
export class FightingCharacterController {
|
|
4
|
+
body;
|
|
5
|
+
walkSpeed;
|
|
6
|
+
crouchSpeed;
|
|
7
|
+
fastFallSpeed;
|
|
8
|
+
#state = "idle";
|
|
9
|
+
constructor(descriptor = {}) {
|
|
10
|
+
this.walkSpeed = positive(descriptor.walkSpeed ?? descriptor.maxSpeed ?? 4.5, "fighting controller walkSpeed");
|
|
11
|
+
this.crouchSpeed = positive(descriptor.crouchSpeed ?? this.walkSpeed * 0.45, "fighting controller crouchSpeed");
|
|
12
|
+
this.fastFallSpeed = positive(descriptor.fastFallSpeed ?? descriptor.maxFallSpeed ?? 20, "fighting controller fastFallSpeed");
|
|
13
|
+
this.body = new KinematicBody({
|
|
14
|
+
...descriptor,
|
|
15
|
+
id: descriptor.id ?? "fighter",
|
|
16
|
+
halfExtents: descriptor.halfExtents ?? [0.32, 0.9, 0.25],
|
|
17
|
+
maxSpeed: descriptor.maxSpeed ?? this.walkSpeed,
|
|
18
|
+
acceleration: descriptor.acceleration ?? 54,
|
|
19
|
+
airAcceleration: descriptor.airAcceleration ?? 24,
|
|
20
|
+
groundFriction: descriptor.groundFriction ?? 56,
|
|
21
|
+
airFriction: descriptor.airFriction ?? 4,
|
|
22
|
+
gravity: descriptor.gravity ?? 26,
|
|
23
|
+
jumpSpeed: descriptor.jumpSpeed ?? 9.4,
|
|
24
|
+
maxFallSpeed: descriptor.maxFallSpeed ?? Math.max(this.fastFallSpeed, 20),
|
|
25
|
+
dashSpeed: descriptor.dashSpeed ?? 8.6,
|
|
26
|
+
dashDuration: descriptor.dashDuration ?? 0.12,
|
|
27
|
+
dashCooldown: descriptor.dashCooldown ?? 0.18,
|
|
28
|
+
groundSnapDistance: descriptor.groundSnapDistance ?? 0.06,
|
|
29
|
+
lockDepth: descriptor.lockDepth ?? true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
walk(direction, speed) {
|
|
33
|
+
const magnitude = Math.min(1, Math.abs(finiteOrZero(direction)));
|
|
34
|
+
const facing = direction < 0 ? -1 : 1;
|
|
35
|
+
const targetSpeed = speed ?? (this.body.snapshot().crouching ? this.crouchSpeed : this.walkSpeed);
|
|
36
|
+
const normalizedSpeed = this.body.maxSpeed > 0 ? Math.min(1, positive(targetSpeed, "fighting controller walk speed") / this.body.maxSpeed) : 0;
|
|
37
|
+
this.body.move(facing * magnitude * normalizedSpeed);
|
|
38
|
+
this.#state = magnitude > 0 ? "walk" : this.#derive([]);
|
|
39
|
+
}
|
|
40
|
+
stop() { this.body.move(0); this.#state = this.#derive([]); }
|
|
41
|
+
jump() { this.body.jump(); this.#state = "jump"; }
|
|
42
|
+
dash(direction) { this.body.dash(direction); this.#state = "dash"; }
|
|
43
|
+
fastFall(speed = this.fastFallSpeed) { this.body.fastFall(speed); if (!this.body.grounded)
|
|
44
|
+
this.#state = "fast-fall"; }
|
|
45
|
+
crouch(active = true) { this.body.crouch(active); this.#state = active ? "crouch" : this.#derive([]); }
|
|
46
|
+
step(dt, options = {}) {
|
|
47
|
+
const events = this.body.step(dt, options);
|
|
48
|
+
this.#state = this.#derive(events);
|
|
49
|
+
return events;
|
|
50
|
+
}
|
|
51
|
+
snapshot() {
|
|
52
|
+
return { ...this.body.snapshot(), state: this.#state, walkSpeed: this.walkSpeed, crouchSpeed: this.crouchSpeed, fastFallSpeed: this.fastFallSpeed };
|
|
53
|
+
}
|
|
54
|
+
#derive(events) {
|
|
55
|
+
if (events.some((event) => event.type === "land"))
|
|
56
|
+
return "landing";
|
|
57
|
+
const snapshot = this.body.snapshot();
|
|
58
|
+
if (snapshot.crouching)
|
|
59
|
+
return "crouch";
|
|
60
|
+
if (snapshot.dashFramesRemaining > 0)
|
|
61
|
+
return "dash";
|
|
62
|
+
if (!snapshot.grounded)
|
|
63
|
+
return snapshot.velocity[1] < -this.fastFallSpeed * 0.5 ? "fast-fall" : "jump";
|
|
64
|
+
return Math.abs(snapshot.velocity[0]) > 0.05 ? "walk" : "idle";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function createFightingCharacterController(descriptor = {}) {
|
|
68
|
+
return new FightingCharacterController(descriptor);
|
|
69
|
+
}
|
|
70
|
+
function positive(value, label) {
|
|
71
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
72
|
+
throw new RangeError(`${label} must be finite and positive.`);
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
function finiteOrZero(value) { return Number.isFinite(value) ? value : 0; }
|
|
76
|
+
//# sourceMappingURL=FightingCharacterController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FightingCharacterController.js","sourceRoot":"","sources":["../../../../packages/physics/src/FightingCharacterController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Vec3 } from "./Shape.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bounding volume hierarchy over an indexed triangle mesh.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Every grounding system in the library was solving against an *approximation of* a
|
|
8
|
+
* surface rather than the surface itself. Turbo Drift sampled
|
|
9
|
+
* `TRACK_SURFACE_Y - VERGE_DROP * shoulderFraction` — a flat plane plus an analytic
|
|
10
|
+
* ramp — so on a banked or crowned corner the returned height was wrong and the car's
|
|
11
|
+
* tyres passed through the visible road. The fix is to ask the real triangles, which
|
|
12
|
+
* needs a spatial index: a naive per-sample scan over a 40k-triangle circuit is far too
|
|
13
|
+
* slow to run four times per frame.
|
|
14
|
+
*
|
|
15
|
+
* ## Determinism
|
|
16
|
+
*
|
|
17
|
+
* Construction must not depend on iteration order or floating-point tie-breaking, or two
|
|
18
|
+
* runs over the same mesh produce different trees and the same query returns different
|
|
19
|
+
* hits. Splits use the median along the widest axis with a stable index-based tiebreak,
|
|
20
|
+
* so the tree is a pure function of the input arrays.
|
|
21
|
+
*/
|
|
22
|
+
export interface MeshBVHBuildOptions {
|
|
23
|
+
/** Stop splitting at this triangle count. Larger leaves trade traversal for tests. */
|
|
24
|
+
readonly maxLeafTriangles?: number | undefined;
|
|
25
|
+
/** Hard depth cap, a safety valve against degenerate geometry. */
|
|
26
|
+
readonly maxDepth?: number | undefined;
|
|
27
|
+
}
|
|
28
|
+
interface BVHNode {
|
|
29
|
+
readonly min: [number, number, number];
|
|
30
|
+
readonly max: [number, number, number];
|
|
31
|
+
/** Triangle indices, leaf nodes only. */
|
|
32
|
+
readonly triangles?: readonly number[] | undefined;
|
|
33
|
+
readonly left?: number | undefined;
|
|
34
|
+
readonly right?: number | undefined;
|
|
35
|
+
}
|
|
36
|
+
export interface MeshBVH {
|
|
37
|
+
readonly kind: "aura-mesh-bvh";
|
|
38
|
+
readonly nodes: readonly BVHNode[];
|
|
39
|
+
readonly positions: Float32Array;
|
|
40
|
+
readonly indices: Uint32Array;
|
|
41
|
+
readonly triangleCount: number;
|
|
42
|
+
readonly maxDepth: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function buildMeshBVH(positions: Float32Array, indices: Uint32Array, options?: MeshBVHBuildOptions): MeshBVH;
|
|
45
|
+
export interface MeshRayHit {
|
|
46
|
+
readonly triangle: number;
|
|
47
|
+
readonly distance: number;
|
|
48
|
+
readonly point: Vec3;
|
|
49
|
+
/** Geometric normal, unit length, oriented against the ray. */
|
|
50
|
+
readonly normal: Vec3;
|
|
51
|
+
/** Barycentric coordinates, for interpolating vertex attributes. */
|
|
52
|
+
readonly barycentric: Vec3;
|
|
53
|
+
/** True when the ray struck the back face. */
|
|
54
|
+
readonly backFace: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface RaycastMeshOptions {
|
|
57
|
+
readonly maxDistance?: number | undefined;
|
|
58
|
+
/** Skip back faces. Off by default so a ray starting inside geometry still reports. */
|
|
59
|
+
readonly cullBackFaces?: boolean | undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Nearest triangle hit along a ray, using the BVH.
|
|
63
|
+
*
|
|
64
|
+
* The direction is normalised internally so `distance` is always in world units; a
|
|
65
|
+
* caller passing an unnormalised direction otherwise gets a distance scaled by its
|
|
66
|
+
* length, which is a silent and very confusing error.
|
|
67
|
+
*/
|
|
68
|
+
export declare function raycastMesh(bvh: MeshBVH, origin: Vec3, direction: Vec3, options?: RaycastMeshOptions): MeshRayHit | undefined;
|
|
69
|
+
/** Reference implementation, for testing the BVH. Never use in a hot path. */
|
|
70
|
+
export declare function raycastMeshBruteForce(bvh: MeshBVH, origin: Vec3, direction: Vec3, options?: RaycastMeshOptions): MeshRayHit | undefined;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=MeshBVH.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshBVH.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/MeshBVH.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,sFAAsF;IACtF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,UAAU,OAAO;IACf,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,yCAAyC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AA0BD,wBAAgB,YAAY,CAC1B,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CA0ET;AA2BD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAiED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,OAAO,GAAE,kBAAuB,GAC/B,UAAU,GAAG,SAAS,CAkCxB;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,OAAO,GAAE,kBAAuB,GAC/B,UAAU,GAAG,SAAS,CAaxB"}
|
package/dist/MeshBVH.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
function triangleBounds(positions, indices, triangle) {
|
|
2
|
+
const a = indices[triangle * 3] * 3;
|
|
3
|
+
const b = indices[triangle * 3 + 1] * 3;
|
|
4
|
+
const c = indices[triangle * 3 + 2] * 3;
|
|
5
|
+
const min = [Infinity, Infinity, Infinity];
|
|
6
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
7
|
+
for (const base of [a, b, c]) {
|
|
8
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
9
|
+
const value = positions[base + axis];
|
|
10
|
+
if (value < min[axis])
|
|
11
|
+
min[axis] = value;
|
|
12
|
+
if (value > max[axis])
|
|
13
|
+
max[axis] = value;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
min,
|
|
18
|
+
max,
|
|
19
|
+
centroid: [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2]
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function buildMeshBVH(positions, indices, options = {}) {
|
|
23
|
+
if (indices.length % 3 !== 0) {
|
|
24
|
+
throw new Error("buildMeshBVH requires an index count divisible by 3.");
|
|
25
|
+
}
|
|
26
|
+
const triangleCount = indices.length / 3;
|
|
27
|
+
const maxLeafTriangles = Math.max(1, options.maxLeafTriangles ?? 8);
|
|
28
|
+
const maxDepth = Math.max(1, options.maxDepth ?? 32);
|
|
29
|
+
const bounds = Array.from({ length: triangleCount }, (_, index) => triangleBounds(positions, indices, index));
|
|
30
|
+
const nodes = [];
|
|
31
|
+
let observedDepth = 0;
|
|
32
|
+
function build(triangles, depth) {
|
|
33
|
+
observedDepth = Math.max(observedDepth, depth);
|
|
34
|
+
const min = [Infinity, Infinity, Infinity];
|
|
35
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
36
|
+
for (const triangle of triangles) {
|
|
37
|
+
const b = bounds[triangle];
|
|
38
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
39
|
+
if (b.min[axis] < min[axis])
|
|
40
|
+
min[axis] = b.min[axis];
|
|
41
|
+
if (b.max[axis] > max[axis])
|
|
42
|
+
max[axis] = b.max[axis];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const index = nodes.length;
|
|
46
|
+
if (triangles.length <= maxLeafTriangles || depth >= maxDepth) {
|
|
47
|
+
nodes.push({ min, max, triangles: [...triangles] });
|
|
48
|
+
return index;
|
|
49
|
+
}
|
|
50
|
+
// Split on the widest axis; median split keeps the tree balanced regardless of
|
|
51
|
+
// how the mesh was authored.
|
|
52
|
+
let axis = 0;
|
|
53
|
+
let widest = -Infinity;
|
|
54
|
+
for (let candidate = 0; candidate < 3; candidate += 1) {
|
|
55
|
+
const extent = max[candidate] - min[candidate];
|
|
56
|
+
if (extent > widest) {
|
|
57
|
+
widest = extent;
|
|
58
|
+
axis = candidate;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Stable sort: centroid, then triangle index. Without the index tiebreak, equal
|
|
62
|
+
// centroids order differently between runs and the tree stops being deterministic.
|
|
63
|
+
const sorted = [...triangles].sort((left, right) => {
|
|
64
|
+
const delta = bounds[left].centroid[axis] - bounds[right].centroid[axis];
|
|
65
|
+
return delta !== 0 ? delta : left - right;
|
|
66
|
+
});
|
|
67
|
+
const mid = Math.floor(sorted.length / 2);
|
|
68
|
+
const leftTriangles = sorted.slice(0, mid);
|
|
69
|
+
const rightTriangles = sorted.slice(mid);
|
|
70
|
+
if (leftTriangles.length === 0 || rightTriangles.length === 0) {
|
|
71
|
+
nodes.push({ min, max, triangles: [...triangles] });
|
|
72
|
+
return index;
|
|
73
|
+
}
|
|
74
|
+
// Reserve this slot before recursing so child indices are stable.
|
|
75
|
+
nodes.push({ min, max });
|
|
76
|
+
const left = build(leftTriangles, depth + 1);
|
|
77
|
+
const right = build(rightTriangles, depth + 1);
|
|
78
|
+
nodes[index] = { min, max, left, right };
|
|
79
|
+
return index;
|
|
80
|
+
}
|
|
81
|
+
if (triangleCount > 0) {
|
|
82
|
+
build(Array.from({ length: triangleCount }, (_, index) => index), 0);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
nodes.push({ min: [0, 0, 0], max: [0, 0, 0], triangles: [] });
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
kind: "aura-mesh-bvh",
|
|
89
|
+
nodes,
|
|
90
|
+
positions,
|
|
91
|
+
indices,
|
|
92
|
+
triangleCount,
|
|
93
|
+
maxDepth: observedDepth
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Slab test. `tMax` lets a caller reject nodes beyond an existing best hit. */
|
|
97
|
+
function rayHitsAabb(origin, inverseDirection, node, tMax) {
|
|
98
|
+
let tMin = 0;
|
|
99
|
+
let tFar = tMax;
|
|
100
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
101
|
+
const inv = inverseDirection[axis];
|
|
102
|
+
let tNear = (node.min[axis] - origin[axis]) * inv;
|
|
103
|
+
let tFarAxis = (node.max[axis] - origin[axis]) * inv;
|
|
104
|
+
if (tNear > tFarAxis) {
|
|
105
|
+
const swap = tNear;
|
|
106
|
+
tNear = tFarAxis;
|
|
107
|
+
tFarAxis = swap;
|
|
108
|
+
}
|
|
109
|
+
if (tNear > tMin)
|
|
110
|
+
tMin = tNear;
|
|
111
|
+
if (tFarAxis < tFar)
|
|
112
|
+
tFar = tFarAxis;
|
|
113
|
+
if (tMin > tFar)
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
/** Möller–Trumbore. Returns undefined for a miss or a degenerate triangle. */
|
|
119
|
+
function intersectTriangle(positions, indices, triangle, origin, direction) {
|
|
120
|
+
const ia = indices[triangle * 3] * 3;
|
|
121
|
+
const ib = indices[triangle * 3 + 1] * 3;
|
|
122
|
+
const ic = indices[triangle * 3 + 2] * 3;
|
|
123
|
+
const ax = positions[ia], ay = positions[ia + 1], az = positions[ia + 2];
|
|
124
|
+
const bx = positions[ib], by = positions[ib + 1], bz = positions[ib + 2];
|
|
125
|
+
const cx = positions[ic], cy = positions[ic + 1], cz = positions[ic + 2];
|
|
126
|
+
const e1x = bx - ax, e1y = by - ay, e1z = bz - az;
|
|
127
|
+
const e2x = cx - ax, e2y = cy - ay, e2z = cz - az;
|
|
128
|
+
const px = direction[1] * e2z - direction[2] * e2y;
|
|
129
|
+
const py = direction[2] * e2x - direction[0] * e2z;
|
|
130
|
+
const pz = direction[0] * e2y - direction[1] * e2x;
|
|
131
|
+
const det = e1x * px + e1y * py + e1z * pz;
|
|
132
|
+
// A near-zero determinant means the ray is parallel to the plane, or the triangle is
|
|
133
|
+
// degenerate (zero area). Both are misses, and both would divide by ~0 below.
|
|
134
|
+
if (Math.abs(det) < 1e-12)
|
|
135
|
+
return undefined;
|
|
136
|
+
const invDet = 1 / det;
|
|
137
|
+
const tx = origin[0] - ax, ty = origin[1] - ay, tz = origin[2] - az;
|
|
138
|
+
const u = (tx * px + ty * py + tz * pz) * invDet;
|
|
139
|
+
if (u < -1e-9 || u > 1 + 1e-9)
|
|
140
|
+
return undefined;
|
|
141
|
+
const qx = ty * e1z - tz * e1y;
|
|
142
|
+
const qy = tz * e1x - tx * e1z;
|
|
143
|
+
const qz = tx * e1y - ty * e1x;
|
|
144
|
+
const v = (direction[0] * qx + direction[1] * qy + direction[2] * qz) * invDet;
|
|
145
|
+
if (v < -1e-9 || u + v > 1 + 1e-9)
|
|
146
|
+
return undefined;
|
|
147
|
+
const t = (e2x * qx + e2y * qy + e2z * qz) * invDet;
|
|
148
|
+
if (t < 0)
|
|
149
|
+
return undefined;
|
|
150
|
+
let nx = e1y * e2z - e1z * e2y;
|
|
151
|
+
let ny = e1z * e2x - e1x * e2z;
|
|
152
|
+
let nz = e1x * e2y - e1y * e2x;
|
|
153
|
+
const length = Math.hypot(nx, ny, nz);
|
|
154
|
+
if (length < 1e-12)
|
|
155
|
+
return undefined;
|
|
156
|
+
nx /= length;
|
|
157
|
+
ny /= length;
|
|
158
|
+
nz /= length;
|
|
159
|
+
// Orient the normal against the ray so callers always get an outward-facing surface.
|
|
160
|
+
const facing = nx * direction[0] + ny * direction[1] + nz * direction[2];
|
|
161
|
+
const backFace = facing > 0;
|
|
162
|
+
if (backFace) {
|
|
163
|
+
nx = -nx;
|
|
164
|
+
ny = -ny;
|
|
165
|
+
nz = -nz;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
triangle,
|
|
169
|
+
distance: t,
|
|
170
|
+
point: [origin[0] + direction[0] * t, origin[1] + direction[1] * t, origin[2] + direction[2] * t],
|
|
171
|
+
normal: [nx, ny, nz],
|
|
172
|
+
barycentric: [1 - u - v, u, v],
|
|
173
|
+
backFace
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Nearest triangle hit along a ray, using the BVH.
|
|
178
|
+
*
|
|
179
|
+
* The direction is normalised internally so `distance` is always in world units; a
|
|
180
|
+
* caller passing an unnormalised direction otherwise gets a distance scaled by its
|
|
181
|
+
* length, which is a silent and very confusing error.
|
|
182
|
+
*/
|
|
183
|
+
export function raycastMesh(bvh, origin, direction, options = {}) {
|
|
184
|
+
const length = Math.hypot(direction[0], direction[1], direction[2]);
|
|
185
|
+
if (!Number.isFinite(length) || length < 1e-12)
|
|
186
|
+
return undefined;
|
|
187
|
+
const dir = [direction[0] / length, direction[1] / length, direction[2] / length];
|
|
188
|
+
const maxDistance = options.maxDistance ?? Infinity;
|
|
189
|
+
const inverse = [
|
|
190
|
+
1 / (dir[0] === 0 ? 1e-30 : dir[0]),
|
|
191
|
+
1 / (dir[1] === 0 ? 1e-30 : dir[1]),
|
|
192
|
+
1 / (dir[2] === 0 ? 1e-30 : dir[2])
|
|
193
|
+
];
|
|
194
|
+
let best;
|
|
195
|
+
let bestDistance = maxDistance;
|
|
196
|
+
const stack = bvh.nodes.length > 0 ? [0] : [];
|
|
197
|
+
while (stack.length > 0) {
|
|
198
|
+
const nodeIndex = stack.pop();
|
|
199
|
+
const node = bvh.nodes[nodeIndex];
|
|
200
|
+
if (!node)
|
|
201
|
+
continue;
|
|
202
|
+
if (!rayHitsAabb(origin, inverse, node, bestDistance))
|
|
203
|
+
continue;
|
|
204
|
+
if (node.triangles) {
|
|
205
|
+
for (const triangle of node.triangles) {
|
|
206
|
+
const hit = intersectTriangle(bvh.positions, bvh.indices, triangle, origin, dir);
|
|
207
|
+
if (!hit)
|
|
208
|
+
continue;
|
|
209
|
+
if (hit.distance > bestDistance)
|
|
210
|
+
continue;
|
|
211
|
+
if (options.cullBackFaces && hit.backFace)
|
|
212
|
+
continue;
|
|
213
|
+
best = hit;
|
|
214
|
+
bestDistance = hit.distance;
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (node.left !== undefined)
|
|
219
|
+
stack.push(node.left);
|
|
220
|
+
if (node.right !== undefined)
|
|
221
|
+
stack.push(node.right);
|
|
222
|
+
}
|
|
223
|
+
return best;
|
|
224
|
+
}
|
|
225
|
+
/** Reference implementation, for testing the BVH. Never use in a hot path. */
|
|
226
|
+
export function raycastMeshBruteForce(bvh, origin, direction, options = {}) {
|
|
227
|
+
const length = Math.hypot(direction[0], direction[1], direction[2]);
|
|
228
|
+
if (!Number.isFinite(length) || length < 1e-12)
|
|
229
|
+
return undefined;
|
|
230
|
+
const dir = [direction[0] / length, direction[1] / length, direction[2] / length];
|
|
231
|
+
const maxDistance = options.maxDistance ?? Infinity;
|
|
232
|
+
let best;
|
|
233
|
+
for (let triangle = 0; triangle < bvh.triangleCount; triangle += 1) {
|
|
234
|
+
const hit = intersectTriangle(bvh.positions, bvh.indices, triangle, origin, dir);
|
|
235
|
+
if (!hit || hit.distance > maxDistance)
|
|
236
|
+
continue;
|
|
237
|
+
if (options.cullBackFaces && hit.backFace)
|
|
238
|
+
continue;
|
|
239
|
+
if (!best || hit.distance < best.distance)
|
|
240
|
+
best = hit;
|
|
241
|
+
}
|
|
242
|
+
return best;
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=MeshBVH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshBVH.js","sourceRoot":"","sources":["../../../../packages/physics/src/MeshBVH.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,47 @@ export type DebugLine = {
|
|
|
4
4
|
readonly from: Vec3;
|
|
5
5
|
readonly to: Vec3;
|
|
6
6
|
readonly color: Vec3;
|
|
7
|
+
/**
|
|
8
|
+
* What this line represents, so a consumer can filter or legend it.
|
|
9
|
+
*
|
|
10
|
+
* Without a category every line is an anonymous coloured segment, and a debug overlay that
|
|
11
|
+
* cannot say "these are contacts and those are joints" is decoration rather than a tool.
|
|
12
|
+
*/
|
|
13
|
+
readonly category?: DebugLineCategory;
|
|
7
14
|
};
|
|
15
|
+
export type DebugLineCategory = "collider" | "sensor" | "contact" | "normal" | "joint" | "sleeping" | "raycast";
|
|
16
|
+
/** A raycast to draw, so a developer can see the query they cannot otherwise observe. */
|
|
17
|
+
export type DebugRaycast = {
|
|
18
|
+
readonly origin: Vec3;
|
|
19
|
+
readonly direction: Vec3;
|
|
20
|
+
readonly distance: number;
|
|
21
|
+
/** True when the ray hit something; drawn in a different colour. */
|
|
22
|
+
readonly hit?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type PhysicsDebugDrawOptions = {
|
|
25
|
+
/** Draw contact points and their normals. */
|
|
26
|
+
readonly contacts?: boolean;
|
|
27
|
+
/** Draw joint anchors and the segment between them. */
|
|
28
|
+
readonly joints?: boolean;
|
|
29
|
+
/** Tint sleeping bodies differently from awake ones. */
|
|
30
|
+
readonly sleeping?: boolean;
|
|
31
|
+
/** Extra rays to visualise, which the world cannot know about. */
|
|
32
|
+
readonly raycasts?: readonly DebugRaycast[];
|
|
33
|
+
/** Length of a drawn contact normal, in world units. */
|
|
34
|
+
readonly normalLength?: number;
|
|
35
|
+
};
|
|
36
|
+
type DebugWorld = Pick<PhysicsWorld, "colliders" | "getBody"> & Partial<Pick<PhysicsWorld, "snapshot" | "constraints">>;
|
|
8
37
|
export declare class PhysicsDebugDraw {
|
|
9
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Build debug geometry for a world.
|
|
40
|
+
*
|
|
41
|
+
* WS-1.7 asks for colliders, contacts, normals, joints, sleeping state and raycasts. Only
|
|
42
|
+
* colliders existed, which is why the capability sat at "unproven with 0 consumers" — there was
|
|
43
|
+
* not enough here for a route to consume.
|
|
44
|
+
*
|
|
45
|
+
* Options default to off so the existing single-argument call keeps its previous output exactly.
|
|
46
|
+
*/
|
|
47
|
+
buildLines(world: DebugWorld, options?: PhysicsDebugDrawOptions): readonly DebugLine[];
|
|
10
48
|
}
|
|
49
|
+
export {};
|
|
11
50
|
//# sourceMappingURL=PhysicsDebugDraw.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhysicsDebugDraw.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"PhysicsDebugDraw.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,GACP,UAAU,GACV,SAAS,CAAC;AAEd,yFAAyF;AACzF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,wDAAwD;IACxD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,KAAK,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC,GAC3D,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC;AAE1D,qBAAa,gBAAgB;IAC3B;;;;;;;;OAQG;IACH,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,uBAA4B,GAAG,SAAS,SAAS,EAAE;CAuE3F"}
|
package/dist/PhysicsDebugDraw.js
CHANGED
|
@@ -1,18 +1,88 @@
|
|
|
1
1
|
export class PhysicsDebugDraw {
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Build debug geometry for a world.
|
|
4
|
+
*
|
|
5
|
+
* WS-1.7 asks for colliders, contacts, normals, joints, sleeping state and raycasts. Only
|
|
6
|
+
* colliders existed, which is why the capability sat at "unproven with 0 consumers" — there was
|
|
7
|
+
* not enough here for a route to consume.
|
|
8
|
+
*
|
|
9
|
+
* Options default to off so the existing single-argument call keeps its previous output exactly.
|
|
10
|
+
*/
|
|
11
|
+
buildLines(world, options = {}) {
|
|
3
12
|
const lines = [];
|
|
13
|
+
const snapshot = options.contacts || options.sleeping ? world.snapshot?.() : undefined;
|
|
14
|
+
const sleepingIds = new Set();
|
|
15
|
+
if (options.sleeping && snapshot) {
|
|
16
|
+
for (const body of snapshot.bodies) {
|
|
17
|
+
if (body.sleeping)
|
|
18
|
+
sleepingIds.add(body.id);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
4
21
|
for (const collider of world.colliders()) {
|
|
5
22
|
const body = world.getBody(collider.bodyId);
|
|
6
23
|
if (!body) {
|
|
7
24
|
continue;
|
|
8
25
|
}
|
|
9
|
-
appendColliderLines(lines, collider, body.position);
|
|
26
|
+
appendColliderLines(lines, collider, body.position, sleepingIds.has(body.id));
|
|
27
|
+
}
|
|
28
|
+
if (options.contacts && snapshot) {
|
|
29
|
+
const normalLength = options.normalLength ?? 0.25;
|
|
30
|
+
for (const contact of snapshot.contacts) {
|
|
31
|
+
const point = contact.point;
|
|
32
|
+
if (!point)
|
|
33
|
+
continue;
|
|
34
|
+
// A short cross at the contact point, then the normal as a ray out of it. Penetration is
|
|
35
|
+
// the number that matters for "is this body inside that one", so it tints the cross.
|
|
36
|
+
const penetrating = contact.penetration > 1e-4;
|
|
37
|
+
const crossColor = penetrating ? [1, 0.2, 0.2] : [0.2, 1, 0.4];
|
|
38
|
+
const size = normalLength * 0.25;
|
|
39
|
+
lines.push({ from: [point[0] - size, point[1], point[2]], to: [point[0] + size, point[1], point[2]], color: crossColor, category: "contact" });
|
|
40
|
+
lines.push({ from: [point[0], point[1] - size, point[2]], to: [point[0], point[1] + size, point[2]], color: crossColor, category: "contact" });
|
|
41
|
+
lines.push({
|
|
42
|
+
from: point,
|
|
43
|
+
to: [
|
|
44
|
+
point[0] + contact.normal[0] * normalLength,
|
|
45
|
+
point[1] + contact.normal[1] * normalLength,
|
|
46
|
+
point[2] + contact.normal[2] * normalLength
|
|
47
|
+
],
|
|
48
|
+
color: [1, 1, 0.3],
|
|
49
|
+
category: "normal"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (options.joints && world.constraints) {
|
|
54
|
+
for (const constraint of world.constraints()) {
|
|
55
|
+
const a = world.getBody(constraint.bodyA.id);
|
|
56
|
+
const b = world.getBody(constraint.bodyB.id);
|
|
57
|
+
if (!a || !b)
|
|
58
|
+
continue;
|
|
59
|
+
// The segment between the two bodies a joint connects. A joint that has come apart is
|
|
60
|
+
// visible as a segment that keeps growing, which is exactly the failure mode that made
|
|
61
|
+
// the former silent backend divergence so hard to spot.
|
|
62
|
+
lines.push({ from: a.position, to: b.position, color: [0.9, 0.4, 1], category: "joint" });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const ray of options.raycasts ?? []) {
|
|
66
|
+
const length = Number.isFinite(ray.distance) ? ray.distance : 1;
|
|
67
|
+
lines.push({
|
|
68
|
+
from: ray.origin,
|
|
69
|
+
to: [
|
|
70
|
+
ray.origin[0] + ray.direction[0] * length,
|
|
71
|
+
ray.origin[1] + ray.direction[1] * length,
|
|
72
|
+
ray.origin[2] + ray.direction[2] * length
|
|
73
|
+
],
|
|
74
|
+
color: ray.hit ? [1, 0.35, 0.35] : [0.5, 0.5, 0.55],
|
|
75
|
+
category: "raycast"
|
|
76
|
+
});
|
|
10
77
|
}
|
|
11
78
|
return lines;
|
|
12
79
|
}
|
|
13
80
|
}
|
|
14
|
-
function appendColliderLines(lines, collider, position) {
|
|
15
|
-
|
|
81
|
+
function appendColliderLines(lines, collider, position, sleeping = false) {
|
|
82
|
+
// Sleeping bodies are drawn dim: a body that has gone to sleep and should not have is otherwise
|
|
83
|
+
// indistinguishable from one that is simply not moving.
|
|
84
|
+
const color = sleeping ? [0.4, 0.42, 0.5] : collider.sensor ? [1, 0.75, 0] : [0.1, 0.8, 1];
|
|
85
|
+
const category = sleeping ? "sleeping" : collider.sensor ? "sensor" : "collider";
|
|
16
86
|
if (collider.shape.kind === "box") {
|
|
17
87
|
const h = collider.shape.halfExtents;
|
|
18
88
|
const corners = [
|
|
@@ -27,24 +97,24 @@ function appendColliderLines(lines, collider, position) {
|
|
|
27
97
|
];
|
|
28
98
|
const pairs = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5], [2, 6], [3, 7]];
|
|
29
99
|
for (const [a, b] of pairs) {
|
|
30
|
-
lines.push({ from: corners[a], to: corners[b], color });
|
|
100
|
+
lines.push({ from: corners[a], to: corners[b], color, category });
|
|
31
101
|
}
|
|
32
102
|
}
|
|
33
103
|
else if (collider.shape.kind === "sphere") {
|
|
34
104
|
const r = collider.shape.radius;
|
|
35
|
-
lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color });
|
|
36
|
-
lines.push({ from: [position[0], position[1] - r, position[2]], to: [position[0], position[1] + r, position[2]], color });
|
|
37
|
-
lines.push({ from: [position[0], position[1], position[2] - r], to: [position[0], position[1], position[2] + r], color });
|
|
105
|
+
lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color, category });
|
|
106
|
+
lines.push({ from: [position[0], position[1] - r, position[2]], to: [position[0], position[1] + r, position[2]], color, category });
|
|
107
|
+
lines.push({ from: [position[0], position[1], position[2] - r], to: [position[0], position[1], position[2] + r], color, category });
|
|
38
108
|
}
|
|
39
109
|
else if (collider.shape.kind === "plane") {
|
|
40
|
-
lines.push({ from: [-10, position[1], 0], to: [10, position[1], 0], color });
|
|
41
|
-
lines.push({ from: [0, position[1], -10], to: [0, position[1], 10], color });
|
|
110
|
+
lines.push({ from: [-10, position[1], 0], to: [10, position[1], 0], color, category });
|
|
111
|
+
lines.push({ from: [0, position[1], -10], to: [0, position[1], 10], color, category });
|
|
42
112
|
}
|
|
43
113
|
else if (collider.shape.kind === "capsule") {
|
|
44
114
|
const r = collider.shape.radius;
|
|
45
115
|
const h = collider.shape.halfHeight;
|
|
46
|
-
lines.push({ from: [position[0], position[1] - h - r, position[2]], to: [position[0], position[1] + h + r, position[2]], color });
|
|
47
|
-
lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color });
|
|
116
|
+
lines.push({ from: [position[0], position[1] - h - r, position[2]], to: [position[0], position[1] + h + r, position[2]], color, category });
|
|
117
|
+
lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color, category });
|
|
48
118
|
}
|
|
49
119
|
else if (collider.shape.kind === "mesh" || collider.shape.kind === "convex-hull") {
|
|
50
120
|
const { vertices, indices } = collider.shape;
|
|
@@ -52,9 +122,9 @@ function appendColliderLines(lines, collider, position) {
|
|
|
52
122
|
const a = translate(vertices[indices[index]], position);
|
|
53
123
|
const b = translate(vertices[indices[index + 1]], position);
|
|
54
124
|
const c = translate(vertices[indices[index + 2]], position);
|
|
55
|
-
lines.push({ from: a, to: b, color });
|
|
56
|
-
lines.push({ from: b, to: c, color });
|
|
57
|
-
lines.push({ from: c, to: a, color });
|
|
125
|
+
lines.push({ from: a, to: b, color, category });
|
|
126
|
+
lines.push({ from: b, to: c, color, category });
|
|
127
|
+
lines.push({ from: c, to: a, color, category });
|
|
58
128
|
}
|
|
59
129
|
}
|
|
60
130
|
else {
|
|
@@ -69,9 +139,9 @@ function appendColliderLines(lines, collider, position) {
|
|
|
69
139
|
for (let row = 0; row < shape.rows; row += 1) {
|
|
70
140
|
for (let column = 0; column < shape.columns; column += 1) {
|
|
71
141
|
if (column + 1 < shape.columns)
|
|
72
|
-
lines.push({ from: sample(row, column), to: sample(row, column + 1), color });
|
|
142
|
+
lines.push({ from: sample(row, column), to: sample(row, column + 1), color, category });
|
|
73
143
|
if (row + 1 < shape.rows)
|
|
74
|
-
lines.push({ from: sample(row, column), to: sample(row + 1, column), color });
|
|
144
|
+
lines.push({ from: sample(row, column), to: sample(row + 1, column), color, category });
|
|
75
145
|
}
|
|
76
146
|
}
|
|
77
147
|
}
|