@gg-web-engine/ammo 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.
package/README.md ADDED
@@ -0,0 +1,16 @@
1
+ <p align="center">
2
+ <img src="../../documentation/assets/logo.png" style="height: 400px; width:400px;" alt=''/>
3
+ </p>
4
+
5
+ ## [Ammo.js](https://github.com/kripken/ammo.js) integration for [gg-web-engine](https://github.com/AndyGura/gg-web-engine), providing 3D phycics simulation
6
+
7
+ ### Installation:
8
+ 1) make sure **@gg-web-engine/core** installed
9
+ 1) `npm install --save @gg-web-engine/ammo`
10
+ 1) Add to your `tsconfig.json` in the record `compilerOptions.paths`:
11
+ ```json lines
12
+ "mini-signals": ["./node_modules/@gg-web-engine/ammo/node_modules/mini-signals/index.js"],
13
+ "path": ["./node_modules/@gg-web-engine/ammo/node_modules/path-browserify"],
14
+ "fs": ["./node_modules/@gg-web-engine/ammo/node_modules/fs-web"],
15
+ "ammojs-typed": ["./node_modules/@gg-web-engine/ammo/node_modules/ammojs-typed"]
16
+ ```
@@ -0,0 +1,38 @@
1
+ import Ammo from 'ammojs-typed';
2
+ import { GgDebugPhysicsDrawer, Point3, Point4 } from '@gg-web-engine/core';
3
+ import { Gg3dPhysicsWorld } from './impl/gg-3d-physics-world';
4
+ export declare const DebugBufferSize: number;
5
+ export declare enum AmmoDebugMode {
6
+ NoDebug = 0,
7
+ DrawWireframe = 1,
8
+ DrawAabb = 2,
9
+ DrawFeaturesText = 4,
10
+ DrawContactPoints = 8,
11
+ NoDeactivation = 16,
12
+ NoHelpText = 32,
13
+ DrawText = 64,
14
+ ProfileTimings = 128,
15
+ EnableSatComparison = 256,
16
+ DisableBulletLCP = 512,
17
+ EnableCCD = 1024,
18
+ DrawConstraints = 2048,
19
+ DrawConstraintLimits = 4096,
20
+ FastWireframe = 8192,
21
+ DrawNormals = 16384,
22
+ MAX_DEBUG_DRAW_MODE = 4294967295
23
+ }
24
+ export declare class AmmoDebugger implements Ammo.btIDebugDraw {
25
+ private readonly world;
26
+ private readonly drawer;
27
+ private debugMode;
28
+ constructor(world: Gg3dPhysicsWorld, drawer: GgDebugPhysicsDrawer<Point3, Point4>);
29
+ readonly ammoInstance: Ammo.btIDebugDraw;
30
+ draw3dText(location: Ammo.btVector3, textString: string): void;
31
+ drawContactPoint(pointOnB: Ammo.btVector3, normalOnB: Ammo.btVector3, distance: number, lifeTime: number, color: Ammo.btVector3): void;
32
+ drawLine(from: Ammo.btVector3, to: Ammo.btVector3, color: Ammo.btVector3): void;
33
+ getDebugMode(): number;
34
+ update(): void;
35
+ setDebugFlags(flags: AmmoDebugMode[]): void;
36
+ setDebugMode(debugMode: number): void;
37
+ reportErrorWarning(warningString: string): void;
38
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AmmoDebugger = exports.AmmoDebugMode = exports.DebugBufferSize = void 0;
4
+ exports.DebugBufferSize = 3 * 1000000;
5
+ var AmmoDebugMode;
6
+ (function (AmmoDebugMode) {
7
+ AmmoDebugMode[AmmoDebugMode["NoDebug"] = 0] = "NoDebug";
8
+ AmmoDebugMode[AmmoDebugMode["DrawWireframe"] = 1] = "DrawWireframe";
9
+ AmmoDebugMode[AmmoDebugMode["DrawAabb"] = 2] = "DrawAabb";
10
+ AmmoDebugMode[AmmoDebugMode["DrawFeaturesText"] = 4] = "DrawFeaturesText";
11
+ AmmoDebugMode[AmmoDebugMode["DrawContactPoints"] = 8] = "DrawContactPoints";
12
+ AmmoDebugMode[AmmoDebugMode["NoDeactivation"] = 16] = "NoDeactivation";
13
+ AmmoDebugMode[AmmoDebugMode["NoHelpText"] = 32] = "NoHelpText";
14
+ AmmoDebugMode[AmmoDebugMode["DrawText"] = 64] = "DrawText";
15
+ AmmoDebugMode[AmmoDebugMode["ProfileTimings"] = 128] = "ProfileTimings";
16
+ AmmoDebugMode[AmmoDebugMode["EnableSatComparison"] = 256] = "EnableSatComparison";
17
+ AmmoDebugMode[AmmoDebugMode["DisableBulletLCP"] = 512] = "DisableBulletLCP";
18
+ AmmoDebugMode[AmmoDebugMode["EnableCCD"] = 1024] = "EnableCCD";
19
+ AmmoDebugMode[AmmoDebugMode["DrawConstraints"] = 2048] = "DrawConstraints";
20
+ AmmoDebugMode[AmmoDebugMode["DrawConstraintLimits"] = 4096] = "DrawConstraintLimits";
21
+ AmmoDebugMode[AmmoDebugMode["FastWireframe"] = 8192] = "FastWireframe";
22
+ AmmoDebugMode[AmmoDebugMode["DrawNormals"] = 16384] = "DrawNormals";
23
+ AmmoDebugMode[AmmoDebugMode["MAX_DEBUG_DRAW_MODE"] = 4294967295] = "MAX_DEBUG_DRAW_MODE";
24
+ })(AmmoDebugMode = exports.AmmoDebugMode || (exports.AmmoDebugMode = {}));
25
+ const deserializeVector = function (ammo, vec) {
26
+ if (!isNaN(+vec)) {
27
+ const heap = ammo.HEAPF32;
28
+ return {
29
+ x: heap[+vec / 4],
30
+ y: heap[(+vec + 4) / 4],
31
+ z: heap[(+vec + 8) / 4],
32
+ };
33
+ }
34
+ return { x: vec.x(), y: vec.y(), z: vec.z() };
35
+ };
36
+ class AmmoDebugger {
37
+ constructor(world, drawer) {
38
+ this.world = world;
39
+ this.drawer = drawer;
40
+ this.debugMode = AmmoDebugMode.DrawWireframe;
41
+ this.ammoInstance = new this.world.ammo.DebugDrawer();
42
+ this.ammoInstance.drawLine = this.drawLine.bind(this);
43
+ this.ammoInstance.drawContactPoint = this.drawContactPoint.bind(this);
44
+ this.ammoInstance.reportErrorWarning = this.reportErrorWarning.bind(this);
45
+ this.ammoInstance.draw3dText = this.draw3dText.bind(this);
46
+ this.ammoInstance.setDebugMode = this.setDebugMode.bind(this);
47
+ this.ammoInstance.getDebugMode = this.getDebugMode.bind(this);
48
+ }
49
+ draw3dText(location, textString) {
50
+ console.log('DRAWER DEBUG', 'draw3dtext');
51
+ }
52
+ drawContactPoint(pointOnB, normalOnB, distance, lifeTime, color) {
53
+ this.drawer.drawContactPoint(deserializeVector(this.world.ammo, pointOnB), deserializeVector(this.world.ammo, normalOnB), deserializeVector(this.world.ammo, color));
54
+ }
55
+ drawLine(from, to, color) {
56
+ this.drawer.drawLine(deserializeVector(this.world.ammo, from), deserializeVector(this.world.ammo, to), deserializeVector(this.world.ammo, color));
57
+ }
58
+ getDebugMode() {
59
+ return this.debugMode;
60
+ }
61
+ update() {
62
+ var _a;
63
+ (_a = this.world.dynamicAmmoWorld) === null || _a === void 0 ? void 0 : _a.debugDrawWorld();
64
+ this.drawer.update();
65
+ }
66
+ setDebugFlags(flags) {
67
+ let res = 0;
68
+ for (const flag of flags) {
69
+ res = res | flag;
70
+ }
71
+ this.setDebugMode(res);
72
+ }
73
+ setDebugMode(debugMode) {
74
+ this.debugMode = debugMode;
75
+ }
76
+ reportErrorWarning(warningString) {
77
+ console.log('DRAWER DEBUG', 'reportErrorWarning', warningString);
78
+ }
79
+ }
80
+ exports.AmmoDebugger = AmmoDebugger;
@@ -0,0 +1,2 @@
1
+ import Ammo from 'ammojs-typed';
2
+ export declare const ammoId: (body: Ammo.btCollisionObject) => number;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ammoId = void 0;
4
+ const ammoId = body => body.a;
5
+ exports.ammoId = ammoId;
@@ -0,0 +1,24 @@
1
+ import { IGg3dBody, Point3, Point4, Gg3dEntity } from '@gg-web-engine/core';
2
+ import { Gg3dPhysicsWorld } from '../gg-3d-physics-world';
3
+ import Ammo from 'ammojs-typed';
4
+ export declare abstract class BaseAmmoGGBody<T extends Ammo.btCollisionObject> implements IGg3dBody {
5
+ protected readonly world: Gg3dPhysicsWorld;
6
+ protected _nativeBody: T;
7
+ protected static nativeBodyReverseMap: Map<number, IGg3dBody>;
8
+ protected get ammo(): typeof Ammo;
9
+ get position(): Point3;
10
+ set position(value: Point3);
11
+ get rotation(): Point4;
12
+ set rotation(value: Point4);
13
+ get scale(): Point3;
14
+ get nativeBody(): T;
15
+ set nativeBody(value: T);
16
+ name: string;
17
+ abstract entity: Gg3dEntity | null;
18
+ protected constructor(world: Gg3dPhysicsWorld, _nativeBody: T);
19
+ abstract clone(): BaseAmmoGGBody<T>;
20
+ abstract addToWorld(world: Gg3dPhysicsWorld): void;
21
+ abstract removeFromWorld(world: Gg3dPhysicsWorld): void;
22
+ dispose(): void;
23
+ abstract resetMotion(): void;
24
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseAmmoGGBody = void 0;
4
+ const ammo_utils_1 = require("../../ammo-utils");
5
+ class BaseAmmoGGBody {
6
+ constructor(world, _nativeBody) {
7
+ this.world = world;
8
+ this._nativeBody = _nativeBody;
9
+ this.name = '';
10
+ BaseAmmoGGBody.nativeBodyReverseMap.set((0, ammo_utils_1.ammoId)(this.nativeBody), this);
11
+ }
12
+ get ammo() {
13
+ return this.world.ammo;
14
+ }
15
+ get position() {
16
+ const origin = this.nativeBody.getWorldTransform().getOrigin();
17
+ return { x: origin.x(), y: origin.y(), z: origin.z() };
18
+ }
19
+ set position(value) {
20
+ const transform = this.nativeBody.getWorldTransform();
21
+ transform.setOrigin(new this.ammo.btVector3(value.x, value.y, value.z));
22
+ this.nativeBody.setWorldTransform(transform);
23
+ }
24
+ get rotation() {
25
+ const quaternion = this.nativeBody.getWorldTransform().getRotation();
26
+ return { x: quaternion.x(), y: quaternion.y(), z: quaternion.z(), w: quaternion.w() };
27
+ }
28
+ set rotation(value) {
29
+ const transform = this.nativeBody.getWorldTransform();
30
+ transform.setRotation(new this.ammo.btQuaternion(value.x, value.y, value.z, value.w));
31
+ this.nativeBody.setWorldTransform(transform);
32
+ }
33
+ get scale() {
34
+ // hmm, is it even possible to be different?
35
+ return { x: 1, y: 1, z: 1 };
36
+ }
37
+ get nativeBody() {
38
+ return this._nativeBody;
39
+ }
40
+ set nativeBody(value) {
41
+ if (value == this._nativeBody) {
42
+ return;
43
+ }
44
+ BaseAmmoGGBody.nativeBodyReverseMap.delete((0, ammo_utils_1.ammoId)(this._nativeBody));
45
+ this._nativeBody = value;
46
+ BaseAmmoGGBody.nativeBodyReverseMap.set((0, ammo_utils_1.ammoId)(value), this);
47
+ }
48
+ dispose() {
49
+ try {
50
+ this.ammo.destroy(this.nativeBody);
51
+ }
52
+ catch (_a) {
53
+ // pass
54
+ }
55
+ BaseAmmoGGBody.nativeBodyReverseMap.delete((0, ammo_utils_1.ammoId)(this.nativeBody));
56
+ }
57
+ }
58
+ exports.BaseAmmoGGBody = BaseAmmoGGBody;
59
+ BaseAmmoGGBody.nativeBodyReverseMap = new Map();
@@ -0,0 +1,14 @@
1
+ import { Gg3dPhysicsWorld } from '../gg-3d-physics-world';
2
+ import Ammo from 'ammojs-typed';
3
+ import { BaseAmmoGGBody } from './base-ammo-gg-body';
4
+ import { Gg3dEntity } from '@gg-web-engine/core';
5
+ export declare class Gg3dBody extends BaseAmmoGGBody<Ammo.btRigidBody> {
6
+ protected readonly world: Gg3dPhysicsWorld;
7
+ protected _nativeBody: Ammo.btRigidBody;
8
+ entity: Gg3dEntity | null;
9
+ constructor(world: Gg3dPhysicsWorld, _nativeBody: Ammo.btRigidBody);
10
+ clone(): Gg3dBody;
11
+ addToWorld(world: Gg3dPhysicsWorld): void;
12
+ removeFromWorld(world: Gg3dPhysicsWorld): void;
13
+ resetMotion(): void;
14
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dBody = void 0;
4
+ const base_ammo_gg_body_1 = require("./base-ammo-gg-body");
5
+ class Gg3dBody extends base_ammo_gg_body_1.BaseAmmoGGBody {
6
+ constructor(world, _nativeBody) {
7
+ super(world, _nativeBody);
8
+ this.world = world;
9
+ this._nativeBody = _nativeBody;
10
+ this.entity = null;
11
+ }
12
+ clone() {
13
+ return this.world.factory.createRigidBodyFromShape(this._nativeBody.getCollisionShape(), {
14
+ dynamic: !this._nativeBody.isStaticObject(),
15
+ mass: 5,
16
+ friction: this._nativeBody.getFriction(),
17
+ restitution: this._nativeBody.getRestitution(),
18
+ }, {
19
+ position: this.position,
20
+ rotation: this.rotation,
21
+ });
22
+ }
23
+ addToWorld(world) {
24
+ var _a;
25
+ if (world != this.world) {
26
+ throw new Error('Ammo bodies cannot be shared between different worlds');
27
+ }
28
+ (_a = world.dynamicAmmoWorld) === null || _a === void 0 ? void 0 : _a.addRigidBody(this.nativeBody);
29
+ }
30
+ removeFromWorld(world) {
31
+ var _a;
32
+ (_a = world.dynamicAmmoWorld) === null || _a === void 0 ? void 0 : _a.removeRigidBody(this.nativeBody);
33
+ }
34
+ resetMotion() {
35
+ const emptyVector = new this.ammo.btVector3();
36
+ this.nativeBody.setLinearVelocity(emptyVector);
37
+ this.nativeBody.setAngularVelocity(emptyVector);
38
+ this.nativeBody.clearForces();
39
+ this.nativeBody.updateInertiaTensor();
40
+ this.ammo.destroy(emptyVector);
41
+ }
42
+ }
43
+ exports.Gg3dBody = Gg3dBody;
@@ -0,0 +1,22 @@
1
+ import { Gg3dTriggerEntity, GgPositionable3dEntity, IGg3dTrigger } from '@gg-web-engine/core';
2
+ import { Gg3dPhysicsWorld } from '../gg-3d-physics-world';
3
+ import { Observable } from 'rxjs';
4
+ import Ammo from 'ammojs-typed';
5
+ import { BaseAmmoGGBody } from './base-ammo-gg-body';
6
+ export declare class Gg3dTrigger extends BaseAmmoGGBody<Ammo.btPairCachingGhostObject> implements IGg3dTrigger {
7
+ protected readonly world: Gg3dPhysicsWorld;
8
+ protected _nativeBody: Ammo.btPairCachingGhostObject;
9
+ entity: Gg3dTriggerEntity | null;
10
+ get onEntityEntered(): Observable<GgPositionable3dEntity>;
11
+ get onEntityLeft(): Observable<GgPositionable3dEntity | null>;
12
+ constructor(world: Gg3dPhysicsWorld, _nativeBody: Ammo.btPairCachingGhostObject);
13
+ private readonly onEnter$;
14
+ private readonly onLeft$;
15
+ private readonly overlaps;
16
+ checkOverlaps(): void;
17
+ clone(): Gg3dTrigger;
18
+ addToWorld(world: Gg3dPhysicsWorld): void;
19
+ removeFromWorld(world: Gg3dPhysicsWorld): void;
20
+ dispose(): void;
21
+ resetMotion(): void;
22
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dTrigger = void 0;
4
+ const core_1 = require("@gg-web-engine/core");
5
+ const rxjs_1 = require("rxjs");
6
+ const base_ammo_gg_body_1 = require("./base-ammo-gg-body");
7
+ const ammo_utils_1 = require("../../ammo-utils");
8
+ class Gg3dTrigger extends base_ammo_gg_body_1.BaseAmmoGGBody {
9
+ constructor(world, _nativeBody) {
10
+ super(world, _nativeBody);
11
+ this.world = world;
12
+ this._nativeBody = _nativeBody;
13
+ this.entity = null;
14
+ this.onEnter$ = new rxjs_1.Subject();
15
+ this.onLeft$ = new rxjs_1.Subject();
16
+ this.overlaps = new Set();
17
+ }
18
+ get onEntityEntered() {
19
+ return this.onEnter$.pipe((0, rxjs_1.map)(b => { var _a; return (_a = base_ammo_gg_body_1.BaseAmmoGGBody.nativeBodyReverseMap.get(b)) === null || _a === void 0 ? void 0 : _a.entity; }), (0, rxjs_1.filter)(x => !!x && x instanceof core_1.GgPositionable3dEntity));
20
+ }
21
+ get onEntityLeft() {
22
+ return this.onLeft$.pipe((0, rxjs_1.map)(b => { var _a; return ((_a = base_ammo_gg_body_1.BaseAmmoGGBody.nativeBodyReverseMap.get(b)) === null || _a === void 0 ? void 0 : _a.entity) || null; }));
23
+ }
24
+ checkOverlaps() {
25
+ const numOverlappingObjects = this.nativeBody.getNumOverlappingObjects();
26
+ const newOverlaps = new Set(new Array(numOverlappingObjects).fill(null).map((_, i) => this.nativeBody.getOverlappingObject(i)));
27
+ for (const overlap of this.overlaps.keys()) {
28
+ if (!newOverlaps.has(overlap)) {
29
+ this.overlaps.delete(overlap);
30
+ this.onLeft$.next((0, ammo_utils_1.ammoId)(overlap));
31
+ }
32
+ else {
33
+ newOverlaps.delete(overlap);
34
+ }
35
+ }
36
+ for (const newOverlap of newOverlaps) {
37
+ this.overlaps.add(newOverlap);
38
+ this.onEnter$.next((0, ammo_utils_1.ammoId)(newOverlap));
39
+ }
40
+ }
41
+ clone() {
42
+ return this.world.factory.createTriggerFromShape(this._nativeBody.getCollisionShape(), {
43
+ position: this.position,
44
+ rotation: this.rotation,
45
+ });
46
+ }
47
+ addToWorld(world) {
48
+ var _a;
49
+ if (world != this.world) {
50
+ throw new Error('Ammo triggers cannot be shared between different worlds');
51
+ }
52
+ (_a = world.dynamicAmmoWorld) === null || _a === void 0 ? void 0 : _a.addCollisionObject(this.nativeBody);
53
+ this.overlaps.clear();
54
+ }
55
+ removeFromWorld(world) {
56
+ var _a;
57
+ for (const body of this.overlaps) {
58
+ this.onLeft$.next((0, ammo_utils_1.ammoId)(body));
59
+ }
60
+ this.overlaps.clear();
61
+ (_a = world.dynamicAmmoWorld) === null || _a === void 0 ? void 0 : _a.removeCollisionObject(this.nativeBody);
62
+ }
63
+ dispose() {
64
+ super.dispose();
65
+ this.overlaps.clear();
66
+ this.onEnter$.complete();
67
+ this.onLeft$.complete();
68
+ }
69
+ resetMotion() { }
70
+ }
71
+ exports.Gg3dTrigger = Gg3dTrigger;
@@ -0,0 +1,26 @@
1
+ import { Body3DOptions, BodyShape3DDescriptor, IGg3dBodyFactory, Point3, Point4, Shape3DDescriptor } from '@gg-web-engine/core';
2
+ import { Gg3dBody } from './bodies/gg-3d-body';
3
+ import { Gg3dPhysicsWorld } from './gg-3d-physics-world';
4
+ import Ammo from 'ammojs-typed';
5
+ import { Gg3dTrigger } from './bodies/gg-3d-trigger';
6
+ export declare class Gg3dBodyFactory implements IGg3dBodyFactory<Gg3dBody, Gg3dTrigger> {
7
+ private readonly world;
8
+ constructor(world: Gg3dPhysicsWorld);
9
+ createRigidBody(descriptor: BodyShape3DDescriptor, transform?: {
10
+ position?: Point3;
11
+ rotation?: Point4;
12
+ }): Gg3dBody;
13
+ createTrigger(descriptor: Shape3DDescriptor, transform?: {
14
+ position?: Point3;
15
+ rotation?: Point4;
16
+ }): Gg3dTrigger;
17
+ private createShape;
18
+ createRigidBodyFromShape(shape: Ammo.btCollisionShape, options: Partial<Body3DOptions>, transform?: {
19
+ position?: Point3;
20
+ rotation?: Point4;
21
+ }): Gg3dBody;
22
+ createTriggerFromShape(shape: Ammo.btCollisionShape, transform?: {
23
+ position?: Point3;
24
+ rotation?: Point4;
25
+ }): Gg3dTrigger;
26
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dBodyFactory = void 0;
4
+ const gg_3d_body_1 = require("./bodies/gg-3d-body");
5
+ const gg_3d_trigger_1 = require("./bodies/gg-3d-trigger");
6
+ class Gg3dBodyFactory {
7
+ constructor(world) {
8
+ this.world = world;
9
+ }
10
+ createRigidBody(descriptor, transform) {
11
+ return this.createRigidBodyFromShape(this.createShape(descriptor.shape), descriptor.body, transform);
12
+ }
13
+ createTrigger(descriptor, transform) {
14
+ return this.createTriggerFromShape(this.createShape(descriptor), transform);
15
+ }
16
+ createShape(descriptor) {
17
+ switch (descriptor.shape) {
18
+ case 'BOX':
19
+ return new this.world.ammo.btBoxShape(new this.world.ammo.btVector3(descriptor.dimensions.x / 2, descriptor.dimensions.y / 2, descriptor.dimensions.z / 2));
20
+ case 'CAPSULE':
21
+ return new this.world.ammo.btCapsuleShapeZ(descriptor.radius, descriptor.centersDistance);
22
+ case 'CYLINDER':
23
+ return new this.world.ammo.btCylinderShapeZ(new this.world.ammo.btVector3(descriptor.radius, descriptor.radius, descriptor.height / 2));
24
+ case 'CONE':
25
+ return new this.world.ammo.btConeShapeZ(descriptor.radius, descriptor.height);
26
+ case 'SPHERE':
27
+ return new this.world.ammo.btSphereShape(descriptor.radius);
28
+ case 'COMPOUND':
29
+ const compoundShape = new this.world.ammo.btCompoundShape();
30
+ for (const item of descriptor.children) {
31
+ const subShape = this.createShape(item.shape);
32
+ if (!subShape) {
33
+ continue;
34
+ }
35
+ const subShapeTransform = new this.world.ammo.btTransform();
36
+ const pos = item.position || { x: 0, y: 0, z: 0 };
37
+ const rot = item.rotation || { x: 0, y: 0, z: 0, w: 1 };
38
+ subShapeTransform.setOrigin(new this.world.ammo.btVector3(pos.x, pos.y, pos.z));
39
+ subShapeTransform.setRotation(new this.world.ammo.btQuaternion(rot.x, rot.y, rot.z, rot.w));
40
+ compoundShape.addChildShape(subShapeTransform, subShape);
41
+ }
42
+ return compoundShape;
43
+ case 'CONVEX_HULL':
44
+ const shape = new this.world.ammo.btConvexHullShape();
45
+ const tmpVector = new this.world.ammo.btVector3();
46
+ for (const v of descriptor.vertices) {
47
+ tmpVector.setValue(v.x, v.y, v.z);
48
+ shape.addPoint(tmpVector);
49
+ }
50
+ this.world.ammo.destroy(tmpVector);
51
+ shape.recalcLocalAabb();
52
+ return shape;
53
+ case 'MESH':
54
+ const mesh = new this.world.ammo.btTriangleMesh(true, true);
55
+ const tmpVectors = [
56
+ new this.world.ammo.btVector3(),
57
+ new this.world.ammo.btVector3(),
58
+ new this.world.ammo.btVector3(),
59
+ ];
60
+ for (const f of descriptor.faces) {
61
+ for (let j = 0; j < 3; j++) {
62
+ tmpVectors[j].setValue(descriptor.vertices[f[0]].x, descriptor.vertices[f[1]].y, descriptor.vertices[f[2]].z);
63
+ }
64
+ mesh.addTriangle(...tmpVectors, true);
65
+ }
66
+ tmpVectors.forEach(v => {
67
+ this.world.ammo.destroy(v);
68
+ });
69
+ return new this.world.ammo.btBvhTriangleMeshShape(mesh, false, true);
70
+ }
71
+ throw new Error(`Shape "${descriptor.shape}" not implemented for Ammo.js`);
72
+ }
73
+ createRigidBodyFromShape(shape, options, transform) {
74
+ if (options.dynamic === false) {
75
+ options.mass = 0;
76
+ }
77
+ const pos = (transform === null || transform === void 0 ? void 0 : transform.position) || { x: 0, y: 0, z: 0 };
78
+ const rot = (transform === null || transform === void 0 ? void 0 : transform.rotation) || { x: 0, y: 0, z: 0, w: 1 };
79
+ const ammo = this.world.ammo;
80
+ const ammoTransform = new ammo.btTransform();
81
+ ammoTransform.setOrigin(new ammo.btVector3(pos.x, pos.y, pos.z));
82
+ ammoTransform.setRotation(new ammo.btQuaternion(rot.x, rot.y, rot.z, rot.w));
83
+ const motionState = new ammo.btDefaultMotionState(ammoTransform);
84
+ const localInertia = new ammo.btVector3(0, 0, 0);
85
+ shape.calculateLocalInertia(options.mass || 0, localInertia);
86
+ const environmentBodyCI = new ammo.btRigidBodyConstructionInfo(options.mass || 0, motionState, shape, localInertia);
87
+ if (options.friction) {
88
+ environmentBodyCI.set_m_friction(options.friction);
89
+ environmentBodyCI.set_m_rollingFriction(options.friction);
90
+ }
91
+ if (options.restitution) {
92
+ environmentBodyCI.set_m_restitution(options.restitution);
93
+ }
94
+ const body = new this.world.ammo.btRigidBody(environmentBodyCI);
95
+ return new gg_3d_body_1.Gg3dBody(this.world, body);
96
+ }
97
+ createTriggerFromShape(shape, transform) {
98
+ var _a, _b, _c, _d, _e, _f, _g;
99
+ const ghostObject = new this.world.ammo.btPairCachingGhostObject();
100
+ ghostObject.setCollisionShape(shape);
101
+ ghostObject.setCollisionFlags(ghostObject.getCollisionFlags() | 4); // 4 is a CF_NO_CONTACT_RESPONSE collision flag
102
+ ghostObject
103
+ .getWorldTransform()
104
+ .setOrigin(new this.world.ammo.btVector3(((_a = transform === null || transform === void 0 ? void 0 : transform.position) === null || _a === void 0 ? void 0 : _a.x) || 0, ((_b = transform === null || transform === void 0 ? void 0 : transform.position) === null || _b === void 0 ? void 0 : _b.y) || 0, ((_c = transform === null || transform === void 0 ? void 0 : transform.position) === null || _c === void 0 ? void 0 : _c.z) || 0));
105
+ ghostObject
106
+ .getWorldTransform()
107
+ .setRotation(new this.world.ammo.btQuaternion(((_d = transform === null || transform === void 0 ? void 0 : transform.rotation) === null || _d === void 0 ? void 0 : _d.x) || 0, ((_e = transform === null || transform === void 0 ? void 0 : transform.rotation) === null || _e === void 0 ? void 0 : _e.y) || 0, ((_f = transform === null || transform === void 0 ? void 0 : transform.rotation) === null || _f === void 0 ? void 0 : _f.z) || 0, ((_g = transform === null || transform === void 0 ? void 0 : transform.rotation) === null || _g === void 0 ? void 0 : _g.w) || 1));
108
+ return new gg_3d_trigger_1.Gg3dTrigger(this.world, ghostObject);
109
+ }
110
+ }
111
+ exports.Gg3dBodyFactory = Gg3dBodyFactory;
@@ -0,0 +1,6 @@
1
+ import { IGg3dBodyLoader } from '@gg-web-engine/core';
2
+ import { Gg3dPhysicsWorld } from './gg-3d-physics-world';
3
+ export declare class Gg3dBodyLoader extends IGg3dBodyLoader {
4
+ protected readonly world: Gg3dPhysicsWorld;
5
+ constructor(world: Gg3dPhysicsWorld);
6
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gg3dBodyLoader = void 0;
4
+ const core_1 = require("@gg-web-engine/core");
5
+ class Gg3dBodyLoader extends core_1.IGg3dBodyLoader {
6
+ constructor(world) {
7
+ super(world);
8
+ this.world = world;
9
+ }
10
+ }
11
+ exports.Gg3dBodyLoader = Gg3dBodyLoader;
@@ -0,0 +1,34 @@
1
+ import { Gg3dWorld, GgDebugPhysicsDrawer, IGg3dPhysicsWorld, Point3, Point4 } from '@gg-web-engine/core';
2
+ import Ammo from 'ammojs-typed';
3
+ import { Gg3dBodyFactory } from './gg-3d-body-factory';
4
+ import { Gg3dBodyLoader } from './gg-3d-body-loader';
5
+ export declare class Gg3dPhysicsWorld implements IGg3dPhysicsWorld {
6
+ private _factory;
7
+ get factory(): Gg3dBodyFactory;
8
+ private _loader;
9
+ get loader(): Gg3dBodyLoader;
10
+ private _gravity;
11
+ get gravity(): Point3;
12
+ set gravity(value: Point3);
13
+ private _timeScale;
14
+ get timeScale(): number;
15
+ set timeScale(value: number);
16
+ private _debugger;
17
+ private _debugDrawer;
18
+ get physicsDebugViewActive(): boolean;
19
+ private ammoInstance;
20
+ get ammo(): typeof Ammo;
21
+ get dynamicAmmoWorld(): Ammo.btDiscreteDynamicsWorld | undefined;
22
+ private collisionConfiguration;
23
+ private dispatcher;
24
+ private ghostPairCallback;
25
+ private broadphase;
26
+ private solver;
27
+ private gravityVector;
28
+ private _dynamicAmmoWorld;
29
+ init(): Promise<void>;
30
+ simulate(delta: number): void;
31
+ startDebugger(world: Gg3dWorld, drawer: GgDebugPhysicsDrawer<Point3, Point4>): void;
32
+ stopDebugger(world: Gg3dWorld): void;
33
+ dispose(): void;
34
+ }