Split StarOctree into StarOctree and DynamicStarOctree. Moved star visibility routines into StarDatabase.

pull/3/head
Chris Laurel 2001-05-09 02:40:48 +00:00
parent b129e41667
commit c34c013f30
8 changed files with 294 additions and 196 deletions

View File

@ -32,70 +32,12 @@ static const int splitThreshold = 100;
static const float sqrt3 = 1.732050808f;
StarOctree::StarOctree(const Point3f& center, float _scale, float limitingMag) :
root(NULL), scale(_scale)
{
absMag = astro::appToAbsMag(limitingMag, scale * sqrt3);
root = new StarOctreeNode(center, absMag);
}
StarOctree::~StarOctree()
{
if (root != NULL)
delete root;
}
void StarOctree::insertStar(const Star& star)
{
root->insertStar(star, scale);
}
void StarOctree::processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Quatf& orientation,
float fovY,
float aspectRatio,
float limitingMag) const
{
// Compute the bounding planes of an infinite view frustum
Planef frustumPlanes[5];
Vec3f planeNormals[5];
Mat3f rot = orientation.toMatrix3();
float h = (float) tan(fovY / 2);
float w = h * aspectRatio;
planeNormals[0] = Vec3f(0, 1, -h);
planeNormals[1] = Vec3f(0, -1, -h);
planeNormals[2] = Vec3f(1, 0, -w);
planeNormals[3] = Vec3f(-1, 0, -w);
planeNormals[4] = Vec3f(0, 0, -1);
for (int i = 0; i < 5; i++)
{
planeNormals[i].normalize();
planeNormals[i] = planeNormals[i] * rot;
frustumPlanes[i] = Planef(planeNormals[i], position);
}
root->processVisibleStars(starHandler, position, frustumPlanes,
limitingMag, scale);
}
int StarOctree::countNodes() const
{
return 1 + root->countChildren();
}
int StarOctree::countStars() const
{
return root->countStars();
}
StarOctreeNode::StarOctreeNode(const Point3f& _center, float _absMag) :
DynamicStarOctree::DynamicStarOctree(const Point3f& _center, float _absMag) :
stars(NULL), children(NULL), center(_center), absMag(_absMag)
{
}
StarOctreeNode::~StarOctreeNode()
DynamicStarOctree::~DynamicStarOctree()
{
if (children != NULL)
{
@ -103,6 +45,7 @@ StarOctreeNode::~StarOctreeNode()
{
delete children[i];
}
delete [] children;
}
}
@ -120,7 +63,7 @@ static int childIndex(const Star& star, const Point3f& center)
}
void StarOctreeNode::insertStar(const Star& star, float scale)
void DynamicStarOctree::insertStar(const Star& star, float scale)
{
// If the star is brighter than the node's magnitude, insert
// it here now.
@ -159,65 +102,7 @@ void StarOctreeNode::insertStar(const Star& star, float scale)
}
void StarOctreeNode::processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Planef* frustumPlanes,
float limitingMag,
float scale) const
{
// See if this node lies within the view frustum
{
for (int i = 0; i < 5; i++)
{
const Planef* plane = frustumPlanes + i;
float r = scale * (abs(plane->normal.x) +
abs(plane->normal.y) +
abs(plane->normal.z));
if (plane->normal * Vec3f(center.x, center.y, center.z) - plane->d < -r)
return;
}
}
// Compute the distance to node; this is equal to the distance to
// the center of the node minus the radius of the node, scale * sqrt3.
float minDistance = (position - center).length() - scale * sqrt3;
// Process the stars in this node
if (stars != NULL)
{
float dimmest = minDistance > 0 ? astro::appToAbsMag(limitingMag, minDistance) : 100;
for (vector<const Star*>::const_iterator iter = stars->begin();
iter != stars->end(); iter++)
{
if ((*iter)->getAbsoluteMagnitude() < dimmest)
{
float distance = (position - (*iter)->getPosition()).length();
float appMag = astro::absToAppMag((*iter)->getAbsoluteMagnitude(), distance);
if (appMag < limitingMag)
starHandler.process(**iter, distance, appMag);
}
}
}
if (minDistance <= 0 || astro::absToAppMag(absMag, minDistance) <= limitingMag)
{
// Recurse into the child nodes
if (children != NULL)
{
for (int i = 0; i < 8; i++)
{
children[i]->processVisibleStars(starHandler,
position,
frustumPlanes,
limitingMag,
scale * 0.5f);
}
}
}
}
void StarOctreeNode::addStar(const Star& star)
void DynamicStarOctree::addStar(const Star& star)
{
if (stars == NULL)
stars = new vector<const Star*>();
@ -225,16 +110,16 @@ void StarOctreeNode::addStar(const Star& star)
}
void StarOctreeNode::split(float scale)
void DynamicStarOctree::split(float scale)
{
children = new StarOctreeNode*[8];
children = new DynamicStarOctree*[8];
for (int i = 0; i < 8; i++)
{
Point3f p(center);
p.x += ((i & XPos) != 0) ? scale : -scale;
p.y += ((i & YPos) != 0) ? scale : -scale;
p.z += ((i & ZPos) != 0) ? scale : -scale;
children[i] = new StarOctreeNode(p, astro::lumToAbsMag(astro::absMagToLum(absMag) / 4.0f));
children[i] = new DynamicStarOctree(p, astro::lumToAbsMag(astro::absMagToLum(absMag) / 4.0f));
}
sortStarsIntoChildNodes();
}
@ -243,7 +128,7 @@ void StarOctreeNode::split(float scale)
// Sort this node's stars into stars that are bright enough to remain
// in the node, and stars that should be placed into one of the eight
// child nodes.
void StarOctreeNode::sortStarsIntoChildNodes()
void DynamicStarOctree::sortStarsIntoChildNodes()
{
int nBrightStars = 0;
@ -265,7 +150,111 @@ void StarOctreeNode::sortStarsIntoChildNodes()
}
int StarOctreeNode::countChildren() const
void DynamicStarOctree::rebuildAndSort(StarOctree*& node, Star*& sortedStars)
{
Star* firstStar = sortedStars;
if (stars != NULL)
{
for (vector<const Star*>::const_iterator iter = stars->begin();
iter != stars->end(); iter++)
{
*sortedStars++ = **iter;
}
}
uint32 nStars = (uint32) (sortedStars - firstStar);
node = new StarOctree(center, absMag, firstStar, nStars);
if (children != NULL)
{
node->children = new StarOctree*[8];
for (int i = 0; i < 8; i++)
children[i]->rebuildAndSort(node->children[i], sortedStars);
}
}
StarOctree::StarOctree(const Point3f& _center,
float _absMag,
Star* _firstStar,
uint32 _nStars) :
center(_center),
absMag(_absMag),
firstStar(_firstStar),
nStars(_nStars),
children(NULL)
{
}
StarOctree::~StarOctree()
{
if (children != NULL)
{
for (int i = 0; i < 8; i++)
delete children[i];
delete [] children;
}
}
void StarOctree::processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Planef* frustumPlanes,
float limitingMag,
float scale) const
{
// See if this node lies within the view frustum
{
for (int i = 0; i < 5; i++)
{
const Planef* plane = frustumPlanes + i;
float r = scale * (abs(plane->normal.x) +
abs(plane->normal.y) +
abs(plane->normal.z));
if (plane->normal * Vec3f(center.x, center.y, center.z) - plane->d < -r)
return;
}
}
// Compute the distance to node; this is equal to the distance to
// the center of the node minus the radius of the node, scale * sqrt3.
float minDistance = (position - center).length() - scale * sqrt3;
// Process the stars in this node
float dimmest = minDistance > 0 ? astro::appToAbsMag(limitingMag, minDistance) : 100;
for (int i = 0; i < nStars; i++)
{
Star& star = firstStar[i];
if (star.getAbsoluteMagnitude() < dimmest)
{
float distance = (position - star.getPosition()).length();
float appMag = astro::absToAppMag(star.getAbsoluteMagnitude(), distance);
if (appMag < limitingMag)
starHandler.process(star, distance, appMag);
}
}
if (minDistance <= 0 || astro::absToAppMag(absMag, minDistance) <= limitingMag)
{
// Recurse into the child nodes
if (children != NULL)
{
for (int i = 0; i < 8; i++)
{
children[i]->processVisibleStars(starHandler,
position,
frustumPlanes,
limitingMag,
scale * 0.5f);
}
}
}
}
int StarOctree::countChildren() const
{
if (children == NULL)
{
@ -281,18 +270,15 @@ int StarOctreeNode::countChildren() const
}
}
int StarOctreeNode::countStars() const
int StarOctree::countStars() const
{
int nStars = stars == NULL ? 0 : stars->size();
int count = nStars;
if (children != NULL)
{
for (int i = 0; i < 8; i++)
{
nStars += children[i]->countStars();
}
count += children[i]->countStars();
}
return nStars;
return count;
}

