Last modified 20 August 2003 by jdavis@math.wisc.edu

SMKUtilities

The SMea Kit Utilities are a motley assortment of C functions, collected ad hoc as they are needed. First we have a plethora of functions to handle three-dimensional vectors, in both double- and single-precision versions:

inline void SMKMakeVector(double x, double y, double z, double *result);
inline void SMKMakeFloatVector(float x, float y, float z, float *result);

Sets the components of the vector result to those indicated.

inline void SMKCopyVector(double *v, double *result);
inline void SMKCopyFloatVector(float *v, float *result);

Copies v to result. The output may alias the input.

inline void SMKAddVectors(double *v, double *w, double *result);
inline void SMKAddFloatVectors(float *v, float *w, float *result);

Computes result = v + w. The inputs may alias the output and each other.

inline void SMKSubtractVectors(double *v, double *w, double *result);
inline void SMKSubtractFloatVectors(float *v, float *w, float *result);

Computes result = v - w. The inputs may alias the output and each other.

inline void SMKScaleVector(double *v, double scalar, double *result);
inline void SMKScaleFloatVector(float *v, float scalar, float *result);

Computes result = scalar * v. The output may alias the input.

void SMKCrossVectors(double *v, double *w, double *result);
void SMKCrossFloatVectors(float *v, float *w, float *result);

Computes the cross product result = v x w. The output may not alias the input.

inline double SMKDotVectors(double *v, double *w);
inline float SMKDotFloatVectors(float *v, float *w);

Returns the dot product of v and w, which may alias each other.

double SMKNormalizeVector(double *v, double *result);
float SMKNormalizeFloatVector(float *v, float *result);

Rescales the vector v to length 1, storing the result in result and returning the original length of v. If this length is 0, then rescaling was impossible. The output may alias the input.

int SMKProjectVectorOntoVector(double *v, double *w, double *result);
int SMKProjectFloatVectorOntoVector(float *v, float *w, float *result);

Projects the first vector onto the second, returning true if and only if it is successful (that is, if and only if the second vector is nonzero). The inputs may alias the output and each other.

int SMKProjectVectorOntoPlane(double *v, double *w, double *result);
int SMKProjectFloatVectorOntoPlane(float *v, float *w, float *result);

Projects the first vector onto the plane perpendicular to the second, returning true if and only if it is successful (that is, if and only if the second vector is nonzero). The output may alias the second input, but not the first.

This function rotates one vector about another:

void SMKRotateVectorAboutAxis(double *v, double *axis, double angle, double *result);

Rotates the vector about the axis through the specified angle. The axis must be a unit vector. The angle is given in radians, counterclockwise about the axis, according to the right-hand rule. The output may alias the input vector, but not the axis.

The next function inverts any invertible 3x3 matrix. The inverse is computed as the quotient of the adjoint and the determinant; this process is quite fast.

int SMKInvertMatrix(double *col0, double *col1, double *col2, double *inv0, double *inv1, double *inv2);

Inverts the 3x3 matrix with columns col0, col1, and col2, placing the inverse matrix in the columns inv0, inv1, and inv2 and returning true if and only if the original matrix was invertible. The input is left unaltered; it cannot alias the output.

The next three functions solve systems of equations that arise frequently in computer graphics.

int SMKSolveQuadratic(double a, double b, double c, double *result1, double *result2);

Finds the real roots of the quadratic polynomial ax2 + bx + c, returning the number of distinct roots. If this number is 1, then result2 is left unaltered; if it's 0, then result1 is left unaltered as well. If two distinct solutions are returned, then result1 is less than result2.

int SMKIntersectLineAndSphere(double *a, double *b, double *center, double radiusSquared, double *result1, double *result2);

Intersects the line through a and b with the sphere centered at center with radius squared radiusSquared, storing the intersection points in the vectors result1 and result2 and returning the number of distinct solutions. If this number is 1, then result2 is left unaltered; if it's 0, then result1 is left unaltered as well. If two distinct solutions are returned, then result1 is "less than" result2, in the sense that the line is oriented so that a is "less than" b. The outputs may not alias a.

int SMKIntersectLineAndPlane(double *a, double *b, double *point, double *normal, double *result);

Intersects the line through a and b with the plane through point with normal vector normal (which need not be length 1); stores the intersection point in the vector result and returns true if and only if it is successful. The output may not alias a.

The next few utilities can be handy when you're dealing with angles. Recall that all angles are in radians in the SMea Kit.

double SMKArcSin(double x);

Clamps x to [-1, 1] and computes the inverse sine.

double SMKArcCos(double x);

Clamps x to [-1, 1] and computes the inverse cosine.

double SMKArcSinCos(double sine, double cosine);

Computes an angle, given its sine and cosine.

double SMKAngleWithoutCut(double a, double b);

Given two angles a and b in [0, 2pi), returns an angle in (-pi, 3pi) equivalent to b but such that there is no cut (on the shorter arc of the unit circle) between a and b. In other words, a - SMKAngleWithoutCut(a, b) gives the angle between b and a.

It is sometimes useful to be able to convert between cartesian and spherical coordinates. While spherical coordinates are typically called (rho, theta, phi), the SMea Kit calls them (distance, azimuth, elevation). SMKNormalizeVector computes the distance, and SMKGetAzimuthAndElevation computes the angles. Another function, SMKGetElevationAndYaw, computes the angles in elevation-yaw coordinates. (See SMKTransformation.)

void SMKGetAzimuthAndElevation(double x, double y, double z, double *azim, double *elev);

Expresses the unit vector (x, y, z) in standard spherical coordinates.

void SMKGetElevationAndYaw(double x, double y, double z, double *elev, double *yaw);

Expresses the unit vector (x, y, z) in elevation-yaw spherical coordinates.

The following two functions, which issue OpenGL commands, are convenient wrappers for gluProject() and gluUnProject().

int SMKProjectPoint(double x, double y, double z, double *a, double *b, double *c);

Projects the world coordinates (x, y, z) into eye coordinates (a, b, c) using the current viewing transformations; returns true if and only if it is successful.

int SMKUnProjectPoint(double a, double b, double c, double *x, double *y, double *z);

Unprojects the eye coordinates (a, b, c) into world coordinates (x, y, z) using the current viewing transformations; returns true if and only if it is successful.