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

SCM Repository

[sml3d] View of /src/common/vec3d.sml
ViewVC logotype

View of /src/common/vec3d.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 109 - (download) (annotate)
Fri May 2 14:41:16 2008 UTC (11 years, 6 months ago) by jhr
File size: 4573 byte(s)
  Change lenghtAndDir to return the zero vector on small vectors.
(* vec3d.sml
 *
 * COPYRIGHT (c) 2006 John Reppy (http://www.cs.uchicago.edu/~jhr)
 * All rights reserved.
 *
 * Operations on vectors in R^3 (double version)
 *)

structure Vec3d : sig

    type double = Double.double

    type vec3d = {x : double, y : double, z : double}
    type vec4d = {x : double, y : double, z : double, w : double}

    val unpack : vec3d -> (double * double * double)
    val pack   : (double * double * double) -> vec3d
    val toList : vec3d -> double list

  (* functional update *)
    val setX : vec3d * double -> vec3d
    val setY : vec3d * double -> vec3d
    val setZ : vec3d * double -> vec3d

    val nth : vec3d * int -> double

  (* lift a 3D vector into homogeneous space *)
    val vector : vec3d -> vec4d
    val point : vec3d -> vec4d

    val zero : vec3d

  (* standard basis vectors *)
    val e1 : vec3d
    val e2 : vec3d
    val e3 : vec3d

    val toString : vec3d -> string

    val neg : vec3d -> vec3d
    val add : (vec3d * vec3d) -> vec3d
    val sub : (vec3d * vec3d) -> vec3d
    val mul : (vec3d * vec3d) -> vec3d

    val scale : (double * vec3d) -> vec3d

  (* adds (u, s, v) = u + s*v *)
    val adds : (vec3d * double * vec3d) -> vec3d

  (* lerp (u, t, v) = (1-t)*u + t*v; we assume that 0 <= t <= 1 *)
    val lerp : (vec3d * double * vec3d) -> vec3d

    val dot : (vec3d * vec3d) -> double
    val cross : (vec3d * vec3d) -> vec3d
    val normalize : vec3d -> vec3d
    val length : vec3d -> double
    val lengthSq : vec3d -> double			(* length squared *)
    val lengthAndDir : vec3d -> (double * vec3d)	(* length and normal vector *)
    val distanceSq : (vec3d * vec3d) -> double		(* distance squared *)
    val distance : (vec3d * vec3d) -> double		(* distance between points *)
    val clipLength : (vec3d * double) -> vec3d

  (* return the parallel and perpendicular components of a vector v relative to a
   * unit basis vector.
   *)
    val parallelComponent : {basis : vec3d, v : vec3d} -> vec3d
    val perpendicularComponent : {basis : vec3d, v : vec3d} -> vec3d

  (* iterators *)
    val map : (double -> 'a) -> vec3d -> {x : 'a, y : 'a, z : 'a}
    val app : (double -> unit) -> vec3d -> unit

  (* rays *)
    type rayf = {orig : vec3d, dir : vec3d}

    val rayToPoint : (rayf * double) -> vec3d

  end = struct

    type double = Double.double

    val epsilon : double = 1.0e~7

    type vec3d = {x : double, y : double, z : double}

    type vec4d = {x : double, y : double, z : double, w : double}

    open Vec3

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

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

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

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

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

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

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

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

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

    fun adds (v1, s, v2) = add(v1, scale(s, v2))

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

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

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

    fun lengthSq v = dot(v, v)
    fun length v = Double.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 / Double.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 rayf = {orig : vec3d, dir : vec3d}

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

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0