View File

@ -26,13 +26,38 @@ class StarHandler
};
class StarOctreeNode
class StarOctree;
class DynamicStarOctree
{
public:
StarOctreeNode(const Point3f& _center, float _absMag);
~StarOctreeNode();
DynamicStarOctree(const Point3f& _center, float _absMag);
~DynamicStarOctree();
void insertStar(const Star&, float);
void rebuildAndSort(StarOctree*& node, Star*& sortedStars);
private:
void addStar(const Star&);
void split(float);
void sortStarsIntoChildNodes();
Point3f center;
float absMag;
std::vector<const Star*>* stars;
DynamicStarOctree** children;
};
class StarOctree
{
public:
StarOctree(const Point3f& _center,
float _absMag,
Star* _firstStar,
uint32 _nStars);
~StarOctree();
void processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Planef* frustumPlanes,
@ -41,39 +66,15 @@ class StarOctreeNode
int countChildren() const;
int countStars() const;
private:
void addStar(const Star&);
void split(float);
void sortStarsIntoChildNodes();
friend DynamicStarOctree;
int nFaintStars;
private:
Point3f center;
float absMag;
std::vector<const Star*>* stars;
StarOctreeNode** children;
Star* firstStar;
uint32 nStars;
StarOctree** children;
};
class StarOctree
{
public:
StarOctree(const Point3f& center, float _scale, float limitingMag);
~StarOctree();
void insertStar(const Star&);
void processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Quatf& orientation,
float fovY,
float aspectRatio,
float limitingMag) const;
int countNodes() const;
int countStars() const;
private:
StarOctreeNode* root;
float scale;
float absMag;
};
#endif // _OCTREE_H_

