Meteor.cpp   Meteor.cpp 
skipping to change at line 31 skipping to change at line 31
// Could use a simple ablation physics model in the future // Could use a simple ablation physics model in the future
/* /*
NOTE: Here the radiant is always along the ecliptic at the apex of the Eart h's way. NOTE: Here the radiant is always along the ecliptic at the apex of the Eart h's way.
In reality, individual meteor streams have varying velocity vectors and the refore radiants In reality, individual meteor streams have varying velocity vectors and the refore radiants
which are generally not at the apex of the Earth's way, such as the Perseid s shower. which are generally not at the apex of the Earth's way, such as the Perseid s shower.
*/ */
// Improved realism and efficiency 2004-12 // Improved realism and efficiency 2004-12
#include <QtOpenGL>
#include <cstdlib> #include <cstdlib>
#include "Meteor.hpp" #include "Meteor.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "renderer/StelRenderer.hpp"
#include "StelToneReproducer.hpp" #include "StelToneReproducer.hpp"
#include "StelMovementMgr.hpp" #include "StelMovementMgr.hpp"
#include "StelPainter.hpp"
Meteor::Meteor(const StelCore* core, double v) Meteor::Meteor(const StelCore* core, double v)
: vertexBuffer(NULL)
{ {
const StelToneReproducer* eye = core->getToneReproducer(); const StelToneReproducer* eye = core->getToneReproducer();
// velocity = 11+(double)rand()/((double)RAND_MAX+1)*v; // abs range 11 // velocity = 11+(double)rand()/((double)RAND_MAX+1)*v; // abs ran
-72 km/s ge 11-72 km/s
velocity=v; velocity=v;
maxMag = 1; maxMag = 1;
// determine meteor model view matrix (want z in dir of travel of earth, // determine meteor model view matrix (want z in dir of travel of ea
z=0 at center of earth) rth, z=0 at center of earth)
// meteor life is so short, no need to recalculate // meteor life is so short, no need to recalculate
double equ_rotation; // rotation needed to align with path of earth double equ_rotation; // rotation needed to align with path of earth
Vec3d sun_dir = core->heliocentricEclipticToEquinoxEqu( Vec3d(0,0,0) ); Vec3d sun_dir = core->heliocentricEclipticToEquinoxEqu( Vec3d(0,0,0)
);
Mat4d tmat = Mat4d::xrotation(-23.45f*M_PI/180.f); // ecliptical tilt
sun_dir.transfo4d(tmat); // convert to ecliptical coordinates Mat4d tmat = Mat4d::xrotation(-23.45f*M_PI/180.f); // ecliptical ti
sun_dir.normalize(); lt
equ_rotation = acos( sun_dir.dot( Vec3d(1,0,0) ) ); sun_dir.transfo4d(tmat); // convert to ecliptical coordinates
if( sun_dir[1] < 0 ) equ_rotation = 2*M_PI - equ_rotation; sun_dir.normalize();
equ_rotation = acos( sun_dir.dot( Vec3d(1,0,0) ) );
equ_rotation -= M_PI_2; if( sun_dir[1] < 0 ) equ_rotation = 2*M_PI - equ_rotation;
mmat = Mat4d::xrotation(23.45f*M_PI/180.f) * Mat4d::zrotation(equ_rotatio equ_rotation -= M_PI_2;
n) * Mat4d::yrotation(M_PI_2);
mmat = Mat4d::xrotation(23.45f*M_PI/180.f) * Mat4d::zrotation(equ_ro
// select random trajectory using polar coordinates in XY plane, centered tation) * Mat4d::yrotation(M_PI_2);
on observer
xydistance = (double)rand()/((double)RAND_MAX+1)*(VISIBLE_RADIUS); // select random trajectory using polar coordinates in XY plane, cen
double angle = (double)rand()/((double)RAND_MAX+1)*2*M_PI; tered on observer
xydistance = (double)rand()/((double)RAND_MAX+1)*(VISIBLE_RADIUS);
// find observer position in meteor coordinate system double angle = (double)rand()/((double)RAND_MAX+1)*2*M_PI;
obs = core->altAzToEquinoxEqu(Vec3d(0,0,EARTH_RADIUS));
obs.transfo4d(mmat.transpose()); // find observer position in meteor coordinate system
obs = core->altAzToEquinoxEqu(Vec3d(0,0,EARTH_RADIUS));
// set meteor start x,y obs.transfo4d(mmat.transpose());
posInternal[0] = posTrain[0] = position[0] = xydistance*cos(angle) +obs[0
]; // set meteor start x,y
posInternal[1] = posTrain[1] = position[1] = xydistance*sin(angle) +obs[1 posInternal[0] = posTrain[0] = position[0] = xydistance*cos(angle) +
]; obs[0];
posInternal[1] = posTrain[1] = position[1] = xydistance*sin(angle) +
// determine life of meteor (start and end z value based on atmosphere bu obs[1];
rn altitudes)
// determine life of meteor (start and end z value based on atmosphe
// D is distance from center of earth re burn altitudes)
double D = sqrt( position[0]*position[0] + position[1]*position[1] );
// D is distance from center of earth
if( D > EARTH_RADIUS+HIGH_ALTITUDE ) { double D = sqrt( position[0]*position[0] + position[1]*position[1] )
// won't be visible ;
alive = 0;
return; if( D > EARTH_RADIUS+HIGH_ALTITUDE )
} {
// won't be visible
startH = sqrt( pow(EARTH_RADIUS+HIGH_ALTITUDE,2) - D*D); alive = 0;
return;
// determine end of burn point, and nearest point to observer for distanc }
e mag calculation
// mag should be max at nearest point still burning startH = sqrt( pow(EARTH_RADIUS+HIGH_ALTITUDE,2) - D*D);
if( D > EARTH_RADIUS+LOW_ALTITUDE ) {
endH = -startH; // earth grazing // determine end of burn point, and nearest point to observer for di
minDist = xydistance; stance mag calculation
} else { // mag should be max at nearest point still burning
endH = sqrt( pow(EARTH_RADIUS+LOW_ALTITUDE,2) - D*D); if( D > EARTH_RADIUS+LOW_ALTITUDE )
minDist = sqrt( xydistance*xydistance + pow( endH - obs[2], 2) ); {
} endH = -startH; // earth grazing
minDist = xydistance;
if(minDist > VISIBLE_RADIUS ) { }
// on average, not visible (although if were zoomed ...) else
alive = 0; {
return; endH = sqrt( pow(EARTH_RADIUS+LOW_ALTITUDE,2) - D*D);
} minDist = sqrt( xydistance*xydistance + pow( endH - obs[2],
2) );
/* experiment }
// limit lifetime to 0.5-3.0 sec
double tmp_h = startH - velocity * (0.5 + (double)rand()/((double)RAND_MA if(minDist > VISIBLE_RADIUS )
X+1) * 2.5); {
if( tmp_h > endH ) { // on average, not visible (although if were zoomed ...)
endH = tmp_h; alive = 0;
} return;
*/ }
posTrain[2] = position[2] = startH; /* experiment
// limit lifetime to 0.5-3.0 sec
// qDebug("New meteor: %f %f s:%f e:%f v:%f\n", position[0], position[1] double tmp_h = startH - velocity * (0.5 + (double)rand()/((double)RA
, startH, endH, velocity); ND_MAX+1) * 2.5);
if( tmp_h > endH ) {
alive = 1; endH = tmp_h;
train=0; }
*/
// Determine drawing color given magnitude and eye
// (won't be visible during daylight) posTrain[2] = position[2] = startH;
// *** color varies somewhat based on velocity, plus atmosphere reddening // qDebug("New meteor: %f %f s:%f e:%f v:%f\n", position[0], positi
on[1], startH, endH, velocity);
// determine intensity
float Mag1 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3; alive = 1;
float Mag2 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3; train = 1;
float Mag = (Mag1 + Mag2)/2.0f;
// Determine drawing color given magnitude and eye
mag = (5. + Mag) / 256.0; // (won't be visible during daylight)
if (mag>250) mag = mag - 256;
// *** color varies somewhat based on velocity, plus atmosphere redd
float term1 = std::exp(-0.92103f*(mag + 12.12331f)) * 108064.73f; ening
float cmag=1.f; // determine intensity
float rmag; float Mag1 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3;
float Mag2 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3;
// Compute the equivalent star luminance for a 5 arc min circle and conve float Mag = (Mag1 + Mag2)/2.0f;
rt it
// in function of the eye adaptation mag = (5. + Mag) / 256.0;
rmag = eye->adaptLuminanceScaled(term1); if (mag>250) mag = mag - 256;
rmag = rmag/powf(core->getMovementMgr()->getCurrentFov(),0.85f)*500.f;
float term1 = std::exp(-0.92103f*(mag + 12.12331f)) * 108064.73f;
// if size of star is too small (blink) we put its size to 1.2 --> no mor
e blink float cmag=1.f;
// And we compensate the difference of brighteness with cmag float rmag;
if (rmag<1.2f) {
cmag=rmag*rmag/1.44f; // Compute the equivalent star luminance for a 5 arc min circle and
} convert it
// in function of the eye adaptation
mag = cmag; // assumes white rmag = eye->adaptLuminanceScaled(term1);
rmag = rmag/powf(core->getMovementMgr()->getCurrentFov(),0.85f)*500.
// most visible meteors are under about 180km distant f;
// scale max mag down if outside this range
float scale = 1; // if size of star is too small (blink) we put its size to 1.2 --> n
if(minDist!=0) scale = 180*180/(minDist*minDist); o more blink
if( scale < 1 ) mag *= scale; // And we compensate the difference of brighteness with cmag
if (rmag<1.2f)
{
cmag=rmag*rmag/1.44f;
}
mag = cmag; // assumes white
// most visible meteors are under about 180km distant
// scale max mag down if outside this range
float scale = 1;
if(minDist!=0) scale = 180*180/(minDist*minDist);
if( scale < 1 ) mag *= scale;
} }
Meteor::~Meteor() Meteor::~Meteor()
{ {
if(NULL != vertexBuffer)
{
delete vertexBuffer;
}
} }
// returns true if alive // returns true if alive
bool Meteor::update(double deltaTime) bool Meteor::update(double deltaTime)
{ {
if(!alive) return(0); if(!alive) return(0);
if( position[2] < endH ) {
// burning has stopped so magnitude fades out
// assume linear fade out
mag -= maxMag * deltaTime/500.0f; if(position[2] < endH)
if( mag < 0 ) alive=0; // no longer visible {
// burning has stopped so magnitude fades out
// assume linear fade out
} mag -= maxMag * deltaTime/500.0f;
if(mag < 0) alive=0; // no longer visible
}
// *** would need time direction multiplier to allow reverse time replay // *** would need time direction multiplier to allow reverse time re
position[2] = position[2] - velocity*deltaTime/1000.0f; play
position[2] = position[2] - velocity*deltaTime/1000.0f;
// train doesn't extend beyond start of burn // train doesn't extend beyond start of burn
if( position[2] + velocity*0.5f > startH ) { if(position[2] + velocity*0.5f > startH)
posTrain[2] = startH ; {
} else { posTrain[2] = startH ;
posTrain[2] -= velocity*deltaTime/1000.0f; }
} else
{
posTrain[2] -= velocity*deltaTime/1000.0f;
}
//qDebug("meteor position: %f delta_t %d\n", position[2], deltaTime); //qDebug("meteor position: %f delta_t %d\n", position[2], deltaTime) ;
// determine visual magnitude based on distance to observer // determine visual magnitude based on distance to observer
double dist = sqrt( xydistance*xydistance + pow( position[2]-obs[2], 2) ) double dist = sqrt(xydistance*xydistance + pow( position[2]-obs[2],
; 2));
if( dist == 0 ) dist = .01; // just to be cautious (meteor hits observer !) if(dist == 0) dist = .01; // just to be cautious (meteor hits obser ver!)
distMultiplier = minDist*minDist / (dist*dist); distMultiplier = minDist*minDist / (dist*dist);
return(alive); return(alive);
} }
// returns true if visible
// Assumes that we are in local frame // Assumes that we are in local frame
void Meteor::draw(const StelCore* core, StelPainter& sPainter) void Meteor::draw(const StelCore* core, StelProjectorP projector, StelRende rer* renderer)
{ {
if (!alive) if (!alive) {return;}
return;
const StelProjectorP proj = sPainter.getProjector();
Vec3d spos = position; Vec3d spos = position;
Vec3d epos = posTrain; Vec3d epos = posTrain;
// convert to equ // convert to equ
spos.transfo4d(mmat); spos.transfo4d(mmat);
epos.transfo4d(mmat); epos.transfo4d(mmat);
// convert to local and correct for earth radius [since equ and loca l coordinates in stellarium use same 0 point!] // convert to local and correct for earth radius [since equ and loca l coordinates in stellarium use same 0 point!]
spos = core->equinoxEquToAltAz( spos ); spos = core->equinoxEquToAltAz(spos);
epos = core->equinoxEquToAltAz( epos ); epos = core->equinoxEquToAltAz(epos);
spos[2] -= EARTH_RADIUS; spos[2] -= EARTH_RADIUS;
epos[2] -= EARTH_RADIUS; epos[2] -= EARTH_RADIUS;
// 1216 is to scale down under 1 for desktop version // 1216 is to scale down under 1 for desktop version
spos/=1216; spos /= 1216;
epos/=1216; epos /= 1216;
// qDebug("[%f %f %f] (%d, %d) (%d, %d)\n", position[0], position[1 ], position[2], (int)start[0], (int)start[1], (int)end[0], (int)end[1]); // qDebug("[%f %f %f] (%d, %d) (%d, %d)\n", position[0], position[1 ], position[2], (int)start[0], (int)start[1], (int)end[0], (int)end[1]);
if(NULL == vertexBuffer)
{
// This well need to be rewritten if the train data member g
ets changed after construction.
vertexBuffer =
renderer->createVertexBuffer<Vertex>(train ? Primiti
veType_LineStrip : PrimitiveType_Points);
}
if (train) if (train)
{ {
// connect this point with last drawn point // connect this point with last drawn point
double tmag = mag*distMultiplier; const double tmag = mag * distMultiplier;
// compute an intermediate point so can curve slightly along projection distortions // compute an intermediate point so can curve slightly along projection distortions
Vec3d posi = posInternal; Vec3d posi = posInternal;
posi[2] = position[2] + (posTrain[2] - position[2])/2; posi[2] = position[2] + (posTrain[2] - position[2]) / 2;
posi.transfo4d(mmat); posi.transfo4d(mmat);
posi = core->equinoxEquToAltAz( posi ); posi = core->equinoxEquToAltAz( posi );
posi[2] -= EARTH_RADIUS; posi[2] -= EARTH_RADIUS;
posi/=1216; posi /= 1216;
// draw dark to light vertexBuffer->unlock();
Vec4f colorArray[3]; vertexBuffer->clear();
colorArray[0].set(0,0,0,0); vertexBuffer->addVertex(Vertex(epos, Vec4f(0.0f, 0.0f, 0.0f,
colorArray[1].set(1,1,1,tmag*0.5); 0.0f)));
colorArray[2].set(1,1,1,tmag); vertexBuffer->addVertex(Vertex(posi, Vec4f(1.0f, 1.0f, 1.0f,
Vec3d vertexArray[3]; tmag * 0.5)));
vertexArray[0]=epos; vertexBuffer->addVertex(Vertex(spos, Vec4f(1.0f, 1.0f, 1.0f,
vertexArray[1]=posi; tmag)));
vertexArray[2]=spos; vertexBuffer->lock();
sPainter.setColorPointer(4, GL_FLOAT, colorArray); renderer->drawVertexBuffer(vertexBuffer, NULL, projector);
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArray);
// TODO the crash doesn't appear when the last true is set t
o false
sPainter.enableClientStates(true, false, true);
sPainter.drawFromArray(StelPainter::LineStrip, 3, 0, true);
sPainter.enableClientStates(false);
} }
else else
{ {
sPainter.setPointSize(1.f); vertexBuffer->unlock();
Vec3d start; vertexBuffer->clear();
proj->project(spos, start); // A line with two identical points ends up being a point.
sPainter.drawPoint2d(start[0],start[1]); vertexBuffer->addVertex(Vertex(spos, Vec4f(1.0f, 1.0f, 1.0f,
1.0f)));
vertexBuffer->lock();
renderer->drawVertexBuffer(vertexBuffer, NULL, projector);
} }
train = 1;
} }
bool Meteor::isAlive(void) bool Meteor::isAlive(void)
{ {
return(alive); return(alive);
} }
 End of changes. 30 change blocks. 
186 lines changed or deleted 206 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/