예제 #1
0
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);
	}
예제 #2
0
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;
}
예제 #3
0
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);
	}
}
예제 #4
0
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;
}
예제 #5
0
// 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;
}