import { Camera, type Intersection, Layers, Object3D, Ray, Raycaster, Vector2, Vector3 } from 'three';
import type { StaticGeometryGenerator } from 'three-mesh-bvh';
import { Context } from './engine_setup.js';
import type { Vec2, Vec3 } from './engine_types.js';
import type { IPhysicsEngine } from './engine_types.js';
export declare type RaycastTestObjectReturnType = void | boolean | "continue in children";
export declare type RaycastTestObjectCallback = (obj: Object3D) => RaycastTestObjectReturnType;
export declare interface IRaycastOptions {
    /** Optionally a custom raycaster can be provided. Other properties will then be set on this raycaster */
    raycaster?: Raycaster;
    /** Optional ray that can be used for raycasting
     *  @link https://threejs.org/docs/#api/en/math/Ray
     * */
    ray?: Ray;
    /** The camera to use for the raycaster */
    cam?: Camera | null;
    /** Point on screen in raycast space / normalized device coordinates (-1 to 1).
     * @link https://threejs.org/docs/#api/en/core/Raycaster.setFromCamera */
    screenPoint?: Vector2;
    /** Raycast results array. You can provide an array here to avoid creating a new one (note that if your array already contains items they will be removed) */
    results?: Array<Intersection>;
    /** Objects to raycast against. If no target array is provided the whole scene will be raycasted */
    targets?: Array<Object3D>;
    /**
     * If true, the raycaster will traverse the scene recursively.
     * @default true
     */
    recursive?: boolean;
    /**
     * If true, the raycaster will use a more precise method to test for intersections. This is slower but more accurate.
     * @default true
     */
    precise?: boolean;
    /** Set the raycaster near distance:
     * The near factor of the raycaster. This value indicates which objects can be discarded based on the distance. This value shouldn't be negative and should be smaller than the far property.
     * @link https://threejs.org/docs/#api/en/core/Raycaster.near
     */
    minDistance?: number;
    /** Set the raycaster far distance:
     * The far factor of the raycaster. This value indicates which objects can be discarded based on the distance. This value shouldn't be negative and should be larger than the near property.
     * @link https://threejs.org/docs/#api/en/core/Raycaster.far
     */
    maxDistance?: number;
    /** @link https://threejs.org/docs/#api/en/core/Raycaster.params */
    lineThreshold?: number;
    /** raw layer mask, use setLayer to set an individual layer active */
    layerMask?: Layers | number;
    ignore?: Object3D[];
    /** Optional calback function to be called per object before tested for intersections.
     * This can be used to filter objects.
     * Return `false` to ignore the object completely or `"continue in children"` to skip the object but continue to traverse its children (if you do raycast with `recursive` enabled)
     * */
    testObject?: RaycastTestObjectCallback;
    /**
     * Use MeshBVH for raycasting. This is faster than the default threejs raycaster but uses more memory.
     * @default true
     */
    useAcceleratedRaycast?: boolean;
    /**
     * When enabled raycasting will use the 'slower' traditional three.js raycasting method while the MeshBVH is being generated in the background. When disabled objects that don't have a BVH available *Yet* because it's still being generated will be ignored and not generate any hits. This is useful to improve performance for cases where raycasting happens frequently and it won't matter if raycasts don't produce hits for a few frames.
     * @default true
     */
    allowSlowRaycastFallback?: boolean;
}
export declare class RaycastOptions implements IRaycastOptions {
    static readonly AllLayers = 4294967295;
    ray?: Ray;
    cam?: Camera | null;
    screenPoint?: Vector2;
    raycaster?: Raycaster;
    results?: Array<Intersection>;
    targets?: Array<Object3D>;
    recursive?: boolean;
    minDistance?: number;
    maxDistance?: number;
    lineThreshold?: number;
    layerMask?: Layers | number;
    ignore?: Object3D[];
    testObject?: RaycastTestObjectCallback;
    useAcceleratedRaycast?: boolean | undefined;
    allowSlowRaycastFallback?: boolean;
    screenPointFromOffset(ox: number, oy: number): void;
    /** sets one layer for raycasting (e.g. layer 4, only objects on layer 4 will then be hit) */
    setLayer(layer: number): void;
    /** sets the layer.mask value directly, use setLayer if you want to set e.g. an individual layer only active. See https://threejs.org/docs/#api/en/core/Layers for more information about layers */
    setMask(mask: number): void;
}
export declare class SphereIntersection implements Intersection {
    distance: number;
    point: Vector3;
    object: Object3D;
    constructor(object: Object3D, distance: number, point: Vector3);
}
/**
 * Provides physics utilities including raycasting and overlap detection.
 * Access via `this.context.physics` from any component.
 *
 * For physics engine features (rigidbodies, colliders, forces, etc.), use `this.context.physics.engine`.
 * The physics engine is {@link RapierPhysics}, which uses the Rapier physics library for realistic simulation.
 *
 * **Performance - Automatic MeshBVH:**
 * Needle Engine automatically uses [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) to accelerate raycasting.
 * MeshBVH structures are generated automatically on web workers in the background, making raycasts significantly faster
 * without blocking the main thread. This happens transparently - you don't need to do anything to enable it.
 * While the BVH is being generated, raycasts fall back to standard three.js raycasting (configurable via `allowSlowRaycastFallback`).
 *
 * @example Raycasting from mouse position
 * ```ts
 * const hits = this.context.physics.raycast();
 * if (hits.length > 0) {
 *   console.log("Hit:", hits[0].object.name);
 * }
 * ```
 * @example Raycasting with inline options
 * ```ts
 * const hits = this.context.physics.raycast({
 *   maxDistance: 100, // Only hit objects within 100 units
 *   layerMask: 1, // Only layer 0
 *   ignore: [this.gameObject] // Ignore self
 * });
 * ```
 * @example Physics engine raycast (against colliders only)
 * ```ts
 * const hit = this.context.physics.engine?.raycast(origin, direction);
 * ```
 * @see {@link Rigidbody} for physics simulation component
 * @see {@link Collider} for collision detection component
 * @see {@link RapierPhysics} for physics engine implementation details
 */
