/** * PhysicsWorldImpl.ts * * Physics world implementation with broadphase collision detection, * constraint solving, and spatial queries. * * @module physics */ import { IVector3, IQuaternion, ITransform, IRigidBodyConfig, IRigidBodyState, IPhysicsWorld, IPhysicsWorldConfig, Constraint, ICollisionEvent, ITriggerEvent, ICollisionFilter, IRay, IRaycastHit, IRaycastOptions, IOverlapResult } from './PhysicsTypes'; /** * Physics world implementation */ export declare class PhysicsWorldImpl implements IPhysicsWorld { private config; private bodies; private constraints; private collisionEvents; private triggerEvents; private islandDetector; /** Full-featured sequential-impulse solver used for all non-distance constraint types. */ private constraintSolver; private accumulator; private bodiesArray; private collisionPairs; private activeContacts; constructor(config?: IPhysicsWorldConfig); setGravity(gravity: IVector3): void; getGravity(): IVector3; createBody(config: IRigidBodyConfig): string; removeBody(id: string): boolean; getBody(id: string): IRigidBodyState | undefined; getAllBodies(): IRigidBodyState[]; setPosition(id: string, position: IVector3): void; setRotation(id: string, rotation: IQuaternion): void; setTransform(id: string, transform: ITransform): void; setLinearVelocity(id: string, velocity: IVector3): void; setAngularVelocity(id: string, velocity: IVector3): void; applyForce(id: string, force: IVector3, worldPoint?: IVector3): void; applyImpulse(id: string, impulse: IVector3, worldPoint?: IVector3): void; applyTorque(id: string, torque: IVector3): void; applyTorqueImpulse(id: string, impulse: IVector3): void; createConstraint(constraint: Constraint): string; removeConstraint(id: string): boolean; setConstraintEnabled(id: string, enabled: boolean): void; step(deltaTime: number): void; private fixedStep; private broadphase; private narrowphase; private checkCollision; /** * Optimized sphere-sphere collision (analytic, O(1)). */ private checkSphereSphere; /** * Exact sphere versus oriented-box contact. The returned normal follows the * world convention and points from the sphere body toward the box body. */ private checkSphereBox; /** * Exact sphere versus finite oriented-cylinder contact. The returned normal * follows the world convention and points from the sphere body toward the * cylinder body. */ private checkSphereCylinder; /** * GJK/EPA narrowphase collision for arbitrary convex shape pairs. * * 1. Run GJK to determine overlap (boolean). * 2. If overlapping, run EPA to get contact normal + penetration depth. * 3. Compute an approximate contact point on the surface between the two shapes. */ private checkGJKEPA; /** * Compute the world-space effective inverse inertia scalar along an axis. * * The local inverse inertia tensor is diagonal (invI[0], invI[1], invI[2]). * To evaluate the angular contribution to the impulse denominator we need: * * angularTerm = ((I_world^-1 * (r × n)) × r) · n * * where I_world^-1 = R * diag(invI) * R^T. * * @param invI Diagonal inverse inertia in body-local space. * @param q Body orientation quaternion [qx, qy, qz, qw]. * @param r Lever arm: contactPoint − bodyPosition (world space). * @param n Contact normal (world space). */ private angularImpulseDenominator; /** * Resolve a collision between two bodies using the standard contact impulse * with both linear and angular (rotational) terms. * * Impulse magnitude (Mirtich 1994 / Baumgarte): * * j = -(1+e) * vRel·n * ───────────────────────────────────────────────────────────── * invMassA + invMassB * + (I_A^-1*(rA×n))×rA·n * + (I_B^-1*(rB×n))×rB·n * * Angular velocity deltas: * dωA = -I_A^-1 * (rA × j*n) * dωB = +I_B^-1 * (rB × j*n) */ private resolveCollision; /** * Build an IRigidBodyState snapshot for a RigidBody, enriched with the * invMass and invInertia fields that ConstraintSolver.addConstraint needs. */ private toConstraintState; /** * Solve all constraints for one timestep. * * - 'distance' constraints: fast positional correction path (unchanged). * - All other types (hinge, ball, spring, slider, cone, generic6dof): * delegated to ConstraintSolver for full sequential-impulse solving with * warm-starting. The solver's velocity deltas are applied back to each * affected RigidBody via applyImpulse / applyTorqueImpulse. * * Follow-up note: 'slider', 'cone', 'generic6dof', 'spring', and 'fixed' * are wired via ConstraintSolver here but not individually test-covered in * this pass. Hinge and ball-socket are the primary use cases. For a full * constraint test suite see registration_snippets. */ private solveConstraints; private solveDistanceConstraint; private detectIslands; getContacts(): ICollisionEvent[]; getTriggers(): ITriggerEvent[]; raycast(ray: IRay, options?: IRaycastOptions): IRaycastHit[]; raycastClosest(ray: IRay, options?: IRaycastOptions): IRaycastHit | null; private raycastBody; private calculateAABBHitNormal; sphereOverlap(center: IVector3, radius: number, filter?: ICollisionFilter): IOverlapResult[]; boxOverlap(center: IVector3, halfExtents: IVector3, _rotation?: IQuaternion, filter?: ICollisionFilter): IOverlapResult[]; /** * Compute the axis-aligned bounding box for a body in world space. * * For box shapes the local half-extents are rotated into world space via the * body's orientation quaternion q. The rotation matrix R derived from q gives * the world-space half-extent on each axis as: * * e_world[i] = Σ_j |R[i][j]| * e_local[j] * * This is the standard tight AABB formula for an oriented box. Spheres are * symmetric so orientation has no effect. Capsules are treated as spheres * around the full swept segment (conservative, axis-independent; capsules * do not yet account for orientation -- pre-existing, out of scope here). * Cylinders use the tight oriented-cylinder formula documented on their * case below. */ private getBodyAABB; private aabbOverlap; private getContactKey; private filterMatches; dispose(): void; } /** * Create a physics world */ export declare function createPhysicsWorld(config?: IPhysicsWorldConfig): IPhysicsWorld; //# sourceMappingURL=PhysicsWorldImpl.d.ts.map