Table of Contents
Doubles
Every type has a counterpart of doubles: dvec2, dvec3 and dvec4,
dmat3, dmat3x2 and dmat4, and dquat, specialised arrays of double
floats. Every function has one for them too, named with each type's d:
dvec3+, dmat4*, dmat4*dvec4, dmat4-from-dquat, dquat-slerp, and
the batches dmat4*-batch and dmat4-transform-points over a
double-array. The two precisions are defined from one source, so they
cannot drift apart.
(gm:dvec3+ (gm:make-dvec3 :x 1 :y 2 :z 3) (gm:make-dvec3 :x 4 :y 5 :z 6))
;; => #(5.0d0 7.0d0 9.0d0)
(gm:radians 180d0) ; => 3.141592653589793d0
What doubles are for
Single floats are a metre apart 10,000 km from the origin; doubles there are 2 nanometres apart. A renderer keeps positions in doubles and gives the GPU floats relative to the camera, subtracted in doubles first, as Unreal's translated world space does:
(let ((position (gm:make-dvec3 :x 1d7)) ; 10,000 km out
(camera (gm:make-dvec3 :x (- 1d7 0.25d0)))) ; a quarter of a metre away
(gm:vec3-from-dvec3 (gm:dvec3- position camera))) ; what the GPU gets
;; => #(0.25 0.0 0.0)
Done in single floats, the same subtraction gives #(0.0 0.0 0.0).
Components
A dvec3's components, dvec3-x and so on, are doubles, so setf writes
them with doubles:
(let ((position (gm:make-dvec3 :x 1 :y 2 :z 3)))
(setf (gm:dvec3-x position) 1d0) ; not 1.0, a single float
position)
;; => #(1.0d0 2.0d0 3.0d0)
The constructors take any reals, as those of single floats do. mref
takes a matrix of either precision, and radians and degrees give a
double for a double.
Between precisions
dvec3-from-vec3 and its kin, one for each type, convert exactly, and
vec3-from-dvec3 and its kin round each component to the nearest single
float:
(gm:dvec3-from-vec3 (gm:make-vec3 :x 0.1)) ; => #(0.10000000149011612d0 0.0d0 0.0d0)
(gm:vec3-from-dvec3 (gm:make-dvec3 :x 0.1d0)) ; => #(0.1 0.0 0.0)
The single float nearest 0.1 is 0.10000000149011612, which a double holds exactly.
Allocation
The functions of doubles allocate nothing, as those of single floats do: those that return a number are inline, as SBCL boxes a double that leaves a function.