1 /* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
3 /* --------------------------------------------------------------------------
4 * This file contains routines that operate on matrices and vectors, or
6 * -------------------------------------------------------------------------*/
8 /* #include "sphigslocal.h" */
10 /* -------------------------- Static Routines ---------------------------- */
12 /* ------------------------- Internal Routines --------------------------- */
14 /* -------------------------- Public Routines ---------------------------- */
17 * Multiplies a vector by a matrix, setting the result vector.
18 * It assumes all homogeneous coordinates are 1.
19 * The two vectors involved may be the same.
22 #include <Math/mat3.h>
32 #if !defined( USE_XTRA_MAT3_INLINES )
35 MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
38 register double *temp = tempvec;
40 temp[0] = vec[0] * mat[0][0] + vec[1] * mat[1][0] +
41 vec[2] * mat[2][0] + mat[3][0];
42 temp[1] = vec[0] * mat[0][1] + vec[1] * mat[1][1] +
43 vec[2] * mat[2][1] + mat[3][1];
44 temp[2] = vec[0] * mat[0][2] + vec[1] * mat[1][2] +
45 vec[2] * mat[2][2] + mat[3][2];
47 MAT3_COPY_VEC(result_vec, temp);
49 #endif // !defined( USE_XTRA_MAT3_INLINES )
52 * Multiplies a vector of size 4 by a matrix, setting the result vector.
53 * The fourth element of the vector is the homogeneous coordinate, which
54 * may or may not be 1. If the "normalize" parameter is TRUE, then the
55 * result vector will be normalized so that the homogeneous coordinate is 1.
56 * The two vectors involved may be the same.
57 * This returns zero if the vector was to be normalized, but couldn't be.
61 MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
65 register double *temp = tempvec;
66 register int ret = TRUE;
68 temp[0] = vec[0] * mat[0][0] + vec[1] * mat[1][0] +
69 vec[2] * mat[2][0] + vec[3] * mat[3][0];
70 temp[1] = vec[0] * mat[0][1] + vec[1] * mat[1][1] +
71 vec[2] * mat[2][1] + vec[3] * mat[3][1];
72 temp[2] = vec[0] * mat[0][2] + vec[1] * mat[1][2] +
73 vec[2] * mat[2][2] + vec[3] * mat[3][2];
74 temp[3] = vec[0] * mat[0][3] + vec[1] * mat[1][3] +
75 vec[2] * mat[2][3] + vec[3] * mat[3][3];
77 /* Normalize if asked for, possible, and necessary */
79 if (MAT3_IS_ZERO(temp[3])) {
82 "Can't normalize vector: homogeneous coordinate is 0");
87 norm_fac = 1.0 / temp[3];
88 MAT3_SCALE_VEC(result_vec, temp, norm_fac);
92 else MAT3_COPY_HVEC(result_vec, temp);
97 #if !defined( USE_XTRA_MAT3_INLINES )
100 * Sets the first vector to be the cross-product of the last two vectors.
104 MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
107 register double *temp = tempvec;
109 temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
110 temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
111 temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
113 MAT3_COPY_VEC(result_vec, temp);
115 #endif // !defined( USE_XTRA_MAT3_INLINES )
118 * Finds a vector perpendicular to vec and stores it in result_vec.
119 * Method: take any vector (we use <0,1,0>) and subtract the
120 * portion of it pointing in the vec direction. This doesn't
121 * work if vec IS <0,1,0> or is very near it. So if this is
122 * the case, use <0,0,1> instead.
123 * If "is_unit" is TRUE, the given vector is assumed to be unit length.
126 #define SELECT .7071 /* selection constant (roughly .5*sqrt(2) */
129 MAT3perp_vec(double *result_vec, double *vec, int is_unit)
134 MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
136 MAT3_COPY_VEC(norm, vec);
138 if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
140 /* See if vector is too close to <0,1,0>. If so, use <0,0,1> */
141 if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
144 dot = MAT3_DOT_PRODUCT(norm, result_vec);
147 /* Subtract off non-perpendicular part */
148 result_vec[0] -= dot * norm[0];
149 result_vec[1] -= dot * norm[1];
150 result_vec[2] -= dot * norm[2];
152 /* Make result unit length */
153 MAT3_NORMALIZE_VEC(result_vec, dot);