Fixed a picking bug that occurred when an object's frame parent was defined with respect to a different star system than it's namespace parent. This was a problem when planets were defined in a frame centered on the solar system barycenter. The picking code had never been updated to use the frame hierarchy; this change corrects the oversight.

ver1_6_1
Chris Laurel 2008-03-26 00:49:04 +00:00
parent e59f4b4b54
commit b1057d803e
1 changed files with 44 additions and 14 deletions

View File

@ -18,6 +18,8 @@
#include "meshmanager.h"
#include "render.h"
#include "universe.h"
#include "timelinephase.h"
#include "frametree.h"
#define ANGULAR_RES 3.5e-6
@ -432,6 +434,38 @@ static bool ExactPlanetPickTraversal(Body* body, void* info)
return true;
}
// Recursively traverse a frame tree; call the specified callback function for each
// body in the tree. The callback function returns a boolean indicating whether
// traversal should continue.
//
// TODO: This function works, but could use some cleanup:
// * Make it a member of the frame tree class
// * Combine info and func into a traversal callback class
static bool traverseFrameTree(FrameTree* frameTree,
double tdb,
PlanetarySystem::TraversalFunc func,
void* info)
{
for (unsigned int i = 0; i < frameTree->childCount(); i++)
{
TimelinePhase* phase = frameTree->getChild(i);
if (phase->includes(tdb))
{
Body* body = phase->body();
if (!func(body, info))
return false;
if (body->getFrameTree() != NULL)
{
if (!traverseFrameTree(body->getFrameTree(), tdb, func, info))
return false;
}
}
}
return true;
}
Selection Universe::pickPlanet(SolarSystem& solarSystem,
const UniversalCoord& origin,
@ -466,31 +500,28 @@ Selection Universe::pickPlanet(SolarSystem& solarSystem,
// First see if there's a planet|moon that the pick ray intersects.
// Select the closest planet|moon intersected.
solarSystem.getPlanets()->traverse(ExactPlanetPickTraversal,
(void*) &pickInfo);
traverseFrameTree(solarSystem.getFrameTree(), when, ExactPlanetPickTraversal, (void*) &pickInfo);
if (pickInfo.closestBody != NULL)
{
// Retain that body
Body* closestBody = pickInfo.closestBody;
// Check if there is a satellite in front of the primary body that is
// sufficiently close to the pickRay
// Check if there is a satellite in front of the primary body that is
// sufficiently close to the pickRay
traverseFrameTree(solarSystem.getFrameTree(), when, ApproxPlanetPickTraversal, (void*) &pickInfo);
solarSystem.getPlanets()->traverse(ApproxPlanetPickTraversal,
(void*) &pickInfo);
if (pickInfo.closestBody == closestBody)
return Selection(closestBody);
return Selection(closestBody);
// Nothing else around, select the body and return
// Are we close enough to the satellite and is it in front of the body?
if ((pickInfo.sinAngle2Closest <= sinTol2) &&
if ((pickInfo.sinAngle2Closest <= sinTol2) &&
(pickInfo.closestDistance > pickInfo.closestApproxDistance))
return Selection(pickInfo.closestBody);
return Selection(pickInfo.closestBody);
// Yes, select the satellite
else
return Selection(closestBody);
else
return Selection(closestBody);
// No, select the primary body
}
@ -500,9 +531,8 @@ Selection Universe::pickPlanet(SolarSystem& solarSystem,
// clicks on a pixel where the planet's disc has been rendered--in order
// to make distant planets visible on the screen at all, their apparent
// size has to be greater than their actual disc size.
traverseFrameTree(solarSystem.getFrameTree(), when, ApproxPlanetPickTraversal, (void*) &pickInfo);
solarSystem.getPlanets()->traverse(ApproxPlanetPickTraversal,
(void*) &pickInfo);
if (pickInfo.sinAngle2Closest <= sinTol2)
return Selection(pickInfo.closestBody);
else