@gg-web-engine/core 0.0.1 → 0.0.3

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 (103) hide show
  1. package/dist/2d/entities/controllers/entity-2d-positioning.animator.d.ts +16 -0
  2. package/dist/2d/entities/controllers/entity-2d-positioning.animator.js +26 -0
  3. package/dist/2d/entities/gg-2d-entity.d.ts +9 -1
  4. package/dist/2d/entities/gg-2d-entity.js +50 -17
  5. package/dist/2d/gg-2d-world.d.ts +3 -0
  6. package/dist/2d/gg-2d-world.js +11 -0
  7. package/dist/3d/controllers/car-keyboard.controller.d.ts +10 -10
  8. package/dist/3d/controllers/car-keyboard.controller.js +21 -20
  9. package/dist/3d/controllers/free-camera.controller.d.ts +8 -8
  10. package/dist/3d/entities/controllers/camera-3d.animator.d.ts +17 -0
  11. package/dist/3d/entities/controllers/camera-3d.animator.js +32 -0
  12. package/dist/3d/entities/controllers/entity-3d-positioning.animator.d.ts +16 -0
  13. package/dist/3d/entities/controllers/entity-3d-positioning.animator.js +26 -0
  14. package/dist/3d/entities/gg-3d-camera.entity.d.ts +2 -0
  15. package/dist/3d/entities/gg-3d-camera.entity.js +6 -0
  16. package/dist/3d/entities/gg-3d-entity.d.ts +4 -1
  17. package/dist/3d/entities/gg-3d-entity.js +19 -10
  18. package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +7 -5
  19. package/dist/3d/entities/gg-3d-map-graph.entity.js +1 -1
  20. package/dist/3d/entities/gg-3d-raycast-vehicle.entity.d.ts +6 -5
  21. package/dist/3d/gg-3d-world.d.ts +3 -0
  22. package/dist/3d/gg-3d-world.js +12 -0
  23. package/dist/base/clock/clock.d.ts +25 -0
  24. package/dist/base/clock/clock.js +79 -0
  25. package/dist/base/clock/global-clock.d.ts +15 -0
  26. package/dist/base/clock/global-clock.js +36 -0
  27. package/dist/base/entities/controllers/animation-mixer.d.ts +83 -0
  28. package/dist/base/entities/controllers/animation-mixer.js +152 -0
  29. package/dist/base/entities/gg-entity.d.ts +4 -1
  30. package/dist/base/entities/gg-entity.js +7 -0
  31. package/dist/base/entities/inline-controller.js +0 -1
  32. package/dist/base/gg-viewport-manager.d.ts +4 -0
  33. package/dist/base/gg-world.d.ts +3 -1
  34. package/dist/base/gg-world.js +6 -5
  35. package/dist/base/math/matrix4.js +3 -3
  36. package/dist/base/math/point2.js +1 -1
  37. package/dist/base/math/point3.js +1 -1
  38. package/dist/base/math/quaternion.d.ts +83 -9
  39. package/dist/base/math/quaternion.js +93 -10
  40. package/dist/base/models/points.d.ts +9 -9
  41. package/dist/index.d.ts +6 -2
  42. package/dist/index.js +6 -2
  43. package/package.json +1 -1
  44. package/.prettierrc +0 -8
  45. package/src/2d/entities/gg-2d-entity.ts +0 -86
  46. package/src/2d/entities/gg-2d-trigger.entity.ts +0 -17
  47. package/src/2d/entities/gg-positionable-2d-entity.ts +0 -16
  48. package/src/2d/factories.ts +0 -20
  49. package/src/2d/gg-2d-world.ts +0 -32
  50. package/src/2d/interfaces.ts +0 -31
  51. package/src/2d/models/body-options.ts +0 -3
  52. package/src/2d/models/shapes.ts +0 -7
  53. package/src/3d/controllers/car-keyboard.controller.ts +0 -128
  54. package/src/3d/controllers/free-camera.controller.ts +0 -86
  55. package/src/3d/entities/controllers/entity-motion.controller.ts +0 -122
  56. package/src/3d/entities/gg-3d-camera.entity.ts +0 -8
  57. package/src/3d/entities/gg-3d-entity.ts +0 -116
  58. package/src/3d/entities/gg-3d-map-graph.entity.ts +0 -204
  59. package/src/3d/entities/gg-3d-raycast-vehicle.entity.ts +0 -468
  60. package/src/3d/entities/gg-3d-trigger.entity.ts +0 -22
  61. package/src/3d/entities/gg-positionable-3d-entity.ts +0 -31
  62. package/src/3d/factories.ts +0 -29
  63. package/src/3d/gg-3d-world.ts +0 -36
  64. package/src/3d/interfaces.ts +0 -96
  65. package/src/3d/loader.ts +0 -165
  66. package/src/3d/models/body-options.ts +0 -3
  67. package/src/3d/models/gg-meta.ts +0 -12
  68. package/src/3d/models/shapes.ts +0 -13
  69. package/src/base/clock.ts +0 -97
  70. package/src/base/controllers/common.ts +0 -37
  71. package/src/base/controllers/i-controller.ts +0 -5
  72. package/src/base/controllers/keyboard.controller.ts +0 -109
  73. package/src/base/controllers/mouse.controller.ts +0 -73
  74. package/src/base/data-structures/graph.ts +0 -125
  75. package/src/base/entities/base-gg-renderer.ts +0 -77
  76. package/src/base/entities/gg-entity.ts +0 -61
  77. package/src/base/entities/gg-positionable-entity.ts +0 -64
  78. package/src/base/entities/inline-controller.ts +0 -31
  79. package/src/base/entities/interfaces/i-tick-listener.ts +0 -15
  80. package/src/base/gg-static.ts +0 -30
  81. package/src/base/gg-viewport-manager.ts +0 -122
  82. package/src/base/gg-viewport.ts +0 -159
  83. package/src/base/gg-world.ts +0 -198
  84. package/src/base/interfaces/gg-body.ts +0 -23
  85. package/src/base/interfaces/gg-debug-physics-drawer.ts +0 -10
  86. package/src/base/interfaces/gg-object.ts +0 -26
  87. package/src/base/interfaces/gg-physics-world.ts +0 -24
  88. package/src/base/interfaces/gg-trigger.ts +0 -10
  89. package/src/base/interfaces/gg-visual-scene.ts +0 -11
  90. package/src/base/math/box.ts +0 -19
  91. package/src/base/math/matrix4.ts +0 -29
  92. package/src/base/math/numbers.ts +0 -10
  93. package/src/base/math/point2.ts +0 -43
  94. package/src/base/math/point3.ts +0 -119
  95. package/src/base/math/quaternion.ts +0 -172
  96. package/src/base/models/axis-directions.ts +0 -3
  97. package/src/base/models/body-options.ts +0 -6
  98. package/src/base/models/geometry-nodes.ts +0 -5
  99. package/src/base/models/points.ts +0 -3
  100. package/src/base/ui/gg-console.ui.ts +0 -165
  101. package/src/base/ui/gg-debugger.ui.ts +0 -69
  102. package/src/index.ts +0 -53
  103. package/test/base/data-structures/graph.spec.ts +0 -76
