Eigenized galaxy rendering and more of the core renderer.

sensor-dev
Chris Laurel 2009-07-21 03:14:29 +00:00
parent 47117439fc
commit 5a31a08df9
14 changed files with 476 additions and 481 deletions

View File

@ -20,7 +20,9 @@
#include <celutil/util.h>
#include <celutil/debug.h>
#include <celmath/intersect.h>
#include "eigenport.h"
using namespace Eigen;
using namespace std;
@ -30,7 +32,7 @@ const float DSO_DEFAULT_ABS_MAGNITUDE = -1000.0f;
DeepSkyObject::DeepSkyObject() :
catalogNumber(InvalidCatalogNumber),
position(0, 0, 0),
orientation(1),
orientation(Quaternionf::Identity()),
radius(1),
absMag(DSO_DEFAULT_ABS_MAGNITUDE),
infoURL(NULL),
@ -48,22 +50,22 @@ void DeepSkyObject::setCatalogNumber(uint32 n)
catalogNumber = n;
}
Point3d DeepSkyObject::getPosition() const
Vector3d DeepSkyObject::getPosition() const
{
return position;
}
void DeepSkyObject::setPosition(const Point3d& p)
void DeepSkyObject::setPosition(const Vector3d& p)
{
position = p;
}
Quatf DeepSkyObject::getOrientation() const
Quaternionf DeepSkyObject::getOrientation() const
{
return orientation;
}
void DeepSkyObject::setOrientation(const Quatf& q)
void DeepSkyObject::setOrientation(const Quaternionf& q)
{
orientation = q;
}
@ -181,7 +183,7 @@ bool DeepSkyObject::load(AssociativeArray* params, const string& resPath)
Vec3d position(0.0, 0.0, 0.0);
if (params->getVector("Position", position))
{
setPosition(Point3d(position.x, position.y, position.z));
setPosition(toEigen(position));
}
else
{
@ -192,7 +194,7 @@ bool DeepSkyObject::load(AssociativeArray* params, const string& resPath)
params->getNumber("RA", RA);
params->getNumber("Dec", dec);
Point3d p = astro::equatorialToCelestialCart(RA, dec, distance);
setPosition(p);
setPosition(toEigen(p));
}
// Get orientation
@ -203,7 +205,7 @@ bool DeepSkyObject::load(AssociativeArray* params, const string& resPath)
Quatf q(1);
q.setAxisAngle(Vec3f((float) axis.x, (float) axis.y, (float) axis.z),
(float) degToRad(angle));
setOrientation(q);
setOrientation(toEigen(q));
double radius = 1.0;
params->getNumber("Radius", radius);

View File

