@gg-web-engine/core 0.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.
Files changed (181) hide show
  1. package/.prettierrc +8 -0
  2. package/README.md +8 -0
  3. package/blender_exporter/build_blender_scene.py +180 -0
  4. package/blender_exporter/spherical_to_cube_texture.py +116 -0
  5. package/dist/2d/entities/gg-2d-entity.d.ts +20 -0
  6. package/dist/2d/entities/gg-2d-entity.js +84 -0
  7. package/dist/2d/entities/gg-2d-trigger.entity.d.ts +10 -0
  8. package/dist/2d/entities/gg-2d-trigger.entity.js +17 -0
  9. package/dist/2d/entities/gg-positionable-2d-entity.d.ts +7 -0
  10. package/dist/2d/entities/gg-positionable-2d-entity.js +16 -0
  11. package/dist/2d/factories.d.ts +18 -0
  12. package/dist/2d/factories.js +13 -0
  13. package/dist/2d/gg-2d-world.d.ts +9 -0
  14. package/dist/2d/gg-2d-world.js +34 -0
  15. package/dist/2d/interfaces.d.ts +26 -0
  16. package/dist/2d/interfaces.js +7 -0
  17. package/dist/2d/models/body-options.d.ts +3 -0
  18. package/dist/2d/models/body-options.js +2 -0
  19. package/dist/2d/models/shapes.d.ts +13 -0
  20. package/dist/2d/models/shapes.js +2 -0
  21. package/dist/3d/controllers/car-keyboard.controller.d.ts +25 -0
  22. package/dist/3d/controllers/car-keyboard.controller.js +98 -0
  23. package/dist/3d/controllers/free-camera.controller.d.ts +23 -0
  24. package/dist/3d/controllers/free-camera.controller.js +79 -0
  25. package/dist/3d/entities/controllers/entity-motion.controller.d.ts +32 -0
  26. package/dist/3d/entities/controllers/entity-motion.controller.js +100 -0
  27. package/dist/3d/entities/gg-3d-camera.entity.d.ts +7 -0
  28. package/dist/3d/entities/gg-3d-camera.entity.js +12 -0
  29. package/dist/3d/entities/gg-3d-entity.d.ts +25 -0
  30. package/dist/3d/entities/gg-3d-entity.js +108 -0
  31. package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +51 -0
  32. package/dist/3d/entities/gg-3d-map-graph.entity.js +164 -0
  33. package/dist/3d/entities/gg-3d-raycast-vehicle.entity.d.ts +107 -0
  34. package/dist/3d/entities/gg-3d-raycast-vehicle.entity.js +372 -0
  35. package/dist/3d/entities/gg-3d-trigger.entity.d.ts +10 -0
  36. package/dist/3d/entities/gg-3d-trigger.entity.js +21 -0
  37. package/dist/3d/entities/gg-positionable-3d-entity.d.ts +11 -0
  38. package/dist/3d/entities/gg-positionable-3d-entity.js +27 -0
  39. package/dist/3d/factories.d.ts +21 -0
  40. package/dist/3d/factories.js +22 -0
  41. package/dist/3d/gg-3d-world.d.ts +11 -0
  42. package/dist/3d/gg-3d-world.js +36 -0
  43. package/dist/3d/interfaces.d.ts +65 -0
  44. package/dist/3d/interfaces.js +40 -0
  45. package/dist/3d/loader.d.ts +40 -0
  46. package/dist/3d/loader.js +129 -0
  47. package/dist/3d/models/body-options.d.ts +3 -0
  48. package/dist/3d/models/body-options.js +2 -0
  49. package/dist/3d/models/gg-meta.d.ts +22 -0
  50. package/dist/3d/models/gg-meta.js +2 -0
  51. package/dist/3d/models/shapes.d.ts +35 -0
  52. package/dist/3d/models/shapes.js +2 -0
  53. package/dist/base/clock.d.ts +26 -0
  54. package/dist/base/clock.js +82 -0
  55. package/dist/base/controllers/common.d.ts +8 -0
  56. package/dist/base/controllers/common.js +32 -0
  57. package/dist/base/controllers/i-controller.d.ts +4 -0
  58. package/dist/base/controllers/i-controller.js +2 -0
  59. package/dist/base/controllers/keyboard.controller.d.ts +16 -0
  60. package/dist/base/controllers/keyboard.controller.js +109 -0
  61. package/dist/base/controllers/mouse.controller.d.ts +24 -0
  62. package/dist/base/controllers/mouse.controller.js +68 -0
  63. package/dist/base/data-structures/graph.d.ts +20 -0
  64. package/dist/base/data-structures/graph.js +118 -0
  65. package/dist/base/entities/base-gg-renderer.d.ts +28 -0
  66. package/dist/base/entities/base-gg-renderer.js +49 -0
  67. package/dist/base/entities/gg-entity.d.ts +14 -0
  68. package/dist/base/entities/gg-entity.js +55 -0
  69. package/dist/base/entities/gg-positionable-entity.d.ts +23 -0
  70. package/dist/base/entities/gg-positionable-entity.js +47 -0
  71. package/dist/base/entities/inline-controller.d.ts +3 -0
  72. package/dist/base/entities/inline-controller.js +25 -0
  73. package/dist/base/entities/interfaces/i-tick-listener.d.ts +7 -0
  74. package/dist/base/entities/interfaces/i-tick-listener.js +6 -0
  75. package/dist/base/gg-static.d.ts +9 -0
  76. package/dist/base/gg-static.js +40 -0
  77. package/dist/base/gg-viewport-manager.d.ts +14 -0
  78. package/dist/base/gg-viewport-manager.js +125 -0
  79. package/dist/base/gg-viewport.d.ts +23 -0
  80. package/dist/base/gg-viewport.js +123 -0
  81. package/dist/base/gg-world.d.ts +32 -0
  82. package/dist/base/gg-world.js +172 -0
  83. package/dist/base/interfaces/gg-body.d.ts +15 -0
  84. package/dist/base/interfaces/gg-body.js +2 -0
  85. package/dist/base/interfaces/gg-debug-physics-drawer.d.ts +7 -0
  86. package/dist/base/interfaces/gg-debug-physics-drawer.js +2 -0
  87. package/dist/base/interfaces/gg-object.d.ts +16 -0
  88. package/dist/base/interfaces/gg-object.js +2 -0
  89. package/dist/base/interfaces/gg-physics-world.d.ts +18 -0
  90. package/dist/base/interfaces/gg-physics-world.js +2 -0
  91. package/dist/base/interfaces/gg-trigger.d.ts +8 -0
  92. package/dist/base/interfaces/gg-trigger.js +2 -0
  93. package/dist/base/interfaces/gg-visual-scene.d.ts +9 -0
  94. package/dist/base/interfaces/gg-visual-scene.js +2 -0
  95. package/dist/base/math/box.d.ts +5 -0
  96. package/dist/base/math/box.js +21 -0
  97. package/dist/base/math/matrix4.d.ts +5 -0
  98. package/dist/base/math/matrix4.js +33 -0
  99. package/dist/base/math/numbers.d.ts +2 -0
  100. package/dist/base/math/numbers.js +14 -0
  101. package/dist/base/math/point2.d.ts +15 -0
  102. package/dist/base/math/point2.js +40 -0
  103. package/dist/base/math/point3.d.ts +25 -0
  104. package/dist/base/math/point3.js +104 -0
  105. package/dist/base/math/quaternion.d.ts +28 -0
  106. package/dist/base/math/quaternion.js +145 -0
  107. package/dist/base/models/axis-directions.d.ts +3 -0
  108. package/dist/base/models/axis-directions.js +2 -0
  109. package/dist/base/models/body-options.d.ts +6 -0
  110. package/dist/base/models/body-options.js +2 -0
  111. package/dist/base/models/geometry-nodes.d.ts +7 -0
  112. package/dist/base/models/geometry-nodes.js +2 -0
  113. package/dist/base/models/points.d.ts +15 -0
  114. package/dist/base/models/points.js +2 -0
  115. package/dist/base/ui/gg-console.ui.d.ts +21 -0
  116. package/dist/base/ui/gg-console.ui.js +162 -0
  117. package/dist/base/ui/gg-debugger.ui.d.ts +10 -0
  118. package/dist/base/ui/gg-debugger.ui.js +68 -0
  119. package/dist/index.d.ts +51 -0
  120. package/dist/index.js +67 -0
  121. package/package.json +64 -0
  122. package/src/2d/entities/gg-2d-entity.ts +86 -0
  123. package/src/2d/entities/gg-2d-trigger.entity.ts +17 -0
  124. package/src/2d/entities/gg-positionable-2d-entity.ts +16 -0
  125. package/src/2d/factories.ts +20 -0
  126. package/src/2d/gg-2d-world.ts +32 -0
  127. package/src/2d/interfaces.ts +31 -0
  128. package/src/2d/models/body-options.ts +3 -0
  129. package/src/2d/models/shapes.ts +7 -0
  130. package/src/3d/controllers/car-keyboard.controller.ts +128 -0
  131. package/src/3d/controllers/free-camera.controller.ts +86 -0
  132. package/src/3d/entities/controllers/entity-motion.controller.ts +122 -0
  133. package/src/3d/entities/gg-3d-camera.entity.ts +8 -0
  134. package/src/3d/entities/gg-3d-entity.ts +116 -0
  135. package/src/3d/entities/gg-3d-map-graph.entity.ts +204 -0
  136. package/src/3d/entities/gg-3d-raycast-vehicle.entity.ts +468 -0
  137. package/src/3d/entities/gg-3d-trigger.entity.ts +22 -0
  138. package/src/3d/entities/gg-positionable-3d-entity.ts +31 -0
  139. package/src/3d/factories.ts +29 -0
  140. package/src/3d/gg-3d-world.ts +36 -0
  141. package/src/3d/interfaces.ts +96 -0
  142. package/src/3d/loader.ts +165 -0
  143. package/src/3d/models/body-options.ts +3 -0
  144. package/src/3d/models/gg-meta.ts +12 -0
  145. package/src/3d/models/shapes.ts +13 -0
  146. package/src/base/clock.ts +97 -0
  147. package/src/base/controllers/common.ts +37 -0
  148. package/src/base/controllers/i-controller.ts +5 -0
  149. package/src/base/controllers/keyboard.controller.ts +109 -0
  150. package/src/base/controllers/mouse.controller.ts +73 -0
  151. package/src/base/data-structures/graph.ts +125 -0
  152. package/src/base/entities/base-gg-renderer.ts +77 -0
  153. package/src/base/entities/gg-entity.ts +61 -0
  154. package/src/base/entities/gg-positionable-entity.ts +64 -0
  155. package/src/base/entities/inline-controller.ts +31 -0
  156. package/src/base/entities/interfaces/i-tick-listener.ts +15 -0
  157. package/src/base/gg-static.ts +30 -0
  158. package/src/base/gg-viewport-manager.ts +122 -0
  159. package/src/base/gg-viewport.ts +159 -0
  160. package/src/base/gg-world.ts +198 -0
  161. package/src/base/interfaces/gg-body.ts +23 -0
  162. package/src/base/interfaces/gg-debug-physics-drawer.ts +10 -0
  163. package/src/base/interfaces/gg-object.ts +26 -0
  164. package/src/base/interfaces/gg-physics-world.ts +24 -0
  165. package/src/base/interfaces/gg-trigger.ts +10 -0
  166. package/src/base/interfaces/gg-visual-scene.ts +11 -0
  167. package/src/base/math/box.ts +19 -0
  168. package/src/base/math/matrix4.ts +29 -0
  169. package/src/base/math/numbers.ts +10 -0
  170. package/src/base/math/point2.ts +43 -0
  171. package/src/base/math/point3.ts +119 -0
  172. package/src/base/math/quaternion.ts +172 -0
  173. package/src/base/models/axis-directions.ts +3 -0
  174. package/src/base/models/body-options.ts +6 -0
  175. package/src/base/models/geometry-nodes.ts +5 -0
  176. package/src/base/models/points.ts +3 -0
  177. package/src/base/ui/gg-console.ui.ts +165 -0
  178. package/src/base/ui/gg-debugger.ui.ts +69 -0
  179. package/src/index.ts +53 -0
  180. package/test/base/data-structures/graph.spec.ts +76 -0
  181. package/tsconfig.json +9 -0
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Gg3dMapGraphEntity = exports.MapGraph = void 0;
13
+ const rxjs_1 = require("rxjs");
14
+ const operators_1 = require("rxjs/operators");
15
+ const graph_1 = require("../../base/data-structures/graph");
16
+ const gg_entity_1 = require("../../base/entities/gg-entity");
17
+ class MapGraph extends graph_1.Graph {
18
+ static fromMapArray(array) {
19
+ const root = new MapGraph(array[0]);
20
+ let tail = root;
21
+ for (let i = 1; i < array.length; i++) {
22
+ const newTail = new MapGraph(array[i]);
23
+ tail.addAdjacent(newTail);
24
+ tail = newTail;
25
+ }
26
+ return root;
27
+ }
28
+ static fromMapSquareGrid(grid) {
29
+ const nodes = grid.map(sgrid => sgrid.map(item => new MapGraph(item)));
30
+ // bind them
31
+ for (let j = 0; j < nodes.length; j++) {
32
+ for (let i = 0; i < nodes.length; i++) {
33
+ if (i > 0) {
34
+ nodes[j][i].addAdjacent(nodes[j][i - 1]);
35
+ }
36
+ if (j > 0) {
37
+ nodes[j][i].addAdjacent(nodes[j - 1][i]);
38
+ }
39
+ }
40
+ }
41
+ return nodes[0][0];
42
+ }
43
+ getNearestDummy(thisNodes, cursor) {
44
+ let min = Infinity;
45
+ let node = this;
46
+ // TODO should be heavily optimized with kd-tree-javascript, but building spatial index takes too much time. Serialize to file?
47
+ thisNodes.forEach(n => {
48
+ let dist = Math.sqrt(Math.pow(cursor.x - n.data.position.x, 2) +
49
+ Math.pow(cursor.y - n.data.position.y, 2) +
50
+ Math.pow(cursor.z - n.data.position.z, 2));
51
+ if (dist < min) {
52
+ min = dist;
53
+ node = n;
54
+ }
55
+ });
56
+ return node;
57
+ }
58
+ // TODO return iterable?
59
+ nodes() {
60
+ return Array.from(this.walkRead(-1));
61
+ }
62
+ }
63
+ exports.MapGraph = MapGraph;
64
+ const defaultOptions = {
65
+ loadDepth: 5,
66
+ inertia: 0,
67
+ };
68
+ class Gg3dMapGraphEntity extends gg_entity_1.GgEntity {
69
+ constructor(mapGraph, options = {}) {
70
+ super();
71
+ this.mapGraph = mapGraph;
72
+ this.tick$ = new rxjs_1.Subject();
73
+ this.tickOrder = 1500;
74
+ this.loaderCursorEntity$ = new rxjs_1.BehaviorSubject(null);
75
+ this.loaded = new Map();
76
+ this._initialLoadComplete$ = new rxjs_1.BehaviorSubject(false);
77
+ this._nearestDummy$ = new rxjs_1.BehaviorSubject(null);
78
+ this._chunkLoaded$ = new rxjs_1.Subject();
79
+ this._world = null;
80
+ this.options = Object.assign(Object.assign({}, defaultOptions), options);
81
+ this.mapGraphNodes = mapGraph.nodes();
82
+ }
83
+ get initialLoadComplete$() {
84
+ return this._initialLoadComplete$.asObservable();
85
+ }
86
+ get nearestDummy() {
87
+ return this._nearestDummy$.getValue();
88
+ }
89
+ get chunkLoaded$() {
90
+ return this._chunkLoaded$.asObservable();
91
+ }
92
+ get world() {
93
+ return this._world;
94
+ }
95
+ onSpawned(world) {
96
+ super.onSpawned(world);
97
+ // TODO takeUntil removed from world?
98
+ this.loaderCursorEntity$
99
+ .pipe((0, rxjs_1.switchMap)(entity => entity
100
+ ? this.tick$.pipe((0, rxjs_1.startWith)(null), // map will perform initial loading even if world not started yet. Handy to preload map
101
+ (0, operators_1.throttleTime)(1000), (0, operators_1.map)(() => entity.position))
102
+ : rxjs_1.NEVER), (0, operators_1.map)(pos => this.mapGraph.getNearestDummy(this.mapGraphNodes, pos)), (0, operators_1.tap)(node => this._nearestDummy$.next(node)), (0, operators_1.distinctUntilChanged)())
103
+ .subscribe(currentChunk => {
104
+ let haveToBeLoaded = new Set();
105
+ let canBeLoaded;
106
+ if (this.options.inertia > 0) {
107
+ canBeLoaded = new Set();
108
+ const nodes = currentChunk.walkReadPreserveDepth(this.options.loadDepth + this.options.inertia);
109
+ for (let distance = 0; distance < nodes.length; distance++) {
110
+ nodes[distance].forEach(node => canBeLoaded.add(node.data));
111
+ if (distance <= this.options.loadDepth) {
112
+ nodes[distance].forEach(node => haveToBeLoaded.add(node.data));
113
+ }
114
+ }
115
+ }
116
+ else {
117
+ currentChunk.walkRead(this.options.loadDepth).forEach(node => haveToBeLoaded.add(node.data));
118
+ canBeLoaded = haveToBeLoaded;
119
+ }
120
+ for (const loadedNode of this.loaded.keys()) {
121
+ if (!canBeLoaded.has(loadedNode)) {
122
+ this.disposeChunk(loadedNode);
123
+ }
124
+ else {
125
+ haveToBeLoaded.delete(loadedNode);
126
+ }
127
+ }
128
+ Promise.all(Array.from(haveToBeLoaded.keys()).map(n => this.loadChunk(n))).then(() => this._initialLoadComplete$.next(true));
129
+ });
130
+ }
131
+ onRemoved() {
132
+ super.onRemoved();
133
+ this.loaderCursorEntity$.next(null);
134
+ }
135
+ loadChunk(node) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ const loaded = yield this.world.loader.loadGgGlb(node.path, Object.assign({ position: node.position, rotation: node.rotation || { x: 0, y: 0, z: 0, w: 1 } }, node.loadOptions));
138
+ const entities = [
139
+ ...loaded.entities,
140
+ ...(loaded.props || [])
141
+ .map(p => p.entities)
142
+ .reduce((p, c) => {
143
+ p.push(...c);
144
+ return p;
145
+ }, []),
146
+ ];
147
+ this.loaded.set(node, entities);
148
+ this.addChildren(...entities);
149
+ this._chunkLoaded$.next([
150
+ loaded,
151
+ { position: node.position, rotation: node.rotation || { x: 0, y: 0, z: 0, w: 1 } },
152
+ ]);
153
+ return entities;
154
+ });
155
+ }
156
+ disposeChunk(node) {
157
+ if (!this.loaded.has(node)) {
158
+ return;
159
+ }
160
+ this.removeChildren(this.loaded.get(node), true);
161
+ this.loaded.delete(node);
162
+ }
163
+ }
164
+ exports.Gg3dMapGraphEntity = Gg3dMapGraphEntity;
@@ -0,0 +1,107 @@
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, Observable } from 'rxjs';
5
+ import { Gg3dWorld } from '../gg-3d-world';
6
+ import { AxisDirection3 } from '../../base/models/axis-directions';
7
+ export declare type WheelOptions = {
8
+ tyre_width: number;
9
+ tyre_radius: number;
10
+ wheelObject?: IGg3dObject;
11
+ wheelObjectDirection?: AxisDirection3;
12
+ isLeft: boolean;
13
+ isFront: boolean;
14
+ position: Point3;
15
+ frictionSlip: number;
16
+ rollInfluence: number;
17
+ maxTravel: number;
18
+ };
19
+ export declare type SuspensionOptions = {
20
+ stiffness: number;
21
+ damping: number;
22
+ compression: number;
23
+ restLength: number;
24
+ };
25
+ export declare type CarProperties = {
26
+ typeOfDrive: 'RWD' | 'FWD' | '4WD';
27
+ wheelOptions: WheelOptions[];
28
+ mpsToRpmFactor?: number;
29
+ engine: {
30
+ minRpm: number;
31
+ maxRpm: number;
32
+ torques: {
33
+ rpm: number;
34
+ torque: number;
35
+ }[];
36
+ maxRpmIncreasePerSecond: number;
37
+ maxRpmDecreasePerSecond: number;
38
+ };
39
+ transmission: {
40
+ isAuto: boolean;
41
+ reverseGearRatio: number;
42
+ gearRatios: number[];
43
+ drivelineEfficiency: number;
44
+ finalDriveRatio: number;
45
+ upShifts: number[];
46
+ };
47
+ suspension: SuspensionOptions;
48
+ };
49
+ export declare class Gg3dRaycastVehicleEntity extends Gg3dEntity {
50
+ readonly carProperties: CarProperties;
51
+ readonly chassis3D: IGg3dObject | null;
52
+ readonly chassisBody: IGg3dRaycastVehicle;
53
+ readonly wheelObject: IGg3dObject | null;
54
+ readonly wheelObjectDirection: AxisDirection3;
55
+ private readonly wheels;
56
+ private readonly wheelLocalRotation;
57
+ private readonly wheelLocalTranslation;
58
+ protected readonly frontWheelsIndices: number[];
59
+ protected readonly tractionWheelIndices: number[];
60
+ readonly tractionWheelRadius: number;
61
+ protected get dynamicTractionWheelRadius(): number;
62
+ get engineTorque(): number;
63
+ get transmissionGearRatio(): number;
64
+ protected get mpsToRpm(): number;
65
+ getSpeed(): number;
66
+ calculateRpmFromCarSpeed(): number;
67
+ getDisplaySpeed(units?: 'ms' | 'kmh' | 'mph'): number;
68
+ protected readonly _rpm$: BehaviorSubject<number>;
69
+ get engineRpm$(): Observable<number>;
70
+ get engineRpm(): number;
71
+ protected get tractionForce(): number;
72
+ private readonly _maxSteerVal;
73
+ private readonly brakingForce;
74
+ get maxSteerVal(): number;
75
+ private getMaxStableSteerVal;
76
+ private _tailLightsOn;
77
+ get tailLightsOn(): boolean;
78
+ protected setTailLightsOn(value: boolean): void;
79
+ protected _acceleration$: BehaviorSubject<number>;
80
+ protected get acceleration(): number;
81
+ get acceleration$(): Observable<number>;
82
+ protected set acceleration(value: number);
83
+ protected brake$: BehaviorSubject<number>;
84
+ protected get brake(): number;
85
+ protected set brake(value: number);
86
+ private _gear;
87
+ private _gear$;
88
+ get gear(): number;
89
+ get gear$(): Observable<number>;
90
+ set gear(value: number);
91
+ set isHonking(value: boolean);
92
+ private _steeringValue;
93
+ get steeringValue(): number;
94
+ protected setSteeringValue(value: number): void;
95
+ /** car mesh and physics body direction has to be pointing: y front, z up*/
96
+ constructor(carProperties: CarProperties, chassis3D: IGg3dObject | null, chassisBody: IGg3dRaycastVehicle, wheelObject?: IGg3dObject | null, wheelObjectDirection?: AxisDirection3);
97
+ onSpawned(world: Gg3dWorld): void;
98
+ protected runTransformBinding(objectBody: IGg3dBody, object3D: IGg3dObject): void;
99
+ private get isTouchingGround();
100
+ private updateEngine;
101
+ resetTo(options?: {
102
+ position?: Point3;
103
+ rotation?: Point4;
104
+ }): void;
105
+ setXAxisControlValue(value: number): void;
106
+ setYAxisControlValue(value: number): void;
107
+ }
@@ -0,0 +1,372 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dRaycastVehicleEntity = void 0;
4
+ const gg_3d_entity_1 = require("./gg-3d-entity");
5
+ const rxjs_1 = require("rxjs");
6
+ const operators_1 = require("rxjs/operators");
7
+ const box_1 = require("../../base/math/box");
8
+ const quaternion_1 = require("../../base/math/quaternion");
9
+ const point3_1 = require("../../base/math/point3");
10
+ class Gg3dRaycastVehicleEntity extends gg_3d_entity_1.Gg3dEntity {
11
+ /** car mesh and physics body direction has to be pointing: y front, z up*/
12
+ constructor(carProperties, chassis3D, chassisBody, wheelObject = null, wheelObjectDirection = 'x') {
13
+ super(chassis3D, chassisBody);
14
+ this.carProperties = carProperties;
15
+ this.chassis3D = chassis3D;
16
+ this.chassisBody = chassisBody;
17
+ this.wheelObject = wheelObject;
18
+ this.wheelObjectDirection = wheelObjectDirection;
19
+ this.wheels = [];
20
+ this.wheelLocalRotation = [];
21
+ this.wheelLocalTranslation = [];
22
+ this.frontWheelsIndices = [];
23
+ this.tractionWheelIndices = [];
24
+ this._rpm$ = new rxjs_1.BehaviorSubject(this.carProperties.engine.minRpm);
25
+ // TODO should be parameters
26
+ this._maxSteerVal = 0.35;
27
+ this.brakingForce = 300;
28
+ this._tailLightsOn = false;
29
+ // 0..1
30
+ this._acceleration$ = new rxjs_1.BehaviorSubject(0);
31
+ // 0..1
32
+ this.brake$ = new rxjs_1.BehaviorSubject(0);
33
+ this._gear = 0;
34
+ this._gear$ = new rxjs_1.BehaviorSubject(0);
35
+ this._steeringValue = 0;
36
+ this.carProperties.wheelOptions.forEach((x, i) => {
37
+ if (x.isFront) {
38
+ this.frontWheelsIndices.push(i);
39
+ }
40
+ if (x.isFront && this.carProperties.typeOfDrive != 'RWD') {
41
+ this.tractionWheelIndices.push(i);
42
+ }
43
+ if (!x.isFront && this.carProperties.typeOfDrive != 'FWD') {
44
+ this.tractionWheelIndices.push(i);
45
+ }
46
+ });
47
+ this.tractionWheelRadius = this.carProperties.wheelOptions[this.tractionWheelIndices[0]].tyre_radius;
48
+ // TODO perform this in a parent application
49
+ // chassisBody.setDamping(0.02, 0.02); // TODO imitates air resistance. calculate from properties
50
+ this.carProperties.wheelOptions.forEach(wheelOpts => {
51
+ this.chassisBody.addWheel(wheelOpts, this.carProperties.suspension);
52
+ });
53
+ if (this.wheelObject) {
54
+ for (let i = 0; i < this.carProperties.wheelOptions.length; i++) {
55
+ const options = this.carProperties.wheelOptions[i];
56
+ if (!options.wheelObject && !this.wheelObject) {
57
+ this.wheels.push(null);
58
+ this.wheelLocalRotation.push(null);
59
+ continue;
60
+ }
61
+ const entity = options.wheelObject || this.wheelObject.clone();
62
+ const localTranslation = { x: options.tyre_width * (options.isLeft ? 1 : -1), y: 0, z: 0 };
63
+ const boundingBox = box_1.Box.expandByPoint(entity.getBoundings(), { x: 0, y: 0, z: 0 });
64
+ const scale = { x: 0, y: 0, z: 0 };
65
+ for (const dir of ['x', 'y', 'z']) {
66
+ const wheelObjectDirection = options.wheelObjectDirection || this.wheelObjectDirection;
67
+ const isNormal = wheelObjectDirection.includes(dir);
68
+ scale[dir] = isNormal
69
+ ? options.tyre_width / (boundingBox.max[dir] - boundingBox.min[dir])
70
+ : (options.tyre_radius * 2) / (boundingBox.max[dir] - boundingBox.min[dir]);
71
+ if (isNormal) {
72
+ localTranslation.x +=
73
+ (wheelObjectDirection.startsWith('-') ? boundingBox.max[dir] : boundingBox.min[dir]) *
74
+ scale[dir] *
75
+ (options.isLeft ? 1 : -1);
76
+ }
77
+ }
78
+ entity.scale = scale;
79
+ const direction = options.wheelObjectDirection || this.wheelObjectDirection;
80
+ const flip = direction.includes('-') ? !options.isLeft : options.isLeft;
81
+ let localRotation = null;
82
+ if (direction.includes('x')) {
83
+ // rotate PI around Z if opposite position (x is correct for right wheel, -x is correct for left wheel)
84
+ if (flip)
85
+ localRotation = { x: 0, y: 0, z: 1, w: 0 };
86
+ }
87
+ else if (direction.includes('y')) {
88
+ // rotate PI/2 around Z
89
+ localRotation = { x: 0, y: 0, z: 0.707107 * (flip ? 1 : -1), w: 0.707107 };
90
+ }
91
+ else if (direction.includes('z')) {
92
+ // rotate PI/2 around Y
93
+ localRotation = { x: 0, y: 0.707107 * (flip ? -1 : 1), z: 0, w: 0.707107 };
94
+ }
95
+ this.wheelLocalTranslation.push(localTranslation);
96
+ this.wheelLocalRotation.push(localRotation);
97
+ this.wheels.push(new gg_3d_entity_1.Gg3dEntity(entity));
98
+ }
99
+ }
100
+ this._children = [...this.wheels.filter(x => !!x)];
101
+ this.chassisBody.entity = this;
102
+ }
103
+ get dynamicTractionWheelRadius() {
104
+ // 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.
105
+ return 0.98 * this.tractionWheelRadius;
106
+ }
107
+ get engineTorque() {
108
+ const currentRPM = this.engineRpm;
109
+ const maxMapTorque = this.carProperties.engine.torques[this.carProperties.engine.torques.length - 1].rpm;
110
+ if (currentRPM >= maxMapTorque) {
111
+ return (Math.pow(Math.max(0, 1 - (currentRPM - maxMapTorque) / (this.carProperties.engine.maxRpm - maxMapTorque)), 2) *
112
+ this.carProperties.engine.torques[this.carProperties.engine.torques.length - 1].torque);
113
+ }
114
+ let index = 0;
115
+ let factor = 0;
116
+ for (let i = 0; i < this.carProperties.engine.torques.length; i++) {
117
+ if (this.carProperties.engine.torques[i].rpm < currentRPM) {
118
+ index = i;
119
+ continue;
120
+ }
121
+ factor = Math.max(0, (currentRPM - this.carProperties.engine.torques[index].rpm) /
122
+ (this.carProperties.engine.torques[index + 1].rpm - this.carProperties.engine.torques[index].rpm));
123
+ break;
124
+ }
125
+ if (factor === 0) {
126
+ return this.carProperties.engine.torques[index].torque;
127
+ }
128
+ else {
129
+ return (this.carProperties.engine.torques[index].torque +
130
+ factor * (this.carProperties.engine.torques[index + 1].torque - this.carProperties.engine.torques[index].torque));
131
+ }
132
+ }
133
+ get transmissionGearRatio() {
134
+ if (this._gear == -1) {
135
+ return this.carProperties.transmission.reverseGearRatio;
136
+ }
137
+ return this.carProperties.transmission.gearRatios[this._gear - 1] || 0;
138
+ }
139
+ get mpsToRpm() {
140
+ return (this.carProperties.mpsToRpmFactor ||
141
+ (30 * this.carProperties.transmission.finalDriveRatio) / (Math.PI * this.dynamicTractionWheelRadius));
142
+ }
143
+ // m/s
144
+ getSpeed() {
145
+ return this.chassisBody.wheelSpeed;
146
+ }
147
+ calculateRpmFromCarSpeed() {
148
+ return this.getSpeed() * this.mpsToRpm * this.transmissionGearRatio;
149
+ }
150
+ // TODO remove from here, end application should do this work
151
+ getDisplaySpeed(units = 'ms') {
152
+ if (units === 'ms') {
153
+ return this.getSpeed();
154
+ }
155
+ const kmh = this.getSpeed() * 3.6;
156
+ if (units === 'mph') {
157
+ return kmh * 0.621371192;
158
+ }
159
+ return kmh;
160
+ }
161
+ get engineRpm$() {
162
+ return this._rpm$.asObservable();
163
+ }
164
+ get engineRpm() {
165
+ return this._rpm$.getValue();
166
+ }
167
+ get tractionForce() {
168
+ return ((this.engineTorque *
169
+ this.transmissionGearRatio *
170
+ this.carProperties.transmission.finalDriveRatio *
171
+ this.carProperties.transmission.drivelineEfficiency) /
172
+ this.dynamicTractionWheelRadius);
173
+ }
174
+ get maxSteerVal() {
175
+ return this._maxSteerVal;
176
+ }
177
+ getMaxStableSteerVal() {
178
+ const speed = this.getSpeed() * 3.6;
179
+ if (speed < 40) {
180
+ return this.maxSteerVal;
181
+ }
182
+ const mult = Math.pow((340 - speed) / 300, 2);
183
+ return this.maxSteerVal * Math.max(mult, 0.06);
184
+ }
185
+ get tailLightsOn() {
186
+ return this._tailLightsOn;
187
+ }
188
+ setTailLightsOn(value) {
189
+ if (this._tailLightsOn != value) {
190
+ this._tailLightsOn = value;
191
+ }
192
+ }
193
+ get acceleration() {
194
+ return this._acceleration$.getValue();
195
+ }
196
+ get acceleration$() {
197
+ return this._acceleration$.asObservable();
198
+ }
199
+ set acceleration(value) {
200
+ this._acceleration$.next(value);
201
+ }
202
+ get brake() {
203
+ return this.brake$.getValue();
204
+ }
205
+ set brake(value) {
206
+ this.brake$.next(value);
207
+ }
208
+ get gear() {
209
+ return this._gear;
210
+ }
211
+ get gear$() {
212
+ return this._gear$.asObservable();
213
+ }
214
+ set gear(value) {
215
+ value = Math.max(-1, Math.min(this.carProperties.transmission.gearRatios.length, value));
216
+ if (value === this._gear) {
217
+ return;
218
+ }
219
+ this._gear = value;
220
+ this._gear$.next(value);
221
+ }
222
+ // TODO remove
223
+ set isHonking(value) { }
224
+ get steeringValue() {
225
+ return this._steeringValue;
226
+ }
227
+ setSteeringValue(value) {
228
+ if (this._steeringValue != value) {
229
+ this._steeringValue = value;
230
+ }
231
+ }
232
+ onSpawned(world) {
233
+ super.onSpawned(world);
234
+ this.tick$.subscribe(([_, delta]) => {
235
+ this.updateEngine(delta);
236
+ if (this.isTouchingGround) {
237
+ // TODO 1 - R (1000 rpm) quick switch with acceleration pedal should have the same speed as without acceleration pedal
238
+ let force;
239
+ let brakeForce = this.brake;
240
+ const calculatedRpm = this.calculateRpmFromCarSpeed();
241
+ if (this.gear !== 0 && calculatedRpm > this.carProperties.engine.maxRpm) {
242
+ // engine brake, this is related to clutch, better clutch condition - bigger force
243
+ force = this.gear > 0 ? -12000 : 12000;
244
+ }
245
+ else {
246
+ force =
247
+ this.acceleration > 0
248
+ ? this.tractionForce * this.acceleration // apply torque
249
+ : 0.5 * (this.carProperties.engine.minRpm - calculatedRpm) * (this.gear > 0 ? 1 : -1); // released, use engine brake
250
+ // this functionality makes car stay still (parking gear) when speed is low
251
+ const speedThreshold = 3;
252
+ if (Math.abs(this.getSpeed()) < speedThreshold && (this.gear == 0 || this.acceleration == 0)) {
253
+ brakeForce = Math.max(brakeForce, (0.3 * (speedThreshold - this.getSpeed()) * this.brakingForce) / speedThreshold);
254
+ force = 0;
255
+ }
256
+ }
257
+ const forcePerWheel = force / this.tractionWheelIndices.length;
258
+ this.tractionWheelIndices.forEach(index => this.chassisBody.applyEngineForce(index, forcePerWheel));
259
+ this.wheels.forEach((w, i) => this.chassisBody.applyBrake(i, brakeForce));
260
+ }
261
+ });
262
+ if (this.carProperties.transmission.isAuto) {
263
+ this.tick$
264
+ .pipe((0, operators_1.throttleTime)(50), (0, rxjs_1.filter)(() => this.isTouchingGround))
265
+ .subscribe(() => {
266
+ let gear = this.gear;
267
+ let upshifted = false;
268
+ if (gear > 0) {
269
+ let rpm = this.engineRpm;
270
+ while (rpm >= this.carProperties.transmission.upShifts[gear - 1]) {
271
+ rpm *=
272
+ this.carProperties.transmission.gearRatios[gear] / this.carProperties.transmission.gearRatios[gear - 1];
273
+ gear++;
274
+ upshifted = true;
275
+ }
276
+ if (!upshifted) {
277
+ while (gear > 1) {
278
+ rpm *=
279
+ this.carProperties.transmission.gearRatios[gear - 2] /
280
+ this.carProperties.transmission.gearRatios[gear - 1];
281
+ if (rpm > this.carProperties.transmission.upShifts[gear - 2]) {
282
+ break;
283
+ }
284
+ gear--;
285
+ }
286
+ }
287
+ this.gear = gear;
288
+ }
289
+ });
290
+ }
291
+ }
292
+ runTransformBinding(objectBody, object3D) {
293
+ super.runTransformBinding(objectBody, object3D);
294
+ const carRotation = this.rotation;
295
+ for (const [i, wheel] of (this.wheels || []).entries()) {
296
+ if (!wheel) {
297
+ continue;
298
+ }
299
+ let { position, rotation } = this.chassisBody.getWheelTransform(i);
300
+ if (this.wheelLocalRotation[i]) {
301
+ rotation = quaternion_1.Qtrn.combineRotations(rotation, this.wheelLocalRotation[i]);
302
+ }
303
+ position = point3_1.Pnt3.add(position, point3_1.Pnt3.rot(this.wheelLocalTranslation[i], carRotation));
304
+ wheel.position = position;
305
+ wheel.rotation = rotation;
306
+ }
307
+ }
308
+ get isTouchingGround() {
309
+ // is at least one traction wheel touches the ground
310
+ return this.tractionWheelIndices
311
+ .map(i => this.chassisBody.isWheelTouchesGround(i))
312
+ .reduce((prev, cur) => cur || prev, false);
313
+ }
314
+ updateEngine(delta) {
315
+ delta = delta / 1000; // ms -> s
316
+ const acceleration = this._acceleration$.getValue();
317
+ let rpm = this.engineRpm;
318
+ // TODO here I will take perioud between gears and drift into account someday :)
319
+ const gripKoeff = this.gear === 0 || !this.isTouchingGround ? 0 : 1;
320
+ if (gripKoeff == 0) {
321
+ rpm +=
322
+ (acceleration * 2 - 1) *
323
+ (acceleration > 0.5
324
+ ? this.carProperties.engine.maxRpmIncreasePerSecond
325
+ : this.carProperties.engine.maxRpmDecreasePerSecond) *
326
+ delta;
327
+ }
328
+ else {
329
+ const rpmFromSpeed = this.calculateRpmFromCarSpeed();
330
+ if (rpmFromSpeed > rpm) {
331
+ rpm = Math.min(rpmFromSpeed, rpm + this.carProperties.engine.maxRpmIncreasePerSecond * delta);
332
+ }
333
+ else {
334
+ rpm = Math.max(rpmFromSpeed, rpm - this.carProperties.engine.maxRpmDecreasePerSecond * delta);
335
+ }
336
+ }
337
+ this._rpm$.next(Math.max(this.carProperties.engine.minRpm, Math.min(this.carProperties.engine.maxRpm, rpm)));
338
+ }
339
+ // TODO delete and let game application do all the steps
340
+ resetTo(options = {}) {
341
+ this.chassisBody.resetMotion();
342
+ this.chassisBody.resetSuspension();
343
+ if (options.position) {
344
+ this.position = options.position;
345
+ }
346
+ if (options.rotation) {
347
+ this.rotation = options.rotation;
348
+ }
349
+ this._steeringValue = 0;
350
+ this.gear = 0;
351
+ this._rpm$.next(this.carProperties.engine.minRpm);
352
+ }
353
+ // TODO refactor: control has to be in control service, here we receive separately braking, acceleration, steering
354
+ setXAxisControlValue(value) {
355
+ const steering = this.getMaxStableSteerVal() * value;
356
+ this.frontWheelsIndices.forEach(index => this.chassisBody.setSteering(index, -steering));
357
+ this.setSteeringValue(-steering);
358
+ }
359
+ // TODO refactor: control has to be in control service, here we receive separately braking, acceleration, steering
360
+ setYAxisControlValue(value) {
361
+ if (value > 0) {
362
+ this.acceleration = value;
363
+ this.brake = 0;
364
+ }
365
+ else {
366
+ this.acceleration = 0;
367
+ this.brake = -this.brakingForce * value;
368
+ }
369
+ this.setTailLightsOn(value < 0);
370
+ }
371
+ }
372
+ exports.Gg3dRaycastVehicleEntity = Gg3dRaycastVehicleEntity;
@@ -0,0 +1,10 @@
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
+ export declare class Gg3dTriggerEntity extends Gg3dEntity {
6
+ readonly objectBody: IGg3dTrigger;
7
+ get onEntityEntered(): Observable<GgPositionable3dEntity>;
8
+ get onEntityLeft(): Observable<GgPositionable3dEntity | null>;
9
+ constructor(objectBody: IGg3dTrigger);
10
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dTriggerEntity = void 0;
4
+ const gg_3d_entity_1 = require("./gg-3d-entity");
5
+ class Gg3dTriggerEntity extends gg_3d_entity_1.Gg3dEntity {
6
+ constructor(objectBody) {
7
+ super(null, objectBody);
8
+ this.objectBody = objectBody;
9
+ this.tick$.subscribe(() => {
10
+ this.objectBody.checkOverlaps();
11
+ });
12
+ this.objectBody.entity = this;
13
+ }
14
+ get onEntityEntered() {
15
+ return this.objectBody.onEntityEntered;
16
+ }
17
+ get onEntityLeft() {
18
+ return this.objectBody.onEntityLeft;
19
+ }
20
+ }
21
+ exports.Gg3dTriggerEntity = Gg3dTriggerEntity;
@@ -0,0 +1,11 @@
1
+ import { Point3, Point4 } from '../../base/models/points';
2
+ import { Observable } from 'rxjs';
3
+ import { GgPositionableEntity } from '../../base/entities/gg-positionable-entity';
4
+ export declare abstract class GgPositionable3dEntity extends GgPositionableEntity<Point3, Point4> {
5
+ getDefaultPosition(): Point3;
6
+ getDefaultRotation(): Point4;
7
+ getDefaultScale(): Point3;
8
+ get euler$(): Observable<Point3>;
9
+ get euler(): Point3;
10
+ set euler(value: Point3);
11
+ }