@@ -1,468 +0,0 @@
1
- import { Point3, Point4 } from '../../base/models/points';
2
- import { Gg3dEntity } from './gg-3d-entity';
3
- import { IGg3dBody, IGg3dObject, IGg3dRaycastVehicle } from '../interfaces';
4
- import { BehaviorSubject, filter, Observable } from 'rxjs';
5
- import { throttleTime } from 'rxjs/operators';
6
- import { GgPositionable3dEntity } from './gg-positionable-3d-entity';
7
- import { Gg3dWorld } from '../gg-3d-world';
8
- import { Box } from '../../base/math/box';
9
- import { Qtrn } from '../../base/math/quaternion';
10
- import { Pnt3 } from '../../base/math/point3';
11
- import { AxisDirection3 } from '../../base/models/axis-directions';
12
-
13
- export type WheelOptions = {
14
- tyre_width: number;
15
- tyre_radius: number;
16
- wheelObject?: IGg3dObject;
17
- wheelObjectDirection?: AxisDirection3;
18
- isLeft: boolean;
19
- isFront: boolean;
20
- position: Point3;
21
- frictionSlip: number; // friction with road
22
- rollInfluence: number;
23
- maxTravel: number;
24
- };
25
-
26
- export type SuspensionOptions = {
27
- stiffness: number;
28
- damping: number;
29
- compression: number;
30
- restLength: number;
31
- };
32
-
33
- export type CarProperties = {
34
- typeOfDrive: 'RWD' | 'FWD' | '4WD'; // FIXME 4WD car won't brake
35
- wheelOptions: WheelOptions[];
36
- mpsToRpmFactor?: number;
37
- engine: {
38
- minRpm: number;
39
- maxRpm: number;
40
- torques: { rpm: number; torque: number }[];
41
- maxRpmIncreasePerSecond: number;
42
- maxRpmDecreasePerSecond: number;
43
- };
44
- transmission: {
45
- isAuto: boolean;
46
- reverseGearRatio: number;
47
- gearRatios: number[];
48
- drivelineEfficiency: number;
49
- finalDriveRatio: number; // differential
50
- upShifts: number[];
51
- };
52
- suspension: SuspensionOptions;
53
- };
54
-
55
- export class Gg3dRaycastVehicleEntity extends Gg3dEntity {
56
- private readonly wheels: (GgPositionable3dEntity | null)[] = [];
57
- private readonly wheelLocalRotation: (Point4 | null)[] = [];
58
- private readonly wheelLocalTranslation: Point3[] = [];
59
- protected readonly frontWheelsIndices: number[] = [];
60
- protected readonly tractionWheelIndices: number[] = [];
61
-
62
- // https://x-engineer.org/vehicle-acceleration-maximum-speed-modeling-simulation/
63
- public readonly tractionWheelRadius: number;
64
-
65
- protected get dynamicTractionWheelRadius(): number {
66
- // The dynamic wheel radius [m] is the radius of the wheel when the vehicle is in motion. It is smaller than the static wheel radius rws because the tire is slightly compressed during vehicle motion.
67
- return 0.98 * this.tractionWheelRadius;
68
- }
69
-
70
- public get engineTorque(): number {
71
- const currentRPM = this.engineRpm;
72
- const maxMapTorque = this.carProperties.engine.torques[this.carProperties.engine.torques.length - 1].rpm;
73
- if (currentRPM >= maxMapTorque) {
74
- return (
75
- Math.pow(Math.max(0, 1 - (currentRPM - maxMapTorque) / (this.carProperties.engine.maxRpm - maxMapTorque)), 2) *
76
- this.carProperties.engine.torques[this.carProperties.engine.torques.length - 1].torque
77
- );
78
- }
79
- let index = 0;
80
- let factor = 0;
81
- for (let i = 0; i < this.carProperties.engine.torques.length; i++) {
82
- if (this.carProperties.engine.torques[i].rpm < currentRPM) {
83
- index = i;
84
- continue;
85
- }
86
- factor = Math.max(
87
- 0,
88
- (currentRPM - this.carProperties.engine.torques[index].rpm) /
89
- (this.carProperties.engine.torques[index + 1].rpm - this.carProperties.engine.torques[index].rpm),
90
- );
91
- break;
92
- }
93
- if (factor === 0) {
94
- return this.carProperties.engine.torques[index].torque;
95
- } else {
96
- return (
97
- this.carProperties.engine.torques[index].torque +
98
- factor * (this.carProperties.engine.torques[index + 1].torque - this.carProperties.engine.torques[index].torque)
99
- );
100
- }
101
- }
102
-
103
- public get transmissionGearRatio(): number {
104
- if (this._gear == -1) {
105
- return this.carProperties.transmission.reverseGearRatio;
106
- }
107
- return this.carProperties.transmission.gearRatios[this._gear - 1] || 0;
108
- }
109
-
110
- protected get mpsToRpm(): number {
111
- return (
112
- this.carProperties.mpsToRpmFactor ||
113
- (30 * this.carProperties.transmission.finalDriveRatio) / (Math.PI * this.dynamicTractionWheelRadius)
114
- );
115
- }
116
-
117
- // m/s
118
- public getSpeed(): number {
119
- return this.chassisBody.wheelSpeed;
120
- }
121
-
122
- public calculateRpmFromCarSpeed(): number {
123
- return this.getSpeed() * this.mpsToRpm * this.transmissionGearRatio;
124
- }
125
-
126
- // TODO remove from here, end application should do this work
127
-
128
- public getDisplaySpeed(units: 'ms' | 'kmh' | 'mph' = 'ms'): number {
129
- if (units === 'ms') {
130
- return this.getSpeed();
131
- }
132
- const kmh = this.getSpeed() * 3.6;
133
- if (units === 'mph') {
134
- return kmh * 0.621371192;
135
- }
136
- return kmh;
137
- }
138
-
139
- protected readonly _rpm$: BehaviorSubject<number> = new BehaviorSubject<number>(this.carProperties.engine.minRpm);
140
-
141
- public get engineRpm$(): Observable<number> {
142
- return this._rpm$.asObservable();
143
- }
144
-
145
- public get engineRpm(): number {
146
- return this._rpm$.getValue();
147
- }
148
-
149
- protected get tractionForce(): number {
150
- return (
151
- (this.engineTorque *
152
- this.transmissionGearRatio *
153
- this.carProperties.transmission.finalDriveRatio *
154
- this.carProperties.transmission.drivelineEfficiency) /
155
- this.dynamicTractionWheelRadius
156
- );
157
- }
158
-
159
- // TODO should be parameters
160
- private readonly _maxSteerVal = 0.35;
161
- private readonly brakingForce = 300;
162
-
163
- public get maxSteerVal(): number {
164
- return this._maxSteerVal;
165
- }
166
-
167
- private getMaxStableSteerVal(): number {
168
- const speed = this.getSpeed() * 3.6;
169
- if (speed < 40) {
170
- return this.maxSteerVal;
171
- }
172
- const mult = Math.pow((340 - speed) / 300, 2);
173
- return this.maxSteerVal * Math.max(mult, 0.06);
174
- }
175
-
176
- private _tailLightsOn: boolean = false;
177
- public get tailLightsOn(): boolean {
178
- return this._tailLightsOn;
179
- }
180
-
181
- protected setTailLightsOn(value: boolean) {
182
- if (this._tailLightsOn != value) {
183
- this._tailLightsOn = value;
184
- }
185
- }
186
-
187
- // 0..1
188
- protected _acceleration$: BehaviorSubject<number> = new BehaviorSubject(0);
189
-
190
- protected get acceleration(): number {
191
- return this._acceleration$.getValue();
192
- }
193
-
194
- public get acceleration$(): Observable<number> {
195
- return this._acceleration$.asObservable();
196
- }
197
-
198
- protected set acceleration(value: number) {
199
- this._acceleration$.next(value);
200
- }
201
-
202
- // 0..1
203
- protected brake$: BehaviorSubject<number> = new BehaviorSubject(0);
204
-
205
- protected get brake(): number {
206
- return this.brake$.getValue();
207
- }
208
-
209
- protected set brake(value: number) {
210
- this.brake$.next(value);
211
- }
212
-
213
- private _gear = 0;
214
- private _gear$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
215
-
216
- get gear(): number {
217
- return this._gear;
218
- }
219
-
220
- get gear$(): Observable<number> {
221
- return this._gear$.asObservable();
222
- }
223
-
224
- set gear(value: number) {
225
- value = Math.max(-1, Math.min(this.carProperties.transmission.gearRatios.length, value));
226
- if (value === this._gear) {
227
- return;
228
- }
229
- this._gear = value;
230
- this._gear$.next(value);
231
- }
232
-
233
- // TODO remove
234
- set isHonking(value: boolean) {}
235
-
236
- private _steeringValue: number = 0;
237
- public get steeringValue(): number {
238
- return this._steeringValue;
239
- }
240
-
241
- protected setSteeringValue(value: number) {
242
- if (this._steeringValue != value) {
243
- this._steeringValue = value;
244
- }
245
- }
246
-
247
- /** car mesh and physics body direction has to be pointing: y front, z up*/
248
- constructor(
249
- public readonly carProperties: CarProperties,
250
- public readonly chassis3D: IGg3dObject | null,
251
- public readonly chassisBody: IGg3dRaycastVehicle,
252
- public readonly wheelObject: IGg3dObject | null = null,
253
- public readonly wheelObjectDirection: AxisDirection3 = 'x',
254
- ) {
255
- super(chassis3D, chassisBody);
256
- this.carProperties.wheelOptions.forEach((x, i) => {
257
- if (x.isFront) {
258
- this.frontWheelsIndices.push(i);
259
- }
260
- if (x.isFront && this.carProperties.typeOfDrive != 'RWD') {
261
- this.tractionWheelIndices.push(i);
262
- }
263
- if (!x.isFront && this.carProperties.typeOfDrive != 'FWD') {
264
- this.tractionWheelIndices.push(i);
265
- }
266
- });
267
- this.tractionWheelRadius = this.carProperties.wheelOptions[this.tractionWheelIndices[0]].tyre_radius;
268
- // TODO perform this in a parent application
269
- // chassisBody.setDamping(0.02, 0.02); // TODO imitates air resistance. calculate from properties
270
- this.carProperties.wheelOptions.forEach(wheelOpts => {
271
- this.chassisBody.addWheel(wheelOpts, this.carProperties.suspension);
272
- });
273
- if (this.wheelObject) {
274
- for (let i = 0; i < this.carProperties.wheelOptions.length; i++) {
275
- const options = this.carProperties.wheelOptions[i];
276
- if (!options.wheelObject && !this.wheelObject) {
277
- this.wheels.push(null);
278
- this.wheelLocalRotation.push(null);
279
- continue;
280
- }
281
- const entity = options.wheelObject || this.wheelObject.clone();
282
- const localTranslation = { x: options.tyre_width * (options.isLeft ? 1 : -1), y: 0, z: 0 };
283
- const boundingBox = Box.expandByPoint(entity.getBoundings(), { x: 0, y: 0, z: 0 });
284
- const scale: Point3 = { x: 0, y: 0, z: 0 };
285
- for (const dir of ['x', 'y', 'z'] as (keyof Point3)[]) {
286
- const wheelObjectDirection = options.wheelObjectDirection || this.wheelObjectDirection;
287
- const isNormal = wheelObjectDirection.includes(dir);
288
- scale[dir] = isNormal
289
- ? options.tyre_width / (boundingBox.max[dir] - boundingBox.min[dir])
290
- : (options.tyre_radius * 2) / (boundingBox.max[dir] - boundingBox.min[dir]);
291
- if (isNormal) {
292
- localTranslation.x +=
293
- (wheelObjectDirection.startsWith('-') ? boundingBox.max[dir] : boundingBox.min[dir]) *
294
- scale[dir] *
295
- (options.isLeft ? 1 : -1);
296
- }
297
- }
298
- entity.scale = scale;
299
- const direction = options.wheelObjectDirection || this.wheelObjectDirection;
300
- const flip = direction.includes('-') ? !options.isLeft : options.isLeft;
301
- let localRotation: Point4 | null = null;
302
- if (direction.includes('x')) {
303
- // rotate PI around Z if opposite position (x is correct for right wheel, -x is correct for left wheel)
304
- if (flip) localRotation = { x: 0, y: 0, z: 1, w: 0 };
305
- } else if (direction.includes('y')) {
306
- // rotate PI/2 around Z
307
- localRotation = { x: 0, y: 0, z: 0.707107 * (flip ? 1 : -1), w: 0.707107 };
308
- } else if (direction.includes('z')) {
309
- // rotate PI/2 around Y
310
- localRotation = { x: 0, y: 0.707107 * (flip ? -1 : 1), z: 0, w: 0.707107 };
311
- }
312
- this.wheelLocalTranslation.push(localTranslation);
313
- this.wheelLocalRotation.push(localRotation);
314
- this.wheels.push(new Gg3dEntity(entity));
315
- }
316
- }
317
- this._children = [...(this.wheels.filter(x => !!x) as GgPositionable3dEntity[])];
318
- this.chassisBody.entity = this;
319
- }
320
-
321
- onSpawned(world: Gg3dWorld) {
322
- super.onSpawned(world);
323
- this.tick$.subscribe(([_, delta]) => {
324
- this.updateEngine(delta);
325
- if (this.isTouchingGround) {
326
- // TODO 1 - R (1000 rpm) quick switch with acceleration pedal should have the same speed as without acceleration pedal
327
- let force;
328
- let brakeForce = this.brake;
329
- const calculatedRpm = this.calculateRpmFromCarSpeed();
330
- if (this.gear !== 0 && calculatedRpm > this.carProperties.engine.maxRpm) {
331
- // engine brake, this is related to clutch, better clutch condition - bigger force
332
- force = this.gear > 0 ? -12000 : 12000;
333
- } else {
334
- force =
335
- this.acceleration > 0
336
- ? this.tractionForce * this.acceleration // apply torque
337
- : 0.5 * (this.carProperties.engine.minRpm - calculatedRpm) * (this.gear > 0 ? 1 : -1); // released, use engine brake
338
- // this functionality makes car stay still (parking gear) when speed is low
339
- const speedThreshold = 3;
340
- if (Math.abs(this.getSpeed()) < speedThreshold && (this.gear == 0 || this.acceleration == 0)) {
341
- brakeForce = Math.max(
342
- brakeForce,
343
- (0.3 * (speedThreshold - this.getSpeed()) * this.brakingForce) / speedThreshold,
344
- );
345
- force = 0;
346
- }
347
- }
348
- const forcePerWheel = force / this.tractionWheelIndices.length;
349
- this.tractionWheelIndices.forEach(index => this.chassisBody.applyEngineForce(index, forcePerWheel));
350
- this.wheels.forEach((w, i) => this.chassisBody.applyBrake(i, brakeForce));
351
- }
352
- });
353
- if (this.carProperties.transmission.isAuto) {
354
- this.tick$
355
- .pipe(
356
- throttleTime(50),
357
- filter(() => this.isTouchingGround),
358
- )
359
- .subscribe(() => {
360
- let gear = this.gear;
361
- let upshifted = false;
362
- if (gear > 0) {
363
- let rpm = this.engineRpm;
364
- while (rpm >= this.carProperties.transmission.upShifts[gear - 1]) {
365
- rpm *=
366
- this.carProperties.transmission.gearRatios[gear] / this.carProperties.transmission.gearRatios[gear - 1];
367
- gear++;
368
- upshifted = true;
369
- }
370
- if (!upshifted) {
371
- while (gear > 1) {
372
- rpm *=
373
- this.carProperties.transmission.gearRatios[gear - 2] /
374
- this.carProperties.transmission.gearRatios[gear - 1];
375
- if (rpm > this.carProperties.transmission.upShifts[gear - 2]) {
376
- break;
377
- }
378
- gear--;
379
- }
380
- }
381
- this.gear = gear;
382
- }
383
- });
384
- }
385
- }
386
-
387
- protected runTransformBinding(objectBody: IGg3dBody, object3D: IGg3dObject): void {
388
- super.runTransformBinding(objectBody, object3D);
389
- const carRotation = this.rotation;
390
- for (const [i, wheel] of (this.wheels || []).entries()) {
391
- if (!wheel) {
392
- continue;
393
- }
394
- let { position, rotation } = this.chassisBody.getWheelTransform(i);
395
- if (this.wheelLocalRotation[i]) {
396
- rotation = Qtrn.combineRotations(rotation, this.wheelLocalRotation[i]!);
397
- }
398
- position = Pnt3.add(position, Pnt3.rot(this.wheelLocalTranslation[i], carRotation));
399
- wheel.position = position;
400
- wheel.rotation = rotation;
401
- }
402
- }
403
-
404
- private get isTouchingGround(): boolean {
405
- // is at least one traction wheel touches the ground
406
- return this.tractionWheelIndices
407
- .map(i => this.chassisBody.isWheelTouchesGround(i))
408
- .reduce((prev, cur) => cur || prev, false);
409
- }
410
-
411
- private updateEngine(delta: number) {
412
- delta = delta / 1000; // ms -> s
413
- const acceleration = this._acceleration$.getValue();
414
- let rpm = this.engineRpm;
415
- // TODO here I will take perioud between gears and drift into account someday :)
416
- const gripKoeff = this.gear === 0 || !this.isTouchingGround ? 0 : 1;
417
- if (gripKoeff == 0) {
418
- rpm +=
419
- (acceleration * 2 - 1) *
420
- (acceleration > 0.5
421
- ? this.carProperties.engine.maxRpmIncreasePerSecond
422
- : this.carProperties.engine.maxRpmDecreasePerSecond) *
423
- delta;
424
- } else {
425
- const rpmFromSpeed = this.calculateRpmFromCarSpeed();
426
- if (rpmFromSpeed > rpm) {
427
- rpm = Math.min(rpmFromSpeed, rpm + this.carProperties.engine.maxRpmIncreasePerSecond * delta);
428
- } else {
429
- rpm = Math.max(rpmFromSpeed, rpm - this.carProperties.engine.maxRpmDecreasePerSecond * delta);
430
- }
431
- }
432
- this._rpm$.next(Math.max(this.carProperties.engine.minRpm, Math.min(this.carProperties.engine.maxRpm, rpm)));
433
- }
434
-
435
- // TODO delete and let game application do all the steps
436
- resetTo(options: { position?: Point3; rotation?: Point4 } = {}) {
437
- this.chassisBody.resetMotion();
438
- this.chassisBody.resetSuspension();
439
- if (options.position) {
440
- this.position = options.position;
441
- }
442
- if (options.rotation) {
443
- this.rotation = options.rotation;
444
- }
445
- this._steeringValue = 0;
446
- this.gear = 0;
447
- this._rpm$.next(this.carProperties.engine.minRpm);
448
- }
449
-
450
- // TODO refactor: control has to be in control service, here we receive separately braking, acceleration, steering
451
- public setXAxisControlValue(value: number) {
452
- const steering = this.getMaxStableSteerVal() * value;
453
- this.frontWheelsIndices.forEach(index => this.chassisBody.setSteering(index, -steering));
454
- this.setSteeringValue(-steering);
455
- }
456
-
457
- // TODO refactor: control has to be in control service, here we receive separately braking, acceleration, steering
458
- public setYAxisControlValue(value: number) {
459
- if (value > 0) {
460
- this.acceleration = value;
461
- this.brake = 0;
462
- } else {
463
- this.acceleration = 0;
464
- this.brake = -this.brakingForce * value;
465
- }
466
- this.setTailLightsOn(value < 0);
467
- }
468
- }
@@ -1,22 +0,0 @@
1
- import { IGg3dTrigger } from '../interfaces';
2
- import { Gg3dEntity } from './gg-3d-entity';
3
- import { Observable } from 'rxjs';
4
- import { GgPositionable3dEntity } from './gg-positionable-3d-entity';
5
-
6
- export class Gg3dTriggerEntity extends Gg3dEntity {
7
- get onEntityEntered(): Observable<GgPositionable3dEntity> {
8
- return this.objectBody.onEntityEntered;
9
- }
10
-
11
- get onEntityLeft(): Observable<GgPositionable3dEntity | null> {
12
- return this.objectBody.onEntityLeft;
13
- }
14
-
15
- constructor(public readonly objectBody: IGg3dTrigger) {
16
- super(null, objectBody);
17
- this.tick$.subscribe(() => {
18
- this.objectBody.checkOverlaps();
19
- });
20
- this.objectBody.entity = this;
21
- }
22
- }
@@ -1,31 +0,0 @@
1
- import { Point3, Point4 } from '../../base/models/points';
2
- import { Observable } from 'rxjs';
3
- import { GgPositionableEntity } from '../../base/entities/gg-positionable-entity';
4
- import { map } from 'rxjs/operators';
5
- import { Qtrn } from '../../base/math/quaternion';
6
-
7
- export abstract class GgPositionable3dEntity extends GgPositionableEntity<Point3, Point4> {
8
- getDefaultPosition(): Point3 {
9
- return { x: 0, y: 0, z: 0 };
10
- }
11
-
12
- getDefaultRotation(): Point4 {
13
- return { x: 0, y: 0, z: 0, w: 1 };
14
- }
15
-
16
- getDefaultScale(): Point3 {
17
- return { x: 1, y: 1, z: 1 };
18
- }
19
-
20
- public get euler$(): Observable<Point3> {
21
- return this._rotation$.pipe(map(q => Qtrn.toEuler(q)));
22
- }
23
-
24
- public get euler(): Point3 {
25
- return Qtrn.toEuler(this._rotation$.getValue());
26
- }
27
-
28
- public set euler(value: Point3) {
29
- this._rotation$.next(Qtrn.fromEuler(value));
30
- }
31
- }
@@ -1,29 +0,0 @@
1
- import { BodyShape3DDescriptor, Shape3DDescriptor } from './models/shapes';
2
- import { Point3, Point4 } from '../base/models/points';
3
- import { IGg3dBody, IGg3dObject, IGg3dTrigger } from './interfaces';
4
-
5
- export abstract class IGg3dObjectFactory<T extends IGg3dObject = IGg3dObject> {
6
- abstract createPrimitive(descriptor: Shape3DDescriptor, material?: any): T;
7
-
8
- // shortcuts
9
- createBox(dimensions: Point3, material?: any): T {
10
- return this.createPrimitive({ shape: 'BOX', dimensions }, material);
11
- }
12
- createCapsule(radius: number, centersDistance: number, material?: any): T {
13
- return this.createPrimitive({ shape: 'CAPSULE', radius, centersDistance }, material);
14
- }
15
- createCylinder(radius: number, height: number, material?: any): T {
16
- return this.createPrimitive({ shape: 'CYLINDER', radius, height }, material);
17
- }
18
- createCone(radius: number, height: number, material?: any): T {
19
- return this.createPrimitive({ shape: 'CONE', radius, height }, material);
20
- }
21
- createSphere(radius: number): T {
22
- return this.createPrimitive({ shape: 'SPHERE', radius });
23
- }
24
- }
25
-
26
- export interface IGg3dBodyFactory<T extends IGg3dBody = IGg3dBody, K extends IGg3dTrigger = IGg3dTrigger> {
27
- createRigidBody(descriptor: BodyShape3DDescriptor, transform?: { position?: Point3; rotation?: Point4 }): T;
28
- createTrigger(descriptor: Shape3DDescriptor, transform?: { position?: Point3; rotation?: Point4 }): K;
29
- }
@@ -1,36 +0,0 @@
1
- import { GgWorld } from '../base/gg-world';
2
- import { Point3, Point4 } from '../base/models/points';
3
- import { IGg3dPhysicsWorld, IGg3dVisualScene } from './interfaces';
4
- import { Gg3dLoader } from './loader';
5
-
6
- export class Gg3dWorld<
7
- V extends IGg3dVisualScene = IGg3dVisualScene,
8
- P extends IGg3dPhysicsWorld = IGg3dPhysicsWorld,
9
- > extends GgWorld<Point3, Point4, V, P> {
10
- public readonly loader: Gg3dLoader;
11
-
12
- constructor(
13
- public readonly visualScene: V,
14
- public readonly physicsWorld: P,
15
- protected readonly consoleEnabled: boolean = false,
16
- ) {
17
- super(visualScene, physicsWorld, consoleEnabled);
18
- this.loader = new Gg3dLoader(this);
19
- if (consoleEnabled) {
20
- this.registerConsoleCommand(
21
- 'ph_gravity',
22
- async (...args: string[]) => {
23
- if (args.length == 1) {
24
- args = ['0', '0', '' + -+args[0]]; // mean -Z axis
25
- }
26
- if (args.length > 0) {
27
- this.physicsWorld.gravity = { x: +args[0], y: +args[1], z: +args[2] };
28
- }
29
- return JSON.stringify(this.physicsWorld.gravity);
30
- },
31
- 'args: [float] or [float float float]; change 3D world gravity vector. 1 argument means ' +
32
- '{x: 0, y: 0, z: -value}, 3 arguments set the whole vector. Default value is "9.82" or "0 0 -9.82"',
33
- );
34
- }
35
- }
36
- }
@@ -1,96 +0,0 @@
1
- import { GgBody } from '../base/interfaces/gg-body';
2
- import { Point3, Point4 } from '../base/models/points';
3
- import { GgObject } from '../base/interfaces/gg-object';
4
- import { GgPhysicsWorld } from '../base/interfaces/gg-physics-world';
5
- import { GgVisualScene } from '../base/interfaces/gg-visual-scene';
6
- import { GgMeta } from './models/gg-meta';
7
- import { BaseGgRenderer } from '../base/entities/base-gg-renderer';
8
- import { Gg3dCameraEntity } from './entities/gg-3d-camera.entity';
9
- import { GgWorld } from '../base/gg-world';
10
- import { SuspensionOptions, WheelOptions } from './entities/gg-3d-raycast-vehicle.entity';
11
- import { GgTrigger } from '../base/interfaces/gg-trigger';
12
- import { Observable } from 'rxjs';
13
- import { GgPositionable3dEntity } from './entities/gg-positionable-3d-entity';
14
- import { IGg3dBodyFactory, IGg3dObjectFactory } from './factories';
15
-
16
- // These interfaces have to be implemented for a particular 3D physics engine
17
- export interface IGg3dPhysicsWorld extends GgPhysicsWorld<Point3, Point4> {
18
- readonly factory: IGg3dBodyFactory;
19
- readonly loader: IGg3dBodyLoader;
20
- }
21
-
22
- export abstract class Gg3dRenderer extends BaseGgRenderer {
23
- abstract readonly camera: Gg3dCameraEntity;
24
-
25
- public onSpawned(world: GgWorld<any, any>) {
26
- super.onSpawned(world);
27
- world.addEntity(this.camera);
28
- }
29
-
30
- onRemoved() {
31
- super.onRemoved();
32
- this.world?.removeEntity(this.camera);
33
- }
34
- }
35
-
36
- export interface IGg3dBody extends GgBody<Point3, Point4> {}
37
-
38
- export interface IGg3dTrigger extends GgTrigger<Point3, Point4> {
39
- get onEntityEntered(): Observable<GgPositionable3dEntity>;
40
- get onEntityLeft(): Observable<GgPositionable3dEntity | null>;
41
- }
42
-
43
- export interface IGg3dRaycastVehicle extends IGg3dBody {
44
- /** Return speed in m/s, calculated by car itself (which should be shown on the speedometer) */
45
- get wheelSpeed(): number;
46
-
47
- addWheel(options: WheelOptions, suspensionOptions: SuspensionOptions): void;
48
-
49
- /** Set steering value for wheel. The unit of steering is radian */
50
- setSteering(wheelIndex: number, steering: number): void;
51
-
52
- /** Apply force to wheel. Units? */
53
- applyEngineForce(wheelIndex: number, force: number): void;
54
-
55
- /** Apply brake force to wheel. Units? */
56
- applyBrake(wheelIndex: number, force: number): void;
57
-
58
- isWheelTouchesGround(wheelIndex: number): boolean;
59
-
60
- getWheelTransform(wheelIndex: number): { position: Point3; rotation: Point4 };
61
-
62
- resetSuspension(): void;
63
- }
64
-
65
- export abstract class IGg3dBodyLoader {
66
- protected constructor(protected readonly world: IGg3dPhysicsWorld) {}
67
-
68
- async loadFromGgGlb(glbFile: ArrayBuffer, meta: GgMeta): Promise<IGg3dBody[]> {
69
- return (meta?.rigidBodies || []).map(d => {
70
- const body = this.world.factory.createRigidBody(
71
- { shape: d.shape, body: d.body },
72
- { position: d.position, rotation: d.rotation },
73
- );
74
- body.name = d.name;
75
- return body;
76
- });
77
- }
78
- }
79
-
80
- // These interfaces have to be implemented for a particular 3D rendering engine
81
- export interface IGg3dVisualScene extends GgVisualScene<Point3, Point4> {
82
- readonly factory: IGg3dObjectFactory;
83
- readonly loader: IGg3dObjectLoader;
84
- }
85
-
86
- export interface IGg3dObject extends GgObject<Point3, Point4> {}
87
-
88
- export interface IGg3dCamera extends IGg3dObject {
89
- get supportsFov(): boolean;
90
- get fov(): number;
91
- set fov(f: number);
92
- }
93
-
94
- export interface IGg3dObjectLoader {
95
- loadFromGgGlb(glbFile: ArrayBuffer, meta: GgMeta): Promise<IGg3dObject | null>;
96
- }