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
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;
00124
00125 t0 = v.dot(direction);
00126 if (v2 > _epsMinus) {
00127 if (t0 < Geometry::EPS) return;
00128 register double td2 = _radius2 - v2 + (t0*t0);
00129 if (td2 < 0.0) return;
00130
00131 t0 = (v2 < _epsPlus) ? t0 + sqrt(td2) : t0 - sqrt(td2);
00132 } else {
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
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;
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);
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;
00223 }
00224
00225 bool Hemisphere::separation(Geometry& geom, Vector3* pDir)
00226 {
00227 fprintf(stderr,"Hemisphere::separation(): Unimplemented\n");
00228 return false;
00229 }
00230
00231 double Hemisphere::distance(const Geometry& geom, Vector3* pDir)
00232 {
00233 fprintf(stderr,"Hemisphere::distance(): Unimplemented\n");
00234 return - MAXDOUBLE;
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); \
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
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
00372 }
00373
00374 Vector3 Hemisphere::samplePriorToPoweredZenith(double elevationRand,
00375 double azimuthRand,
00376 int power,
00377 double* pPDFVal) const
00378 {
00379
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
00420 }
00421
00422 #undef ESG_ANGLES_TO_VECTOR