// -*- C++ -*- /* * Simple MultimEdia LiTerator(SMELT) * by Chris Xiong 2015 * Math header & implementation * * WARNING: This library is in development and interfaces would be very * unstable. * */ #ifndef SMMATH_H #define SMMATH_H #include #include #define sqr(x) ((x)*(x)) #define EPS 1e-8 #ifndef PI #define PI 3.14159265358979323846264338327950288f #endif #ifdef min //for windows sdk, the stupidest sdk ever #undef min #undef max #endif templateconst T& min(const T& a,const T& b){return aconst T& max(const T& a,const T& b){return a>b?a:b;} class smMath { public: static double deg2rad(double deg){return deg/180.*PI;} static double rad2deg(double rad){return rad/PI*180.;} static double clamprad(double a){while(a<0)a+=2*PI;while(a>2*PI)a-=2*PI;return a;} static double clampdeg(double a){while(a<0)a+=360.;while(a>360)a-=360.;return a;} }; class smvec2d { public: double x,y; smvec2d(double _x,double _y){x=_x;y=_y;} smvec2d(){x=y=.0;} double l(){return sqrt(sqr(x)+sqr(y));} void normalize(){double L=l();if(L=0&&s<4)return m+s*4;else return NULL;} void clear(){for(int i=0;i<16;++i)m[i]=.0;} void loadIdentity(){clear();m[0]=m[5]=m[10]=m[15]=1.;} void translate(double x,double y,double z) { smMatrix tmp;tmp.loadIdentity(); tmp.m[12]=x;tmp.m[13]=y;tmp.m[14]=z; *this=*this*tmp; } void rotate(double a,double x,double y,double z) { if(smvec3d(x,y,z).l()<=EPS)return; if(fabs(smvec3d(x,y,z).l()-1)>EPS) { smvec3d a(x,y,z);a.normalize(); x=a.x;y=a.y;z=a.z; } smMatrix tmp; double c=cos(a),s=sin(a); tmp.m[ 0]=x*x*(1-c)+c; tmp.m[ 4]=x*y*(1-c)-z*s; tmp.m[ 8]=x*z*(1-c)+y*s; tmp.m[ 1]=y*x*(1-c)+z*s; tmp.m[ 5]=y*y*(1-c)+c; tmp.m[ 9]=y*z*(1-c)-x*s; tmp.m[ 2]=x*z*(1-c)-y*s; tmp.m[ 6]=y*z*(1-c)+x*s; tmp.m[10]=z*z*(1-c)+c; tmp.m[15]=1; *this=*this*tmp; } void lookat(smvec3d eye,smvec3d at,smvec3d up) { smvec3d f=at-eye;f.normalize();up.normalize(); smvec3d s=f*up;smvec3d u=s.getNormalized()*f; m[0]= s.x;m[4]= s.y;m[ 8]= s.z;m[12]=0; m[1]= u.x;m[5]= u.y;m[ 9]= u.z;m[13]=0; m[2]=-f.x;m[6]=-f.y;m[10]=-f.z;m[14]=0; m[3]= 0;m[7]= 0;m[11]= 0;m[15]=1; } friend smMatrix operator *(smMatrix a,smMatrix b) { smMatrix ret; for(int i=0;i<4;++i) for(int j=0;j<4;++j) for(int k=0;k<4;++k) ret[j][i]+=a[k][i]*b[j][k]; return ret; } friend smvec3d operator *(smMatrix a,smvec3d b) { return smvec3d(a[0][0]*b.x+a[1][0]*b.y+a[2][0]*b.z, a[0][1]*b.x+a[1][1]*b.y+a[2][1]*b.z, a[0][2]*b.x+a[1][2]*b.y+a[2][2]*b.z); } friend smvec4d operator *(smMatrix a,smvec4d b) { return smvec4d(a[0][0]*b.x+a[1][0]*b.y+a[2][0]*b.z+a[3][0]*b.w, a[0][1]*b.x+a[1][1]*b.y+a[2][1]*b.z+a[3][1]*b.w, a[0][2]*b.x+a[1][2]*b.y+a[2][2]*b.z+a[3][2]*b.w, a[0][3]*b.x+a[1][3]*b.y+a[2][3]*b.z+a[3][3]*b.w); } }; #endif