@ -18,6 +18,8 @@
#include <celmath/ray.h>
#include <celengine/glcontext.h>
#include <celengine/parser.h>
#include <Eigen/Core>
#include <Eigen/Geometry>
extern const float DSO_DEFAULT_ABS_MAGNITUDE;
@ -29,6 +31,8 @@ class OpenCluster;
class DeepSkyObject
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
DeepSkyObject();
virtual ~DeepSkyObject();
@ -38,8 +42,8 @@ class DeepSkyObject
}
void setCatalogNumber(uint32);
Point3d getPosition() const;
void setPosition(const Point3d&);
Eigen::Vector3d getPosition() const;
void setPosition(const Eigen::Vector3d&);
static void hsv2rgb( float*, float*, float*, float, float, float);
@ -47,8 +51,8 @@ class DeepSkyObject
virtual void setType(const std::string&) = 0;
virtual size_t getDescription(char* buf, size_t bufLength) const;
Quatf getOrientation() const;
void setOrientation(const Quatf&);
Eigen::Quaternionf getOrientation() const;
void setOrientation(const Eigen::Quaternionf&);
/*! Return the radius of a bounding sphere large enough to contain the object.
* For correct rendering, all of the geometry must fit within this sphere radius.
@ -98,8 +102,8 @@ class DeepSkyObject
private:
uint32 catalogNumber;
Point3d position;
Quatf orientation;
Eigen::Vector3d position;
Eigen::Quaternionf orientation;
float radius;
float absMag;
std::string* infoURL;

View File

@ -33,11 +33,8 @@ bool dsoStraddlesNodesPredicate(const Vector3d& cellCenterPos, DeepSkyObject* co
//checks if this dso's radius straddles child nodes
float dsoRadius = _dso->getBoundingSphereRadius();
Point3d dsoPos2 = _dso->getPosition();
Vector3d dsoPos(dsoPos2.x, dsoPos2.y, dsoPos2.z);
return (dsoPos - cellCenterPos).cwise().abs().minCoeff() < dsoRadius;
#if 0
return (_dso->getPosition() - cellCenterPos).cwise().abs().minCoeff() < dsoRadius;
#if CELVEC
return abs(dsoPos.x - cellCenterPos.x) < dsoRadius ||
abs(dsoPos.y - cellCenterPos.y) < dsoRadius ||
abs(dsoPos.z - cellCenterPos.z) < dsoRadius;
@ -54,8 +51,7 @@ double dsoAbsoluteMagnitudeDecayFunction(const double excludingFactor)
template <>
DynamicDSOOctree* DynamicDSOOctree::getChild(DeepSkyObject* const & _obj, const PointType& cellCenterPos)
{
Point3d objPos2 = _obj->getPosition();
PointType objPos(objPos2.x, objPos2.y, objPos2.z);
PointType objPos = _obj->getPosition();
int child = 0;
child |= objPos.x() < cellCenterPos.x() ? 0 : XPos;
@ -91,7 +87,11 @@ void DSOOctree::processVisibleObjects(DSOHandler& processor,
{
const Hyperplane<double, 3>& plane = frustumPlanes[i];
#if 0
double r = scale * plane.normal().cwise().abs().sum();
if (plane.signedDistance(cellCenterPos) < -r)
return;
#if CELVEC
double r = scale * (abs(plane->normal.x) +
abs(plane->normal.y) +
abs(plane->normal.z));
@ -99,9 +99,6 @@ void DSOOctree::processVisibleObjects(DSOHandler& processor,
if (plane->normal * cellCenterPos - plane->d < -r)
return;
#endif
double r = scale * plane.normal().cwise().abs().sum();
if (plane.signedDistance(cellCenterPos) < -r)
return;
}
// Compute the distance to node; this is equal to the distance to
@ -117,7 +114,7 @@ void DSOOctree::processVisibleObjects(DSOHandler& processor,
float absMag = _obj->getAbsoluteMagnitude();
if (absMag < dimmest)
{
double distance = (obsPosition - toEigen(_obj->getPosition())).norm() - _obj->getBoundingSphereRadius();
double distance = (obsPosition - _obj->getPosition()).norm() - _obj->getBoundingSphereRadius();
float appMag = (float) ((distance >= 32.6167) ? astro::absToAppMag((double) absMag, distance) : absMag);
if ( appMag < limitingFactor)
@ -128,9 +125,11 @@ void DSOOctree::processVisibleObjects(DSOHandler& processor,
// See if any of the objects in child nodes are potentially included
// that we need to recurse deeper.
if (minDistance <= 0.0 || astro::absToAppMag((double) exclusionFactor, minDistance) <= limitingFactor)
{
// Recurse into the child nodes
if (_children != NULL)
for (int i=0; i<8; ++i)
{
for (int i = 0; i < 8; ++i)
{
_children[i]->processVisibleObjects(processor,
obsPosition,
@ -138,6 +137,8 @@ void DSOOctree::processVisibleObjects(DSOHandler& processor,
limitingFactor,
scale * 0.5f);
}
}
}
}
@ -166,10 +167,10 @@ void DSOOctree::processCloseObjects(DSOHandler& processor,
{
DeepSkyObject* _obj = _firstObject[i]; //
if ((obsPosition - toEigen(_obj->getPosition())).squaredNorm() < radiusSquared) //
if ((obsPosition - _obj->getPosition()).squaredNorm() < radiusSquared) //
{
float absMag = _obj->getAbsoluteMagnitude();
double distance = (obsPosition - toEigen(_obj->getPosition())).norm() - _obj->getBoundingSphereRadius();
double distance = (obsPosition - _obj->getPosition()).norm() - _obj->getBoundingSphereRadius();
processor.process(_obj, distance, absMag);
}

View File

@ -13,6 +13,7 @@
#include <algorithm>
#include <cstdio>
#include <cassert>
#include <Eigen/StdVector>
#include "celestia.h"
#include <celmath/mathlib.h>
#include <celmath/perlin.h>
@ -25,14 +26,14 @@
#include "vecgl.h"
#include "render.h"
#include "texture.h"
#include "eigenport.h"
#include <Eigen/Geometry>
using namespace Eigen;
using namespace std;
static int width = 128, height = 128;
static Color colorTable[256];
static Vector3f colorTable[256];
static const unsigned int GALAXY_POINTS = 3500;
static bool formsInitialized = false;
@ -50,9 +51,15 @@ float Galaxy::lightGain = 0.0f;
bool operator < (const Blob& b1, const Blob& b2)
{
return (b1.position.distanceFromOrigin() < b2.position.distanceFromOrigin());
return (b1.position.squaredNorm() < b2.position.squaredNorm());
}
struct GalacticForm
{
std::vector<Blob>* blobs;
Vector3f scale;
};
struct GalaxyTypeName
{
const char* name;
@ -227,16 +234,13 @@ bool Galaxy::pick(const Ray3d& ray,
// The ellipsoid should be slightly larger to compensate for the fact
// that blobs are considered points when galaxies are built, but have size
// when they are drawn.
float yscale = (type < E0 )? MAX_SPIRAL_THICKNESS: form->scale.y + RADIUS_CORRECTION;
Vec3d ellipsoidAxes(getRadius()*(form->scale.x + RADIUS_CORRECTION),
getRadius()* yscale,
getRadius()*(form->scale.z + RADIUS_CORRECTION));
float yscale = (type < E0 )? MAX_SPIRAL_THICKNESS: form->scale.y() + RADIUS_CORRECTION;
Vector3d ellipsoidAxes(getRadius()*(form->scale.x() + RADIUS_CORRECTION),
getRadius()* yscale,
getRadius()*(form->scale.z() + RADIUS_CORRECTION));
Quatf qf= getOrientation();
Quatd qd(qf.w, qf.x, qf.y, qf.z);
Eigen::Vector3d p(getPosition().x, getPosition().y, getPosition().z);
return testIntersection(Ray3d(ray.origin - p, ray.direction).transform(Eigen::Quaterniond(qf.w, qf.x, qf.y, qf.z).toRotationMatrix()),
Matrix3d rotation = getOrientation().cast<double>().toRotationMatrix();
return testIntersection(Ray3d(ray.origin - getPosition(), ray.direction).transform(rotation),
Ellipsoidd(ellipsoidAxes),
distanceToPicker,
cosAngleToBoundCenter);
@ -268,15 +272,24 @@ void Galaxy::render(const GLContext& context,
float pixelSize)
{
if (form == NULL)
renderGalaxyEllipsoid(context, offset, viewerOrientation, brightness, pixelSize);
{
//renderGalaxyEllipsoid(context, offset, viewerOrientation, brightness, pixelSize);
}
else
renderGalaxyPointSprites(context, offset, viewerOrientation, brightness, pixelSize);
{
renderGalaxyPointSprites(context, toEigen(offset), toEigen(viewerOrientation), brightness, pixelSize);
}
}
inline void glVertex4(const Vector4f& v)
{
glVertex3fv(v.data());
}
void Galaxy::renderGalaxyPointSprites(const GLContext&,
const Vec3f& offset,
const Quatf& viewerOrientation,
const Vector3f& offset,
const Quaternionf& viewerOrientation,
float brightness,
float pixelSize)
{
@ -287,15 +300,15 @@ void Galaxy::renderGalaxyPointSprites(const GLContext&,
be noticeable on screen; if it's not we'll break right here,
avoiding all the overhead of the matrix transformations and
GL state changes: */
float distanceToDSO = offset.length() - getRadius();
if (distanceToDSO < 0)
distanceToDSO = 0;
float distanceToDSO = offset.norm() - getRadius();
if (distanceToDSO < 0)
distanceToDSO = 0;
float minimumFeatureSize = pixelSize * distanceToDSO;
float size = 2 * getRadius();
float minimumFeatureSize = pixelSize * distanceToDSO;
float size = 2 * getRadius();
if (size < minimumFeatureSize)
return;
if (size < minimumFeatureSize)
return;
if (galaxyTex == NULL)
{
@ -307,21 +320,32 @@ void Galaxy::renderGalaxyPointSprites(const GLContext&,
glEnable(GL_TEXTURE_2D);
galaxyTex->bind();
Mat3f viewMat = viewerOrientation.toMatrix3();
Vec3f v0 = Vec3f(-1, -1, 0) * viewMat;
Vec3f v1 = Vec3f( 1, -1, 0) * viewMat;
Vec3f v2 = Vec3f( 1, 1, 0) * viewMat;
Vec3f v3 = Vec3f(-1, 1, 0) * viewMat;
Matrix3f viewMat = viewerOrientation.conjugate().toRotationMatrix();
Vector4f v0(Vector4f::Zero());
Vector4f v1(Vector4f::Zero());
Vector4f v2(Vector4f::Zero());
Vector4f v3(Vector4f::Zero());
v0.start<3>() = viewMat * Vector3f(-1, -1, 0) * size;
v1.start<3>() = viewMat * Vector3f( 1, -1, 0) * size;
v2.start<3>() = viewMat * Vector3f( 1, 1, 0) * size;
v3.start<3>() = viewMat * Vector3f(-1, 1, 0) * size;
//Mat4f m = (getOrientation().toMatrix4() *
// Mat4f::scaling(form->scale) *
// Mat4f::scaling(getRadius()));
Quaternionf orientation = getOrientation().conjugate();
#if 0
Mat3f m =
Mat3f::scaling(form->scale)*getOrientation().toMatrix3()*Mat3f::scaling(size);
#endif
Matrix3f mScale = form->scale.asDiagonal() * size;
Matrix3f mLinear = orientation.toRotationMatrix() * mScale;
// Note: fixed missing factor of 2 in getRadius() scaling of galaxy diameter!
// Note: fixed correct ordering of (non-commuting) operations!
Matrix4f m = Matrix4f::Identity();
m.corner<3,3>(TopLeft) = mLinear;
m.block<3,1>(0, 3) = offset;
int pow2 = 1;
@ -334,57 +358,64 @@ void Galaxy::renderGalaxyPointSprites(const GLContext&,
if (type < E0 || type > E3) //all galaxies, except ~round elliptics
{
cosi = Vec3f(0,1,0) * getOrientation().toMatrix3()
* offset/offset.length();
brightness_corr = (float) sqrt(abs(cosi));
cosi = (orientation * Vector3f::UnitY()).dot(offset) / offset.norm();
brightness_corr = std::sqrt(std::abs(cosi));
if (brightness_corr < 0.2f)
brightness_corr = 0.2f;
}
if (type > E3) // only elliptics with higher ellipticities
{
cosi = Vec3f(1,0,0) * getOrientation().toMatrix3()
* offset/offset.length();
brightness_corr = brightness_corr * (float) abs((cosi));
cosi = (orientation * Vector3f::UnitX()).dot(offset) / offset.norm();
brightness_corr = brightness_corr * std::abs(cosi);
if (brightness_corr < 0.45f)
brightness_corr = 0.45f;
}
glPushMatrix();
glTranslatef(-offset.x(), -offset.y(), -offset.z());
float btot = ((type > SBc) && (type < Irr))? 2.5f: 5.0f;
const float spriteScaleFactor = 1.0f / 1.55f;
glBegin(GL_QUADS);
for (unsigned int i = 0; i < nPoints; ++i)
{
if ((i & pow2) != 0)
{
pow2 <<= 1;
size /= 1.55f;
size *= spriteScaleFactor;
v0 *= spriteScaleFactor;
v1 *= spriteScaleFactor;
v2 *= spriteScaleFactor;
v3 *= spriteScaleFactor;
if (size < minimumFeatureSize)
break;
}
Blob b = (*points)[i];
Point3f p = b.position * m;
float br = b.brightness / 255.0f;
const Blob& b = (*points)[i];
Vector4f p = m * b.position;
float br = b.brightness / 255.0f;
Color c = colorTable[b.colorIndex]; // lookup static color table
Point3f relPos = p + offset;
Vector3f c = colorTable[b.colorIndex]; // lookup static color table
float screenFrac = size / relPos.distanceFromOrigin();
float screenFrac = size / p.norm();
if (screenFrac < 0.1f)
{
float btot = ((type > SBc) && (type < Irr))? 2.5f: 5.0f;
float a = btot * (0.1f - screenFrac) * brightness_corr * brightness * br;
glColor4f(c.red(), c.green(), c.blue(), (4.0f*lightGain + 1.0f)*a);
glTexCoord2f(0, 0); glVertex(p + (v0 * size));
glTexCoord2f(1, 0); glVertex(p + (v1 * size));
glTexCoord2f(1, 1); glVertex(p + (v2 * size));
glTexCoord2f(0, 1); glVertex(p + (v3 * size));
glColor4f(c.x(), c.y(), c.z(), (4.0f * lightGain + 1.0f) * a);
glTexCoord2f(0, 0); glVertex4(p + v0);
glTexCoord2f(1, 0); glVertex4(p + v1);
glTexCoord2f(1, 1); glVertex4(p + v2);
glTexCoord2f(0, 1); glVertex4(p + v3);
}
}
glEnd();
glPopMatrix();
}
#if 0
void Galaxy::renderGalaxyEllipsoid(const GLContext& context,
const Vec3f& offset,
const Quatf&,
@ -443,6 +474,7 @@ void Galaxy::renderGalaxyEllipsoid(const GLContext& context,
vproc->disable();
}
#endif
unsigned int Galaxy::getRenderMask() const
@ -555,8 +587,8 @@ GalacticForm* buildGalacticForms(const std::string& filename)
kmin = 12;
}
b.position = Point3f(x, y, z);
unsigned int rr = (unsigned int) (b.position.distanceFromOrigin() * 511);
b.position = Vector4f(x, y, z, 1.0f);
unsigned int rr = (unsigned int) (b.position.start<3>().norm() * 511);
b.colorIndex = rr < 256? rr: 255;
galacticPoints->push_back(b);
j++;
@ -578,7 +610,7 @@ GalacticForm* buildGalacticForms(const std::string& filename)
GalacticForm* galacticForm = new GalacticForm();
galacticForm->blobs = galacticPoints;
galacticForm->scale = Vec3f(1.0f, 1.0f, 1.0f);
galacticForm->scale = Vector3f::Ones();
return galacticForm;
}
@ -600,7 +632,8 @@ void InitializeForms()
//convert Hue to RGB
DeepSkyObject::hsv2rgb(&rr, &gg, &bb, hue, 0.20f, 1.0f);
colorTable[i] = Color(rr, gg, bb);
Color c(rr, gg, bb);
colorTable[i] = Vector3f(c.red(), c.green(), c.blue());
}
// Spiral Galaxies, 7 classical Hubble types
@ -629,7 +662,7 @@ void InitializeForms()
ellipticalForms[eform] = buildGalacticForms("models/E0.png");
if (*ellipticalForms)
ellipticalForms[eform]->scale = Vec3f(ell, ell, 1.0f);
ellipticalForms[eform]->scale = Vector3f(ell, ell, 1.0f);
// account for reddening of ellipticals rel.to spirals
if (*ellipticalForms)
@ -658,7 +691,7 @@ void InitializeForms()
float prob = (1 - r) * (fractalsum(Point3f(p.x + 5, p.y + 5, p.z + 5), 8) + 1) * 0.5f;
if (Mathf::frand() < prob)
{
b.position = p;
b.position = Vector4f(p.x, p.y, p.z, 1.0f);
b.brightness = 64u;
unsigned int rr = (unsigned int) (r * 511);
b.colorIndex = rr < 256? rr: 255;
@ -669,7 +702,7 @@ void InitializeForms()
}
irregularForm = new GalacticForm();
irregularForm->blobs = irregularPoints;
irregularForm->scale = Vec3f(0.5f, 0.5f, 0.5f);
irregularForm->scale = Vector3f::Constant(0.5f);
formsInitialized = true;
}

