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 }
Page created: 2007-12-23