Hemisphere.cc

Go to the documentation of this file.
00001 #include <esg/geometry/Hemisphere.h>
00002 
00003 using namespace esg;
00004 
00005 Mesh* Hemisphere::_mesh(int density) const
00006 {
00007     fprintf(stderr,"Hemisphere::_mesh(): Unimplemented\n");
00008     return NULL;
00009 }
00010 
00011 void Hemisphere::_duplicate_attributes(const Geometry& src)
00012 {
00013     Sphere::_duplicate_attributes(src);
00014     _xAxis.set(((Hemisphere&)src)._xAxis);
00015     _yAxis.set(((Hemisphere&)src)._yAxis);
00016     _zAxis.set(((Hemisphere&)src)._zAxis);
00017     _backfaceCulling = ((Hemisphere&)src)._backfaceCulling;
00018 }
00019 
00020 void Hemisphere::_rotateX(float a)
00021 {
00022     Matrix3 trMat;
00023     trMat.rotX(a);
00024     trMat.transform(_centre);
00025     trMat.transform(_xAxis);
00026     trMat.transform(_yAxis);
00027     trMat.transform(_zAxis);
00028 }
00029 
00030 void Hemisphere::_rotateY(float a)
00031 {
00032     Matrix3 trMat;
00033     trMat.rotY(a);
00034     trMat.transform(_centre);
00035     trMat.transform(_xAxis);
00036     trMat.transform(_yAxis);
00037     trMat.transform(_zAxis);
00038 }
00039 
00040 void Hemisphere::_rotateZ(float a)
00041 {
00042     Matrix3 trMat;
00043     trMat.rotZ(a);
00044     trMat.transform(_centre);
00045     trMat.transform(_xAxis);
00046     trMat.transform(_yAxis);
00047     trMat.transform(_zAxis);
00048 }
00049 
00050 void Hemisphere::_rotate(float a, const Vector3& axis)
00051 {
00052     Matrix4 trMat;
00053     trMat.rotationGL(a, axis);
00054     trMat.transform(_centre);
00055     trMat.transform(_xAxis);
00056     trMat.transform(_yAxis);
00057     trMat.transform(_zAxis);
00058 }
00059 
00060 void Hemisphere::_rotate(const Matrix3& rotMat)
00061 {
00062     rotMat.transform(_centre);
00063     rotMat.transform(_xAxis);
00064     rotMat.transform(_yAxis);
00065     rotMat.transform(_zAxis);
00066 }
00067 
00068 void Hemisphere::_transform(const Matrix4& trMat)
00069 {
00070     Matrix3 rMat;
00071     trMat.get(rMat);
00072     trMat.transform(_centre);
00073     rMat.transform(_xAxis);
00074     rMat.transform(_yAxis);
00075     rMat.transform(_zAxis);
00076 }
00077 
00078 
00079 //-------- public --------
00080 
00081 Hemisphere::Hemisphere(const Vector3& c, float r, const Vector3& z, bool bfc)
00082     : Sphere(c,r), _zAxis(z), _backfaceCulling(bfc)
00083 {
00084     (fabs(z.y) > fabs(z.x)) ? _xAxis.set(1., 0., 0.) : _xAxis.set(0., 1., 0.);
00085     _yAxis.cross(_zAxis, _xAxis);
00086     _yAxis.normalize();
00087     _xAxis.cross(_zAxis, _yAxis);
00088     _xAxis.normalize();
00089 }
00090 
00091 Hemisphere::Hemisphere(const Vector3& z, bool bfc)
00092     : _zAxis(z), _backfaceCulling(bfc)
00093 {
00094     (fabs(z.y) > fabs(z.x)) ? _xAxis.set(1., 0., 0.) : _xAxis.set(0., 1., 0.);
00095     _yAxis.cross(_zAxis, _xAxis);
00096     _yAxis.normalize();
00097     _xAxis.cross(_zAxis, _yAxis);
00098     _xAxis.normalize();
00099 }
00100 
00101 Hemisphere::Hemisphere(bool bfc)
00102     : _xAxis(Vector3(1., 0., 0.)),
00103       _yAxis(Vector3(1., 0.,-1.)),
00104       _zAxis(Vector3(0., 1., 0.)),
00105       _backfaceCulling(bfc)
00106 {
00107 }
00108 
00109 
00110 void Hemisphere::rayIntersection(PointEnv*      pPE,
00111                                  int            mask,
00112                                  const Vector3& origin,
00113                                  const Vector3& direction,
00114                                  float          maxDist)
00115 {
00116     pPE->mask = ENV_HAVE_NOTHING;
00117 
00118     Vector3          v(_centre - origin);
00119     register double  v2 = v.dot(v);
00120     register double& t0 = pPE->distance;
00121 
00122     fprintf(stderr,"Hemisphere::_rayIntersection(): Unimplemented\n");
00123     return; // TO DO
00124 
00125     t0 = v.dot(direction);
00126     if (v2 > _epsMinus) { // outside of or at the sphere
00127         if (t0 < Geometry::EPS) return; // sphere is 'behind' the ray
00128         register double td2 = _radius2 - v2 + (t0*t0);
00129         if (td2 < 0.0) return; // ray doesn't hit the sphere
00130         // if ray starts on the surface then get farter (inner) intersection
00131         t0 = (v2 < _epsPlus) ? t0 + sqrt(td2) : t0 - sqrt(td2);
00132     } else { // ray starts inside the sphere
00133         t0 += sqrt(_radius2 - v2 + (t0*t0));
00134     }
00135 
00136     if (t0 > maxDist) return;
00137 
00138     if (mask & (ENV_WANT_INTERSECTION|ENV_WANT_UV_COORD|ENV_WANT_NORMAL)) {
00139         pPE->intersection.set(direction);
00140         pPE->intersection.scaleAdd(t0, origin);
00141         if (mask & ENV_WANT_UV_COORD) {
00142             Vector3 xyz(pPE->intersection);
00143             xyz.sub(_centre);
00144             double auxV = acos(xyz.z/_radius);
00145             if (xyz.y >= 0.) 
00146                 pPE->uvCoord.set(acos(xyz.x/(_radius*sin(auxV))) / (2*PI),
00147                                  auxV / PI);
00148             else
00149                 pPE->uvCoord.set((PI+acos(xyz.x/(_radius*sin(auxV)))) / (2*PI),
00150                                  auxV / PI);
00151             pPE->mask |=
00152                 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE|ENV_HAVE_UV_COORD;
00153         } else 
00154             pPE->mask |=
00155                 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE;
00156 
00157         if (mask & ENV_WANT_NORMAL) {
00158             pPE->normal.set(pPE->intersection - _centre);
00159             //pPE->normal.scale(1. / _radius); // unsharp normalization
00160             pPE->normal.normalize();
00161             pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00162             pPE->mask |= ENV_HAVE_NORMAL;
00163         }
00164     } else 
00165         pPE->mask |= ENV_HAVE_INTERFERENCE|ENV_HAVE_DISTANCE;
00166 }
00167 
00168 
00169 bool Hemisphere::mapToUV(const Vector3& v, Vector2& uv)
00170 {
00171     fprintf(stderr,"Hemisphere::mapToUV(): Unimplemented\n");
00172     return false; // TO DO 
00173 }
00174 
00175 void Hemisphere::randomSample(int mask, PointEnv& pe, double* pdf)
00176 {
00177     pe.mask = ENV_HAVE_NOTHING;
00178     
00179     if (mask & (ENV_WANT_SURFACE_POINT|ENV_WANT_NORMAL|ENV_WANT_UV_COORD)) {
00180         pe.intersection.set(sampleUniformly(ESG_DBL_RAND, ESG_DBL_RAND, pdf));
00181         pe.intersection.scale(_radius/pe.intersection.length());
00182         pe.intersection.add(_centre);
00183         pe.mask |= ENV_HAVE_SURFACE_POINT;
00184 
00185         if ((mask&ENV_WANT_UV_COORD) && mapToUV(pe.intersection, pe.uvCoord))
00186             pe.mask |= ENV_HAVE_UV_COORD;
00187 
00188         if (mask & ENV_WANT_NORMAL) {
00189             pe.normal.set(pe.intersection);
00190             pe.normal.normalize();
00191             pe.mask |= ENV_HAVE_NORMAL;
00192             pe.normalOrientation = PointEnv::OUTWARDS_NORMAL;
00193         }
00194     }
00195 
00196     if (pdf) *pdf *= _radius2;
00197 }
00198 
00199 bool Hemisphere::randomDirection(const Vector3& pov, Vector3&, double* pdf) 
00200 {
00201     fprintf(stderr,"Hemisphere::randomDirection(): Not implemented\n");
00202     return false;
00203 }
00204 
00205 Interval Hemisphere::extent(const Vector3& direction) const
00206 {
00207     fprintf(stderr,"Hemisphere::extent(): Unimplemented\n");
00208     return Interval(FLT_MAX,FLT_MIN);   //MAXFLOAT,MINFLOAT);
00209 }
00210 
00211 Geometry* Hemisphere::clone(const Matrix4* pTrMat) const
00212 {
00213     Hemisphere* pRet = new Hemisphere();
00214     pRet->_duplicate_attributes(*this);
00215     if (pTrMat) pRet->_transform(*pTrMat);
00216     return pRet;
00217 }
00218 
00219 double Hemisphere::radius(const Vector3& centroid) const
00220 {
00221     fprintf(stderr,"Hemisphere::radius(): Unimplemented\n");
00222     return - MAXDOUBLE; // TO DO
00223 }
00224 
00225 bool Hemisphere::separation(Geometry& geom, Vector3* pDir)
00226 {
00227     fprintf(stderr,"Hemisphere::separation(): Unimplemented\n");
00228     return false; // TO DO
00229 }
00230 
00231 double Hemisphere::distance(const Geometry& geom, Vector3* pDir)
00232 {
00233     fprintf(stderr,"Hemisphere::distance(): Unimplemented\n");
00234     return - MAXDOUBLE; // TO DO
00235 }
00236 
00237 void Hemisphere::dump(const char* intent, const char* tab)
00238 {
00239     printf("%s geometry Hemisphere {\n", intent);
00240     printf("%s %s centre %f %f %f\n", intent, tab, _centre.x, _centre.y, _centre.z);
00241     printf("%s %s radius %f\n", intent, tab, _radius);
00242     printf("%s %s backfaceCulling %s\n", intent, tab, ((_backfaceCulling) ? "yes" : "no"));
00243     printf("%s %s orientation [ # x axis, y axis, z axis\n", intent, tab);
00244     printf("%s %s %s %f %f %f\n", intent, tab, tab, _xAxis.x, _xAxis.y, _xAxis.z);
00245     printf("%s %s %s %f %f %f\n", intent, tab, tab, _yAxis.x, _yAxis.y, _yAxis.z);
00246     printf("%s %s %s %f %f %f\n", intent, tab, tab, _zAxis.x, _zAxis.y, _zAxis.z);
00247     printf("%s %s ]\n", intent, tab);
00248     printf("%s }\n", intent);
00249 }
00250 
00251 void Hemisphere::setZenith(const Vector3& zenith)
00252 {
00253     _zAxis.set(zenith);
00254     (fabs(zenith.y) > fabs(zenith.x))
00255         ? _xAxis.set(1., 0., 0.)
00256         : _xAxis.set(0., 1., 0.);
00257     _yAxis.cross(_zAxis, _xAxis);
00258     _yAxis.normalize();
00259     _xAxis.cross(_zAxis, _yAxis);
00260     _xAxis.normalize();
00261 }
00262 
00263 
00264 Vector2 Hemisphere::world2local2D(const Vector3& dir) const
00265 {
00266     Vector3 aux(dir.x * _xAxis.x + dir.y * _xAxis.y + dir.z * _xAxis.z,  
00267                 dir.x * _yAxis.x + dir.y * _yAxis.y + dir.z * _yAxis.z,  
00268                 dir.x * _zAxis.x + dir.y * _zAxis.y + dir.z * _zAxis.z); 
00269     double len = sqrt(aux.x * aux.x + aux.y * aux.y);                 
00270     double p   = 0.0;                                                 
00271     if (len != 0.0) {                                                 
00272         p = acos(aux.x/len);                                          
00273         if (aux.y < 0.) p = 2 * M_PI - p;                             
00274     }
00275     return Vector2(acos(aux.z), p);
00276 }
00277 
00278 #define ESG_ANGLES_TO_VECTOR(a, cosE, sinE, d) { \
00279     double cos_a = cos(a); \
00280     Vector3 aux(_xAxis); \
00281     aux.scale(cos_a); \
00282     (d).set(_yAxis); \
00283     (d).scaleAdd((a<M_PI) ? sqrt(1-cos_a*cos_a) : -sqrt(1-cos_a*cos_a), aux); \
00284     aux.set(_zAxis); /* ^^^^^^^^ fast sin(a) ^^^^^^^^^ */  \
00285     aux.scale(cosE); \
00286     (d).scaleAdd(sinE, aux); \
00287 }
00288 
00289 Vector3 Hemisphere::sampleUniformly(double  elevationRand,
00290                                     double  azimuthRand,
00291                                     double* pPDFVal) const
00292 {
00293     double azimuth = 2. * PI * azimuthRand;
00294     double cosElev = sqrt(1. - elevationRand); 
00295     double sinElev = sqrt(elevationRand);
00296 
00297     Vector3 dir;
00298     
00299     ESG_ANGLES_TO_VECTOR(azimuth, cosElev, sinElev, dir);
00300 
00301     if (pPDFVal) *pPDFVal = .5 / PI;
00302 
00303     return dir;
00304 }
00305 
00306 Vector2 Hemisphere::sampleUniformly2D(double  elevationRand,
00307                                       double  azimuthRand,
00308                                       double* pPDFVal) const
00309 {
00310     if (pPDFVal) *pPDFVal = .5 / PI;
00311     return Vector2(acos(sqrt(1. - elevationRand)), 2. * PI * azimuthRand);
00312 }
00313 
00314 Vector2 Hemisphere::dir2uvUniformly(const Vector3& dir) const
00315 {
00316     Vector3 aux(dir.x * _xAxis.x + dir.y * _xAxis.y + dir.z * _xAxis.z,  
00317                 dir.x * _yAxis.x + dir.y * _yAxis.y + dir.z * _yAxis.z,  
00318                 dir.x * _zAxis.x + dir.y * _zAxis.y + dir.z * _zAxis.z);
00319 
00320     double len = sqrt(aux.x * aux.x + aux.y * aux.y);                 
00321     double phi = 0.0;
00322     if (len != 0.0) {                                                 
00323         phi = acos(aux.x/len) / (2 * M_PI);
00324         if (aux.y < 0.) phi = 1. - phi;
00325     }
00326 
00327     return Vector2(1. - aux.z * aux.z, phi);
00328     //                  ^^^^^  => cos(acos(aux.z)) = aux.z
00329 }
00330 
00331 Vector3 Hemisphere::samplePriorToZenith(double  elevationRand,
00332                                         double  azimuthRand,
00333                                         double* pPDFVal) const
00334 {
00335     double azimuth = 2. * PI * azimuthRand;
00336     double sinElev = elevationRand;
00337     double cosElev = sqrt(1. - elevationRand * elevationRand);
00338 
00339     Vector3 dir;
00340     
00341     ESG_ANGLES_TO_VECTOR(azimuth, cosElev, sinElev, dir);
00342 
00343     if (pPDFVal) *pPDFVal = cosElev / PI;
00344 
00345     return dir;
00346 }
00347 
00348 Vector2 Hemisphere::samplePriorToZenith2D(double  elevationRand,
00349                                           double  azimuthRand,
00350                                           double* pPDFVal) const
00351 {
00352     double cosElev = sqrt(1. - elevationRand * elevationRand);
00353     if (pPDFVal) *pPDFVal = cosElev / PI;
00354     return Vector2(asin(elevationRand), 2. * PI * azimuthRand);
00355 }
00356 
00357 Vector2 Hemisphere::dir2uvPriorToZenith(const Vector3& dir) const 
00358 {
00359     Vector3 aux(dir.x * _xAxis.x + dir.y * _xAxis.y + dir.z * _xAxis.z,  
00360                 dir.x * _yAxis.x + dir.y * _yAxis.y + dir.z * _yAxis.z,  
00361                 dir.x * _zAxis.x + dir.y * _zAxis.y + dir.z * _zAxis.z);
00362 
00363     double len = sqrt(aux.x * aux.x + aux.y * aux.y);                 
00364     double phi = 0.0;                                                 
00365     if (len != 0.0) {                                                 
00366         phi = acos(aux.x/len) / (2 * M_PI);
00367         if (aux.y < 0.) phi = 1. - phi;
00368     }                                                                 
00369     
00370     return Vector2(sqrt(1. - aux.z * aux.z), phi);
00371     //             ^^^^^^^^^^^^^^^^^^^^^^^^ = sin(acos(aux.z))
00372 }
00373 
00374 Vector3 Hemisphere::samplePriorToPoweredZenith(double  elevationRand,
00375                                                double  azimuthRand,
00376                                                int     power,
00377                                                double* pPDFVal) const
00378 {
00379     // here the elevation angle is the angle between direction and base plane!
00380     double azimuth = 2. * PI * azimuthRand;
00381     double sinElev = 1. - pow(elevationRand,  1./(power+1.));
00382     double cosElev = sqrt(1. - sinElev * sinElev);
00383 
00384     Vector3 dir;
00385 
00386     ESG_ANGLES_TO_VECTOR(azimuth, cosElev, sinElev, dir);
00387 
00388     if (pPDFVal) *pPDFVal = (power + 1.) * pow(cosElev, power) / (2. * PI);
00389 
00390     return dir;
00391 }
00392 
00393 Vector2 Hemisphere::samplePriorToPoweredZenith2D(double  elevationRand,
00394                                                  double  azimuthRand,
00395                                                  int     power,
00396                                                  double* pPDFVal) const
00397 {
00398     double sinElev = 1. - pow(elevationRand,  1./(power+1.));
00399     double cosElev = sqrt(1. - sinElev * sinElev);
00400     if (pPDFVal) *pPDFVal = (power + 1.) * pow(cosElev, power) / (2. * PI);
00401     return Vector2(asin(sinElev), 2. * PI * azimuthRand);
00402 }
00403 
00404 Vector2 Hemisphere::dir2uvPriorToPoweredZenith(const Vector3& dir,
00405                                                int            power) const
00406 {
00407     Vector3 aux(dir.x * _xAxis.x + dir.y * _xAxis.y + dir.z * _xAxis.z,  
00408                 dir.x * _yAxis.x + dir.y * _yAxis.y + dir.z * _yAxis.z,  
00409                 dir.x * _zAxis.x + dir.y * _zAxis.y + dir.z * _zAxis.z);
00410 
00411     double len = sqrt(aux.x * aux.x + aux.y * aux.y);                 
00412     double phi = 0.0;                                                 
00413     if (len != 0.0) {                                                 
00414         phi = acos(aux.x/len) / (2 * M_PI);
00415         if (aux.y < 0.) phi = 1. - phi;
00416     }                                                                 
00417     
00418     return Vector2(1. - pow(sqrt(1. - aux.z*aux.z), ((double)power+1.)), phi);
00419     //                      ^^^^^^^^^^^^^^^^^^^^^ = sin(acos(aux.z))
00420 }
00421 
00422 #undef ESG_ANGLES_TO_VECTOR

Generated on Wed Jun 28 12:24:31 2006 for esg by  doxygen 1.4.6