View File

@ -12,24 +12,26 @@
#define _GALAXY_H_
#include <celengine/deepskyobj.h>
#include <Eigen/Core>
#include <Eigen/Geometry>
struct Blob
{
Point3f position;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Eigen::Vector4f position;
unsigned int colorIndex;
float brightness;
};
struct GalacticForm
{
std::vector<Blob>* blobs;
Vec3f scale;
};
class GalacticForm;
class Galaxy : public DeepSkyObject
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Galaxy();
virtual const char* getType() const;
virtual void setType(const std::string&);
@ -52,15 +54,17 @@ class Galaxy : public DeepSkyObject
float brightness,
float pixelSize);
virtual void renderGalaxyPointSprites(const GLContext& context,
const Vec3f& offset,
const Quatf& viewerOrientation,
const Eigen::Vector3f& offset,
const Eigen::Quaternionf& viewerOrientation,
float brightness,
float pixelSize);
#if 0
virtual void renderGalaxyEllipsoid(const GLContext& context,
const Vec3f& offset,
const Quatf& viewerOrientation,
const Eigen::Vector3f& offset,
const Eigen::Quaternionf& viewerOrientation,
float brightness,
float pixelSize);
#endif
GalacticForm* getForm() const;

View File

@ -231,7 +231,7 @@ float Globular::getHalfMassRadius() const
// Aproximation to the half-mass radius r_h [ly]
// (~ 20% accuracy)
return std::tan(degToRad(r_c / 60.0f)) * (float) getPosition().distanceFromOrigin() * pow(10.0f, 0.6f * c - 0.4f);
return std::tan(degToRad(r_c / 60.0f)) * (float) getPosition().norm() * pow(10.0f, 0.6f * c - 0.4f);
}
float Globular::getConcentration() const
@ -284,11 +284,8 @@ bool Globular::pick(const Ray3d& ray,
getRadius() * (form->scale.y + RADIUS_CORRECTION),
getRadius() * (form->scale.z + RADIUS_CORRECTION));
Quatf qf= getOrientation();
Quatd qd(qf.w, qf.x, qf.y, qf.z);
Eigen::Vector3d p(getPosition().x, getPosition().y, getPosition().z);
return testIntersection(Ray3d(ray.origin - p, ray.direction).transform(Eigen::Quaterniond(qf.w, qf.x, qf.y, qf.z).toRotationMatrix()),
Eigen::Vector3d p = getPosition();
return testIntersection(Ray3d(ray.origin - p, ray.direction).transform(getOrientation().cast<double>().toRotationMatrix()),
Ellipsoidd(ellipsoidAxes),
distanceToPicker,
cosAngleToBoundCenter);
@ -398,7 +395,7 @@ void Globular::renderGlobularPointSprites(const GLContext&,
float tidalSize = 2 * tidalRadius;
Mat3f m =
Mat3f::scaling(form->scale) * getOrientation().toMatrix3() *
Mat3f::scaling(form->scale) * fromEigen(getOrientation()).toMatrix3() *
Mat3f::scaling(tidalSize);
vector<GBlob>* points = form->gblobs;
@ -514,7 +511,7 @@ void Globular::recomputeTidalRadius()
// Convert the core radius from arcminutes to light years
// Compute the tidal radius in light years
float coreRadiusLy = std::tan(degToRad(r_c / 60.0f)) * (float) getPosition().distanceFromOrigin();
float coreRadiusLy = std::tan(degToRad(r_c / 60.0f)) * (float) getPosition().norm();
tidalRadius = coreRadiusLy * std::pow(10.0f, c);
}

View File

@ -34,6 +34,8 @@ struct GlobularForm
class Globular : public DeepSkyObject
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Globular();
virtual const char* getType() const;
virtual void setType(const std::string&);

View File

@ -17,6 +17,8 @@
class Nebula : public DeepSkyObject
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Nebula();
virtual const char* getType() const;

View File

@ -17,6 +17,8 @@
class OpenCluster : public DeepSkyObject
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
OpenCluster();
virtual const char* getType() const;

View File

@ -279,16 +279,16 @@ public:
void start();
void render();
void finish();
void addStar(const Vec3f&, const Color&, float);
void setBillboardOrientation(const Quatf&);
void addStar(const Eigen::Vector3f&, const Color&, float);
void setBillboardOrientation(const Eigen::Quaternionf&);
private:
unsigned int capacity;
unsigned int nStars;
float* vertices;
Eigen::Vector3f* vertices;
float* texCoords;
unsigned char* colors;
Vec3f v0, v1, v2, v3;
Eigen::Vector3f v0, v1, v2, v3;
};
@ -331,7 +331,7 @@ StarVertexBuffer::StarVertexBuffer(unsigned int _capacity) :
colors(NULL)
{
nStars = 0;
vertices = new float[capacity * 12];
vertices = new Vector3f[capacity * 4];
texCoords = new float[capacity * 8];
colors = new unsigned char[capacity * 16];
@ -385,13 +385,18 @@ void StarVertexBuffer::finish()
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void StarVertexBuffer::addStar(const Vec3f& pos,
const Color& color,
float size)
void StarVertexBuffer::addStar(const Vector3f& pos,
const Color& color,
float size)
{
if (nStars < capacity)
{
int n = nStars * 12;
int n = nStars * 4;
vertices[n + 0] = pos + v0 * size;
vertices[n + 1] = pos + v1 * size;
vertices[n + 2] = pos + v2 * size;
vertices[n + 3] = pos + v3 * size;
#if 0
vertices[n + 0] = pos.x + v0.x * size;
vertices[n + 1] = pos.y + v0.y * size;
vertices[n + 2] = pos.z + v0.z * size;
@ -404,6 +409,7 @@ void StarVertexBuffer::addStar(const Vec3f& pos,
vertices[n + 9] = pos.x + v3.x * size;
vertices[n + 10] = pos.y + v3.y * size;
vertices[n + 11] = pos.z + v3.z * size;
#endif
n = nStars * 16;
color.get(colors + n);
color.get(colors + n + 4);
@ -420,13 +426,13 @@ void StarVertexBuffer::addStar(const Vec3f& pos,
}
}
void StarVertexBuffer::setBillboardOrientation(const Quatf& q)
void StarVertexBuffer::setBillboardOrientation(const Quaternionf& q)
{
Mat3f m = q.toMatrix3();
v0 = Vec3f(-1, -1, 0) * m;
v1 = Vec3f( 1, -1, 0) * m;
v2 = Vec3f( 1, 1, 0) * m;
v3 = Vec3f(-1, 1, 0) * m;
Matrix3f m = q.conjugate().toRotationMatrix();
v0 = m * Vector3f(-1, -1, 0);
v1 = m * Vector3f( 1, -1, 0);
v2 = m * Vector3f( 1, 1, 0);
v3 = m * Vector3f(-1, 1, 0);
}
@ -3195,10 +3201,13 @@ void Renderer::draw(const Observer& observer,
// Set up the camera for star rendering; the units of this phase
// are light years.
Point3f observerPosLY = (Point3f) observer.getPosition();
Vector3f observerPosLY = observer.getPosition().offsetFromLy(Vector3f::Zero());
#if CELVEC
Point3f observerPosLy = (Point3f) observer.getPosition();
observerPosLY.x *= 1e-6f;
observerPosLY.y *= 1e-6f;
observerPosLY.z *= 1e-6f;
#endif
glPushMatrix();
glRotate(m_cameraOrientation);
@ -3589,7 +3598,7 @@ void Renderer::draw(const Observer& observer,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
#endif
glTranslatef(-observerPosLY.x, -observerPosLY.y, -observerPosLY.z);
glTranslatef(-observerPosLY.x(), -observerPosLY.y(), -observerPosLY.z());
// Render asterisms
if ((renderFlags & ShowDiagrams) != 0 && universe.getAsterisms() != NULL)
@ -3597,7 +3606,7 @@ void Renderer::draw(const Observer& observer,
/* We'll linearly fade the lines as a function of the observer's
distance to the origin of coordinates: */
float opacity = 1.0f;
float dist = observerPosLY.distanceFromOrigin() * 1e6f;
float dist = observerPosLY.norm() * 1e6f;
if (dist > MaxAsterismLinesConstDist)
{
opacity = clamp((MaxAsterismLinesConstDist - dist) /
@ -3643,7 +3652,7 @@ void Renderer::draw(const Observer& observer,
/* We'll linearly fade the boundaries as a function of the
observer's distance to the origin of coordinates: */
float opacity = 1.0f;
float dist = observerPosLY.distanceFromOrigin() * 1e6f;
float dist = observerPosLY.norm() * 1e6f;
if (dist > MaxAsterismLabelsConstDist)
{
opacity = clamp((MaxAsterismLabelsConstDist - dist) /
@ -4824,9 +4833,9 @@ struct LightIrradiancePredicate
void renderAtmosphere(const Atmosphere& atmosphere,
Point3f center,
const Vector3f& center,
float radius,
const Vec3f& sunDirection,
const Vector3f& sunDirection,
Color ambientColor,
float fade,
bool lit)
@ -4836,35 +4845,32 @@ void renderAtmosphere(const Atmosphere& atmosphere,
glDepthMask(GL_FALSE);
Vec3f eyeVec = center - Point3f(0.0f, 0.0f, 0.0f);
double centerDist = eyeVec.length();
// double surfaceDist = (double) centerDist - (double) radius;
Vector3f eyeVec = center;
double centerDist = eyeVec.norm();
Vec3f normal = eyeVec;
Vector3f normal = eyeVec;
normal = normal / (float) centerDist;
float tangentLength = (float) sqrt(square(centerDist) - square(radius));
float atmRadius = tangentLength * radius / (float) centerDist;
float atmOffsetFromCenter = square(radius) / (float) centerDist;
Point3f atmCenter = center - atmOffsetFromCenter * normal;
Vector3f atmCenter = center - atmOffsetFromCenter * normal;
Vec3f uAxis, vAxis;
if (abs(normal.x) < abs(normal.y) && abs(normal.x) < abs(normal.z))
Vector3f uAxis, vAxis;
if (abs(normal.x()) < abs(normal.y()) && abs(normal.x()) < abs(normal.z()))
{
uAxis = Vec3f(1, 0, 0) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitX().cross(normal);
}
else if (abs(eyeVec.y) < abs(normal.z))
else if (abs(eyeVec.y()) < abs(normal.z()))
{
uAxis = Vec3f(0, 1, 0) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitY().cross(normal);
}
else
{
uAxis = Vec3f(0, 0, 1) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitZ().cross(normal);
}
vAxis = uAxis ^ normal;
uAxis.normalize();
vAxis = uAxis.cross(normal);
float height = atmosphere.height / radius;
@ -4873,11 +4879,11 @@ void renderAtmosphere(const Atmosphere& atmosphere,
for (int i = 0; i <= divisions; i++)
{
float theta = (float) i / (float) divisions * 2 * (float) PI;
Vec3f v = (float) cos(theta) * uAxis + (float) sin(theta) * vAxis;
Point3f base = atmCenter + v * atmRadius;
Vec3f toCenter = base - center;
Vector3f v = (float) cos(theta) * uAxis + (float) sin(theta) * vAxis;
Vector3f base = atmCenter + v * atmRadius;
Vector3f toCenter = base - center;
float cosSunAngle = (toCenter * sunDirection) / radius;
float cosSunAngle = toCenter.dot(sunDirection) / radius;
float brightness = 1.0f;
float botColor[3];
float topColor[3];
@ -4917,6 +4923,7 @@ void renderAtmosphere(const Atmosphere& atmosphere,
}
#if 0
static Vec3f ellipsoidTangent(const Vec3f& recipSemiAxes,
const Vec3f& w,
const Vec3f& e,
@ -4966,13 +4973,63 @@ static Vec3f ellipsoidTangent(const Vec3f& recipSemiAxes,
return e + v * t1;
}
#endif
template <typename T> static Matrix<T, 3, 1>
ellipsoidTangent(const Matrix<T, 3, 1>& recipSemiAxes,
const Matrix<T, 3, 1>& w,
const Matrix<T, 3, 1>& e,
const Matrix<T, 3, 1>& e_,
T ee)
{
// We want to find t such that -E(1-t) + Wt is the direction of a ray
// tangent to the ellipsoid. A tangent ray will intersect the ellipsoid
// at exactly one point. Finding the intersection between a ray and an
// ellipsoid ultimately requires using the quadratic formula, which has
// one solution when the discriminant (b^2 - 4ac) is zero. The code below
// computes the value of t that results in a discriminant of zero.
Matrix<T, 3, 1> w_ = w.cwise() * recipSemiAxes;//(w.x * recipSemiAxes.x, w.y * recipSemiAxes.y, w.z * recipSemiAxes.z);
T ww = w_.dot(w_);
T ew = w_.dot(e_);
// Before elimination of terms:
// double a = 4 * square(ee + ew) - 4 * (ee + 2 * ew + ww) * (ee - 1.0f);
// double b = -8 * ee * (ee + ew) - 4 * (-2 * (ee + ew) * (ee - 1.0f));
// double c = 4 * ee * ee - 4 * (ee * (ee - 1.0f));
// Simplify the below expression and eliminate the ee^2 terms; this
// prevents precision errors, as ee tends to be a very large value.
//T a = 4 * square(ee + ew) - 4 * (ee + 2 * ew + ww) * (ee - 1);
T a = 4 * (square(ew) - ee * ww + ee + 2 * ew + ww);
T b = -8 * (ee + ew);
T c = 4 * ee;
T t = 0;
T discriminant = b * b - 4 * a * c;
if (discriminant < 0)
t = (-b + (T) sqrt(-discriminant)) / (2 * a); // Bad!
else
t = (-b + (T) sqrt(discriminant)) / (2 * a);
// V is the direction vector. We now need the point of intersection,
// which we obtain by solving the quadratic equation for the ray-ellipse
// intersection. Since we already know that the discriminant is zero,
// the solution is just -b/2a
Matrix<T, 3, 1> v = -e * (1 - t) + w * t;
Matrix<T, 3, 1> v_ = v.cwise() * recipSemiAxes;
T a1 = v_.dot(v_);
T b1 = (T) 2 * v_.dot(e_);
T t1 = -b1 / (2 * a1);
return e + v * t1;
}
void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
Point3f center,
const Quatf& orientation,
Vec3f semiAxes,
const Vec3f& sunDirection,
const Vector3f& center,
const Quaternionf& orientation,
const Vector3f& semiAxes,
const Vector3f& sunDirection,
const LightingState& ls,
float pixSize,
bool lit)
@ -4986,22 +5043,23 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
// over one pixel.
float fade = clamp(pixSize - 2);
Mat3f rot = orientation.toMatrix3();
Mat3f irot = conjugate(orientation).toMatrix3();
Matrix3f rot = orientation.toRotationMatrix();
Matrix3f irot = orientation.conjugate().toRotationMatrix();
Point3f eyePos(0.0f, 0.0f, 0.0f);
float radius = max(semiAxes.x, max(semiAxes.y, semiAxes.z));
Vec3f eyeVec = center - eyePos;
eyeVec = eyeVec * irot;
double centerDist = eyeVec.length();
Vector3f eyePos = Vector3f::Zero();
float radius = semiAxes.maxCoeff();
Vector3f eyeVec = center - eyePos;
eyeVec = rot * eyeVec;
double centerDist = eyeVec.norm();
float height = atmosphere.height / radius;
Vec3f recipSemiAxes(1.0f / semiAxes.x, 1.0f / semiAxes.y, 1.0f / semiAxes.z);
Vector3f recipSemiAxes = semiAxes.cwise().inverse();
Vec3f recipAtmSemiAxes = recipSemiAxes / (1.0f + height);
Vector3f recipAtmSemiAxes = recipSemiAxes / (1.0f + height);
#if CELVEC
Mat3f A = Mat3f::scaling(recipAtmSemiAxes);
Mat3f A1 = Mat3f::scaling(recipSemiAxes);
#endif
// ellipDist is not the true distance from the surface unless the
// planet is spherical. Computing the true distance requires finding
// the roots of a sixth degree polynomial, and isn't actually what we
@ -5009,7 +5067,10 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
// multiplied by a uniform scale factor. The value that we do compute
// is the distance to the surface along a line from the eye position to
// the center of the ellipsoid.
#if CELVEC
float ellipDist = (float) sqrt((eyeVec * A1) * (eyeVec * A1)) - 1.0f;
#endif
float ellipDist = (eyeVec.cwise() * recipSemiAxes).norm() - 1.0f;
bool within = ellipDist < height;
// Adjust the tesselation of the sky dome/ring based on distance from the
@ -5035,16 +5096,16 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
horizonHeight *= max((float) pow(ellipDist / height, 0.33f), 0.001f);
}
Vec3f e = -eyeVec;
Vec3f e_(e.x * recipSemiAxes.x, e.y * recipSemiAxes.y, e.z * recipSemiAxes.z);
float ee = e_ * e_;
Vector3f e = -eyeVec;
Vector3f e_ = e.cwise() * recipSemiAxes;//(e.x * recipSemiAxes.x, e.y * recipSemiAxes.y, e.z * recipSemiAxes.z);
float ee = e_.dot(e_);
// Compute the cosine of the altitude of the sun. This is used to compute
// the degree of sunset/sunrise coloration.
float cosSunAltitude = 0.0f;
{
// Check for a sun either directly behind or in front of the viewer
float cosSunAngle = (float) ((sunDirection * e) / centerDist);
float cosSunAngle = (float) (sunDirection.dot(e) / centerDist);
if (cosSunAngle < -1.0f + 1.0e-6f)
{
cosSunAltitude = 0.0f;
@ -5055,36 +5116,34 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
}
else
{
Point3f tangentPoint = center +
ellipsoidTangent(recipSemiAxes,
(-sunDirection * irot) * (float) centerDist,
e, e_, ee) * rot;
Vec3f tangentDir = tangentPoint - eyePos;
tangentDir.normalize();
cosSunAltitude = sunDirection * tangentDir;
Vector3f v = (rot * -sunDirection) * (float) centerDist;
Vector3f tangentPoint = center +
irot * ellipsoidTangent(recipSemiAxes,
v,
e, e_, ee);
Vector3f tangentDir = (tangentPoint - eyePos).normalized();
cosSunAltitude = sunDirection.dot(tangentDir);
}
}
Vec3f normal = eyeVec;
Vector3f normal = eyeVec;
normal = normal / (float) centerDist;
Vec3f uAxis, vAxis;
if (abs(normal.x) < abs(normal.y) && abs(normal.x) < abs(normal.z))
Vector3f uAxis, vAxis;
if (abs(normal.x()) < abs(normal.y()) && abs(normal.x()) < abs(normal.z()))
{
uAxis = Vec3f(1, 0, 0) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitX().cross(normal);
}
else if (abs(eyeVec.y) < abs(normal.z))
else if (abs(eyeVec.y()) < abs(normal.z()))
{
uAxis = Vec3f(0, 1, 0) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitY().cross(normal);
}
else
{
uAxis = Vec3f(0, 0, 1) ^ normal;
uAxis.normalize();
uAxis = Vector3f::UnitZ().cross(normal);
}
vAxis = uAxis ^ normal;
uAxis.normalize();
vAxis = uAxis.cross(normal);
// Compute the contour of the ellipsoid
int i;
@ -5093,14 +5152,14 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
// We want rays with an origin at the eye point and tangent to the the
// ellipsoid.
float theta = (float) i / (float) nSlices * 2 * (float) PI;
Vec3f w = (float) cos(theta) * uAxis + (float) sin(theta) * vAxis;
Vector3f w = (float) cos(theta) * uAxis + (float) sin(theta) * vAxis;
w = w * (float) centerDist;
Vec3f toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee);
skyContour[i].v = toCenter * rot;
skyContour[i].centerDist = skyContour[i].v.length();
Vector3f toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee);
skyContour[i].v = irot * toCenter;
skyContour[i].centerDist = skyContour[i].v.norm();
skyContour[i].eyeDir = skyContour[i].v + (center - eyePos);
skyContour[i].eyeDist = skyContour[i].eyeDir.length();
skyContour[i].eyeDist = skyContour[i].eyeDir.norm();
skyContour[i].eyeDir.normalize();
float skyCapDist = (float) sqrt(square(skyContour[i].eyeDist) +
@ -5110,20 +5169,20 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
}
Vec3f botColor(atmosphere.lowerColor.red(),
atmosphere.lowerColor.green(),
atmosphere.lowerColor.blue());
Vec3f topColor(atmosphere.upperColor.red(),
atmosphere.upperColor.green(),
atmosphere.upperColor.blue());
Vec3f sunsetColor(atmosphere.sunsetColor.red(),
atmosphere.sunsetColor.green(),
atmosphere.sunsetColor.blue());
Vector3f botColor(atmosphere.lowerColor.red(),
atmosphere.lowerColor.green(),
atmosphere.lowerColor.blue());
Vector3f topColor(atmosphere.upperColor.red(),
atmosphere.upperColor.green(),
atmosphere.upperColor.blue());
Vector3f sunsetColor(atmosphere.sunsetColor.red(),
atmosphere.sunsetColor.green(),
atmosphere.sunsetColor.blue());
if (within)
{
Vec3f skyColor(atmosphere.skyColor.red(),
atmosphere.skyColor.green(),
atmosphere.skyColor.blue());
Vector3f skyColor(atmosphere.skyColor.red(),
atmosphere.skyColor.green(),
atmosphere.skyColor.blue());
if (ellipDist < 0.0f)
topColor = skyColor;
else
@ -5132,11 +5191,10 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
if (ls.nLights == 0 && lit)
{
Vec3f black(0.0f, 0.0f, 0.0f);
botColor = topColor = sunsetColor = black;
botColor = topColor = sunsetColor = Vector3f::Zero();
}
Vec3f zenith = (skyContour[0].v + skyContour[nSlices / 2].v);
Vector3f zenith = (skyContour[0].v + skyContour[nSlices / 2].v);
zenith.normalize();
zenith *= skyContour[0].centerDist * (1.0f + horizonHeight * 2.0f);
@ -5156,18 +5214,16 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
for (int j = 0; j < nSlices; j++)
{
Vec3f v;
Vector3f v;
if (i <= nHorizonRings)
v = skyContour[j].v * r;
else
v = (skyContour[j].v * (1.0f - u) + zenith * u) * r;
Point3f p = center + v;
Vector3f p = center + v;
Vec3f viewDir(p.x, p.y, p.z);
viewDir.normalize();
float cosSunAngle = viewDir * sunDirection;
float cosAltitude = viewDir * skyContour[j].eyeDir;
Vector3f viewDir = p.normalized();
float cosSunAngle = viewDir.dot(sunDirection);
float cosAltitude = viewDir.dot(skyContour[j].eyeDir);
float brightness = 1.0f;
float coloration = 0.0f;
if (lit)
@ -5179,7 +5235,7 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
coloration *= sunset;
}
cosSunAngle = (skyContour[j].v * sunDirection) / skyContour[j].centerDist;
cosSunAngle = skyContour[j].v.dot(sunDirection) / skyContour[j].centerDist;
if (cosSunAngle > -0.2f)
{
if (cosSunAngle < 0.3f)
@ -5193,31 +5249,12 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
}
}
vtx->x = p.x;
vtx->y = p.y;
vtx->z = p.z;
#if 0
// Better way of generating sky color gradients--based on
// altitude angle.
if (!within)
{
hh = (1.0f - cosAltitude) / (1.0f - skyContour[j].cosSkyCapAltitude);
}
else
{
float top = pow((ellipDist / height), 0.125f) * skyContour[j].cosSkyCapAltitude;
if (cosAltitude < top)
hh = 1.0f;
else
hh = (1.0f - cosAltitude) / (1.0f - top);
}
hh = sqrt(hh);
//hh = (float) pow(hh, 0.25f);
#endif
vtx->x = p.x();
vtx->y = p.y();
vtx->z = p.z();
atten = 1.0f - hh;
Vec3f color = (1.0f - hh) * botColor + hh * topColor;
Vector3f color = (1.0f - hh) * botColor + hh * topColor;
brightness *= minOpacity + (1.0f - minOpacity) * fade * atten;
if (coloration != 0.0f)
color = (1.0f - coloration) * color + coloration * sunsetColor;
@ -5225,9 +5262,9 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
#ifdef HDR_COMPRESS
brightness *= 0.5f;
#endif
Color(brightness * color.x,
brightness * color.y,
brightness * color.z,
Color(brightness * color.x(),
brightness * color.y(),
brightness * color.z(),
fade * (minOpacity + (1.0f - minOpacity)) * atten).get(vtx->color);
vtx++;
}
@ -5265,90 +5302,6 @@ void Renderer::renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
}
void renderCompass(Point3f center,
const Quatf& orientation,
Vec3f semiAxes,
float pixelSize)
{
Mat3f rot = orientation.toMatrix3();
Mat3f irot = conjugate(orientation).toMatrix3();
Point3f eyePos(0.0f, 0.0f, 0.0f);
float radius = max(semiAxes.x, max(semiAxes.y, semiAxes.z));
Vec3f eyeVec = center - eyePos;
eyeVec = eyeVec * irot;
double centerDist = eyeVec.length();
float height = 1.0f / radius;
Vec3f recipSemiAxes(1.0f / semiAxes.x,
1.0f / semiAxes.y,
1.0f / semiAxes.z);
Vec3f recipAtmSemiAxes = recipSemiAxes / (1.0f + height);
Mat3f A = Mat3f::scaling(recipAtmSemiAxes);
Mat3f A1 = Mat3f::scaling(recipSemiAxes);
const int nCompassPoints = 16;
Vec3f compassPoints[nCompassPoints];
// ellipDist is not the true distance from the surface unless the
// planet is spherical. Computing the true distance requires finding
// the roots of a sixth degree polynomial, and isn't actually what we
// want anyhow since the atmosphere region is just the planet ellipsoid
// multiplied by a uniform scale factor. The value that we do compute
// is the distance to the surface along a line from the eye position to
// the center of the ellipsoid.
/*float ellipDist = (float) sqrt((eyeVec * A1) * (eyeVec * A1)) - 1.0f; Unused*/
Vec3f e = -eyeVec;
Vec3f e_(e.x * recipSemiAxes.x, e.y * recipSemiAxes.y, e.z * recipSemiAxes.z);
float ee = e_ * e_;
Vec3f normal = eyeVec;
normal = normal / (float) centerDist;
Vec3f uAxis, vAxis;
Vec3f northPole(0.0f, 1.0f, 0.0f);
vAxis = normal ^ northPole;
vAxis.normalize();
uAxis = vAxis ^ normal;
// Compute the compass points
int i;
for (i = 0; i < nCompassPoints; i++)
{
// We want rays with an origin at the eye point and tangent to the the
// ellipsoid.
float theta = (float) i / (float) nCompassPoints * 2 * (float) PI;
Vec3f w = (float) cos(theta) * uAxis + (float) sin(theta) * vAxis;
w = w * (float) centerDist;
Vec3f toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee);
compassPoints[i] = toCenter * rot;
}
glColor(compassColor);
glBegin(GL_LINES);
glDisable(GL_LIGHTING);
for (i = 0; i < nCompassPoints; i++)
{
float distance = (center + compassPoints[i]).distanceFromOrigin();
float length = distance * pixelSize * 8.0f;
if (i % 4 == 0)
length *= 3.0f;
else if (i % 2 == 0)
length *= 2.0f;
glVertex(center + compassPoints[i]);
glVertex(center + compassPoints[i] * (1.0f + length));
}
glEnd();
}
static void setupNightTextureCombine()
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
@ -6681,22 +6634,6 @@ renderEclipseShadows(Geometry* geometry,
{
EclipseShadow shadow = *iter;
#ifdef DEBUG_ECLIPSE_SHADOWS
// Eclipse debugging: render the central axis of the eclipse
// shadow volume.
glDisable(GL_TEXTURE_2D);
glColor4f(1, 0, 0, 1);
Point3f blorp = shadow.origin * planetMat;
Vec3f blah = shadow.direction * planetMat;
blorp.x /= planetRadius; blorp.y /= planetRadius; blorp.z /= planetRadius;
float foo = blorp.distanceFromOrigin();
glBegin(GL_LINES);
glVertex(blorp);
glVertex(blorp + foo * blah);
glEnd();
glEnable(GL_TEXTURE_2D);
#endif
// Determine which eclipse shadow texture to use. This is only
// a very rough approximation to reality. Since there are an
// infinite number of possible eclipse volumes, what we should be
@ -7731,10 +7668,10 @@ void Renderer::renderObject(const Vector3f& pos,
glRotate(cameraOrientation);
renderEllipsoidAtmosphere(*atmosphere,
ptFromEigen(pos),
fromEigen(obj.orientation),
fromEigen(scaleFactors),
fromEigen(ri.sunDir_eye),
pos,
obj.orientation,
scaleFactors,
ri.sunDir_eye,
ls,
thicknessInPixels,
lit);
@ -9537,7 +9474,7 @@ void StarRenderer::process(const Star& star, float distance, float appMag)
}
else
{
starVertexBuffer->addStar(fromEigen(relPos),
starVertexBuffer->addStar(relPos,
Color(starColor, alpha),
pointSize * renderDistance);
}
@ -9915,7 +9852,7 @@ void Renderer::renderStars(const StarDatabase& starDB,
glareParticles.clear();
starVertexBuffer->setBillboardOrientation(observer.getOrientationf());
starVertexBuffer->setBillboardOrientation(toEigen(observer.getOrientationf()));
glEnable(GL_TEXTURE_2D);
@ -10062,12 +9999,15 @@ class DSORenderer : public ObjectRenderer<DeepSkyObject*, double>
int wHeight;
double avgAbsMag;
unsigned int dsosProcessed;
};
DSORenderer::DSORenderer() :
ObjectRenderer<DeepSkyObject*, double>(DSO_OCTREE_ROOT_SIZE),
frustum(degToRad(45.0f), 1.0f, 1.0f)
frustum(degToRad(45.0f), 1.0f, 1.0f),
dsosProcessed(0)
{
}
@ -10079,7 +10019,7 @@ void DSORenderer::process(DeepSkyObject* const & dso,
if (distanceToDSO > distanceLimit)
return;
Vector3d dsoPos = toEigen(dso->getPosition());
Vector3d dsoPos = dso->getPosition();
Vector3f relPos = (dsoPos - obsPos).cast<float>();
Vector3f center = orientationMatrix.transpose() * relPos;
@ -10098,146 +10038,152 @@ void DSORenderer::process(DeepSkyObject* const & dso,
// each object (even if it's not visible) would be sent to the OpenGL
// pipeline.
if ((renderFlags & dso->getRenderMask()) && dso->isVisible())
if (dso->isVisible())
{
double dsoRadius = dso->getBoundingSphereRadius();
double dsoRadius = dso->getBoundingSphereRadius();
bool inFrustum = frustum.testSphere(center, (float) dsoRadius) != Frustum::Outside;
if (frustum.testSphere(center, (float) dsoRadius) != Frustum::Outside)
if (inFrustum)
{
// Input: display looks satisfactory for 0.2 < brightness < O(1.0)
// Ansatz: brightness = a - b * appMag(distanceToDSO), emulating eye sensitivity...
// determine a,b such that
// a - b * absMag = absMag / avgAbsMag ~ 1; a - b * faintestMag = 0.2.
// The 2nd eq. guarantees that the faintest galaxies are still visible.
if(!strcmp(dso->getObjTypeName(),"globular"))
avgAbsMag = -6.86; // average over 150 globulars in globulars.dsc.
else if (!strcmp(dso->getObjTypeName(),"galaxy"))
avgAbsMag = -19.04; // average over 10937 galaxies in galaxies.dsc.
float r = absMag / (float) avgAbsMag;
float brightness = r - (r - 0.2f) * (absMag - appMag) / (absMag - faintestMag);
// obviously, brightness(appMag = absMag) = r and
// brightness(appMag = faintestMag) = 0.2, as desired.
if ((renderFlags & dso->getRenderMask()))
{
dsosProcessed++;
brightness = 2.3f * brightness * (faintestMag - 4.75f) / renderer->getFaintestAM45deg();
// Input: display looks satisfactory for 0.2 < brightness < O(1.0)
// Ansatz: brightness = a - b * appMag(distanceToDSO), emulating eye sensitivity...
// determine a,b such that
// a - b * absMag = absMag / avgAbsMag ~ 1; a - b * faintestMag = 0.2.
// The 2nd eq. guarantees that the faintest galaxies are still visible.
if(!strcmp(dso->getObjTypeName(),"globular"))
avgAbsMag = -6.86; // average over 150 globulars in globulars.dsc.
else if (!strcmp(dso->getObjTypeName(),"galaxy"))
avgAbsMag = -19.04; // average over 10937 galaxies in galaxies.dsc.
float r = absMag / (float) avgAbsMag;
float brightness = r - (r - 0.2f) * (absMag - appMag) / (absMag - faintestMag);
// obviously, brightness(appMag = absMag) = r and
// brightness(appMag = faintestMag) = 0.2, as desired.
brightness = 2.3f * brightness * (faintestMag - 4.75f) / renderer->getFaintestAM45deg();
#ifdef USE_HDR
brightness *= exposure;
brightness *= exposure;
#endif
if (brightness < 0)
brightness = 0;
if (dsoRadius < 1000.0)
{
// Small objects may be prone to clipping; give them special
// handling. We don't want to always set the projection
// matrix, since that could be expensive with large galaxy
// catalogs.
float nearZ = (float) (distanceToDSO / 2);
float farZ = (float) (distanceToDSO + dsoRadius * 2 * CubeCornerToCenterDistance);
if (nearZ < dsoRadius * 0.001)
if (brightness < 0)
brightness = 0;
if (dsoRadius < 1000.0)
{
nearZ = (float) (dsoRadius * 0.001);
farZ = nearZ * 10000.0f;
// Small objects may be prone to clipping; give them special
// handling. We don't want to always set the projection
// matrix, since that could be expensive with large galaxy
// catalogs.
float nearZ = (float) (distanceToDSO / 2);
float farZ = (float) (distanceToDSO + dsoRadius * 2 * CubeCornerToCenterDistance);
if (nearZ < dsoRadius * 0.001)
{
nearZ = (float) (dsoRadius * 0.001);
farZ = nearZ * 10000.0f;
}
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(fov,
(float) wWidth / (float) wHeight,
nearZ,
farZ);
glMatrixMode(GL_MODELVIEW);
}
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(fov,
(float) wWidth / (float) wHeight,
nearZ,
farZ);
glMatrixMode(GL_MODELVIEW);
}
glTranslate(relPos);
glPushMatrix();
glTranslate(relPos);
dso->render(*context,
fromEigen(relPos),
observer->getOrientationf(),
(float) brightness,
pixelSize);
glPopMatrix();
#if 1
if (dsoRadius < 1000.0)
{
glMatrixMode(GL_PROJECTION);
dso->render(*context,
fromEigen(relPos),
observer->getOrientationf(),
(float) brightness,
pixelSize);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
#endif
} // frustum test
} // renderFlags check
// Only render those labels that are in front of the camera:
// Place labels for DSOs brighter than the specified label threshold brightness
//
unsigned int labelMask = dso->getLabelMask();
#if 1
if (dsoRadius < 1000.0)
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
#endif
} // renderFlags check
if ((labelMask & labelMode) && relPos.dot(viewNormal) > 0 && dso->isVisible())
{
Color labelColor;
float appMagEff = 6.0f;
float step = 6.0f;
float symbolSize = 0.0f;
MarkerRepresentation* rep = NULL;
// Only render those labels that are in front of the camera:
// Place labels for DSOs brighter than the specified label threshold brightness
//
unsigned int labelMask = dso->getLabelMask();
// Use magnitude based fading for galaxies, and distance based
// fading for nebulae and open clusters.
switch (labelMask)
{
case Renderer::NebulaLabels:
rep = &renderer->nebulaRep;
labelColor = Renderer::NebulaLabelColor;
appMagEff = astro::absToAppMag(-7.5f, (float) distanceToDSO);
symbolSize = (float) (dso->getRadius() / distanceToDSO) / pixelSize;
step = 6.0f;
break;
case Renderer::OpenClusterLabels:
rep = &renderer->openClusterRep;
labelColor = Renderer::OpenClusterLabelColor;
appMagEff = astro::absToAppMag(-6.0f, (float) distanceToDSO);
symbolSize = (float) (dso->getRadius() / distanceToDSO) / pixelSize;
step = 4.0f;
break;
case Renderer::GalaxyLabels:
labelColor = Renderer::GalaxyLabelColor;
appMagEff = appMag;
step = 6.0f;
break;
case Renderer::GlobularLabels:
labelColor = Renderer::GlobularLabelColor;
appMagEff = appMag;
step = 3.0f;
break;
default:
// Unrecognized object class
labelColor = Color::White;
appMagEff = appMag;
step = 6.0f;
break;
}
if ((labelMask & labelMode))
{
Color labelColor;
float appMagEff = 6.0f;
float step = 6.0f;
float symbolSize = 0.0f;
MarkerRepresentation* rep = NULL;
if (appMagEff < labelThresholdMag)
{
// introduce distance dependent label transparency.
float distr = step * (labelThresholdMag - appMagEff) / labelThresholdMag;
if (distr > 1.0f)
distr = 1.0f;
// Use magnitude based fading for galaxies, and distance based
// fading for nebulae and open clusters.
switch (labelMask)
{
case Renderer::NebulaLabels:
rep = &renderer->nebulaRep;
labelColor = Renderer::NebulaLabelColor;
appMagEff = astro::absToAppMag(-7.5f, (float) distanceToDSO);
symbolSize = (float) (dso->getRadius() / distanceToDSO) / pixelSize;
step = 6.0f;
break;
case Renderer::OpenClusterLabels:
rep = &renderer->openClusterRep;
labelColor = Renderer::OpenClusterLabelColor;
appMagEff = astro::absToAppMag(-6.0f, (float) distanceToDSO);
symbolSize = (float) (dso->getRadius() / distanceToDSO) / pixelSize;
step = 4.0f;
break;
case Renderer::GalaxyLabels:
labelColor = Renderer::GalaxyLabelColor;
appMagEff = appMag;
step = 6.0f;
break;
case Renderer::GlobularLabels:
labelColor = Renderer::GlobularLabelColor;
appMagEff = appMag;
step = 3.0f;
break;
default:
// Unrecognized object class
labelColor = Color::White;
appMagEff = appMag;
step = 6.0f;
break;
}
renderer->addBackgroundAnnotation(rep,
dsoDB->getDSOName(dso, true),
Color(labelColor, distr * labelColor.alpha()),
ptFromEigen(relPos),
Renderer::AlignLeft, Renderer::VerticalAlignCenter, symbolSize);
}
}
if (appMagEff < labelThresholdMag)
{
// introduce distance dependent label transparency.
float distr = step * (labelThresholdMag - appMagEff) / labelThresholdMag;
if (distr > 1.0f)
distr = 1.0f;
renderer->addBackgroundAnnotation(rep,
dsoDB->getDSOName(dso, true),
Color(labelColor, distr * labelColor.alpha()),
ptFromEigen(relPos),
Renderer::AlignLeft, Renderer::VerticalAlignCenter, symbolSize);
}
} // labels enabled
} // in frustum
} // isVisible()
}
@ -10304,6 +10250,8 @@ void Renderer::renderDeepSkyObjects(const Universe& universe,
(float) windowWidth / (float) windowHeight,
2 * faintestMagNight);
// clog << "DSOs processed: " << dsoRenderer.dsosProcessed << endl;
if ((renderFlags & ShowSmoothLines) != 0)
disableSmoothLines();
}

View File

@ -377,8 +377,8 @@ class Renderer
struct SkyContourPoint
{
Vec3f v;
Vec3f eyeDir;
Eigen::Vector3f v;
Eigen::Vector3f eyeDir;
float centerDist;
float eyeDist;
float cosSkyCapAltitude;
@ -517,10 +517,10 @@ class Renderer
bool emissive);
void renderEllipsoidAtmosphere(const Atmosphere& atmosphere,
Point3f center,
const Quatf& orientation,
Vec3f semiAxes,
const Vec3f& sunDirection,
const Eigen::Vector3f& center,
const Eigen::Quaternionf& orientation,
const Eigen::Vector3f& semiAxes,
const Eigen::Vector3f& sunDirection,
const LightingState& ls,
float fade,
bool lit);

View File

@ -54,7 +54,7 @@ UniversalCoord Selection::getPosition(double t) const
case Type_DeepSky:
{
Vector3d p = toEigen(deepsky()->getPosition());
Vector3d p = deepsky()->getPosition();
// NOTE: cast to single precision is only present to maintain compatibility with
// Celestia 1.6.0.
return UniversalCoord::CreateLy(p.cast<float>());

View File

@ -757,14 +757,14 @@ void DSOPicker::process(DeepSkyObject* const & dso, double, float)
if (!(dso->getRenderMask() & renderFlags) || !dso->isVisible() || !dso->isClickable())
return;
Vector3d relativeDSOPos = toEigen(dso->getPosition()) - pickOrigin;
Vector3d relativeDSOPos = dso->getPosition() - pickOrigin;
Vector3d dsoDir = relativeDSOPos;
double distance2 = 0.0;
if (testIntersection(Ray3d(Vector3d::Zero(), pickDir),
Sphered(relativeDSOPos, (double) dso->getRadius()), distance2))
{
Vector3d dsoPos = toEigen(dso->getPosition());
Vector3d dsoPos = dso->getPosition();
dsoDir = dsoPos * 1.0e-6 - pickOrigin;
}
dsoDir.normalize();
@ -830,7 +830,7 @@ void CloseDSOPicker::process(DeepSkyObject* const & dso,
if (dso->pick(Ray3d(pickOrigin, pickDir), distanceToPicker, cosAngleToBoundCenter))
{
// Don't select the object the observer is currently in:
if ((pickOrigin - toEigen(dso->getPosition())).norm() > dso->getRadius() &&
if ((pickOrigin - dso->getPosition()).norm() > dso->getRadius() &&
cosAngleToBoundCenter > largestCosAngle)
{
closestDSO = dso;

View File

@ -504,7 +504,7 @@ void showSelectionInfo(const Selection& sel)
float angle = 0.0f;
if (sel.deepsky() != NULL)
sel.deepsky()->getOrientation().getAxisAngle(axis, angle);
fromEigen(sel.deepsky()->getOrientation()).getAxisAngle(axis, angle);
else if (sel.body() != NULL)
fromEigen(sel.body()->getGeometryOrientation()).getAxisAngle(axis, angle);
@ -907,7 +907,7 @@ void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
Selection sel = sim->getSelection();
Quatf q(1);
if (sel.getType() == Selection::Type_DeepSky)
q = sel.deepsky()->getOrientation();
q = fromEigen(sel.deepsky()->getOrientation());
else if (sel.getType() == Selection::Type_Body)
q = fromEigen(sel.body()->getGeometryOrientation());
@ -915,7 +915,7 @@ void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
q.xrotate(dy / height);
if (sel.getType() == Selection::Type_DeepSky)
sel.deepsky()->setOrientation(q);
sel.deepsky()->setOrientation(toEigen(q));
else if (sel.getType() == Selection::Type_Body)
sel.body()->setGeometryOrientation(toEigen(q));
}
@ -934,8 +934,8 @@ void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
Quatf r;
r.setAxisAngle(axis, dx / width);
Quatf q = sel.deepsky()->getOrientation();
sel.deepsky()->setOrientation(r * q);
Quatf q = fromEigen(sel.deepsky()->getOrientation());
sel.deepsky()->setOrientation(toEigen(r * q));
}
}
else if (checkMask(modifiers, LeftButton | RightButton) ||