copper3d / Modules / Controls/orbitFraming
Module: Controls/orbitFraming
Table of contents
Interfaces
Variables
Functions
Variables
FRAMING_MARGIN
• Const FRAMING_MARGIN: 1.3
Leave ~30% margin so the model does not touch the panel edge while pan/rotating.
Defined in
src/Controls/orbitFraming.ts:35
Functions
computeFraming
▸ computeFraming(box, fovDeg): Framing
Bounding box -> pivot + size + framing distance.
fovDeg is read from the camera by the caller at runtime (copper3d uses 75); it is not hardcoded here.
Parameters
| Name | Type |
|---|---|
box | Box3 |
fovDeg | number |
Returns
Defined in
src/Controls/orbitFraming.ts:66
fitDistance
▸ fitDistance(bounds, aspect, fovDeg, margin?): number
How far a perspective camera must sit from an object's centre for the whole object to fit in frame.
Unlike computeFraming above this takes the viewport's ASPECT into account: below aspect 1 the horizontal field is the narrower of the two, and it is the narrower one that has to contain the object. A camera framed on vertical FOV alone under-frames every tall, narrow viewport.
It also fits the bounding SPHERE rather than the box. Fitting the facing box face plus half the depth frames each object by whichever dimension happens to point at the camera, so a thin slab and a near-cubic volume of similar overall extent come out at wildly different sizes on screen. A sphere has no orientation, so comparable objects get comparable screen size -- and orbiting can no longer push a corner out of frame.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
bounds | FitBounds | undefined | - |
aspect | number | undefined | Viewport width / height. Zero or non-finite is treated as 1: a viewport mid-collapse measures 0 for a frame, and NaN in a projection matrix is unrecoverable. |
fovDeg | number | undefined | The camera's VERTICAL field of view, in degrees. |
margin | number | 0.85 | Multiplier applied at the end, and deliberately BELOW 1. A bounding sphere circumscribes the object -- a cube's has 1.73x its half-side -- so fitting the sphere exactly leaves the object filling well under half the frame. Letting the sphere overflow is what makes the object read at a sensible size. A tuning knob, not a correctness threshold: smaller means larger on screen. |
Returns
number
Defined in
src/Controls/orbitFraming.ts:166
isRotateGesture
▸ isRotateGesture(state): boolean
Whether this gesture is a pure rotate. Used to decide whether to snap the rotation pivot back to the model centre: OrbitControls' pan moves target with the camera, so after a pan target is off the model and a rotate would orbit an empty point. We snap target back on rotate start, but must NOT on pan/dolly (or the model jumps at pan start).
Picking the wrong state constant is a silent bug (rotate not re-pivoting, or pan wrongly re-pivoting), so it is unit-tested.
Parameters
| Name | Type |
|---|---|
state | number |
Returns
boolean
Defined in
src/Controls/orbitFraming.ts:53
resolveFarPlane
▸ resolveFarPlane(presetFar, maxDistance, dist): number
Far clipping plane (decision D2).
The preset's farPlane is 1000, but a large volume's maxDistance (= size*5) can exceed it, which would clip the model when the user zooms all the way out.
The Number.isFinite guard is required: right after construction and before the first frameBox, OrbitControls' maxDistance is still the default Infinity.
Parameters
| Name | Type |
|---|---|
presetFar | number |
maxDistance | number |
dist | number |
Returns
number
Defined in
src/Controls/orbitFraming.ts:114
resolveViewPose
▸ resolveViewPose(preset, pivot, dist): ViewPose
Preset + pivot + distance -> camera pose.
The preset's eyePosition is absolute; only its DIRECTION is taken here, and the distance comes from C5 auto-framing (the implicit 600 in the JSON is ignored).
up must be Gram-Schmidt-orthogonalised against the view direction (decision D1): OrbitControls uses camera.up as its polar axis, and nrrd_view_coronal.json's up (0,1,-1) is not perpendicular to its own view direction (0,1,0) — feeding it raw gives a 45-degree-tilted pole. The old trackball path got away with it only because three's lookAt() orthogonalises internally.
Parameters
| Name | Type |
|---|---|
preset | CameraViewPreset |
pivot | Vector3 |
dist | number |