3D Graphics Math Code Snippets

Some useful bits of common code used in 3d graphics software. These are mostly random pieces of code. I tried to keep it clean and simple for the fellow math-impaired. You are free to copy this as you wish.

For a more in-depth reference, visit the excelent website Euclidean Space.

Constants

Some constants that may be used in some functions.
#define PI 3.14159265
#define RADTODEG (180 / PI) // multiply with this to convert radians to degrees
#define DEGTORAD (PI / 180) // multiply with this to convert degrees to radians

Structures

Below are some structures used throughout the functions on this page. You may want to expand some of them to classes and turn the individual functions into class members. Some functions on this page rely on overloaded operators which, which I will leave to your imagination.
// two dimensional vector
struct float2
{
 float x;
 float y;
};

// three dimensional vector
struct float3
{
 float x;
 float y;
 float z;
};

// four dimensional vector
struct float4
{
 float x;
 float y;
 float z;
 float w;
};

Linear Interpolation

float Lerp(float a, float b, float t)
{
 return a + (b - a) * t;
}

Distance

Returns the square distance between two points.
// two dimensional
float Distance(float2 a, float2 b)
{
 return sqrt( ((a.x - b.x) * (a.x - b.x)) +
              ((a.y - b.y) * (a.y - b.y)) );
}

// three dimensional
float Distance(float3 a, float3 b)
{
 return sqrt( ((a.x - b.x) * (a.x - b.x)) +
              ((a.y - b.y) * (a.y - b.y)) +
              ((a.z - b.z) * (a.z - b.z)) );
}

Magnitude

Returns the length of a vector.
float Magnitude(float3 v)
{
 return sqrt( (v.x * v.x) + (v.y * v.y) + (v.z * v.z) );
}

Normalize

Normalizes a vector to unit space. The length (or magnitude) of the resulting normal will be exactly 1.0.
float3 Normalize(float3 v)
{
 float m = Magnitude(vec);
 if (m == 0) return vec; // escape division by zero
 return (vec / m);
}

Dot Product

Sometimes also known as Inner Product.
// two dimensional
float DotProduct(float2 a, float2 b)
{
 return (a.x * b.x) + (a.y * b.y);
}

// three dimensional
float DotProduct(float3 a, float3 b)
{
 return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}

Cross Product

float3 CrossProduct(float3 a, float3 b)
{
 return float3( (a.y * b.z) - (a.z * b.y),
                (a.z * b.x) - (a.x * b.z),
                (a.x * b.y) - (a.y * b.x) );
}
Note: a two-dimensional cross product does not exist!

Vector-Plane Reflection

Returns the reflection of vector v on a plane represented by plane normal n.
float3 Reflect(float3 v, float3 n)
{
 return 2 * -DotProduct(v,n) * n + v;
}

Angle Between Vectors

Returns the angle between two vectors in radians.
float AngleBetweenVectors(float3 v1, float3 v2)
{
 return acos( DotProduct(Normalize(v1), Normalize(v2)) );
}

Random Numbers

Useful function that returns a random floating point number.
#include <stdlib.h> // RAND_MAX is defined there

// returns random number in range 0.0 to 1.0
float Randf()
{
 return (float)(rand() % RAND_MAX) / RAND_MAX;
}

// returns random value in range
float Randf(float min, float max)
{
 return min + (Randf()*(max-min));
}

Random Point In Circle (Uniform Distribution)

Returns a random point inside a circle positioned at the origin.
float2 RandomPointInCircle(float radius)
{
 float q = Randf() * (PI * 2);
 float r = sqrt(Randf());
 float2 t;
 t.x = (radius * r) * cos(q);
 t.y = (radius * r) * sin(q);
 return t;
}

Point In Sphere Test

Returns whether a point lies inside a sphere.
 center is the center of the sphere
 radius is the sphere radius
 pos is the point
bool SphereTest(float3 center, float radius, float3 pos)
{
 float3 t = (pos - center);
 return ((t.x * t.x) + (t.y * t.y) + (t.z * t.z) - (radius * radius)) < 0.0;
}
Notice the lack of a square root. This is faster than computing a distance.

Surface Normal Generation

