-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatrix.cpp
More file actions
216 lines (186 loc) · 4.65 KB
/
matrix.cpp
File metadata and controls
216 lines (186 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* matrix.cpp
* proj3
*
* Created by Michael Atwood on 6/11/08.
* Copyright 2008 __MyCompanyName__. All rights reserved.
*
*/
#include <cmath>
#include "matrix.h"
#include "vert3.h"
/**
* Calculates the inverse of the matrix
*/
int inverse_mat(double mat[][NUMCOLS], double inv[][NUMCOLS])
{
int lp, i, j, k;
static double wrk[NUMROWS][8];
static double a, b;
for(i=0; i<NUMROWS; i++) { /* Set up matrices */
for(j=0; j<NUMCOLS; j++) {
wrk[i][j]=mat[i][j];
wrk[i][j+NUMCOLS]=0.0;
}
wrk[i][i+NUMCOLS]=1.0;
}
for(lp=0; lp<4; lp++) { /* Loop over all rows */
a=0.0;
j=(-1);
for(i=lp; i<4; i++) { /* Find largest non-zero element */
b=wrk[i][lp];
if(b<0.0)
b=(-b);
if(b>a) {
a=b;
j=i;
}
}
if(j!=lp) { /* If not on diagonal, put it there */
if(j<0) /* Singular if none found */
return(0);
else /* Exchange rows from lp to end */
for(k=lp; k<8; k++) {
a=wrk[j][k];
wrk[j][k]=wrk[lp][k];
wrk[lp][k]=a;
}
}
a=wrk[lp][lp]; /* Normalize working row */
for(i=lp; i<8; i++)
wrk[lp][i]/=a;
/*
Note: the column at lp is not cleared to zero since the
original matrix is destroyed anyway and only the second
half of the work matrix will be returned.
*/
for(i=lp+1; i<8; i++) { /* Adjust rest of work space */
b=wrk[lp][i];
for(j=0; j<4; j++) /* One column at a time */
if(j!=lp)
wrk[j][i]-=wrk[j][lp]*b;
}
}
for(i=0; i<NUMROWS; i++) /* Return result matrix */
for(j=0; j<NUMCOLS; j++)
inv[i][j]=wrk[i][j+NUMCOLS];
return(1);
}
/**
* Changes world coords to eye
*/
void make_world_to_eye_mat(const vert3& eye, const vert3& coi, double m[][NUMCOLS])
{
double a, b, c, r, p, pr;
a = coi.x - eye.x;
b = coi.y - eye.y;
c = coi.z - eye.z;
r = sqrt(a*a + b*b + c*c);
p = sqrt(a*a + c*c);
pr = p * r;
m[0][0] = -c/p;
m[0][1] = 0.0;
m[0][2] = a/p;
m[0][3] = eye.x*c/p - eye.z*a/p;
m[1][0] = -a*b/pr;
m[1][1] = p/r;
m[1][2] = -b*c/pr;
m[1][3] = eye.x*a*b/pr - eye.y*p/r + eye.z*b*c/pr;
m[2][0] = a/r;
m[2][1] = b/r;
m[2][2] = c/r;
m[2][3] = -eye.x*a/r - eye.y*b/r - eye.z*c/r;
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
m[3][3] = 1.0;
}
/**
* Makes the ident mat
*/
void make_identmat(double I[][NUMCOLS])
{
I[0][0] = 1.0; I[0][1] = 0.0; I[0][2] = 0.0; I[0][3] = 0.0;
I[1][0] = 0.0; I[1][1] = 1.0; I[1][2] = 0.0; I[1][3] = 0.0;
I[2][0] = 0.0; I[2][1] = 0.0; I[2][2] = 1.0; I[2][3] = 0.0;
I[3][0] = 0.0; I[3][1] = 0.0; I[3][2] = 0.0; I[3][3] = 1.0;
}
/*
This routine is only to be used for scale, rotate, and translate.
(e.g. World to Eye transform)
*/
void transform_pt3D(double m[][NUMCOLS], const vert3& v, vert3& p)
{
p.x = m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3];
p.y = m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3];
p.z = m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3];
}
/**
* Makes the translation matrix based on the vector
*/
void make_transmat(double dx, double dy, double dz, double m[][NUMCOLS])
{
m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = dx;
m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = dy;
m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = dz;
m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
}
/**
* Copies a matrix
*/
void copymat(double src[][NUMCOLS], double dest[][NUMCOLS])
{
int r, c;
for (r = 0; r < NUMROWS; r++)
for (c = 0; c < NUMCOLS; c++)
dest[r][c] = src[r][c];
}
/**
* Doing a copymat so that one can make the call, "matmult(a, b, a)".
*/
void matmult(double a[][NUMCOLS], double b[][NUMCOLS], double res[][NUMCOLS])
{
int r, c, i;
mat4D prod;
for (r = 0; r < NUMROWS; r++)
for (c = 0; c < NUMCOLS; c++) {
prod[r][c] = 0.0;
for (i = 0; i < NUMCOLS; i++)
prod[r][c] += a[r][i]*b[i][c];
}
copymat(prod, res);
}
/**
* Calculates the OUTWARD face normal given 3 points on the face. I am
* assuming a clockwise orientation of the face vertices (when facing
* outside of face).
*/
const vec3 calc_face_norm(const vert3& p1, const vert3& p2, const vert3& p3)
{
vec3 v1, v2;
v1 = p2-p1;
v2 = p3-p2;
return v2 * v1;
}
const double dot(vec3 v, vec3 v2)
{
double out = 0.0;
out += v.x * v2.x;
out += v.y * v2.y;
out += v.z * v2.z;
return out;
}
const vec3 calc_face_norm_newell(const vert3 verts[], const int& num_verts)
{
vec3 norm;
norm.x = 0; norm.y = 0; norm.z = 0;
for(int i = 0; i < num_verts; i++)
{
vert3 u = verts[i];
vert3 v = verts[(i + 1) % num_verts];
norm.x += (u.y - v.y) * (u.z + v.z);
norm.y += (u.z - v.z) * (u.x + v.x);
norm.z += (u.x - v.x) * (u.y + v.y);
}
return norm;
}