@aura3d/physics 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/dist/CharacterController.d.ts +0 -135
- package/dist/CharacterController.d.ts.map +0 -1
- package/dist/CharacterController.js +0 -609
- package/dist/CharacterController.js.map +0 -1
- package/dist/ClothFixtures.d.ts +0 -87
- package/dist/ClothFixtures.d.ts.map +0 -1
- package/dist/ClothFixtures.js +0 -264
- package/dist/ClothFixtures.js.map +0 -1
- package/dist/Crowd.d.ts +0 -64
- package/dist/Crowd.d.ts.map +0 -1
- package/dist/Crowd.js +0 -209
- package/dist/Crowd.js.map +0 -1
- package/dist/FireSmokeFixtures.d.ts +0 -103
- package/dist/FireSmokeFixtures.d.ts.map +0 -1
- package/dist/FireSmokeFixtures.js +0 -271
- package/dist/FireSmokeFixtures.js.map +0 -1
- package/dist/FluidFixtures.d.ts +0 -75
- package/dist/FluidFixtures.d.ts.map +0 -1
- package/dist/FluidFixtures.js +0 -219
- package/dist/FluidFixtures.js.map +0 -1
- package/dist/FractureFixtures.d.ts +0 -68
- package/dist/FractureFixtures.d.ts.map +0 -1
- package/dist/FractureFixtures.js +0 -199
- package/dist/FractureFixtures.js.map +0 -1
- package/dist/NarrowPhase.d.ts +0 -11
- package/dist/NarrowPhase.d.ts.map +0 -1
- package/dist/NarrowPhase.js +0 -565
- package/dist/NarrowPhase.js.map +0 -1
- package/dist/Navigation.d.ts +0 -67
- package/dist/Navigation.d.ts.map +0 -1
- package/dist/Navigation.js +0 -261
- package/dist/Navigation.js.map +0 -1
- package/dist/PathFollowDriver.d.ts +0 -162
- package/dist/PathFollowDriver.d.ts.map +0 -1
- package/dist/PathFollowDriver.js +0 -163
- package/dist/PathFollowDriver.js.map +0 -1
- package/dist/PhysicsSandboxFixtures.d.ts +0 -53
- package/dist/PhysicsSandboxFixtures.d.ts.map +0 -1
- package/dist/PhysicsSandboxFixtures.js +0 -280
- package/dist/PhysicsSandboxFixtures.js.map +0 -1
- package/dist/PlatformerFixtures.d.ts +0 -70
- package/dist/PlatformerFixtures.d.ts.map +0 -1
- package/dist/PlatformerFixtures.js +0 -120
- package/dist/PlatformerFixtures.js.map +0 -1
- package/dist/RacingLineProfile.d.ts +0 -116
- package/dist/RacingLineProfile.d.ts.map +0 -1
- package/dist/RacingLineProfile.js +0 -181
- package/dist/RacingLineProfile.js.map +0 -1
- package/dist/SoftBodyFixtures.d.ts +0 -70
- package/dist/SoftBodyFixtures.d.ts.map +0 -1
- package/dist/SoftBodyFixtures.js +0 -272
- package/dist/SoftBodyFixtures.js.map +0 -1
- package/dist/Steering.d.ts +0 -161
- package/dist/Steering.d.ts.map +0 -1
- package/dist/Steering.js +0 -347
- package/dist/Steering.js.map +0 -1
- package/dist/VehicleDynamics.d.ts +0 -162
- package/dist/VehicleDynamics.d.ts.map +0 -1
- package/dist/VehicleDynamics.js +0 -363
- package/dist/VehicleDynamics.js.map +0 -1
- package/dist/VehicleMotion.d.ts +0 -125
- package/dist/VehicleMotion.d.ts.map +0 -1
- package/dist/VehicleMotion.js +0 -373
- package/dist/VehicleMotion.js.map +0 -1
- package/dist/solverless-entry.d.ts +0 -41
- package/dist/solverless-entry.d.ts.map +0 -1
- package/dist/solverless-entry.js +0 -40
- package/dist/solverless-entry.js.map +0 -1
- package/dist/world-entry.d.ts +0 -31
- package/dist/world-entry.d.ts.map +0 -1
- package/dist/world-entry.js +0 -30
- package/dist/world-entry.js.map +0 -1
package/dist/VehicleMotion.js
DELETED
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
import { samplePacejkaTireForces, tirePeakCorneringStiffness } from "./VehicleDynamics.js";
|
|
2
|
-
const DEFAULT_GRAVITY = 9.81;
|
|
3
|
-
/*
|
|
4
|
-
* Yaw velocity damping, in reciprocal seconds.
|
|
5
|
-
*
|
|
6
|
-
* Chosen to reproduce the previous behaviour's intent at its implicit 60 Hz timestep
|
|
7
|
-
* (0.985 per 1/60 s => -ln(0.985) * 60), now expressed so the decay is a property of
|
|
8
|
-
* elapsed simulated time rather than of call frequency.
|
|
9
|
-
*/
|
|
10
|
-
const YAW_DAMPING_RATE = -Math.log(0.985) * 60;
|
|
11
|
-
function clamp(value, min, max) {
|
|
12
|
-
return Math.min(max, Math.max(min, Number.isFinite(value) ? value : min));
|
|
13
|
-
}
|
|
14
|
-
function clamp01(value) {
|
|
15
|
-
return clamp(value, 0, 1);
|
|
16
|
-
}
|
|
17
|
-
function positive(value, fallback) {
|
|
18
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
19
|
-
}
|
|
20
|
-
export function createVehicleMotion(spec) {
|
|
21
|
-
const mass = positive(spec.mass, 1200);
|
|
22
|
-
const wheelbase = positive(spec.wheelbase, 2.5);
|
|
23
|
-
const frontWeightBias = clamp(spec.frontWeightBias ?? 0.52, 0.2, 0.8);
|
|
24
|
-
const centreOfMassHeight = positive(spec.centreOfMassHeight, 0.5);
|
|
25
|
-
const maxSteerAngle = positive(spec.maxSteerAngle, 0.55);
|
|
26
|
-
const driveForce = positive(spec.driveForce, mass * 5);
|
|
27
|
-
const brakeForce = positive(spec.brakeForce, mass * 9);
|
|
28
|
-
const tirePreset = spec.tirePreset ?? "sport";
|
|
29
|
-
const dragCoefficient = positive(spec.dragCoefficient, 0.42);
|
|
30
|
-
const rollingResistance = positive(spec.rollingResistance, 0.014);
|
|
31
|
-
// A uniform box of length `wheelbase` has I = m * L^2 / 12; cars run higher because
|
|
32
|
-
// mass sits away from the centre, so 1.8x is the usual lumped approximation.
|
|
33
|
-
const yawInertia = positive(spec.yawInertia, (mass * wheelbase * wheelbase) / 12 * 1.8);
|
|
34
|
-
const GRAVITY = positive(spec.gravity, DEFAULT_GRAVITY);
|
|
35
|
-
const resolved = {
|
|
36
|
-
mass, wheelbase, frontWeightBias, centreOfMassHeight, maxSteerAngle,
|
|
37
|
-
driveForce, brakeForce, tirePreset, dragCoefficient, rollingResistance, yawInertia,
|
|
38
|
-
gravity: GRAVITY
|
|
39
|
-
};
|
|
40
|
-
let current = { x: 0, z: 0, heading: 0, speed: 0, lateralSpeed: 0, yawRate: 0 };
|
|
41
|
-
let last = { ...current, frontSlipAngle: 0, rearSlipAngle: 0, slipRatio: 0, wheelspin: false, understeering: false, oversteering: false, frontLoad: 0, rearLoad: 0, lateralG: 0 };
|
|
42
|
-
const frontAxle = wheelbase * frontWeightBias;
|
|
43
|
-
const rearAxle = wheelbase * (1 - frontWeightBias);
|
|
44
|
-
/*
|
|
45
|
-
* Rated tyre load, derived from the car this integrator is actually simulating.
|
|
46
|
-
*
|
|
47
|
-
* `samplePacejkaTireForces` scales grip by `(normalForce / maxLoad) ^ loadSensitivity`,
|
|
48
|
-
* clamped to a 0.1 floor, and `maxLoad` defaults to 5000 N — a road car's tyre. Any vehicle
|
|
49
|
-
* lighter than that therefore ran permanently on the 0.1 floor, losing **ten times** its grip
|
|
50
|
-
* no matter what the caller asked for.
|
|
51
|
-
*
|
|
52
|
-
* That is a silent, mass-dependent defect: it never throws, and it only shows up as a car
|
|
53
|
-
* that will not turn. Measured on a unit-mass car, a full-lock corner produced 1.1 g where
|
|
54
|
-
* the same request should have given about 3.5 g, so a racing kit could not make its own
|
|
55
|
-
* circuit no matter how much grip it asked for.
|
|
56
|
-
*
|
|
57
|
-
* Rating the tyre against the car's own static axle load means the load factor sits near 1 at
|
|
58
|
-
* rest for *any* mass, and load transfer then moves it up and down as it should. A heavier car
|
|
59
|
-
* still needs proportionally more force, which is the physics; what it no longer does is fall
|
|
60
|
-
* off a cliff because the vehicle is not a 1200 kg saloon.
|
|
61
|
-
*/
|
|
62
|
-
const ratedTireLoad = Math.max(1, (mass * GRAVITY) / 2);
|
|
63
|
-
/*
|
|
64
|
-
* Previous substep's longitudinal acceleration, used to resolve the implicit
|
|
65
|
-
* load-transfer relationship above. Reset with the rest of the state.
|
|
66
|
-
*/
|
|
67
|
-
let lastForwardAccel = 0;
|
|
68
|
-
/*
|
|
69
|
-
* Substepping, because a tyre is a stiff spring and explicit Euler is only conditionally
|
|
70
|
-
* stable against one.
|
|
71
|
-
*
|
|
72
|
-
* A cornering tyre's lateral force responds steeply to slip angle. The stiffer that
|
|
73
|
-
* response and the lighter the car, the shorter the timestep the integrator needs before
|
|
74
|
-
* the yaw/slip feedback loop stops converging. At a 1/60 s frame this model demonstrably
|
|
75
|
-
* crossed that threshold: holding a constant steering input, yaw came out at **-4.279
|
|
76
|
-
* rad/s**, the opposite direction to the steer, while the same second of simulated time at
|
|
77
|
-
* dt/2 or finer converged to **+0.5 rad/s**. See `vehicle-timestep-convergence.test.ts`.
|
|
78
|
-
*
|
|
79
|
-
* That is the mechanism behind the yaw-rate chatter in the traces, and it is why the model
|
|
80
|
-
* previously needed a kinematic ceiling and a lateral decay factor to look plausible — both
|
|
81
|
-
* of which were suppressing a numerical artefact rather than modelling a car.
|
|
82
|
-
*
|
|
83
|
-
* The cap is chosen from the physics rather than picked: the lateral relaxation time is
|
|
84
|
-
* roughly `mass / (2 * corneringStiffness)`, and the yaw time constant scales with
|
|
85
|
-
* `sqrt(yawInertia / (stiffness * wheelbase^2))`. Taking a fraction of the smaller keeps
|
|
86
|
-
* the integration inside its stable region for any mass, wheelbase and tyre the caller
|
|
87
|
-
* configures, instead of assuming a 1200 kg saloon at 60 Hz.
|
|
88
|
-
*/
|
|
89
|
-
const peakLateralStiffness = tirePeakCorneringStiffness(tirePreset) * Math.max(1, mass * GRAVITY);
|
|
90
|
-
const lateralTimeConstant = mass / Math.max(1e-6, 2 * peakLateralStiffness);
|
|
91
|
-
const yawTimeConstant = Math.sqrt(yawInertia / Math.max(1e-6, peakLateralStiffness * wheelbase * wheelbase));
|
|
92
|
-
/*
|
|
93
|
-
* The factor on the smaller time constant is 1.0, measured rather than guessed. Sweeping it
|
|
94
|
-
* against the convergence suite, results are identical to four decimals from 0.25 up to 4.0;
|
|
95
|
-
* the first divergence appears at 8.0 (grip 8 yaw collapses 3.66 -> 1.11 rad/s) and grip 4
|
|
96
|
-
* follows at 16.0. Sitting at 1.0 keeps a 4-8x margin below the observed stability boundary.
|
|
97
|
-
*
|
|
98
|
-
* That margin is not free, and the cost is why the number matters: an over-conservative 0.25
|
|
99
|
-
* spent 252us per simulated frame on a single car, enough to blow a 16ms frame budget on its
|
|
100
|
-
* own and enough to time out the suite. At 1.0 the same frame costs 67us for identical output.
|
|
101
|
-
*/
|
|
102
|
-
const maxStableStep = clamp(Math.min(lateralTimeConstant, yawTimeConstant), 1e-4, 1 / 60);
|
|
103
|
-
function resolveSample(dt, input) {
|
|
104
|
-
const frame = clamp(dt, 1e-4, 0.1);
|
|
105
|
-
/*
|
|
106
|
-
* Grip raises the tyre's peak force, so it shortens the stable step too. A route asking
|
|
107
|
-
* for 4 g needs proportionally finer integration than one asking for 1 g.
|
|
108
|
-
*/
|
|
109
|
-
const gripDemand = Math.sqrt(clamp(input.grip ?? 1, 0.05, 8));
|
|
110
|
-
const substepCount = Math.max(1, Math.min(64, Math.ceil((frame / maxStableStep) * gripDemand)));
|
|
111
|
-
for (let index = 0; index < substepCount; index += 1) {
|
|
112
|
-
integrate(frame / substepCount, input);
|
|
113
|
-
}
|
|
114
|
-
return last;
|
|
115
|
-
}
|
|
116
|
-
function integrate(step, input) {
|
|
117
|
-
const throttle = clamp01(input.throttle ?? 0);
|
|
118
|
-
const brake = clamp01(input.brake ?? 0);
|
|
119
|
-
const steer = clamp(input.steer ?? 0, -1, 1) * maxSteerAngle;
|
|
120
|
-
/*
|
|
121
|
-
* Grip multiplier on the tyre's peak force.
|
|
122
|
-
*
|
|
123
|
-
* The upper bound is 8 rather than 1.5 because arcade racing routes legitimately declare a
|
|
124
|
-
* pace that a road tyre cannot hold. Aura3D's own certified circuit is the worked example:
|
|
125
|
-
* its tightest corner needs 0.25 g at the certified speed, and the route then declares a
|
|
126
|
-
* 4x gameplay pace, which is 16x the lateral load — 4 g. Clamped at 1.5 the car understeers
|
|
127
|
-
* off the track at every corner no matter what the caller asks for, so the ceiling was
|
|
128
|
-
* silently deciding the game's handling.
|
|
129
|
-
*
|
|
130
|
-
* This scales the tyre's force, so slip angles, saturation, load transfer and the
|
|
131
|
-
* understeer/oversteer distinction all still emerge from the model. A high-grip tyre is
|
|
132
|
-
* still a tyre; the alternative is a kinematic point that turns wherever it is pointed,
|
|
133
|
-
* which is the defect this model exists to remove.
|
|
134
|
-
*/
|
|
135
|
-
const grip = clamp(input.grip ?? 1, 0.05, 8);
|
|
136
|
-
const handbrake = input.handbrake === true;
|
|
137
|
-
const speed = current.speed;
|
|
138
|
-
const lateral = current.lateralSpeed;
|
|
139
|
-
/*
|
|
140
|
-
* Longitudinal load transfer.
|
|
141
|
-
*
|
|
142
|
-
* Braking pitches load onto the front axle and off the rear, which is why a car
|
|
143
|
-
* loses rear grip under heavy braking and can spin. A kinematic model has no
|
|
144
|
-
* mechanism for this at all.
|
|
145
|
-
*/
|
|
146
|
-
/*
|
|
147
|
-
* Load transfer follows the acceleration the car is *actually* undergoing.
|
|
148
|
-
*
|
|
149
|
-
* This used throttle and brake demand: `(throttle * driveForce - brake * brakeForce) / mass`.
|
|
150
|
-
* That is not what pitches a car. A car at its top speed with the throttle pinned is not
|
|
151
|
-
* accelerating at all — drag and rolling resistance cancel the drive force — so it sits
|
|
152
|
-
* level, yet the demand-based formula claimed full-throttle weight transfer forever.
|
|
153
|
-
*
|
|
154
|
-
* The consequence was severe and permanent. On the test car, holding full throttle at
|
|
155
|
-
* terminal velocity reported a front axle load of **1.66 N against a rear load of 8.15 N**,
|
|
156
|
-
* a 17.7 m/s^2 transfer that no longer existed. With almost no vertical load the front
|
|
157
|
-
* tyre could not generate lateral force, so it ran at **0.62 rad (35 degrees) of slip** —
|
|
158
|
-
* far past the peak of the Magic Formula curve — and the car understeered straight on at
|
|
159
|
-
* any speed. That is the "car will not turn" symptom, and it got worse the faster you went,
|
|
160
|
-
* because faster meant more throttle held for longer.
|
|
161
|
-
*
|
|
162
|
-
* Longitudinal force depends on the traction limit, which depends on rear load, which
|
|
163
|
-
* depends on this transfer, so the relationship is implicit. Resolving it with the previous
|
|
164
|
-
* substep's measured acceleration is both stable and physically honest: real load transfer
|
|
165
|
-
* lags the tyre forces through the suspension anyway, and at substep resolution that lag is
|
|
166
|
-
* well under a millisecond.
|
|
167
|
-
*/
|
|
168
|
-
const transfer = (centreOfMassHeight / wheelbase) * mass * lastForwardAccel;
|
|
169
|
-
const staticFront = mass * GRAVITY * (1 - frontWeightBias);
|
|
170
|
-
const staticRear = mass * GRAVITY * frontWeightBias;
|
|
171
|
-
const frontLoad = Math.max(0, staticFront - transfer);
|
|
172
|
-
const rearLoad = Math.max(0, staticRear + transfer);
|
|
173
|
-
/*
|
|
174
|
-
* Slip angles: the difference between where a tyre points and where it travels.
|
|
175
|
-
*
|
|
176
|
-
* This is the heart of the model. A tyre generates lateral force in response to slip
|
|
177
|
-
* angle, and that force saturates. Understeer is the front pair saturating first.
|
|
178
|
-
*/
|
|
179
|
-
const forwardSpeed = Math.max(Math.abs(speed), 0.6) * Math.sign(speed || 1);
|
|
180
|
-
/*
|
|
181
|
-
* Lateral velocity *at each axle*, which is what sets that axle's slip angle. A yawing
|
|
182
|
-
* car sweeps its front axle one way and its rear the other, which is why the two axles
|
|
183
|
-
* slip differently and why understeer and oversteer are distinguishable at all.
|
|
184
|
-
*
|
|
185
|
-
* These are handed to the tyre model as velocities, not as angles. The model derives
|
|
186
|
-
* slip itself; passing it a precomputed slip angle in its `steeringAngle` parameter
|
|
187
|
-
* counted slip twice (proven in `vehicle-lateral-stability.test.ts`).
|
|
188
|
-
*/
|
|
189
|
-
const frontAxleLateral = lateral + current.yawRate * frontAxle;
|
|
190
|
-
const rearAxleLateral = lateral - current.yawRate * rearAxle;
|
|
191
|
-
// Drive slip: how much the driven wheels are over-spinning relative to the road.
|
|
192
|
-
const tractionLimit = rearLoad * grip * 1.1;
|
|
193
|
-
const requestedDrive = throttle * driveForce;
|
|
194
|
-
const wheelspin = requestedDrive > tractionLimit && Math.abs(speed) < 40;
|
|
195
|
-
const slipRatio = tractionLimit > 0 ? clamp((requestedDrive - tractionLimit) / tractionLimit, -1, 1) : 0;
|
|
196
|
-
const frontTire = samplePacejkaTireForces({
|
|
197
|
-
normalForce: Math.max(1, frontLoad),
|
|
198
|
-
maxLoad: ratedTireLoad,
|
|
199
|
-
longitudinalVelocity: Math.abs(forwardSpeed),
|
|
200
|
-
lateralVelocity: frontAxleLateral,
|
|
201
|
-
angularVelocity: Math.abs(forwardSpeed) / 0.32,
|
|
202
|
-
radius: 0.32,
|
|
203
|
-
// The steered roadwheel angle. Only the front axle is steered.
|
|
204
|
-
steeringAngle: steer * Math.sign(forwardSpeed),
|
|
205
|
-
lateral: tirePreset,
|
|
206
|
-
longitudinal: tirePreset
|
|
207
|
-
});
|
|
208
|
-
const rearTire = samplePacejkaTireForces({
|
|
209
|
-
normalForce: Math.max(1, rearLoad),
|
|
210
|
-
maxLoad: ratedTireLoad,
|
|
211
|
-
longitudinalVelocity: Math.abs(forwardSpeed),
|
|
212
|
-
lateralVelocity: rearAxleLateral,
|
|
213
|
-
angularVelocity: (Math.abs(forwardSpeed) / 0.32) * (1 + Math.abs(slipRatio)),
|
|
214
|
-
radius: 0.32,
|
|
215
|
-
steeringAngle: 0,
|
|
216
|
-
lateral: tirePreset,
|
|
217
|
-
longitudinal: tirePreset
|
|
218
|
-
});
|
|
219
|
-
const frontSlipAngle = frontTire.slipAngle;
|
|
220
|
-
const rearSlipAngle = rearTire.slipAngle;
|
|
221
|
-
// Handbrake destroys rear lateral grip, which is what makes a drift initiate.
|
|
222
|
-
const rearGripScale = handbrake ? 0.25 : 1;
|
|
223
|
-
/*
|
|
224
|
-
* A tyre resists its own slip. `samplePacejkaTireForces` reports force with the sign of
|
|
225
|
-
* the slip that produced it, so the force acting on the body is the negation. Adding it
|
|
226
|
-
* unnegated — which is what this integrator used to do — made the tyre drive the car
|
|
227
|
-
* deeper into its slide, and lateral velocity then grew without bound.
|
|
228
|
-
*/
|
|
229
|
-
const frontLateral = -frontTire.lateralForce * grip;
|
|
230
|
-
const rearLateral = -rearTire.lateralForce * grip * rearGripScale;
|
|
231
|
-
// Longitudinal: drive limited by traction, minus brake, drag and rolling resistance.
|
|
232
|
-
const drive = Math.min(requestedDrive, tractionLimit);
|
|
233
|
-
const braking = brake * brakeForce * Math.sign(speed || 1);
|
|
234
|
-
const drag = dragCoefficient * speed * Math.abs(speed);
|
|
235
|
-
const rolling = rollingResistance * mass * GRAVITY * Math.sign(speed || 0);
|
|
236
|
-
/*
|
|
237
|
-
* Braking, drag and rolling resistance are dissipative: they oppose motion, so they can
|
|
238
|
-
* remove the car's momentum but must never become a source of it. Integrating them
|
|
239
|
-
* unconditionally lets the resisting force overshoot through zero and accelerate the car
|
|
240
|
-
* backwards. Under full brake on flat ground the car did not settle: it oscillated between
|
|
241
|
-
* 0 and -0.15 m/s every other frame, creeping -0.26 m along x while visibly stopped. The
|
|
242
|
-
* pre-existing `never reverses the car under braking` test missed this because it sampled
|
|
243
|
-
* after an even number of frames, landing on the 0 half of the oscillation; the regression
|
|
244
|
-
* test `stays at rest under continuous braking instead of jittering backwards` asserts
|
|
245
|
-
* every frame and fails without this clamp.
|
|
246
|
-
*
|
|
247
|
-
* Clamping the resisting impulse to the momentum actually available this step fixes it at
|
|
248
|
-
* the source, for any resisting force and any timestep, rather than special-casing brake.
|
|
249
|
-
* `drive` is excluded because engine force is a genuine source and may legitimately pull
|
|
250
|
-
* the car through zero into reverse.
|
|
251
|
-
*/
|
|
252
|
-
const resisting = braking + drag + rolling;
|
|
253
|
-
const maxResisting = Math.abs(speed) * mass / step;
|
|
254
|
-
const clampedResisting = Math.sign(resisting) * Math.min(Math.abs(resisting), maxResisting + Math.abs(drive));
|
|
255
|
-
const forwardAccel = (drive - clampedResisting) / mass;
|
|
256
|
-
lastForwardAccel = forwardAccel;
|
|
257
|
-
// Lateral acceleration includes the centripetal term from yaw.
|
|
258
|
-
const lateralAccel = (frontLateral + rearLateral) / mass - current.yawRate * speed;
|
|
259
|
-
const yawMoment = frontLateral * frontAxle - rearLateral * rearAxle;
|
|
260
|
-
const yawAccel = yawMoment / yawInertia;
|
|
261
|
-
let nextSpeed = speed + forwardAccel * step;
|
|
262
|
-
/*
|
|
263
|
-
* The resisting-impulse clamp above keeps dissipative forces from reversing the car, so the
|
|
264
|
-
* previous `Math.sign(nextSpeed) !== Math.sign(speed)` guard is gone: it silently skipped
|
|
265
|
-
* `speed === 0` (Math.sign(0) is 0, never unequal to itself under the old ordering) which is
|
|
266
|
-
* exactly the state the car settles into under braking, and it also clobbered legitimate
|
|
267
|
-
* throttle-into-reverse transitions.
|
|
268
|
-
*/
|
|
269
|
-
/*
|
|
270
|
-
* No artificial decay factor here. The previous 0.96-per-step bleed existed to hide the
|
|
271
|
-
* sign defect above: the tyre pushed the slide outward and a blanket multiplier dragged
|
|
272
|
-
* it back, and the two balanced at a permanent, physically meaningless sideways drift.
|
|
273
|
-
* With the tyre restoring correctly, lateral damping is the tyre's job.
|
|
274
|
-
*/
|
|
275
|
-
const nextLateral = lateral + lateralAccel * step;
|
|
276
|
-
/*
|
|
277
|
-
* Yaw is bounded by what the steered geometry can actually produce.
|
|
278
|
-
*
|
|
279
|
-
* `yawAccel` comes from the tyre moment, and with no ceiling it integrates without limit: a
|
|
280
|
-
* high-grip tyre generates a large moment, which produces more yaw, which increases slip angle,
|
|
281
|
-
* which generates more moment. Measured on a racing route asking for ~4 g of grip, the car reached
|
|
282
|
-
* **-55 rad/z of yaw at 24.5 g lateral** — spinning on the spot rather than cornering, which made
|
|
283
|
-
* the vehicle undrivable and looked like a wiring error in the consumer.
|
|
284
|
-
*
|
|
285
|
-
* The bicycle model gives the kinematic bound: a car travelling at `v` with roadwheel angle `delta`
|
|
286
|
-
* and wheelbase `L` turns at `v * tan(delta) / L`. Real cars exceed it slightly in a slide, so the
|
|
287
|
-
* cap allows 1.6x before clamping, which leaves oversteer expressible while keeping the result a
|
|
288
|
-
* cornering vehicle rather than a spinning point.
|
|
289
|
-
*
|
|
290
|
-
* This is a bound, not a substitute: yaw still *comes from* tyre forces, so understeer, oversteer
|
|
291
|
-
* and load transfer are unaffected below the limit.
|
|
292
|
-
*/
|
|
293
|
-
const kinematicYaw = Math.abs(nextSpeed) * Math.abs(Math.tan(steer)) / Math.max(1e-6, wheelbase);
|
|
294
|
-
const yawCeiling = Math.max(0.05, kinematicYaw * 1.6);
|
|
295
|
-
/*
|
|
296
|
-
* Yaw damping as a rate, not a per-call multiplier.
|
|
297
|
-
*
|
|
298
|
-
* This was `* 0.985` applied once per `step()`. A fixed per-call factor makes the
|
|
299
|
-
* physics depend on how often it is called: under substepping it compounds
|
|
300
|
-
* (0.985^64 = 0.38, so a frame would shed 62% of its yaw), and even without
|
|
301
|
-
* substepping a 30 fps client and a 120 fps client got different handling from
|
|
302
|
-
* identical input. Expressed as a time constant, the decay over a given span of
|
|
303
|
-
* simulated time is the same at any timestep.
|
|
304
|
-
*/
|
|
305
|
-
const unboundedYaw = (current.yawRate + yawAccel * step) * Math.exp(-YAW_DAMPING_RATE * step);
|
|
306
|
-
const nextYaw = clamp(unboundedYaw, -yawCeiling, yawCeiling);
|
|
307
|
-
const heading = current.heading + nextYaw * step;
|
|
308
|
-
const cos = Math.cos(heading);
|
|
309
|
-
const sin = Math.sin(heading);
|
|
310
|
-
current = {
|
|
311
|
-
x: current.x + (cos * nextSpeed - sin * nextLateral) * step,
|
|
312
|
-
z: current.z + (sin * nextSpeed + cos * nextLateral) * step,
|
|
313
|
-
heading,
|
|
314
|
-
speed: nextSpeed,
|
|
315
|
-
lateralSpeed: nextLateral,
|
|
316
|
-
yawRate: nextYaw
|
|
317
|
-
};
|
|
318
|
-
/*
|
|
319
|
-
* Understeer and oversteer, from the slip angles rather than asserted.
|
|
320
|
-
*
|
|
321
|
-
* Understeer is the front axle slipping more than the rear: the car goes wider than
|
|
322
|
-
* it is pointed. Oversteer is the reverse. Both are impossible to detect in a model
|
|
323
|
-
* where heading comes directly from steering input.
|
|
324
|
-
*/
|
|
325
|
-
const understeering = Math.abs(frontSlipAngle) > Math.abs(rearSlipAngle) + 0.02 && Math.abs(steer) > 0.02;
|
|
326
|
-
const oversteering = Math.abs(rearSlipAngle) > Math.abs(frontSlipAngle) + 0.02 && Math.abs(speed) > 1;
|
|
327
|
-
last = {
|
|
328
|
-
...current,
|
|
329
|
-
frontSlipAngle,
|
|
330
|
-
rearSlipAngle,
|
|
331
|
-
slipRatio,
|
|
332
|
-
wheelspin,
|
|
333
|
-
understeering,
|
|
334
|
-
oversteering,
|
|
335
|
-
frontLoad,
|
|
336
|
-
rearLoad,
|
|
337
|
-
/*
|
|
338
|
-
* Lateral g is the acceleration the car actually undergoes, which is the tyre
|
|
339
|
-
* force divided by mass.
|
|
340
|
-
*
|
|
341
|
-
* This previously reported `lateralAccel`, the rate of change of *body-frame
|
|
342
|
-
* lateral velocity*. Those differ by the centripetal term, and in a steady
|
|
343
|
-
* corner — exactly when a caller asks "how many g is it pulling?" — the
|
|
344
|
-
* body-frame derivative is approximately **zero** by definition, because the
|
|
345
|
-
* tyre force and the centripetal term are in balance. So a car holding a
|
|
346
|
-
* perfectly good 1 g corner reported 0.004 g, and any consumer using this to
|
|
347
|
-
* drive tyre squeal, camera shake or a grip readout saw nothing at the moment
|
|
348
|
-
* there was most to show.
|
|
349
|
-
*/
|
|
350
|
-
lateralG: Math.abs(frontLateral + rearLateral) / mass / GRAVITY
|
|
351
|
-
};
|
|
352
|
-
return last;
|
|
353
|
-
}
|
|
354
|
-
return {
|
|
355
|
-
kind: "aura-vehicle-motion",
|
|
356
|
-
spec: resolved,
|
|
357
|
-
step: resolveSample,
|
|
358
|
-
state: () => ({ ...last, ...current }),
|
|
359
|
-
reset: (state = {}) => {
|
|
360
|
-
current = {
|
|
361
|
-
x: state.x ?? 0,
|
|
362
|
-
z: state.z ?? 0,
|
|
363
|
-
heading: state.heading ?? 0,
|
|
364
|
-
speed: state.speed ?? 0,
|
|
365
|
-
lateralSpeed: state.lateralSpeed ?? 0,
|
|
366
|
-
yawRate: state.yawRate ?? 0
|
|
367
|
-
};
|
|
368
|
-
last = { ...current, frontSlipAngle: 0, rearSlipAngle: 0, slipRatio: 0, wheelspin: false, understeering: false, oversteering: false, frontLoad: 0, rearLoad: 0, lateralG: 0 };
|
|
369
|
-
return last;
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
//# sourceMappingURL=VehicleMotion.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"VehicleMotion.js","sourceRoot":"","sources":["../../../../packages/physics/src/VehicleMotion.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WS-2.2 — the parts of `@aura3d/physics` that do NOT reach the rigid-body solver.
|
|
3
|
-
*
|
|
4
|
-
* ## Why this exists
|
|
5
|
-
*
|
|
6
|
-
* `createAuraApp` needs a handful of physics values at module scope: `Shape` to translate a declared
|
|
7
|
-
* collider, `PhysicsStepper` to drive a fixed timestep, `ScenePhysicsBridge` to push transforms, and
|
|
8
|
-
* `PhysicsDebugDraw` to draw colliders. Every one of those files is **cannon-free** — they import
|
|
9
|
-
* `PhysicsWorld` as a *type* only.
|
|
10
|
-
*
|
|
11
|
-
* But they were reached through `@aura3d/physics`, whose barrel is a chain of `export *`, and one of
|
|
12
|
-
* those re-exports is `PhysicsWorld` — which imports `cannon-es`. So a scene with **no bodies at all**
|
|
13
|
-
* downloaded the whole solver. Measured on scenario 1 (one cube, no physics): a **77,081-byte gzip
|
|
14
|
-
* chunk** on the critical path, of which `cannon-es` is 83,869 bytes raw.
|
|
15
|
-
*
|
|
16
|
-
* This is *not* the same defect as eager construction. `createAuraApp` already constructs its world
|
|
17
|
-
* lazily and carries a comment recording that eager construction cost 85 KB — that fix was correct and
|
|
18
|
-
* insufficient, because a lazy `new` still leaves a static `import`. A bundler keeps the module either
|
|
19
|
-
* way. Deferring the *import* is what actually removes the bytes.
|
|
20
|
-
*
|
|
21
|
-
* ## What is deliberately absent
|
|
22
|
-
*
|
|
23
|
-
* `PhysicsWorld`, `NarrowPhase`, `CharacterController`, `HitboxWorld`, `VehicleDynamics` and the
|
|
24
|
-
* fixture modules. Anything that simulates. `@aura3d/physics` still exports all of them, and
|
|
25
|
-
* `createAuraApp` loads the world through `await import("@aura3d/physics")` when a scene actually
|
|
26
|
-
* declares a body — so behaviour is unchanged and only the download moves.
|
|
27
|
-
*/
|
|
28
|
-
export { Shape } from "./Shape.js";
|
|
29
|
-
export type { BoxShape, Bounds, CapsuleShape, ConvexHullShape, HeightfieldShape, MeshShape, PhysicsShape, PlaneShape, SphereShape, Vec3 } from "./Shape.js";
|
|
30
|
-
export { EPSILON, vec3 } from "./Shape.js";
|
|
31
|
-
export { PhysicsStepper } from "./PhysicsStepper.js";
|
|
32
|
-
export type { PhysicsStepperResult } from "./PhysicsStepper.js";
|
|
33
|
-
export { ScenePhysicsBridge } from "./ScenePhysicsBridge.js";
|
|
34
|
-
export type { ScenePhysicsBinding, ScenePhysicsNode } from "./ScenePhysicsBridge.js";
|
|
35
|
-
export { PhysicsDebugDraw } from "./PhysicsDebugDraw.js";
|
|
36
|
-
export type { DebugLine } from "./PhysicsDebugDraw.js";
|
|
37
|
-
export { buildMeshBVH, raycastMesh, raycastMeshBruteForce } from "./MeshBVH.js";
|
|
38
|
-
export type { MeshBVH, MeshBVHBuildOptions, MeshRayHit, RaycastMeshOptions } from "./MeshBVH.js";
|
|
39
|
-
export { createMeshSurfaceQuery } from "./SurfaceQuery.js";
|
|
40
|
-
export type { MeshSurfaceQuery, MeshSurfaceQueryOptions, SurfaceSample } from "./SurfaceQuery.js";
|
|
41
|
-
//# sourceMappingURL=solverless-entry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"solverless-entry.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/solverless-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5J,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMvD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAChF,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/solverless-entry.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WS-2.2 — the parts of `@aura3d/physics` that do NOT reach the rigid-body solver.
|
|
3
|
-
*
|
|
4
|
-
* ## Why this exists
|
|
5
|
-
*
|
|
6
|
-
* `createAuraApp` needs a handful of physics values at module scope: `Shape` to translate a declared
|
|
7
|
-
* collider, `PhysicsStepper` to drive a fixed timestep, `ScenePhysicsBridge` to push transforms, and
|
|
8
|
-
* `PhysicsDebugDraw` to draw colliders. Every one of those files is **cannon-free** — they import
|
|
9
|
-
* `PhysicsWorld` as a *type* only.
|
|
10
|
-
*
|
|
11
|
-
* But they were reached through `@aura3d/physics`, whose barrel is a chain of `export *`, and one of
|
|
12
|
-
* those re-exports is `PhysicsWorld` — which imports `cannon-es`. So a scene with **no bodies at all**
|
|
13
|
-
* downloaded the whole solver. Measured on scenario 1 (one cube, no physics): a **77,081-byte gzip
|
|
14
|
-
* chunk** on the critical path, of which `cannon-es` is 83,869 bytes raw.
|
|
15
|
-
*
|
|
16
|
-
* This is *not* the same defect as eager construction. `createAuraApp` already constructs its world
|
|
17
|
-
* lazily and carries a comment recording that eager construction cost 85 KB — that fix was correct and
|
|
18
|
-
* insufficient, because a lazy `new` still leaves a static `import`. A bundler keeps the module either
|
|
19
|
-
* way. Deferring the *import* is what actually removes the bytes.
|
|
20
|
-
*
|
|
21
|
-
* ## What is deliberately absent
|
|
22
|
-
*
|
|
23
|
-
* `PhysicsWorld`, `NarrowPhase`, `CharacterController`, `HitboxWorld`, `VehicleDynamics` and the
|
|
24
|
-
* fixture modules. Anything that simulates. `@aura3d/physics` still exports all of them, and
|
|
25
|
-
* `createAuraApp` loads the world through `await import("@aura3d/physics")` when a scene actually
|
|
26
|
-
* declares a body — so behaviour is unchanged and only the download moves.
|
|
27
|
-
*/
|
|
28
|
-
export { Shape } from "./Shape.js";
|
|
29
|
-
export { EPSILON, vec3 } from "./Shape.js";
|
|
30
|
-
export { PhysicsStepper } from "./PhysicsStepper.js";
|
|
31
|
-
export { ScenePhysicsBridge } from "./ScenePhysicsBridge.js";
|
|
32
|
-
export { PhysicsDebugDraw } from "./PhysicsDebugDraw.js";
|
|
33
|
-
/*
|
|
34
|
-
* Mesh queries are geometry, not simulation. `MeshBVH` and `SurfaceQuery` import only `Shape`'s
|
|
35
|
-
* types, so grounding a vehicle or a character on a real mesh needs no solver — which is also WS-4.5's
|
|
36
|
-
* point about MeshBVH having responsibilities beyond physics contact.
|
|
37
|
-
*/
|
|
38
|
-
export { buildMeshBVH, raycastMesh, raycastMeshBruteForce } from "./MeshBVH.js";
|
|
39
|
-
export { createMeshSurfaceQuery } from "./SurfaceQuery.js";
|
|
40
|
-
//# sourceMappingURL=solverless-entry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"solverless-entry.js","sourceRoot":"","sources":["../../../../packages/physics/src/solverless-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/world-entry.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WS-2.2 — `PhysicsWorld` and the solver, as a narrow entry point.
|
|
3
|
-
*
|
|
4
|
-
* ## Why this exists rather than importing the barrel
|
|
5
|
-
*
|
|
6
|
-
* `app.physics` is documented and tested as being live **synchronously** for every app
|
|
7
|
-
* (`tests/unit/agent-api/lazy-physics-world.test.ts`), so `createAuraApp` must be able to construct a
|
|
8
|
-
* world without awaiting. That rules out loading the solver with `await import()` — R7 forbids breaking
|
|
9
|
-
* working semantics to chase a byte count, and an async-only `app.physics` would break every existing
|
|
10
|
-
* caller.
|
|
11
|
-
*
|
|
12
|
-
* So the solver is imported statically, but from **here** rather than from `@aura3d/physics`. The
|
|
13
|
-
* barrel is a chain of `export *` covering `HitboxWorld`, `CharacterController`, `KinematicBody`,
|
|
14
|
-
* `VehicleDynamics`, `NarrowPhase` and six fixture modules; importing it to get one class dragged all
|
|
15
|
-
* of them in. This entry exposes the solver and nothing else.
|
|
16
|
-
*
|
|
17
|
-
* Measured on scenario 1 (one cube, no bodies), the eager physics chunk:
|
|
18
|
-
*
|
|
19
|
-
* via the barrel 77,081 B gzip (cannon-es 83,869 raw + HitboxWorld 14,379 + KinematicBody
|
|
20
|
-
* 8,975 + CharacterController 8,531 + NarrowPhase 8,488 +
|
|
21
|
-
* VehicleDynamics 8,125 + PhysicsSandboxFixtures 7,687 + ...)
|
|
22
|
-
* via this entry the solver only
|
|
23
|
-
*
|
|
24
|
-
* `cannon-es` itself stays on the critical path, and that is the honest remaining cost of a synchronous
|
|
25
|
-
* `app.physics`. Removing it requires deciding whether the public contract may become async — which is
|
|
26
|
-
* a **P4** question, not a P2 one, and one the physics bake-off has to answer anyway because Rapier is
|
|
27
|
-
* WASM and therefore asynchronous by construction.
|
|
28
|
-
*/
|
|
29
|
-
export { PhysicsWorld } from "./PhysicsWorld.js";
|
|
30
|
-
export type { PhysicsBackend, PhysicsBackendPreference, PhysicsBackendSelection, PhysicsContinuousCollisionDescriptor, PhysicsContinuousCollisionSelection, PhysicsSnapshot, PhysicsStepStats, PhysicsWorldDescriptor } from "./PhysicsWorld.js";
|
|
31
|
-
//# sourceMappingURL=world-entry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"world-entry.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/world-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,oCAAoC,EACpC,mCAAmC,EACnC,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC"}
|
package/dist/world-entry.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WS-2.2 — `PhysicsWorld` and the solver, as a narrow entry point.
|
|
3
|
-
*
|
|
4
|
-
* ## Why this exists rather than importing the barrel
|
|
5
|
-
*
|
|
6
|
-
* `app.physics` is documented and tested as being live **synchronously** for every app
|
|
7
|
-
* (`tests/unit/agent-api/lazy-physics-world.test.ts`), so `createAuraApp` must be able to construct a
|
|
8
|
-
* world without awaiting. That rules out loading the solver with `await import()` — R7 forbids breaking
|
|
9
|
-
* working semantics to chase a byte count, and an async-only `app.physics` would break every existing
|
|
10
|
-
* caller.
|
|
11
|
-
*
|
|
12
|
-
* So the solver is imported statically, but from **here** rather than from `@aura3d/physics`. The
|
|
13
|
-
* barrel is a chain of `export *` covering `HitboxWorld`, `CharacterController`, `KinematicBody`,
|
|
14
|
-
* `VehicleDynamics`, `NarrowPhase` and six fixture modules; importing it to get one class dragged all
|
|
15
|
-
* of them in. This entry exposes the solver and nothing else.
|
|
16
|
-
*
|
|
17
|
-
* Measured on scenario 1 (one cube, no bodies), the eager physics chunk:
|
|
18
|
-
*
|
|
19
|
-
* via the barrel 77,081 B gzip (cannon-es 83,869 raw + HitboxWorld 14,379 + KinematicBody
|
|
20
|
-
* 8,975 + CharacterController 8,531 + NarrowPhase 8,488 +
|
|
21
|
-
* VehicleDynamics 8,125 + PhysicsSandboxFixtures 7,687 + ...)
|
|
22
|
-
* via this entry the solver only
|
|
23
|
-
*
|
|
24
|
-
* `cannon-es` itself stays on the critical path, and that is the honest remaining cost of a synchronous
|
|
25
|
-
* `app.physics`. Removing it requires deciding whether the public contract may become async — which is
|
|
26
|
-
* a **P4** question, not a P2 one, and one the physics bake-off has to answer anyway because Rapier is
|
|
27
|
-
* WASM and therefore asynchronous by construction.
|
|
28
|
-
*/
|
|
29
|
-
export { PhysicsWorld } from "./PhysicsWorld.js";
|
|
30
|
-
//# sourceMappingURL=world-entry.js.map
|
package/dist/world-entry.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"world-entry.js","sourceRoot":"","sources":["../../../../packages/physics/src/world-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|