View File

@ -481,7 +481,6 @@ void Renderer::clearLabels()
void Renderer::render(const Observer& observer,
const StarDatabase& starDB,
const VisibleStarSet& visset,
const StarOctree& visTree,
float faintestVisible,
SolarSystem* solarSystem,
GalaxyList* galaxies,
@ -544,7 +543,7 @@ void Renderer::render(const Observer& observer,
if ((renderFlags & ShowStars) != 0)
{
if ((renderFlags & ShowCloudMaps) != 0)
renderStars(starDB, visTree, faintestVisible, observer);
renderStars(starDB, faintestVisible, observer);
else
renderStars(starDB, visset, faintestVisible, observer);
}
@ -1883,7 +1882,6 @@ void StarRenderer::process(const Star& star, float distance, float appMag)
void Renderer::renderStars(const StarDatabase& starDB,
const StarOctree& visTree,
float faintestVisible,
const Observer& observer)
{
@ -1904,12 +1902,12 @@ void Renderer::renderStars(const StarDatabase& starDB,
starParticles.clear();
glareParticles.clear();
visTree.processVisibleStars(starRenderer,
(Point3f) observer.getPosition(),
observer.getOrientation(),
fov,
(float) windowWidth / (float) windowHeight,
faintestVisible);
starDB.processVisibleStars(starRenderer,
(Point3f) observer.getPosition(),
observer.getOrientation(),
fov,
(float) windowWidth / (float) windowHeight,
faintestVisible);
glBindTexture(GL_TEXTURE_2D, starTex->getName());
renderParticles(starParticles, observer.getOrientation());

View File

@ -14,7 +14,6 @@
#include <string>
#include "stardb.h"
#include "visstars.h"
#include "octree.h"
#include "observer.h"
#include "solarsys.h"
#include "galaxy.h"
@ -43,7 +42,6 @@ class Renderer
void render(const Observer&,
const StarDatabase&,
const VisibleStarSet&,
const StarOctree&,
float faintestVisible,
SolarSystem*,
GalaxyList*,
@ -133,7 +131,6 @@ class Renderer
float faintestVisible,
const Observer& observer);
void renderStars(const StarDatabase& starDB,
const StarOctree& visTree,
float faintestVisible,
const Observer& observer);
void renderGalaxies(const GalaxyList& galaxies,

View File

@ -31,7 +31,6 @@ Simulation::Simulation() :
solarSystemCatalog(NULL),
galaxies(NULL),
visibleStars(NULL),
visTree(NULL),
closestSolarSystem(NULL),
selection(),
targetSpeed(0.0),
@ -155,7 +154,6 @@ void Simulation::render(Renderer& renderer)
renderer.render(observer,
*stardb,
*visibleStars,
*visTree,
faintestVisible,
closestSolarSystem,
galaxies,
@ -259,12 +257,14 @@ void Simulation::setStarDatabase(StarDatabase* db,
visibleStars->setCloseDistance(10.0f);
visibleStars->updateAll(observer);
#if 0
visTree = new StarOctree(Point3f(1000, 1000, 1000), 5000.0f, 6.0f);
for (int i = 0; i < (int) db->size(); i++)
visTree->insertStar(*db->getStar(i));
cout << "Node count: " << visTree->countNodes() << "\n";
cout << "Total stars: " << visTree->countStars() << "\n";
#endif
}
}

View File

@ -19,7 +19,6 @@
#include "mesh.h"
#include "stardb.h"
#include "visstars.h"
#include "octree.h"
#include "solarsys.h"
#include "galaxy.h"
#include "texmanager.h"
@ -127,7 +126,6 @@ class Simulation
GalaxyList* galaxies;
VisibleStarSet* visibleStars;
StarOctree* visTree;
SolarSystem* closestSolarSystem;
Star* selectedStar;
Body* selectedBody;

View File

@ -14,6 +14,8 @@
#include "celestia.h"
#include "mathlib.h"
#include "util.h"
#include "astro.h"
#include "plane.h"
#include "stardb.h"
using namespace std;
@ -28,8 +30,15 @@ static string GlieseCatalogPrefix("Gliese ");
static string RossCatalogPrefix("Ross ");
static string LacailleCatalogPrefix("Lacaille ");
static const float OctreeRootSize = 5000.0f;
static const float OctreeMagnitude = 6.0f;
StarDatabase::StarDatabase() : nStars(0), stars(NULL), names(NULL)
StarDatabase::StarDatabase() : nStars(0),
stars(NULL),
names(NULL),
catalogNumberIndex(NULL),
octreeRoot(NULL)
{
}
@ -37,10 +46,11 @@ StarDatabase::~StarDatabase()
{
if (stars != NULL)
delete [] stars;
if (catalogNumberIndex != NULL)
delete [] catalogNumberIndex;
}
// Less than operator for stars is used to sort and find stars by catalog
// number
#if 0
bool operator<(const Star& a, const Star& b)
{
return a.getCatalogNumber() < b.getCatalogNumber();
@ -50,15 +60,38 @@ bool operator<(Star& s, uint32 n)
{
return s.getCatalogNumber() < n;
}
#endif
// Less than operator for stars is used to sort and find stars by catalog
// number
bool operator<(const StarRecord& a,
const StarRecord& b)
{
return a.star->getCatalogNumber() < b.star->getCatalogNumber();
}
bool operator<(StarRecord& s, uint32 n)
{
return s.star->getCatalogNumber() < n;
}
Star* StarDatabase::find(uint32 catalogNumber) const
{
#if 0
Star* star = lower_bound(stars, stars + nStars, catalogNumber);
if (star != stars + nStars && star->getCatalogNumber() == catalogNumber)
return star;
else
return NULL;
#endif
StarRecord* star = lower_bound(catalogNumberIndex, catalogNumberIndex + nStars,
catalogNumber);
if (star != catalogNumberIndex + nStars &&
star->star->getCatalogNumber() == catalogNumber)
return star->star;
else
return NULL;
}
@ -169,6 +202,36 @@ string StarDatabase::getStarName(uint32 catalogNumber) const
}
void StarDatabase::processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Quatf& orientation,
float fovY,
float aspectRatio,
float limitingMag) const
{
// Compute the bounding planes of an infinite view frustum
Planef frustumPlanes[5];
Vec3f planeNormals[5];
Mat3f rot = orientation.toMatrix3();
float h = (float) tan(fovY / 2);
float w = h * aspectRatio;
planeNormals[0] = Vec3f(0, 1, -h);
planeNormals[1] = Vec3f(0, -1, -h);
planeNormals[2] = Vec3f(1, 0, -w);
planeNormals[3] = Vec3f(-1, 0, -w);
planeNormals[4] = Vec3f(0, 0, -1);
for (int i = 0; i < 5; i++)
{
planeNormals[i].normalize();
planeNormals[i] = planeNormals[i] * rot;
frustumPlanes[i] = Planef(planeNormals[i], position);
}
octreeRoot->processVisibleStars(starHandler, position, frustumPlanes,
limitingMag, OctreeRootSize);
}
StarNameDatabase* StarDatabase::getNameDatabase() const
{
return names;
@ -272,16 +335,60 @@ StarDatabase *StarDatabase::read(istream& in)
db = NULL;
}
sort(db->stars, db->stars + db->nStars);
cout << "nStars = " << db->nStars << '\n';
cout << "throw out = " << throwOut << '\n';
cout << "fix up = " << fixUp << '\n';
db->buildOctree();
db->buildIndexes();
return db;
}
void StarDatabase::buildOctree()
{
// This should only be called once for the database
// ASSERT(octreeRoot == NULL);
cout << "Sorting stars into octree . . .\n";
cout.flush();
float absMag = astro::appToAbsMag(OctreeMagnitude,
OctreeRootSize * (float) sqrt(3));
DynamicStarOctree* root = new DynamicStarOctree(Point3f(1000, 1000, 1000),
absMag);
for (int i = 0; i < nStars; i++)
root->insertStar(stars[i], OctreeRootSize);
cout << "Spatially sorting stars for improved locality of reference . . .\n";
cout.flush();
Star* sortedStars = new Star[nStars];
Star* firstStar = sortedStars;
root->rebuildAndSort(octreeRoot, firstStar);
cout << "Octree has " << 1 + octreeRoot->countChildren() << " nodes " <<
" and " << octreeRoot->countStars() << " stars.\n";
// Clean up . . .
delete stars;
delete root;
stars = sortedStars;
}
void StarDatabase::buildIndexes()
{
// This should only be called once for the database
// ASSERT(catalogNumberIndex == NULL);
cout << "Building catalog number index . . .\n";
cout.flush();
catalogNumberIndex = new StarRecord[nStars];
for (int i = 0; i < nStars; i++)
catalogNumberIndex[i].star = &stars[i];
sort(catalogNumberIndex, catalogNumberIndex + nStars);
}
StarNameDatabase* StarDatabase::readNames(istream& in)
{
StarNameDatabase* db = new StarNameDatabase();

View File

@ -15,13 +15,19 @@
#include "constellation.h"
#include "starname.h"
#include "star.h"
#include "octree.h"
typedef std::map<uint32, StarName*> StarNameDatabase;
struct StarRecord
{
Star* star;
};
class StarDatabase
{
public:
public:
static StarDatabase* read(std::istream&);
static StarNameDatabase* readNames(std::istream&);
@ -33,15 +39,27 @@ public:
Star* find(uint32 catalogNumber) const;
Star* find(std::string) const;
void processVisibleStars(StarHandler& starHandler,
const Point3f& position,
const Quatf& orientation,
float fovY,
float aspectRatio,
float limitingMag) const;
string getStarName(uint32 catalogNumber) const;
StarNameDatabase* getNameDatabase() const;
void setNameDatabase(StarNameDatabase*);
private:
private:
void buildOctree();
void buildIndexes();
int nStars;
Star *stars;
StarNameDatabase* names;
StarRecord* catalogNumberIndex;
StarOctree* octreeRoot;
};
@ -55,11 +73,4 @@ uint32 StarDatabase::size() const
return nStars;
}
#if 0
bool GetCatalogNumber(std::string name,
const StarNameDatabase& namedb,
uint32& catalogNumber);
#endif
#endif // _STARDB_H_