/**
 * Object holding the result of a contact between two Entities.
 *
 * @category Physics
 */
export class ContactPoint {
    /**
     * Create a new ContactPoint instance.
     *
     * @param {Vec3} [localPoint] - The point on the entity where the contact occurred, relative to
     * the entity.
     * @param {Vec3} [localPointOther] - The point on the other entity where the contact occurred,
     * relative to the other entity.
     * @param {Vec3} [point] - The point on the entity where the contact occurred, in world space.
     * @param {Vec3} [pointOther] - The point on the other entity where the contact occurred, in
     * world space.
     * @param {Vec3} [normal] - The normal vector of the contact on the other entity, in world
     * space.
     * @param {number} [impulse] - The total accumulated impulse applied by the constraint solver
     * during the last sub-step. Describes how hard two objects collide. Defaults to 0.
     * @ignore
     */
    constructor(localPoint?: Vec3, localPointOther?: Vec3, point?: Vec3, pointOther?: Vec3, normal?: Vec3, impulse?: number);
    /**
     * The point on the entity where the contact occurred, relative to the entity.
     *
     * @type {Vec3}
     */
    localPoint: Vec3;
    /**
     * The point on the other entity where the contact occurred, relative to the other entity.
     *
     * @type {Vec3}
     */
    localPointOther: Vec3;
    /**
     * The point on the entity where the contact occurred, in world space.
     *
     * @type {Vec3}
     */
    point: Vec3;
    /**
     * The point on the other entity where the contact occurred, in world space.
     *
     * @type {Vec3}
     */
    pointOther: Vec3;
    /**
     * The normal vector of the contact on the other entity, in world space.
     *
     * @type {Vec3}
     */
    normal: Vec3;
    /**
     * The total accumulated impulse applied by the constraint solver during the last sub-step.
     * Describes how hard two objects collide.
     *
     * @type {number}
     */
    impulse: number;
}
/**
 * Object holding the result of a contact between two Entities.
 *
 * @category Physics
 */
export class ContactResult {
    /**
     * Create a new ContactResult instance.
     *
     * @param {Entity} other - The entity that was involved in the contact with this entity.
     * @param {ContactPoint[]} contacts - An array of ContactPoints with the other entity.
     * @ignore
     */
    constructor(other: Entity, contacts: ContactPoint[]);
    /**
     * The entity that was involved in the contact with this entity.
     *
     * @type {Entity}
     */
    other: Entity;
    /**
     * An array of ContactPoints with the other entity.
     *
     * @type {ContactPoint[]}
     */
    contacts: ContactPoint[];
}
/**
 * Object holding the result of a successful raycast hit.
 *
 * @category Physics
 */
export class RaycastResult {
    /**
     * Create a new RaycastResult instance.
     *
     * @param {Entity} entity - The entity that was hit.
     * @param {Vec3} point - The point at which the ray hit the entity in world space.
     * @param {Vec3} normal - The normal vector of the surface where the ray hit in world space.
     * @param {number} hitFraction - The normalized distance (between 0 and 1) at which the ray hit
     * occurred from the starting point.
     * @ignore
     */
    constructor(entity: Entity, point: Vec3, normal: Vec3, hitFraction: number);
    /**
     * The entity that was hit.
     *
     * @type {Entity}
     */
    entity: Entity;
    /**
     * The point at which the ray hit the entity in world space.
     *
     * @type {Vec3}
     */
    point: Vec3;
    /**
     * The normal vector of the surface where the ray hit in world space.
     *
     * @type {Vec3}
     */
    normal: Vec3;
    /**
     * The normalized distance (between 0 and 1) at which the ray hit occurred from the
     * starting point.
     *
     * @type {number}
     */
    hitFraction: number;
}
/**
 * The RigidBodyComponentSystem maintains the dynamics world for simulating rigid bodies, it also
 * controls global values for the world such as gravity. Note: The RigidBodyComponentSystem is only
 * valid if 3D Physics is enabled in your application. You can enable this in the application
 * settings for your project.
 *
 * @category Physics
 */
