void TrailGroup::draw(StelCore* core, StelPainter* sPainter) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float currentTime = core->getJDE(); StelProjector::ModelViewTranformP transfo = core->getJ2000ModelViewTransform(); transfo->combine(j2000ToTrailNativeInverted); sPainter->setProjector(core->getProjection(transfo)); foreach (const Trail& trail, allTrails) { Planet* hpl = dynamic_cast<Planet*>(trail.stelObject.data()); if (hpl!=NULL) { // Avoid drawing the trails if the object is the home planet QString homePlanetName = hpl->getEnglishName(); if (homePlanetName==StelApp::getInstance().getCore()->getCurrentLocation().planetName) continue; } const QList<Vec3d>& posHistory = trail.posHistory; vertexArray.resize(posHistory.size()); colorArray.resize(posHistory.size()); for (int i=0;i<posHistory.size();++i) { float colorRatio = 1.f-(currentTime-times.at(i))/timeExtent; colorArray[i].set(trail.color[0], trail.color[1], trail.color[2], colorRatio*opacity); vertexArray[i]=posHistory.at(i); } sPainter->drawPath(vertexArray, colorArray); }
void Comet::drawComa(StelCore* core, StelProjector::ModelViewTranformP transfo) { // Find rotation matrix from 0/0/1 to viewdirection! crossproduct for axis (normal vector), dotproduct for angle. Vec3d eclposNrm=eclipticPos - core->getObserverHeliocentricEclipticPos() ; eclposNrm.normalize(); Mat4d comarot=Mat4d::rotation(Vec3d(0.0, 0.0, 1.0)^(eclposNrm), std::acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) ); StelProjector::ModelViewTranformP transfo2 = transfo->clone(); transfo2->combine(comarot); StelPainter* sPainter = new StelPainter(core->getProjection(transfo2)); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_CULL_FACE); // GZ: For the coma, we can use extinction via atmosphere. // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6. float minSkyMag=core->getSkyDrawer()->getLimitMagnitude(); float mag100pct=minSkyMag-6.0f; // should be 5, but let us draw it a bit brighter. float magDrop=getVMagnitudeWithExtinction(core)-mag100pct; float magFactor=std::pow(0.6f , magDrop); magFactor=qMin(magFactor, 2.0f); // Limit excessively bright display. comaTexture->bind(); sPainter->setColor(magFactor,magFactor,0.6f*magFactor); sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaTexCoordArr.constData()); sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size()/3); glDisable(GL_BLEND); if (sPainter) delete sPainter; sPainter=NULL; }
void TrailGroup::draw(StelCore* core, StelRenderer* renderer) { renderer->setBlendMode(BlendMode_Alpha); float currentTime = core->getJDay(); StelProjector::ModelViewTranformP transfo = core->getJ2000ModelViewTransform(); transfo->combine(j2000ToTrailNativeInverted); StelProjectorP projector = core->getProjection(transfo); // We skip some positions to avoid drawing too many vertices when the history is long. int totalPositions = 0; foreach(const Trail& trail, allTrails) { totalPositions += trail.posHistory.size(); } const int desiredMaxTotalTrailVertices = 8192; const int skip = std::max(1, totalPositions / desiredMaxTotalTrailVertices); for(int t = 0; t < allTrails.size(); t++) { Trail& trail(allTrails[t]); Planet* hpl = dynamic_cast<Planet*>(trail.stelObject.data()); if (hpl != NULL) { // Avoid drawing the trails if the object is the home planet QString homePlanetName = hpl == NULL ? "" : hpl->getEnglishName(); if (homePlanetName == StelApp::getInstance().getCore()->getCurrentLocation().planetName) { continue; } } const QVector<Vec3f>& posHistory = trail.posHistory; // Construct the vertex buffer if not yet constructed, otherwise clear it. if(NULL == trail.vertexBuffer) { trail.vertexBuffer = renderer->createVertexBuffer<ColoredVertex>(PrimitiveType_LineStrip); } else { trail.vertexBuffer->unlock(); trail.vertexBuffer->clear(); } // Hand-optimized as this previously took up to 9% of time when // trail groups were enabled. Now it's up to 3%. Further optimization // is possible, but would lead to more uglification. int posCount = posHistory.size(); int p = 0; const float timeMult = 1.0f / timeExtent; ColoredVertex vertex; for (p = 0; p < posCount - 1; ++p) { // Skip if too many positions, but don't skip the last position. if(p % skip != 0) { continue; } const float colorRatio = 1.0f - (currentTime - times.at(p)) * timeMult; vertex.color = Vec4f(trail.color[0], trail.color[1], trail.color[2], colorRatio * opacity); vertex.position = posHistory.at(p); trail.vertexBuffer->addVertex(vertex); } // Last vertex (separate to avoid a branch in the code above) const float colorRatio = 1.0f - (currentTime - times.at(p)) * timeMult; vertex.color = Vec4f(trail.color[0], trail.color[1], trail.color[2], colorRatio * opacity); vertex.position = posHistory.at(p); trail.vertexBuffer->addVertex(vertex); trail.vertexBuffer->lock(); renderer->drawVertexBuffer(trail.vertexBuffer, NULL, projector); } }
void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP transfo, bool gas) { // Find rotation matrix from 0/0/1 to eclipticPosition: crossproduct for axis (normal vector), dotproduct for angle. Vec3d eclposNrm=eclipticPos; eclposNrm.normalize(); Mat4d tailrot=Mat4d::rotation(Vec3d(0.0, 0.0, 1.0)^(eclposNrm), std::acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) ); StelProjector::ModelViewTranformP transfo2 = transfo->clone(); transfo2->combine(tailrot); if (!gas) { CometOrbit* orbit=(CometOrbit*)userDataPtr; Vec3d velocity=orbit->getVelocity(); // [AU/d] // This was a try to rotate a straight parabola somewhat away from the antisolar direction. //Mat4d dustTailRot=Mat4d::rotation(eclposNrm^(-velocity), 0.15f*std::acos(eclposNrm.dot(-velocity))); // GZ: This scale factor of 0.15 is empirical from photos of Halley and Hale-Bopp. // The curved tail is curved towards positive X. We first rotate around the Z axis into a direction opposite of the motion vector, then again the antisolar rotation applies. Mat4d dustTailRot=Mat4d::zrotation(atan2(velocity[1], velocity[0]) + M_PI); transfo2->combine(dustTailRot); // In addition, we let the dust tail already start with a light tilt. Mat4d dustTailYrot=Mat4d::yrotation(5.0f*velocity.length()); // again, this is pretty ad-hoc, feel free to improve! transfo2->combine(dustTailYrot); } StelPainter* sPainter = new StelPainter(core->getProjection(transfo2)); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_CULL_FACE); // GZ: If we use getVMagnitudeWithExtinction(), a head extincted in the horizon mist can completely hide an otherwise frighteningly long tail. // we must use unextincted mag, but mix/dim with atmosphere/sky brightness. // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6. //float magfactor=std::pow(0.4f , getVMagnitudeWithExtinction(core)); float magFactor=std::pow(0.6f , getVMagnitude(core)); if (core->getSkyDrawer()->getFlagHasAtmosphere()) { // Mix with sky brightness and light pollution: This is very ad-hoc, if someone finds a better solution, please go ahead! // Light pollution: float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->getBortleScaleIndex()); magFactor*= bortleIndexFactor*bortleIndexFactor; // GZ-Guesstimate for light pollution influence // sky brightness: This is about 10 for twilight where bright comet tails should already be visible. Dark night is close to 0. float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance(); float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFactor<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor); magFactor*=atmLumFactor*atmLumFactor; } magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical adjustment for texture brightness. magFactor=qMin(magFactor, 1.05f); // Limit excessively bright display. gasTailTexture->bind(); if (gas) { //gasTailTexture->bind(); sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magFactor); sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (Vec2f*)gastailTexCoordArr.constData()); sPainter->drawFromArray(StelPainter::Triangles, gastailIndices.size(), 0, true, gastailIndices.constData()); } else { //dustTailTexture->bind(); sPainter->setColor(magFactor, magFactor,0.6f*magFactor); //sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)dusttailTexCoordArr.constData()); //sPainter->drawFromArray(StelPainter::Triangles, dusttailIndices.size(), 0, true, dusttailIndices.constData()); sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)gastailTexCoordArr.constData()); sPainter->drawFromArray(StelPainter::Triangles, gastailIndices.size(), 0, true, gastailIndices.constData()); } glDisable(GL_BLEND); if (sPainter) delete sPainter; sPainter=NULL; }
// Draw the Comet and all the related infos : name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont) { if (hidden) return; if (getEnglishName() == core->getCurrentLocation().planetName) { // GZ moved this up. Maybe even don't do that? E.g., draw tail while riding the comet? Decide later. return; } // The CometOrbit is in fact available in userDataPtr! CometOrbit* orbit=(CometOrbit*)userDataPtr; Q_ASSERT(orbit); if (!orbit->objectDateValid(core->getJDay())) return; // out of useful date range. This allows having hundreds of comet elements. if (orbit->getUpdateTails()){ // Compute lengths and orientations from orbit object, but only if required. // TODO: This part should possibly be moved to another thread to keep draw() free from too much computation. Vec2f tailFactors=getComaDiameterAndTailLengthAU(); float gasTailEndRadius=qMax(tailFactors[0], 0.025f*tailFactors[1]) ; // This avoids too slim gas tails for bright comets like Hale-Bopp. float gasparameter=gasTailEndRadius*gasTailEndRadius/(2.0f*tailFactors[1]); // parabola formula: z=r²/2p, so p=r²/2z // The dust tail is thicker and usually shorter. The factors can be configured in the elements. float dustparameter=gasTailEndRadius*gasTailEndRadius*dustTailWidthFactor*dustTailWidthFactor/(2.0f*dustTailLengthFactor*tailFactors[1]); // Find valid parameters to create paraboloid vertex arrays: dustTail, gasTail. computeParabola(gasparameter, gasTailEndRadius, -0.5f*gasparameter, gastailVertexArr, gastailTexCoordArr, gastailIndices); // This was for a rotated straight parabola: //computeParabola(dustparameter, 2.0f*tailFactors[0], -0.5f*dustparameter, dusttailVertexArr, dusttailTexCoordArr, dusttailIndices); // Now we make a skewed parabola. Skew factor 15 (last arg) ad-hoc/empirical. TBD later: Find physically correct solution. computeParabola(dustparameter, dustTailWidthFactor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, gastailTexCoordArr, gastailIndices, 25.0f*orbit->getVelocity().length()); // Note that we use a diameter larger than what the formula returns. A scale factor of 1.2 is ad-hoc/empirical (GZ), but may look better. computeComa(1.0f*tailFactors[0]); orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere } Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; /* // We can remove that - a Comet has no parent except for the sun... PlanetP p = parent; while (p && p->parent) { mat = Mat4d::translation(p->eclipticPos) * mat * p->rotLocalToParent; p = p->parent; } */ // This removed totally the Planet shaking bug!!! StelProjector::ModelViewTranformP transfo = core->getHeliocentricEclipticModelViewTransform(); transfo->combine(mat); // Compute the 2D position and check if in the screen const StelProjectorP prj = core->getProjection(transfo); float screenSz = getAngularSize(core)*M_PI/180.*prj->getPixelPerRadAtCenter(); float viewport_left = prj->getViewportPosX(); float viewport_bottom = prj->getViewportPosY(); if (prj->project(Vec3d(0), screenPos) && screenPos[1]>viewport_bottom - screenSz && screenPos[1] < viewport_bottom + prj->getViewportHeight()+screenSz && screenPos[0]>viewport_left - screenSz && screenPos[0] < viewport_left + prj->getViewportWidth() + screenSz) { // Draw the name, and the circle if it's not too close from the body it's turning around // this prevents name overlapping (ie for jupiter satellites) float ang_dist = 300.f*atan(getEclipticPos().length()/getEquinoxEquatorialPos(core).length())/core->getMovementMgr()->getCurrentFov(); // if (ang_dist==0.f) ang_dist = 1.f; // if ang_dist == 0, the Planet is sun.. --> GZ: we can remove it. // by putting here, only draw orbit if Comet is visible for clarity drawOrbit(core); // TODO - fade in here also... if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitude(core)) { labelsFader=true; } else { labelsFader=false; } drawHints(core, planetNameFont); draw3dModel(core,transfo,screenSz); } // tails should also be drawn if core is off-screen... drawTail(core,transfo,true); // gas tail drawTail(core,transfo,false); // dust tail //Coma: this is just a fan disk tilted towards the observer;-) drawComa(core, transfo); return; }