A Camera3d
is a perspective or orthographic camera in 3D space. This module contains functions
for:
A camera in 3D space, using particular units
(usually meters)
within a particular coordinate system
(generally a user-defined type like WorldCoordinates
).
Defines whether a camera uses perspective or orthographic projection.
Defines the vertical field of view of a camera. Strictly speaking, for a perspective camera the field of view should be defined as an angle and for an orthographic camera it should be defined as a height. Practically speaking, however, it is usually possible (and often useful) to convert between the two.
Given a focal distance it is possible (with a bit of trigonometry) to compute the field of view angle from the field of view height, or vice versa:
All the camera construction functions in this module either compute the focal distance
automatically (e.g. as the distance from an eye point to a focal point), or (in the case of the
with
constructor) require you to provide one explicitly.
As a result, this module allows you to specify field of view as either an angle or a height for either perspective or orthographic cameras, and any necessary conversions will be done automatically.
angle : Angle -> FieldOfView units
Specify vertical field of view as an angle. For an orthographic camera, this will be converted to a height at the camera's focal distance.
height : Quantity Basics.Float units -> FieldOfView units
Specify vertical field of view as a height. For a perspective camera, this will be converted to an angle at the camera's focal distance.
lookAt : { eyePoint : Point3d units coordinates, focalPoint : Point3d units coordinates, upDirection : Direction3d coordinates, projection : Projection, fov : FieldOfView units } -> Camera3d units coordinates
Construct a Camera3d
at the given eye point looking towards the given
focal point, with the given global up direction (which will typically be
Direction3d.positiveZ
or Direction3d.positiveY
). The focal distance will
be computed as the distance from the eye point to the focal point. For
example, to construct a camera at the point (10, 0, 5) looking towards the
origin:
camera =
Camera3d.lookAt
{ eyePoint = Point3d.meters 10 0 5
, focalPoint = Point3d.origin
, upDirection = Direction3d.positiveZ
, projection = Camera3d.Perspective
, fov = Camera3d.angle (Angle.degrees 30)
}
Camera3d.eyePoint camera
--> Point3d.meters 10 0 5
Camera3d.viewDirection camera
--> Direction3d.xz (Angle.degrees -153.43)
That is likely all you need to know but if you are interested in the details and corner cases, read on!
The view direction of the returned camera will point from the eye point to the focal point. The Y direction will be chosen to be as close to the global up direction as possible (the camera will not have any 'roll') and the X direction will point to the right.
If the direction from the eye point to the focal point is parallel to the global up direction (that is, the camera represents looking straight up or straight down) then the X and Y directions will be chosen arbitrarily.
If the given eye point and focal point are coincident (so that there is no well- defined view direction), then the returned camera will have its Y direction set to the global up direction and its X and view directions will be chosen arbitrarily.
orbit : { focalPoint : Point3d units coordinates, groundPlane : SketchPlane3d units coordinates defines, azimuth : Angle, elevation : Angle, distance : Quantity Basics.Float units, projection : Projection, fov : FieldOfView units } -> Camera3d units coordinates
Construct a Camera3d
looking at the given focal point, the given
distance away. The direction from the focal point to the eye point is defined by
the given azimuth and elevation angles, which are with respect to the given
ground plane (the position of the ground plane does not matter, only its
orientation). For example,
Camera3d.orbit
{ focalPoint = Point3d.meters 0 0 1
, groundPlane = SketchPlane3d.xy
, azimuth = Angle.degrees 0
, elevation = Angle.degrees 45
, distance = Length.meters 10
, projection = Camera3d.Perspective
, fov = Camera3d.angle (Angle.degrees 30)
}
is equivalent to
Camera3d.lookAt
{ focalPoint = Point3d.meters 0 0 1
, eyePoint = Point3d.meters 7.071 0 7.071
, upDirection = Direction3d.z
, projection = Camera3d.Perspective
, fov = Camera3d.angle (Angle.degrees 30)
}
As the name suggests, Camera3d.orbit
is useful for making orbiting cameras;
you can orbit around the focal point by changing just the azimuth, and rotate
up and down by changing just the elevation.
orbitZ : { focalPoint : Point3d units coordinates, azimuth : Angle, elevation : Angle, distance : Quantity Basics.Float units, projection : Projection, fov : FieldOfView units } -> Camera3d units coordinates
A special case of orbit
for orbiting around a Z axis through the given
focal point. This corresponds to setting groundPlane
to SketchPlane3d.xy
,
so azimuth is measured from the X axis towards the Y axis and elevation is
measured up from the XY plane. Not related to the classic soft drink.
isometric : { focalPoint : Point3d units coordinates, distance : Quantity Basics.Float units, projection : Projection, fov : FieldOfView units } -> Camera3d units coordinates
Construct a camera looking at the given focal point, the given distance away, such that a set of XYZ axes at that point will appear to have:
isometricElevation : Angle
Not actually a constructor, but a useful value (approximately 35.26 degrees)
to use when constructing cameras using orbit
or orbitZ
: using this as the
elevation
value will result in an isometric camera if
azimuth
is set to 45 degrees. Said another way, this is the elevation angle of
a vector with components (1, 1, 1).
with : { viewPlane : SketchPlane3d units coordinates defines, focalDistance : Quantity Basics.Float units, projection : Projection, fov : FieldOfView units } -> Camera3d units coordinates
Construct a camera directly from:
SketchPlane3d
conceptually aligned with the screenThis corresponds most directly to the internal representation of a Camera3d
and is the most
flexible, but usually also the most akward to use.
eyePoint : Camera3d units coordinates -> Point3d units coordinates
Get the location of a camera.
viewDirection : Camera3d units coordinates -> Direction3d coordinates
Get the direction that a camera is looking in (the direction 'into the screen').
viewPlane : Camera3d units coordinates -> SketchPlane3d units coordinates defines
The view plane of a camera is a SketchPlane3d
where:
frame : Camera3d units coordinates -> Frame3d units coordinates defines
The frame of a camera is a Frame3d
where:
focalDistance : Camera3d units coordinates -> Quantity Basics.Float units
The focal distance of the camera is used to convert between angle-based and height-based field of view. This generally corresponds to the distance from the camera to the object currently being looked at/focused on (which is often also the center of rotation/orbit point for the camera).
projection : Camera3d units coordinates -> Projection
Get the projection type of a camera.
fovAngle : Camera3d units coordinates -> Angle
Get a camera's vertical field of view as an angle. If necessary, this will be computed from a height-based field of view using the camera's focal distance.
fovHeight : Camera3d units coordinates -> Quantity Basics.Float units
Get a camera's vertical field of view as a height. If necessary, this will be computed from an angle-based field of view using the camera's focal distance.
ray : Camera3d units coordinates -> Rectangle2d screenUnits screenCoordinates -> Point2d screenUnits screenCoordinates -> Axis3d units coordinates
Given a camera, a rectangle defining the shape and size of a screen,
and a 2D point within that screen, calculate the corresponding 3D ray as an Axis3d
.
Conceptually, the ray will pass through the given point on the screen and will
have direction equal to the viewing direction at that point.
For a perspective camera, the origin of the ray will be constant (always equal to the camera's eye point) and the direction will vary depending on the 2D screen point. For an orthographic camera, the direction of the ray will be constant (the view direction of the camera) but the origin will vary depending on the 2D screen point.
frustumSlope : Camera3d units coordinates -> Basics.Float
Half the fovAngle
, expressed as a slope instead of an angle. This is useful for
various low-level camera operations such as computing projection matrices.