export class RigidBodyComponentSystem extends ComponentSystem {
    /**
     * Fired when a contact occurs between two rigid bodies. The handler is passed a
     * {@link SingleContactResult} object containing details of the contact between the two bodies.
     *
     * @event
     * @example
     * app.systems.rigidbody.on('contact', (result) => {
     *     console.log(`Contact between ${result.a.name} and ${result.b.name}`);
     * });
     */
    static EVENT_CONTACT: string;
    /**
     * @type {number}
     * @ignore
     */
    maxSubSteps: number;
    /**
     * @type {number}
     * @ignore
     */
    fixedTimeStep: number;
    /**
     * The world space vector representing global gravity in the physics simulation. Defaults to
     * [0, -9.81, 0] which is an approximation of the gravitational force on Earth.
     *
     * @type {Vec3}
     */
    gravity: Vec3;
    /**
     * @type {Float32Array}
     * @private
     */
    private _gravityFloat32;
    /**
     * @type {RigidBodyComponent[]}
     * @private
     */
    private _dynamic;
    /**
     * @type {RigidBodyComponent[]}
     * @private
     */
    private _kinematic;
    /**
     * @type {RigidBodyComponent[]}
     * @private
     */
    private _triggers;
    /**
     * @type {RigidBodyComponent[]}
     * @private
     */
    private _compounds;
    id: string;
    _stats: {
        fps: number;
        ms: number;
        dt: number;
        updateStart: number;
        updateTime: number;
        renderStart: number;
        renderTime: number;
        physicsStart: number;
        physicsTime: number;
        cullTime: number;
        sortTime: number;
        skinTime: number;
        morphTime: number;
        instancingTime: number;
        triangles: number;
        otherPrimitives: number;
        shaders: number;
        materials: number;
        cameras: number;
        shadowMapUpdates: number;
        shadowMapTime: number;
        depthMapTime: number;
        forwardTime: number;
        lightClustersTime: number;
        lightClusters: number;
        _timeToCountFrames: number;
        _fpsAccum: number;
    };
    ComponentType: typeof RigidBodyComponent;
    DataType: typeof RigidBodyComponentData;
    contactPointPool: ObjectPool<typeof ContactPoint>;
    contactResultPool: ObjectPool<typeof ContactResult>;
    singleContactResultPool: ObjectPool<typeof SingleContactResult>;
    schema: string[];
    collisions: {};
    frameCollisions: {};
    /**
     * Called once Ammo has been loaded. Responsible for creating the physics world.
     *
     * @ignore
     */
    onLibraryLoaded(): void;
    collisionConfiguration: any;
    dispatcher: any;
    overlappingPairCache: any;
    solver: any;
    dynamicsWorld: any;
    initializeComponentData(component: any, data: any, properties: any): void;
    cloneComponent(entity: any, clone: any): Component;
    onBeforeRemove(entity: any, component: any): void;
    addBody(body: any, group: any, mask: any): void;
    removeBody(body: any): void;
    createBody(mass: any, shape: any, transform: any): any;
    destroyBody(body: any): void;
    /**
     * Raycast the world and return the first entity the ray hits. Fire a ray into the world from
     * start to end, if the ray hits an entity with a collision component, it returns a
     * {@link RaycastResult}, otherwise returns null.
     *
     * @param {Vec3} start - The world space point where the ray starts.
     * @param {Vec3} end - The world space point where the ray ends.
     * @param {object} [options] - The additional options for the raycasting.
     * @param {number} [options.filterCollisionGroup] - Collision group to apply to the raycast.
     * @param {number} [options.filterCollisionMask] - Collision mask to apply to the raycast.
     * @param {any[]} [options.filterTags] - Tags filters. Defined the same way as a {@link Tags#has}
     * query but within an array.
     * @param {Function} [options.filterCallback] - Custom function to use to filter entities.
     * Must return true to proceed with result. Takes one argument: the entity to evaluate.
     *
     * @returns {RaycastResult|null} The result of the raycasting or null if there was no hit.
     */
    raycastFirst(start: Vec3, end: Vec3, options?: {
        filterCollisionGroup?: number;
        filterCollisionMask?: number;
        filterTags?: any[];
        filterCallback?: Function;
    }): RaycastResult | null;
    /**
     * Raycast the world and return all entities the ray hits. It returns an array of
     * {@link RaycastResult}, one for each hit. If no hits are detected, the returned array will be
     * of length 0. Results are sorted by distance with closest first.
     *
     * @param {Vec3} start - The world space point where the ray starts.
     * @param {Vec3} end - The world space point where the ray ends.
     * @param {object} [options] - The additional options for the raycasting.
     * @param {boolean} [options.sort] - Whether to sort raycast results based on distance with closest
     * first. Defaults to false.
     * @param {number} [options.filterCollisionGroup] - Collision group to apply to the raycast.
     * @param {number} [options.filterCollisionMask] - Collision mask to apply to the raycast.
     * @param {any[]} [options.filterTags] - Tags filters. Defined the same way as a {@link Tags#has}
     * query but within an array.
     * @param {Function} [options.filterCallback] - Custom function to use to filter entities.
     * Must return true to proceed with result. Takes the entity to evaluate as argument.
     *
     * @returns {RaycastResult[]} An array of raycast hit results (0 length if there were no hits).
     *
     * @example
     * // Return all results of a raycast between 0, 2, 2 and 0, -2, -2
     * const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2));
     * @example
     * // Return all results of a raycast between 0, 2, 2 and 0, -2, -2
     * // where hit entity is tagged with `bird` OR `mammal`
     * const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
     *     filterTags: [ "bird", "mammal" ]
     * });
     * @example
     * // Return all results of a raycast between 0, 2, 2 and 0, -2, -2
     * // where hit entity has a `camera` component
     * const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
     *     filterCallback: (entity) => entity && entity.camera
     * });
     * @example
     * // Return all results of a raycast between 0, 2, 2 and 0, -2, -2
     * // where hit entity is tagged with (`carnivore` AND `mammal`) OR (`carnivore` AND `reptile`)
     * // and the entity has an `anim` component
     * const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
     *     filterTags: [
     *         [ "carnivore", "mammal" ],
     *         [ "carnivore", "reptile" ]
     *     ],
     *     filterCallback: (entity) => entity && entity.anim
     * });
     */
    raycastAll(start: Vec3, end: Vec3, options?: {
        sort?: boolean;
        filterCollisionGroup?: number;
        filterCollisionMask?: number;
        filterTags?: any[];
        filterCallback?: Function;
    }): RaycastResult[];
    /**
     * Stores a collision between the entity and other in the contacts map and returns true if it
     * is a new collision.
     *
     * @param {Entity} entity - The entity.
     * @param {Entity} other - The entity that collides with the first entity.
     * @returns {boolean} True if this is a new collision, false otherwise.
     * @private
     */
    private _storeCollision;
    _createContactPointFromAmmo(contactPoint: any): ContactPoint;
    _createReverseContactPointFromAmmo(contactPoint: any): ContactPoint;
    _createSingleContactResult(a: any, b: any, contactPoint: any): SingleContactResult;
    _createContactResult(other: any, contacts: any): ContactResult;
    /**
     * Removes collisions that no longer exist from the collisions list and fires collisionend
     * events to the related entities.
     *
     * @private
     */
    private _cleanOldCollisions;
    /**
     * Returns true if the entity has a contact event attached and false otherwise.
     *
     * @param {Entity} entity - Entity to test.
     * @returns {boolean} True if the entity has a contact and false otherwise.
     * @private
     */
    private _hasContactEvent;
    /**
     * Checks for collisions and fires collision events.
     *
     * @param {number} world - The pointer to the dynamics world that invoked this callback.
     * @param {number} timeStep - The amount of simulation time processed in the last simulation tick.
     * @private
     */
    private _checkForCollisions;
    onUpdate(dt: any): void;
}
/**
 * Object holding the result of a contact between two rigid bodies.
 *
 * @category Physics
 */
