/** This file must only contain pure code and pure imports */
import { type Nullable } from "../types.js";
import { type Scene } from "../scene.pure.js";
import { type AbstractMesh } from "../Meshes/abstractMesh.pure.js";
import { Mesh } from "../Meshes/mesh.pure.js";
import { Matrix, Vector3 } from "../Maths/math.vector.pure.js";
import { type Material } from "../Materials/material.pure.js";
import { StandardMaterial } from "../Materials/standardMaterial.pure.js";
import { type IPhysicsEnginePlugin as IPhysicsEnginePluginV1 } from "../Physics/v1/IPhysicsEnginePlugin.js";
import { type IPhysicsEnginePluginV2, type PhysicsMassProperties } from "../Physics/v2/IPhysicsEnginePlugin.js";
import { PhysicsImpostor } from "../Physics/v1/physicsImpostor.pure.js";
import { UtilityLayerRenderer } from "../Rendering/utilityLayerRenderer.js";
import { type PhysicsBody } from "../Physics/v2/physicsBody.js";
import { type PhysicsConstraint } from "../Physics/v2/physicsConstraint.js";
import { TransformNode } from "../Meshes/transformNode.pure.js";
/**
 * Used to show the physics impostor around the specific mesh
 */
export declare class PhysicsViewer {
    /** @internal */
    protected _impostors: Array<Nullable<PhysicsImpostor>>;
    /** @internal */
    protected _meshes: Array<Nullable<AbstractMesh>>;
    /** @internal */
    protected _bodies: Array<Nullable<PhysicsBody>>;
    /** @internal */
    protected _inertiaBodies: Array<Nullable<PhysicsBody>>;
    /** @internal */
    protected _constraints: Array<Nullable<PhysicsConstraint>>;
    /** @internal */
    protected _bodyMeshes: Array<Nullable<AbstractMesh>>;
    /** @internal */
    protected _inertiaMeshes: Array<Nullable<AbstractMesh>>;
    /** @internal */
    protected _constraintMeshes: Array<Nullable<Array<TransformNode>>>;
    /** @internal */
    protected _scene: Nullable<Scene>;
    /** @internal */
    protected _numMeshes: number;
    /** @internal */
    protected _numBodies: number;
    /** @internal */
    protected _numInertiaBodies: number;
    /** @internal */
    protected _numConstraints: number;
    /** @internal */
    protected _physicsEnginePlugin: IPhysicsEnginePluginV1 | IPhysicsEnginePluginV2 | null;
    protected _renderFunction: () => void;
    protected _inertiaRenderFunction: () => void;
    protected _constraintRenderFunction: () => void;
    protected _utilityLayer: Nullable<UtilityLayerRenderer>;
    protected _ownUtilityLayer: boolean;
    protected _debugBoxMesh: Mesh;
    protected _debugSphereMesh: Mesh;
    protected _debugCapsuleMesh: Mesh;
    protected _debugCylinderMesh: Mesh;
    protected _debugMaterial: StandardMaterial;
    protected _debugInertiaMaterial: StandardMaterial;
    protected _debugMeshMeshes: Mesh[];
    protected _constraintAxesSize: number;
    protected _constraintAngularSize: number;
    /**
     * Creates a new PhysicsViewer
     * @param scene defines the hosting scene
     * @param size Physics V2 size scalar
     * @param utilityLayer The utility layer the viewer will be added to
     */
    constructor(scene?: Scene, size?: number, utilityLayer?: UtilityLayerRenderer);
    /**
     * Updates the debug meshes of the physics engine.
     *
     * This code is useful for synchronizing the debug meshes of the physics engine with the physics impostor and mesh.
     * It checks if the impostor is disposed and if the plugin version is 1, then it syncs the mesh with the impostor.
     * This ensures that the debug meshes are up to date with the physics engine.
     */
    protected _updateDebugMeshes(): void;
    /**
     * Updates the debug meshes of the physics engine.
     *
     * This method is useful for synchronizing the debug meshes with the physics impostors.
     * It iterates through the impostors and meshes, and if the plugin version is 1, it syncs the mesh with the impostor.
     * This ensures that the debug meshes accurately reflect the physics impostors, which is important for debugging the physics engine.
     */
    protected _updateDebugMeshesV1(): void;
    /**
     * Updates the debug meshes of the physics engine for V2 plugin.
     *
     * This method is useful for synchronizing the debug meshes of the physics engine with the current state of the bodies.
     * It iterates through the bodies array and updates the debug meshes with the current transform of each body.
     * This ensures that the debug meshes accurately reflect the current state of the physics engine.
     */
    protected _updateDebugMeshesV2(): void;
    protected _updateInertiaMeshes(): void;
    protected _updateDebugInertia(body: PhysicsBody, inertiaMesh: AbstractMesh): void;
    protected _updateDebugConstraints(): void;
    /**
     * Given a scaling vector, make all of its components
     * 1, preserving the sign
     * @param scaling
     */
    protected _makeScalingUnitInPlace(scaling: Vector3): void;
    protected _updateDebugConstraint(constraint: PhysicsConstraint, parentingMesh: TransformNode): void;
    /**
     * Renders a specified physic impostor
     * @param impostor defines the impostor to render
     * @param targetMesh defines the mesh represented by the impostor
     * @returns the new debug mesh used to render the impostor
     */
    showImpostor(impostor: PhysicsImpostor, targetMesh?: Mesh): Nullable<AbstractMesh>;
    /**
     * Shows a debug mesh for a given physics body.
     * @param body The physics body to show.
     * @returns The debug mesh, or null if the body is already shown.
     *
     * This function is useful for visualizing the physics body in the scene.
     * It creates a debug mesh for the given body and adds it to the scene.
     * It also registers a before render function to update the debug mesh position and rotation.
     */
    showBody(body: PhysicsBody): Nullable<AbstractMesh>;
    /**
     * Shows a debug box corresponding to the inertia of a given body
     * @param body the physics body used to get the inertia
     * @returns the debug mesh used to show the inertia, or null if the body is already shown
     */
    showInertia(body: PhysicsBody): Nullable<AbstractMesh>;
    /**
     * Shows a debug mesh for a given physics constraint.
     * @param constraint the physics constraint to show
     * @returns the debug mesh, or null if the constraint is already shown
     */
    showConstraint(constraint: PhysicsConstraint): Nullable<TransformNode>;
    /**
     * Hides an impostor from the scene.
     * @param impostor - The impostor to hide.
     *
     * This method is useful for hiding an impostor from the scene. It removes the
     * impostor from the utility layer scene, disposes the mesh, and removes the
     * impostor from the list of impostors. If the impostor is the last one in the
     * list, it also unregisters the render function.
     */
    hideImpostor(impostor: Nullable<PhysicsImpostor>): void;
    /**
     * Hides a body from the physics engine.
     * @param body - The body to hide.
     * @returns true if body actually removed
     *
     * This function is useful for hiding a body from the physics engine.
     * It removes the body from the utility layer scene and disposes the mesh associated with it.
     * It also unregisters the render function if the number of bodies is 0.
     * This is useful for hiding a body from the physics engine without deleting it.
     */
    hideBody(body: Nullable<PhysicsBody>): boolean;
    /**
     * Hides a body's inertia from the viewer utility layer
     * @param body the body to hide
     * @returns true if inertia actually removed
     */
    hideInertia(body: Nullable<PhysicsBody>): boolean;
    /**
     * Hide a physics constraint from the viewer utility layer
     * @param constraint the constraint to hide
     */
    hideConstraint(constraint: Nullable<PhysicsConstraint>): void;
    protected _getDebugMaterial(scene: Scene): Material;
    protected _getDebugInertiaMaterial(scene: Scene): Material;
    protected _getDebugAxisColoredMaterial(axisNumber: number, scene: Scene): Material;
    protected _getDebugBoxMesh(scene: Scene): AbstractMesh;
    protected _getDebugSphereMesh(scene: Scene): AbstractMesh;
    protected _getDebugCapsuleMesh(scene: Scene): AbstractMesh;
    protected _getDebugCylinderMesh(scene: Scene): AbstractMesh;
    protected _getDebugMeshMesh(mesh: Mesh, scene: Scene): AbstractMesh;
    protected _getDebugMesh(impostor: PhysicsImpostor, targetMesh?: Mesh): Nullable<AbstractMesh>;
    /**
     * Creates a debug mesh for a given physics body
     * @param body The physics body to create the debug mesh for
     * @returns The created debug mesh or null if the utility layer is not available
     *
     * This code is useful for creating a debug mesh for a given physics body.
     * It creates a Mesh object with a VertexData object containing the positions and indices
     * of the geometry of the body. The mesh is then assigned a debug material from the utility layer scene.
     * This allows for visualizing the physics body in the scene.
     */
    protected _getDebugBodyMesh(body: PhysicsBody): Nullable<AbstractMesh>;
    protected _getMeshDebugInertiaMatrixToRef(massProps: PhysicsMassProperties, matrix: Matrix): Matrix;
    protected _getDebugInertiaMesh(body: PhysicsBody): Nullable<AbstractMesh>;
    protected _getTransformFromBodyToRef(body: PhysicsBody, matrix: Matrix, instanceIndex?: number): Matrix;
    protected _createAngularConstraintMesh(minLimit: number, maxLimit: number, axisNumber: number, parent: TransformNode, scene: Scene): TransformNode;
    protected _createCage(parent: TransformNode, scene: Scene): AbstractMesh;
    protected _getDebugConstraintMesh(constraint: PhysicsConstraint): Nullable<Array<TransformNode>>;
    /**
     * Clean up physics debug display
     */
    dispose(): void;
}