export declare class Physics {
    private static _raycasting;
    /**
     * Returns true if raycasting is currently in progress
     */
    static get raycasting(): boolean;
    /**@deprecated use `this.context.physics.engine.raycast` {@link IPhysicsEngine.raycast} */
    raycastPhysicsFast(origin: Vec2 | Vec3, direction?: Vec3 | undefined, maxDistance?: number, solid?: boolean): {
        point: Vector3;
        collider: import("./engine_types.js").ICollider;
        normal?: Vector3;
    } | null;
    /**@deprecated use `this.context.physics.engine.raycastAndGetNormal` {@link IPhysicsEngine.raycastAndGetNormal} */
    raycastPhysicsFastAndGetNormal(origin: Vec2 | Vec3, direction?: Vec3 | undefined, maxDistance?: number, solid?: boolean): {
        point: Vector3;
        collider: import("./engine_types.js").ICollider;
        normal?: Vector3;
    } | null;
    /**@deprecated use this.context.physics.engine.sphereOverlap */
    sphereOverlapPhysics(point: Vector3, radius: number): import("./engine_types.js").ShapeOverlapResult[] | null;
    private readonly context;
    engine?: IPhysicsEngine;
    constructor(context: Context);
    private readonly raycaster;
    private readonly defaultRaycastOptions;
    private readonly targetBuffer;
    private readonly defaultThresholds;
    private sphereResults;
    private sphereMask;
    private readonly sphere;
    /** Test overlapping of a sphere with the threejs geometry. This does not use colliders. This does not return an exact intersection point (intersections returned contain the object and the world position of the object that is being hit)
     * For a more accurate test use the physics engine's collider overlap test (see sphereOverlapPhysics)
     * @param spherePos the center of the sphere in world space
     * @param radius the radius of the sphere
     * @param traverseChildsAfterHit if false it will stop after the first hit. If true it will continue to traverse and add all hits to the result array
     * @param bvh use MeshBVH for raycasting. This is faster than the default threejs raycaster but uses more memory.
     * @param shouldRaycast optional callback to filter objects. Return `false` to ignore the object completely or `"continue in children"` to skip the object but continue to traverse its children (if you do raycast with `recursive` enabled)
     */
    sphereOverlap(spherePos: Vector3, radius: number, traverseChildsAfterHit?: boolean, bvh?: boolean, shouldRaycast?: RaycastTestObjectCallback | null): Array<Intersection>;
    raycastFromRay(ray: Ray, options?: IRaycastOptions | null): Array<Intersection>;
    /** raycast against rendered three objects. This might be very slow depending on your scene complexity.
     * We recommend setting objects to IgnoreRaycast layer (2) when you don't need them to be raycasted.
     * Raycasting SkinnedMeshes is specially expensive.
     * Use raycastPhysics for raycasting against physic colliders only. Depending on your scenario this might be faster.
     * @param options raycast options. If null, default options will be used.
     */
    raycast(options?: IRaycastOptions | null): Array<Intersection>;
    private intersect;
    private tempBoundingBox;
    private intersectSphere;
}
declare module 'three' {
    interface SkinnedMesh {
        staticGenerator?: StaticGeometryGenerator;
        staticGeometry?: BufferGeometry;
        staticGeometryLastUpdate?: number;
    }
    interface Mesh {
        acceleratedRaycast?: any;
    }
    interface SkinnedMesh {
        /** @deprecated use autoUpdateMeshBvhInterval */
        autoUpdateMeshBVH?: boolean;
        /**
         * Interval in milliseconds to automatically update the mesh BVH. When set to >= 0 the BVH will be updated every x milliseconds.
         * @default undefined (disabled)
         */
        autoUpdateMeshBvhInterval?: number;
        bvhNeedsUpdate?: boolean;
    }
}
