/** * Canonical camera data types for serialization and events. * Used by OrbitControls, CameraControls, and other components that emit camera events. */ /** Base camera data common to all camera types */ export interface BaseCameraData { /** @dial-ignore */ type: string; /** * Position of the camera in 3D space * @dial transform * @dial-layout grid * @dial-cols 2 * @dial-dtype vector3 * @dial-step 0.1 */ position: [number, number, number]; /** * Rotation of the camera in Euler angles * @dial transform * @dial-dtype euler * @dial-step 0.01 */ rotation: [number, number, number]; /** * Quaternion representation of rotation * @dial-ignore */ quaternion: [number, number, number, number]; /** @dial-ignore */ matrix: number[]; /** * Near clipping plane distance * @dial camera * @dial-dtype number * @dial-min 0.001 * @dial-max 100 * @dial-step 0.001 */ near: number; /** * Far clipping plane distance * @dial camera * @dial-dtype number * @dial-min 1 * @dial-max 10000 * @dial-step 1 */ far: number; /** * Zoom level * @dial camera * @dial-dtype number * @dial-min 0.1 * @dial-max 10 * @dial-step 0.1 */ zoom: number; /** * Viewport height in pixels * @dial-ignore */ height: number; /** * Viewport width in pixels * @dial-ignore */ width: number; } /** Perspective camera specific data */ export interface PerspectiveCameraData extends BaseCameraData { type: 'perspective'; /** * Field of view in degrees (vertical FOV) * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype number * @dial-min 1 * @dial-max 179 * @dial-step 0.1 */ fov: number; /** * Aspect ratio (width/height) * @dial camera * @dial-dtype number * @dial-min 0.1 * @dial-max 10 * @dial-step 0.01 */ aspect: number; /** @dial-ignore */ focus: number; /** @dial-ignore */ filmGauge: number; /** @dial-ignore */ filmOffset: number; } /** Orthographic camera specific data */ export interface OrthographicCameraData extends BaseCameraData { type: 'orthographic'; /** * Left plane position (frustum boundary) * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype number * @dial-min -100 * @dial-max 0 * @dial-step 0.1 */ left: number; /** * Right plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min 0 * @dial-max 100 * @dial-step 0.1 */ right: number; /** * Top plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min 0 * @dial-max 100 * @dial-step 0.1 */ top: number; /** * Bottom plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min -100 * @dial-max 0 * @dial-step 0.1 */ bottom: number; } /** Fisheye camera specific data */ export interface FisheyeCameraData extends BaseCameraData { type: 'fisheye'; /** @dial-ignore */ fov: 180; /** @dial-ignore */ aspect: 1; /** * Number of segments for the frustum visualization * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype int * @dial-min 16 * @dial-max 256 * @dial-step 1 */ segments: number; } /** Union type for all camera data */ export type CameraData = PerspectiveCameraData | OrthographicCameraData | FisheyeCameraData | BaseCameraData; /** Base transform props shared by all cameras */ export interface CameraTransformProps { /** * Position of the camera in 3D space * @dial transform * @dial-layout grid * @dial-cols 2 * @dial-dtype vector3 * @dial-step 0.1 */ position?: [number, number, number]; /** * Rotation of the camera in Euler angles * @dial transform * @dial-dtype euler * @dial-step 0.01 */ rotation?: [number, number, number]; } /** Base clipping plane props shared by all cameras */ export interface CameraClipProps { /** * Near clipping plane distance * @dial camera * @dial-dtype number * @dial-min 0.001 * @dial-max 100 * @dial-step 0.001 */ near?: number; /** * Far clipping plane distance * @dial camera * @dial-dtype number * @dial-min 1 * @dial-max 10000 * @dial-step 1 */ far?: number; } /** Base display props shared by all cameras */ export interface CameraDisplayProps { /** * Hide the camera view completely * @dial render * @dial-dtype boolean */ hide?: boolean; /** * Show the frustum visualization * @dial appearance * @dial-layout grid * @dial-cols 2 * @dial-dtype boolean */ showFrustum?: boolean; } /** Base render/preview props shared by all cameras */ export interface CameraRenderProps { /** * Show preview plane in 3D scene (follows camera) * @dial render * @dial-layout grid * @dial-cols 2 * @dial-dtype boolean */ previewInScene?: boolean; /** * Show preview in overlay (bottom-left corner) * @dial render * @dial-dtype boolean */ previewInOverlay?: boolean; /** * Preview texture height resolution in pixels * @dial render * @dial-dtype int * @dial-min 64 * @dial-max 2048 * @dial-step 64 */ renderSizeH?: number; /** * MSAA samples for anti-aliasing (1 = no AA, 4 = good quality, 8 = high quality) * @dial render * @dial-dtype int * @dial-min 1 * @dial-max 8 * @dial-step 1 */ samples?: number; /** * Enable depth buffer for the render target * @dial render * @dial-dtype boolean */ depthBuffer?: boolean; /** * Show camera helpers from other virtual cameras * @dial render * @dial-dtype boolean */ showCameraHelpers?: boolean; /** * Distance from camera to preview plane in scene units (meters) * @dial appearance * @dial-dtype number * @dial-min 0.1 * @dial-max 100 * @dial-step 0.1 */ previewDistance?: number; /** * Use SparkViewpoint for rendering preview (supports 3DGS/Gaussian Splatting). * When true, uses SparkViewpoint's internal render target for proper 3DGS sorting. * When false, uses legacy useFBO mode with standard WebGL rendering. * @dial render * @dial-dtype boolean * @default true */ useViewpoint?: boolean; /** * Background color for the camera preview * @dial appearance * @dial-dtype color */ previewBackgroundColor?: string; /** * Background opacity for the camera preview (0-1) * @dial appearance * @dial-dtype number * @dial-min 0 * @dial-max 1 * @dial-step 0.01 */ previewBackgroundOpacity?: number; } /** Perspective camera specific props */ export interface PerspectiveCameraSpecificProps { /** * Field of view in degrees (vertical FOV) * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype number * @dial-min 1 * @dial-max 179 * @dial-step 0.1 */ fov?: number; /** * Aspect ratio (width/height) * @dial camera * @dial-dtype number * @dial-min 0.1 * @dial-max 10 * @dial-step 0.01 */ aspect?: number; /** * Zoom level * @dial camera * @dial-dtype number * @dial-min 0.1 * @dial-max 10 * @dial-step 0.1 */ zoom?: number; } /** Orthographic camera specific props */ export interface OrthographicCameraSpecificProps { /** * Left plane position (frustum boundary) * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype number * @dial-min -100 * @dial-max 0 * @dial-step 0.1 */ left?: number; /** * Right plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min 0 * @dial-max 100 * @dial-step 0.1 */ right?: number; /** * Top plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min 0 * @dial-max 100 * @dial-step 0.1 */ top?: number; /** * Bottom plane position (frustum boundary) * @dial camera * @dial-dtype number * @dial-min -100 * @dial-max 0 * @dial-step 0.1 */ bottom?: number; /** * Zoom level * @dial camera * @dial-dtype number * @dial-min 0.01 * @dial-max 100 * @dial-step 0.1 */ zoom?: number; } /** Fisheye camera specific props */ export interface FisheyeCameraSpecificProps { /** * Number of segments for the frustum visualization * @dial camera * @dial-layout grid * @dial-cols 2 * @dial-dtype int * @dial-min 16 * @dial-max 256 * @dial-step 1 */ segments?: number; }