@osobh/reactar
Version:
AR Library for React Native and Expo
231 lines • 8.99 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.PhysicsManager = void 0;
// src/core/PhysicsManager.ts
const AmmoModule = __importStar(require("ammojs3"));
let ammoInstance;
const three_1 = require("three");
const events_1 = require("events");
class PhysicsManager extends events_1.EventEmitter {
constructor() {
super();
this.objects = new Map();
this.isInitialized = false;
this.gravity = new three_1.Vector3(0, -9.81, 0);
this.timeStep = 1 / 60;
}
/**
* Initializes the physics engine
*/
async initialize() {
try {
// Initialize Ammo.js
const ammo = await AmmoModule.default();
// Assign to global Ammo variable
globalThis.Ammo = ammo;
this.collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
this.dispatcher = new Ammo.btCollisionDispatcher(this.collisionConfiguration);
this.broadphase = new Ammo.btDbvtBroadphase();
this.solver = new Ammo.btSequentialImpulseConstraintSolver();
this.physicsWorld = new Ammo.btDiscreteDynamicsWorld(this.dispatcher, this.broadphase, this.solver, this.collisionConfiguration);
// Set default gravity
const gravity = new Ammo.btVector3(this.gravity.x, this.gravity.y, this.gravity.z);
this.physicsWorld.setGravity(gravity);
this.isInitialized = true;
this.emit('initialized');
return true;
}
catch (error) {
this.emit('error', error);
throw error;
}
}
/**
* Creates a physics object and adds it to the physics world
*/
createObject(id, position, rotation, scale, properties = {}) {
var _a, _b, _c, _d, _e;
if (!this.isInitialized) {
throw new Error('PhysicsManager must be initialized first');
}
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
transform.setRotation(new Ammo.btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
const motionState = new Ammo.btDefaultMotionState(transform);
const shape = this.createBoxShape(scale);
const mass = (_a = properties.mass) !== null && _a !== void 0 ? _a : 0;
const localInertia = new Ammo.btVector3(0, 0, 0);
if (mass > 0) {
shape.calculateLocalInertia(mass, localInertia);
}
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
// Set additional properties
body.setFriction((_b = properties.friction) !== null && _b !== void 0 ? _b : 0.5);
body.setRestitution((_c = properties.restitution) !== null && _c !== void 0 ? _c : 0.2);
body.setDamping((_d = properties.linearDamping) !== null && _d !== void 0 ? _d : 0.1, (_e = properties.angularDamping) !== null && _e !== void 0 ? _e : 0.1);
if (properties.isKinematic) {
body.setCollisionFlags(body.getCollisionFlags() | 2); // CF_KINEMATIC_OBJECT
}
this.physicsWorld.addRigidBody(body);
this.objects.set(id, {
id,
body,
mass,
position: position.clone(),
rotation: rotation.clone(),
scale: scale.clone()
});
this.emit('object-created', id);
}
/**
* Updates the physics simulation
*/
update(deltaTime = this.timeStep) {
if (!this.isInitialized)
return;
this.physicsWorld.stepSimulation(deltaTime, 10);
// Update object positions and rotations
this.objects.forEach((object) => {
const transform = new Ammo.btTransform();
object.body.getMotionState().getWorldTransform(transform);
const pos = transform.getOrigin();
const rot = transform.getRotation();
object.position.set(pos.x(), pos.y(), pos.z());
object.rotation.set(rot.x(), rot.y(), rot.z(), rot.w());
this.emit('object-updated', {
id: object.id,
position: object.position,
rotation: object.rotation
});
});
}
/**
* Applies a force to an object
*/
applyForce(id, force, point) {
const object = this.objects.get(id);
if (!object) {
throw new Error(`Physics object ${id} not found`);
}
const btForce = new Ammo.btVector3(force.x, force.y, force.z);
if (point) {
const btPoint = new Ammo.btVector3(point.x, point.y, point.z);
object.body.applyForce(btForce, btPoint);
}
else {
object.body.applyCentralForce(btForce);
}
}
/**
* Sets the gravity of the physics world
*/
setGravity(gravity) {
this.gravity = gravity.clone();
const btGravity = new Ammo.btVector3(gravity.x, gravity.y, gravity.z);
this.physicsWorld.setGravity(btGravity);
}
/**
* Creates a box collision shape
*/
createBoxShape(scale) {
const shape = new Ammo.btBoxShape(new Ammo.btVector3(scale.x * 0.5, scale.y * 0.5, scale.z * 0.5));
return shape;
}
/**
* Removes an object from the physics world
*/
removeObject(id) {
const object = this.objects.get(id);
if (!object)
return;
this.physicsWorld.removeRigidBody(object.body);
this.objects.delete(id);
this.emit('object-removed', id);
}
/**
* Cleans up physics resources
*/
/**
* Creates a rigid body with specified position, rotation and mass
*/
createRigidBody(position, rotation, mass) {
if (!this.isInitialized) {
throw new Error('PhysicsManager must be initialized first');
}
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
transform.setRotation(new Ammo.btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
const motionState = new Ammo.btDefaultMotionState(transform);
const shape = new Ammo.btBoxShape(new Ammo.btVector3(0.5, 0.5, 0.5));
const localInertia = new Ammo.btVector3(0, 0, 0);
if (mass > 0) {
shape.calculateLocalInertia(mass, localInertia);
}
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
body.setMass(mass);
this.physicsWorld.addRigidBody(body);
return body;
}
/**
* Gets the physics world instance
*/
getWorld() {
if (!this.isInitialized) {
throw new Error('PhysicsManager must be initialized first');
}
return this.physicsWorld;
}
/**
* Cleans up physics resources
*/
cleanup() {
Array.from(this.objects.keys()).forEach(id => this.removeObject(id));
// Clean up Ammo.js resources
Ammo.destroy(this.physicsWorld);
Ammo.destroy(this.solver);
Ammo.destroy(this.broadphase);
Ammo.destroy(this.dispatcher);
Ammo.destroy(this.collisionConfiguration);
this.isInitialized = false;
this.emit('cleanup-complete');
}
}
exports.PhysicsManager = PhysicsManager;
//# sourceMappingURL=PhysicsManager.js.map