@perplexdotgg/bounce 1.0.0
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/LICENSE +21 -0
- package/README.md +30 -0
- package/package.json +32 -0
- package/src/builders/ConvexHullBuilder.ts +437 -0
- package/src/builders/ConvexHullBuilder2d.ts +344 -0
- package/src/builders/ConvexHullBuilder3d.ts +1689 -0
- package/src/builders/HeightMapBuilder.ts +414 -0
- package/src/builders/TriangleMeshBuilder.ts +92 -0
- package/src/collision/CastShapesModule.ts +184 -0
- package/src/collision/CollideShapesModule.ts +152 -0
- package/src/collision/HeightMapCaster.ts +38 -0
- package/src/collision/HeightMapCollider.ts +33 -0
- package/src/collision/TriangleCaster.ts +249 -0
- package/src/collision/TriangleCollider.ts +308 -0
- package/src/collision/TriangleCollider2.ts +379 -0
- package/src/collision/activeEdge.ts +146 -0
- package/src/collision/cast/cast.ts +139 -0
- package/src/collision/cast/castCompoundVsCompound.ts +59 -0
- package/src/collision/cast/castCompoundVsConvex.ts +116 -0
- package/src/collision/cast/castConvexVsCompound.ts +123 -0
- package/src/collision/cast/castConvexVsConvex.ts +213 -0
- package/src/collision/cast/castConvexVsHeightMap.ts +73 -0
- package/src/collision/cast/castConvexVsTriangleMesh.ts +56 -0
- package/src/collision/cast/castRayVsCompound.ts +44 -0
- package/src/collision/cast/castRayVsConvex.ts +45 -0
- package/src/collision/cast/castRayVsHeightMap.ts +58 -0
- package/src/collision/cast/castRayVsTriangleMesh.ts +58 -0
- package/src/collision/closestPoints/closestPoints.ts +23 -0
- package/src/collision/closestPoints/computeBarycentricCoordinates2d.ts +32 -0
- package/src/collision/closestPoints/computeBarycentricCoordinates3d.ts +81 -0
- package/src/collision/closestPoints/computeClosestPointOnLine.ts +30 -0
- package/src/collision/closestPoints/computeClosestPointOnTetrahedron.ts +96 -0
- package/src/collision/closestPoints/computeClosestPointOnTriangle.ts +195 -0
- package/src/collision/closestPoints/isOriginOutsideOfPlane.ts +25 -0
- package/src/collision/closestPoints/isOriginOutsideOfTrianglePlanes.ts +72 -0
- package/src/collision/collide/collide.ts +146 -0
- package/src/collision/collide/collideCompoundVsCompound.ts +60 -0
- package/src/collision/collide/collideCompoundVsConvex.ts +59 -0
- package/src/collision/collide/collideCompoundVsHeightMap.ts +73 -0
- package/src/collision/collide/collideCompoundVsTriangleMesh.ts +56 -0
- package/src/collision/collide/collideConvexVsCompound.ts +57 -0
- package/src/collision/collide/collideConvexVsConvex.ts +225 -0
- package/src/collision/collide/collideConvexVsConvexImp.ts +236 -0
- package/src/collision/collide/collideConvexVsHeightMap.ts +53 -0
- package/src/collision/collide/collideConvexVsTriangleMesh.ts +58 -0
- package/src/collision/collide/collideHeightMapVsCompound.ts +69 -0
- package/src/collision/collide/collideHeightMapVsConvex.ts +53 -0
- package/src/collision/collide/collideSphereVsSphere.ts +81 -0
- package/src/collision/collide/collideTriangleMeshVsCompound.ts +58 -0
- package/src/collision/collide/collideTriangleMeshVsConvex.ts +58 -0
- package/src/collision/epa/EpaConvexHullBuilder.ts +397 -0
- package/src/collision/epa/StaticArray.ts +154 -0
- package/src/collision/epa/TriangleFactory.ts +32 -0
- package/src/collision/epa/arrays.ts +99 -0
- package/src/collision/epa/binaryHeap.ts +82 -0
- package/src/collision/epa/structs.ts +227 -0
- package/src/collision/gjk/GjkModule.ts +864 -0
- package/src/collision/gjk/PenetrationDepthModule.ts +493 -0
- package/src/collision/gjk/SupportPoints.ts +50 -0
- package/src/collision/imp/MinkowskiDifference.ts +36 -0
- package/src/collision/imp/computeExploredDistanceLowerUpperBound.ts +40 -0
- package/src/collision/imp/finalizeImpResult.ts +69 -0
- package/src/collision/imp/findContactImp.ts +196 -0
- package/src/collision/imp/imp.ts +28 -0
- package/src/collision/imp/incrementalMinimumDistanceExploreDirection.ts +207 -0
- package/src/collision/mpr/findPortal.ts +152 -0
- package/src/collision/mpr/mpr.ts +29 -0
- package/src/collision/mpr/updatePortal.ts +52 -0
- package/src/constraints/BaseConstraint.ts +50 -0
- package/src/constraints/ConstraintOptions.ts +22 -0
- package/src/constraints/ConstraintSolver.ts +119 -0
- package/src/constraints/DistanceConstraint.ts +229 -0
- package/src/constraints/FixedConstraint.ts +203 -0
- package/src/constraints/HingeConstraint.ts +460 -0
- package/src/constraints/PointConstraint.ts +108 -0
- package/src/constraints/components/AngleComponent.ts +226 -0
- package/src/constraints/components/AxisComponent.ts +263 -0
- package/src/constraints/components/HingeComponent.ts +215 -0
- package/src/constraints/components/Motor.ts +36 -0
- package/src/constraints/components/PointConstraintComponent.ts +179 -0
- package/src/constraints/components/RotationEulerComponent.ts +139 -0
- package/src/constraints/components/Spring.ts +30 -0
- package/src/constraints/components/SpringComponent.ts +71 -0
- package/src/constraints/types.ts +6 -0
- package/src/helpers.ts +147 -0
- package/src/index.ts +50 -0
- package/src/math/BasicTransform.ts +19 -0
- package/src/math/NumberValue.ts +13 -0
- package/src/math/isometry.ts +64 -0
- package/src/math/mat3.ts +529 -0
- package/src/math/mat4.ts +588 -0
- package/src/math/quat.ts +193 -0
- package/src/math/scalar.ts +81 -0
- package/src/math/tensor.ts +17 -0
- package/src/math/vec3.ts +589 -0
- package/src/math/vec4.ts +10 -0
- package/src/physics/Body.ts +581 -0
- package/src/physics/CollisionFilter.ts +52 -0
- package/src/physics/SleepModule.ts +163 -0
- package/src/physics/broadphase/BodyPairsModule.ts +363 -0
- package/src/physics/broadphase/BvhModule.ts +237 -0
- package/src/physics/broadphase/BvhTree.ts +803 -0
- package/src/physics/broadphase/ConstraintPairsModule.ts +385 -0
- package/src/physics/broadphase/TriangleMeshBvhTree.ts +379 -0
- package/src/physics/manifold/ContactManifold.ts +227 -0
- package/src/physics/manifold/ContactManifoldModule.ts +623 -0
- package/src/physics/manifold/Face.ts +119 -0
- package/src/physics/manifold/ManifoldCache.ts +116 -0
- package/src/physics/manifold/clipping/clipPolyVsEdge.ts +131 -0
- package/src/physics/manifold/clipping/clipPolyVsPlane.ts +73 -0
- package/src/physics/manifold/clipping/clipPolyVsPoly.ts +72 -0
- package/src/physics/narrowphase/CollideBodiesModule.ts +755 -0
- package/src/physics/solver/ContactConstraintModule.ts +659 -0
- package/src/physics/solver/ManifoldConstraint.ts +420 -0
- package/src/physics/solver/estimateCollisionResponse.ts +146 -0
- package/src/shape/Aabb.ts +400 -0
- package/src/shape/Box.ts +231 -0
- package/src/shape/Capsule.ts +332 -0
- package/src/shape/CompoundShape.ts +288 -0
- package/src/shape/Convex.ts +130 -0
- package/src/shape/ConvexHull.ts +423 -0
- package/src/shape/Cylinder.ts +313 -0
- package/src/shape/HeightMap.ts +511 -0
- package/src/shape/Line.ts +14 -0
- package/src/shape/Plane.ts +116 -0
- package/src/shape/Ray.ts +81 -0
- package/src/shape/Segment.ts +25 -0
- package/src/shape/Shape.ts +77 -0
- package/src/shape/Sphere.ts +181 -0
- package/src/shape/TransformedShape.ts +51 -0
- package/src/shape/Triangle.ts +122 -0
- package/src/shape/TriangleMesh.ts +186 -0
- package/src/types.ts +1 -0
- package/src/world.ts +1335 -0
- package/tests/BodyPairsModule.test.ts +71 -0
- package/tests/BvhTree.test.ts +406 -0
- package/tests/test.md +642 -0
- package/tests/vec3.test.ts +12 -0
- package/tsconfig.json +20 -0
- package/vite.config.js +40 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// activeEdges (uint8bit): 0 = edge AB active, bit 1 = edge BC active, bit 2 = edge CA active
|
|
2
|
+
|
|
3
|
+
import { degreesToRadians } from "../math/scalar";
|
|
4
|
+
import { Vec3 } from "../math/vec3";
|
|
5
|
+
import { BarycentricCoordinatesResult } from "./closestPoints/closestPoints";
|
|
6
|
+
import { computeBarycentricCoordinates3d } from "./closestPoints/computeBarycentricCoordinates3d";
|
|
7
|
+
|
|
8
|
+
const cos1degree = Math.cos(degreesToRadians(1));
|
|
9
|
+
const cos179degrees = Math.cos(degreesToRadians(179));
|
|
10
|
+
const epsilon = 1e-4;
|
|
11
|
+
const oneMinusEpsilon = 1 - epsilon;
|
|
12
|
+
|
|
13
|
+
const result = /*@__PURE__*/ BarycentricCoordinatesResult.create();
|
|
14
|
+
const crossNormal1Normal2 = /*@__PURE__*/ Vec3.create();
|
|
15
|
+
const pa = /*@__PURE__*/ Vec3.create();
|
|
16
|
+
const pb = /*@__PURE__*/ Vec3.create();
|
|
17
|
+
const pc = /*@__PURE__*/ Vec3.create();
|
|
18
|
+
|
|
19
|
+
export function isEdgeActive(
|
|
20
|
+
inNormal1: Vec3,
|
|
21
|
+
inNormal2: Vec3,
|
|
22
|
+
inEdgeDirection: Vec3,
|
|
23
|
+
inCosThresholdAngle: number
|
|
24
|
+
): boolean {
|
|
25
|
+
// If normals are opposite the edges are active (the triangles are back to back)
|
|
26
|
+
const cosAngleBetweenNormals = inNormal1.dot(inNormal2);
|
|
27
|
+
|
|
28
|
+
// case: triangles are back to back -> edge is active
|
|
29
|
+
if (cosAngleBetweenNormals < cos179degrees) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
crossNormal1Normal2.crossVectors(inNormal1, inNormal2);
|
|
34
|
+
|
|
35
|
+
// case: concave edge -> edge is inactive
|
|
36
|
+
if (crossNormal1Normal2.dot(inEdgeDirection) < 0) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// case: convex edge -> edge is active when angle between normals is bigger than threshold
|
|
41
|
+
return cosAngleBetweenNormals < inCosThresholdAngle;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function fixNormal(
|
|
45
|
+
out: Vec3,
|
|
46
|
+
inV0: Vec3,
|
|
47
|
+
inV1: Vec3,
|
|
48
|
+
inV2: Vec3,
|
|
49
|
+
inTriangleNormal: Vec3,
|
|
50
|
+
inActiveEdges: number,
|
|
51
|
+
inPoint: Vec3,
|
|
52
|
+
inNormal: Vec3,
|
|
53
|
+
inMovementDirection: Vec3
|
|
54
|
+
): void {
|
|
55
|
+
// #v-ifdef DEV
|
|
56
|
+
// TODO: assert that not all edges are active, else we already have the correct normal
|
|
57
|
+
if (inActiveEdges === 0b111) {
|
|
58
|
+
throw new Error("All edges are active, no need to fix normal");
|
|
59
|
+
}
|
|
60
|
+
// #v-endif
|
|
61
|
+
|
|
62
|
+
// If inNormal would affect movement less than inTriangleNormal use inNormal
|
|
63
|
+
// This is done since it is really hard to make a distinction between sliding over a horizontal triangulated grid and hitting an edge (in this case you want to use the triangle normal)
|
|
64
|
+
// and sliding over a triangulated grid and grazing a vertical triangle with an inactive edge (in this case using the triangle normal will cause the object to bounce back so we want to use the calculated normal).
|
|
65
|
+
// To solve this we take a movement hint to give an indication of what direction our object is moving. If the edge normal results in less motion difference than the triangle normal we use the edge normal.
|
|
66
|
+
const normal_length = inNormal.length();
|
|
67
|
+
const triangle_normal_length = inTriangleNormal.length();
|
|
68
|
+
if (
|
|
69
|
+
inMovementDirection.dot(inNormal) * triangle_normal_length <
|
|
70
|
+
inMovementDirection.dot(inTriangleNormal) * normal_length
|
|
71
|
+
) {
|
|
72
|
+
out.copy(inNormal);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check: None of the edges are active, we need to use the triangle normal
|
|
77
|
+
if (inActiveEdges === 0) {
|
|
78
|
+
out.copy(inTriangleNormal);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Some edges are active.
|
|
83
|
+
// If normal is parallel to the triangle normal we don't need to check the active edges.
|
|
84
|
+
if (inTriangleNormal.dot(inNormal) > cos1degree * normal_length * triangle_normal_length) {
|
|
85
|
+
out.copy(inNormal);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let collidingEdge: number;
|
|
90
|
+
|
|
91
|
+
// Test where the contact point is in the triangle
|
|
92
|
+
result.u;
|
|
93
|
+
result.v;
|
|
94
|
+
result.w;
|
|
95
|
+
|
|
96
|
+
pa.subtractVectors(inV0, inPoint);
|
|
97
|
+
pb.subtractVectors(inV1, inPoint);
|
|
98
|
+
pc.subtractVectors(inV2, inPoint);
|
|
99
|
+
|
|
100
|
+
computeBarycentricCoordinates3d(result, pa, pb, pc);
|
|
101
|
+
|
|
102
|
+
// Colliding with v0, edge 0 or 2 needs to be active
|
|
103
|
+
if (result.u > oneMinusEpsilon) {
|
|
104
|
+
collidingEdge = 0b101;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Colliding with v1, edge 0 or 1 needs to be active
|
|
108
|
+
else if (result.v > oneMinusEpsilon) {
|
|
109
|
+
collidingEdge = 0b011;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Colliding with v2, edge 1 or 2 needs to be active
|
|
113
|
+
else if (result.w > oneMinusEpsilon) {
|
|
114
|
+
collidingEdge = 0b110;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Colliding with edge v1, v2, edge 1 needs to be active
|
|
118
|
+
else if (result.u < epsilon) {
|
|
119
|
+
collidingEdge = 0b010;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Colliding with edge v0, v2, edge 2 needs to be active
|
|
123
|
+
else if (result.v < epsilon) {
|
|
124
|
+
collidingEdge = 0b100;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Colliding with edge v0, v1, edge 0 needs to be active
|
|
128
|
+
else if (result.w < epsilon) {
|
|
129
|
+
collidingEdge = 0b001;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Interior hit
|
|
133
|
+
else {
|
|
134
|
+
out.copy(inTriangleNormal);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// If this edge is active, use the provided normal
|
|
139
|
+
if ((inActiveEdges & collidingEdge) !== 0) {
|
|
140
|
+
out.copy(inNormal);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// if this edge is not active, use the triangle normal
|
|
145
|
+
out.copy(inTriangleNormal);
|
|
146
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BooleanType,
|
|
3
|
+
createClass,
|
|
4
|
+
LazyReferenceType,
|
|
5
|
+
MonomorphType,
|
|
6
|
+
NumberType,
|
|
7
|
+
PropertyDefinitionMap,
|
|
8
|
+
PropertyDefinitionReference,
|
|
9
|
+
} from "monomorph";
|
|
10
|
+
import { Vec3 } from "../../math/vec3";
|
|
11
|
+
import { Face } from "../../physics/manifold/Face";
|
|
12
|
+
import { BackFaceMode, CollisionSettings, createDefaultCollisionSettings } from "../collide/collide";
|
|
13
|
+
import { Body } from "../../physics/Body";
|
|
14
|
+
|
|
15
|
+
export const enum CastStatus {
|
|
16
|
+
NotColliding,
|
|
17
|
+
Colliding,
|
|
18
|
+
Indeterminate,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const castResultProps = {
|
|
22
|
+
status: NumberType(0),
|
|
23
|
+
hasContact: BooleanType(false),
|
|
24
|
+
penetration: NumberType(0.0),
|
|
25
|
+
contactPointA: MonomorphType(Vec3),
|
|
26
|
+
contactPointB: MonomorphType(Vec3),
|
|
27
|
+
normalA: MonomorphType(Vec3),
|
|
28
|
+
normalB: MonomorphType(Vec3),
|
|
29
|
+
momentArmA: MonomorphType(Vec3),
|
|
30
|
+
momentArmB: MonomorphType(Vec3),
|
|
31
|
+
surfaceNormalA: MonomorphType(Vec3),
|
|
32
|
+
surfaceNormalB: MonomorphType(Vec3),
|
|
33
|
+
bodyA: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
|
|
34
|
+
bodyB: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
|
|
35
|
+
subShapeIdA: NumberType(0),
|
|
36
|
+
subShapeIdB: NumberType(0),
|
|
37
|
+
isBackFace: BooleanType(false),
|
|
38
|
+
faceA: MonomorphType(Face),
|
|
39
|
+
faceB: MonomorphType(Face),
|
|
40
|
+
fraction: NumberType(0.0),
|
|
41
|
+
isBackFaceHit: BooleanType(false),
|
|
42
|
+
} as const satisfies PropertyDefinitionMap;
|
|
43
|
+
|
|
44
|
+
export class CastResult extends createClass<CastResult, typeof castResultProps>(castResultProps) {
|
|
45
|
+
reset() {
|
|
46
|
+
this.status = CastStatus.Indeterminate;
|
|
47
|
+
this.hasContact = false;
|
|
48
|
+
this.penetration = 0;
|
|
49
|
+
this.bodyA = null;
|
|
50
|
+
this.bodyB = null;
|
|
51
|
+
this.subShapeIdA = 0;
|
|
52
|
+
this.subShapeIdB = 0;
|
|
53
|
+
this.isBackFace = false;
|
|
54
|
+
this.faceA.clear();
|
|
55
|
+
this.faceB.clear();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* swaps the A and B data
|
|
60
|
+
*/
|
|
61
|
+
swap() {
|
|
62
|
+
this.contactPointA.swap(this.contactPointB);
|
|
63
|
+
this.normalA.swap(this.normalB);
|
|
64
|
+
this.momentArmA.swap(this.momentArmB);
|
|
65
|
+
this.surfaceNormalA.swap(this.surfaceNormalB);
|
|
66
|
+
|
|
67
|
+
const tempBody = this.bodyA;
|
|
68
|
+
this.bodyA = this.bodyB;
|
|
69
|
+
this.bodyB = tempBody;
|
|
70
|
+
|
|
71
|
+
const tempSubShapeId = this.subShapeIdA;
|
|
72
|
+
this.subShapeIdA = this.subShapeIdB;
|
|
73
|
+
this.subShapeIdB = tempSubShapeId;
|
|
74
|
+
|
|
75
|
+
this.faceA.swap(this.faceB);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getEarlyOutFraction(): number {
|
|
79
|
+
return this.fraction > 0.0 ? this.fraction : -this.penetration;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class CastCollector {
|
|
84
|
+
static initialEarlyOutFraction: number = 1.0 + 1e-4;
|
|
85
|
+
static shouldEarlyOutFraction: number = -Infinity;
|
|
86
|
+
earlyOutFraction: number = CastCollector.initialEarlyOutFraction;
|
|
87
|
+
body2: Body | null = null;
|
|
88
|
+
|
|
89
|
+
getEarlyOutFraction(): number {
|
|
90
|
+
return this.earlyOutFraction;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getPositiveEarlyOutFraction(): number {
|
|
94
|
+
return Math.max(Number.MIN_VALUE, this.earlyOutFraction);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
reset() {
|
|
98
|
+
this.earlyOutFraction = CastCollector.initialEarlyOutFraction;
|
|
99
|
+
this.body2 = null;
|
|
100
|
+
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
updateEarlyOutFraction(inFraction: number): void {
|
|
105
|
+
if (inFraction <= this.earlyOutFraction) {
|
|
106
|
+
this.earlyOutFraction = inFraction;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
addHit(result: CastResult): void {}
|
|
111
|
+
|
|
112
|
+
addMiss(): void {}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface CastSettings extends CollisionSettings {
|
|
116
|
+
backFaceModeConvex: BackFaceMode;
|
|
117
|
+
backFaceModeTriangles: BackFaceMode;
|
|
118
|
+
useShrunkenShapeAndConvexRadius: boolean;
|
|
119
|
+
returnDeepestPoint: boolean;
|
|
120
|
+
}
|
|
121
|
+
export const enum QueryPrecision {
|
|
122
|
+
approximate,
|
|
123
|
+
precise,
|
|
124
|
+
preciseWithContacts,
|
|
125
|
+
}
|
|
126
|
+
export interface RayCastSettings {
|
|
127
|
+
precision?: QueryPrecision;
|
|
128
|
+
returnClosestOnly?: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createDefaultCastSettings() {
|
|
132
|
+
return {
|
|
133
|
+
...createDefaultCollisionSettings(),
|
|
134
|
+
backFaceModeConvex: BackFaceMode.IgnoreBackFaces,
|
|
135
|
+
backFaceModeTriangles: BackFaceMode.IgnoreBackFaces,
|
|
136
|
+
useShrunkenShapeAndConvexRadius: false,
|
|
137
|
+
returnDeepestPoint: false,
|
|
138
|
+
} satisfies CastSettings;
|
|
139
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// import { Isometry } from "../../math/isometry";
|
|
2
|
+
// import { Vec3 } from "../../math/vec3";
|
|
3
|
+
// import { CompoundShape } from "../../shape/CompoundShape";
|
|
4
|
+
// import { ConvexWithcomputeSupportShape } from "../../shape/Convex";
|
|
5
|
+
// import { PenetrationDepthModule } from "../gjk/PenetrationDepthModule";
|
|
6
|
+
// import { CastCollector, CastSettings } from "./cast";
|
|
7
|
+
// import { castConvexVsConvex } from "./castConvexVsConvex";
|
|
8
|
+
|
|
9
|
+
// const negatedOffset = /*@__PURE__*/ Vec3.create();
|
|
10
|
+
// const offsetIsometryA = /*@__PURE__*/ Isometry.create();
|
|
11
|
+
// const offsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
12
|
+
// const inverseOffsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
13
|
+
// const offsetIsometryAToB = /*@__PURE__*/ Isometry.create();
|
|
14
|
+
// const displacementInB = /*@__PURE__*/ Vec3.create();
|
|
15
|
+
|
|
16
|
+
// export function castCompoundVsCompound(
|
|
17
|
+
// penetrationDepthModule: PenetrationDepthModule,
|
|
18
|
+
// ioCollector: CastCollector,
|
|
19
|
+
// inShapeA: CompoundShape,
|
|
20
|
+
// inShapeB: CompoundShape,
|
|
21
|
+
// isometryA: Isometry,
|
|
22
|
+
// isometryB: Isometry,
|
|
23
|
+
// inScaleA: number,
|
|
24
|
+
// inScaleB: number,
|
|
25
|
+
// displacement: Vec3,
|
|
26
|
+
// offset: Vec3,
|
|
27
|
+
// inSettings: CastSettings,
|
|
28
|
+
// preferredNormalBDirection?: Vec3,
|
|
29
|
+
// bodyIdA: number = 0,
|
|
30
|
+
// bodyIdB: number = 0
|
|
31
|
+
// ): void {
|
|
32
|
+
// // translate A and B by the offset, for example to move them both to origin
|
|
33
|
+
// negatedOffset.negateVector(offset);
|
|
34
|
+
// offsetIsometryA.matrix.postTranslatedMatrix(isometryA.matrix, negatedOffset);
|
|
35
|
+
// offsetIsometryB.matrix.postTranslatedMatrix(isometryB.matrix, negatedOffset);
|
|
36
|
+
|
|
37
|
+
// // get a transformA in the space of B
|
|
38
|
+
// inverseOffsetIsometryB.matrix.invertMat4(offsetIsometryB.matrix);
|
|
39
|
+
// offsetIsometryAToB.matrix.multiplyMatrices(inverseOffsetIsometryB.matrix, offsetIsometryA.matrix);
|
|
40
|
+
|
|
41
|
+
// // get displacement in the space of B
|
|
42
|
+
// inverseOffsetIsometryB.matrix.multiply3x3(displacementInB, displacement);
|
|
43
|
+
|
|
44
|
+
// castConvexVsConvex(
|
|
45
|
+
// penetrationDepthModule,
|
|
46
|
+
// ioCollector,
|
|
47
|
+
// inShapeA,
|
|
48
|
+
// inShapeB,
|
|
49
|
+
// offsetIsometryAToB,
|
|
50
|
+
// offsetIsometryB,
|
|
51
|
+
// inScaleA,
|
|
52
|
+
// inScaleB,
|
|
53
|
+
// displacementInB,
|
|
54
|
+
// inSettings,
|
|
55
|
+
// preferredNormalBDirection,
|
|
56
|
+
// bodyIdA,
|
|
57
|
+
// bodyIdB
|
|
58
|
+
// );
|
|
59
|
+
// }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { BasicTransform } from "../../math/BasicTransform";
|
|
2
|
+
import { Isometry } from "../../math/isometry";
|
|
3
|
+
import { Vec3 } from "../../math/vec3";
|
|
4
|
+
import { Body } from "../../physics/Body";
|
|
5
|
+
import { CompoundShape } from "../../shape/CompoundShape";
|
|
6
|
+
import { ConvexWithcomputeSupportShape } from "../../shape/Convex";
|
|
7
|
+
import { ConvexShape } from "../../shape/Shape";
|
|
8
|
+
import { PenetrationDepthModule } from "../gjk/PenetrationDepthModule";
|
|
9
|
+
import { CastCollector, CastSettings } from "./cast";
|
|
10
|
+
import { castConvexVsConvexLocal } from "./castConvexVsConvex";
|
|
11
|
+
|
|
12
|
+
const negatedOffset = /*@__PURE__*/ Vec3.create();
|
|
13
|
+
const offsetIsometryA = /*@__PURE__*/ Isometry.create();
|
|
14
|
+
const offsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
15
|
+
const inverseOffsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
16
|
+
const offsetIsometryAToB = /*@__PURE__*/ Isometry.create();
|
|
17
|
+
const displacementInB = /*@__PURE__*/ Vec3.create();
|
|
18
|
+
|
|
19
|
+
export function castCompoundVsConvex(
|
|
20
|
+
penetrationDepthModule: PenetrationDepthModule,
|
|
21
|
+
ioCollector: CastCollector,
|
|
22
|
+
inShapeA: CompoundShape,
|
|
23
|
+
inShapeB: ConvexWithcomputeSupportShape,
|
|
24
|
+
isometryA: Isometry,
|
|
25
|
+
isometryB: Isometry,
|
|
26
|
+
inScaleA: number,
|
|
27
|
+
inScaleB: number,
|
|
28
|
+
displacement: Vec3,
|
|
29
|
+
offset: Vec3,
|
|
30
|
+
inSettings: CastSettings,
|
|
31
|
+
preferredNormalBDirection?: Vec3,
|
|
32
|
+
bodyA: Body | null = null,
|
|
33
|
+
bodyB: Body | null = null
|
|
34
|
+
): void {
|
|
35
|
+
// translate A and B by the offset, for example to move them both to origin
|
|
36
|
+
negatedOffset.negateVector(offset);
|
|
37
|
+
offsetIsometryA.matrix.postTranslatedMatrix(isometryA.matrix, negatedOffset);
|
|
38
|
+
offsetIsometryB.matrix.postTranslatedMatrix(isometryB.matrix, negatedOffset);
|
|
39
|
+
|
|
40
|
+
// get a transformA in the space of B
|
|
41
|
+
inverseOffsetIsometryB.matrix.invertMatrix(offsetIsometryB.matrix);
|
|
42
|
+
offsetIsometryAToB.matrix.multiplyMatrices(inverseOffsetIsometryB.matrix, offsetIsometryA.matrix);
|
|
43
|
+
|
|
44
|
+
// get displacement in the space of B
|
|
45
|
+
inverseOffsetIsometryB.matrix.multiply3x3(displacementInB, displacement);
|
|
46
|
+
|
|
47
|
+
castCompoundVsConvexLocal(
|
|
48
|
+
penetrationDepthModule,
|
|
49
|
+
ioCollector,
|
|
50
|
+
inShapeA,
|
|
51
|
+
inShapeB,
|
|
52
|
+
offsetIsometryAToB,
|
|
53
|
+
offsetIsometryB,
|
|
54
|
+
inScaleA,
|
|
55
|
+
inScaleB,
|
|
56
|
+
displacementInB,
|
|
57
|
+
inSettings,
|
|
58
|
+
preferredNormalBDirection,
|
|
59
|
+
bodyA,
|
|
60
|
+
bodyB
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const transformSubShapeToA = /*@__PURE__*/ Isometry.create();
|
|
65
|
+
const transformSubShapeToB = /*@__PURE__*/ Isometry.create();
|
|
66
|
+
|
|
67
|
+
export function castCompoundVsConvexLocal(
|
|
68
|
+
penetrationDepthModule: PenetrationDepthModule,
|
|
69
|
+
ioCollector: CastCollector,
|
|
70
|
+
inShapeA: CompoundShape,
|
|
71
|
+
inShapeB: ConvexWithcomputeSupportShape,
|
|
72
|
+
isometryAToB: Isometry,
|
|
73
|
+
isometryB: Isometry,
|
|
74
|
+
inScaleA: number,
|
|
75
|
+
inScaleB: number,
|
|
76
|
+
displacementInB: Vec3,
|
|
77
|
+
inShapeCastSettings: CastSettings,
|
|
78
|
+
preferredNormalBDirection?: Vec3,
|
|
79
|
+
bodyA: Body | null = null,
|
|
80
|
+
bodyB: Body | null = null
|
|
81
|
+
): void {
|
|
82
|
+
// debugger;
|
|
83
|
+
// for (let i = 0; i < inShapeA.shapeIds.itemMaxCount; i++) {
|
|
84
|
+
let index = 0;
|
|
85
|
+
for (const shapeObj of inShapeA.shapes) {
|
|
86
|
+
const shape = shapeObj.shape as ConvexShape;
|
|
87
|
+
const transform = shapeObj.transform as BasicTransform;
|
|
88
|
+
const translation = transform.position;
|
|
89
|
+
const rotation = transform.rotation;
|
|
90
|
+
|
|
91
|
+
// set the isometries
|
|
92
|
+
transformSubShapeToA.fromRotationAndTranslation(rotation, translation);
|
|
93
|
+
transformSubShapeToB.matrix.multiplyMatrices(isometryAToB.matrix, transformSubShapeToA.matrix);
|
|
94
|
+
|
|
95
|
+
// cast the shapes
|
|
96
|
+
castConvexVsConvexLocal(
|
|
97
|
+
penetrationDepthModule,
|
|
98
|
+
ioCollector,
|
|
99
|
+
shape,
|
|
100
|
+
inShapeB,
|
|
101
|
+
transformSubShapeToB,
|
|
102
|
+
isometryB,
|
|
103
|
+
inScaleA,
|
|
104
|
+
inScaleB,
|
|
105
|
+
displacementInB,
|
|
106
|
+
inShapeCastSettings,
|
|
107
|
+
preferredNormalBDirection,
|
|
108
|
+
bodyA,
|
|
109
|
+
bodyB,
|
|
110
|
+
index,
|
|
111
|
+
0
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
index++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { BasicTransform, ConvexShape } from "../..";
|
|
2
|
+
import { Isometry } from "../../math/isometry";
|
|
3
|
+
import { Vec3 } from "../../math/vec3";
|
|
4
|
+
import { Body } from "../../physics/Body";
|
|
5
|
+
import { CompoundShape } from "../../shape/CompoundShape";
|
|
6
|
+
import { ConvexWithcomputeSupportShape } from "../../shape/Convex";
|
|
7
|
+
import { PenetrationDepthModule } from "../gjk/PenetrationDepthModule";
|
|
8
|
+
import { CastCollector, CastSettings } from "./cast";
|
|
9
|
+
import { castConvexVsConvexLocal } from "./castConvexVsConvex";
|
|
10
|
+
|
|
11
|
+
const negatedOffset = /*@__PURE__*/ Vec3.create();
|
|
12
|
+
const offsetIsometryA = /*@__PURE__*/ Isometry.create();
|
|
13
|
+
const offsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
14
|
+
const inverseOffsetIsometryB = /*@__PURE__*/ Isometry.create();
|
|
15
|
+
const offsetIsometryAToB = /*@__PURE__*/ Isometry.create();
|
|
16
|
+
const displacementInB = /*@__PURE__*/ Vec3.create();
|
|
17
|
+
|
|
18
|
+
export function castConvexVsCompound(
|
|
19
|
+
penetrationDepthModule: PenetrationDepthModule,
|
|
20
|
+
ioCollector: CastCollector,
|
|
21
|
+
inShapeA: ConvexWithcomputeSupportShape,
|
|
22
|
+
inShapeB: CompoundShape,
|
|
23
|
+
isometryA: Isometry,
|
|
24
|
+
isometryB: Isometry,
|
|
25
|
+
inScaleA: number,
|
|
26
|
+
inScaleB: number,
|
|
27
|
+
displacement: Vec3,
|
|
28
|
+
offset: Vec3,
|
|
29
|
+
inSettings: CastSettings,
|
|
30
|
+
preferredNormalBDirection?: Vec3,
|
|
31
|
+
bodyA: Body | null = null,
|
|
32
|
+
bodyB: Body | null = null
|
|
33
|
+
) {
|
|
34
|
+
// translate A and B by the offset, for example to move them both to origin
|
|
35
|
+
negatedOffset.negateVector(offset);
|
|
36
|
+
offsetIsometryA.matrix.postTranslatedMatrix(isometryA.matrix, negatedOffset);
|
|
37
|
+
offsetIsometryB.matrix.postTranslatedMatrix(isometryB.matrix, negatedOffset);
|
|
38
|
+
|
|
39
|
+
// get a transformA in the space of B
|
|
40
|
+
inverseOffsetIsometryB.matrix.invertMatrix(offsetIsometryB.matrix);
|
|
41
|
+
offsetIsometryAToB.matrix.multiplyMatrices(inverseOffsetIsometryB.matrix, offsetIsometryA.matrix);
|
|
42
|
+
|
|
43
|
+
// get displacement in the space of B
|
|
44
|
+
inverseOffsetIsometryB.matrix.multiply3x3(displacementInB, displacement);
|
|
45
|
+
|
|
46
|
+
castConvexVsCompoundLocal(
|
|
47
|
+
penetrationDepthModule,
|
|
48
|
+
ioCollector,
|
|
49
|
+
inShapeA,
|
|
50
|
+
inShapeB,
|
|
51
|
+
offsetIsometryAToB,
|
|
52
|
+
offsetIsometryB,
|
|
53
|
+
inScaleA,
|
|
54
|
+
inScaleB,
|
|
55
|
+
displacementInB,
|
|
56
|
+
inSettings,
|
|
57
|
+
preferredNormalBDirection,
|
|
58
|
+
bodyA,
|
|
59
|
+
bodyB
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const transformSubShapeToB = /*@__PURE__*/ Isometry.create();
|
|
64
|
+
const transformBToSubShape = /*@__PURE__*/ Isometry.create();
|
|
65
|
+
const transformAToSubShape = /*@__PURE__*/ Isometry.create();
|
|
66
|
+
const transformSubShapeToWorld = /*@__PURE__*/ Isometry.create();
|
|
67
|
+
const displacementInSubShape = /*@__PURE__*/ Vec3.create();
|
|
68
|
+
|
|
69
|
+
export function castConvexVsCompoundLocal(
|
|
70
|
+
penetrationDepthModule: PenetrationDepthModule,
|
|
71
|
+
ioCollector: CastCollector,
|
|
72
|
+
inShapeA: ConvexWithcomputeSupportShape,
|
|
73
|
+
inShapeB: CompoundShape,
|
|
74
|
+
isometryAToB: Isometry,
|
|
75
|
+
isometryB: Isometry,
|
|
76
|
+
inScaleA: number,
|
|
77
|
+
inScaleB: number,
|
|
78
|
+
displacementInB: Vec3,
|
|
79
|
+
inShapeCastSettings: CastSettings,
|
|
80
|
+
preferredNormalBDirection?: Vec3,
|
|
81
|
+
bodyA: Body | null = null,
|
|
82
|
+
bodyB: Body | null = null
|
|
83
|
+
): void {
|
|
84
|
+
let index = 0;
|
|
85
|
+
for (const shapeObj of inShapeB.shapes) {
|
|
86
|
+
const shape = shapeObj.shape as ConvexShape;
|
|
87
|
+
const transform = shapeObj.transform as BasicTransform;
|
|
88
|
+
const translation = transform.position;
|
|
89
|
+
const rotation = transform.rotation;
|
|
90
|
+
|
|
91
|
+
// set the isometries
|
|
92
|
+
transformSubShapeToB.fromRotationAndTranslation(rotation, translation);
|
|
93
|
+
transformBToSubShape.fromInverseRotationAndTranslation(rotation, translation);
|
|
94
|
+
transformAToSubShape.matrix.multiplyMatrices(transformBToSubShape.matrix, isometryAToB.matrix);
|
|
95
|
+
|
|
96
|
+
// set the displacement
|
|
97
|
+
transformBToSubShape.matrix.multiply3x3(displacementInSubShape, displacementInB);
|
|
98
|
+
|
|
99
|
+
// subshape to world transform to transform results back to world space
|
|
100
|
+
transformSubShapeToWorld.matrix.multiplyMatrices(isometryB.matrix, transformSubShapeToB.matrix);
|
|
101
|
+
|
|
102
|
+
// cast the shapes
|
|
103
|
+
castConvexVsConvexLocal(
|
|
104
|
+
penetrationDepthModule,
|
|
105
|
+
ioCollector,
|
|
106
|
+
inShapeA,
|
|
107
|
+
shape,
|
|
108
|
+
transformAToSubShape,
|
|
109
|
+
transformSubShapeToWorld,
|
|
110
|
+
inScaleA,
|
|
111
|
+
inScaleB,
|
|
112
|
+
displacementInSubShape,
|
|
113
|
+
inShapeCastSettings,
|
|
114
|
+
preferredNormalBDirection,
|
|
115
|
+
bodyA,
|
|
116
|
+
bodyB,
|
|
117
|
+
0,
|
|
118
|
+
index
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
index++;
|
|
122
|
+
}
|
|
123
|
+
}
|