import { Ray, Vector3, DeepImmutable, BoundingInfo } from '../loader/babylonjs-import';
import { Vertex2 } from '../math';
import { CanvasPosition, PickOption } from '../loader/Selectables';
import { TwinfinityCameraStateSnapshot } from './TwinfinityCameraStateSnapshot';
import { FrustumPlanes } from '../math/Frustum';
import { ShortFrustumProjectionMatrixState } from '../loader/ShortFrustumProjectionMatrixState';
import { PickResult } from '../loader/PickResult';
import { TwinfinityViewer } from '../loader/twinfinity-viewer';
/**
 * Consists of different strings explaining a viewing direction for the camera.
 */
export type CameraDirection = 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right' | 'default';
/**
 * Includes methods and properties used to manipulate a wrapped `TargetCamera` relative a pivot point {@link target}.
 * The point is a point in the world and the pivot plane is a plane defined by that
 * point and the negated `TargetCamera` Z axis normal (the normalized camera forward vector).
 */
export interface TwinfinityCameraPivot {
    /**
     * If `true` then the pivot point cannot be modified. Calling {@link update} will only reorient the pivot plane to face
     * the camera. {@link target} will not be updated.
     */
    isFrozen: boolean;
    /**
     * Normal of the pivot plane.
     */
    readonly normal: DeepImmutable<Vector3>;
    /**
     * Whether the pivot point is visualized or not.
     */
    isVisible: boolean;
    /**
     * Pivot point. It is always located on the pivot plane.
     */
    readonly target: DeepImmutable<Vector3>;
    /**
     * Whether the pivot plane is in front of the camera or not.
     */
    readonly isInFront: boolean;
    /**
     * Closest distance from camera to pivotplane. Will be negative if camera is behind pivot plane
     */
    readonly signedDistanceToCamera: number;
    /**
     * Updates the pivot point {@link target} and the corresponding pivot plane.
     * Also see {@link isFrozen}.
     * @param o Optional. If not specified, the current pivot plane is simply reoriented to face the camera. (plane can be behind camera plane).
     * If specified, it is either a screen space coordinate or a world space coordinate. If a screen space
     * coordinate is used, a ray is shot from the camera through the screen cordinate. If the
     * ray intersects a object, the intersection coordinate is calculated and used as {@link target}.
     * If no intersection is found, the previous pivot plane is reoriented so it faces the
     * camera and a intersection test between the ray and the plane is calculated. If an intersection
     * is found that coordinate is used as {@link target}. If no such intersection could be found (because
     * current pivot plane is behind camera), a new pivot plane is calculated exactly at {@link PivotPlane.DefaultDistanceToPivotPlane}
     * world units in front of the camera. A new {@link target} is then calculated by intersecting
     * the ray from the center of the camera viewport with the plane.
     */
    update(o?: {
        canvasCoordinate: Vertex2;
    } | {
        target: Vector3;
    }): void;
    /**
     * Zooms a camera in or out. Actual camera movement is performed over a series of frames. The camera is animated
     * so we get a smooth visualization.
     * @param delta Value to zoom with. A positive value means zoom in. A negative value means zoom out.
     * @param screenCoordinate Intersects pivot plane with a ray shot through this screen coordinate.
     * Camera is then zoomed towards this coordinate.
     */
    zoom(delta: number, screenCoordinate: Vertex2): void;
    /**
     * Pans camera relative {@link target}.
     * @param currentScreenCoordinate A ray is shot from the camera through this screen coordinate and
     * a intersection with the pivot plane is calculated.
     * The camera is then repositioned according to the following formula
     * this._camera.position.subtractInPlace(currentOnPivotPlane.subtractInPlace(this.target));
     * cameraPos = cameraPos - (intersection - target);
     * @returns `true` if a intersection could be found (camera could be repositioned). Otherwise `false` only
     * happens if current pivotplane is behind the camera.
     */
    pan(currentScreenCoordinate: Vertex2): boolean;
    /**
     * Rotates the camera around {@link target}. Actual rotation of the camera is performed
     * over a series of frames (camera is animated) in order to get a smooth visualization.
     * @param pitch Relative delta pitch in radians
     * @param yaw Relative delta yaw in radians
     */
    rotate(pitch: number, yaw: number): void;
    /**
     * Creates a ray from camera through canvas position specified by `o` and intersect it with the pivot plane
     * and store the resulting coordinate in `dst`.
     * @param dst Holds resulting intersection (if any). Not set if < 0 is returned.
     * @param o Determines which canvas position to shoot intersection ray through.
     * @returns distance to pivot plane along ray. If no intersection can be found then -1.
     */
    intersectWithScreenCoordinateToRef(dst: Vector3, o: CanvasPosition): number;
    /**
     * Zooms camera to the extent of the specified bounding box.
     * @param aabb {@link BoundingInfo}.
     * @param direction Optional {@link CameraDirection}. If specified camera is reoriented according to this. Otherwise camera orientation is kept as is
     */
    zoomToExtent(aabb: BoundingInfo, direction?: CameraDirection): void;
    /**
     * Sets camera rotation to look towards the specified direction and zooms to extent of visible objects.
     * @param direction The direction to look from (top = -Z, bottom = +Z, front = +Y, back = -Y, left = +X, right = -X).
     */
    lookFrom(direction: CameraDirection): void;
}
/**
 * Includes methods and properties for querying and manipulating a {@link Camera} instance.
 */
