@ue-too/dynamics 0.5.2 → 0.6.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.
Files changed (42) hide show
  1. package/package.json +9 -10
  2. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/collision.js +0 -330
  3. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/collision.js.map +0 -1
  4. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/constraint.js +0 -166
  5. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/constraint.js.map +0 -1
  6. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/index.js +0 -4
  7. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/index.js.map +0 -1
  8. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/quadtree.js +0 -124
  9. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/quadtree.js.map +0 -1
  10. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/rigidbody.js +0 -476
  11. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/rigidbody.js.map +0 -1
  12. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/world.js +0 -90
  13. package/.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/world.js.map +0 -1
  14. package/dist/collision.d.ts +0 -36
  15. package/dist/constraint.d.ts +0 -35
  16. package/dist/dynamics.tsbuildinfo +0 -1
  17. package/dist/index.d.ts +0 -3
  18. package/dist/package.json +0 -22
  19. package/dist/quadtree.d.ts +0 -26
  20. package/dist/rigidbody.d.ts +0 -252
  21. package/dist/world.d.ts +0 -29
  22. package/jest.config.js +0 -18
  23. package/project.json +0 -33
  24. package/rollup.config.js +0 -20
  25. package/src/collision.ts +0 -359
  26. package/src/constraint.ts +0 -245
  27. package/src/index.ts +0 -3
  28. package/src/quadtree.ts +0 -145
  29. package/src/rigidbody.ts +0 -640
  30. package/src/world.ts +0 -116
  31. package/test/rigidbody.test.ts +0 -10
  32. package/tsconfig.json +0 -21
  33. package/tsconfig.spec.json +0 -12
  34. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/collision.d.ts → collision.d.ts} +0 -0
  35. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/constraint.d.ts → constraint.d.ts} +0 -0
  36. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/dynamics.tsbuildinfo → dynamics.tsbuildinfo} +0 -0
  37. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/index.d.ts → index.d.ts} +0 -0
  38. /package/{dist/index.js → index.js} +0 -0
  39. /package/{dist/index.js.map → index.js.map} +0 -0
  40. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/quadtree.d.ts → quadtree.d.ts} +0 -0
  41. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/rigidbody.d.ts → rigidbody.d.ts} +0 -0
  42. /package/{.rollup.cache/home/runner/work/ue-too/ue-too/packages/dynamics/dist/world.d.ts → world.d.ts} +0 -0
