Meteor.cpp   Meteor.cpp 
/* /*
* Stellarium * Stellarium
* Copyright (C) 2004 Robert Spearman * Copyright (C) 2014-2015 Marcos Cardinot
* Copyright (C) 2014 Marcos Cardinot
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 26 skipping to change at line 25
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/ */
#include "Meteor.hpp" #include "Meteor.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelMovementMgr.hpp" #include "StelMovementMgr.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "StelTexture.hpp" #include "StelTexture.hpp"
#include "StelUtils.hpp"
StelTextureSP Meteor::bolideTexture; #include <QtMath>;
Meteor::Meteor(const StelCore* core, float v) Meteor::Meteor(const StelCore* core, const StelTextureSP& bolideTexture)
: m_distMultiplier(0.) : m_core(core)
, m_alive(false)
, m_speed(72.)
, m_initialZ(1.)
, m_finalZ(1.)
, m_minDist(1.)
, m_absMag(.5)
, m_aptMag(.5)
, m_bolideTexture(bolideTexture)
, m_segments(10) , m_segments(10)
{ {
qsrand (QDateTime::currentMSecsSinceEpoch()); qsrand(QDateTime::currentMSecsSinceEpoch());
// determine meteor velocity
// abs range 11-72 km/s by default (see line 427 in StelApp.cpp)
m_speed = 11+(float)qrand()/((float)RAND_MAX+1)*(v-11);
// view matrix of sporadic meteors model
float alpha = (double)qrand()/((double)RAND_MAX+1)*2*M_PI;
float delta = M_PI_2 - (double)qrand()/((double)RAND_MAX+1)*M_PI;
m_viewMatrix = Mat4d::zrotation(alpha) * Mat4d::yrotation(delta);
// building meteor model
m_alive = initMeteorModel(core, m_segments, m_viewMatrix, meteor);
if (!m_alive)
{
return;
}
// building lineColorArray and trainColorArray
buildColorArrays(m_segments, getRandColor(), m_lineColorArray, m_tra
inColorArray);
} }
Meteor::~Meteor() Meteor::~Meteor()
{ {
m_bolideTexture.clear();
} }
// returns true if alive void Meteor::init(const float& radiantAlpha, const float& radiantDelta,
bool Meteor::initMeteorModel(const StelCore* core, const int segments, cons const float& speed, const QList<ColorPair> colors)
t Mat4d viewMatrix, MeteorModel &mm)
{ {
float high_range = EARTH_RADIUS + HIGH_ALTITUDE; // meteor velocity in km/s
float low_range = EARTH_RADIUS + LOW_ALTITUDE; m_speed = speed;
// find the radiant in horizontal coordinates
Vec3d radiantAltAz;
StelUtils::spheToRect(radiantAlpha, radiantDelta, radiantAltAz);
radiantAltAz = m_core->j2000ToAltAz(radiantAltAz);
float radiantAlt, radiantAz;
// S is zero, E is 90 degrees (SDSS)
StelUtils::rectToSphe(&radiantAz, &radiantAlt, radiantAltAz);
// meteors won't be visible if radiant is below 0degrees
if (radiantAlt < 0.f)
{
return;
}
// define the radiant coordinate system
// rotation matrix to align z axis with radiant
m_matAltAzToRadiant = Mat4d::zrotation(radiantAz) * Mat4d::yrotation
(M_PI_2 - radiantAlt);
// select a random initial meteor altitude in the horizontal system
[MIN_ALTITUDE, MAX_ALTITUDE]
float initialAlt = MIN_ALTITUDE + (MAX_ALTITUDE - MIN_ALTITUDE) * ((
float) qrand() / ((float) RAND_MAX + 1));
// calculates the max z-coordinate for the currrent radiant
float maxZ = meteorZ(M_PI_2 - radiantAlt, initialAlt);
// meteor trajectory
// select a random xy position in polar coordinates (radiant system)
// find observer position in meteor coordinate system float xyDist = maxZ * ((double) qrand() / ((double) RAND_MAX + 1));
mm.obs = core->altAzToJ2000(Vec3d(0,0,EARTH_RADIUS)); // [0, maxZ]
mm.obs.transfo4d(viewMatrix.transpose()); float theta = 2 * M_PI * ((double) qrand() / ((double) RAND_MAX + 1)
); // [0, 2pi]
// select random trajectory using polar coordinates in XY plane, cen // initial meteor coordinates (radiant system)
tered on observer m_position[0] = xyDist * qCos(theta);
mm.xydistance = (double)qrand() / ((double)RAND_MAX+1)*(VISIBLE_RADI m_position[1] = xyDist * qSin(theta);
US); m_position[2] = maxZ;
float angle = (double)qrand() / ((double)RAND_MAX+1)*2*M_PI; m_posTrain = m_position;
// set meteor start x,y // store the initial z-component (radiant system)
mm.position[0] = mm.posTrain[0] = mm.xydistance*cos(angle) + mm.obs[ m_initialZ = m_position[2];
0];
mm.position[1] = mm.posTrain[1] = mm.xydistance*sin(angle) + mm.obs[
1];
// D is distance from center of earth // find the initial meteor coordinates in the horizontal system
float D = std::sqrt(mm.position[0]*mm.position[0] + mm.position[1]*m Vec3d positionAltAz = m_position;
m.position[1]); positionAltAz.transfo4d(m_matAltAzToRadiant);
if (D > high_range) // won't be visible, meteor still dead // find the angle from horizon to meteor
float meteorAlt = qAsin(positionAltAz[2] / positionAltAz.length());
// this meteor should not be visible if it is above the maximum alti
tude
// or if it's below the horizon!
if (positionAltAz[2] > MAX_ALTITUDE || meteorAlt <= 0.f)
{ {
return false; return;
} }
mm.posTrain[2] = mm.position[2] = mm.startH = std::sqrt(high_range*h // determine the final z-component and the min distance between mete
igh_range - D*D); or and observer
if (radiantAlt < 0.0262f) // (<1.5 degrees) earth grazing meteor ?
// determine end of burn point, and nearest point to observer for di
stance mag calculation
// mag should be max at nearest point still burning
if (D > low_range)
{ {
mm.endH = -mm.startH; // earth grazing // earth-grazers are rare!
mm.minDist = mm.xydistance; // introduce a probabilistic factor just to make them a bit
harder to occur
float prob = ((float) qrand() / ((float) RAND_MAX + 1));
if (prob > 0.3f) {
return;
}
// limit lifetime to 12sec
m_finalZ = -m_position[2];
m_finalZ = qMax(m_position[2] - m_speed * 12.f, (double) m_f
inalZ);
m_minDist = xyDist;
} }
else else
{ {
mm.endH = std::sqrt(low_range*low_range - D*D); // limit lifetime to 12sec
mm.minDist = std::sqrt(mm.xydistance*mm.xydistance + pow(mm. m_finalZ = meteorZ(M_PI_2 - meteorAlt, MIN_ALTITUDE);
endH - mm.obs[2], 2)); m_finalZ = qMax(m_position[2] - m_speed * 12.f, (double) m_f
inalZ);
m_minDist = qSqrt(m_finalZ * m_finalZ + xyDist * xyDist);
} }
if (mm.minDist > VISIBLE_RADIUS) // a meteor cannot hit the observer!
{ if (m_minDist < MIN_ALTITUDE) {
// on average, not visible (although if were zoomed ...) return;
return false; //meteor still dead
} }
// determine intensity [-3; 4.5] // select random magnitude [-3; 4.5]
float Mag1 = (double)qrand()/((double)RAND_MAX+1)*7.5f - 3; float Mag = (float) qrand() / ((float) RAND_MAX + 1) * 7.5f - 3.f;
float Mag2 = (double)qrand()/((double)RAND_MAX+1)*7.5f - 3;
float Mag = (Mag1 + Mag2)/2.0f;
// compute RMag and CMag // compute RMag and CMag
RCMag rcMag; RCMag rcMag;
core->getSkyDrawer()->computeRCMag(Mag, &rcMag); m_core->getSkyDrawer()->computeRCMag(Mag, &rcMag);
mm.mag = rcMag.luminance; m_absMag = rcMag.radius <= 1.2f ? 0.f : rcMag.luminance;
if (m_absMag == 0.f) {
return;
}
// most visible meteors are under about 180km distant // most visible meteors are under about 184km distant
// scale max mag down if outside this range // scale max mag down if outside this range
float scale = 1; float scale = qPow(184.0 / m_minDist, 2);
if (mm.minDist) m_absMag *= qMin(scale, 1.0f);
// build the color vector
buildColorVectors(colors);
m_alive = true;
}
bool Meteor::update(double deltaTime)
{
if (!m_alive)
{
return false;
}
if (m_position[2] < m_finalZ)
{
// burning has stopped so magnitude fades out
// assume linear fade out
m_absMag -= deltaTime * 2.f;
}
// no longer visible
if(m_absMag <= 0.f)
{ {
scale = 180*180 / (mm.minDist*mm.minDist); m_alive = false;
return false;
}
m_position[2] -= m_speed * deltaTime;
// train doesn't extend beyond start of burn
if (m_position[2] + m_speed * 0.5f > m_initialZ)
{
m_posTrain[2] = m_initialZ;
}
else
{
m_posTrain[2] -= m_speed * deltaTime;
} }
if (scale < 1)
// update apparent magnitude based on distance to observer
float scale = qPow(m_minDist / m_position.length(), 2);
m_aptMag = m_absMag * qMin(scale, 1.f);
m_aptMag = qMax(m_aptMag, 0.f);
return true;
}
void Meteor::draw(const StelCore* core, StelPainter& sPainter)
{
if (!m_alive)
{ {
mm.mag *= scale; return;
} }
mm.firstBrightSegment = (double)qrand()/((double)RAND_MAX+1)*segment float thickness;
s; float bolideSize;
calculateThickness(core, thickness, bolideSize);
drawTrain(sPainter, thickness);
// If everything is ok until here, drawBolide(sPainter, bolideSize);
return true; //the meteor is alive
} }
Vec4f Meteor::getColorFromName(QString colorName) { Vec4f Meteor::getColorFromName(QString colorName)
{
int R, G, B; // 0-255 int R, G, B; // 0-255
if (colorName == "violet") { // Calcium if (colorName == "violet")
{ // Calcium
R = 176; R = 176;
G = 67; G = 67;
B = 172; B = 172;
} else if (colorName == "blueGreen") { // Magnesium }
else if (colorName == "blueGreen")
{ // Magnesium
R = 0; R = 0;
G = 255; G = 255;
B = 152; B = 152;
} else if (colorName == "yellow") { // Iron }
else if (colorName == "yellow")
{ // Iron
R = 255; R = 255;
G = 255; G = 255;
B = 0; B = 0;
} else if (colorName == "orangeYellow") { // Sodium }
else if (colorName == "orangeYellow")
{ // Sodium
R = 255; R = 255;
G = 160; G = 160;
B = 0; B = 0;
} else if (colorName == "red") { // atmospheric nitrogen and oxygen }
else if (colorName == "red")
{ // atmospheric nitrogen and oxygen
R = 255; R = 255;
G = 30; G = 30;
B = 0; B = 0;
} else { // white }
else
{ // white
R = 255; R = 255;
G = 255; G = 255;
B = 255; B = 255;
} }
return Vec4f(R/255.f, G/255.f, B/255.f, 1); return Vec4f(R/255.f, G/255.f, B/255.f, 1);
} }
QList<Meteor::colorPair> Meteor::getRandColor() { void Meteor::buildColorVectors(const QList<ColorPair> colors)
QList<colorPair> colors;
float prob = (double)qrand()/((double)RAND_MAX+1);
if (prob > 0.9) {
colors.push_back(Meteor::colorPair("white", 70));
colors.push_back(Meteor::colorPair("orangeYellow", 10));
colors.push_back(Meteor::colorPair("yellow", 10));
colors.push_back(Meteor::colorPair("blueGreen", 10));
} else if (prob > 0.85) {
colors.push_back(Meteor::colorPair("white", 80));
colors.push_back(Meteor::colorPair("violet", 20));
} else if (prob > 0.80) {
colors.push_back(Meteor::colorPair("white", 80));
colors.push_back(Meteor::colorPair("orangeYellow", 20));
} else {
colors.push_back(Meteor::colorPair("white", 100));
}
return colors;
}
void Meteor::buildColorArrays(const int segments,
const QList<colorPair> colors,
QList<Vec4f> &lineColorArray,
QList<Vec4f> &trainColorArray)
{ {
// building color arrays (line and prism) // building color arrays (line and prism)
int totalOfSegments = 0; QList<Vec4f> lineColor;
int currentSegment = 1+(double)qrand()/((double)RAND_MAX+1)*(segment QList<Vec4f> trainColor;
s-1); foreach (ColorPair color, colors)
for (int colorIndex=0; colorIndex<colors.size(); colorIndex++) { {
colorPair currentColor = colors[colorIndex]; // segments to be painted with the current color
int segs = qRound(m_segments * (color.second / 100.f)); // r
// segments which we'll paint with the current color ounds to nearest integer
int numOfSegments = segments*(currentColor.second / 100.f) + for (int s = 0; s < segs; ++s)
0.4f; // +0.4 affect approximation {
if (colorIndex == colors.size()-1) { Vec4f rgba = getColorFromName(color.first);
numOfSegments = segments - totalOfSegments; lineColor.append(rgba);
} trainColor.append(rgba);
trainColor.append(rgba);
totalOfSegments += numOfSegments;
for (int i=0; i<numOfSegments; i++) {
lineColorArray.insert(currentSegment, getColorFromNa
me(currentColor.first));
trainColorArray.insert(currentSegment, getColorFromN
ame(currentColor.first));
if (currentSegment >= segments-1) {
currentSegment = 0;
} else {
currentSegment++;
}
trainColorArray.insert(currentSegment, getColorFromN
ame(currentColor.first));
} }
} }
}
bool Meteor::updateMeteorModel(double deltaTime, double speed, MeteorModel // make sure that all segments have been painted!
&mm) const int segs = lineColor.size();
{ if (segs < m_segments) {
if (mm.position[2] < mm.endH) // use the last color to paint the last segments
{ Vec4f rgba = getColorFromName(colors.last().first);
// burning has stopped so magnitude fades out for (int s = segs; s < m_segments; ++s) {
// assume linear fade out lineColor.append(rgba);
mm.mag -= deltaTime/500.0f; trainColor.append(rgba);
if(mm.mag < 0) trainColor.append(rgba);
{ }
return false; // no longer visible } else if (segs > m_segments) {
// remove the extra segments
for (int s = segs; s > m_segments; --s) {
lineColor.removeLast();
trainColor.removeLast();
trainColor.removeLast();
} }
} }
// *** would need time direction multiplier to allow reverse time re // multi-color ?
play // select a random segment to be the first (to alternate colors)
float dt = 820+(double)qrand()/((double)RAND_MAX+1)*185; // range 82 if (colors.size() > 1) {
0-1005 int firstSegment = (segs - 1) * ((float) qrand() / ((float)
mm.position[2] -= speed*deltaTime/dt; RAND_MAX + 1)); // [0, segments-1]
QList<Vec4f> lineColor2 = lineColor.mid(0, firstSegment);
// train doesn't extend beyond start of burn QList<Vec4f> lineColor1 = lineColor.mid(firstSegment);
if (mm.position[2] + speed*0.5f > mm.startH) lineColor.clear();
{ lineColor.append(lineColor1);
mm.posTrain[2] = mm.startH; lineColor.append(lineColor2);
firstSegment *= 2;
QList<Vec4f> trainColor2 = trainColor.mid(0, firstSegment);
QList<Vec4f> trainColor1 = trainColor.mid(firstSegment);
trainColor.clear();
trainColor.append(trainColor1);
trainColor.append(trainColor2);
}
m_lineColorVector = lineColor.toVector();
m_trainColorVector = trainColor.toVector();
}
float Meteor::meteorZ(float zenithAngle, float altitude)
{
float distance;
if (zenithAngle > 1.13446401f) // > 65 degrees?
{
float zcos = qCos(zenithAngle);
distance = qSqrt(EARTH_RADIUS2 * qPow(zcos, 2)
+ 2 * EARTH_RADIUS * altitude
+ qPow(altitude, 2));
distance -= EARTH_RADIUS * zcos;
} }
else else
{ {
mm.posTrain[2] -= speed*deltaTime/dt; // (first order approximation)
distance = altitude / qCos(zenithAngle);
} }
return true; return distance;
} }
// returns true if alive Vec3d Meteor::altAzToRadiant(Vec3d position)
bool Meteor::update(double deltaTime)
{ {
if (!m_alive) position.transfo4d(m_matAltAzToRadiant.transpose());
{ position *= 1242;
return false; return position;
}
m_alive = updateMeteorModel(deltaTime, m_speed, meteor);
// determine visual magnitude based on distance to observer
double dist = std::sqrt(meteor.xydistance*meteor.xydistance + pow(me
teor.position[2]-meteor.obs[2], 2));
if (dist == 0)
{
dist = .01; // just to be cautious (meteor hits observer!
)
}
m_distMultiplier = meteor.minDist*meteor.minDist / (dist*dist);
return m_alive;
} }
void Meteor::insertVertex(const StelCore* core, const Mat4d& viewMatrix, QV ector<Vec3d> &vertexArray, Vec3d vertex) Vec3d Meteor::radiantToAltAz(Vec3d position)
{ {
vertex.transfo4d(viewMatrix); position /= 1242.0; // 1242 to scale down under 1
vertex = core->j2000ToAltAz(vertex); position.transfo4d(m_matAltAzToRadiant);
vertex[2] -= EARTH_RADIUS; return position;
vertex/=1216; // 1216 is to scale down under 1 for desktop version
vertexArray.push_back(vertex);
} }
void Meteor::calculateThickness(const StelCore* core, float& thickness, flo at& bolideSize) void Meteor::calculateThickness(const StelCore* core, float& thickness, flo at& bolideSize)
{ {
float maxFOV = core->getMovementMgr()->getMaxFov(); float maxFOV = core->getMovementMgr()->getMaxFov();
float FOV = core->getMovementMgr()->getCurrentFov(); float FOV = core->getMovementMgr()->getCurrentFov();
thickness = 2*log(FOV + 0.25)/(1.2*maxFOV - (FOV + 0.25)) + 0.01; thickness = 2*log(FOV + 0.25)/(1.2*maxFOV - (FOV + 0.25)) + 0.01;
if (FOV <= 0.5) if (FOV <= 0.5)
{ {
thickness = 0.013 * FOV; // decreasing faster thickness = 0.013 * FOV; // decreasing faster
} else if (FOV > 100.0) { }
else if (FOV > 100.0)
{
thickness = 0; // remove prism thickness = 0; // remove prism
} }
bolideSize = thickness*3; bolideSize = thickness*3;
} }
void Meteor::drawBolide(const StelCore* core, StelPainter& sPainter, const void Meteor::drawBolide(StelPainter& sPainter, const float& bolideSize)
MeteorModel& mm,
const Mat4d& viewMatrix, const float bolideSize)
{ {
if (!bolideSize) { if (!bolideSize || !m_bolideTexture)
{
return; return;
} }
// bolide // bolide
// //
QVector<Vec3d> vertexArrayBolide; QVector<Vec3d> vertexArrayBolide;
QVector<Vec4f> colorArrayBolide; QVector<Vec4f> colorArrayBolide;
Vec4f bolideColor = Vec4f(1,1,1,mm.mag); Vec4f bolideColor = Vec4f(1, 1, 1, m_aptMag);
Vec3d topLeft = mm.position; Vec3d topLeft = m_position;
topLeft[1] -= bolideSize; topLeft[1] -= bolideSize;
insertVertex(core, viewMatrix, vertexArrayBolide, topLeft); vertexArrayBolide.push_back(radiantToAltAz(topLeft));
colorArrayBolide.push_back(bolideColor); colorArrayBolide.push_back(bolideColor);
Vec3d topRight = mm.position; Vec3d topRight = m_position;
topRight[0] -= bolideSize; topRight[0] -= bolideSize;
insertVertex(core, viewMatrix, vertexArrayBolide, topRight); vertexArrayBolide.push_back(radiantToAltAz(topRight));
colorArrayBolide.push_back(bolideColor); colorArrayBolide.push_back(bolideColor);
Vec3d bottomRight = mm.position; Vec3d bottomRight = m_position;
bottomRight[1] += bolideSize; bottomRight[1] += bolideSize;
insertVertex(core, viewMatrix, vertexArrayBolide, bottomRight); vertexArrayBolide.push_back(radiantToAltAz(bottomRight));
colorArrayBolide.push_back(bolideColor); colorArrayBolide.push_back(bolideColor);
Vec3d bottomLeft = mm.position; Vec3d bottomLeft = m_position;
bottomLeft[0] += bolideSize; bottomLeft[0] += bolideSize;
insertVertex(core, viewMatrix, vertexArrayBolide, bottomLeft); vertexArrayBolide.push_back(radiantToAltAz(bottomLeft));
colorArrayBolide.push_back(bolideColor); colorArrayBolide.push_back(bolideColor);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE); glBlendFunc(GL_ONE, GL_ONE);
sPainter.enableClientStates(true, true, true); sPainter.enableClientStates(true, true, true);
Meteor::bolideTexture->bind(); m_bolideTexture->bind();
static const float texCoordData[] = {1.,0., 0.,0., 0.,1., 1.,1.}; static const float texCoordData[] = {1.,0., 0.,0., 0.,1., 1.,1.};
sPainter.setTexCoordPointer(2, GL_FLOAT, texCoordData); sPainter.setTexCoordPointer(2, GL_FLOAT, texCoordData);
sPainter.setColorPointer(4, GL_FLOAT, colorArrayBolide.constData()); sPainter.setColorPointer(4, GL_FLOAT, colorArrayBolide.constData());
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayBolide.constData( )); sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayBolide.constData( ));
sPainter.drawFromArray(StelPainter::TriangleFan, vertexArrayBolide.s ize(), 0, true); sPainter.drawFromArray(StelPainter::TriangleFan, vertexArrayBolide.s ize(), 0, true);
glDisable(GL_BLEND); glDisable(GL_BLEND);
sPainter.enableClientStates(false); sPainter.enableClientStates(false);
} }
void Meteor::drawTrain(const StelCore *core, StelPainter& sPainter, const M void Meteor::drawTrain(StelPainter& sPainter, const float& thickness)
eteorModel& mm,
const Mat4d& viewMatrix, const float thickness, const
int segments,
QList<Vec4f> lineColorArray, QList<Vec4f> trainColorA
rray)
{ {
if (segments != lineColorArray.size() || 2*segments != trainColorArr ay.size()) if (m_segments != m_lineColorVector.size() || 2*m_segments != m_trai nColorVector.size())
{ {
qWarning() << "Meteor: color arrays have an inconsistent siz e!"; qWarning() << "Meteor: color arrays have an inconsistent siz e!";
return; return;
} }
// train (triangular prism) // train (triangular prism)
// //
QVector<Vec3d> vertexArrayLine; QVector<Vec3d> vertexArrayLine;
QVector<Vec3d> vertexArrayL; QVector<Vec3d> vertexArrayL;
QVector<Vec3d> vertexArrayR; QVector<Vec3d> vertexArrayR;
QVector<Vec3d> vertexArrayTop; QVector<Vec3d> vertexArrayTop;
Vec3d posTrainB = mm.posTrain; Vec3d posTrainB = m_posTrain;
posTrainB[0] += thickness*0.7; posTrainB[0] += thickness*0.7;
posTrainB[1] += thickness*0.7; posTrainB[1] += thickness*0.7;
Vec3d posTrainL = mm.posTrain; Vec3d posTrainL = m_posTrain;
posTrainL[1] -= thickness; posTrainL[1] -= thickness;
Vec3d posTrainR = mm.posTrain; Vec3d posTrainR = m_posTrain;
posTrainR[0] -= thickness; posTrainR[0] -= thickness;
for (int i=0; i<segments; i++) { for (int i = 0; i < m_segments; ++i)
float mag = mm.mag * i/(3* (segments-1)); {
if (i > mm.firstBrightSegment) { double height = m_posTrain[2] + i*(m_position[2] - m_posTrai
mag *= 12./5.; n[2])/(m_segments-1);
}
double height = mm.posTrain[2] + i*(mm.position[2] - mm.posT
rain[2])/(segments-1);
Vec3d posi; Vec3d posi;
posi = mm.posTrain; posi = m_posTrain;
posi[2] = height; posi[2] = height;
insertVertex(core, viewMatrix, vertexArrayLine, posi); vertexArrayLine.push_back(radiantToAltAz(posi));
posi = posTrainB; posi = posTrainB;
posi[2] = height; posi[2] = height;
insertVertex(core, viewMatrix, vertexArrayL, posi); vertexArrayL.push_back(radiantToAltAz(posi));
insertVertex(core, viewMatrix, vertexArrayR, posi); vertexArrayR.push_back(radiantToAltAz(posi));
posi = posTrainL; posi = posTrainL;
posi[2] = height; posi[2] = height;
insertVertex(core, viewMatrix, vertexArrayL, posi); vertexArrayL.push_back(radiantToAltAz(posi));
insertVertex(core, viewMatrix, vertexArrayTop, posi); vertexArrayTop.push_back(radiantToAltAz(posi));
posi = posTrainR; posi = posTrainR;
posi[2] = height; posi[2] = height;
insertVertex(core, viewMatrix, vertexArrayR, posi); vertexArrayR.push_back(radiantToAltAz(posi));
insertVertex(core, viewMatrix, vertexArrayTop, posi); vertexArrayTop.push_back(radiantToAltAz(posi));
lineColorArray[i][3] = mag; float mag = m_aptMag * ((float) i / (float) (m_segments-1));
trainColorArray[i*2][3] = mag; m_lineColorVector[i][3] = mag;
trainColorArray[i*2+1][3] = mag; m_trainColorVector[i*2][3] = mag;
m_trainColorVector[i*2+1][3] = mag;
} }
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
sPainter.enableClientStates(true, false, true); sPainter.enableClientStates(true, false, true);
if (thickness) { if (thickness)
sPainter.setColorPointer(4, GL_FLOAT, trainColorArray.toVect {
or().constData()); sPainter.setColorPointer(4, GL_FLOAT, m_trainColorVector.con
stData());
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayL.constDa ta()); sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayL.constDa ta());
sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayL.size(), 0, true); sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayL.size(), 0, true);
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayR.constDa ta()); sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayR.constDa ta());
sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayR.size(), 0, true); sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayR.size(), 0, true);
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayTop.const Data()); sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayTop.const Data());
sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayTop.size(), 0, true); sPainter.drawFromArray(StelPainter::TriangleStrip, vertexArr ayTop.size(), 0, true);
} }
sPainter.setColorPointer(4, GL_FLOAT, lineColorArray.toVector().cons tData()); sPainter.setColorPointer(4, GL_FLOAT, m_lineColorVector.constData()) ;
sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayLine.constData()) ; sPainter.setVertexPointer(3, GL_DOUBLE, vertexArrayLine.constData()) ;
sPainter.drawFromArray(StelPainter::LineStrip, vertexArrayLine.size( ), 0, true); sPainter.drawFromArray(StelPainter::LineStrip, vertexArrayLine.size( ), 0, true);
glDisable(GL_BLEND); glDisable(GL_BLEND);
sPainter.enableClientStates(false); sPainter.enableClientStates(false);
} }
// returns true if visible
// Assumes that we are in local frame
void Meteor::draw(const StelCore* core, StelPainter& sPainter)
{
if (!m_alive)
{
return;
}
float thickness, bolideSize;
calculateThickness(core, thickness, bolideSize);
drawTrain(core, sPainter, meteor, m_viewMatrix, thickness,
m_segments, m_lineColorArray, m_trainColorArray);
drawBolide(core, sPainter, meteor, m_viewMatrix, bolideSize);
}
 End of changes. 74 change blocks. 
236 lines changed or deleted 300 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/