Returns the triangle surface normal (clockwise vertex winding).
float3 Normal(float3 v1, float3 v2, float3 v3)
{
 return Normalize( CrossProduct(v3 - v1, v2 - v1) );
}

Point Inside Triangle

Returns whether point lies inside 2D triangle (clockwise vertex winding).
bool InsideTriangle(float2 v1, float2 v2, float2 v3, float2 p)
{
 if ((p.x - v1.x) * (v2.y - v1.y) - (p.y - v1.y) * (v2.x - v1.x) > 0) return false;
 if ((p.x - v2.x) * (v3.y - v2.y) - (p.y - v2.y) * (v3.x - v2.x) > 0) return false;
 if ((p.x - v3.x) * (v1.y - v3.y) - (p.y - v3.y) * (v1.x - v3.x) > 0) return false;
 return true;
}

Triangle Surface Area

Returns the surface area of a 3D triangle.
float TriangleArea(float3 v1, float3 v2, float3 v3)
{
 float d1 = Magnitude(v1 - v2);
 float d2 = Magnitude(v2 - v3);
 float d3 = Magnitude(v3 - v1);
 float h = (d1 + d2 + d3) * 0.5;
 return sqrt(h * (h - d1) * (h - d2) * (h - d3));
}

Triangle Point Height

Returns the height of a point over a triangle. This is useful for terrain collision detection.
 v1,v2,v3 are the triangle vertices
 x,z are the coordinates of the point over the triangle
The returned value is the height component (y) of the coordinates at [x,z].
float TrianglePointHeight(float3 v1, float3 v2, float3 v3, float x, float z)
{
 float q = (v2.x - v1.x) * (v3.z - v1.z) - (v3.x - v1.x) * (v2.z - v1.z);
 if (q == 0) return v1.y;
 float q = 1.0 / q;
 float u = q * ((v2.x - x) * (v3.z - z) - (v3.x - x) * (v2.z - z));
 float v = q * ((v3.x - x) * (v1.z - z) - (v1.x - x) * (v3.z - z));
 float w = q * ((v1.x - x) * (v2.z - z) - (v2.x - x) * (v1.z - z));
 return (u * v1.y) + (v * v2.y) + (w * v3.y);
}
Note: y is the vertical axis here.

Texture Coordinate To World Space Position

Returns the world position of a point (in texture coordinate space) on the triangle.
 v1,v2,v3 are the triangle vertices
 t1,t2,t3 are the triangle texture coordinates
 p is the coordinate in texture coordinate space
This code is useful to implement a lightmap renderer.
float3 TexcoordToPos(float3 v1, float3 v2, float3 v3,
                     float2 t1, float2 t2, float2 t3,
                     float2 p)
{
 float i = 1 / ((t2.x - t1.x) * (t3.y - t1.y) - (t2.y - t1.y) * (t3.x - t1.x));
 float s = i * ( (t3.y - t1.y) * (p.x - t1.x) - (t3.x - t1.x) * (p.y - t1.y));
 float t = i * (-(t2.y - t1.y) * (p.x - t1.x) + (t2.x - t1.x) * (p.y - t1.y));
 float3 r;
 r.x = v1.x + s * (v2.x - v1.x) + t * (v3.x - v1.x);
 r.y = v1.y + s * (v2.y - v1.y) + t * (v3.y - v1.y);
 r.z = v1.z + s * (v2.z - v1.z) + t * (v3.z - v1.z);
 return r;
}
Note: The upper left corner in texture coordinate space is [0,1]. That means the textures are essentially flipped vertically. Most 3d graphics software use this convention, as most digital images are stored upside down.

Distance From Line To Point

Returns minimum distance between line segment and a point.
float PointLineDist(float3 p, float3 v1, float3 v2)
{
 float len = Distance(v1, v2);                  // measure line length
 if (len == 0.0) return Distance(p, v1);        // line is infinitely short
 float w = DotProduct(p - v1, v2 - v1) / len;   // compute 'weight' on line
 if (w < 0.0) return Distance(p, v1);           // beyond v1
 if (w > 1.0) return Distance(p, v2);           // beyond v2
 float3 proj = v1 + w * (v2 - v1);              // project point to segment
 return Distance(p, proj);                      // return distance between points
}
Email: martijn AT bytehazard DOT com
Page created: 2007-12-23