void PointerCoordinates::draw(StelCore *core) { if (!isEnabled()) return; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto); StelPainter sPainter(prj); sPainter.setColor(textColor[0], textColor[1], textColor[2], 1.f); font.setPixelSize(getFontSize()); sPainter.setFont(font); QPoint p = QCursor::pos(); // get screen coordinates of mouse cursor Vec3d mousePosition; float wh = prj->getViewportWidth()/2; // get half of width of the screen float hh = prj->getViewportHeight()/2; // get half of height of the screen float mx = p.x()-wh; // point 0 in center of the screen, axis X directed to right float my = p.y()-hh; // point 0 in center of the screen, axis Y directed to bottom // calculate position of mouse cursor via position of center of the screen (and invert axis Y) prj->unProject(prj->getViewportPosX()+wh+mx, prj->getViewportPosY()+hh+1-my, mousePosition); double dec_j2000, ra_j2000; StelUtils::rectToSphe(&ra_j2000,&dec_j2000,mousePosition); // Calculate RA/DE (J2000.0) and show it... QString coordsText = QString("%1/%2").arg(StelUtils::radToHmsStr(ra_j2000, true)).arg(StelUtils::radToDmsStr(dec_j2000, true)); sPainter.drawText(getCoordinatesPlace(coordsText).first, getCoordinatesPlace(coordsText).second, coordsText); }
//! Fill with black around viewport disc shape. static void drawViewportShape(StelRenderer* renderer, StelProjectorP projector) { if (projector->getMaskType() != StelProjector::MaskDisk) { return; } renderer->setBlendMode(BlendMode_None); renderer->setGlobalColor(0.0f, 0.0f, 0.0f); const float innerRadius = 0.5 * projector->getViewportFovDiameter(); const float outerRadius = projector->getViewportWidth() + projector->getViewportHeight(); Q_ASSERT_X(innerRadius >= 0.0f && outerRadius > innerRadius, Q_FUNC_INFO, "Inner radius must be at least zero and outer radius must be greater"); const float sweepAngle = 360.0f; static const int resolution = 192; float sinCache[resolution]; float cosCache[resolution]; const float deltaRadius = outerRadius - innerRadius; const int slices = resolution - 1; // Cache is the vertex locations cache for (int s = 0; s <= slices; s++) { const float angle = (M_PI * sweepAngle) / 180.0f * s / slices; sinCache[s] = std::sin(angle); cosCache[s] = std::cos(angle); } sinCache[slices] = sinCache[0]; cosCache[slices] = cosCache[0]; const float radiusHigh = outerRadius - deltaRadius; StelVertexBuffer<VertexP2>* vertices = renderer->createVertexBuffer<VertexP2>(PrimitiveType_TriangleStrip); const Vec2f center = projector->getViewportCenterAbsolute(); for (int i = 0; i <= slices; i++) { vertices->addVertex(VertexP2(center[0] + outerRadius * sinCache[i], center[1] + outerRadius * cosCache[i])); vertices->addVertex(VertexP2(center[0] + radiusHigh * sinCache[i], center[1] + radiusHigh * cosCache[i])); } vertices->lock(); renderer->setCulledFaces(CullFace_None); renderer->drawVertexBuffer(vertices); delete vertices; }
void PointerCoordinates::draw(StelCore *core) { if (!isEnabled()) return; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto); StelPainter sPainter(prj); sPainter.setColor(textColor[0], textColor[1], textColor[2], 1.f); font.setPixelSize(getFontSize()); sPainter.setFont(font); QPoint p = StelMainView::getInstance().getMousePos(); // get screen coordinates of mouse cursor Vec3d mousePosition; float wh = prj->getViewportWidth()/2.; // get half of width of the screen float hh = prj->getViewportHeight()/2.; // get half of height of the screen float mx = p.x()-wh; // point 0 in center of the screen, axis X directed to right float my = p.y()-hh; // point 0 in center of the screen, axis Y directed to bottom // calculate position of mouse cursor via position of center of the screen (and invert axis Y) // If coordinates are invalid, don't draw them. bool coordsValid=false; coordsValid = prj->unProject(prj->getViewportPosX()+wh+mx, prj->getViewportPosY()+hh+1-my, mousePosition); { // Nick Fedoseev patch Vec3d win; prj->project(mousePosition,win); float dx = prj->getViewportPosX()+wh+mx - win.v[0]; float dy = prj->getViewportPosY()+hh+1-my - win.v[1]; coordsValid = prj->unProject(prj->getViewportPosX()+wh+mx+dx, prj->getViewportPosY()+hh+1-my+dy, mousePosition); } if (!coordsValid) return; bool withDecimalDegree = StelApp::getInstance().getFlagShowDecimalDegrees(); bool useSouthAzimuth = StelApp::getInstance().getFlagSouthAzimuthUsage(); QString coordsSystem, cxt, cyt; double cx, cy; switch (getCurrentCoordinateSystem()) { case RaDecJ2000: { StelUtils::rectToSphe(&cx,&cy,mousePosition); // Calculate RA/DE (J2000.0) and show it... coordsSystem = qc_("RA/Dec (J2000.0)", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx, 5, false, true); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case RaDec: { StelUtils::rectToSphe(&cx,&cy,core->j2000ToEquinoxEqu(mousePosition)); // Calculate RA/DE and show it... coordsSystem = qc_("RA/Dec", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx, 5, false, true); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case AltAzi: { StelUtils::rectToSphe(&cy,&cx,core->j2000ToAltAz(mousePosition, StelCore::RefractionAuto)); float direction = 3.; // N is zero, E is 90 degrees if (useSouthAzimuth) direction = 2.; cy = direction*M_PI - cy; if (cy > M_PI*2) cy -= M_PI*2; coordsSystem = qc_("Az/Alt", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cy); cyt = StelUtils::radToDecDegStr(cx); } else { cxt = StelUtils::radToDmsStr(cy); cyt = StelUtils::radToDmsStr(cx); } break; } case Galactic: { StelUtils::rectToSphe(&cx,&cy,core->j2000ToGalactic(mousePosition)); // Calculate galactic position and show it... coordsSystem = qc_("Gal. Long/Lat", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToDmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case Ecliptic: { double lambda, beta; StelUtils::rectToSphe(&cx,&cy,core->j2000ToEquinoxEqu(mousePosition)); StelUtils::equToEcl(cx, cy, core->getCurrentPlanet()->getRotObliquity(core->getJDE()), &lambda, &beta); // Calculate ecliptic position and show it... if (lambda<0) lambda+=2.0*M_PI; coordsSystem = qc_("Ecl. Long/Lat", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(lambda); cyt = StelUtils::radToDecDegStr(beta); } else { cxt = StelUtils::radToDmsStr(lambda, true); cyt = StelUtils::radToDmsStr(beta, true); } break; } case EclipticJ2000: { double lambda, beta; StelUtils::rectToSphe(&cx,&cy, mousePosition); StelUtils::equToEcl(cx, cy, core->getCurrentPlanet()->getRotObliquity(2451545.0), &lambda, &beta); // Calculate ecliptic position and show it... if (lambda<0) lambda+=2.0*M_PI; coordsSystem = qc_("Ecl. Long/Lat (J2000.0)", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(lambda); cyt = StelUtils::radToDecDegStr(beta); } else { cxt = StelUtils::radToDmsStr(lambda, true); cyt = StelUtils::radToDmsStr(beta, true); } break; } case HourAngle: { Vec3d v = core->j2000ToAltAz(mousePosition, StelCore::RefractionAuto); StelUtils::rectToSphe(&cx,&cy,Mat4d::zrotation(-core->getLocalSiderealTime())*core->altAzToEquinoxEqu(v, StelCore::RefractionOff)); cx = 2.*M_PI-cx; coordsSystem = qc_("HA/Dec", "abbreviated in the plugin"); if (withDecimalDegree) { double ha_sidereal = cx*12/M_PI; if (ha_sidereal>24.) ha_sidereal -= 24.; cxt = QString("%1h").arg(ha_sidereal, 0, 'f', 5); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx); cyt = StelUtils::radToDmsStr(cy); } break; } } QString coordsText = QString("%1: %2/%3").arg(coordsSystem).arg(cxt).arg(cyt); sPainter.drawText(getCoordinatesPlace(coordsText).first, getCoordinatesPlace(coordsText).second, coordsText); }
//! Draw the sky grid in the current frame void SkyGrid::draw(const StelCore* core) const { const StelProjectorP prj = core->getProjection(frameType, frameType!=StelCore::FrameAltAz ? StelCore::RefractionAuto : StelCore::RefractionOff); if (!fader.getInterstate()) return; bool withDecimalDegree = dynamic_cast<StelGui*>(StelApp::getInstance().getGui())->getFlagShowDecimalDegrees(); // Look for all meridians and parallels intersecting with the disk bounding the viewport // Check whether the pole are in the viewport bool northPoleInViewport = false; bool southPoleInViewport = false; Vec3f win; if (prj->project(Vec3f(0,0,1), win) && prj->checkInViewport(win)) northPoleInViewport = true; if (prj->project(Vec3f(0,0,-1), win) && prj->checkInViewport(win)) southPoleInViewport = true; // Get the longitude and latitude resolution at the center of the viewport Vec3d centerV; prj->unProject(prj->getViewportPosX()+prj->getViewportWidth()/2, prj->getViewportPosY()+prj->getViewportHeight()/2+1, centerV); double lon2, lat2; StelUtils::rectToSphe(&lon2, &lat2, centerV); const double gridStepParallelRad = M_PI/180.*getClosestResolutionDMS(prj->getPixelPerRadAtCenter()); double gridStepMeridianRad; if (northPoleInViewport || southPoleInViewport) gridStepMeridianRad = (frameType==StelCore::FrameAltAz || frameType==StelCore::FrameGalactic) ? M_PI/180.* 10. : M_PI/180.* 15.; else { const double closetResLon = (frameType==StelCore::FrameAltAz || frameType==StelCore::FrameGalactic) ? getClosestResolutionDMS(prj->getPixelPerRadAtCenter()*std::cos(lat2)) : getClosestResolutionHMS(prj->getPixelPerRadAtCenter()*std::cos(lat2)); gridStepMeridianRad = M_PI/180.* ((northPoleInViewport || southPoleInViewport) ? 15. : closetResLon); } // Get the bounding halfspace const SphericalCap& viewPortSphericalCap = prj->getBoundingCap(); // Compute the first grid starting point. This point is close to the center of the screen // and lays at the intersection of a meridien and a parallel lon2 = gridStepMeridianRad*((int)(lon2/gridStepMeridianRad+0.5)); lat2 = gridStepParallelRad*((int)(lat2/gridStepParallelRad+0.5)); Vec3d firstPoint; StelUtils::spheToRect(lon2, lat2, firstPoint); firstPoint.normalize(); // Q_ASSERT(viewPortSphericalCap.contains(firstPoint)); // Initialize a painter and set openGL state StelPainter sPainter(prj); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode Vec4f textColor(color[0], color[1], color[2], 0); sPainter.setColor(color[0],color[1],color[2], fader.getInterstate()); textColor*=2; textColor[3]=fader.getInterstate(); sPainter.setFont(font); ViewportEdgeIntersectCallbackData userData(&sPainter); userData.textColor = textColor; userData.frameType = frameType; ///////////////////////////////////////////////// // Draw all the meridians (great circles) SphericalCap meridianSphericalCap(Vec3d(1,0,0), 0); Mat4d rotLon = Mat4d::zrotation(gridStepMeridianRad); Vec3d fpt = firstPoint; Vec3d p1, p2; int maxNbIter = (int)(M_PI/gridStepMeridianRad); int i; for (i=0; i<maxNbIter; ++i) { StelUtils::rectToSphe(&lon2, &lat2, fpt); userData.raAngle = lon2; meridianSphericalCap.n = fpt^Vec3d(0,0,1); meridianSphericalCap.n.normalize(); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) { if (viewPortSphericalCap.d<meridianSphericalCap.d && viewPortSphericalCap.contains(meridianSphericalCap.n)) { // The meridian is fully included in the viewport, draw it in 3 sub-arcs to avoid length > 180. const Mat4d& rotLon120 = Mat4d::rotation(meridianSphericalCap.n, 120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawGreatCircleArc(fpt, rotFpt, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(rotFpt, rotFpt2, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(rotFpt2, fpt, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } Vec3d middlePoint = p1+p2; middlePoint.normalize(); if (!viewPortSphericalCap.contains(middlePoint)) middlePoint*=-1.; // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg sPainter.drawGreatCircleArc(p1, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(p2, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } if (i!=maxNbIter) { rotLon = Mat4d::zrotation(-gridStepMeridianRad); fpt = firstPoint; fpt.transfo4d(rotLon); for (int j=0; j<maxNbIter-i; ++j) { StelUtils::rectToSphe(&lon2, &lat2, fpt); userData.raAngle = lon2; meridianSphericalCap.n = fpt^Vec3d(0,0,1); meridianSphericalCap.n.normalize(); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) break; Vec3d middlePoint = p1+p2; middlePoint.normalize(); if (!viewPortSphericalCap.contains(middlePoint)) middlePoint*=-1; sPainter.drawGreatCircleArc(p1, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(p2, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } } ///////////////////////////////////////////////// // Draw all the parallels (small circles) SphericalCap parallelSphericalCap(Vec3d(0,0,1), 0); rotLon = Mat4d::rotation(firstPoint^Vec3d(0,0,1), gridStepParallelRad); fpt = firstPoint; maxNbIter = (int)(M_PI/gridStepParallelRad)-1; for (i=0; i<maxNbIter; ++i) { StelUtils::rectToSphe(&lon2, &lat2, fpt); if (withDecimalDegree) userData.text = StelUtils::radToDecDegStr(lat2); else userData.text = StelUtils::radToDmsStrAdapt(lat2); parallelSphericalCap.d = fpt[2]; if (parallelSphericalCap.d>0.9999999) break; const Vec3d rotCenter(0,0,parallelSphericalCap.d); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, parallelSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<parallelSphericalCap.d && viewPortSphericalCap.contains(parallelSphericalCap.n)) || (viewPortSphericalCap.d<-parallelSphericalCap.d && viewPortSphericalCap.contains(-parallelSphericalCap.n))) { // The parallel is fully included in the viewport, draw it in 3 sub-arcs to avoid lengths >= 180 deg static const Mat4d rotLon120 = Mat4d::zrotation(120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawSmallCircleArc(fpt, rotFpt, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt, rotFpt2, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt2, fpt, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg Vec3d middlePoint = p1-rotCenter+p2-rotCenter; middlePoint.normalize(); middlePoint*=(p1-rotCenter).length(); middlePoint+=rotCenter; if (!viewPortSphericalCap.contains(middlePoint)) { middlePoint-=rotCenter; middlePoint*=-1.; middlePoint+=rotCenter; } sPainter.drawSmallCircleArc(p1, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(p2, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } if (i!=maxNbIter) { rotLon = Mat4d::rotation(firstPoint^Vec3d(0,0,1), -gridStepParallelRad); fpt = firstPoint; fpt.transfo4d(rotLon); for (int j=0; j<maxNbIter-i; ++j) { StelUtils::rectToSphe(&lon2, &lat2, fpt); if (withDecimalDegree) userData.text = StelUtils::radToDecDegStr(lat2); else userData.text = StelUtils::radToDmsStrAdapt(lat2); parallelSphericalCap.d = fpt[2]; const Vec3d rotCenter(0,0,parallelSphericalCap.d); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, parallelSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<parallelSphericalCap.d && viewPortSphericalCap.contains(parallelSphericalCap.n)) || (viewPortSphericalCap.d<-parallelSphericalCap.d && viewPortSphericalCap.contains(-parallelSphericalCap.n))) { // The parallel is fully included in the viewport, draw it in 3 sub-arcs to avoid lengths >= 180 deg static const Mat4d rotLon120 = Mat4d::zrotation(120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawSmallCircleArc(fpt, rotFpt, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt, rotFpt2, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt2, fpt, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg Vec3d middlePoint = p1-rotCenter+p2-rotCenter; middlePoint.normalize(); middlePoint*=(p1-rotCenter).length(); middlePoint+=rotCenter; if (!viewPortSphericalCap.contains(middlePoint)) { middlePoint-=rotCenter; middlePoint*=-1.; middlePoint+=rotCenter; } sPainter.drawSmallCircleArc(p1, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(p2, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } } }
// Find an object in a "clever" way, v in J2000 frame StelObjectP StelObjectMgr::cleverFind(const StelCore* core, const Vec3d& v) const { StelObjectP sobj; QList<StelObjectP> candidates; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000); // Field of view for a searchRadiusPixel pixel diameter circle on screen float fov_around = core->getMovementMgr()->getCurrentFov()/qMin(prj->getViewportWidth(), prj->getViewportHeight()) * searchRadiusPixel; // Collect the objects inside the range for (const auto* m : objectsModule) candidates += m->searchAround(v, fov_around, core); // GZ 2014-08-17: This should be exactly the sky's limit magnitude (or even more, but not less!), else visible stars cannot be clicked. float limitMag = core->getSkyDrawer()->getLimitMagnitude(); // -2.f; QList<StelObjectP> tmp; for (const auto& obj : candidates) { if (obj->getSelectPriority(core)<=limitMag) tmp.append(obj); } candidates = tmp; // Now select the object minimizing the function y = distance(in pixel) + magnitude Vec3d winpos; prj->project(v, winpos); float xpos = winpos[0]; float ypos = winpos[1]; float best_object_value; best_object_value = 100000.f; for (const auto& obj : candidates) { prj->project(obj->getJ2000EquatorialPos(core), winpos); float distance = std::sqrt((xpos-winpos[0])*(xpos-winpos[0]) + (ypos-winpos[1])*(ypos-winpos[1]))*distanceWeight; float priority = obj->getSelectPriority(core); // qDebug() << (*iter).getShortInfoString(core) << ": " << priority << " " << distance; if (distance + priority < best_object_value) { best_object_value = distance + priority; sobj = obj; } } return sobj; }
// 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; }
void Atmosphere::updateGrid(const StelProjectorP projector) { viewport = projector->getViewport(); const float viewportWidth = projector->getViewportWidth(); const float viewportHeight = projector->getViewportHeight(); const float aspectRatio = viewportWidth / viewportHeight; skyResolutionY = StelApp::getInstance() .getSettings() ->value("landscape/atmosphereybin", 44) .toInt(); const float resolutionX = skyResolutionY * 0.5 * sqrt(3.0) * aspectRatio; skyResolutionX = static_cast<int>(floor(0.5 + resolutionX)); const float stepX = viewportWidth / (skyResolutionX - 0.5); const float stepY = viewportHeight / skyResolutionY; const float viewportLeft = projector->getViewportPosX(); const float viewportBottom = projector->getViewportPosY(); vertexGrid->unlock(); vertexGrid->clear(); // Construct the vertex grid. for(int y = 0; y <= skyResolutionY; ++y) { const float yPos = viewportBottom + y * stepY; for (int x = 0; x <= skyResolutionX; ++x) { const float offset = (x == 0) ? 0.0f : (x == skyResolutionX) ? viewportWidth : (x - 0.5 * (y & 1)) * stepX; const float xPos = viewportLeft + offset; vertexGrid->addVertex(Vertex(Vec2f(xPos, yPos), Vec4f())); } } vertexGrid->lock(); // The grid is (resolutionX + 1) * (resolutionY + 1), // so the rows are for 0 to resolutionY-1 // The last row includes vertices in row resolutionY // Construct an index buffer for each row in the grid. for(int row = 0; row < skyResolutionY; ++row) { StelIndexBuffer* buffer; // Reuse previously used row index buffer. if(rowIndices.size() > row) { buffer = rowIndices[row]; buffer->unlock(); buffer->clear(); } // Add new row index buffer. else { buffer = renderer->createIndexBuffer(IndexType_U16); rowIndices.append(buffer); } uint g0 = row * (1 + skyResolutionX); uint g1 = (row + 1) * (1 + skyResolutionX); for (int col = 0; col <= skyResolutionX; ++col) { buffer->addIndex(g0++); buffer->addIndex(g1++); } buffer->lock(); Q_ASSERT_X(buffer->length() == (skyResolutionX + 1) * 2, Q_FUNC_INFO, "Unexpected grid row index buffer size"); } Q_ASSERT_X(rowIndices.size() >= skyResolutionY, Q_FUNC_INFO, "Not enough row index buffers"); }