dacha 0.17.2 → 0.18.0-alpha.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/build/contrib/components/collider/index.d.ts +17 -4
- package/build/contrib/components/collider/index.js +30 -2
- package/build/contrib/components/rigid-body/index.d.ts +29 -17
- package/build/contrib/components/rigid-body/index.js +64 -21
- package/build/contrib/components/shape/index.d.ts +17 -2
- package/build/contrib/components/shape/index.js +16 -0
- package/build/contrib/events/index.d.ts +10 -75
- package/build/contrib/events/index.js +0 -36
- package/build/contrib/systems/camera-system/{service.d.ts → api.d.ts} +4 -4
- package/build/contrib/systems/camera-system/{service.js → api.js} +2 -2
- package/build/contrib/systems/camera-system/index.d.ts +1 -1
- package/build/contrib/systems/camera-system/index.js +1 -1
- package/build/contrib/systems/camera-system/system.d.ts +1 -1
- package/build/contrib/systems/camera-system/system.js +5 -4
- package/build/contrib/systems/index.d.ts +3 -3
- package/build/contrib/systems/index.js +3 -3
- package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.d.ts +0 -1
- package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.js +4 -5
- package/build/contrib/systems/physics-system/api.d.ts +58 -0
- package/build/contrib/systems/physics-system/api.js +67 -0
- package/build/contrib/systems/physics-system/index.d.ts +2 -21
- package/build/contrib/systems/physics-system/index.js +2 -40
- package/build/contrib/systems/physics-system/physics-system.d.ts +24 -0
- package/build/contrib/systems/physics-system/physics-system.js +47 -0
- package/build/contrib/systems/physics-system/subsystems/collision-broadcast/collision.d.ts +5 -3
- package/build/contrib/systems/physics-system/subsystems/collision-broadcast/collision.js +7 -5
- package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.d.ts +4 -6
- package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.js +20 -17
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-circle-aabb.js +1 -2
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-point-aabb.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-point-aabb.js +7 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-ray-aabb.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-ray-aabb.js +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-segment-aabb.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/build-segment-aabb.js +14 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/aabb-builders/index.js +6 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-box-geometry.d.ts +3 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-box-geometry.js +52 -16
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-circle-geometry.d.ts +3 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-circle-geometry.js +32 -7
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-point-geometry.d.ts +3 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-point-geometry.js +5 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-ray-geometry.d.ts +3 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-ray-geometry.js +7 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-segment-geometry.d.ts +3 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/build-segment-geometry.js +33 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/index.d.ts +12 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/geometry-builders/index.js +6 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +21 -9
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +177 -92
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.d.ts +10 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.js +36 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.d.ts +17 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.js +126 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-circle/check-box-and-circle-intersection.d.ts +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-circle/check-box-and-circle-intersection.js +46 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.d.ts +10 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.js +28 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/utils.d.ts +19 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/utils.js +76 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-circle/check-circles-intersection.d.ts +12 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-circle/check-circles-intersection.js +47 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-segment/check-circle-and-segment-intersection.d.ts +10 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/circle-segment/check-circle-and-segment-intersection.js +33 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.d.ts +2 -2
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.js +27 -3
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-box/check-point-and-box-intersection.d.ts +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-box/check-point-and-box-intersection.js +36 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-circle/check-point-and-circle-intersection.d.ts +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-circle/check-point-and-circle-intersection.js +33 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-segment/check-point-and-segment-intersection.d.ts +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/point-segment/check-point-and-segment-intersection.js +26 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-box/check-ray-and-box-intersection.d.ts +11 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-box/check-ray-and-box-intersection.js +69 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-circle/check-ray-and-circle-intersection.d.ts +10 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-circle/check-ray-and-circle-intersection.js +45 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/check-ray-and-segment-intersection.d.ts +16 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/check-ray-and-segment-intersection.js +51 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/utils.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/ray-segment/utils.js +4 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.d.ts +20 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.js +69 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/utils.d.ts +9 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/utils.js +23 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.d.ts +10 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.js +63 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/reorientation-checkers/check-collider.js +17 -8
- package/build/contrib/systems/physics-system/subsystems/collision-detection/types.d.ts +41 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/types.js +0 -3
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +7 -10
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +117 -79
- package/build/contrib/systems/physics-system/subsystems/index.d.ts +0 -1
- package/build/contrib/systems/physics-system/subsystems/index.js +0 -1
- package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +3 -9
- package/build/contrib/systems/physics-system/subsystems/physics/index.js +57 -93
- package/build/contrib/systems/physics-system/types.d.ts +37 -0
- package/build/contrib/systems/renderer/actor-render-tree.js +1 -2
- package/build/contrib/systems/renderer/{service → api}/index.d.ts +6 -6
- package/build/contrib/systems/renderer/{service → api}/index.js +14 -16
- package/build/contrib/systems/renderer/api/utils.d.ts +4 -0
- package/build/contrib/systems/renderer/{service → api}/utils.js +5 -0
- package/build/contrib/systems/renderer/builders/shape-builder/index.js +9 -1
- package/build/contrib/systems/renderer/builders/shape-builder/utils.js +16 -0
- package/build/contrib/systems/renderer/index.d.ts +1 -1
- package/build/contrib/systems/renderer/index.js +1 -1
- package/build/contrib/systems/renderer/renderer.d.ts +2 -1
- package/build/contrib/systems/renderer/renderer.js +9 -7
- package/build/engine/actor/actor-creator.js +6 -4
- package/build/engine/math-lib/math/ops.d.ts +1 -2
- package/build/engine/math-lib/math/ops.js +3 -3
- package/build/engine/math-lib/vector/ops.d.ts +18 -3
- package/build/engine/math-lib/vector/ops.js +28 -5
- package/build/engine/math-lib/vector/vector2.d.ts +22 -7
- package/build/engine/math-lib/vector/vector2.js +29 -5
- package/build/engine/template/template-collection.js +1 -1
- package/build/engine/world/index.d.ts +4 -24
- package/build/engine/world/index.js +5 -33
- package/build/engine/world/system-api-registry.d.ts +17 -0
- package/build/engine/world/system-api-registry.js +34 -0
- package/build/events/index.d.ts +2 -2
- package/build/events/index.js +1 -1
- package/build/types/global.d.ts +4 -0
- package/package.json +4 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-box-and-circle-intersection.d.ts +0 -16
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-box-and-circle-intersection.js +0 -80
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-boxes-intersection.d.ts +0 -6
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-boxes-intersection.js +0 -72
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-circles-intersection.d.ts +0 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/check-circles-intersection.js +0 -39
- package/build/contrib/systems/physics-system/subsystems/collision-solver/index.d.ts +0 -10
- package/build/contrib/systems/physics-system/subsystems/collision-solver/index.js +0 -50
- package/build/contrib/systems/renderer/service/utils.d.ts +0 -3
|
@@ -1,36 +1,12 @@
|
|
|
1
|
-
import { Vector2 } from '../../../../../engine/math-lib';
|
|
2
1
|
import { RigidBody } from '../../../../components/rigid-body';
|
|
3
2
|
import { Transform } from '../../../../components/transform';
|
|
4
|
-
import { Collision } from '../../../../events';
|
|
5
3
|
import { RIGID_BODY_TYPE } from '../../consts';
|
|
4
|
+
const SOLVER_ITERATIONS = 8;
|
|
5
|
+
const POSITION_CORRECTION_PERCENT = 0.8;
|
|
6
|
+
const PENETRATION_SLOP = 0.01;
|
|
7
|
+
const DEFAULT_CONTACT_FRICTION = 0.6;
|
|
6
8
|
export class ConstraintSolver {
|
|
7
|
-
|
|
8
|
-
processedPairs;
|
|
9
|
-
mtvMap;
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.scene = options.scene;
|
|
12
|
-
this.processedPairs = new Map();
|
|
13
|
-
this.mtvMap = new Map();
|
|
14
|
-
this.scene.addEventListener(Collision, this.handleCollision);
|
|
15
|
-
}
|
|
16
|
-
destroy() {
|
|
17
|
-
this.scene.removeEventListener(Collision, this.handleCollision);
|
|
18
|
-
}
|
|
19
|
-
handleCollision = (event) => {
|
|
20
|
-
const { actor1, actor2, mtv1, mtv2 } = event;
|
|
21
|
-
if (this.processedPairs.has(actor2) &&
|
|
22
|
-
this.processedPairs.get(actor2).has(actor1)) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
if (!this.processedPairs.has(actor1)) {
|
|
26
|
-
this.processedPairs.set(actor1, new Set());
|
|
27
|
-
}
|
|
28
|
-
this.processedPairs.get(actor1).add(actor2);
|
|
29
|
-
if (!this.validateCollision(actor1, actor2)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
this.resolveCollision(actor1, actor2, mtv1, mtv2);
|
|
33
|
-
};
|
|
9
|
+
validContacts = [];
|
|
34
10
|
validateCollision(actor1, actor2) {
|
|
35
11
|
const rigidBody1 = actor1.getComponent(RigidBody);
|
|
36
12
|
const rigidBody2 = actor2.getComponent(RigidBody);
|
|
@@ -41,68 +17,130 @@ export class ConstraintSolver {
|
|
|
41
17
|
rigidBody2.type === RIGID_BODY_TYPE.STATIC) {
|
|
42
18
|
return false;
|
|
43
19
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
getInverseMass(rigidBody) {
|
|
23
|
+
if (rigidBody.disabled || rigidBody.type === RIGID_BODY_TYPE.STATIC) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
return rigidBody.inverseMass;
|
|
27
|
+
}
|
|
28
|
+
applyNormalImpulse(contact) {
|
|
29
|
+
const { actor1, actor2, normal } = contact;
|
|
30
|
+
const rigidBody1 = actor1.getComponent(RigidBody);
|
|
31
|
+
const rigidBody2 = actor2.getComponent(RigidBody);
|
|
32
|
+
const inverseMass1 = this.getInverseMass(rigidBody1);
|
|
33
|
+
const inverseMass2 = this.getInverseMass(rigidBody2);
|
|
34
|
+
const inverseMassSum = inverseMass1 + inverseMass2;
|
|
35
|
+
if (inverseMassSum === 0) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
const relativeVelocityX = rigidBody2.linearVelocity.x - rigidBody1.linearVelocity.x;
|
|
39
|
+
const relativeVelocityY = rigidBody2.linearVelocity.y - rigidBody1.linearVelocity.y;
|
|
40
|
+
const velocityAlongNormal = relativeVelocityX * normal.x + relativeVelocityY * normal.y;
|
|
41
|
+
if (velocityAlongNormal >= 0) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
const impulseMagnitude = -velocityAlongNormal / inverseMassSum;
|
|
45
|
+
const impulseX = normal.x * impulseMagnitude;
|
|
46
|
+
const impulseY = normal.y * impulseMagnitude;
|
|
47
|
+
if (inverseMass1 > 0) {
|
|
48
|
+
rigidBody1.linearVelocity.x -= impulseX * inverseMass1;
|
|
49
|
+
rigidBody1.linearVelocity.y -= impulseY * inverseMass1;
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (inverseMass2 > 0) {
|
|
52
|
+
rigidBody2.linearVelocity.x += impulseX * inverseMass2;
|
|
53
|
+
rigidBody2.linearVelocity.y += impulseY * inverseMass2;
|
|
54
|
+
}
|
|
55
|
+
return impulseMagnitude;
|
|
52
56
|
}
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
57
|
+
applyFrictionImpulse(contact, normalImpulseMagnitude) {
|
|
58
|
+
if (normalImpulseMagnitude <= 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const { normal } = contact;
|
|
62
|
+
const rigidBody1 = contact.actor1.getComponent(RigidBody);
|
|
63
|
+
const rigidBody2 = contact.actor2.getComponent(RigidBody);
|
|
64
|
+
const inverseMass1 = this.getInverseMass(rigidBody1);
|
|
65
|
+
const inverseMass2 = this.getInverseMass(rigidBody2);
|
|
66
|
+
const inverseMassSum = inverseMass1 + inverseMass2;
|
|
67
|
+
if (inverseMassSum === 0) {
|
|
68
|
+
return;
|
|
56
69
|
}
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
const relativeVelocityX = rigidBody2.linearVelocity.x - rigidBody1.linearVelocity.x;
|
|
71
|
+
const relativeVelocityY = rigidBody2.linearVelocity.y - rigidBody1.linearVelocity.y;
|
|
72
|
+
const velocityAlongNormal = relativeVelocityX * normal.x + relativeVelocityY * normal.y;
|
|
73
|
+
const tangentX = relativeVelocityX - normal.x * velocityAlongNormal;
|
|
74
|
+
const tangentY = relativeVelocityY - normal.y * velocityAlongNormal;
|
|
75
|
+
const tangentMagnitude = Math.sqrt(tangentX ** 2 + tangentY ** 2);
|
|
76
|
+
if (tangentMagnitude === 0) {
|
|
60
77
|
return;
|
|
61
78
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
const normalizedTangentX = tangentX / tangentMagnitude;
|
|
80
|
+
const normalizedTangentY = tangentY / tangentMagnitude;
|
|
81
|
+
const velocityAlongTangent = relativeVelocityX * normalizedTangentX +
|
|
82
|
+
relativeVelocityY * normalizedTangentY;
|
|
83
|
+
const unclampedImpulseMagnitude = -velocityAlongTangent / inverseMassSum;
|
|
84
|
+
const maxFrictionImpulseMagnitude = DEFAULT_CONTACT_FRICTION * normalImpulseMagnitude;
|
|
85
|
+
const impulseMagnitude = Math.max(-maxFrictionImpulseMagnitude, Math.min(unclampedImpulseMagnitude, maxFrictionImpulseMagnitude));
|
|
86
|
+
const impulseX = normalizedTangentX * impulseMagnitude;
|
|
87
|
+
const impulseY = normalizedTangentY * impulseMagnitude;
|
|
88
|
+
if (inverseMass1 > 0) {
|
|
89
|
+
rigidBody1.linearVelocity.x -= impulseX * inverseMass1;
|
|
90
|
+
rigidBody1.linearVelocity.y -= impulseY * inverseMass1;
|
|
91
|
+
}
|
|
92
|
+
if (inverseMass2 > 0) {
|
|
93
|
+
rigidBody2.linearVelocity.x += impulseX * inverseMass2;
|
|
94
|
+
rigidBody2.linearVelocity.y += impulseY * inverseMass2;
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
|
-
|
|
97
|
+
applyPositionCorrection(contact) {
|
|
98
|
+
const { actor1, actor2, normal, penetration } = contact;
|
|
75
99
|
const rigidBody1 = actor1.getComponent(RigidBody);
|
|
76
100
|
const rigidBody2 = actor2.getComponent(RigidBody);
|
|
77
|
-
|
|
78
|
-
|
|
101
|
+
const inverseMass1 = this.getInverseMass(rigidBody1);
|
|
102
|
+
const inverseMass2 = this.getInverseMass(rigidBody2);
|
|
103
|
+
const inverseMassSum = inverseMass1 + inverseMass2;
|
|
104
|
+
if (inverseMassSum === 0) {
|
|
105
|
+
return;
|
|
79
106
|
}
|
|
80
|
-
|
|
81
|
-
|
|
107
|
+
const correctionMagnitude = (Math.max(penetration - PENETRATION_SLOP, 0) *
|
|
108
|
+
POSITION_CORRECTION_PERCENT) /
|
|
109
|
+
inverseMassSum;
|
|
110
|
+
if (correctionMagnitude === 0) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const correctionX = normal.x * correctionMagnitude;
|
|
114
|
+
const correctionY = normal.y * correctionMagnitude;
|
|
115
|
+
const transform1 = actor1.getComponent(Transform);
|
|
116
|
+
const transform2 = actor2.getComponent(Transform);
|
|
117
|
+
if (inverseMass1 > 0) {
|
|
118
|
+
transform1.world.position.x -= correctionX * inverseMass1;
|
|
119
|
+
transform1.world.position.y -= correctionY * inverseMass1;
|
|
82
120
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
121
|
+
if (inverseMass2 > 0) {
|
|
122
|
+
transform2.world.position.x += correctionX * inverseMass2;
|
|
123
|
+
transform2.world.position.y += correctionY * inverseMass2;
|
|
86
124
|
}
|
|
87
125
|
}
|
|
88
|
-
update() {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
update(contacts) {
|
|
127
|
+
let validContactsCount = 0;
|
|
128
|
+
contacts.forEach((contact) => {
|
|
129
|
+
if (!this.validateCollision(contact.actor1, contact.actor2)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
this.validContacts[validContactsCount] = contact;
|
|
133
|
+
validContactsCount += 1;
|
|
134
|
+
});
|
|
135
|
+
this.validContacts.length = validContactsCount;
|
|
136
|
+
for (let iteration = 0; iteration < SOLVER_ITERATIONS; iteration += 1) {
|
|
137
|
+
this.validContacts.forEach((contact) => {
|
|
138
|
+
const normalImpulseMagnitude = this.applyNormalImpulse(contact);
|
|
139
|
+
this.applyFrictionImpulse(contact, normalImpulseMagnitude);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
this.validContacts.forEach((contact) => {
|
|
143
|
+
this.applyPositionCorrection(contact);
|
|
144
|
+
});
|
|
107
145
|
}
|
|
108
146
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { PhysicsSubsystem } from './physics';
|
|
2
2
|
export { CollisionDetectionSubsystem } from './collision-detection';
|
|
3
3
|
export { CollisionBroadcastSubsystem } from './collision-broadcast';
|
|
4
|
-
export { CollisionSolver } from './collision-solver';
|
|
5
4
|
export { ConstraintSolver } from './constraint-solver';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { PhysicsSubsystem } from './physics';
|
|
2
2
|
export { CollisionDetectionSubsystem } from './collision-detection';
|
|
3
3
|
export { CollisionBroadcastSubsystem } from './collision-broadcast';
|
|
4
|
-
export { CollisionSolver } from './collision-solver';
|
|
5
4
|
export { ConstraintSolver } from './constraint-solver';
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import type { SceneSystemOptions, UpdateOptions } from '../../../../../engine/system';
|
|
2
2
|
export declare class PhysicsSubsystem {
|
|
3
|
-
private scene;
|
|
4
3
|
private actorQuery;
|
|
5
4
|
private gravity;
|
|
6
|
-
private actorVectors;
|
|
7
5
|
constructor(options: SceneSystemOptions);
|
|
8
6
|
destroy(): void;
|
|
9
|
-
private
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private handleAddImpulse;
|
|
13
|
-
private setUpVectors;
|
|
14
|
-
private applyDragForce;
|
|
15
|
-
private getGravityForce;
|
|
7
|
+
private applyLinearDamping;
|
|
8
|
+
private integrateVelocities;
|
|
9
|
+
private integratePositions;
|
|
16
10
|
update(options: UpdateOptions): void;
|
|
17
11
|
}
|
|
@@ -1,125 +1,89 @@
|
|
|
1
|
-
import { Vector2 } from '../../../../../engine/math-lib';
|
|
2
1
|
import { ActorQuery } from '../../../../../engine/actor';
|
|
3
2
|
import { RigidBody } from '../../../../components/rigid-body';
|
|
4
3
|
import { Transform } from '../../../../components/transform';
|
|
5
|
-
import { AddForce, AddImpulse, StopMovement } from '../../../../events';
|
|
6
|
-
import { RemoveActor } from '../../../../../engine/events';
|
|
7
|
-
const DIRECTION_VECTOR = {
|
|
8
|
-
UP: new Vector2(0, -1),
|
|
9
|
-
LEFT: new Vector2(-1, 0),
|
|
10
|
-
RIGHT: new Vector2(1, 0),
|
|
11
|
-
DOWN: new Vector2(0, 1),
|
|
12
|
-
};
|
|
13
4
|
export class PhysicsSubsystem {
|
|
14
|
-
scene;
|
|
15
5
|
actorQuery;
|
|
16
6
|
gravity;
|
|
17
|
-
actorVectors;
|
|
18
7
|
constructor(options) {
|
|
19
8
|
const { gravity, scene } = options;
|
|
20
|
-
this.scene = scene;
|
|
21
9
|
this.actorQuery = new ActorQuery({ scene, filter: [RigidBody, Transform] });
|
|
22
10
|
this.gravity = gravity;
|
|
23
|
-
this.actorVectors = {};
|
|
24
|
-
this.actorQuery.addEventListener(RemoveActor, this.handleActorRemove);
|
|
25
|
-
this.scene.addEventListener(StopMovement, this.handleStopMovement);
|
|
26
|
-
this.scene.addEventListener(AddForce, this.handleAddForce);
|
|
27
|
-
this.scene.addEventListener(AddImpulse, this.handleAddImpulse);
|
|
28
11
|
}
|
|
29
12
|
destroy() {
|
|
30
|
-
this.actorQuery.
|
|
31
|
-
this.scene.removeEventListener(StopMovement, this.handleStopMovement);
|
|
32
|
-
this.scene.removeEventListener(AddForce, this.handleAddForce);
|
|
33
|
-
this.scene.removeEventListener(AddImpulse, this.handleAddImpulse);
|
|
13
|
+
this.actorQuery.destroy();
|
|
34
14
|
}
|
|
35
|
-
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
};
|
|
39
|
-
handleStopMovement = (event) => {
|
|
40
|
-
const { target } = event;
|
|
41
|
-
if (!this.actorVectors[target.id]) {
|
|
42
|
-
this.setUpVectors(target);
|
|
43
|
-
}
|
|
44
|
-
this.actorVectors[target.id].velocity.multiplyNumber(0);
|
|
45
|
-
};
|
|
46
|
-
handleAddForce = (event) => {
|
|
47
|
-
const { target, value } = event;
|
|
48
|
-
if (!this.actorVectors[target.id]) {
|
|
49
|
-
this.setUpVectors(target);
|
|
50
|
-
}
|
|
51
|
-
this.actorVectors[target.id].force.add(value);
|
|
52
|
-
};
|
|
53
|
-
handleAddImpulse = (event) => {
|
|
54
|
-
const { target, value } = event;
|
|
55
|
-
if (!this.actorVectors[target.id]) {
|
|
56
|
-
this.setUpVectors(target);
|
|
57
|
-
}
|
|
58
|
-
this.actorVectors[target.id].impulse.add(value);
|
|
59
|
-
};
|
|
60
|
-
setUpVectors(actor) {
|
|
61
|
-
this.actorVectors[actor.id] = {
|
|
62
|
-
velocity: new Vector2(0, 0),
|
|
63
|
-
force: new Vector2(0, 0),
|
|
64
|
-
impulse: new Vector2(0, 0),
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
applyDragForce(actor, deltaTime) {
|
|
68
|
-
const { mass, drag } = actor.getComponent(RigidBody);
|
|
69
|
-
const velocity = this.actorVectors[actor.id]?.velocity;
|
|
70
|
-
if (!drag || !velocity || (!velocity.x && !velocity.y)) {
|
|
15
|
+
applyLinearDamping(rigidBody, deltaTime) {
|
|
16
|
+
const { mass, linearDamping, linearVelocity } = rigidBody;
|
|
17
|
+
if (!linearDamping || (!linearVelocity.x && !linearVelocity.y)) {
|
|
71
18
|
return;
|
|
72
19
|
}
|
|
73
|
-
const velocitySignX = Math.sign(
|
|
74
|
-
const velocitySignY = Math.sign(
|
|
20
|
+
const velocitySignX = Math.sign(linearVelocity.x);
|
|
21
|
+
const velocitySignY = Math.sign(linearVelocity.y);
|
|
75
22
|
const reactionForceValue = mass * this.gravity;
|
|
76
|
-
const dragForceValue = -1 *
|
|
23
|
+
const dragForceValue = -1 * linearDamping * reactionForceValue;
|
|
77
24
|
const forceToVelocityMultiplier = deltaTime / mass;
|
|
78
25
|
const slowdownValue = dragForceValue * forceToVelocityMultiplier;
|
|
79
|
-
const normalizationMultiplier = 1 /
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (Math.sign(
|
|
84
|
-
Math.sign(
|
|
85
|
-
|
|
26
|
+
const normalizationMultiplier = 1 / linearVelocity.magnitude;
|
|
27
|
+
const slowdownMultiplier = slowdownValue * normalizationMultiplier;
|
|
28
|
+
linearVelocity.x += linearVelocity.x * slowdownMultiplier;
|
|
29
|
+
linearVelocity.y += linearVelocity.y * slowdownMultiplier;
|
|
30
|
+
if (Math.sign(linearVelocity.x) !== velocitySignX &&
|
|
31
|
+
Math.sign(linearVelocity.y) !== velocitySignY) {
|
|
32
|
+
linearVelocity.multiplyNumber(0);
|
|
86
33
|
}
|
|
87
34
|
}
|
|
88
|
-
|
|
89
|
-
const { mass, useGravity } = rigidBody;
|
|
90
|
-
const gravityVector = new Vector2(0, 0);
|
|
91
|
-
if (useGravity) {
|
|
92
|
-
gravityVector.add(DIRECTION_VECTOR.DOWN);
|
|
93
|
-
gravityVector.multiplyNumber(mass * this.gravity);
|
|
94
|
-
}
|
|
95
|
-
return gravityVector;
|
|
96
|
-
}
|
|
97
|
-
update(options) {
|
|
98
|
-
const { deltaTime } = options;
|
|
99
|
-
const deltaTimeInMsec = deltaTime;
|
|
100
|
-
const deltaTimeInSeconds = deltaTimeInMsec / 1000;
|
|
35
|
+
integrateVelocities(deltaTimeInSeconds) {
|
|
101
36
|
this.actorQuery.getActors().forEach((actor) => {
|
|
102
37
|
const rigidBody = actor.getComponent(RigidBody);
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
38
|
+
const { mass, inverseMass } = rigidBody;
|
|
39
|
+
if (rigidBody.disabled || rigidBody.type === 'static' || mass <= 0) {
|
|
40
|
+
rigidBody.clearForces();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const { force, impulse } = rigidBody;
|
|
44
|
+
const velocity = rigidBody.linearVelocity;
|
|
45
|
+
if (rigidBody.sleeping) {
|
|
46
|
+
if (force.x || force.y || impulse.x || impulse.y) {
|
|
47
|
+
rigidBody.wakeUp();
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (rigidBody.gravityScale) {
|
|
54
|
+
force.y += mass * this.gravity * rigidBody.gravityScale;
|
|
107
55
|
}
|
|
108
|
-
const { velocity, force, impulse } = this.actorVectors[actor.id];
|
|
109
|
-
force.add(this.getGravityForce(rigidBody));
|
|
110
56
|
if (force.x || force.y) {
|
|
111
|
-
force.multiplyNumber(deltaTimeInSeconds
|
|
57
|
+
force.multiplyNumber(deltaTimeInSeconds * inverseMass);
|
|
112
58
|
velocity.add(force);
|
|
113
59
|
}
|
|
114
60
|
if (impulse.x || impulse.y) {
|
|
115
|
-
impulse.multiplyNumber(
|
|
61
|
+
impulse.multiplyNumber(inverseMass);
|
|
116
62
|
velocity.add(impulse);
|
|
117
63
|
}
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
transform.world.position.y += velocity.y * deltaTimeInSeconds;
|
|
121
|
-
force.multiplyNumber(0);
|
|
122
|
-
impulse.multiplyNumber(0);
|
|
64
|
+
this.applyLinearDamping(rigidBody, deltaTimeInSeconds);
|
|
65
|
+
rigidBody.clearForces();
|
|
123
66
|
});
|
|
124
67
|
}
|
|
68
|
+
integratePositions(deltaTimeInSeconds) {
|
|
69
|
+
this.actorQuery.getActors().forEach((actor) => {
|
|
70
|
+
const rigidBody = actor.getComponent(RigidBody);
|
|
71
|
+
const transform = actor.getComponent(Transform);
|
|
72
|
+
if (rigidBody.disabled ||
|
|
73
|
+
rigidBody.type === 'static' ||
|
|
74
|
+
rigidBody.mass <= 0 ||
|
|
75
|
+
rigidBody.sleeping) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
transform.world.position.x +=
|
|
79
|
+
rigidBody.linearVelocity.x * deltaTimeInSeconds;
|
|
80
|
+
transform.world.position.y +=
|
|
81
|
+
rigidBody.linearVelocity.y * deltaTimeInSeconds;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
update(options) {
|
|
85
|
+
const deltaTimeInSeconds = options.deltaTime / 1000;
|
|
86
|
+
this.integrateVelocities(deltaTimeInSeconds);
|
|
87
|
+
this.integratePositions(deltaTimeInSeconds);
|
|
88
|
+
}
|
|
125
89
|
}
|
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
import type { SceneSystemOptions } from '../../../engine/system';
|
|
2
|
+
import type { Actor } from '../../../engine/actor';
|
|
3
|
+
import type { Vector2, Point } from '../../../engine/math-lib';
|
|
2
4
|
export interface PhysicsSystemOptions extends SceneSystemOptions {
|
|
3
5
|
gravity: number;
|
|
4
6
|
}
|
|
7
|
+
export interface CollisionLayer {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
export type CollisionMatrix = Record<string, Record<string, boolean>>;
|
|
12
|
+
export interface PhysicsSettings {
|
|
13
|
+
collisionLayers: CollisionLayer[];
|
|
14
|
+
collisionMatrix: CollisionMatrix;
|
|
15
|
+
}
|
|
16
|
+
export interface PhysicsQueryFilter {
|
|
17
|
+
layer?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RaycastParams extends PhysicsQueryFilter {
|
|
20
|
+
origin: Point;
|
|
21
|
+
direction: Vector2;
|
|
22
|
+
maxDistance: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RaycastHit {
|
|
25
|
+
actor: Actor;
|
|
26
|
+
point: Point;
|
|
27
|
+
normal: Vector2;
|
|
28
|
+
distance: number;
|
|
29
|
+
}
|
|
30
|
+
export interface OverlapPointParams extends PhysicsQueryFilter {
|
|
31
|
+
point: Point;
|
|
32
|
+
}
|
|
33
|
+
export interface OverlapCircleParams extends PhysicsQueryFilter {
|
|
34
|
+
center: Point;
|
|
35
|
+
radius: number;
|
|
36
|
+
}
|
|
37
|
+
export interface OverlapBoxParams extends PhysicsQueryFilter {
|
|
38
|
+
center: Point;
|
|
39
|
+
size: Point;
|
|
40
|
+
rotation?: number;
|
|
41
|
+
}
|
|
@@ -108,8 +108,6 @@ export class ActorRenderTree {
|
|
|
108
108
|
container.addChild(view);
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
|
-
this.updateParent(container, actor);
|
|
112
|
-
this.updatePosition(container, actor);
|
|
113
111
|
return container;
|
|
114
112
|
}
|
|
115
113
|
delete(actor) {
|
|
@@ -178,6 +176,7 @@ export class ActorRenderTree {
|
|
|
178
176
|
renderLayer?.attach(view);
|
|
179
177
|
meta.sortingLayer = sortingLayer;
|
|
180
178
|
}
|
|
179
|
+
view.__dacha.isReady = true;
|
|
181
180
|
});
|
|
182
181
|
}
|
|
183
182
|
update() {
|
|
@@ -6,7 +6,7 @@ import type { FilterSystem } from '../filters';
|
|
|
6
6
|
import type { FilterEffectConfig } from '../filters/filter-effect';
|
|
7
7
|
import type { MaterialSystem } from '../material';
|
|
8
8
|
import type { ShaderConstructor } from '../material/shader';
|
|
9
|
-
interface
|
|
9
|
+
interface RendererAPIOptions {
|
|
10
10
|
application: Application;
|
|
11
11
|
worldContainer: Container;
|
|
12
12
|
getViewEntries: () => Set<ViewContainer> | undefined;
|
|
@@ -15,21 +15,21 @@ interface RendererServiceOptions {
|
|
|
15
15
|
materialSystem: MaterialSystem;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* API that provides rendering utilities and view management
|
|
19
19
|
*
|
|
20
20
|
* Offers methods for view intersection testing, bounds calculation, and
|
|
21
21
|
* direct access to the underlying PIXI.js application
|
|
22
22
|
*
|
|
23
23
|
* @category Systems
|
|
24
24
|
*/
|
|
25
|
-
export declare class
|
|
25
|
+
export declare class RendererAPI {
|
|
26
26
|
private application;
|
|
27
27
|
private worldContainer;
|
|
28
28
|
private getViewEntries;
|
|
29
29
|
private sortFn;
|
|
30
30
|
private filterSystem;
|
|
31
31
|
private materialSystem;
|
|
32
|
-
constructor({ application, worldContainer, getViewEntries, sortFn, filterSystem, materialSystem, }:
|
|
32
|
+
constructor({ application, worldContainer, getViewEntries, sortFn, filterSystem, materialSystem, }: RendererAPIOptions);
|
|
33
33
|
/**
|
|
34
34
|
* Returns the underlying PIXI.js application
|
|
35
35
|
*
|
|
@@ -61,9 +61,9 @@ export declare class RendererService {
|
|
|
61
61
|
* the bounds will be the smallest rectangle that contains all views
|
|
62
62
|
*
|
|
63
63
|
* @param actor - Actor to get the bounds of
|
|
64
|
-
* @returns Bounds of the actor
|
|
64
|
+
* @returns Bounds of the actor or null if the actor has no available views
|
|
65
65
|
*/
|
|
66
|
-
getBounds(actor: Actor): Bounds;
|
|
66
|
+
getBounds(actor: Actor): Bounds | null;
|
|
67
67
|
/**
|
|
68
68
|
* Adds a post-processing effect that applies to the entire scene.
|
|
69
69
|
* Effects are applied in the order they are added.
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { Transform } from '../../../components/transform';
|
|
2
1
|
import { VIEW_COMPONENTS } from '../consts';
|
|
3
|
-
import { convertBounds } from './utils';
|
|
2
|
+
import { convertBounds, getWorldPosition } from './utils';
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
4
|
+
* API that provides rendering utilities and view management
|
|
6
5
|
*
|
|
7
6
|
* Offers methods for view intersection testing, bounds calculation, and
|
|
8
7
|
* direct access to the underlying PIXI.js application
|
|
9
8
|
*
|
|
10
9
|
* @category Systems
|
|
11
10
|
*/
|
|
12
|
-
export class
|
|
11
|
+
export class RendererAPI {
|
|
13
12
|
application;
|
|
14
13
|
worldContainer;
|
|
15
14
|
getViewEntries;
|
|
@@ -43,6 +42,9 @@ export class RendererService {
|
|
|
43
42
|
const intersects = new Set();
|
|
44
43
|
const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
|
|
45
44
|
this.getViewEntries()?.forEach((entry) => {
|
|
45
|
+
if (!entry.__dacha.isReady) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
46
48
|
const { minX, minY, maxX, maxY } = convertBounds(entry, inverseMatrix);
|
|
47
49
|
if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
|
|
48
50
|
intersects.add(entry);
|
|
@@ -67,8 +69,12 @@ export class RendererService {
|
|
|
67
69
|
*/
|
|
68
70
|
intersectsWithRectangle(minX, minY, maxX, maxY) {
|
|
69
71
|
const actors = new Set();
|
|
72
|
+
const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
|
|
70
73
|
this.getViewEntries()?.forEach((entry) => {
|
|
71
|
-
|
|
74
|
+
if (!entry.__dacha.isReady) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const { x, y } = getWorldPosition(entry, inverseMatrix);
|
|
72
78
|
if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
|
|
73
79
|
actors.add(entry.__dacha.actor);
|
|
74
80
|
}
|
|
@@ -81,10 +87,9 @@ export class RendererService {
|
|
|
81
87
|
* the bounds will be the smallest rectangle that contains all views
|
|
82
88
|
*
|
|
83
89
|
* @param actor - Actor to get the bounds of
|
|
84
|
-
* @returns Bounds of the actor
|
|
90
|
+
* @returns Bounds of the actor or null if the actor has no available views
|
|
85
91
|
*/
|
|
86
92
|
getBounds(actor) {
|
|
87
|
-
const { world } = actor.getComponent(Transform);
|
|
88
93
|
let minX = Infinity;
|
|
89
94
|
let minY = Infinity;
|
|
90
95
|
let maxX = -Infinity;
|
|
@@ -92,7 +97,7 @@ export class RendererService {
|
|
|
92
97
|
const inverseMatrix = this.worldContainer.worldTransform.clone().invert();
|
|
93
98
|
VIEW_COMPONENTS.forEach((ViewComponent) => {
|
|
94
99
|
const viewComponent = actor.getComponent(ViewComponent);
|
|
95
|
-
if (!viewComponent?.renderData?.view) {
|
|
100
|
+
if (!viewComponent?.renderData?.view?.__dacha.isReady) {
|
|
96
101
|
return;
|
|
97
102
|
}
|
|
98
103
|
const bounds = convertBounds(viewComponent.renderData.view, inverseMatrix);
|
|
@@ -102,14 +107,7 @@ export class RendererService {
|
|
|
102
107
|
maxY = Math.max(maxY, bounds?.maxY);
|
|
103
108
|
});
|
|
104
109
|
if (minX === Infinity) {
|
|
105
|
-
return
|
|
106
|
-
minX: world.position.x,
|
|
107
|
-
minY: world.position.y,
|
|
108
|
-
maxX: world.position.x,
|
|
109
|
-
maxY: world.position.y,
|
|
110
|
-
width: 0,
|
|
111
|
-
height: 0,
|
|
112
|
-
};
|
|
110
|
+
return null;
|
|
113
111
|
}
|
|
114
112
|
return {
|
|
115
113
|
minX,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Container, Point, type Matrix } from 'pixi.js';
|
|
2
|
+
import { type Bounds } from '../types';
|
|
3
|
+
export declare const convertBounds: (container: Container, matrix: Matrix) => Bounds;
|
|
4
|
+
export declare const getWorldPosition: (container: Container, matrix: Matrix) => Point;
|
|
@@ -12,3 +12,8 @@ export const convertBounds = (container, matrix) => {
|
|
|
12
12
|
height: bottomRight.y - topLeft.y,
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
|
+
export const getWorldPosition = (container, matrix) => {
|
|
16
|
+
const worldPoint = new Point();
|
|
17
|
+
container.getGlobalPosition(worldPoint, true);
|
|
18
|
+
return matrix.apply(worldPoint);
|
|
19
|
+
};
|