package/project.json DELETED
@@ -1,33 +0,0 @@
1
- {
2
- "name": "dynamics",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "packages/dynamics/src",
5
- "projectType": "library",
6
- "targets": {
7
- "build": {
8
- "executor": "nx:run-commands",
9
- "options": {
10
- "command": "pnpm build",
11
- "cwd": "packages/dynamics"
12
- }
13
- },
14
- "move-package": {
15
- "executor": "nx:run-commands",
16
- "options": {
17
- "command": "node ../../scripts/move-package.mjs",
18
- "cwd": "packages/dynamics"
19
- }
20
- },
21
- "test": {
22
- "executor": "nx:run-commands",
23
- "options": {
24
- "command": "pnpm test",
25
- "cwd": "packages/dynamics"
26
- }
27
- }
28
- },
29
- "tags": [],
30
- "implicitDependencies": [
31
- "math"
32
- ]
33
- }
package/rollup.config.js DELETED
@@ -1,20 +0,0 @@
1
- /**
2
- * @type {import('rollup').RollupOptions}
3
- */
4
- import typescript from '@rollup/plugin-typescript';
5
-
6
- export default {
7
- input: 'src/index.ts',
8
- output: {
9
- file: 'dist/index.js',
10
- format: 'esm',
11
- sourcemap: true
12
- },
13
- plugins: [
14
- typescript({
15
- tsconfig: 'tsconfig.json',
16
- outputToFilesystem: true,
17
- })
18
- ],
19
- external: ['@ue-too/math']
20
- };
package/src/collision.ts DELETED
@@ -1,359 +0,0 @@
1
- import { BaseRigidBody, RigidBody } from "./rigidbody";
2
- import { PointCal, Point } from "@ue-too/math";
3
- import { QuadTree } from "./quadtree";
4
-
5
- export function resolveCollision(bodyA: RigidBody, bodyB: RigidBody, normal: Point): void {
6
- // console.log("resolve");
7
- if (bodyA.isStatic() && bodyB.isStatic()) {
8
- return;
9
- }
10
- let restitution = 0.4;
11
- let inverseMassA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.mass;
12
- let inverseMassB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.mass;
13
- // console.log("inverse mass a", inverseMassA);
14
- // console.log("inverse mass b", inverseMassB);
15
-
16
- let relativeVelocity = PointCal.subVector(bodyA.linearVelocity, bodyB.linearVelocity);
17
- // console.log("relative velocity: ", relativeVelocity);
18
- // console.log("linear velocity of a", bodyA.getLinearVelocity());
19
- // console.log("linear veolcity of b", bodyB.getLinearVelocity());
20
- let J = -(1 + restitution) * PointCal.dotProduct(relativeVelocity, normal);
21
- J /= inverseMassA + inverseMassB;
22
-
23
- let deltaVelocityA = PointCal.multiplyVectorByScalar(normal, J * inverseMassA);
24
- let deltaVelocityB = PointCal.multiplyVectorByScalar(normal, J * inverseMassB);
25
- // console.log("delta velocity A:", deltaVelocityA);
26
- // console.log("delta velocity B:", deltaVelocityB);
27
-
28
- bodyA.linearVelocity = PointCal.addVector(bodyA.linearVelocity, deltaVelocityA);
29
- bodyB.linearVelocity = PointCal.subVector(bodyB.linearVelocity, deltaVelocityB);
30
- }
31
-
32
- export function resolveCollisionWithRotation(bodyA: RigidBody, bodyB: RigidBody, contactManifold: {normal: Point, contactPoints: Point[]}){
33
- // console.log("resolve");
34
- if (bodyA.isStatic() && bodyB.isStatic()) {
35
- return;
36
- }
37
-
38
- let restitution = 0.4;
39
- let inverseMassA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.mass;
40
- let inverseMassB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.mass;
41
-
42
- let inverseMMOIA = bodyA.isStatic() || bodyA.isMovingStatic() ? 0 : 1 / bodyA.momentOfInertia;
43
- let inverseMMOIB = bodyB.isStatic() || bodyB.isMovingStatic() ? 0 : 1 / bodyB.momentOfInertia;
44
-
45
- const Js: Point[] = [];
46
- for(let index = 0; index < contactManifold.contactPoints.length; index++){
47
- const contactPoint = contactManifold.contactPoints[index];
48
- const rA = PointCal.subVector(contactPoint, bodyA.center);
49
- const rB = PointCal.subVector(contactPoint, bodyB.center);
50
- const rAPerpendicular = {x: -rA.y, y: rA.x};
51
- const rBPerpendicular = {x: -rB.y, y: rB.x};
52
-
53
- const angularVelocityA = PointCal.multiplyVectorByScalar(rAPerpendicular, bodyA.angularVelocity);
54
- const angularVelocityB = PointCal.multiplyVectorByScalar(rBPerpendicular, bodyB.angularVelocity);
55
-
56
- // console.log("inverse mass a", inverseMassA);
57
- // console.log("inverse mass b", inverseMassB);
58
-
59
- let relativeVelocity = PointCal.subVector(PointCal.addVector(bodyA.linearVelocity, angularVelocityA), PointCal.addVector(bodyB.linearVelocity, angularVelocityB));
60
- // console.log("relative velocity: ", relativeVelocity);
61
- // console.log("linear velocity of a", bodyA.getLinearVelocity());
62
- // console.log("linear veolcity of b", bodyB.getLinearVelocity());
63
- let relativeVelocityNormal = PointCal.dotProduct(relativeVelocity, contactManifold.normal);
64
- const rAPerpendicularNormal = PointCal.dotProduct(rAPerpendicular, contactManifold.normal);
65
- const rBPerpendicularNormal = PointCal.dotProduct(rBPerpendicular, contactManifold.normal);
66
-
67
- const denominator = inverseMassA + inverseMassB + rAPerpendicularNormal * rAPerpendicularNormal * inverseMMOIA + rBPerpendicularNormal * rBPerpendicularNormal * inverseMMOIB;
68
- let J = -(1 + restitution) * relativeVelocityNormal;
69
- J /= denominator;
70
-
71
- J /= contactManifold.contactPoints.length;
72
-
73
- Js.push(PointCal.multiplyVectorByScalar(contactManifold.normal, J));
74
- }
75
-
76
- Js.forEach((impulse, index) => {
77
- let deltaVelocityA = PointCal.multiplyVectorByScalar(impulse, inverseMassA);
78
- let deltaVelocityB = PointCal.multiplyVectorByScalar(impulse, inverseMassB);
79
-
80
- bodyA.linearVelocity = PointCal.addVector(bodyA.linearVelocity, deltaVelocityA);
81
- let resA = PointCal.crossProduct(PointCal.subVector(contactManifold.contactPoints[index], bodyA.center), impulse).z;
82
- resA = resA == undefined ? 0 : resA;
83
- let resB = PointCal.crossProduct(PointCal.subVector(contactManifold.contactPoints[index], bodyB.center), impulse).z;
84
- resB = resB == undefined ? 0 : resB;
85
- bodyA.angularVelocity += resA * inverseMMOIA;
86
- bodyB.angularVelocity -= resB * inverseMMOIB;
87
- bodyB.linearVelocity = PointCal.subVector(bodyB.linearVelocity, deltaVelocityB);
88
- });
89
- }
90
-
91
- export function aabbIntersects(aabbA: {min: Point, max: Point}, aabbB: {min: Point, max: Point}): boolean{
92
- if ((aabbA.min.x <= aabbB.max.x && aabbB.min.x <= aabbA.max.x) && (aabbA.min.y <= aabbB.max.y && aabbB.min.y <= aabbA.max.y)) {
93
- return true;
94
- }
95
- return false;
96
- }
97
-
98
- export function intersects(bodyA: RigidBody, bodyB: RigidBody): {collision: boolean, depth?: number, normal?: Point}{
99
- let axis: Point[] = [];
100
- let bodyAAxes = bodyA.getCollisionAxes(bodyB);
101
- let bodyBAxes = bodyB.getCollisionAxes(bodyA);
102
-
103
- axis.push(...bodyAAxes);
104
- axis.push(...bodyBAxes);
105
-
106
- let collision = true;
107
- let minDepth = Number.MAX_VALUE;
108
- let minAxis = axis[0];
109
-
110
- axis.forEach(projAxis => {
111
- let bodyAInterval = bodyA.getMinMaxProjection(projAxis);
112
- let bodyBInterval = bodyB.getMinMaxProjection(projAxis);
113
-
114
- if (bodyAInterval.min >= bodyBInterval.max || bodyBInterval.min >= bodyAInterval.max) {
115
- collision = false;
116
- }else {
117
- let depth = Math.abs(Math.min(bodyAInterval.max, bodyBInterval.max) - Math.max(bodyBInterval.min, bodyAInterval.min));
118
- if (depth < minDepth) {
119
- minDepth = depth;
120
- minAxis = projAxis;
121
- if (bodyAInterval.max < bodyBInterval.max) {
122
- minAxis = PointCal.multiplyVectorByScalar(minAxis, -1);
123
- }
124
- }
125
- }
126
- });
127
-
128
- if (collision){
129
- return {collision: collision, depth: minDepth, normal: minAxis};
130
- }else {
131
- return {collision: false, depth: undefined, normal: undefined};
132
- }
133
- }
134
-
135
- export function narrowPhaseWithRigidBody(bodies: RigidBody[], combinationsToCheck: {bodyA: RigidBody, bodyB: RigidBody}[], resolveCollisionFlag: boolean): Point[]{
136
- if (!resolveCollisionFlag) {
137
- return [];
138
- }
139
- const contactPoints: Point[] = [];
140
- combinationsToCheck.forEach(combination => {
141
- let bodyA = combination.bodyA;
142
- let bodyB = combination.bodyB;
143
- if (bodyA == bodyB) {
144
- // console.log("same body");
145
- return;
146
- }
147
- let bodyAZ = bodyA.center.z == undefined ? 0 : bodyA.center.z;
148
- let bodyBZ = bodyB.center.z == undefined ? 0 : bodyB.center.z;
149
- if(Math.abs(bodyAZ - bodyBZ) > 0.5){
150
- // console.log("z-index difference is too large");
151
- return;
152
- }
153
- let {collision, depth, normal: normalAxis} = intersects(bodyA, bodyB);
154
- if (collision && normalAxis !== undefined && depth !== undefined) {
155
- // the normal axis points in the direction that push bodyA away from bodyB
156
-
157
- let moveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, depth / 2);
158
- let revMoveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, -depth / 2);
159
-
160
- if (!bodyA.isStatic()) {
161
- bodyA.move(moveDisplacement);
162
- }
163
- if (!bodyB.isStatic()) {
164
- bodyB.move(revMoveDisplacement);
165
- }
166
- if (bodyA.isStatic()) {
167
- // bodyA.move(revMoveDisplacement);
168
- bodyB.move(revMoveDisplacement);
169
- }
170
- if (bodyB.isStatic()) {
171
- bodyA.move(moveDisplacement);
172
- // bodyB.move(moveDisplacement);
173
- }
174
-
175
- // finding the collision contact point(s)
176
- const bodyASigNormal = bodyA.getNormalOfSignificantFace(PointCal.multiplyVectorByScalar(normalAxis, -1));
177
- const bodyBSigNormal = bodyB.getNormalOfSignificantFace(normalAxis);
178
- const bodyASigVertices = bodyA.getSignificantVertices(PointCal.multiplyVectorByScalar(normalAxis, -1));
179
- const bodyBSigVertices = bodyB.getSignificantVertices(normalAxis);
180
- const bodyAParallelIndicator = Math.abs(PointCal.dotProduct(bodyASigNormal, PointCal.multiplyVectorByScalar(normalAxis, -1)));
181
- const bodyBParallelIndicator = Math.abs(PointCal.dotProduct(bodyBSigNormal, normalAxis));
182
-
183
- if (bodyBSigVertices.length == 1 || bodyASigVertices.length == 1){
184
- // one of the body is a circle
185
- // console.log("involving a circle");
186
- if (bodyBSigVertices.length == 1){
187
- // bodyB is a circle
188
- // contact point is on the perimeter of the circle and the direction is the collision normal
189
- contactPoints.push(bodyBSigVertices[0]);
190
- } else {
191
- // bodyA is a circle
192
- // contact point is on the perimeter of the circle and the direction is the collision normal
193
- contactPoints.push(bodyASigVertices[0]);
194
- }
195
- }
196
- else if (bodyAParallelIndicator > bodyBParallelIndicator) {
197
- // bodyA has the normal that is the most parallel to the collision normal
198
- const adjacentFaces = bodyA.getAdjacentFaces(PointCal.multiplyVectorByScalar(normalAxis, -1));
199
- let faceToClip = [...bodyBSigVertices];
200
- for(let index = 0; index < adjacentFaces.length - 1; index++){
201
- let startPoint = adjacentFaces[index].startPoint.coord;
202
- let endPoint = adjacentFaces[index].endPoint.coord;
203
- let direction = PointCal.subVector(endPoint, startPoint);
204
- let sigStart = PointCal.subVector(faceToClip[0], startPoint);
205
- let sigEnd = PointCal.subVector(faceToClip[1], startPoint);
206
- let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;
207
- let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;
208
- if ((startInside ? 1 : 0) ^ (endInside ? 1 : 0)){
209
- // one of the point is outside the face
210
- let intersectionPoint = PointCal.getLineIntersection(startPoint, endPoint, faceToClip[0], faceToClip[1]);
211
- if (intersectionPoint.intersects && intersectionPoint.intersection !== undefined){
212
- if(startInside){
213
- faceToClip[1] = intersectionPoint.intersection;
214
- } else {
215
- faceToClip[0] = intersectionPoint.intersection;
216
- }
217
- }
218
- }
219
- }
220
- const referenceFace = adjacentFaces[adjacentFaces.length - 1];
221
- let startPoint = referenceFace.startPoint.coord;
222
- let endPoint = referenceFace.endPoint.coord;
223
- let direction = PointCal.subVector(endPoint, startPoint);
224
- let sigStart = PointCal.subVector(faceToClip[0], startPoint);
225
- let sigEnd = PointCal.subVector(faceToClip[1], startPoint);
226
- let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;
227
- let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;
228
- if (startInside){
229
- contactPoints.push(faceToClip[0]);
230
- }
231
- if (endInside){
232
- contactPoints.push(faceToClip[1]);
233
- }
234
- } else {
235
- // bodyB has the normal that is the most parallel to the collision normal
236
- const adjacentFaces = bodyB.getAdjacentFaces(normalAxis);
237
- let faceToClip = [...bodyASigVertices];
238
- if(faceToClip.length == 0){
239
- console.log("warning");
240
- }
241
- let count = 0;
242
- for(let index = 0; index < adjacentFaces.length - 1; index++){
243
- let startPoint = adjacentFaces[index].startPoint.coord;
244
- let endPoint = adjacentFaces[index].endPoint.coord;
245
- let direction = PointCal.subVector(endPoint, startPoint);
246
- let sigStart = PointCal.subVector(faceToClip[0], startPoint);
247
- let sigEnd = PointCal.subVector(faceToClip[1], startPoint);
248
- let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;
249
- let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;
250
- if ((startInside ? 1 : 0) ^ (endInside ? 1 : 0)){
251
- count += 1;
252
- // one of the point is outside the face
253
- let intersectionPoint = PointCal.getLineIntersection(startPoint, endPoint, faceToClip[0], faceToClip[1]);
254
- if (intersectionPoint.intersects && intersectionPoint.intersection !== undefined){
255
- if(startInside){
256
- faceToClip[1] = intersectionPoint.intersection;
257
- } else {
258
- faceToClip[0] = intersectionPoint.intersection;
259
- }
260
- }
261
- }
262
- }
263
- const referenceFace = adjacentFaces[adjacentFaces.length - 1];
264
- let startPoint = referenceFace.startPoint.coord;
265
- let endPoint = referenceFace.endPoint.coord;
266
- let direction = PointCal.subVector(endPoint, startPoint);
267
- let sigStart = PointCal.subVector(faceToClip[0], startPoint);
268
- let sigEnd = PointCal.subVector(faceToClip[1], startPoint);
269
- let startInside = PointCal.angleFromA2B(direction, sigStart) >= 0;
270
- let endInside = PointCal.angleFromA2B(direction, sigEnd) >= 0;
271
- if (startInside){
272
- contactPoints.push(faceToClip[0]);
273
- }
274
- if (endInside){
275
- contactPoints.push(faceToClip[1]);
276
- }
277
- }
278
- if (resolveCollisionFlag) {
279
- resolveCollisionWithRotation(bodyA, bodyB, {normal: normalAxis, contactPoints: contactPoints});
280
- // resolveCollision(bodyA, bodyB, normalAxis);
281
- }
282
- }
283
- });
284
- return contactPoints;
285
- }
286
-
287
- export function narrowPhase(bodies: BaseRigidBody[], combinationsToCheck: {bodyAIndex: number, bodyBIndex: number}[], resolveCollisionFlag: boolean): void {
288
- if (!resolveCollisionFlag) {
289
- return;
290
- }
291
- combinationsToCheck.forEach(combination => {
292
- let bodyA = bodies[combination.bodyAIndex];
293
- let bodyB = bodies[combination.bodyBIndex];
294
- let {collision, depth, normal: normalAxis} = intersects(bodyA, bodyB);
295
- if (collision && normalAxis !== undefined && depth !== undefined) {
296
- // console.log("collision");
297
- let moveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, depth / 2);
298
- let revMoveDisplacement = PointCal.multiplyVectorByScalar(normalAxis, -depth / 2);
299
-
300
- if (!bodyA.isStatic()) {
301
- bodyA.move(moveDisplacement);
302
- }
303
- if (!bodyB.isStatic()) {
304
- bodyB.move(revMoveDisplacement);
305
- }
306
- if (bodyA.isStatic()) {
307
- // bodyA.move(revMoveDisplacement);
308
- bodyB.move(revMoveDisplacement);
309
- }
310
- if (bodyB.isStatic()) {
311
- bodyA.move(moveDisplacement);
312
- // bodyB.move(moveDisplacement);
313
- }
314
-
315
- if (resolveCollisionFlag) {
316
- resolveCollision(bodyA, bodyB, normalAxis);
317
- }
318
-
319
- }
320
- })
321
- }
322
-
323
- export function broadPhaseWithRigidBodyReturned(quadTree: QuadTree, bodies: RigidBody[]): {bodyA: RigidBody, bodyB: RigidBody}[]{
324
- let possibleCombi: {bodyA: RigidBody, bodyB: RigidBody}[] = [];
325
- for(let index = 0; index <= bodies.length - 1; index++){
326
- let objsToCheck = quadTree.retrieve(bodies[index]);
327
- for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){
328
- let bodyA = bodies[index];
329
- let bodyB = objsToCheck[jindex];
330
- if (bodyA.isStatic() && bodyB.isStatic()){
331
- continue;
332
- }
333
- if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){
334
- continue;
335
- }
336
- possibleCombi.push({bodyA: bodyA, bodyB: bodyB});
337
- }
338
- }
339
- return possibleCombi
340
- }
341
-
342
- export function broadPhase(quadTree: QuadTree, bodies: BaseRigidBody[]): {bodyAIndex: number, bodyBIndex: number}[]{
343
- let possibleCombi: {bodyAIndex: number, bodyBIndex: number}[] = [];
344
- for(let index = 0; index <= bodies.length - 1; index++){
345
- let objsToCheck = quadTree.retrieve(bodies[index]);
346
- for(let jindex = 0; jindex <= objsToCheck.length - 1; jindex++){
347
- let bodyA = bodies[index];
348
- let bodyB = objsToCheck[jindex];
349
- if (bodyA.isStatic() && bodyB.isStatic()){
350
- continue;
351
- }
352
- if(!aabbIntersects(bodyA.AABB, bodyB.AABB)){
353
- continue;
354
- }
355
- possibleCombi.push({bodyAIndex: index, bodyBIndex: jindex});
356
- }
357
- }
358
- return possibleCombi
359
- }
package/src/constraint.ts DELETED
@@ -1,245 +0,0 @@
1
- import { Point, PointCal } from "@ue-too/math";
2
- import { RigidBody } from "./rigidbody";
3
-
4
- export interface Constraint {
5
- enforce(dt: number): void;
6
- }
7
-
8
- export class FixedPinJoint implements Constraint {
9
-
10
- private anchorA: Point;
11
- private worldAnchorA: Point;
12
- private bodyA: RigidBody;
13
-
14
- constructor(bodyA: RigidBody, anchorA: Point, worldAnchorA: Point) {
15
- this.bodyA = bodyA;
16
- this.anchorA = anchorA;
17
- this.worldAnchorA = worldAnchorA;
18
- }
19
-
20
- enforce(dt: number): void {
21
- this.solveWorldPinJointConstraint(dt);
22
- }
23
-
24
- solveWorldPinJointConstraint(dt: number) {
25
- const body = this.bodyA;
26
- const localAnchor = this.anchorA;
27
- const worldAnchor = this.worldAnchorA;
28
-
29
- // Transform local anchor point to world space
30
- const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));
31
-
32
- // Calculate the difference between the anchor points
33
- const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);
34
-
35
- // Calculate the relative velocity of the anchor point
36
- const r = PointCal.subVector(worldAnchorOnBody, body.center);
37
- const velocity = PointCal.addVector(
38
- body.linearVelocity,
39
- PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)
40
- );
41
-
42
- // Calculate the mass matrix
43
- const invMass = body.isStatic() ? 0 : 1 / body.mass;
44
- const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;
45
-
46
- const K = {
47
- x: invMass + invI * r.y * r.y,
48
- y: invMass + invI * r.x * r.x,
49
- xy: -invI * r.x * r.y
50
- };
51
-
52
- // Calculate the impulse
53
- const baumgarte = 1; // Baumgarte stabilization factor
54
- const impulse = {
55
- x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,
56
- y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y
57
- };
58
-
59
- // Apply the impulse
60
- if (!body.isStatic()) {
61
- body.linearVelocity.x += invMass * impulse.x;
62
- body.linearVelocity.y += invMass * impulse.y;
63
- body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);
64
- }
65
- }
66
- }
67
-
68
- export class PinJoint implements Constraint {
69
-
70
- private anchorA: Point;
71
- private anchorB: Point;
72
- private bodyA: RigidBody;
73
- private bodyB: RigidBody;
74
-
75
- constructor(bodyA: RigidBody, bodyB: RigidBody, anchorA: Point, anchorB: Point) {
76
- this.bodyA = bodyA;
77
- this.bodyB = bodyB;
78
- this.anchorA = anchorA;
79
- this.anchorB = anchorB;
80
- }
81
-
82
- enforce(dt: number): void {
83
- this.solvePinJointConstraint(dt);
84
- }
85
-
86
- solvePinJointConstraint(dt: number) {
87
- const bodyA = this.bodyA;
88
- const bodyB = this.bodyB;
89
- const anchorA = this.anchorA;
90
- const anchorB = this.anchorB;
91
-
92
- // Transform local anchor points to world space
93
- const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));
94
- const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));
95
-
96
- // Calculate the difference between the two anchor points in world space
97
- const diff = PointCal.subVector(worldAnchorB, worldAnchorA);
98
-
99
- // Calculate the relative velocity of the anchor points
100
- const rA = PointCal.subVector(worldAnchorA, bodyA.center);
101
- const rB = PointCal.subVector(worldAnchorB, bodyB.center);
102
- const relativeVelocity = PointCal.subVector(
103
- PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),
104
- PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))
105
- );
106
-
107
- // Calculate the mass matrix
108
- const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;
109
- const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;
110
- const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;
111
- const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;
112
-
113
- const K = {
114
- x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,
115
- y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,
116
- xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y
117
- };
118
-
119
- // Calculate the impulse
120
- const baumgarte = 1; // Baumgarte stabilization factor
121
- const impulse = {
122
- x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,
123
- y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y
124
- };
125
-
126
- // Apply the impulse
127
- if (!bodyA.isStatic()) {
128
- bodyA.linearVelocity.x -= invMassA * impulse.x;
129
- bodyA.linearVelocity.y -= invMassA * impulse.y;
130
- bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);
131
- }
132
-
133
- if (!bodyB.isStatic()) {
134
- bodyB.linearVelocity.x += invMassB * impulse.x;
135
- bodyB.linearVelocity.y += invMassB * impulse.y;
136
- bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);
137
- }
138
- }
139
-
140
- }
141
-
142
- export interface PinJointConstraint {
143
- bodyA: RigidBody;
144
- bodyB: RigidBody;
145
- anchorA: Point; // Local anchor point for bodyA
146
- anchorB: Point; // Local anchor point for bodyB
147
- }
148
-
149
- export function solvePinJointConstraint(constraint: PinJointConstraint, dt: number) {
150
- const { bodyA, bodyB, anchorA, anchorB } = constraint;
151
-
152
- // Transform local anchor points to world space
153
- const worldAnchorA = PointCal.addVector(bodyA.center, PointCal.rotatePoint(anchorA, bodyA.orientationAngle));
154
- const worldAnchorB = PointCal.addVector(bodyB.center, PointCal.rotatePoint(anchorB, bodyB.orientationAngle));
155
-
156
- // Calculate the difference between the two anchor points in world space
157
- const diff = PointCal.subVector(worldAnchorB, worldAnchorA);
158
-
159
- // Calculate the relative velocity of the anchor points
160
- const rA = PointCal.subVector(worldAnchorA, bodyA.center);
161
- const rB = PointCal.subVector(worldAnchorB, bodyB.center);
162
- const relativeVelocity = PointCal.subVector(
163
- PointCal.addVector(bodyB.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyB.angularVelocity}, rB)),
164
- PointCal.addVector(bodyA.linearVelocity, PointCal.crossProduct({x: 0, y: 0, z: bodyA.angularVelocity}, rA))
165
- );
166
-
167
- // Calculate the mass matrix
168
- const invMassA = bodyA.isStatic() ? 0 : 1 / bodyA.mass;
169
- const invMassB = bodyB.isStatic() ? 0 : 1 / bodyB.mass;
170
- const invIA = bodyA.isStatic() ? 0 : 1 / bodyA.momentOfInertia;
171
- const invIB = bodyB.isStatic() ? 0 : 1 / bodyB.momentOfInertia;
172
-
173
- const K = {
174
- x: invMassA + invMassB + invIA * rA.y * rA.y + invIB * rB.y * rB.y,
175
- y: invMassA + invMassB + invIA * rA.x * rA.x + invIB * rB.x * rB.x,
176
- xy: -invIA * rA.x * rA.y - invIB * rB.x * rB.y
177
- };
178
-
179
- // Calculate the impulse
180
- const baumgarte = 0.5; // Baumgarte stabilization factor
181
- const impulse = {
182
- x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - relativeVelocity.x,
183
- y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - relativeVelocity.y
184
- };
185
-
186
- // Apply the impulse
187
- if (!bodyA.isStatic()) {
188
- bodyA.linearVelocity.x -= invMassA * impulse.x;
189
- bodyA.linearVelocity.y -= invMassA * impulse.y;
190
- bodyA.angularVelocity -= invIA * (rA.x * impulse.y - rA.y * impulse.x);
191
- }
192
-
193
- if (!bodyB.isStatic()) {
194
- bodyB.linearVelocity.x += invMassB * impulse.x;
195
- bodyB.linearVelocity.y += invMassB * impulse.y;
196
- bodyB.angularVelocity += invIB * (rB.x * impulse.y - rB.y * impulse.x);
197
- }
198
- }
199
-
200
- export interface WorldPinJointConstraint {
201
- body: RigidBody;
202
- localAnchor: Point; // Anchor point in body's local space
203
- worldAnchor: Point; // Fixed point in world space
204
- }
205
-
206
- export function solveWorldPinJointConstraint(constraint: WorldPinJointConstraint, dt: number) {
207
- const { body, localAnchor, worldAnchor } = constraint;
208
-
209
- // Transform local anchor point to world space
210
- const worldAnchorOnBody = PointCal.addVector(body.center, PointCal.rotatePoint(localAnchor, body.orientationAngle));
211
-
212
- // Calculate the difference between the anchor points
213
- const diff = PointCal.subVector(worldAnchorOnBody, worldAnchor);
214
-
215
- // Calculate the relative velocity of the anchor point
216
- const r = PointCal.subVector(worldAnchorOnBody, body.center);
217
- const velocity = PointCal.addVector(
218
- body.linearVelocity,
219
- PointCal.crossProduct({x: 0, y: 0, z: body.angularVelocity}, r)
220
- );
221
-
222
- // Calculate the mass matrix
223
- const invMass = body.isStatic() ? 0 : 1 / body.mass;
224
- const invI = body.isStatic() ? 0 : 1 / body.momentOfInertia;
225
-
226
- const K = {
227
- x: invMass + invI * r.y * r.y,
228
- y: invMass + invI * r.x * r.x,
229
- xy: -invI * r.x * r.y
230
- };
231
-
232
- // Calculate the impulse
233
- const baumgarte = 0.2; // Baumgarte stabilization factor
234
- const impulse = {
235
- x: -K.x * diff.x - K.xy * diff.y - baumgarte * diff.x / dt - velocity.x,
236
- y: -K.xy * diff.x - K.y * diff.y - baumgarte * diff.y / dt - velocity.y
237
- };
238
-
239
- // Apply the impulse
240
- if (!body.isStatic()) {
241
- body.linearVelocity.x += invMass * impulse.x;
242
- body.linearVelocity.y += invMass * impulse.y;
243
- body.angularVelocity += invI * (r.x * impulse.y - r.y * impulse.x);
244
- }
245
- }
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from "./rigidbody";
2
- export * from "./quadtree";
3
- export * from "./collision";