Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

universe.cpp File Reference

#include <celmath/mathlib.h>
#include <celmath/vecmath.h>
#include <celmath/intersect.h>
#include <celutil/utf8.h>
#include <cassert>
#include "astro.h"
#include "3dsmesh.h"
#include "meshmanager.h"
#include "universe.h"

Include dependency graph for universe.cpp:

Go to the source code of this file.

Defines

#define ANGULAR_RES   3.5e-6

Functions

static bool ApproxPlanetPickTraversal (Body *body, void *info)
static bool ExactPlanetPickTraversal (Body *body, void *info)


Define Documentation

#define ANGULAR_RES   3.5e-6
 

Definition at line 22 of file universe.cpp.

Referenced by ApproxPlanetPickTraversal(), CloseStarPicker::CloseStarPicker(), DSOPicker::DSOPicker(), Universe::pickDeepSkyObject(), Universe::pickPlanet(), Universe::pickStar(), DSOPicker::process(), CloseStarPicker::process(), StarPicker::process(), and StarPicker::StarPicker().


Function Documentation

static bool ApproxPlanetPickTraversal Body body,
void *  info
[static]
 

Definition at line 303 of file universe.cpp.

References ANGULAR_RES, PlanetPickInfo::atanTolerance, PlanetPickInfo::closestApproxDistance, PlanetPickInfo::closestBody, Ray3< T >::direction, distance(), PlanetPickInfo::jd, Vector3< T >::length(), Vector3< T >::normalize(), Ray3< T >::origin, PlanetPickInfo::pickRay, PlanetPickInfo::sinAngle2Closest, and sqrt().

Referenced by Universe::pickPlanet().

00304 {
00305     PlanetPickInfo* pickInfo = (PlanetPickInfo*) info;
00306 
00307     // Reject invisible bodies and bodies that don't exist at the current time
00308     if (body->getClassification() == Body::Invisible || !body->extant(pickInfo->jd))
00309         return true;
00310 
00311     Point3d bpos = body->getHeliocentricPosition(pickInfo->jd);
00312     Vec3d bodyDir = bpos - pickInfo->pickRay.origin;
00313     double distance = bodyDir.length();
00314 
00315     // Check the apparent radius of the orbit against our tolerance factor.
00316     // This check exists to make sure than when picking a distant, we select
00317     // the planet rather than one of its satellites.
00318     float appOrbitRadius = (float) (body->getOrbit()->getBoundingRadius() /
00319                                     distance);
00320     
00321     if ((pickInfo->atanTolerance > ANGULAR_RES ? pickInfo->atanTolerance: 
00322         ANGULAR_RES) > appOrbitRadius)
00323     {
00324         return true;
00325     }
00326 
00327     bodyDir.normalize();
00328     Vec3d bodyMiss = bodyDir - pickInfo->pickRay.direction;
00329     double sinAngle2 = sqrt(bodyMiss * bodyMiss)/2.0;
00330 
00331     if (sinAngle2 <= pickInfo->sinAngle2Closest)
00332     {
00333         pickInfo->sinAngle2Closest = sinAngle2 > ANGULAR_RES ? sinAngle2 : 
00334                                                  ANGULAR_RES;
00335         pickInfo->closestBody = body;
00336         pickInfo->closestApproxDistance = distance;
00337     }
00338 
00339     return true;
00340 }

static bool ExactPlanetPickTraversal Body body,
void *  info
[static]
 

Definition at line 344 of file universe.cpp.

References PlanetPickInfo::closestBody, PlanetPickInfo::closestDistance, conjugate(), Ray3< T >::direction, distance(), ResourceManager< T >::find(), GetModelManager(), InvalidResource, PlanetPickInfo::jd, Vector3< T >::normalize(), Ray3< T >::origin, Model::pick(), PlanetPickInfo::pickRay, sqrt(), testIntersection(), Quaternion< T >::w, Quaternion< T >::x, Quaternion< T >::y, and Quaternion< T >::z.

Referenced by Universe::pickPlanet().

00345 {
00346     PlanetPickInfo* pickInfo = reinterpret_cast<PlanetPickInfo*>(info);
00347     Point3d bpos = body->getHeliocentricPosition(pickInfo->jd);
00348     float radius = body->getRadius();
00349     double distance = -1.0;
00350 
00351     // Test for intersection with the bounding sphere
00352     if (body->getClassification() != Body::Invisible &&
00353         body->extant(pickInfo->jd) &&
00354         testIntersection(pickInfo->pickRay, Sphered(bpos, radius), distance))
00355     {
00356         if (body->getModel() == InvalidResource)
00357         {
00358             // There's no mesh, so the object is an ellipsoid.  If it's
00359             // oblate, do a ray intersection test to see if the object was
00360             // picked.  Otherwise, the object is spherical and we've already
00361             // done all the work we need to.
00362             if (body->getOblateness() != 0.0f)
00363             {
00364                 // Oblate sphere; use ray ellipsoid intersection calculation
00365                 Vec3d ellipsoidAxes(radius,
00366                                     radius * (1.0 - body->getOblateness()),
00367                                     radius);
00368                 // Transform rotate the pick ray into object coordinates
00369                 Mat3d m = conjugate(body->getEclipticalToEquatorial(pickInfo->jd)).toMatrix3();
00370                 Ray3d r(Point3d(0, 0, 0) + (pickInfo->pickRay.origin - bpos),
00371                         pickInfo->pickRay.direction);
00372                 r = r * m;
00373                 if (!testIntersection(r, Ellipsoidd(ellipsoidAxes), distance))
00374                     distance = -1.0;
00375             }
00376         }
00377         else
00378         {
00379             // Transform rotate the pick ray into object coordinates
00380             Quatf qf = body->getOrientation();
00381             Quatd qd(qf.w, qf.x, qf.y, qf.z);
00382             Mat3d m = conjugate(qd * body->getEclipticalToGeographic(pickInfo->jd)).toMatrix3();
00383             Ray3d r(Point3d(0, 0, 0) + (pickInfo->pickRay.origin - bpos),
00384                     pickInfo->pickRay.direction);
00385             r = r * m;
00386 
00387             // The mesh vertices are normalized, then multiplied by a scale
00388             // factor.  Thus, the ray needs to be multiplied by the inverse of
00389             // the mesh scale factor.
00390             double s = 1.0 / radius;
00391             r.origin.x *= s;
00392             r.origin.y *= s;
00393             r.origin.z *= s;
00394             r.direction *= s;
00395 
00396             Model* model = GetModelManager()->find(body->getModel());
00397             if (model != NULL)
00398             {
00399                 if (!model->pick(r, distance))
00400                     distance = -1.0;
00401             }
00402         }
00403         // Make also sure that the pickRay does not intersect the body in the
00404         // opposite hemisphere! Hence, need again the "bodyMiss" angle
00405 
00406         Vec3d bodyDir = bpos - pickInfo->pickRay.origin;
00407         bodyDir.normalize();
00408         Vec3d bodyMiss = bodyDir - pickInfo->pickRay.direction;
00409         double sinAngle2 = sqrt(bodyMiss * bodyMiss)/2.0;
00410 
00411 
00412         if (sinAngle2 < sin(PI/4.0) && distance > 0.0 && 
00413             distance  <= pickInfo->closestDistance)
00414         {
00415             pickInfo->closestDistance = distance;
00416             pickInfo->closestBody = body;
00417         }
00418     }
00419 
00420     return true;
00421 }


Generated on Sat Jan 14 22:31:28 2006 for Celestia by  doxygen 1.4.1