export class SingleContactResult {
    /**
     * Create a new SingleContactResult instance.
     *
     * @param {Entity} a - The first entity involved in the contact.
     * @param {Entity} b - The second entity involved in the contact.
     * @param {ContactPoint} contactPoint - The contact point between the two entities.
     * @ignore
     */
    constructor(a: Entity, b: Entity, contactPoint: ContactPoint, ...args: any[]);
    /**
     * The first entity involved in the contact.
     *
     * @type {Entity}
     */
    a: Entity;
    /**
     * The second entity involved in the contact.
     *
     * @type {Entity}
     */
    b: Entity;
    /**
     * The total accumulated impulse applied by the constraint solver during the last
     * sub-step. Describes how hard two bodies collided.
     *
     * @type {number}
     */
    impulse: number;
    /**
     * The point on Entity A where the contact occurred, relative to A.
     *
     * @type {Vec3}
     */
    localPointA: Vec3;
    /**
     * The point on Entity B where the contact occurred, relative to B.
     *
     * @type {Vec3}
     */
    localPointB: Vec3;
    /**
     * The point on Entity A where the contact occurred, in world space.
     *
     * @type {Vec3}
     */
    pointA: Vec3;
    /**
     * The point on Entity B where the contact occurred, in world space.
     *
     * @type {Vec3}
     */
    pointB: Vec3;
    /**
     * The normal vector of the contact on Entity B, in world space.
     *
     * @type {Vec3}
     */
    normal: Vec3;
}
import { Vec3 } from '../../../core/math/vec3.js';
import type { Entity } from '../../entity.js';
import { ComponentSystem } from '../system.js';
import { RigidBodyComponent } from './component.js';
import { RigidBodyComponentData } from './data.js';
import { ObjectPool } from '../../../core/object-pool.js';
import { Component } from '../component.js';
