00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __UIUC_PPL_CHARM_VIEWPOINT_H
00009 #define __UIUC_PPL_CHARM_VIEWPOINT_H
00010
00011 #ifndef CMK_USE_INTEL_SSE
00012
00013 #if defined (__SSE__)
00014 # define CMK_USE_INTEL_SSE 1
00015 #endif
00016
00017 #endif
00018
00019 #if CMK_USE_INTEL_SSE
00020 #include <xmmintrin.h>
00021 #endif
00022
00023 #include "ckvector3d.h"
00024 #ifdef __CHARMC__
00025 # include "pup.h"
00026 #endif
00027
00031 class CkRay {
00032 public:
00033 CkVector3d pos,dir;
00034
00035 CkRay() {}
00036 CkRay(const CkVector3d &s,const CkVector3d &d)
00037 :pos(s), dir(d) {}
00038
00039 CkVector3d at(double t) const {return pos+t*dir;}
00040
00041 #ifdef __CK_PUP_H
00042 void pup(PUP::er &p) {p|pos; p|dir;}
00043 #endif
00044 };
00045
00050 class CkMatrix3d {
00051 double data[4][4];
00052 public:
00053 inline double &operator() (int r,int c) {return data[r][c];}
00054 inline const double &operator() (int r,int c) const {return data[r][c];}
00055
00056
00057 inline void scaleRow(int r,double s) {
00058 for (int c=0;c<4;c++) data[r][c]*=s;
00059 }
00060
00061 inline void addRow(int rSrc,double s,int rDest) {
00062 for (int c=0;c<4;c++) data[rDest][c]+=s*data[rSrc][c];
00063 }
00064
00065 #ifdef __CK_PUP_H
00066 void pup(PUP::er &p) {
00067 p(&data[0][0],16);
00068 }
00069 #endif
00070 };
00071
00073 typedef CkVector3d CkVector2d;
00074
00075 #if CMK_USE_INTEL_SSE
00076
00077
00078
00079
00080
00081
00082
00083 inline __m128 _ck_SSE_reduce(__m128 r) {
00084
00085
00086
00087
00088
00089
00090 __m128 swapLo = _mm_shuffle_ps(r,r, _MM_SHUFFLE(2,3,0,1));
00091 __m128 sumLo = _mm_add_ps(r,swapLo);
00092 __m128 swapHi = _mm_shuffle_ps(sumLo,sumLo, _MM_SHUFFLE(1,1,3,3));
00093 __m128 sum = _mm_add_ps(sumLo,swapHi);
00094 return sum;
00095 }
00096
00097
00098
00099
00100
00101 inline __m128 _ck_SSE_dot(__m128 a,__m128 b) {
00102 return _ck_SSE_reduce(_mm_mul_ps(a,b));
00103 }
00104 #endif
00105
00110 class CkViewpoint {
00111 #if CMK_USE_INTEL_SSE
00112 float projX[4], projY[4], projZ[4], projW[4];
00113 #endif
00114 CkVector3d E;
00115 CkVector3d R;
00116 CkVector3d X,Y;
00117 CkVector3d Z;
00118 CkMatrix3d m;
00119 int wid,ht;
00120
00121 bool isPerspective;
00122
00124 void buildM(void);
00125 public:
00130 CkViewpoint(const CkVector3d &E_,const CkVector3d &R_,CkVector3d Y_=CkVector3d(0,1,1.0e-8));
00131
00134 CkViewpoint(const CkVector3d &E_,const CkVector3d &R_,
00135 const CkVector3d &X_,const CkVector3d &Y_,int w,int h);
00136
00143 CkViewpoint(const CkVector3d &R_,
00144 const CkVector3d &X_,const CkVector3d &Y_,const CkVector3d &Z_,
00145 int w,int h,bool yesThisIsPerspective);
00146
00148 void disablePerspective(void);
00149
00154 void discretize(int w,int h,double hFOV);
00155
00157 void discretizeFlip(int w,int h,double hFOV);
00158
00160 void flip(void);
00161
00163 void window(int w,int h, int x,int y);
00164
00166 CkViewpoint() { wid=ht=-1; }
00167
00169 inline const CkVector3d &getEye(void) const {return E;}
00171 inline bool isOrthographic(void) const {return !isPerspective;}
00172
00174 inline const CkVector3d &getOrigin(void) const {return R;}
00176 inline const CkVector3d &getX(void) const {return X;}
00178 inline const CkVector3d &getY(void) const {return Y;}
00180 inline const CkVector3d &getZ(void) const {return Z;}
00181
00183 inline int getXsize(void) const { return wid; }
00184 inline int getWidth(void) const { return wid; }
00186 inline int getYsize(void) const { return ht; }
00187 inline int getHeight(void) const { return ht; }
00188
00191 inline const CkMatrix3d &getMatrix(void) const {return m;}
00192
00199 inline CkVector3d project(const CkVector3d &in) const {
00200 float w=1.0f/(float)(
00201 m(3,0)*in.x+m(3,1)*in.y+m(3,2)*in.z+m(3,3)
00202 );
00203 return CkVector3d(
00204 w*(m(0,0)*in.x+m(0,1)*in.y+m(0,2)*in.z+m(0,3)),
00205 w*(m(1,0)*in.x+m(1,1)*in.y+m(1,2)*in.z+m(1,3)),
00206 w*(m(2,0)*in.x+m(2,1)*in.y+m(2,2)*in.z+m(2,3))
00207 );
00208 }
00209
00210 enum {nClip=4};
00211
00215 CkHalfspace3d getClip(int i) const;
00216
00218 bool allOffscreen(int n,const CkVector3d *p) const {
00219 for (int c=0;c<nClip;c++) {
00220 CkHalfspace3d h=getClip(c);
00221 int i;
00222 for (i=0;i<n;i++)
00223 if (h.side(p[i])>=0)
00224 break;
00225 if (i==n)
00226 return true;
00227 }
00228 return false;
00229 }
00230
00232 CkVector2d project_noz(const CkVector3d &in) const {
00233 float w=1.0f/(float)(
00234 m(3,0)*in.x+m(3,1)*in.y+m(3,2)*in.z+m(3,3)
00235 );
00236 return CkVector2d(
00237 w*(m(0,0)*in.x+m(0,1)*in.y+m(0,2)*in.z+m(0,3)),
00238 w*(m(1,0)*in.x+m(1,1)*in.y+m(1,2)*in.z+m(1,3)),
00239 0.0
00240 );
00241 }
00242 #if CMK_USE_INTEL_SSE
00243 inline void project_noz(const float *in,int *x,int *y) const {
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 __m128 inR=_mm_load_ps((float *)in);
00256
00257 __m128 w=_mm_rcp_ss(_ck_SSE_dot(inR,_mm_load_ps((float *)projW)));
00258
00259 *x=_mm_cvttss_si32(_mm_mul_ss(w,
00260 _ck_SSE_dot(inR,_mm_load_ps((float *)projX))
00261 ));
00262 *y=_mm_cvttss_si32(_mm_mul_ss(w,
00263 _ck_SSE_dot(inR,_mm_load_ps((float *)projY))
00264 ));
00265 }
00266 #endif
00267
00269 inline CkVector3d viewplane(const CkVector2d &v) const {
00270 return R+v.x*X+v.y*Y;
00271 }
00273 inline CkVector3d projectViewplane(const CkVector3d &u) const {
00274 return viewplane(project_noz(u));
00275 }
00276
00277
00278 CkRay getRay(const CkVector3d &univ) const {
00279 return CkRay(getEye(),univ-getEye());
00280 }
00281
00282 CkRay getPixelRay(const CkVector2d &screen) const {
00283 if (isPerspective)
00284 return CkRay(getEye(),viewplane(screen)-getEye());
00285 else
00286 return CkRay(viewplane(screen)-1000.0*Z, Z);
00287 }
00289 CkVector3d toCamera(const CkVector3d &pt) const {
00290 if (isPerspective)
00291 return getEye()-pt;
00292 else
00293 return Z;
00294 }
00295
00296
00297 bool isInbounds(const CkVector2d &screen) const {
00298 return (screen.x>=0) && (screen.y>=0) &&
00299 (screen.x<wid) && (screen.y<ht);
00300 }
00301
00302 void clip(CkVector2d &screen) const {
00303 if (screen.x<0) screen.x=0;
00304 if (screen.y<0) screen.y=0;
00305 if (screen.x>wid) screen.x=wid;
00306 if (screen.y>ht) screen.y=ht;
00307 }
00308
00309 void makeOpenGL(double *dest,double z_near,double z_far) const;
00310
00311 #ifdef __CK_PUP_H
00312 void pup(PUP::er &p);
00313 #endif
00314 };
00315
00317 class CkAxes3d {
00318 CkVector3d axes[3];
00319
00320 CkVector3d &x(void) {return axes[0];}
00321 CkVector3d &y(void) {return axes[1];}
00322 CkVector3d &z(void) {return axes[2];}
00323
00324
00325 void ortho(void) {
00326 z()=x().cross(y());
00327 y()=z().cross(x());
00328 }
00329
00330 void normalize(void) {
00331 for (int i=0;i<3;i++)
00332 axes[i]=axes[i].dir();
00333 }
00334 public:
00335 CkAxes3d() {
00336 axes[0]=CkVector3d(1,0,0);
00337 axes[1]=CkVector3d(0,1,0);
00338 axes[2]=CkVector3d(0,0,1);
00339 }
00340
00341
00342 const CkVector3d &getX(void) const {return axes[0];}
00343 const CkVector3d &getY(void) const {return axes[1];}
00344 const CkVector3d &getZ(void) const {return axes[2];}
00345
00346
00347
00348
00349 void nudge(double dx,double dy) {
00350 x()+=dx*z();
00351 y()+=dy*z();
00352 ortho(); normalize();
00353 }
00354
00355 void rotate(double dz) {
00356 x()+=dz*y();
00357 y()-=dz*x();
00358 ortho(); normalize();
00359 }
00360 };
00361
00362
00363
00364
00365 #endif