00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __MX_MATH__H_
00022 #define __MX_MATH__H_
00023 #include<cmath>
00024 #include<string>
00025 #include<iostream>
00026 #include<fstream>
00027 #include<cstdio>
00028 #include<vector>
00029 #include "mx_tok.h"
00030 #include "mx3d_graphics.h"
00031
00032
00033 namespace mx3d {
00034
00035 const float PI = 3.141592654f;
00036
00037 float sin_look[361];
00038 float cos_look[361];
00039
00040 inline void BuildTables() {
00041 for (int ang = 0; ang <= 360; ang++) {
00042 float theta = (float)ang*PI/(float)180;
00043 cos_look[ang] = cos(theta);
00044 sin_look[ang] = sin(theta);
00045 }
00046 }
00047
00048 inline float fast_cosf(float theta) {
00049 theta = fmodf(theta,360);
00050
00051 if (theta < 0) theta+=360.0;
00052
00053 int theta_int = (int)theta;
00054 float theta_frac = theta - theta_int;
00055
00056 return(cos_look[theta_int] +
00057 theta_frac*(cos_look[theta_int+1] - cos_look[theta_int]));
00058 }
00059
00060 inline float fast_sinf(float theta) {
00061 theta = fmodf(theta,360);
00062 if (theta < 0) theta+=360.0;
00063 int theta_int = (int)theta;
00064 float theta_frac = theta - theta_int;
00065 return(sin_look[theta_int] + theta_frac*(sin_look[theta_int+1] - sin_look[theta_int]));
00066 }
00067
00068 inline float deg2rad(float ang) {
00069 return ((ang*PI/180.0f));
00070 }
00071
00072 inline int rrand(int x, int y) {
00073 return (x) + (rand()%((y)-(x)+1));
00074 }
00075
00076
00077 class vec2D {
00078 public:
00079 union {
00080 float vec[2];
00081 struct {
00082 float x,y;
00083 };
00084
00085 };
00086
00087 vec2D(float x, float y) {
00088 this->x = x, this->y = y;
00089 }
00090
00091
00092 vec2D() {
00093 x = 0;
00094 y = 0;
00095 }
00096
00097 void Set(float x, float y) {
00098 this->x = x, this->y = y;
00099 }
00100
00101
00102 void operator=(const vec2D &v) {
00103 x = v.x, y = v.y;
00104 }
00105
00106
00107 vec2D operator+(const vec2D &v) {
00108 vec2D p = *this;
00109 p.x += v.x;
00110 p.y += v.y;
00111 return p;
00112 }
00113
00114
00115 void operator+=(const vec2D &v) {
00116 x += v.x;
00117 y += v.y;
00118 }
00119
00120
00121 vec2D operator-(const vec2D &v) {
00122 vec2D p = *this;
00123 p.x -= v.x;
00124 p.y -= v.y;
00125 return p;
00126 }
00127
00128
00129 void operator-=(const vec2D &v) {
00130 x -= v.x;
00131 y -= v.y;
00132 }
00133
00134
00135 vec2D Scale(float k) {
00136 vec2D p = *this;
00137 p.x = k * p.x;
00138 p.y = k * p.y;
00139 return p;
00140 }
00141
00142
00143 void ScaleThis(float k) {
00144 x *= k;
00145 y *= k;
00146 }
00147
00148
00149 float DotProduct(const vec2D &v) {
00150 return ((x*v.x) + (y*v.y));
00151 }
00152
00153
00154 float Length() {
00155 return sqrtf(x * x + y * y);
00156 }
00157
00158
00159 void Normalize() {
00160 float length = sqrtf(x * x + y * y);
00161 if ( length < float(1E-5))
00162 return;
00163 float inv = 1/length;
00164 x = x * inv;
00165 y = y * inv;
00166 }
00167
00168
00169 void Normalize(vec2D &v) {
00170 float length = sqrtf(x * x + y * y);
00171 if ( length < float(1E-5))
00172 return;
00173 float inv = 1/length;
00174 v.x = x * inv;
00175 v.y = y * inv;
00176 }
00177
00178
00179 float Cos(vec2D &v) {
00180 float the_dot = DotProduct(v);
00181 return ( the_dot / Length() * v.Length() );
00182 }
00183
00184 std::string Print(std::string v = "v") {
00185 std::string p;
00186 char dat[256];
00187 sprintf(dat,"%s<%f,%f>", v.c_str(), x,y);
00188 p = dat;
00189 return p;
00190 }
00191
00192
00193 friend std::ostream &operator<<(std::ostream &out,vec2D &v) {
00194 out << v.Print();
00195 return out;
00196 }
00197
00198
00199 friend std::istream& operator>>(std::istream &in, vec2D &v) {
00200 fflush(stdin);
00201 in >> v.x >> v.y;
00202 return in;
00203 }
00204
00205 };
00206
00207
00208 class vec3D {
00209 public:
00210 union {
00211 float vec[3];
00212
00213 struct {
00214
00215 float x,y,z;
00216
00217 };
00218
00219 };
00220
00221 vec3D(float x, float y, float z) {
00222 this->x = x, this->y = y, this->z = z;
00223 }
00224
00225
00226 vec3D() {
00227 x = y = z = 0;
00228 }
00229
00230 virtual ~vec3D() { }
00231
00232
00233 void Set(float x, float y, float z) {
00234 this->x = x, this->y = y, this->z = z;
00235 }
00236
00237
00238 void operator=(const vec3D &v ) {
00239 this->x = v.x, this->y = v.y, this->z = v.z;
00240 }
00241
00242
00243 virtual vec3D operator+(const vec3D &v) {
00244 vec3D p = *this;
00245 p.x += v.x;
00246 p.y += v.y;
00247 p.z += v.z;
00248 return p;
00249 }
00250
00251
00252 virtual void operator+=(const vec3D &v) {
00253 x += v.x;
00254 y += v.y;
00255 z += v.z;
00256 }
00257
00258
00259 vec3D operator-(const vec3D &v) {
00260 vec3D p = *this;
00261 p.x -= v.x;
00262 p.y -= v.y;
00263 p.z -= v.z;
00264 return p;
00265 }
00266
00267
00268 void operator-=(const vec3D &v) {
00269 x -= v.x;
00270 y -= v.y;
00271 z -= v.z;
00272 }
00273
00274
00275 vec3D Scale(float k) {
00276 vec3D p = *this;
00277 p.x *= k;
00278 p.y *= k;
00279 p.z *= k;
00280 return p;
00281 }
00282
00283
00284 void ScaleThis(float k) {
00285 x *= k;
00286 y *= k;
00287 z *= k;
00288 }
00289
00290
00291 float DotProduct(const vec3D &v) {
00292 return ((x*v.x) + (y*v.y) + (z*v.z));
00293 }
00294
00295
00296 vec3D CrossProduct(const vec3D &v) {
00297 vec3D p;
00298 p.x = ( ( y * v.z ) - ( z * v.y ) );
00299 p.y = -( ( x * v.z ) - ( z * v.x ) );
00300 p.z = ( ( x * v.y ) - ( y * v.x ) );
00301 return p;
00302 }
00303
00304
00305 float Length() {
00306 return sqrtf( x * x + y * y + z * z );
00307 }
00308
00309
00310 void Normalize() {
00311 float len = sqrtf( x * x + y * y + z * z );
00312 if(len < float(1E-5))
00313 return;
00314 float inv = 1/len;
00315 x *= inv;
00316 y *= inv;
00317 z *= inv;
00318 }
00319
00320
00321 void Normalize(vec3D &v) {
00322 float len = sqrtf( x * x + y * y + z * z );
00323 if(len < float(1E-5)) {
00324 v = *this;
00325 return;
00326 }
00327 float inv = 1/len;
00328 v.x = x * inv;
00329 v.y = y * inv;
00330 v.z = z * inv;
00331 }
00332
00333
00334 float Cos(vec3D &v) {
00335 float dot = DotProduct(v);
00336 return (dot / Length() * v.Length());
00337 }
00338
00339
00340 virtual std::string Print(std::string v = "v") {
00341 std::string p;
00342 char dat[256];
00343 sprintf(dat,"%s<%f,%f,%f>", v.c_str(), x,y,z);
00344 p = dat;
00345 return p;
00346 }
00347
00348
00349 friend std::ostream &operator<<(std::ostream &out, vec3D &v) {
00350 out << v.Print();
00351 return out;
00352 }
00353
00354
00355 friend std::istream &operator>>(std::istream &in, vec3D &v) {
00356 fflush(stdin);
00357 in >> v.x >> v.y >> v.z;
00358 return in;
00359 }
00360
00361 };
00362
00363
00364 class vec4D {
00365 public:
00366 union {
00367 float vec[4];
00368
00369 struct {
00370
00371 float x,y,z,w;
00372
00373 };
00374
00375 };
00376
00377 vec4D(float x, float y, float z, float w) {
00378 this->x = x, this->y = y, this->z = z, this->w = 1;
00379 }
00380
00381 vec4D() {
00382 w = 1;
00383 }
00384
00385 vec4D(const vec4D ©) {
00386 this->x = copy.x;
00387 this->y = copy.y;
00388 this->z = copy.z;
00389 this->w = copy.w;
00390 }
00391
00392
00393 ~vec4D() { }
00394
00395 void Set(float x, float y, float z, float w = 1) {
00396 this->x = x, this->y = y, this->z = z, this->w = w;
00397 }
00398
00399 void Set(const vec4D &v) {
00400 this->x = v.x, this->y = v.y, this->z = v.z, this->w = v.w;
00401 }
00402
00403 vec4D &operator=(const vec4D &v ) {
00404 this->x = v.x, this->y = v.y, this->z = v.z;
00405 w = 1;
00406 return *this;
00407 }
00408
00409
00410 vec4D operator+(const vec4D &v) {
00411 vec4D p = *this;
00412 p.x += v.x;
00413 p.y += v.y;
00414 p.z += v.z;
00415 p.w += v.w;
00416 return p;
00417 }
00418 vec4D operator*(const vec4D &v) {
00419 vec4D p = *this;
00420 p.x *= v.x;
00421 p.y *= v.y;
00422 p.z *= v.z;
00423 p.w *= v.w;
00424 return p;
00425 }
00426
00427 void AddVec(vec4D &src, vec4D &out) {
00428 src.x += out.x;
00429 src.y += out.y;
00430 src.z += out.z;
00431 src.w = 1;
00432 }
00433
00434 void operator+=(const vec4D &v) {
00435 x += v.x;
00436 y += v.y;
00437 z += v.z;
00438 w = 1;
00439 }
00440
00441
00442 vec4D operator-(const vec3D &v) {
00443 vec4D p = *this;
00444 p.x -= v.x;
00445 p.y -= v.y;
00446 p.z -= v.z;
00447 p.w = 1;
00448 return p;
00449 }
00450
00451
00452 void operator-=(const vec4D &v) {
00453 x -= v.x;
00454 y -= v.y;
00455 z -= v.z;
00456 w = 1;
00457 }
00458
00459
00460 vec4D Scale(float k) {
00461 vec4D p = *this;
00462 p.x *= k;
00463 p.y *= k;
00464 p.z *= k;
00465 p.w = 1;
00466 return p;
00467 }
00468
00469
00470 void ScaleThis(float k) {
00471 x *= k;
00472 y *= k;
00473 z *= k;
00474 w = 1;
00475 }
00476
00477
00478 float DotProduct(const vec4D &v) {
00479 return ((x*v.x) + (y*v.y) + (z*v.z));
00480 }
00481
00482
00483 vec4D CrossProduct(const vec4D &v) {
00484 vec4D p;
00485 p.x = ( ( y * v.z ) - ( z * v.y ) );
00486 p.y = -( ( x * v.z ) - ( z * v.x ) );
00487 p.z = ( ( x * v.y ) - ( y * v.x ) );
00488 p.w = 1;
00489 return p;
00490 }
00491
00492
00493 float Length() {
00494 return sqrtf( x * x + y * y + z * z );
00495 }
00496
00497
00498 void Normalize() {
00499 float len = sqrtf( x * x + y * y + z * z );
00500 if(len < float(1E-5))
00501 return;
00502 float inv = 1/len;
00503 x *= inv;
00504 y *= inv;
00505 z *= inv;
00506 w = 1;
00507 }
00508
00509
00510 void Normalize(vec4D &v) {
00511 float len = sqrtf( x * x + y * y + z * z );
00512 if(len < float(1E-5)) {
00513 v = *this;
00514 return;
00515 }
00516 float inv = 1/len;
00517 v.x = x * inv;
00518 v.y = y * inv;
00519 v.z = z * inv;
00520 v.w = 1;
00521 }
00522
00523
00524 float Cos(vec4D &v) {
00525 float dot = DotProduct(v);
00526 return (dot / Length() * v.Length());
00527 }
00528
00529 std::string Print(std::string v= "v") {
00530 std::string p;
00531 char dat[300];
00532 sprintf(dat,"%s<%f,%f,%f,%f>", v.c_str(), x,y,z,w);
00533 p = dat;
00534 return p;
00535 }
00536
00537 void Build(vec4D &vec) {
00538 x = vec.x - x;
00539 y = vec.y - y;
00540 z = vec.z - z;
00541 w = 1;
00542 }
00543
00544 vec4D Build(vec4D &in , vec4D &by) {
00545 vec4D p;
00546 p.x = by.x - in.x;
00547 p.y = by.y - in.y;
00548 p.z = by.z - in.z;
00549 p.w = 1;
00550 return p;
00551 }
00552
00553 friend std::ostream &operator<<(std::ostream &out, vec4D &v) {
00554 out << v.Print();
00555 return out;
00556 }
00557
00558 friend std::istream &operator>>(std::istream &in, vec4D &v) {
00559 in >> v.x >> v.y >> v.z >> v.w;
00560 return in;
00561 }
00562 };
00563
00564
00565 class Mat1D {
00566 public:
00567 float mat[2];
00568
00569 Mat1D(float m0, float m1) {
00570 mat[0] = m0, mat[1] = m1;
00571 }
00572
00573 Mat1D() {
00574 memset(this, 0, sizeof(Mat1D));
00575 }
00576
00577 virtual ~Mat1D() { }
00578
00579
00580 void Set(float m0, float m1) {
00581 mat[0] = m0, mat[1] = m1;
00582 }
00583
00584
00585 void operator=(Mat1D &m) {
00586 memcpy(this,&m,sizeof(Mat1D));
00587 }
00588
00589 Mat1D operator+(const Mat1D &m) {
00590 Mat1D p = *this;
00591 p.mat[0] += m.mat[0];
00592 p.mat[1] += m.mat[1];
00593 return p;
00594 }
00595
00596 Mat1D operator-(const Mat1D &m) {
00597 Mat1D p = *this;
00598 p.mat[0] -= m.mat[0];
00599 p.mat[1] -= m.mat[1];
00600 return p;
00601 }
00602
00603 Mat1D operator*(const Mat1D &m) {
00604 Mat1D p = *this;
00605 p.mat[0] *= m.mat[0];
00606 p.mat[1] *= m.mat[1];
00607 return p;
00608 }
00609
00610 virtual std::string Print(std::string m = "m") {
00611 char dat[256];
00612 std::string p;
00613 sprintf(dat,"%s = { ", m.c_str());
00614 for(unsigned int i = 0; i < 2; i++)
00615 sprintf(dat,"%s%f ", dat, mat[i]);
00616 sprintf(dat,"%s}\n", dat);
00617 p = dat;
00618 return p;
00619 }
00620
00621 };
00622
00623
00624 class Mat1x3D {
00625 public:
00626 float mat[3];
00627 Mat1x3D() {
00628 memset(this, 0, sizeof(Mat1x3D));
00629
00630 }
00631
00632 Mat1x3D(float m0, float m1 , float m2) {
00633 mat[0] = m0, mat[1] = m1, mat[2] = m2;
00634 }
00635 };
00636
00637 class Mat1x4D {
00638 public:
00639 float mat[4];
00640 Mat1x4D() {
00641
00642 memset(this, 0, sizeof(Mat1x4D));
00643 }
00644
00645 Mat1x4D(float m0, float m1, float m2, float m3) {
00646 mat[0] = m0, mat[1] = m1, mat[2] = m2, mat[3] = m3;
00647 }
00648 };
00649
00650 class Mat4x3D {
00651 public:
00652 float mat[4][3];
00653 Mat4x3D() {
00654 memset(this,0,sizeof(Mat4x3D));
00655 }
00656 };
00657
00658
00659 class Mat2D {
00660 public:
00661 float mat[2][2];
00662
00663 Mat2D() {
00664 memset(mat,0,sizeof(mat));
00665 }
00666
00667 virtual ~Mat2D() { }
00668
00669
00670 Mat2D(float m00, float m01, float m10, float m11) {
00671 Set(m00,m01,m10,m11);
00672 }
00673
00674
00675 void Set(float m00, float m01, float m10, float m11) {
00676 mat[0][0] = m00;
00677 mat[0][1] = m01;
00678 mat[1][0] = m10;
00679 mat[1][1] = m11;
00680 }
00681
00682
00683 void LoadIdentity() {
00684 mat[0][0] = 1, mat[0][1] = 0;
00685 mat[1][0] = 0, mat[1][1] = 1;
00686 }
00687
00688
00689 void operator=(Mat2D &m) {
00690 memcpy(this,&m,sizeof(Mat2D));
00691 }
00692
00693
00694 Mat2D operator+(const Mat2D &mat) {
00695 Mat2D m = *this;
00696 m.mat[0][0] += mat.mat[0][0];
00697 m.mat[0][1] += mat.mat[0][1];
00698 m.mat[1][0] += mat.mat[1][0];
00699 m.mat[1][1] += mat.mat[1][1];
00700 return m;
00701 }
00702
00703
00704 void operator+=(const Mat2D &m) {
00705 mat[0][0] += m.mat[0][0];
00706 mat[0][1] += m.mat[0][1];
00707 mat[1][0] += m.mat[1][0];
00708 mat[1][1] += m.mat[1][1];
00709 }
00710
00711
00712 Mat2D operator-(const Mat2D &mat) {
00713 Mat2D m = *this;
00714 m.mat[0][0] -= mat.mat[0][0];
00715 m.mat[0][1] -= mat.mat[0][1];
00716 m.mat[1][0] -= mat.mat[1][0];
00717 m.mat[1][1] -= mat.mat[1][1];
00718 return m;
00719 }
00720
00721
00722 void operator-=(const Mat2D &m) {
00723 mat[0][0] -= m.mat[0][0];
00724 mat[0][1] -= m.mat[0][1];
00725 mat[1][0] -= m.mat[1][0];
00726 mat[1][1] -= m.mat[1][1];
00727 }
00728
00729
00730 Mat2D operator*(const Mat2D &mat) {
00731 Mat2D m = *this;
00732 m.mat[0][0] *= mat.mat[0][0];
00733 m.mat[0][1] *= mat.mat[0][1];
00734 m.mat[1][0] *= mat.mat[1][0];
00735 m.mat[1][1] *= mat.mat[1][1];
00736 return m;
00737 }
00738
00739
00740 void operator*=(const Mat2D &m) {
00741 mat[0][0] *= m.mat[0][0];
00742 mat[0][1] *= m.mat[0][1];
00743 mat[1][0] *= m.mat[1][0];
00744 mat[1][1] *= m.mat[1][1];
00745 }
00746
00747
00748 bool Inverse(Mat2D &m) {
00749 float d = mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
00750 if(fabs(d) < float(1E-5))
00751 return false;
00752 float inv = 1.0f/d;
00753 m.mat[0][0] = mat[1][1] * inv;
00754 m.mat[0][1] = -mat[0][1] * inv;
00755 m.mat[1][0] = -mat[1][0] * inv;
00756 m.mat[1][1] = mat[0][0] * inv;
00757 return true;
00758 }
00759
00760
00761 float Determinate() {
00762 return (mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]);
00763 }
00764
00765 void Swap(Mat2D &m, int c, Mat1D &m2) {
00766 m.mat[0][c] = m2.mat[0];
00767 m.mat[1][c] = m2.mat[1];
00768 }
00769
00770 bool Solve2x2(Mat2D &m1, Mat1D &m2, Mat1D &m3) {
00771 float det_a = m1.Determinate();
00772 if(fabs(det_a) < float(1E-5))
00773 return false;
00774 Mat2D wm;
00775 wm = m1;
00776 Swap(wm,0,m3);
00777 float det_a_b = wm.Determinate();
00778 m2.mat[0] = det_a_b / det_a;
00779 wm = m1;
00780 Swap(wm,1,m3);
00781 det_a_b = wm.Determinate();
00782 m2.mat[1] = det_a_b / det_a;
00783 return true;
00784 }
00785
00786
00787 virtual std::string Print(std::string m = "m") {
00788 std::string p;
00789 char dat[256];
00790 sprintf(dat,"%s = {\n", m.c_str());
00791 for(unsigned int i = 0; i < 2; i++) {
00792 for(unsigned int z = 0; z < 2; z++) {
00793 sprintf(dat,"%s%f ", dat,mat[i][z]);
00794 }
00795 sprintf(dat,"%s\n", dat);
00796 }
00797 sprintf(dat,"%s}\n", dat);
00798 p = dat;
00799 return p;
00800 }
00801 };
00802
00803
00804 class Mat3D {
00805 public:
00806 float mat[3][3];
00807 Mat3D() {
00808 memset(this,0,sizeof(Mat3D));
00809 }
00810
00811 Mat3D(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) {
00812 Set(m00,01,m02,m10,m11,m12,m20,m21,m22);
00813 }
00814
00815
00816 void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) {
00817 mat[0][0] = m00;
00818 mat[0][1] = m01;
00819 mat[0][2] = m02;
00820 mat[1][0] = m10;
00821 mat[1][1] = m11;
00822 mat[1][2] = m12;
00823 mat[2][0] = m20;
00824 mat[2][1] = m21;
00825 mat[2][2] = m22;
00826 }
00827
00828
00829 void LoadIdentity() {
00830 mat[0][0] = 1, mat[0][1] = 0, mat[0][2] = 0;
00831 mat[1][0] = 0, mat[1][1] = 1, mat[1][2] = 0;
00832 mat[2][0] = 0, mat[2][1] = 0, mat[2][2] = 1;
00833 }
00834
00835
00836 Mat3D operator+(const Mat3D &m) {
00837 Mat3D p = *this;
00838 for(i = 0; i < 3; i++)
00839 for(z = 0; z < 3; z++)
00840 p.mat[i][z] += m.mat[i][z];
00841 return p;
00842 }
00843
00844
00845 void operator+=(const Mat3D &m) {
00846 for(i = 0; i < 3; i++)
00847 for(z = 0; z < 3; z++)
00848 mat[i][z] += m.mat[i][z];
00849 }
00850
00851
00852 Mat3D operator*(const Mat3D &m) {
00853 Mat3D p = *this;
00854 for(i = 0; i < 3; i++)
00855 for(z = 0; z < 3; z++)
00856 p.mat[i][z] *= m.mat[i][z];
00857 return p;
00858 }
00859
00860
00861 void operator*=(const Mat3D &m) {
00862 for(i = 0; i < 3; i++)
00863 for(z = 0; z < 3; z++)
00864 mat[i][z] *= m.mat[i][z];
00865 }
00866
00867 void MulVec(vec3D &in, vec3D &out) {
00868 for(z = 0; z < 3; z++) {
00869 float s = 0;
00870 for(i = 0; i < 3; i++) {
00871 s += in.vec[z] * mat[i][z];
00872 }
00873 out.vec[z] = s;
00874 }
00875 }
00876
00877
00878 bool Inverse(Mat3D &out) {
00879 float d = mat[0][0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2]) - mat[0][1] * (mat[1][0] * mat[2][2] - mat[2][0] * mat[1][2]) + mat[0][2] * (mat[1][0] * mat[2][1] - mat[2][0] * mat[1][1]);
00880 if(fabs(d) < float(1E-5))
00881 return false;
00882
00883 float inv = 1.0f/d;
00884
00885 out.mat[0][0] = inv*(mat[1][1]*mat[2][2]-mat[2][1]*mat[1][2]);
00886 out.mat[1][0] = -inv*(mat[1][0]*mat[2][2]-mat[2][0]*mat[1][2]);
00887 out.mat[2][0] = inv*(mat[1][0]*mat[2][1]-mat[2][0]*mat[1][1]);
00888
00889 out.mat[1][0] = -inv*(mat[0][1]*mat[2][2]-mat[2][1]*mat[0][2]);
00890 out.mat[1][1] = inv*(mat[0][0]*mat[2][2]-mat[2][0]*mat[0][2]);
00891 out.mat[2][1] = -inv*(mat[0][0]*mat[2][1]-mat[2][0]*mat[0][1]);
00892
00893 out.mat[0][2] = inv*(mat[0][1]*mat[1][2]-mat[1][1]*mat[0][2]);
00894 out.mat[1][2] = -inv*(mat[0][0]*mat[1][2]-mat[1][0]*mat[0][2]);
00895 out.mat[2][2] = inv*(mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1]);
00896
00897 return true;
00898
00899 }
00900
00901
00902 float Determinate() {
00903 return mat[0][0]*(mat[1][1]*mat[2][2]-mat[2][1]*mat[1][2])-mat[0][1]*(mat[1][0]*mat[2][2]-mat[2][0]*mat[1][2])+mat[0][2]*(mat[1][0]*mat[2][1]-mat[2][0]*mat[1][1]);
00904 }
00905
00906 void Swap(Mat3D &out, int c, Mat1x3D &in) {
00907 out.mat[0][c] = in.mat[0];
00908 out.mat[1][c] = in.mat[1];
00909 out.mat[2][c] = in.mat[2];
00910 }
00911
00912 bool Solve3x3(Mat3D &m1, Mat1x3D &m1d, Mat1x3D &m2) {
00913 float d = m1.Determinate();
00914 if(fabs(d) < float(1E-5))
00915 return false;
00916 Mat3D wm;
00917 wm = m1;
00918 Swap(wm,0,m2);
00919 float d_x = wm.Determinate();
00920 m1d.mat[0] = d/d_x;
00921 wm = m1;
00922 Swap(wm,1,m2);
00923 float d_y = wm.Determinate();
00924 m1d.mat[1] = d/d_y;
00925 wm = m1;
00926 Swap(wm,2,m2);
00927 float d_z = wm.Determinate();
00928 m1d.mat[2] = d/d_z;
00929 return true;
00930 }
00931
00932 private:
00933 unsigned int i,z;
00934 };
00935
00936
00937 class Mat4D {
00938 public:
00939 float mat[4][4];
00940 Mat4D(float m00, float m01, float m02, float m03, float m10,float m11,float m12,float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) {
00941 Set(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33);
00942 }
00943 Mat4D() {
00944 memset(this,0,sizeof(Mat4D));
00945 }
00946 void Set(float m00, float m01, float m02, float m03, float m10,float m11,float m12,float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) {
00947 mat[0][0] = m00;
00948 mat[0][1] = m01;
00949 mat[0][2] = m02;
00950 mat[0][3] = m03;
00951 mat[1][0] = m10;
00952 mat[1][1] = m11;
00953 mat[1][2] = m12;
00954 mat[1][3] = m13;
00955 mat[2][0] = m20;
00956 mat[2][1] = m21;
00957 mat[2][2] = m22;
00958 mat[2][3] = m23;
00959 mat[3][0] = m30;
00960 mat[3][1] = m31;
00961 mat[3][2] = m32;
00962 mat[3][3] = m33;
00963 }
00964 std::string Print(std::string m = "m") {
00965 std::string p;
00966 char dat[256];
00967 sprintf(dat,"%s = {\n", m.c_str());
00968 for(unsigned int i = 0; i < 4; i++) {
00969 for(unsigned int z = 0; z < 4; z++) {
00970 sprintf(dat,"%s%f ", dat,mat[i][z]);
00971 }
00972 sprintf(dat,"%s\n", dat);
00973 }
00974 sprintf(dat,"%s}\n", dat);
00975 p = dat;
00976 return p;
00977 }
00978 void operator=(const Mat4D &m) {
00979 memcpy(this,&m, sizeof(Mat4D));
00980 }
00981
00982 Mat4D operator+(const Mat4D &m) {
00983 Mat4D p = *this;
00984 for(i = 0; i < 4; i++)
00985 for(z = 0; z < 4; z++)
00986 p.mat[i][z] += m.mat[i][z];
00987 return p;
00988 }
00989
00990 void operator+=(const Mat4D &m) {
00991 for(i = 0; i < 4; i++)
00992 for(z = 0; z < 4; z++)
00993 mat[i][z] += m.mat[i][z];
00994 }
00995
00996 Mat4D operator*(const Mat4D &m) {
00997 Mat4D p;
00998 for(i = 0; i < 4; i++)
00999 for(z = 0; z < 4; z++) {
01000 float sum = 0;
01001 for(int index = 0; index < 4; index++) {
01002 sum += mat[i][index] * m.mat[index][z];
01003 }
01004 p.mat[i][z] = sum;
01005 }
01006 return p;
01007 }
01008
01009 void operator*=(const Mat4D &m) {
01010 for(i = 0; i < 4; i++)
01011 for(z = 0; z < 4; z++)
01012 mat[i][z] *= m.mat[i][z];
01013 }
01014
01015 void Swap(Mat4D &out, int c, Mat1x4D &in) {
01016 out.mat[0][c] = in.mat[0];
01017 out.mat[1][c] = in.mat[1];
01018 out.mat[2][c] = in.mat[2];
01019 out.mat[3][c] = in.mat[3];
01020 }
01021
01022 vec4D MulVec(vec4D &in) {
01023 vec4D out;
01024 for(int col = 0; col < 4; col++) {
01025 float s = 0;
01026 for(int row = 0; row < 4; row++) {
01027 s += (in.vec[row] * mat[row][col]);
01028 }
01029 out.vec[col] = s;
01030 }
01031 return out;
01032 }
01033
01034 void MulVec(vec3D &in, vec3D &out) {
01035 for(z = 0; z < 3; z++) {
01036 float s = 0;
01037 for(i = 0; i < 3; i++) {
01038 s += in.vec[z] * mat[i][z];
01039 }
01040 s += mat[i][3];
01041 out.vec[z] = s;
01042 }
01043 }
01044
01045 void MulVec(vec3D &v1, Mat4x3D &in, vec3D &out ) {
01046 for(z = 0; z < 3; z++) {
01047 float s = 0;
01048 for(i = 0; i < 3; i++) {
01049 s += v1.vec[i] * in.mat[i][z];
01050 }
01051 s += in.mat[i][3];
01052 out.vec[z] = s;
01053 }
01054 }
01055
01056 void MulVec(vec3D &v1, Mat4D &in, vec3D &out) {
01057 for(z = 0; z < 3; z++) {
01058 float s = 0;
01059 for(i = 0; i < 3; i++) {
01060 s += in.mat[i][z] * v1.vec[i];
01061 }
01062 s += in.mat[i][3];
01063 out.vec[z] = s;
01064 }
01065 }
01066
01067 void MulVec(vec4D &v1, Mat4D &in, vec4D &out) {
01068 for(int col = 0; col < 4; col++) {
01069 float sum = 0.0f;
01070 for(int row = 0; row < 4; row++) {
01071 sum += (v1.vec[row]*in.mat[row][col]);
01072 }
01073 out.vec[col] = sum;
01074 }
01075 }
01076
01077 void MulVec(vec4D &v1, Mat4x3D &in, vec4D &out) {
01078 for(z = 0; z < 3; z++) {
01079 float s = 0;
01080 for(i = 0; i < 4; i++) {
01081 s += v1.vec[i] * in.mat[i][z];
01082 }
01083 out.vec[z] = s;
01084 }
01085
01086 out.vec[3] = v1.vec[3];
01087 }
01088
01089 bool Inverse(Mat4D &m) {
01090 float d = ( mat[0][0] * ( mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) - mat[0][1] *(mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0] ) + mat[0][2] *(mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0] ));
01091
01092 if(fabs(d) < float(1E-5))
01093 return false;
01094
01095 float inv = 1.0f/d;
01096 m.mat[0][0] = inv *( mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1] );
01097 m.mat[0][1] = -inv *( mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1] );
01098 m.mat[0][2] = inv *( mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1] );
01099 m.mat[0][3] = 0.0f;
01100
01101 m.mat[1][0] = -inv *(mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0] );
01102 m.mat[1][1] = inv *(mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0] );
01103 m.mat[1][2] = -inv *(mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0] );
01104 m.mat[1][3] = 0.0f;
01105
01106 m.mat[2][0] = inv *(mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0] );
01107 m.mat[2][1] = -inv *(mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0] );
01108 m.mat[2][2] = inv *(mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0] );
01109 m.mat[2][3] = 0.0f;
01110
01111 m.mat[3][0] = -(mat[3][0] * m.mat[0][0] + mat[3][1] * m.mat[1][0] + mat[3][2] * m.mat[2][0] );
01112 m.mat[3][1] = -(mat[3][0] * m.mat[0][0] + mat[3][1] * m.mat[1][1] + mat[3][2] * m.mat[2][1] );
01113 m.mat[3][2] = -(mat[3][0] * m.mat[0][2] + mat[3][1] * m.mat[1][2] + mat[3][2] * m.mat[2][2] );
01114 m.mat[3][3] = 1.0f;
01115
01116 return true;
01117 }
01118
01119 void LoadIdentity() {
01120 mat[0][0] = 1, mat[0][1] = 0, mat[0][2] = 0, mat[0][3] = 0;
01121 mat[1][0] = 0, mat[1][1] = 1, mat[1][2] = 0, mat[1][3] = 0;
01122 mat[2][0] = 0, mat[2][1] = 0, mat[2][2] = 1, mat[2][3] = 0;
01123 mat[3][0] = 0, mat[3][1] = 0, mat[3][2] = 0, mat[3][3] = 1;
01124 }
01125
01126 void BuildXYZ(float theta_x, float theta_y, float theta_z) {
01127
01128 Mat4D mx, my, mz, mtmp;
01129 float sin_theta = 0, cos_theta = 0;
01130 int rot_seq = 0;
01131 LoadIdentity();
01132
01133 if (fabs(theta_x) > float(1E-5))
01134 rot_seq = rot_seq | 1;
01135
01136 if (fabs(theta_y) > float(1E-5))
01137 rot_seq = rot_seq | 2;
01138
01139 if (fabs(theta_z) > float(1E-5))
01140 rot_seq = rot_seq | 4;
01141
01142 switch(rot_seq) {
01143 case 0:
01144 return;
01145 case 1:
01146 cos_theta = fast_cosf(theta_x);
01147 sin_theta = fast_sinf(theta_x);
01148 mx.Set( 1, 0, 0, 0,0, cos_theta, sin_theta, 0,0, -sin_theta, cos_theta, 0,0, 0, 0, 1);
01149 *this = mx;
01150 break;
01151 case 2:
01152 cos_theta = fast_cosf(theta_y);
01153 sin_theta = fast_sinf(theta_y);
01154 my.Set(cos_theta, 0, -sin_theta, 0,
01155 0, 1, 0, 0,
01156 sin_theta, 0, cos_theta, 0,
01157 0, 0, 0, 1);
01158 *this = my;
01159 break;
01160 case 3:
01161 cos_theta = fast_cosf(theta_x);
01162 sin_theta = fast_sinf(theta_x);
01163 mx.Set(1, 0, 0, 0,
01164 0, cos_theta, sin_theta, 0,
01165 0, -sin_theta, cos_theta, 0,
01166 0, 0, 0, 1);
01167 cos_theta = fast_cosf(theta_y);
01168 sin_theta = fast_sinf(theta_y);
01169 my.Set(cos_theta, 0, -sin_theta, 0,
01170 0, 1, 0, 0,
01171 sin_theta, 0, cos_theta, 0,
01172 0, 0, 0, 1);
01173 *this = mx * my;
01174 break;
01175 case 4:
01176 cos_theta = fast_cosf(theta_z);
01177 sin_theta = fast_sinf(theta_z);
01178 mz.Set(
01179 cos_theta, sin_theta, 0, 0,
01180 -sin_theta, cos_theta, 0, 0,
01181 0, 0, 1, 0,
01182 0, 0, 0, 1);
01183 *this = mz;
01184 break;
01185 case 5:
01186 cos_theta = fast_cosf(theta_x);
01187 sin_theta = fast_sinf(theta_x);
01188 mx.Set(
01189 1, 0, 0, 0,
01190 0, cos_theta, sin_theta, 0,
01191 0, -sin_theta, cos_theta, 0,
01192 0, 0, 0, 1);
01193 cos_theta = fast_cosf(theta_z);
01194 sin_theta = fast_sinf(theta_z);
01195 mz.Set(
01196 cos_theta, sin_theta, 0, 0,
01197 -sin_theta, cos_theta, 0, 0,
01198 0, 0, 1, 0,
01199 0, 0, 0, 1);
01200 *this = mx * mz;
01201 break;
01202 case 6:
01203 cos_theta = fast_cosf(theta_y);
01204 sin_theta = fast_sinf(theta_y);
01205 my.Set(
01206 cos_theta, 0, -sin_theta, 0,
01207 0, 1, 0, 0,
01208 sin_theta, 0, cos_theta, 0,
01209 0, 0, 0, 1);
01210 cos_theta = fast_cosf(theta_z);
01211 sin_theta = fast_sinf(theta_z);
01212 mz.Set(
01213 cos_theta, sin_theta, 0, 0,
01214 -sin_theta, cos_theta, 0, 0,
01215 0, 0, 1, 0,
01216 0, 0, 0, 1);
01217 *this = my * mz;
01218 break;
01219 case 7:
01220 cos_theta = fast_cosf(theta_x);
01221 sin_theta = fast_sinf(theta_x);
01222 mx.Set(
01223 1, 0, 0, 0,
01224 0, cos_theta, sin_theta, 0,
01225 0, -sin_theta, cos_theta, 0,
01226 0, 0, 0, 1);
01227 cos_theta = fast_cosf(theta_y);
01228 sin_theta = fast_sinf(theta_y);
01229 my.Set(
01230 cos_theta, 0, -sin_theta, 0,
01231 0, 1, 0, 0,
01232 sin_theta, 0, cos_theta, 0,
01233 0, 0, 0, 1);
01234 cos_theta = fast_cosf(theta_z);
01235 sin_theta = fast_sinf(theta_z);
01236 mz.Set(
01237 cos_theta, sin_theta, 0, 0,
01238 -sin_theta, cos_theta, 0, 0,
01239 0, 0, 1, 0,
01240 0, 0, 0, 1);
01241 mtmp = mx * my * mz;
01242 *this = mtmp;
01243 break;
01244 }
01245 }
01246
01247 private:
01248 unsigned int i,z;
01249
01250 };
01251
01252 struct paramLine2D {
01253 vec2D p0,p1,v;
01254
01255 paramLine2D() {
01256 memset(this,0,sizeof(paramLine2D));
01257 }
01258
01259 paramLine2D(vec2D &p0, vec2D &p1, vec2D &v) {
01260 Set(p0,p1,v);
01261 }
01262
01263 void Set(vec2D &p0, vec2D &p1, vec2D &v) {
01264 this->p0 = p0, this->p1 = p1, this->v = v;
01265 }
01266
01267
01268 void Init(vec2D &p0, vec2D &p1) {
01269 this->p0 = p0;
01270 this->p1 = p1;
01271 v = p0 - p1;
01272 }
01273
01274 vec2D ComputePoint(float t, vec2D &p) {
01275 vec2D y = p;
01276 y.x = p0.x + v.x * t;
01277 y.y = p0.y + v.y * t;
01278 return y;
01279 }
01280
01281 int Intersect(paramLine2D &p, float &x, float &y) {
01282 float det = v.x * p.v.x - v.y * p.v.y;
01283 if(fabs(det) < float(1E-5))
01284 return 0;
01285 x = (p.v.x * (p0.y - p.p0.y) - p.v.y * ( p0.x - p.p0.x )) / det;
01286 y = (v.x * (p0.y - p.p0.y) - v.y * ( p0.x - p.p0.x)) / det;
01287
01288 if(x >= 0 && x <= 1 && y >= 0 && y <= 1)
01289 return 1;
01290 return 2;
01291 }
01292
01293 int Intersect(paramLine2D &p, vec2D &out) {
01294
01295 float det = v.x * p.v.x - v.y * p.v.y;
01296 if(fabs(det) < float(1E-5))
01297 return 0;
01298 float x = (p.v.x * (p0.y - p.p0.y) - p.v.y * ( p0.x - p.p0.x )) / det;
01299 float y = (v.x * (p0.y - p.p0.y) - v.y * ( p0.x - p.p0.x)) / det;
01300
01301 out.x = p0.x + v.x * x;
01302 out.y = p0.y + v.y * x;
01303
01304 if(x >= 0 && x <= 1 && y >= 0 && y <= 1)
01305 return 1;
01306
01307 return 2;
01308 }
01309
01310 };
01311
01312 struct paramLine3D {
01313 vec3D p0,p1,v;
01314
01315 paramLine3D() {
01316 memset(this,0,sizeof(paramLine3D));
01317 }
01318
01319 paramLine3D(vec3D &p0, vec3D &p1, vec3D &v) {
01320 Set(p0,p1,v);
01321 }
01322
01323 void operator=(paramLine3D &p) {
01324 memcpy(this,&p,sizeof(paramLine2D));
01325 }
01326
01327 void Set(vec3D &p0, vec3D &p1, vec3D &v) {
01328 this->p0 = p0, this->p1 = p1, this->v = v;
01329 }
01330
01331 void Init(vec3D &p0, vec3D &p) {
01332 this->p0 = p0;
01333 this->p1 = p1;
01334 v = p0 - p1;
01335 }
01336
01337 vec3D ComputePoint(float t, vec3D &p) {
01338 vec3D y = p;
01339 y.x = p0.x + v.x * t;
01340 y.y = p0.y + v.y * t;
01341 y.z = p0.z + v.z * t;
01342 return y;
01343 }
01344 };
01345
01346 struct Plane3D {
01347 vec3D p0,v;
01348
01349 Plane3D() {
01350 memset(this,0,sizeof(Plane3D));
01351 }
01352
01353 Plane3D(vec3D &p0, vec3D &v) {
01354 this->p0 = p0, this->v = v;
01355 }
01356
01357 void Set(vec3D &p0, vec3D &v, bool norm) {
01358
01359 this->p0 = p0;
01360
01361 if(!norm)
01362 this->v = v;
01363 else {
01364 this->v.Normalize(v);
01365 }
01366 }
01367 };
01368
01369 struct Polar {
01370 float r, theta;
01371 };
01372
01373 struct CyType {
01374 float r, theta, z;
01375 };
01376
01377 struct SpType {
01378 float p, theta, pi;
01379 };
01380
01381 class QuatType {
01382 public:
01383 union {
01384 float p[4];
01385 struct {
01386 float x,y,z,w;
01387 };
01388 };
01389
01390 QuatType() {
01391 memset(this,0,sizeof(QuatType));
01392 }
01393
01394 QuatType(float x, float y, float z, float w) {
01395 this->x = x, this->y = y, this->z = z, this->w = w;
01396 }
01397
01398 void operator=(QuatType &t) {
01399 memcpy(this,&t,sizeof(QuatType));
01400 }
01401
01402 QuatType operator+(const QuatType &t) {
01403 QuatType p = *this;
01404 p.x += t.x;
01405 p.y += t.y;
01406 p.z += t.z;
01407 p.w += t.w;
01408 return p;
01409 }
01410
01411 QuatType operator-(const QuatType &t) {
01412 QuatType p = *this;
01413 p.x -= t.x;
01414 p.y -= t.y;
01415 p.z -= t.z;
01416 p.w -= t.w;
01417 return p;
01418 }
01419
01420 QuatType operator*(const QuatType &t) {
01421 QuatType p;
01422 float prod0 = (z - y) * (t.y - t.z);
01423 float prod1 = (w + x) * (t.w + t.x);
01424 float prod2 = (w - x) * (t.y + t.z);
01425 float prod3 = (y + z) * (t.w - t.x);
01426 float prod4 = (z - x) * (t.x - t.y);
01427 float prod5 = (z + x) * (t.x + t.y);
01428 float prod6 = (w + y) * (t.w - t.z);
01429 float prod7 = (w - y) * (t.w + t.z);
01430
01431 float prod8 = prod5 + prod6 + prod7;
01432 float prod9 = 0.5f * (prod4 + prod8);
01433 p.w = prod0+prod9-prod5;
01434 p.x = prod1+prod9-prod8;
01435 p.y = prod2+prod9-prod7;
01436 p.z = prod3+prod9-prod6;
01437 return p;
01438 }
01439
01440 void operator*=(const QuatType &t) {
01441 float prod0 = (z - y) * (t.y - t.z);
01442 float prod1 = (w + x) * (t.w + t.x);
01443 float prod2 = (w - x) * (t.y + t.z);
01444 float prod3 = (y + z) * (t.w - t.x);
01445 float prod4 = (z - x) * (t.x - t.y);
01446 float prod5 = (z + x) * (t.x + t.y);
01447 float prod6 = (w + y) * (t.w - t.z);
01448 float prod7 = (w - y) * (t.w + t.z);
01449
01450 float prod8 = prod5 + prod6 + prod7;
01451 float prod9 = 0.5f * (prod4 + prod8);
01452 w = prod0+prod9-prod5;
01453 x = prod1+prod9-prod8;
01454 y = prod2+prod9-prod7;
01455 z = prod3+prod9-prod6;
01456 }
01457 void Conj() {
01458 x = -x;
01459 y = -y;
01460 z = -z;
01461 }
01462
01463 void Scale(float f) {
01464 x = x*f;
01465 y = y*f;
01466 z = z*f;
01467 w = w*f;
01468 }
01469
01470 float Norm() {
01471 return sqrtf( w * w + x * x + y * y + z * z );
01472 }
01473
01474 float Norm2() {
01475 return ( w*w + x*x + y*y + z*z );
01476 }
01477
01478 void Normalize() {
01479 float inv = 1.0f/(sqrtf( ( w * w + x * x + y * y + z * z ) ));
01480 x *= inv;
01481 y *= inv;
01482 z *= inv;
01483 w *= inv;
01484 }
01485
01486 void Inverse() {
01487 x = -x;
01488 y = -y;
01489 z = -z;
01490 }
01491
01492 void InverseNormal() {
01493 float inv = 1.0f/(sqrtf( ( w * w + x * x + y * y + z * z ) ));
01494 x *= -inv;
01495 y *= -inv;
01496 z *= -inv;
01497 w *= inv;
01498 }
01499
01500 QuatType TripleProduct(QuatType p1, QuatType p2) {
01501 QuatType p = *this;
01502 p *= p1;
01503 p *= p2;
01504 return p;
01505 }
01506
01507 void vec3DthetaQuat(float theta, const vec3D &v) {
01508 float theta_2 = 0.5f * theta;
01509 float sin_f = fast_sinf(theta_2);
01510 x = sin_f * v.x;
01511 y = sin_f * v.y;
01512 z = sin_f * v.z;
01513 w = fast_cosf(theta_2);
01514 }
01515
01516 void vec4DthetaQuat(float theta, const vec4D &v) {
01517 float theta_2 = 0.5f * theta;
01518 float sin_f = fast_sinf(theta_2);
01519 x = sin_f * v.x;
01520 y = sin_f * v.y;
01521 z = sin_f * v.z;
01522 w = fast_cosf(theta_2);
01523 }
01524
01525 void EulerZYX(float theta_x, float theta_y, float theta_z) {
01526 float cos_z_2 = 0.5f*fast_cosf(theta_z);
01527 float cos_y_2 = 0.5f*fast_cosf(theta_y);
01528 float cos_x_2 = 0.5f*fast_cosf(theta_x);
01529 float sin_z_2 = 0.5f*fast_sinf(theta_z);
01530 float sin_y_2 = 0.5f*fast_sinf(theta_y);
01531 float sin_x_2 = 0.5f*fast_sinf(theta_x);
01532 w = cos_z_2*cos_y_2*cos_x_2 + sin_z_2*sin_y_2*sin_x_2;
01533 x = cos_z_2*cos_y_2*sin_x_2 - sin_z_2*sin_y_2*cos_x_2;
01534 y = cos_z_2*sin_y_2*cos_x_2 + sin_z_2*cos_y_2*sin_x_2;
01535 z = sin_z_2*cos_y_2*cos_x_2 - cos_z_2*sin_y_2*sin_x_2;
01536 }
01537
01538 void QuatToVec3D(float *theta, vec3D &v) {
01539
01540 *theta = acosf(w);
01541 float sinf_theta_inv = 1.0f/sinf(*theta);
01542 v.x = x*sinf_theta_inv;
01543 v.y = y*sinf_theta_inv;
01544 v.z = z*sinf_theta_inv;
01545 *theta*=2;
01546 }
01547
01548 };
01549
01550
01551
01552 struct Triangle {
01553 vec4D vlist[3],tlist[3];
01554 int color;
01555 int attr;
01556 int state;
01557 int vert[3];
01558 Triangle() {
01559 memset(this,0,sizeof(Triangle));
01560 }
01561
01562
01563 Triangle(vec4D vlist[3], vec4D tlist[3]) {
01564 for(unsigned int i = 0; i < 3; i++) {
01565 this->vlist[i] = vlist[i];
01566 this->tlist[i] = tlist[i];
01567 }
01568 }
01569
01570 };
01571
01572 enum { MX_ACTIVE = 0x1, MX_VISIBLE = 0x2, MX_BACKFACE = 0x4 , MX_CULLED = 0x5};
01573
01574 class RenderList {
01575 public:
01576 std::vector<Triangle> polys;
01577 int num_polys;
01578 RenderList() {
01579 num_polys = 0;
01580 }
01581
01582 void Reset() {
01583 if(!polys.empty())
01584 polys.erase(polys.begin(),polys.end());
01585 num_polys = 0;
01586 }
01587
01588 void TransformRenderList(Mat4D &mrot, int type) {
01589 switch(type) {
01590 case 0: {
01591 for(int i = 0; i < num_polys; i++) {
01592 if(polys[i].state == 0 || polys[i].state == MX_BACKFACE)
01593 continue;
01594 for(int z = 0; z < 3; z++) {
01595 polys[i].vlist[z] = mrot.MulVec(polys[i].vlist[z]);
01596 }
01597 }
01598 }
01599 break;
01600 }
01601 }
01602
01603 void RemoveFaces(vec4D &pos) {
01604 for(unsigned int i = 0; i < polys.size(); i++) {
01605 if(polys[i].state == 0 || polys[i].state & MX_ACTIVE || polys[i].state & MX_VISIBLE )
01606 continue;
01607 vec4D u,v,n,b;
01608 u = u.Build(polys[i].tlist[0], polys[i].tlist[1]);
01609 v = v.Build(polys[i].tlist[0], polys[i].tlist[2]);
01610 n = u.CrossProduct(v);
01611 b = b.Build(polys[i].tlist[0], pos);
01612 float dot = n.DotProduct(b);
01613 if(dot <= 0.0f) {
01614 polys[i].state = MX_BACKFACE;
01615 }
01616 }
01617 }
01618
01619
01620 void ModelToWorld(vec4D &pos, int type) {
01621 switch(type) {
01622 case 0: {
01623 for(int col = 0; col < this->num_polys; col++)
01624 {
01625 if(this->polys[col].state == 0 || polys[col].state == MX_BACKFACE)
01626 continue;
01627 for(int vertex = 0; vertex < 3; vertex++) {
01628 this->polys[col].tlist[vertex] = (polys[col].vlist[vertex] + pos);
01629 }
01630 }
01631 }
01632 break;
01633 case 1:
01634 break;
01635 }
01636 }
01637
01638 void BuildRenderList(Triangle &triangles) {
01639 polys.push_back(triangles);
01640 num_polys++;
01641 }
01642
01643 };
01644
01645 class mxObject {
01646 public:
01647 int state, attr;
01648 float avg_rad, max_rad;
01649 vec4D world_pos, dir, ux, uy, uz;
01650 int num_vertices, num_polys;
01651 std::vector<vec4D> local, trans;
01652 std::vector<Triangle> vlist;
01653 std::string object_name;
01654
01655
01656 bool LoadMX(std::string source, vec4D &scale, vec4D &obj_pos, vec4D &rotation) {
01657 std::fstream file;
01658 file.open(source.c_str(),std::ios::in);
01659 if(!file.is_open())
01660 return false;
01661
01662 this->world_pos = obj_pos;
01663
01664 int num_vertex = 0, num_polys = 0, got_vertex = 0;
01665
01666 bool get_vertex = false, get_polys = false;
01667 unsigned int cur_color;
01668
01669 std::string header;
01670 std::getline(file, header);
01671 if(header != ".mx_format")
01672 return false;
01673
01674 while(!file.eof()) {
01675 std::string cur_line;
01676 std::getline(file, cur_line);
01677 if(cur_line[0] == '/' || cur_line[0] == '#' || cur_line.length() < 2)
01678 continue;
01679 std::vector<std::string> tok_vec;
01680 token::tokenize<std::string>(cur_line,std::string(" "), tok_vec);
01681
01682
01683 if(tok_vec.size() > 2 && tok_vec[0].length() != 0) {
01684 num_vertex = atoi(tok_vec[1].c_str()), num_polys = atoi(tok_vec[2].c_str());
01685 get_vertex = true;
01686 this->num_vertices = num_vertex;
01687 this->num_polys = num_polys;
01688 object_name = tok_vec[0];
01689 }
01690 else if(tok_vec[0] == "color" && tok_vec.size() > 3) {
01691
01692 }
01693 else if(get_vertex == true && tok_vec.size() > 2) {
01694 vec4D vertex;
01695 vertex.x = float(atof(tok_vec[0].c_str())*scale.x);
01696 vertex.y = float(atof(tok_vec[1].c_str())*scale.y);
01697 vertex.z = float(atof(tok_vec[2].c_str())*scale.z);
01698 vertex.w = 1;
01699 this->local.push_back(vertex);
01700 memset(&vertex,0,sizeof(vertex));
01701 this->trans.push_back(vertex);
01702 if(++got_vertex > num_vertex-1) {
01703 get_vertex = false;
01704 get_polys = true;
01705 continue;
01706 }
01707 }
01708 else if(get_polys == true && tok_vec.size() > 4) {
01709 Triangle tri;
01710 tri.vert[0] = atoi(tok_vec[2].c_str());
01711 tri.vert[1] = atoi(tok_vec[3].c_str());
01712 tri.vert[2] = atoi(tok_vec[4].c_str());
01713 tri.state = atoi(tok_vec[0].c_str());
01714 tri.color = cur_color;
01715 this->vlist.push_back(tri);
01716 }
01717 }
01718
01719 file.close();
01720
01721 return true;
01722 }
01723
01724
01725 bool LoadPLG(std::string plg,vec4D &scale, vec4D &obj_pos, vec4D &rotation, unsigned int triz_color = 0xFF) {
01726 std::fstream file;
01727 file.open(plg.c_str(), std::ios::in);
01728 if(!file.is_open())
01729 return false;
01730 this->world_pos = obj_pos;
01731 while(!file.eof()) {
01732 std::string cur_line;
01733 std::getline(file,cur_line);
01734 if(cur_line[0] == '#' || cur_line.length() < 2)
01735 continue;
01736 char type[256];
01737 int num_v, num_p;
01738 sscanf(cur_line.c_str(),"%s %d %d", type, &num_v, &num_p);
01739 int counter = 0;
01740 object_name = type;
01741 this->num_polys = num_p;
01742 this->num_vertices = num_v;
01743
01744 while(counter < num_v) {
01745 std::getline(file,cur_line);
01746 if(cur_line[0] == '#' || cur_line.length() < 2)
01747 continue;
01748 vec4D vertex;
01749 sscanf(cur_line.c_str(), "%f %f %f", &vertex.x, &vertex.y, &vertex.z);
01750 vertex.w = 1;
01751 vertex.x *= scale.x;
01752 vertex.y *= scale.y;
01753 vertex.z *= scale.z;
01754 this->local.push_back(vertex);
01755
01756 memset(&vertex,0,sizeof(vertex));
01757 this->trans.push_back(vertex);
01758 counter++;
01759
01760
01761 }
01762
01763 ComputeRad();
01764 counter = 0;
01765 while(counter < num_p) {
01766 std::getline(file,cur_line);
01767 if(cur_line[0] == '#' || cur_line.length() < 2)
01768 continue;
01769 Triangle tri;
01770 int num = 0;
01771 tri.color = triz_color;
01772 sscanf(cur_line.c_str(),"%x %d %d %d %d",(unsigned int*)&tri.state, &num, &tri.vert[0], &tri.vert[1], &tri.vert[2]);
01773 this->vlist.push_back(tri);
01774 counter++;
01775 }
01776 }
01777 file.close();
01778 return true;
01779 }
01780
01781
01782 void ModelToWorld(int type = 0) {
01783 switch(type) {
01784 case 0:
01785 {
01786 for(unsigned int i = 0; i < local.size(); i++) {
01787 trans[i] = local[i] + world_pos;
01788 }
01789 break;
01790 }
01791 case 1:
01792 {
01793 for(unsigned int i = 0; i < trans.size(); i++) {
01794 trans[i] += world_pos;
01795 }
01796
01797 }
01798 break;
01799 }
01800 }
01801
01802 void TransformObject(Mat4D &mrot, int type=0) {
01803 switch(type) {
01804 case 0:
01805 {
01806 for(unsigned int i = 0; i < local.size(); i++) {
01807 local[i] = mrot.MulVec(local[i]);
01808 }
01809 }
01810 break;
01811 case 1:
01812 {
01813 for(unsigned int i = 0; i < trans.size(); i++) {
01814 trans[i] = mrot.MulVec(trans[i]);
01815 }
01816 }
01817 break;
01818 case 2:
01819 {
01820 for(unsigned int i = 0; i < local.size(); i++)
01821 trans[i] = mrot.MulVec(local[i]);
01822 }
01823 break;
01824 }
01825 }
01826
01827
01828 void RemoveFaces(vec4D &pos) {
01829 for(unsigned int i = 0; i < this->vlist.size(); i++) {
01830 if(vlist[i].state == 0 || vlist[i].state & MX_VISIBLE || vlist[i].state & MX_CULLED )
01831 continue;
01832
01833 vec4D u,v,n,b;
01834 int v1 = vlist[i].vert[0], v2 = vlist[i].vert[1] , v3 = vlist[i].vert[2];
01835 u = u.Build(trans[v1], trans[v2]);
01836 v = v.Build(trans[v1], trans[v3]);
01837 n = u.CrossProduct(v);
01838 b = b.Build(trans[v1], pos);
01839 float dot = n.DotProduct(b);
01840 if(dot <= 0.0f) {
01841 vlist[i].state = MX_BACKFACE;
01842 }
01843 }
01844 }
01845
01846 void BuildRenderList(RenderList &l) {
01847 for(unsigned int i = 0; i < vlist.size(); i++) {
01848 Triangle tri;
01849 tri.state = vlist[i].state;
01850 tri.color = vlist[i].color;
01851 tri.attr = vlist[i].color;
01852 tri.vlist[0] = local[vlist[i].vert[0]];
01853 tri.vlist[1] = local[vlist[i].vert[1]];
01854 tri.vlist[2] = local[vlist[i].vert[2]];
01855 tri.tlist[0] = trans[vlist[i].vert[0]];
01856 tri.tlist[1] = trans[vlist[i].vert[1]];
01857 tri.tlist[2] = trans[vlist[i].vert[2]];
01858 l.BuildRenderList(tri);
01859 }
01860 }
01861
01862 void Reset() {
01863 for(unsigned int i = 0; i < this->vlist.size(); i++)
01864 vlist[i].state = MX_ACTIVE;
01865 this->state = MX_ACTIVE;
01866
01867 }
01868
01869 float ComputeRad() {
01870 max_rad = 0;
01871 avg_rad = 0;
01872 for(unsigned int i = 0; i < local.size(); i++) {
01873 float dist = sqrtf( local[i].x + local[i].x * local[i].y + local[i].y * local[i].z + local[i].z );
01874 avg_rad += dist;
01875 if(avg_rad > max_rad)
01876 max_rad = dist;
01877 }
01878 avg_rad /= float(local.size());
01879 return max_rad;
01880 }
01881
01882 bool CullObject(bool cull_x, bool cull_y, bool cull_z,Mat4D &camera_pos, float far_z, float near_z, float viewplane_width,float viewplane_height, float view_dist) {
01883 vec4D s_p;
01884 s_p = camera_pos.MulVec(world_pos);
01885
01886 if(cull_z == true) {
01887 if(((s_p.z - this->max_rad) > far_z) || ((s_p.z+this->max_rad) < near_z) ) {
01888 this->state = MX_CULLED;
01889 return true;
01890 }
01891 }
01892
01893 if(cull_x == true) {
01894 float z_test = (0.5f)*viewplane_width*s_p.z/view_dist;
01895 if(s_p.x+max_rad > z_test)
01896 {
01897 this->state = MX_CULLED;
01898 return true;
01899 }
01900 else if(s_p.x+max_rad < -z_test) {
01901 this->state = MX_CULLED;
01902 return true;
01903 }
01904 }
01905 if(cull_y == true) {
01906 float z_test = (0.5f)*viewplane_height*s_p.z/view_dist;
01907 if(s_p.y+max_rad > z_test) {
01908 this->state = MX_CULLED;
01909 return true;
01910 }
01911 else if(s_p.y+max_rad < -z_test) {
01912 this->state = MX_CULLED;
01913 return true;
01914 }
01915 }
01916
01917 return false;
01918 }
01919
01920 void SetState(int state) {
01921 this->state = state;
01922 }
01923
01924 };
01925
01926
01927
01928
01929 class Camera {
01930 public:
01931 int state, attr;
01932 vec4D pos, dir, u, v, n, target;
01933 float view_dist, fov, near_clip_z, far_clip_z;
01934 Plane3D rt_clip_plane, lt_clip_plane,tp_clip_plane,bt_clip_plane;
01935 float viewplane_height, viewplane_width;
01936 float viewport_width, viewport_height, viewport_center_x, viewport_center_y;
01937 float aspect_ratio;
01938 Mat4D mcam, mper, mscr;
01939
01940 Camera() {
01941 memset(this,0,sizeof(Camera));
01942 }
01943
01944 void InitalizeForEuler() {
01945 pos.x = 100;
01946 pos.y = 200;
01947 pos.z = 300;
01948 dir.x = -48;
01949 dir.y = 0;
01950 dir.z = 0;
01951 BuildEuler(5);
01952 }
01953
01954 void Init(int attr, vec4D &pos, vec4D &cam_dir, vec4D *cam_target, float near_clip_z, float far_clip_z, float fov, float viewport_width, float viewport_height) {
01955 this->attr = attr;
01956 this->pos = pos;
01957 this->dir = cam_dir;
01958 u.Set(1,0,0);
01959 v.Set(0,1,0);
01960 n.Set(0,0,1);
01961 if(cam_target != 0)
01962 target = *cam_target;
01963 else
01964 memset(&target,0,sizeof(target));
01965
01966 this->near_clip_z = near_clip_z;
01967 this->far_clip_z = far_clip_z;
01968
01969 this->viewport_height = viewport_height;
01970 this->viewport_width = viewport_width;
01971 this->viewport_center_x = (viewport_width-1)/2;;
01972 this->viewport_center_y =(viewport_height-1)/2;
01973 this->aspect_ratio = float(float(viewport_width)/float(viewport_height));
01974 mcam.LoadIdentity();
01975 mper.LoadIdentity();
01976 mscr.LoadIdentity();
01977
01978 this->fov = fov;
01979 this->viewplane_width = 2.0f;
01980 this->viewplane_height = 2.0f/this->aspect_ratio;
01981 float tan_fov_div2 = tan(deg2rad(fov/2));
01982 this->view_dist = (0.5f) * (this->viewplane_width)*tan_fov_div2;
01983 if(fov == 90.0f) {
01984 vec3D pt_origin(0,0,0);
01985 vec3D vn(1,0,-1);
01986 rt_clip_plane.Set(pt_origin, vn, true);
01987 vn.Set(-1,0,-1);
01988 lt_clip_plane.Set(pt_origin, vn, true);
01989 vn.Set(0,1,-1);
01990 tp_clip_plane.Set(pt_origin, vn, true);
01991 vn.Set(0,-1,-1);
01992 bt_clip_plane.Set(pt_origin, vn, true);
01993 }
01994 else {
01995 vec3D pt_origin(0,0,0);
01996 vec3D vn;
01997 vn.Set(this->view_dist, 0, this->viewplane_width / 2.0f);
01998 rt_clip_plane.Set(pt_origin,vn,true);
01999 vn.Set(this->view_dist, 0, this->viewplane_width/2.0f);
02000 lt_clip_plane.Set(pt_origin,vn,true);
02001 vn.Set(0,this->view_dist, this->viewplane_width/2.0f);
02002 tp_clip_plane.Set(pt_origin,vn,true);
02003 vn.Set(0,this->view_dist, this->viewplane_width/2.0f);
02004 bt_clip_plane.Set(pt_origin,vn,true);
02005 }
02006
02007 }
02008
02009 void BuildEuler(int cam_rot_seq) {
02010 Mat4D mt_inv
02011 ( 1,0,0,0,
02012 0,1,0,0,
02013 0,0,1,0,
02014 -pos.x,-pos.y,-pos.z, 1
02015 );
02016 float theta_x = dir.x;
02017 float theta_y = dir.y;
02018 float theta_z = dir.z;
02019
02020 float cos_theta = fast_cosf(theta_x);
02021 float sin_theta = -fast_sinf(theta_x);
02022 Mat4D mx_inv (1, 0, 0, 0,
02023 0, cos_theta, sin_theta, 0,
02024 0, -sin_theta, cos_theta, 0,
02025 0, 0, 0, 1);
02026
02027 cos_theta = fast_cosf(theta_y);
02028 sin_theta = -fast_sinf(theta_y);
02029
02030 Mat4D my_inv(cos_theta, 0, -sin_theta, 0,
02031 0, 1, 0, 0,
02032 sin_theta, 0, cos_theta, 0,
02033 0, 0, 0, 1);
02034
02035 cos_theta = fast_cosf(theta_z);
02036 sin_theta = -fast_sinf(theta_z);
02037
02038 Mat4D mz_inv(cos_theta, sin_theta, 0, 0,
02039 -sin_theta, cos_theta, 0, 0,
02040 0, 0, 1, 0,
02041 0, 0, 0, 1);
02042
02043 Mat4D mtmp, mrot;
02044 switch(cam_rot_seq) {
02045 case 0:
02046 mtmp = mx_inv * my_inv;
02047 mrot = mtmp * mz_inv;
02048 break;
02049 case 1:
02050 mtmp = my_inv * mx_inv;
02051 mrot = mtmp * mz_inv;
02052 break;
02053 case 2:
02054 mtmp = mx_inv * mz_inv;
02055 mrot = mtmp * my_inv;
02056 break;
02057 case 3:
02058 mtmp = my_inv * mz_inv;
02059 mrot = mtmp * mx_inv;
02060 break;
02061 case 4:
02062 mtmp = mz_inv * my_inv;
02063 mrot = mtmp * mx_inv;
02064 break;
02065 case 5:
02066 mrot = mz_inv * mx_inv * my_inv;
02067 break;
02068 }
02069
02070 this->mcam = mt_inv * mrot;
02071 }
02072
02073 void BuildUVN(int type) {
02074 Mat4D mt_inv(1,0,0,0,0,1,0,0,0,0,1,0,-pos.x,-pos.y,-pos.z, 1), mt_uvn, mtmp;
02075 if(type == 1) {
02076
02077
02078
02079 }
02080 n = n.Build(pos,target);
02081 v.Set(0,1,0,1);
02082 u = v.CrossProduct(n);
02083 v = n.CrossProduct(u);
02084 u.Normalize();
02085 v.Normalize();
02086 n.Normalize();
02087 mt_uvn.Set(u.x,v.x,n.x,0,u.y,v.y,n.y,0,u.z,v.z,n.z,0,0,0,0,1);
02088 mcam = mt_inv * mt_uvn;
02089 }
02090
02091 void CameraToPerspective(RenderList &l) {
02092 for(int i = 0; i < l.num_polys; i++) {
02093 if(l.polys[i].state == 0 || l.polys[i].state == MX_BACKFACE)
02094 continue;
02095 else
02096 for(int z = 0; z < 3; z++) {
02097 float cur_z = l.polys[i].tlist[z].z;
02098 l.polys[i].tlist[z].x = this->view_dist * l.polys[i].tlist[z].x/ cur_z;
02099 l.polys[i].tlist[z].y = this->view_dist * l.polys[i].tlist[z].y * this->aspect_ratio / cur_z;
02100 }
02101 }
02102 }
02103
02104 void CameraToPerspective(mxObject &m) {
02105
02106 for(unsigned int i = 0; i < m.trans.size(); i++) {
02107 m.trans[i].x = view_dist*m.trans[i].x/m.trans[i].z;
02108 m.trans[i].y = view_dist*m.trans[i].y*aspect_ratio/m.trans[i].z;
02109 }
02110
02111 }
02112
02113 void PerspectiveToScreen(RenderList &l) {
02114 for(int i = 0; i < l.num_polys; i++) {
02115 if(l.polys[i].state == 0 || l.polys[i].state == MX_BACKFACE)
02116 continue;
02117
02118 float alpha = (0.5f * viewport_width - 0.5f);
02119 float beta = (0.5f * viewport_height - 0.5f);
02120
02121
02122 for(int z = 0; z < 3; z++) {
02123 l.polys[i].tlist[z].x = alpha + alpha * l.polys[i].tlist[z].x;
02124 l.polys[i].tlist[z].y = beta - beta * l.polys[i].tlist[z].y;
02125 }
02126 }
02127 }
02128
02129 void PerspectiveToScreen(mxObject &o) {
02130 float alpha = (0.5f*viewport_width-0.5f);
02131 float beta = (0.5f*viewport_height-0.5f);
02132
02133 for(unsigned int i = 0; i < o.trans.size(); i++) {
02134 o.trans[i].x = alpha+alpha * o.trans[i].x;
02135 o.trans[i].y = beta-beta * o.trans[i].y;
02136 }
02137
02138 }
02139
02140 void BuildPerspective(Mat4D &m) {
02141 float alpha = (0.5f*viewport_width-0.5f);
02142 float beta = (0.5f*viewport_height-0.5f);
02143 m.Set(alpha,0,0,0,0,-beta,0,0,alpha,beta,1,0,0,0,0,1);
02144 }
02145
02146 void WorldToCamera(RenderList &l) {
02147 for(int row = 0; row < l.num_polys; row++) {
02148
02149 if(l.polys[row].state == 0 || l.polys[row].state == MX_BACKFACE)
02150 continue;
02151 for(int col = 0; col < 3; col++) {
02152 vec4D r;
02153 r = mcam.MulVec(l.polys[row].tlist[col]);
02154 l.polys[row].tlist[col] = r;
02155 }
02156 }
02157 }
02158
02159 void WorldToCamera(mxObject &m) {
02160 for(unsigned int i = 0; i < m.trans.size(); i++)
02161 m.trans[i] = mcam.MulVec(m.trans[i]);
02162 }
02163 };
02164
02165
02166 union mx3d_color {
02167
02168 unsigned char rgb[4];
02169 unsigned int value;
02170
02171 };
02172
02173
02174
02175
02176 class PipeLine {
02177 protected:
02178
02179 graphicsInterface *mx;
02180 public:
02181 PipeLine() {
02182
02183 }
02184
02185 virtual ~PipeLine() { }
02186
02187 int max_clip_x,max_clip_y,min_clip_x,min_clip_y;
02188
02189 void Begin(graphicsInterface &mx) {
02190 this->mx = &mx;
02191 clip_min_x = clip_min_y = min_clip_x = min_clip_y = 0;
02192 clip_max_x = this->mx->w - 1;
02193 clip_max_y = this->mx->h - 1;
02194 max_clip_x = this->mx->w - 1;
02195 max_clip_y = this->mx->h - 1;
02196
02197 this->mx->lock();
02198 }
02199
02200 void DrawPolys(RenderList &l) {
02201
02202 for(unsigned int i = 0; i < l.polys.size(); i++) {
02203 if(l.polys[i].state == 0 || l.polys[i].state == MX_BACKFACE )
02204 continue;
02205 else {
02206 DrawClipedLine(int(l.polys[i].tlist[0].x), int(l.polys[i].tlist[0].y), int(l.polys[i].tlist[1].x), int(l.polys[i].tlist[1].y), l.polys[i].color);
02207 DrawClipedLine(int(l.polys[i].tlist[1].x), int(l.polys[i].tlist[1].y), int(l.polys[i].tlist[2].x), int(l.polys[i].tlist[2].y), l.polys[i].color);
02208 DrawClipedLine(int(l.polys[i].tlist[2].x), int(l.polys[i].tlist[2].y), int(l.polys[i].tlist[0].x), int(l.polys[i].tlist[0].y), l.polys[i].color);
02209 }
02210 }
02211 }
02212
02213 void DrawSolidPolys(RenderList &l) {
02214
02215 for(unsigned int i = 0; i < l.polys.size(); i++) {
02216 if(l.polys[i].state == 0 || l.polys[i].state == MX_BACKFACE )
02217 continue;
02218 this->mx->drawtri(int(l.polys[i].tlist[0].x), int(l.polys[i].tlist[0].y), int(l.polys[i].tlist[1].x), int(l.polys[i].tlist[1].y), int(l.polys[i].tlist[2].x), int(l.polys[i].tlist[2].y),int(l.polys[i].color));
02219 }
02220 }
02221
02222 void DrawObject(mxObject &o) {
02223
02224 if(o.state == MX_CULLED)
02225 return;
02226
02227 for(unsigned int i = 0; i < o.vlist.size(); i++) {
02228 if(o.vlist[i].state == 0 || o.vlist[i].state == MX_BACKFACE)
02229 continue;
02230 int vertex_one = o.vlist[i].vert[0], vertex_two = o.vlist[i].vert[1] , vertex_three = o.vlist[i].vert[2];
02231 DrawClipedLine(int(o.trans[vertex_one].x), int(o.trans[vertex_one].y), int(o.trans[vertex_two].x), int(o.trans[vertex_two].y), o.vlist[i].color);
02232 DrawClipedLine(int(o.trans[vertex_two].x), int(o.trans[vertex_two].y), int(o.trans[vertex_three].x), int(o.trans[vertex_three].y), o.vlist[i].color);
02233 DrawClipedLine(int(o.trans[vertex_three].x), int(o.trans[vertex_three].y),int(o.trans[vertex_one].x), int(o.trans[vertex_one].y), o.vlist[i].color);
02234
02235 }
02236 }
02237
02238 int clip_min_x, clip_max_x, clip_min_y, clip_max_y;
02239
02240
02241 enum LINE_CODE { CODE_C = 0x0000, CODE_N = 0x0008, CODE_S = 0x0004, CODE_E = 0x0002, CODE_W = 0x0001, CODE_NE = 0x000a, CODE_SE = 0x0006,CODE_NW = 0x0009 ,CODE_SW = 0x0005 };
02242
02243
02244 bool ClipLine(int &x1, int &y1, int &x2, int &y2) {
02245 int xc1 = x1, yc1 = y1, xc2 = x2, yc2 = y2;
02246 int p1_code = 0,p2_code = 0;
02247 if (y1 < clip_min_y)
02248 p1_code |= CODE_N;
02249 else
02250 if (y1 > clip_max_y)
02251 p1_code |= CODE_S;
02252
02253 if (x1 < clip_min_x)
02254 p1_code |= CODE_W;
02255 else
02256 if (x1 > clip_max_x)
02257 p1_code |= CODE_E;
02258
02259 if (y2 < clip_min_y)
02260 p2_code |= CODE_N;
02261 else
02262 if (y2 > clip_max_y)
02263 p2_code |= CODE_S;
02264
02265 if (x2 < clip_min_x)
02266 p2_code |= CODE_W;
02267 else
02268 if (x2 > clip_max_x)
02269 p2_code |= CODE_E;
02270
02271 if(p1_code && p2_code)
02272 return false;
02273
02274 if(p1_code == 0 && p2_code)
02275 return true;
02276 switch(p2_code) {
02277 case CODE_C: break;
02278 case CODE_N:
02279 yc2 = clip_min_y;
02280 xc2 = x2 + (clip_min_y-y2)*(x1-x2)/(y1-y2);
02281 break;
02282 case CODE_S:
02283 yc2 = clip_max_y;
02284 xc2 = x2 + (clip_max_y-y2)*(x1-x2)/(y1-y2);
02285 break;
02286 case CODE_W:
02287 xc2 = clip_min_x;
02288 yc2 = y2 + (clip_min_x-x2)*(y1-y2)/(x1-x2);
02289 break;
02290 case CODE_E:
02291 xc2 = clip_max_x;
02292 yc2 = y2 + (clip_max_x-x2)*(y1-y2)/(x1-x2);
02293 break;
02294 case CODE_NE: {
02295 yc2 = clip_min_x;
02296 xc2 = x2 + int(0.5+(clip_min_x-y2)*(x1-x2)/(y1-y2));
02297
02298 if (xc2 < clip_min_x || xc2 > clip_max_x) {
02299 xc2 = clip_max_x;
02300 yc2 = y2 + int(0.5+(clip_max_x-x2)*(y1-y2)/(x1-x2));
02301 }
02302 }
02303 break;
02304 case CODE_SE: {
02305
02306 yc2 = clip_max_y;
02307 xc2 = x2 + int(0.5+(clip_max_y-y2)*(x1-x2)/(y1-y2));
02308 if (xc2 < clip_min_x || xc2 > clip_max_x) {
02309 xc2 = clip_max_x;
02310 yc2 = y2 + int(0.5+(clip_max_x-x2)*(y1-y2)/(x1-x2));
02311 }
02312 }
02313 break;
02314
02315 case CODE_NW:
02316 yc2 = clip_min_y;
02317 xc2 = x2 + int(0.5+(clip_min_y-y2)*(x1-x2)/(y1-y2));
02318 if (xc2 < clip_min_x || xc2 > clip_max_x) {
02319 xc2 = clip_min_x;
02320 yc2 = y2 + int(0.5+(clip_min_x-x2)*(y1-y2)/(x1-x2));
02321 }
02322 break;
02323 case CODE_SW:
02324 yc2 = clip_max_y;
02325 xc2 = x2 + int(0.5+(clip_max_y-y2)*(x1-x2)/(y1-y2));
02326 if (xc2 < clip_min_x || xc2 > clip_max_x) {
02327 xc2 = clip_min_x;
02328 yc2 = int(y2 + 0.5+(clip_min_x-x2)*(y1-y2)/(x1-x2));
02329 }
02330 break;
02331 default:
02332 break;
02333
02334 }
02335
02336 if ((xc1 < clip_min_x) || (xc1 > clip_max_x) ||(yc1 < clip_min_y) || (yc1 > clip_max_y) ||(xc2 < clip_min_x) || (xc2 > clip_max_x) || (yc2 < clip_min_y) || (yc2 > clip_max_y) )
02337 return false;
02338 x1 = xc1;
02339 y1 = yc1;
02340 x2 = xc2;
02341 y2 = yc2;
02342
02343 return true;
02344 }
02345
02346 virtual void DrawClipedLine(int x1, int y1, int x2, int y2, unsigned int color) {
02347 if(ClipLine(x1,y1,x2,y2))
02348 {
02349
02350 mx->drawline(x1,y1,x2,y2,color);
02351 }
02352 }
02353
02354 void End() {
02355
02356 mx->unlock();
02357 }
02358
02359 };
02360
02361 }
02362
02363
02364 #endif