Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
 Summary Activity SCM

# SCM Repository

[sml3d] View of /trunk/sml3d/src/base/common/vec3d.sml
 [sml3d] / trunk / sml3d / src / base / common / vec3d.sml

# View of /trunk/sml3d/src/base/common/vec3d.sml

Fri Jan 22 02:37:06 2010 UTC (9 years, 3 months ago) by jhr
File size: 3242 byte(s)
```  Migrating 4D vector modules to use VEC4 signature
```
```(* vec3.sml
*
* COPYRIGHT (c) 2006 John Reppy (http://www.cs.uchicago.edu/~jhr)
*
* Operations on vectors in R^3 (flt version)
*)

structure Vec3d : VEC3 where type flt = Double.flt =
struct

structure Flt = Double

type flt = Flt.flt

val epsilon = Flt.epsilon
val slerpTolerance = 0.999

type vec3 = {x : flt, y : flt, z : flt}

type vec4 = {x : flt, y : flt, z : flt, w : flt}

open Vec3

(* lift a 3D vector into homogeneous space *)
fun vector {x, y, z} : vec4 = {x=x, y=y, z=z, w=0.0}
fun point {x, y, z} : vec4 = {x=x, y=y, z=z, w=1.0}

val zero : vec3 = {x=0.0, y = 0.0, z = 0.0}

val e1 : vec3 = {x = 1.0, y = 0.0, z = 0.0}
val e2 : vec3 = {x = 0.0, y = 1.0, z = 0.0}
val e3 : vec3 = {x = 0.0, y = 0.0, z = 1.0}

fun toString ({x, y, z} : vec3) = concat[
"<", Flt.toString x, ",", Flt.toString y, ",", Flt.toString z, ">"
]

fun neg ({x, y, z} : vec3) = {x = ~x, y = ~y, z = ~z}

fun add ({x=x1, y=y1, z=z1} : vec3, {x=x2, y=y2, z=z2}) =
{x=x1+x2, y=y1+y2, z=z1+z2}

fun sub ({x=x1, y=y1, z=z1} : vec3, {x=x2, y=y2, z=z2}) =
{x=x1-x2, y=y1-y2, z=z1-z2}

fun mul ({x=x1, y=y1, z=z1} : vec3, {x=x2, y=y2, z=z2}) =
{x=x1*x2, y=y1*y2, z=z1*z2}

fun scale (s, {x, y, z} : vec3) = {x = s*x, y = s*y, z = s*z}

fun abs {x, y, z} = {x = Flt.abs x, y = Flt.abs y, z = Flt.abs z}
fun min ({x=x1, y=y1, z=z1}, {x=x2, y=y2, z=z2}) =
{x = Flt.min(x1, x2), y = Flt.min(y1, y2), z = Flt.min(z1, z2)}
fun max ({x=x1, y=y1, z=z1}, {x=x2, y=y2, z=z2}) =
{x = Flt.max(x1, x2), y = Flt.max(y1, y2), z = Flt.max(z1, z2)}

fun dot ({x=x1, y=y1, z=z1} : vec3, {x=x2, y=y2, z=z2}) =
(x1*x2 + y1*y2 +z1*z2)

fun lerp (v1, t, v2) = adds (scale(1.0-t, v1), t, v2)

(* spherical interpolation between unit vectors *)
fun slerp (v1, t, v2) = let
val cosAngle = dot(v1, v2)
in
if (cosAngle < slerpTolerance)
then let
val angle = Flt.acos cosAngle
val recipSinAngle = 1.0 / Flt.sin angle
val scale1 = recipSinAngle * Flt.sin((1.0 - t) * angle)
val scale2 = recipSinAngle * Flt.sin(t * angle)
in
end
else lerp(v1, t, v2)
end

fun cross ({x=x1, y=y1, z=z1} : vec3, {x=x2, y=y2, z=z2}) = {
x = y1*z2 - z1*y2,
y = z1*x2 - x1*z2,
z = x1*y2 - y1*x2
}

fun lengthSq v = dot(v, v)
fun length v = Flt.sqrt(lengthSq v)

fun distanceSq (u, v) = lengthSq (sub (u, v))
fun distance (u, v) = length (sub (u, v))

fun lengthAndDir v = let
val l = length v
in
if (l < epsilon)
then (0.0, zero)
else (l, scale(1.0 / l, v))
end

fun normalize v = #2(lengthAndDir v)

fun clipLength (v, maxLen) = let
val lenSq = lengthSq v
in
if (lenSq < maxLen*maxLen)
then v
else scale(maxLen / Flt.sqrt lenSq, v)
end

fun parallelComponent {basis, v} = scale(dot(basis, v), basis)

fun perpendicularComponent {basis, v} = sub(v, parallelComponent {basis=basis, v=v})

(* rays *)
type ray = {orig : vec3, dir : vec3}

fun rayToPoint ({orig, dir}, s) = adds(orig, s, dir)

end
```