export interface TwinfinityCameraExtensions {
    /**
     * Gets the distance that the camera has to be positioned at (perpendicular to pivot plane) when in perspective
     * mode to get approximately the same view. The objects in the center
     * of the frustum will appear to have almost the same size.
     */
    readonly perspectiveDistanceFromOrtho: number;
    /**
     * `true` if the camera has somehow moved during this frame. Otherwise `false`. Will automatically be reset to `false` after each frame has rendered (if camera is used by {@link TwinfinityViewer}).
     */
    readonly hasMovedInCurrentFrame: boolean;
    /**
     * Gets a {@link TwinfinityCameraStateSnapshot} instance which can be used to check if a camera has changed since a previous check.
     */
    stateSnapshot(): TwinfinityCameraStateSnapshot;
    /**
     * Sets {@link hasMovedInCurrentFrame} to `false`.
     */
    clearHasMovedInCurrentFrame(): void;
    /**
     * Sets the orthographic frustum based on either `distance` or `height`
     * @param o Sets orthographic frustum based on either `distance` or `height`.
     * If `height` then {@link Camera.orthoBottom} = -`height` / 2 and {@link Camera.orthoTop} is set to `height` / 2. {@link Camera.orthoLeft} and {@link Camera.orthoRight} is then calculated using the aspect ratio.-
     * If `distance` then frustum is sized optimally so a object in center of camera at `distance` will get approx the same size as it would with the perspective camera.
     */
    setOrtho(o: {
        distance: number;
    } | {
        height: number;
    }): void;
    /**
     * Gets the size of the orthographic frustm (defined by {@link Camera.orthoBottom}, {@link Camera.orthoTop}, {@link Camera.orthoLeft}, {@link Camera.orthoRight}).
     * @param dst Size is written here,. `x` is width and `y`i is height.
     * @return `dst`.
     */
    getOrthoFrustumSizeToRef(dst: Vertex2): Vertex2;
    /**
     * Is used by orthographic camera when calculating zoom speed.
     * @param distance Distance to change the orthographic frustum size with.
     * @internal Only for internal use.
     * @returns speed.
     */
    computeOrthographicZoomSpeed(distance: number): number;
    /**
     * Creates a ray from the camera through the screen coordinate defined by `o`.
     * This ray is useful for pick operations.
     * @param dst Ray is written here.
     * @param o Optional. If not specified then the center of the canvas is used.
     */
    createPickingRayToRef(dst: Ray, o: CanvasPosition): Ray;
    /**
     * Performs intersection testing against objects in the scene from the cameras point of view.
     * @param o See {@link PickOption}.
     */
    pick(o: PickOption): PickResult;
    /**
     * Gets the camera frustum planes
     * @param dst Camera frustum planes are written
     * @returns Frustum planes (same reference as `dst`)
     */
    getFrustumToRef(dst: FrustumPlanes): FrustumPlanes;
    /**
     * Gets the camera short frustum state, which is used to render the depth buffer
     * @returns The short frustum state
     * @hidden
     */
    get shortFrustum(): ShortFrustumProjectionMatrixState;
    /**
     * Twinfinity viewer instance.
     */
    get viewer(): TwinfinityViewer | undefined;
}
export interface TwinfinityTargetCameraExtensions extends TwinfinityCameraExtensions {
    /** If `true` then camera acts like a free camera during rotation and rotation is
     *  relative to camera's own axes (first person camera).
     */
    isFreeLook: boolean;
    /**
     * Includes methods and properties for camera manipulation around a pivot plane and point.
     */
    readonly pivot: TwinfinityCameraPivot;
}
declare module '@babylonjs/core/Cameras/camera' {
    interface Camera {
        readonly twinfinity: TwinfinityCameraExtensions;
    }
}
declare module '@babylonjs/core/Cameras/targetCamera' {
    interface TargetCamera {
        readonly twinfinity: TwinfinityTargetCameraExtensions;
    }
}
//# sourceMappingURL=CameraExtensions.d.ts.map