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