| [0b990d] | 1 | #include <util/misc/math.h> | 
|---|
|  | 2 | #include <util/render/algebra3.h> | 
|---|
|  | 3 | #include <util/misc/exenv.h> | 
|---|
|  | 4 | #include <ctype.h> | 
|---|
|  | 5 |  | 
|---|
|  | 6 | using namespace std; | 
|---|
|  | 7 | using namespace sc; | 
|---|
|  | 8 |  | 
|---|
|  | 9 | // min-max macros | 
|---|
|  | 10 | #define MIN(A,B) ((A) < (B) ? (A) : (B)) | 
|---|
|  | 11 | #define MAX(A,B) ((A) > (B) ? (A) : (B)) | 
|---|
|  | 12 |  | 
|---|
|  | 13 | // error handling macro | 
|---|
|  | 14 | #define V_ERROR(E) { ExEnv::errn() << E; exit(1); } | 
|---|
|  | 15 |  | 
|---|
|  | 16 | /**************************************************************** | 
|---|
|  | 17 | *                                                               * | 
|---|
|  | 18 | *                   vec2 Member functions                       * | 
|---|
|  | 19 | *                                                               * | 
|---|
|  | 20 | ****************************************************************/ | 
|---|
|  | 21 |  | 
|---|
|  | 22 | // CONSTRUCTORS | 
|---|
|  | 23 |  | 
|---|
|  | 24 | vec2::vec2() {} | 
|---|
|  | 25 |  | 
|---|
|  | 26 | vec2::vec2(const double x, const double y) | 
|---|
|  | 27 | { n[VX] = x; n[VY] = y; } | 
|---|
|  | 28 |  | 
|---|
|  | 29 | vec2::vec2(const double d) | 
|---|
|  | 30 | { n[VX] = n[VY] = d; } | 
|---|
|  | 31 |  | 
|---|
|  | 32 | vec2::vec2(const vec2& v) | 
|---|
|  | 33 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; } | 
|---|
|  | 34 |  | 
|---|
|  | 35 | vec2::vec2(const vec3& v) // it is up to caller to avoid divide-by-zero | 
|---|
|  | 36 | { n[VX] = v.n[VX]/v.n[VZ]; n[VY] = v.n[VY]/v.n[VZ]; }; | 
|---|
|  | 37 |  | 
|---|
|  | 38 | vec2::vec2(const vec3& v, int dropAxis) { | 
|---|
|  | 39 | switch (dropAxis) { | 
|---|
|  | 40 | case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; break; | 
|---|
|  | 41 | case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; break; | 
|---|
|  | 42 | default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; break; | 
|---|
|  | 43 | } | 
|---|
|  | 44 | } | 
|---|
|  | 45 |  | 
|---|
|  | 46 |  | 
|---|
|  | 47 | // ASSIGNMENT OPERATORS | 
|---|
|  | 48 |  | 
|---|
|  | 49 | vec2& vec2::operator = (const vec2& v) | 
|---|
|  | 50 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; return *this; } | 
|---|
|  | 51 |  | 
|---|
|  | 52 | vec2& vec2::operator += ( const vec2& v ) | 
|---|
|  | 53 | { n[VX] += v.n[VX]; n[VY] += v.n[VY]; return *this; } | 
|---|
|  | 54 |  | 
|---|
|  | 55 | vec2& vec2::operator -= ( const vec2& v ) | 
|---|
|  | 56 | { n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; return *this; } | 
|---|
|  | 57 |  | 
|---|
|  | 58 | vec2& vec2::operator *= ( const double d ) | 
|---|
|  | 59 | { n[VX] *= d; n[VY] *= d; return *this; } | 
|---|
|  | 60 |  | 
|---|
|  | 61 | vec2& vec2::operator /= ( const double d ) | 
|---|
|  | 62 | { double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; return *this; } | 
|---|
|  | 63 |  | 
|---|
|  | 64 | double& vec2::operator [] ( int i) { | 
|---|
|  | 65 | if (i < VX || i > VY) | 
|---|
|  | 66 | V_ERROR("vec2 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 67 | return n[i]; | 
|---|
|  | 68 | } | 
|---|
|  | 69 |  | 
|---|
|  | 70 | const double& vec2::operator [] ( int i) const { | 
|---|
|  | 71 | if (i < VX || i > VY) | 
|---|
|  | 72 | V_ERROR("vec2 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 73 | return n[i]; | 
|---|
|  | 74 | } | 
|---|
|  | 75 |  | 
|---|
|  | 76 |  | 
|---|
|  | 77 | // SPECIAL FUNCTIONS | 
|---|
|  | 78 |  | 
|---|
|  | 79 | double vec2::length() | 
|---|
|  | 80 | { return sqrt(length2()); } | 
|---|
|  | 81 |  | 
|---|
|  | 82 | double vec2::length2() | 
|---|
|  | 83 | { return n[VX]*n[VX] + n[VY]*n[VY]; } | 
|---|
|  | 84 |  | 
|---|
|  | 85 | vec2& vec2::normalize() // it is up to caller to avoid divide-by-zero | 
|---|
|  | 86 | { *this /= length(); return *this; } | 
|---|
|  | 87 |  | 
|---|
|  | 88 | vec2& vec2::apply(V_FCT_PTR fct) | 
|---|
|  | 89 | { n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); return *this; } | 
|---|
|  | 90 |  | 
|---|
|  | 91 |  | 
|---|
|  | 92 | // FRIENDS | 
|---|
|  | 93 |  | 
|---|
|  | 94 | namespace sc { | 
|---|
|  | 95 |  | 
|---|
|  | 96 | vec2 operator - (const vec2& a) | 
|---|
|  | 97 | { return vec2(-a.n[VX],-a.n[VY]); } | 
|---|
|  | 98 |  | 
|---|
|  | 99 | vec2 operator + (const vec2& a, const vec2& b) | 
|---|
|  | 100 | { return vec2(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY]); } | 
|---|
|  | 101 |  | 
|---|
|  | 102 | vec2 operator - (const vec2& a, const vec2& b) | 
|---|
|  | 103 | { return vec2(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY]); } | 
|---|
|  | 104 |  | 
|---|
|  | 105 | vec2 operator * (const vec2& a, const double d) | 
|---|
|  | 106 | { return vec2(d*a.n[VX], d*a.n[VY]); } | 
|---|
|  | 107 |  | 
|---|
|  | 108 | vec2 operator * (const double d, const vec2& a) | 
|---|
|  | 109 | { return a*d; } | 
|---|
|  | 110 |  | 
|---|
|  | 111 | vec2 operator * (const mat3& a, const vec2& v) { | 
|---|
|  | 112 | vec3 av; | 
|---|
|  | 113 |  | 
|---|
|  | 114 | av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ]; | 
|---|
|  | 115 | av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ]; | 
|---|
|  | 116 | av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]; | 
|---|
|  | 117 | return av; | 
|---|
|  | 118 | } | 
|---|
|  | 119 |  | 
|---|
|  | 120 | vec2 operator * (const vec2& v, const mat3& a) | 
|---|
|  | 121 | { return a.transpose() * v; } | 
|---|
|  | 122 |  | 
|---|
|  | 123 | double operator * (const vec2& a, const vec2& b) | 
|---|
|  | 124 | { return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]); } | 
|---|
|  | 125 |  | 
|---|
|  | 126 | vec2 operator / (const vec2& a, const double d) | 
|---|
|  | 127 | { double d_inv = 1./d; return vec2(a.n[VX]*d_inv, a.n[VY]*d_inv); } | 
|---|
|  | 128 |  | 
|---|
|  | 129 | vec3 operator ^ (const vec2& a, const vec2& b) | 
|---|
|  | 130 | { return vec3(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); } | 
|---|
|  | 131 |  | 
|---|
|  | 132 | int operator == (const vec2& a, const vec2& b) | 
|---|
|  | 133 | { return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); } | 
|---|
|  | 134 |  | 
|---|
|  | 135 | int operator != (const vec2& a, const vec2& b) | 
|---|
|  | 136 | { return !(a == b); } | 
|---|
|  | 137 |  | 
|---|
|  | 138 | ostream& operator << (ostream& s, vec2& v) | 
|---|
|  | 139 | { return s << "| " << v.n[VX] << ' ' << v.n[VY] << " |"; } | 
|---|
|  | 140 |  | 
|---|
|  | 141 | istream& operator >> (istream& s, vec2& v) { | 
|---|
|  | 142 | vec2        v_tmp; | 
|---|
|  | 143 | char        c = ' '; | 
|---|
|  | 144 |  | 
|---|
|  | 145 | while (isspace(c)) | 
|---|
|  | 146 | s >> c; | 
|---|
|  | 147 | // The vectors can be formatted either as x y or | x y | | 
|---|
|  | 148 | if (c == '|') { | 
|---|
|  | 149 | s >> v_tmp[VX] >> v_tmp[VY]; | 
|---|
|  | 150 | while (s >> c && isspace(c)) ; | 
|---|
|  | 151 | //if (c != '|') | 
|---|
|  | 152 | //    s.set(_bad); | 
|---|
|  | 153 | } | 
|---|
|  | 154 | else { | 
|---|
|  | 155 | s.putback(c); | 
|---|
|  | 156 | s >> v_tmp[VX] >> v_tmp[VY]; | 
|---|
|  | 157 | } | 
|---|
|  | 158 | if (s) | 
|---|
|  | 159 | v = v_tmp; | 
|---|
|  | 160 | return s; | 
|---|
|  | 161 | } | 
|---|
|  | 162 |  | 
|---|
|  | 163 | void swap(vec2& a, vec2& b) | 
|---|
|  | 164 | { vec2 tmp(a); a = b; b = tmp; } | 
|---|
|  | 165 |  | 
|---|
|  | 166 | vec2 min(const vec2& a, const vec2& b) | 
|---|
|  | 167 | { return vec2(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); } | 
|---|
|  | 168 |  | 
|---|
|  | 169 | vec2 max(const vec2& a, const vec2& b) | 
|---|
|  | 170 | { return vec2(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); } | 
|---|
|  | 171 |  | 
|---|
|  | 172 | vec2 prod(const vec2& a, const vec2& b) | 
|---|
|  | 173 | { return vec2(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); } | 
|---|
|  | 174 |  | 
|---|
|  | 175 | } | 
|---|
|  | 176 |  | 
|---|
|  | 177 | /**************************************************************** | 
|---|
|  | 178 | *                                                               * | 
|---|
|  | 179 | *                   vec3 Member functions                       * | 
|---|
|  | 180 | *                                                               * | 
|---|
|  | 181 | ****************************************************************/ | 
|---|
|  | 182 |  | 
|---|
|  | 183 | // CONSTRUCTORS | 
|---|
|  | 184 |  | 
|---|
|  | 185 | vec3::vec3() {} | 
|---|
|  | 186 |  | 
|---|
|  | 187 | vec3::vec3(const double x, const double y, const double z) | 
|---|
|  | 188 | { n[VX] = x; n[VY] = y; n[VZ] = z; } | 
|---|
|  | 189 |  | 
|---|
|  | 190 | vec3::vec3(const double d) | 
|---|
|  | 191 | { n[VX] = n[VY] = n[VZ] = d; } | 
|---|
|  | 192 |  | 
|---|
|  | 193 | vec3::vec3(const vec3& v) | 
|---|
|  | 194 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; } | 
|---|
|  | 195 |  | 
|---|
|  | 196 | vec3::vec3(const vec2& v) | 
|---|
|  | 197 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = 1.0; } | 
|---|
|  | 198 |  | 
|---|
|  | 199 | vec3::vec3(const vec2& v, double d) | 
|---|
|  | 200 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = d; } | 
|---|
|  | 201 |  | 
|---|
|  | 202 | vec3::vec3(const vec4& v) // it is up to caller to avoid divide-by-zero | 
|---|
|  | 203 | { n[VX] = v.n[VX] / v.n[VW]; n[VY] = v.n[VY] / v.n[VW]; | 
|---|
|  | 204 | n[VZ] = v.n[VZ] / v.n[VW]; } | 
|---|
|  | 205 |  | 
|---|
|  | 206 | vec3::vec3(const vec4& v, int dropAxis) { | 
|---|
|  | 207 | switch (dropAxis) { | 
|---|
|  | 208 | case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break; | 
|---|
|  | 209 | case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break; | 
|---|
|  | 210 | case VZ: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VW]; break; | 
|---|
|  | 211 | default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; break; | 
|---|
|  | 212 | } | 
|---|
|  | 213 | } | 
|---|
|  | 214 |  | 
|---|
|  | 215 |  | 
|---|
|  | 216 | // ASSIGNMENT OPERATORS | 
|---|
|  | 217 |  | 
|---|
|  | 218 | vec3& vec3::operator = (const vec3& v) | 
|---|
|  | 219 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; return *this; } | 
|---|
|  | 220 |  | 
|---|
|  | 221 | vec3& vec3::operator += ( const vec3& v ) | 
|---|
|  | 222 | { n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; return *this; } | 
|---|
|  | 223 |  | 
|---|
|  | 224 | vec3& vec3::operator -= ( const vec3& v ) | 
|---|
|  | 225 | { n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; return *this; } | 
|---|
|  | 226 |  | 
|---|
|  | 227 | vec3& vec3::operator *= ( const double d ) | 
|---|
|  | 228 | { n[VX] *= d; n[VY] *= d; n[VZ] *= d; return *this; } | 
|---|
|  | 229 |  | 
|---|
|  | 230 | vec3& vec3::operator /= ( const double d ) | 
|---|
|  | 231 | { double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv; | 
|---|
|  | 232 | return *this; } | 
|---|
|  | 233 |  | 
|---|
|  | 234 | double& vec3::operator [] ( int i) { | 
|---|
|  | 235 | if (i < VX || i > VZ) | 
|---|
|  | 236 | V_ERROR("vec3 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 237 | return n[i]; | 
|---|
|  | 238 | } | 
|---|
|  | 239 |  | 
|---|
|  | 240 | const double& vec3::operator [] ( int i) const { | 
|---|
|  | 241 | if (i < VX || i > VZ) | 
|---|
|  | 242 | V_ERROR("vec3 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 243 | return n[i]; | 
|---|
|  | 244 | } | 
|---|
|  | 245 |  | 
|---|
|  | 246 |  | 
|---|
|  | 247 | // SPECIAL FUNCTIONS | 
|---|
|  | 248 |  | 
|---|
|  | 249 | double vec3::length() | 
|---|
|  | 250 | {  return sqrt(length2()); } | 
|---|
|  | 251 |  | 
|---|
|  | 252 | double vec3::length2() | 
|---|
|  | 253 | {  return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ]; } | 
|---|
|  | 254 |  | 
|---|
|  | 255 | vec3& vec3::normalize() // it is up to caller to avoid divide-by-zero | 
|---|
|  | 256 | { *this /= length(); return *this; } | 
|---|
|  | 257 |  | 
|---|
|  | 258 | vec3& vec3::apply(V_FCT_PTR fct) | 
|---|
|  | 259 | { n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]); | 
|---|
|  | 260 | return *this; } | 
|---|
|  | 261 |  | 
|---|
|  | 262 |  | 
|---|
|  | 263 | // FRIENDS | 
|---|
|  | 264 |  | 
|---|
|  | 265 | namespace sc { | 
|---|
|  | 266 |  | 
|---|
|  | 267 | vec3 operator - (const vec3& a) | 
|---|
|  | 268 | {  return vec3(-a.n[VX],-a.n[VY],-a.n[VZ]); } | 
|---|
|  | 269 |  | 
|---|
|  | 270 | vec3 operator + (const vec3& a, const vec3& b) | 
|---|
|  | 271 | { return vec3(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ]); } | 
|---|
|  | 272 |  | 
|---|
|  | 273 | vec3 operator - (const vec3& a, const vec3& b) | 
|---|
|  | 274 | { return vec3(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY], a.n[VZ]-b.n[VZ]); } | 
|---|
|  | 275 |  | 
|---|
|  | 276 | vec3 operator * (const vec3& a, const double d) | 
|---|
|  | 277 | { return vec3(d*a.n[VX], d*a.n[VY], d*a.n[VZ]); } | 
|---|
|  | 278 |  | 
|---|
|  | 279 | vec3 operator * (const double d, const vec3& a) | 
|---|
|  | 280 | { return a*d; } | 
|---|
|  | 281 |  | 
|---|
|  | 282 | vec3 operator * (const mat4& a, const vec3& v) | 
|---|
|  | 283 | { return a * vec4(v); } | 
|---|
|  | 284 |  | 
|---|
|  | 285 | vec3 operator * (const vec3& v, const mat4& a) | 
|---|
|  | 286 | { return a.transpose() * v; } | 
|---|
|  | 287 |  | 
|---|
|  | 288 | double operator * (const vec3& a, const vec3& b) | 
|---|
|  | 289 | { return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]); } | 
|---|
|  | 290 |  | 
|---|
|  | 291 | vec3 operator / (const vec3& a, const double d) | 
|---|
|  | 292 | { double d_inv = 1./d; return vec3(a.n[VX]*d_inv, a.n[VY]*d_inv, | 
|---|
|  | 293 | a.n[VZ]*d_inv); } | 
|---|
|  | 294 |  | 
|---|
|  | 295 | vec3 operator ^ (const vec3& a, const vec3& b) { | 
|---|
|  | 296 | return vec3(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY], | 
|---|
|  | 297 | a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ], | 
|---|
|  | 298 | a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]); | 
|---|
|  | 299 | } | 
|---|
|  | 300 |  | 
|---|
|  | 301 | int operator == (const vec3& a, const vec3& b) | 
|---|
|  | 302 | { return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]); | 
|---|
|  | 303 | } | 
|---|
|  | 304 |  | 
|---|
|  | 305 | int operator != (const vec3& a, const vec3& b) | 
|---|
|  | 306 | { return !(a == b); } | 
|---|
|  | 307 |  | 
|---|
|  | 308 | ostream& operator << (ostream& s, vec3& v) | 
|---|
|  | 309 | { return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << " |"; } | 
|---|
|  | 310 |  | 
|---|
|  | 311 | istream& operator >> (istream& s, vec3& v) { | 
|---|
|  | 312 | vec3        v_tmp; | 
|---|
|  | 313 | char        c = ' '; | 
|---|
|  | 314 |  | 
|---|
|  | 315 | while (isspace(c)) | 
|---|
|  | 316 | s >> c; | 
|---|
|  | 317 | // The vectors can be formatted either as x y z or | x y z | | 
|---|
|  | 318 | if (c == '|') { | 
|---|
|  | 319 | s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ]; | 
|---|
|  | 320 | while (s >> c && isspace(c)) ; | 
|---|
|  | 321 | //if (c != '|') | 
|---|
|  | 322 | //    s.set(_bad); | 
|---|
|  | 323 | } | 
|---|
|  | 324 | else { | 
|---|
|  | 325 | s.putback(c); | 
|---|
|  | 326 | s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ]; | 
|---|
|  | 327 | } | 
|---|
|  | 328 | if (s) | 
|---|
|  | 329 | v = v_tmp; | 
|---|
|  | 330 | return s; | 
|---|
|  | 331 | } | 
|---|
|  | 332 |  | 
|---|
|  | 333 | void swap(vec3& a, vec3& b) | 
|---|
|  | 334 | { vec3 tmp(a); a = b; b = tmp; } | 
|---|
|  | 335 |  | 
|---|
|  | 336 | vec3 min(const vec3& a, const vec3& b) | 
|---|
|  | 337 | { return vec3(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ], | 
|---|
|  | 338 | b.n[VZ])); } | 
|---|
|  | 339 |  | 
|---|
|  | 340 | vec3 max(const vec3& a, const vec3& b) | 
|---|
|  | 341 | { return vec3(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ], | 
|---|
|  | 342 | b.n[VZ])); } | 
|---|
|  | 343 |  | 
|---|
|  | 344 | vec3 prod(const vec3& a, const vec3& b) | 
|---|
|  | 345 | { return vec3(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ]); } | 
|---|
|  | 346 |  | 
|---|
|  | 347 | } | 
|---|
|  | 348 |  | 
|---|
|  | 349 | /**************************************************************** | 
|---|
|  | 350 | *                                                               * | 
|---|
|  | 351 | *                   vec4 Member functions                       * | 
|---|
|  | 352 | *                                                               * | 
|---|
|  | 353 | ****************************************************************/ | 
|---|
|  | 354 |  | 
|---|
|  | 355 | // CONSTRUCTORS | 
|---|
|  | 356 |  | 
|---|
|  | 357 | vec4::vec4() {} | 
|---|
|  | 358 |  | 
|---|
|  | 359 | vec4::vec4(const double x, const double y, const double z, const double w) | 
|---|
|  | 360 | { n[VX] = x; n[VY] = y; n[VZ] = z; n[VW] = w; } | 
|---|
|  | 361 |  | 
|---|
|  | 362 | vec4::vec4(const double d) | 
|---|
|  | 363 | {  n[VX] = n[VY] = n[VZ] = n[VW] = d; } | 
|---|
|  | 364 |  | 
|---|
|  | 365 | vec4::vec4(const vec4& v) | 
|---|
|  | 366 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW]; } | 
|---|
|  | 367 |  | 
|---|
|  | 368 | vec4::vec4(const vec3& v) | 
|---|
|  | 369 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = 1.0; } | 
|---|
|  | 370 |  | 
|---|
|  | 371 | vec4::vec4(const vec3& v, const double d) | 
|---|
|  | 372 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ];  n[VW] = d; } | 
|---|
|  | 373 |  | 
|---|
|  | 374 |  | 
|---|
|  | 375 | // ASSIGNMENT OPERATORS | 
|---|
|  | 376 |  | 
|---|
|  | 377 | vec4& vec4::operator = (const vec4& v) | 
|---|
|  | 378 | { n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW]; | 
|---|
|  | 379 | return *this; } | 
|---|
|  | 380 |  | 
|---|
|  | 381 | vec4& vec4::operator += ( const vec4& v ) | 
|---|
|  | 382 | { n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; n[VW] += v.n[VW]; | 
|---|
|  | 383 | return *this; } | 
|---|
|  | 384 |  | 
|---|
|  | 385 | vec4& vec4::operator -= ( const vec4& v ) | 
|---|
|  | 386 | { n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; n[VW] -= v.n[VW]; | 
|---|
|  | 387 | return *this; } | 
|---|
|  | 388 |  | 
|---|
|  | 389 | vec4& vec4::operator *= ( const double d ) | 
|---|
|  | 390 | { n[VX] *= d; n[VY] *= d; n[VZ] *= d; n[VW] *= d; return *this; } | 
|---|
|  | 391 |  | 
|---|
|  | 392 | vec4& vec4::operator /= ( const double d ) | 
|---|
|  | 393 | { double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv; | 
|---|
|  | 394 | n[VW] *= d_inv; return *this; } | 
|---|
|  | 395 |  | 
|---|
|  | 396 | double& vec4::operator [] ( int i) { | 
|---|
|  | 397 | if (i < VX || i > VW) | 
|---|
|  | 398 | V_ERROR("vec4 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 399 | return n[i]; | 
|---|
|  | 400 | } | 
|---|
|  | 401 |  | 
|---|
|  | 402 | const double& vec4::operator [] ( int i) const { | 
|---|
|  | 403 | if (i < VX || i > VW) | 
|---|
|  | 404 | V_ERROR("vec4 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 405 | return n[i]; | 
|---|
|  | 406 | } | 
|---|
|  | 407 |  | 
|---|
|  | 408 |  | 
|---|
|  | 409 | // SPECIAL FUNCTIONS | 
|---|
|  | 410 |  | 
|---|
|  | 411 | double vec4::length() | 
|---|
|  | 412 | { return sqrt(length2()); } | 
|---|
|  | 413 |  | 
|---|
|  | 414 | double vec4::length2() | 
|---|
|  | 415 | { return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ] + n[VW]*n[VW]; } | 
|---|
|  | 416 |  | 
|---|
|  | 417 | vec4& vec4::normalize() // it is up to caller to avoid divide-by-zero | 
|---|
|  | 418 | { *this /= length(); return *this; } | 
|---|
|  | 419 |  | 
|---|
|  | 420 | vec4& vec4::apply(V_FCT_PTR fct) | 
|---|
|  | 421 | { n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]); | 
|---|
|  | 422 | n[VW] = (*fct)(n[VW]); return *this; } | 
|---|
|  | 423 |  | 
|---|
|  | 424 |  | 
|---|
|  | 425 | // FRIENDS | 
|---|
|  | 426 |  | 
|---|
|  | 427 | namespace sc { | 
|---|
|  | 428 |  | 
|---|
|  | 429 | vec4 operator - (const vec4& a) | 
|---|
|  | 430 | { return vec4(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); } | 
|---|
|  | 431 |  | 
|---|
|  | 432 | vec4 operator + (const vec4& a, const vec4& b) | 
|---|
|  | 433 | { return vec4(a.n[VX] + b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ], | 
|---|
|  | 434 | a.n[VW] + b.n[VW]); } | 
|---|
|  | 435 |  | 
|---|
|  | 436 | vec4 operator - (const vec4& a, const vec4& b) | 
|---|
|  | 437 | {  return vec4(a.n[VX] - b.n[VX], a.n[VY] - b.n[VY], a.n[VZ] - b.n[VZ], | 
|---|
|  | 438 | a.n[VW] - b.n[VW]); } | 
|---|
|  | 439 |  | 
|---|
|  | 440 | vec4 operator * (const vec4& a, const double d) | 
|---|
|  | 441 | { return vec4(d*a.n[VX], d*a.n[VY], d*a.n[VZ], d*a.n[VW] ); } | 
|---|
|  | 442 |  | 
|---|
|  | 443 | vec4 operator * (const double d, const vec4& a) | 
|---|
|  | 444 | { return a*d; } | 
|---|
|  | 445 |  | 
|---|
|  | 446 | vec4 operator * (const mat4& a, const vec4& v) { | 
|---|
|  | 447 | #define ROWCOL(i) a.v[i].n[0]*v.n[VX] + a.v[i].n[1]*v.n[VY] \ | 
|---|
|  | 448 | + a.v[i].n[2]*v.n[VZ] + a.v[i].n[3]*v.n[VW] | 
|---|
|  | 449 | return vec4(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3)); | 
|---|
|  | 450 | #undef ROWCOL | 
|---|
|  | 451 | } | 
|---|
|  | 452 |  | 
|---|
|  | 453 | vec4 operator * (const vec4& v, const mat4& a) | 
|---|
|  | 454 | { return a.transpose() * v; } | 
|---|
|  | 455 |  | 
|---|
|  | 456 | double operator * (const vec4& a, const vec4& b) | 
|---|
|  | 457 | { return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ] + | 
|---|
|  | 458 | a.n[VW]*b.n[VW]); } | 
|---|
|  | 459 |  | 
|---|
|  | 460 | vec4 operator / (const vec4& a, const double d) | 
|---|
|  | 461 | { double d_inv = 1./d; return vec4(a.n[VX]*d_inv, a.n[VY]*d_inv, a.n[VZ]*d_inv, | 
|---|
|  | 462 | a.n[VW]*d_inv); } | 
|---|
|  | 463 |  | 
|---|
|  | 464 | int operator == (const vec4& a, const vec4& b) | 
|---|
|  | 465 | { return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]) | 
|---|
|  | 466 | && (a.n[VW] == b.n[VW]); } | 
|---|
|  | 467 |  | 
|---|
|  | 468 | int operator != (const vec4& a, const vec4& b) | 
|---|
|  | 469 | { return !(a == b); } | 
|---|
|  | 470 |  | 
|---|
|  | 471 | ostream& operator << (ostream& s, vec4& v) | 
|---|
|  | 472 | { return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << ' ' | 
|---|
|  | 473 | << v.n[VW] << " |"; } | 
|---|
|  | 474 |  | 
|---|
|  | 475 | istream& operator >> (istream& s, vec4& v) { | 
|---|
|  | 476 | vec4        v_tmp; | 
|---|
|  | 477 | char        c = ' '; | 
|---|
|  | 478 |  | 
|---|
|  | 479 | while (isspace(c)) | 
|---|
|  | 480 | s >> c; | 
|---|
|  | 481 | // The vectors can be formatted either as x y z w or | x y z w | | 
|---|
|  | 482 | if (c == '|') { | 
|---|
|  | 483 | s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW]; | 
|---|
|  | 484 | while (s >> c && isspace(c)) ; | 
|---|
|  | 485 | //if (c != '|') | 
|---|
|  | 486 | //    s.set(_bad); | 
|---|
|  | 487 | } | 
|---|
|  | 488 | else { | 
|---|
|  | 489 | s.putback(c); | 
|---|
|  | 490 | s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW]; | 
|---|
|  | 491 | } | 
|---|
|  | 492 | if (s) | 
|---|
|  | 493 | v = v_tmp; | 
|---|
|  | 494 | return s; | 
|---|
|  | 495 | } | 
|---|
|  | 496 |  | 
|---|
|  | 497 | void swap(vec4& a, vec4& b) | 
|---|
|  | 498 | { vec4 tmp(a); a = b; b = tmp; } | 
|---|
|  | 499 |  | 
|---|
|  | 500 | vec4 min(const vec4& a, const vec4& b) | 
|---|
|  | 501 | { return vec4(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ], | 
|---|
|  | 502 | b.n[VZ]), MIN(a.n[VW], b.n[VW])); } | 
|---|
|  | 503 |  | 
|---|
|  | 504 | vec4 max(const vec4& a, const vec4& b) | 
|---|
|  | 505 | { return vec4(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ], | 
|---|
|  | 506 | b.n[VZ]), MAX(a.n[VW], b.n[VW])); } | 
|---|
|  | 507 |  | 
|---|
|  | 508 | vec4 prod(const vec4& a, const vec4& b) | 
|---|
|  | 509 | { return vec4(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ], | 
|---|
|  | 510 | a.n[VW] * b.n[VW]); } | 
|---|
|  | 511 |  | 
|---|
|  | 512 | } | 
|---|
|  | 513 |  | 
|---|
|  | 514 | /**************************************************************** | 
|---|
|  | 515 | *                                                               * | 
|---|
|  | 516 | *                   mat3 member functions                       * | 
|---|
|  | 517 | *                                                               * | 
|---|
|  | 518 | ****************************************************************/ | 
|---|
|  | 519 |  | 
|---|
|  | 520 | // CONSTRUCTORS | 
|---|
|  | 521 |  | 
|---|
|  | 522 | mat3::mat3() {} | 
|---|
|  | 523 |  | 
|---|
|  | 524 | mat3::mat3(const vec3& v0, const vec3& v1, const vec3& v2) | 
|---|
|  | 525 | { v[0] = v0; v[1] = v1; v[2] = v2; } | 
|---|
|  | 526 |  | 
|---|
|  | 527 | mat3::mat3(const double d) | 
|---|
|  | 528 | { v[0] = v[1] = v[2] = vec3(d); } | 
|---|
|  | 529 |  | 
|---|
|  | 530 | mat3::mat3(const mat3& m) | 
|---|
|  | 531 | { v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; } | 
|---|
|  | 532 |  | 
|---|
|  | 533 |  | 
|---|
|  | 534 | // ASSIGNMENT OPERATORS | 
|---|
|  | 535 |  | 
|---|
|  | 536 | mat3& mat3::operator = ( const mat3& m ) | 
|---|
|  | 537 | { v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; return *this; } | 
|---|
|  | 538 |  | 
|---|
|  | 539 | mat3& mat3::operator += ( const mat3& m ) | 
|---|
|  | 540 | { v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; return *this; } | 
|---|
|  | 541 |  | 
|---|
|  | 542 | mat3& mat3::operator -= ( const mat3& m ) | 
|---|
|  | 543 | { v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; return *this; } | 
|---|
|  | 544 |  | 
|---|
|  | 545 | mat3& mat3::operator *= ( const double d ) | 
|---|
|  | 546 | { v[0] *= d; v[1] *= d; v[2] *= d; return *this; } | 
|---|
|  | 547 |  | 
|---|
|  | 548 | mat3& mat3::operator /= ( const double d ) | 
|---|
|  | 549 | { v[0] /= d; v[1] /= d; v[2] /= d; return *this; } | 
|---|
|  | 550 |  | 
|---|
|  | 551 | vec3& mat3::operator [] ( int i) { | 
|---|
|  | 552 | if (i < VX || i > VZ) | 
|---|
|  | 553 | V_ERROR("mat3 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 554 | return v[i]; | 
|---|
|  | 555 | } | 
|---|
|  | 556 |  | 
|---|
|  | 557 | const vec3& mat3::operator [] ( int i) const { | 
|---|
|  | 558 | if (i < VX || i > VZ) | 
|---|
|  | 559 | V_ERROR("mat3 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 560 | return v[i]; | 
|---|
|  | 561 | } | 
|---|
|  | 562 |  | 
|---|
|  | 563 |  | 
|---|
|  | 564 | // SPECIAL FUNCTIONS | 
|---|
|  | 565 |  | 
|---|
|  | 566 | mat3 mat3::transpose() const { | 
|---|
|  | 567 | return mat3(vec3(v[0][0], v[1][0], v[2][0]), | 
|---|
|  | 568 | vec3(v[0][1], v[1][1], v[2][1]), | 
|---|
|  | 569 | vec3(v[0][2], v[1][2], v[2][2])); | 
|---|
|  | 570 | } | 
|---|
|  | 571 |  | 
|---|
|  | 572 | mat3 mat3::inverse()        // Gauss-Jordan elimination with partial pivoting | 
|---|
|  | 573 | { | 
|---|
|  | 574 | mat3 a(*this),          // As a evolves from original mat into identity | 
|---|
|  | 575 | b(identity2D());   // b evolves from identity into inverse(a) | 
|---|
|  | 576 | int  i, j, i1; | 
|---|
|  | 577 |  | 
|---|
|  | 578 | // Loop over cols of a from left to right, eliminating above and below diag | 
|---|
|  | 579 | for (j=0; j<3; j++) {   // Find largest pivot in column j among rows j..2 | 
|---|
|  | 580 | i1 = j;                 // Row with largest pivot candidate | 
|---|
|  | 581 | for (i=j+1; i<3; i++) | 
|---|
|  | 582 | if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) | 
|---|
|  | 583 | i1 = i; | 
|---|
|  | 584 |  | 
|---|
|  | 585 | // Swap rows i1 and j in a and b to put pivot on diagonal | 
|---|
|  | 586 | swap(a.v[i1], a.v[j]); | 
|---|
|  | 587 | swap(b.v[i1], b.v[j]); | 
|---|
|  | 588 |  | 
|---|
|  | 589 | // Scale row j to have a unit diagonal | 
|---|
|  | 590 | if (a.v[j].n[j]==0.) | 
|---|
|  | 591 | V_ERROR("mat3::inverse: singular matrix; can't invert\n") | 
|---|
|  | 592 | b.v[j] /= a.v[j].n[j]; | 
|---|
|  | 593 | a.v[j] /= a.v[j].n[j]; | 
|---|
|  | 594 |  | 
|---|
|  | 595 | // Eliminate off-diagonal elems in col j of a, doing identical ops to b | 
|---|
|  | 596 | for (i=0; i<3; i++) | 
|---|
|  | 597 | if (i!=j) { | 
|---|
|  | 598 | b.v[i] -= a.v[i].n[j]*b.v[j]; | 
|---|
|  | 599 | a.v[i] -= a.v[i].n[j]*a.v[j]; | 
|---|
|  | 600 | } | 
|---|
|  | 601 | } | 
|---|
|  | 602 | return b; | 
|---|
|  | 603 | } | 
|---|
|  | 604 |  | 
|---|
|  | 605 | mat3& mat3::apply(V_FCT_PTR fct) { | 
|---|
|  | 606 | v[VX].apply(fct); | 
|---|
|  | 607 | v[VY].apply(fct); | 
|---|
|  | 608 | v[VZ].apply(fct); | 
|---|
|  | 609 | return *this; | 
|---|
|  | 610 | } | 
|---|
|  | 611 |  | 
|---|
|  | 612 |  | 
|---|
|  | 613 | // FRIENDS | 
|---|
|  | 614 |  | 
|---|
|  | 615 | namespace sc { | 
|---|
|  | 616 |  | 
|---|
|  | 617 | mat3 operator - (const mat3& a) | 
|---|
|  | 618 | { return mat3(-a.v[0], -a.v[1], -a.v[2]); } | 
|---|
|  | 619 |  | 
|---|
|  | 620 | mat3 operator + (const mat3& a, const mat3& b) | 
|---|
|  | 621 | { return mat3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]); } | 
|---|
|  | 622 |  | 
|---|
|  | 623 | mat3 operator - (const mat3& a, const mat3& b) | 
|---|
|  | 624 | { return mat3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]); } | 
|---|
|  | 625 |  | 
|---|
|  | 626 | mat3 operator * (const mat3& a, const mat3& b) { | 
|---|
|  | 627 | #define ROWCOL(i, j) \ | 
|---|
|  | 628 | a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + a.v[i].n[2]*b.v[2][j] | 
|---|
|  | 629 | return mat3(vec3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)), | 
|---|
|  | 630 | vec3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)), | 
|---|
|  | 631 | vec3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2))); | 
|---|
|  | 632 | #undef ROWCOL | 
|---|
|  | 633 | } | 
|---|
|  | 634 |  | 
|---|
|  | 635 | mat3 operator * (const mat3& a, const double d) | 
|---|
|  | 636 | { return mat3(a.v[0] * d, a.v[1] * d, a.v[2] * d); } | 
|---|
|  | 637 |  | 
|---|
|  | 638 | mat3 operator * (const double d, const mat3& a) | 
|---|
|  | 639 | { return a*d; } | 
|---|
|  | 640 |  | 
|---|
|  | 641 | mat3 operator / (const mat3& a, const double d) | 
|---|
|  | 642 | { return mat3(a.v[0] / d, a.v[1] / d, a.v[2] / d); } | 
|---|
|  | 643 |  | 
|---|
|  | 644 | int operator == (const mat3& a, const mat3& b) | 
|---|
|  | 645 | { return (a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]); } | 
|---|
|  | 646 |  | 
|---|
|  | 647 | int operator != (const mat3& a, const mat3& b) | 
|---|
|  | 648 | { return !(a == b); } | 
|---|
|  | 649 |  | 
|---|
|  | 650 | ostream& operator << (ostream& s, mat3& m) | 
|---|
|  | 651 | { return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ]; } | 
|---|
|  | 652 |  | 
|---|
|  | 653 | istream& operator >> (istream& s, mat3& m) { | 
|---|
|  | 654 | mat3    m_tmp; | 
|---|
|  | 655 |  | 
|---|
|  | 656 | s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ]; | 
|---|
|  | 657 | if (s) | 
|---|
|  | 658 | m = m_tmp; | 
|---|
|  | 659 | return s; | 
|---|
|  | 660 | } | 
|---|
|  | 661 |  | 
|---|
|  | 662 | void swap(mat3& a, mat3& b) | 
|---|
|  | 663 | { mat3 tmp(a); a = b; b = tmp; } | 
|---|
|  | 664 |  | 
|---|
|  | 665 | } | 
|---|
|  | 666 |  | 
|---|
|  | 667 | /**************************************************************** | 
|---|
|  | 668 | *                                                               * | 
|---|
|  | 669 | *                   mat4 member functions                       * | 
|---|
|  | 670 | *                                                               * | 
|---|
|  | 671 | ****************************************************************/ | 
|---|
|  | 672 |  | 
|---|
|  | 673 | // CONSTRUCTORS | 
|---|
|  | 674 |  | 
|---|
|  | 675 | mat4::mat4() {} | 
|---|
|  | 676 |  | 
|---|
|  | 677 | mat4::mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4& v3) | 
|---|
|  | 678 | { v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; } | 
|---|
|  | 679 |  | 
|---|
|  | 680 | mat4::mat4(const double d) | 
|---|
|  | 681 | { v[0] = v[1] = v[2] = v[3] = vec4(d); } | 
|---|
|  | 682 |  | 
|---|
|  | 683 | mat4::mat4(const mat4& m) | 
|---|
|  | 684 | { v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3]; } | 
|---|
|  | 685 |  | 
|---|
|  | 686 |  | 
|---|
|  | 687 | // ASSIGNMENT OPERATORS | 
|---|
|  | 688 |  | 
|---|
|  | 689 | mat4& mat4::operator = ( const mat4& m ) | 
|---|
|  | 690 | { v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3]; | 
|---|
|  | 691 | return *this; } | 
|---|
|  | 692 |  | 
|---|
|  | 693 | mat4& mat4::operator += ( const mat4& m ) | 
|---|
|  | 694 | { v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; v[3] += m.v[3]; | 
|---|
|  | 695 | return *this; } | 
|---|
|  | 696 |  | 
|---|
|  | 697 | mat4& mat4::operator -= ( const mat4& m ) | 
|---|
|  | 698 | { v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; v[3] -= m.v[3]; | 
|---|
|  | 699 | return *this; } | 
|---|
|  | 700 |  | 
|---|
|  | 701 | mat4& mat4::operator *= ( const double d ) | 
|---|
|  | 702 | { v[0] *= d; v[1] *= d; v[2] *= d; v[3] *= d; return *this; } | 
|---|
|  | 703 |  | 
|---|
|  | 704 | mat4& mat4::operator /= ( const double d ) | 
|---|
|  | 705 | { v[0] /= d; v[1] /= d; v[2] /= d; v[3] /= d; return *this; } | 
|---|
|  | 706 |  | 
|---|
|  | 707 | vec4& mat4::operator [] ( int i) { | 
|---|
|  | 708 | if (i < VX || i > VW) | 
|---|
|  | 709 | V_ERROR("mat4 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 710 | return v[i]; | 
|---|
|  | 711 | } | 
|---|
|  | 712 |  | 
|---|
|  | 713 | const vec4& mat4::operator [] ( int i) const { | 
|---|
|  | 714 | if (i < VX || i > VW) | 
|---|
|  | 715 | V_ERROR("mat4 [] operator: illegal access; index = " << i << '\n') | 
|---|
|  | 716 | return v[i]; | 
|---|
|  | 717 | } | 
|---|
|  | 718 |  | 
|---|
|  | 719 | // SPECIAL FUNCTIONS; | 
|---|
|  | 720 |  | 
|---|
|  | 721 | mat4 mat4::transpose() const { | 
|---|
|  | 722 | return mat4(vec4(v[0][0], v[1][0], v[2][0], v[3][0]), | 
|---|
|  | 723 | vec4(v[0][1], v[1][1], v[2][1], v[3][1]), | 
|---|
|  | 724 | vec4(v[0][2], v[1][2], v[2][2], v[3][2]), | 
|---|
|  | 725 | vec4(v[0][3], v[1][3], v[2][3], v[3][3])); | 
|---|
|  | 726 | } | 
|---|
|  | 727 |  | 
|---|
|  | 728 | mat4 mat4::inverse()        // Gauss-Jordan elimination with partial pivoting | 
|---|
|  | 729 | { | 
|---|
|  | 730 | mat4 a(*this),          // As a evolves from original mat into identity | 
|---|
|  | 731 | b(identity3D());   // b evolves from identity into inverse(a) | 
|---|
|  | 732 | int i, j, i1; | 
|---|
|  | 733 |  | 
|---|
|  | 734 | // Loop over cols of a from left to right, eliminating above and below diag | 
|---|
|  | 735 | for (j=0; j<4; j++) {   // Find largest pivot in column j among rows j..3 | 
|---|
|  | 736 | i1 = j;                 // Row with largest pivot candidate | 
|---|
|  | 737 | for (i=j+1; i<4; i++) | 
|---|
|  | 738 | if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) | 
|---|
|  | 739 | i1 = i; | 
|---|
|  | 740 |  | 
|---|
|  | 741 | // Swap rows i1 and j in a and b to put pivot on diagonal | 
|---|
|  | 742 | swap(a.v[i1], a.v[j]); | 
|---|
|  | 743 | swap(b.v[i1], b.v[j]); | 
|---|
|  | 744 |  | 
|---|
|  | 745 | // Scale row j to have a unit diagonal | 
|---|
|  | 746 | if (a.v[j].n[j]==0.) | 
|---|
|  | 747 | V_ERROR("mat4::inverse: singular matrix; can't invert\n"); | 
|---|
|  | 748 | b.v[j] /= a.v[j].n[j]; | 
|---|
|  | 749 | a.v[j] /= a.v[j].n[j]; | 
|---|
|  | 750 |  | 
|---|
|  | 751 | // Eliminate off-diagonal elems in col j of a, doing identical ops to b | 
|---|
|  | 752 | for (i=0; i<4; i++) | 
|---|
|  | 753 | if (i!=j) { | 
|---|
|  | 754 | b.v[i] -= a.v[i].n[j]*b.v[j]; | 
|---|
|  | 755 | a.v[i] -= a.v[i].n[j]*a.v[j]; | 
|---|
|  | 756 | } | 
|---|
|  | 757 | } | 
|---|
|  | 758 | return b; | 
|---|
|  | 759 | } | 
|---|
|  | 760 |  | 
|---|
|  | 761 | mat4& mat4::apply(V_FCT_PTR fct) | 
|---|
|  | 762 | { v[VX].apply(fct); v[VY].apply(fct); v[VZ].apply(fct); v[VW].apply(fct); | 
|---|
|  | 763 | return *this; } | 
|---|
|  | 764 |  | 
|---|
|  | 765 |  | 
|---|
|  | 766 | // FRIENDS | 
|---|
|  | 767 |  | 
|---|
|  | 768 | namespace sc { | 
|---|
|  | 769 |  | 
|---|
|  | 770 | mat4 operator - (const mat4& a) | 
|---|
|  | 771 | { return mat4(-a.v[0], -a.v[1], -a.v[2], -a.v[3]); } | 
|---|
|  | 772 |  | 
|---|
|  | 773 | mat4 operator + (const mat4& a, const mat4& b) | 
|---|
|  | 774 | { return mat4(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2], | 
|---|
|  | 775 | a.v[3] + b.v[3]); | 
|---|
|  | 776 | } | 
|---|
|  | 777 |  | 
|---|
|  | 778 | mat4 operator - (const mat4& a, const mat4& b) | 
|---|
|  | 779 | { return mat4(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2], a.v[3] - b.v[3]); } | 
|---|
|  | 780 |  | 
|---|
|  | 781 | mat4 operator * (const mat4& a, const mat4& b) { | 
|---|
|  | 782 | #define ROWCOL(i, j) a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + \ | 
|---|
|  | 783 | a.v[i].n[2]*b.v[2][j] + a.v[i].n[3]*b.v[3][j] | 
|---|
|  | 784 | return mat4( | 
|---|
|  | 785 | vec4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)), | 
|---|
|  | 786 | vec4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)), | 
|---|
|  | 787 | vec4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)), | 
|---|
|  | 788 | vec4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3)) | 
|---|
|  | 789 | ); | 
|---|
|  | 790 | } | 
|---|
|  | 791 |  | 
|---|
|  | 792 | mat4 operator * (const mat4& a, const double d) | 
|---|
|  | 793 | { return mat4(a.v[0] * d, a.v[1] * d, a.v[2] * d, a.v[3] * d); } | 
|---|
|  | 794 |  | 
|---|
|  | 795 | mat4 operator * (const double d, const mat4& a) | 
|---|
|  | 796 | { return a*d; } | 
|---|
|  | 797 |  | 
|---|
|  | 798 | mat4 operator / (const mat4& a, const double d) | 
|---|
|  | 799 | { return mat4(a.v[0] / d, a.v[1] / d, a.v[2] / d, a.v[3] / d); } | 
|---|
|  | 800 |  | 
|---|
|  | 801 | int operator == (const mat4& a, const mat4& b) | 
|---|
|  | 802 | { return ((a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]) && | 
|---|
|  | 803 | (a.v[3] == b.v[3])); } | 
|---|
|  | 804 |  | 
|---|
|  | 805 | int operator != (const mat4& a, const mat4& b) | 
|---|
|  | 806 | { return !(a == b); } | 
|---|
|  | 807 |  | 
|---|
|  | 808 | ostream& operator << (ostream& s, mat4& m) | 
|---|
|  | 809 | { return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ] << '\n' << m.v[VW]; } | 
|---|
|  | 810 |  | 
|---|
|  | 811 | istream& operator >> (istream& s, mat4& m) | 
|---|
|  | 812 | { | 
|---|
|  | 813 | mat4    m_tmp; | 
|---|
|  | 814 |  | 
|---|
|  | 815 | s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ] >> m_tmp[VW]; | 
|---|
|  | 816 | if (s) | 
|---|
|  | 817 | m = m_tmp; | 
|---|
|  | 818 | return s; | 
|---|
|  | 819 | } | 
|---|
|  | 820 |  | 
|---|
|  | 821 | void swap(mat4& a, mat4& b) | 
|---|
|  | 822 | { mat4 tmp(a); a = b; b = tmp; } | 
|---|
|  | 823 |  | 
|---|
|  | 824 | } | 
|---|
|  | 825 |  | 
|---|
|  | 826 |  | 
|---|
|  | 827 | /**************************************************************** | 
|---|
|  | 828 | *                                                               * | 
|---|
|  | 829 | *              2D functions and 3D functions                    * | 
|---|
|  | 830 | *                                                               * | 
|---|
|  | 831 | ****************************************************************/ | 
|---|
|  | 832 |  | 
|---|
|  | 833 | namespace sc { | 
|---|
|  | 834 |  | 
|---|
|  | 835 | mat3 identity2D() | 
|---|
|  | 836 | {   return mat3(vec3(1.0, 0.0, 0.0), | 
|---|
|  | 837 | vec3(0.0, 1.0, 0.0), | 
|---|
|  | 838 | vec3(0.0, 0.0, 1.0)); } | 
|---|
|  | 839 |  | 
|---|
|  | 840 | mat3 translation2D(const vec2& v) | 
|---|
|  | 841 | {   return mat3(vec3(1.0, 0.0, v[VX]), | 
|---|
|  | 842 | vec3(0.0, 1.0, v[VY]), | 
|---|
|  | 843 | vec3(0.0, 0.0, 1.0)); } | 
|---|
|  | 844 |  | 
|---|
|  | 845 | mat3 rotation2D(const vec2& Center, const double angleDeg) { | 
|---|
|  | 846 | double  angleRad = angleDeg * M_PI / 180.0, | 
|---|
|  | 847 | c = cos(angleRad), | 
|---|
|  | 848 | s = sin(angleRad); | 
|---|
|  | 849 |  | 
|---|
|  | 850 | return mat3(vec3(c, -s, Center[VX] * (1.0-c) + Center[VY] * s), | 
|---|
|  | 851 | vec3(s, c, Center[VY] * (1.0-c) - Center[VX] * s), | 
|---|
|  | 852 | vec3(0.0, 0.0, 1.0)); | 
|---|
|  | 853 | } | 
|---|
|  | 854 |  | 
|---|
|  | 855 | mat3 scaling2D(const vec2& scaleVector) | 
|---|
|  | 856 | {   return mat3(vec3(scaleVector[VX], 0.0, 0.0), | 
|---|
|  | 857 | vec3(0.0, scaleVector[VY], 0.0), | 
|---|
|  | 858 | vec3(0.0, 0.0, 1.0)); } | 
|---|
|  | 859 |  | 
|---|
|  | 860 | mat4 identity3D() | 
|---|
|  | 861 | {   return mat4(vec4(1.0, 0.0, 0.0, 0.0), | 
|---|
|  | 862 | vec4(0.0, 1.0, 0.0, 0.0), | 
|---|
|  | 863 | vec4(0.0, 0.0, 1.0, 0.0), | 
|---|
|  | 864 | vec4(0.0, 0.0, 0.0, 1.0)); } | 
|---|
|  | 865 |  | 
|---|
|  | 866 | mat4 translation3D(const vec3& v) | 
|---|
|  | 867 | {   return mat4(vec4(1.0, 0.0, 0.0, v[VX]), | 
|---|
|  | 868 | vec4(0.0, 1.0, 0.0, v[VY]), | 
|---|
|  | 869 | vec4(0.0, 0.0, 1.0, v[VZ]), | 
|---|
|  | 870 | vec4(0.0, 0.0, 0.0, 1.0)); } | 
|---|
|  | 871 |  | 
|---|
|  | 872 | mat4 rotation3D(const vec3& Axisarg, const double angleDeg) { | 
|---|
|  | 873 | double  angleRad = angleDeg * M_PI / 180.0, | 
|---|
|  | 874 | c = cos(angleRad), | 
|---|
|  | 875 | s = sin(angleRad), | 
|---|
|  | 876 | t = 1.0 - c; | 
|---|
|  | 877 |  | 
|---|
|  | 878 | vec3 Axis(Axisarg); | 
|---|
|  | 879 | Axis.normalize(); | 
|---|
|  | 880 | return mat4(vec4(t * Axis[VX] * Axis[VX] + c, | 
|---|
|  | 881 | t * Axis[VX] * Axis[VY] - s * Axis[VZ], | 
|---|
|  | 882 | t * Axis[VX] * Axis[VZ] + s * Axis[VY], | 
|---|
|  | 883 | 0.0), | 
|---|
|  | 884 | vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ], | 
|---|
|  | 885 | t * Axis[VY] * Axis[VY] + c, | 
|---|
|  | 886 | t * Axis[VY] * Axis[VZ] - s * Axis[VX], | 
|---|
|  | 887 | 0.0), | 
|---|
|  | 888 | vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY], | 
|---|
|  | 889 | t * Axis[VY] * Axis[VZ] + s * Axis[VX], | 
|---|
|  | 890 | t * Axis[VZ] * Axis[VZ] + c, | 
|---|
|  | 891 | 0.0), | 
|---|
|  | 892 | vec4(0.0, 0.0, 0.0, 1.0)); | 
|---|
|  | 893 | } | 
|---|
|  | 894 |  | 
|---|
|  | 895 | mat4 scaling3D(const vec3& scaleVector) | 
|---|
|  | 896 | {   return mat4(vec4(scaleVector[VX], 0.0, 0.0, 0.0), | 
|---|
|  | 897 | vec4(0.0, scaleVector[VY], 0.0, 0.0), | 
|---|
|  | 898 | vec4(0.0, 0.0, scaleVector[VZ], 0.0), | 
|---|
|  | 899 | vec4(0.0, 0.0, 0.0, 1.0)); } | 
|---|
|  | 900 |  | 
|---|
|  | 901 | mat4 perspective3D(const double d) | 
|---|
|  | 902 | {   return mat4(vec4(1.0, 0.0, 0.0, 0.0), | 
|---|
|  | 903 | vec4(0.0, 1.0, 0.0, 0.0), | 
|---|
|  | 904 | vec4(0.0, 0.0, 1.0, 0.0), | 
|---|
|  | 905 | vec4(0.0, 0.0, 1.0/d, 0.0)); } | 
|---|
|  | 906 |  | 
|---|
|  | 907 | } | 
|---|