Implemented phase lock and sync follow modes for stars.

ver1_5_1
Chris Laurel 2004-11-09 07:18:46 +00:00
parent 91caabf6df
commit 252182a102
4 changed files with 77 additions and 60 deletions

View File

@ -27,7 +27,7 @@ RigidTransform FrameOfReference::toUniversal(const RigidTransform& xform,
rotation = refObject.body()->getEclipticalToGeographic(t);
break;
case Selection::Type_Star:
rotation = Quatd(1, 0, 0, 0);
rotation = refObject.star()->getRotationElements().eclipticalToPlanetographic(t);
break;
case Selection::Type_Location:
if (refObject.location()->getParentBody() != NULL)
@ -44,22 +44,30 @@ RigidTransform FrameOfReference::toUniversal(const RigidTransform& xform,
else if (coordSys == astro::PhaseLock)
{
Mat3d m;
Vec3d lookDir = refObject.getPosition(t) - targetObject.getPosition(t);
lookDir.normalize();
switch (refObject.getType())
{
case Selection::Type_Body:
{
Body* body = refObject.body();
Vec3d lookDir = refObject.getPosition(t) -
targetObject.getPosition(t);
Vec3d axisDir = Vec3d(0, 1, 0) * body->getEclipticalToEquatorial(t).toMatrix3();
lookDir.normalize();
Vec3d v = axisDir ^ lookDir;
v.normalize();
Vec3d u = lookDir ^ v;
m = Mat3d(v, u, lookDir);
}
break;
case Selection::Type_Star:
{
Star* star = refObject.star();
Vec3d axisDir = Vec3d(0, 1, 0) * star->getRotationElements().eclipticalToEquatorial(t).toMatrix3();
Vec3d v = axisDir ^ lookDir;
v.normalize();
Vec3d u = lookDir ^ v;
m = Mat3d(v, u, lookDir);
}
default:
break;
}
@ -121,7 +129,7 @@ RigidTransform FrameOfReference::fromUniversal(const RigidTransform& xform,
rotation = refObject.body()->getEclipticalToGeographic(t);
break;
case Selection::Type_Star:
rotation = Quatd(1, 0, 0, 0);
rotation = refObject.star()->getRotationElements().eclipticalToPlanetographic(t);
break;
case Selection::Type_Location:
if (refObject.location()->getParentBody() != NULL)
@ -138,16 +146,15 @@ RigidTransform FrameOfReference::fromUniversal(const RigidTransform& xform,
else if (coordSys == astro::PhaseLock)
{
Mat3d m;
Vec3d lookDir = refObject.getPosition(t) - targetObject.getPosition(t);
lookDir.normalize();
switch (refObject.getType())
{
case Selection::Type_Body:
{
Body* body = refObject.body();
Vec3d lookDir = refObject.getPosition(t) -
targetObject.getPosition(t);
Vec3d axisDir = Vec3d(0, 1, 0) * body->getEclipticalToEquatorial(t).toMatrix3();
lookDir.normalize();
Vec3d v = axisDir ^ lookDir;
v.normalize();
Vec3d u = lookDir ^ v;
@ -155,6 +162,16 @@ RigidTransform FrameOfReference::fromUniversal(const RigidTransform& xform,
}
break;
case Selection::Type_Star:
{
Star* star = refObject.star();
Vec3d axisDir = Vec3d(0, 1, 0) * star->getRotationElements().eclipticalToEquatorial(t).toMatrix3();
Vec3d v = axisDir ^ lookDir;
v.normalize();
Vec3d u = lookDir ^ v;
m = Mat3d(v, u, lookDir);
}
default:
break;
}

View File

@ -1251,12 +1251,14 @@ void Observer::follow(const Selection& selection)
void Observer::geosynchronousFollow(const Selection& selection)
{
if (selection.body() != NULL ||
selection.location() != NULL)
selection.location() != NULL ||
selection.star() != NULL)
{
setFrame(FrameOfReference(astro::Geographic, selection));
}
}
void Observer::phaseLock(const Selection& selection)
{
if (frame.refObject.body() != NULL)
@ -1271,6 +1273,13 @@ void Observer::phaseLock(const Selection& selection)
setFrame(FrameOfReference(astro::PhaseLock, frame.refObject, selection));
}
}
else if (frame.refObject.star() != NULL)
{
if (selection != frame.refObject)
{
setFrame(FrameOfReference(astro::PhaseLock, frame.refObject, selection));
}
}
}
void Observer::chase(const Selection& selection)
@ -1279,6 +1288,10 @@ void Observer::chase(const Selection& selection)
{
setFrame(FrameOfReference(astro::Chase, selection));
}
else if (selection.star() != NULL)
{
setFrame(FrameOfReference(astro::Chase, selection));
}
}

View File

@ -4504,52 +4504,6 @@ renderEclipseShadows_Shaders(Model* model,
ri.pixWidth, NULL);
vproc->disable();
#if 0
float R2 = 0.25f;
float umbra = shadow.umbraRadius / shadow.penumbraRadius;
umbra = umbra * umbra;
if (umbra < 0.0001f)
umbra = 0.0001f;
else if (umbra > 0.99f)
umbra = 0.99f;
float umbraRadius = R2 * umbra;
float penumbraRadius = R2;
float shadowBias = 1.0f / (1.0f - penumbraRadius / umbraRadius);
float shadowScale = -shadowBias / umbraRadius;
fproc->parameter(fp::ShadowParams0,
shadowScale, shadowBias, 0.0f, 0.0f);
fproc->parameter(fp::AmbientColor, ri.ambientColor * ri.color);
// Compute the transformation to use for generating texture
// coordinates from the object vertices.
Point3f origin = shadow.origin * planetMat;
Vec3f dir = shadow.direction * planetMat;
float scale = planetRadius / shadow.penumbraRadius;
Vec3f axis = Vec3f(0, 1, 0) ^ dir;
float angle = (float) acos(Vec3f(0, 1, 0) * dir);
axis.normalize();
Mat4f mat = Mat4f::rotation(axis, -angle);
Vec3f sAxis = Vec3f(0.5f * scale, 0, 0) * mat;
Vec3f tAxis = Vec3f(0, 0, 0.5f * scale) * mat;
float sPlane[4] = { 0, 0, 0, 0 };
float tPlane[4] = { 0, 0, 0, 0 };
sPlane[0] = sAxis.x; sPlane[1] = sAxis.y; sPlane[2] = sAxis.z;
tPlane[0] = tAxis.x; tPlane[1] = tAxis.y; tPlane[2] = tAxis.z;
sPlane[3] = (Point3f(0, 0, 0) - origin) * sAxis / planetRadius + 0.5f;
tPlane[3] = (Point3f(0, 0, 0) - origin) * tAxis / planetRadius + 0.5f;
renderShadowedModelVertexShader(ri, viewFrustum,
sPlane, tPlane,
dir,
context);
}
#endif
fproc->disable();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
@ -5654,11 +5608,7 @@ void Renderer::renderStar(const Star& star,
rp.atmosphere = NULL;
const RotationElements& re = star.getRotationElements();
double ascendingNode = (double) re.ascendingNode +
re.precessionRate * (now - astro::J2000);
Quatd q =
Quatd::xrotation(-re.obliquity) *
Quatd::yrotation(-ascendingNode);
Quatd q = re.eclipticalToEquatorial(now);
double rotation = 0.0;
// Watch out for the precision limits of floats when computing

View File

@ -10,6 +10,7 @@
#ifndef _CELENGINE_ROTATION_H_
#define _CELENGINE_ROTATION_H_
#include <celmath/quaternion.h>
#include <celengine/astro.h>
@ -18,6 +19,10 @@ class RotationElements
public:
inline RotationElements();
inline Quatd eclipticalToEquatorial(double t) const;
inline Quatd eclipticalToPlanetographic(double t) const;
inline Quatd equatorialToPlanetographic(double t) const;
float period; // sidereal rotation period
float offset; // rotation at epoch
double epoch;
@ -48,4 +53,36 @@ inline bool operator==(const RotationElements& re0, const RotationElements& re1)
re0.precessionRate == re1.precessionRate);
}
Quatd RotationElements::eclipticalToEquatorial(double t) const
{
double Omega = (double) ascendingNode + precessionRate * (t - astro::J2000);
return (Quatd::xrotation(-obliquity) * Quatd::yrotation(-Omega));
}
Quatd RotationElements::eclipticalToPlanetographic(double t) const
{
return equatorialToPlanetographic(t) * eclipticalToEquatorial(t);
}
Quatd RotationElements::equatorialToPlanetographic(double t) const
{
double rotations = (t - epoch) / (double) period;
double wholeRotations = floor(rotations);
double remainder = rotations - wholeRotations;
// Add an extra half rotation because of the convention in all
// planet texture maps where zero deg long. is in the middle of
// the texture.
remainder += 0.5;
Quatd q(1);
q.yrotate(-remainder * 2 * PI - offset);
return q;
}
#endif // _CELENGINE_ROTATION_H_