]> git.mxchange.org Git - simgear.git/blob - Math/MAT3geom.c
Tweak for SGI portability.
[simgear.git] / Math / MAT3geom.c
1 /* #include "HEADERS.h" */
2 /* Copyright 1988, Brown Computer Graphics Group.  All Rights Reserved. */
3
4 /* --------------------------------------------------------------------------
5  * This file contains routines that perform geometry-related operations
6  * on matrices.
7  * -------------------------------------------------------------------------*/
8
9 #include <Math/mat3defs.h>
10
11 /* --------------------------  Static Routines  ---------------------------- */
12
13 /* -------------------------  Internal Routines  --------------------------- */
14
15 /* --------------------------  Public Routines  ---------------------------- */
16
17 /*
18  * This takes a matrix used to transform points, and returns a corresponding
19  * matrix that can be used to transform direction vectors (between points).
20  */
21
22 void
23 MAT3direction_matrix(register double (*result_mat)[4], register double (*mat)[4])
24 {
25    register int i;
26
27    MAT3copy(result_mat, mat);
28
29    for (i = 0; i < 4; i++) result_mat[i][3] = result_mat[3][i] = 0.0;
30
31    result_mat[3][3] = 1.0;
32 }
33
34 /*
35  * This takes a matrix used to transform points, and returns a corresponding
36  * matrix that can be used to transform vectors that must remain perpendicular
37  * to planes defined by the points.  It is useful when you are transforming
38  * some object that has both points and normals in its definition, and you
39  * only have the transformation matrix for the points.  This routine returns
40  * FALSE if the normal matrix is uncomputable.  Otherwise, it returns TRUE.
41  *
42  * Spike sez: "This is the adjoint for the non-homogeneous part of the
43  *             transformation."
44  */
45
46 int
47 MAT3normal_matrix(register double (*result_mat)[4], register double (*mat)[4])
48 {
49    register int ret;
50    MAT3mat      tmp_mat;
51
52    MAT3direction_matrix(result_mat, mat);
53
54    if ( (ret = MAT3invert(tmp_mat, tmp_mat)) ) {
55        MAT3transpose(result_mat, tmp_mat);
56    }
57
58    return(ret);
59 }
60
61 /*
62  * Sets the given matrix to be a scale matrix for the given vector of
63  * scale values.
64  */
65
66 void
67 MAT3scale(double (*result_mat)[4], double *scale)
68 {
69    MAT3identity(result_mat);
70
71    result_mat[0][0] = scale[0];
72    result_mat[1][1] = scale[1];
73    result_mat[2][2] = scale[2];
74 }
75
76 /*
77  * Sets up a matrix for a rotation about an axis given by the line from
78  * (0,0,0) to axis, through an angle (in radians).
79  * Looking along the axis toward the origin, the rotation is counter-clockwise.
80  */
81
82 #define SELECT  .7071   /* selection constant (roughly .5*sqrt(2) */
83
84 void
85 MAT3rotate(double (*result_mat)[4], double *axis, double angle_in_radians)
86 {
87    MAT3vec      naxis,  /* Axis of rotation, normalized                 */
88                 base2,  /* 2nd unit basis vec, perp to axis             */
89                 base3;  /* 3rd unit basis vec, perp to axis & base2     */
90    double       dot;
91    MAT3mat      base_mat,       /* Change-of-basis matrix               */
92                 base_mat_trans; /* Inverse of c-o-b matrix              */
93    register int i;
94
95    /* Step 1: extend { axis } to a basis for 3-space: { axis, base2, base3 }
96     * which is orthonormal (all three have unit length, and all three are
97     * mutually orthogonal). Also should be oriented, i.e. axis cross base2 =
98     * base3, rather than -base3.
99     *
100     * Method: Find a vector linearly independent from axis. For this we
101     * either use the y-axis, or, if that is too close to axis, the
102     * z-axis. 'Too close' means that the dot product is too near to 1.
103     */
104
105    MAT3_COPY_VEC(naxis, axis);
106    MAT3_NORMALIZE_VEC(naxis, dot);
107
108    if (dot == 0.0) {
109        /* ERR_ERROR(MAT3_errid, ERR_SEVERE,
110                    (ERR_S, "Zero-length axis vector given to MAT3rotate")); */
111       return;
112    }
113
114    MAT3perp_vec(base2, naxis, TRUE);
115    MAT3cross_product(base3, naxis, base2);
116
117    /* Set up the change-of-basis matrix, and its inverse */
118    MAT3identity(base_mat);
119    MAT3identity(base_mat_trans);
120    MAT3identity(result_mat);
121
122    for (i = 0; i < 3; i++){
123       base_mat_trans[i][0] = base_mat[0][i] = naxis[i];
124       base_mat_trans[i][1] = base_mat[1][i] = base2[i];
125       base_mat_trans[i][2] = base_mat[2][i] = base3[i];
126    }
127
128    /* If T(u) = uR, where R is base_mat, then T(x-axis) = naxis,
129     * T(y-axis) = base2, and T(z-axis) = base3. The inverse of base_mat is
130     * its transpose.  OK?
131     */
132
133    result_mat[1][1] =   result_mat[2][2] = cos(angle_in_radians);
134    result_mat[2][1] = -(result_mat[1][2] = sin(angle_in_radians));
135
136    MAT3mult(result_mat, base_mat_trans, result_mat);
137    MAT3mult(result_mat, result_mat,     base_mat);
138 }
139
140 /*
141  * Sets the given matrix to be a translation matrix for the given vector of
142  * translation values.
143  */
144
145 void
146 MAT3translate(double (*result_mat)[4], double *trans)
147 {
148    MAT3identity(result_mat);
149
150    result_mat[3][0] = trans[0];
151    result_mat[3][1] = trans[1];
152    result_mat[3][2] = trans[2];
153 }
154
155 /*
156  * Sets the given matrix to be a shear matrix for the given x and y shear
157  * values.
158  */
159
160 void
161 MAT3shear(double (*result_mat)[4], double xshear, double yshear)
162 {
163    MAT3identity(result_mat);
164
165    result_mat[2][0] = xshear;
166    result_mat[2][1] = yshear;
167 }
168