Landscape.cpp   Landscape.cpp 
skipping to change at line 23 skipping to change at line 23
* 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.
* *
* 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 "Landscape.hpp" #include "Landscape.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelTextureMgr.hpp" #include "renderer/StelGeometryBuilder.hpp"
#include "renderer/StelRenderer.hpp"
#include "renderer/StelTextureNew.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "StelIniParser.hpp" #include "StelIniParser.hpp"
#include "StelLocation.hpp" #include "StelLocation.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelPainter.hpp"
#include <QDebug> #include <QDebug>
#include <QSettings> #include <QSettings>
#include <QVarLengthArray> #include <QVarLengthArray>
Landscape::Landscape(float _radius) : radius(_radius), skyBrightness(1.), n ightBrightness(0.8), angleRotateZOffset(0.) Landscape::Landscape(float _radius) : radius(_radius), skyBrightness(1.), n ightBrightness(0.8), angleRotateZOffset(0.)
{ {
validLandscape = 0; validLandscape = 0;
} }
skipping to change at line 143 skipping to change at line 144
} }
catch (std::runtime_error& e) catch (std::runtime_error& e)
{;} {;}
} }
#endif #endif
path = StelFileMgr::findFile("textures/" + basename); path = StelFileMgr::findFile("textures/" + basename);
return path; return path;
} }
} }
LandscapeOldStyle::LandscapeOldStyle(float _radius) : Landscape(_radius), s LandscapeOldStyle::LandscapeOldStyle(float _radius)
ideTexs(NULL), sides(NULL), tanMode(false), calibrated(false) : Landscape(_radius)
, sideTexs(NULL)
, texturesInitialized(false)
, sides(NULL)
, fogTex(NULL)
, groundTex(NULL)
, tanMode(false)
, calibrated(false)
, fogCylinderBuffer(NULL)
// Way off to ensure the height is detected as "changed" on the firs
t drawFog() call.
, previousFogHeight(-1000.0f)
, groundFanDisk(NULL)
, groundFanDiskIndices(NULL)
{} {}
LandscapeOldStyle::~LandscapeOldStyle() LandscapeOldStyle::~LandscapeOldStyle()
{ {
if (sideTexs) if (NULL != sideTexs)
{ {
if(texturesInitialized)
{
for(int i = 0; i < nbSideTexs; ++i)
{
delete sideTexs[i].texture;
}
}
delete [] sideTexs; delete [] sideTexs;
sideTexs = NULL; sideTexs = NULL;
} }
if (sides) delete [] sides; if(NULL != fogTex)
{
delete fogTex;
fogTex = NULL;
}
if(NULL != groundTex)
{
delete groundTex;
groundTex = NULL;
}
if (NULL != fogCylinderBuffer)
{
delete fogCylinderBuffer;
fogCylinderBuffer = NULL;
}
if (NULL != groundFanDisk)
{
Q_ASSERT_X(NULL != groundFanDiskIndices, Q_FUNC_INFO,
"Vertex buffer is generated but index buffer is n
ot");
delete groundFanDisk;
groundFanDisk = NULL;
delete groundFanDiskIndices;
groundFanDiskIndices = NULL;
}
if (NULL != sides)
{
delete [] sides;
sides = NULL;
}
for(int side = 0; side < precomputedSides.length(); ++side)
{
delete precomputedSides[side].vertices;
delete precomputedSides[side].indices;
}
precomputedSides.clear();
} }
void LandscapeOldStyle::load(const QSettings& landscapeIni, const QString& landscapeId) void LandscapeOldStyle::load(const QSettings& landscapeIni, const QString& landscapeId)
{ {
// TODO: put values into hash and call create method to consolidate code // TODO: put values into hash and call create method to consolidate code
loadCommon(landscapeIni, landscapeId); loadCommon(landscapeIni, landscapeId);
if (landscapeIni.contains("landscape/tesselate_rows")) if (landscapeIni.contains("landscape/tesselate_rows"))
rows = landscapeIni.value("landscape/tesselate_rows").toInt( ); rows = landscapeIni.value("landscape/tesselate_rows").toInt( );
else rows=8; else rows=8;
skipping to change at line 180 skipping to change at line 240
if(type != "old_style") if(type != "old_style")
{ {
qWarning() << "Landscape type mismatch for landscape " << la ndscapeId qWarning() << "Landscape type mismatch for landscape " << la ndscapeId
<< ", expected old_style, found " << type << ". No landscape in use."; << ", expected old_style, found " << type << ". No landscape in use.";
validLandscape = 0; validLandscape = 0;
return; return;
} }
// Load sides textures // Load sides textures
nbSideTexs = landscapeIni.value("landscape/nbsidetex", 0).toInt(); nbSideTexs = landscapeIni.value("landscape/nbsidetex", 0).toInt();
sideTexs = new StelTextureSP[nbSideTexs]; sideTexs = new SideTexture[nbSideTexs];
for (int i=0; i<nbSideTexs; ++i) for (int i=0; i<nbSideTexs; ++i)
{ {
QString textureKey = QString("landscape/tex%1").arg(i); QString textureKey = QString("landscape/tex%1").arg(i);
QString textureName = landscapeIni.value(textureKey).toStrin g(); QString textureName = landscapeIni.value(textureKey).toStrin g();
const QString texturePath = getTexturePath(textureName, land sideTexs[i].path = getTexturePath(textureName, landscapeId);
scapeId); // Will be lazily initialized
sideTexs[i] = StelApp::getInstance().getTextureManager().cre sideTexs[i].texture = NULL;
ateTexture(texturePath);
} }
QMap<int, int> texToSide;
// Init sides parameters // Init sides parameters
nbSide = landscapeIni.value("landscape/nbside", 0).toInt(); nbSide = landscapeIni.value("landscape/nbside", 0).toInt();
sides = new landscapeTexCoord[nbSide]; sides = new landscapeTexCoord[nbSide];
int texnum; int texnum;
for (int i=0;i<nbSide;++i) for (int i=0;i<nbSide;++i)
{ {
QString key = QString("landscape/side%1").arg(i); QString key = QString("landscape/side%1").arg(i);
QString description = landscapeIni.value(key).toString(); QString description = landscapeIni.value(key).toString();
//sscanf(s.toLocal8Bit(),"tex%d:%f:%f:%f:%f",&texnum,&a,&b,& c,&d); //sscanf(s.toLocal8Bit(),"tex%d:%f:%f:%f:%f",&texnum,&a,&b,& c,&d);
QStringList parameters = description.split(':'); QStringList parameters = description.split(':');
//TODO: How should be handled an invalid texture description ? //TODO: How should be handled an invalid texture description ?
QString textureName = parameters.value(0); QString textureName = parameters.value(0);
texnum = textureName.right(textureName.length() - 3).toInt() ; texnum = textureName.right(textureName.length() - 3).toInt() ;
sides[i].tex = sideTexs[texnum];
sides[i].texCoords[0] = parameters.at(1).toFloat(); sides[i].texCoords[0] = parameters.at(1).toFloat();
sides[i].texCoords[1] = parameters.at(2).toFloat(); sides[i].texCoords[1] = parameters.at(2).toFloat();
sides[i].texCoords[2] = parameters.at(3).toFloat(); sides[i].texCoords[2] = parameters.at(3).toFloat();
sides[i].texCoords[3] = parameters.at(4).toFloat(); sides[i].texCoords[3] = parameters.at(4).toFloat();
//qDebug() << i << texnum << sides[i].texCoords[0] << sides[ i].texCoords[1] << sides[i].texCoords[2] << sides[i].texCoords[3]; //qDebug() << i << texnum << sides[i].texCoords[0] << sides[ i].texCoords[1] << sides[i].texCoords[2] << sides[i].texCoords[3];
// Prior to precomputing the sides, we used to match E to si de0 // Prior to precomputing the sides, we used to match E to si de0
// in r4598 the precomputing was put in place and caused a p roblem for // in r4598 the precomputing was put in place and caused a p roblem for
// old_style landscapes which had a z rotation on the side t extures // old_style landscapes which had a z rotation on the side t extures
// and where side0 did not map to tex0 // and where side0 did not map to tex0
// texToSide is a nasty hack to replace the old behaviour // texToSide is a nasty hack to replace the old behaviour
texToSide[i] = texnum; texToSide[i] = texnum;
} }
nbDecorRepeat = landscapeIni.value("landscape/nb_decor_repeat", 1).t oInt(); nbDecorRepeat = landscapeIni.value("landscape/nb_decor_repeat", 1).t oInt();
QString groundTexName = landscapeIni.value("landscape/groundtex").to String(); QString groundTexName = landscapeIni.value("landscape/groundtex").to String();
QString groundTexPath = getTexturePath(groundTexName, landscapeId); groundTexPath = getTexturePath(groundTexName, landscapeId);
groundTex = StelApp::getInstance().getTextureManager().createTexture
(groundTexPath, StelTexture::StelTextureParams(true));
QString description = landscapeIni.value("landscape/ground").toStrin g(); QString description = landscapeIni.value("landscape/ground").toStrin g();
//sscanf(description.toLocal8Bit(),"groundtex:%f:%f:%f:%f",&a,&b,&c, &d); //sscanf(description.toLocal8Bit(),"groundtex:%f:%f:%f:%f",&a,&b,&c, &d);
QStringList parameters = description.split(':'); QStringList parameters = description.split(':');
groundTexCoord.tex = groundTex;
groundTexCoord.texCoords[0] = parameters.at(1).toFloat(); groundTexCoord.texCoords[0] = parameters.at(1).toFloat();
groundTexCoord.texCoords[1] = parameters.at(2).toFloat(); groundTexCoord.texCoords[1] = parameters.at(2).toFloat();
groundTexCoord.texCoords[2] = parameters.at(3).toFloat(); groundTexCoord.texCoords[2] = parameters.at(3).toFloat();
groundTexCoord.texCoords[3] = parameters.at(4).toFloat(); groundTexCoord.texCoords[3] = parameters.at(4).toFloat();
QString fogTexName = landscapeIni.value("landscape/fogtex").toString (); QString fogTexName = landscapeIni.value("landscape/fogtex").toString ();
QString fogTexPath = getTexturePath(fogTexName, landscapeId); fogTexPath = getTexturePath(fogTexName, landscapeId);
fogTex = StelApp::getInstance().getTextureManager().createTexture(fo
gTexPath, StelTexture::StelTextureParams(true, GL_LINEAR, GL_REPEAT));
description = landscapeIni.value("landscape/fog").toString(); description = landscapeIni.value("landscape/fog").toString();
//sscanf(description.toLocal8Bit(),"fogtex:%f:%f:%f:%f",&a,&b,&c,&d) ; //sscanf(description.toLocal8Bit(),"fogtex:%f:%f:%f:%f",&a,&b,&c,&d) ;
parameters = description.split(':'); parameters = description.split(':');
fogTexCoord.tex = fogTex;
fogTexCoord.texCoords[0] = parameters.at(1).toFloat(); fogTexCoord.texCoords[0] = parameters.at(1).toFloat();
fogTexCoord.texCoords[1] = parameters.at(2).toFloat(); fogTexCoord.texCoords[1] = parameters.at(2).toFloat();
fogTexCoord.texCoords[2] = parameters.at(3).toFloat(); fogTexCoord.texCoords[2] = parameters.at(3).toFloat();
fogTexCoord.texCoords[3] = parameters.at(4).toFloat(); fogTexCoord.texCoords[3] = parameters.at(4).toFloat();
fogAltAngle = landscapeIni.value("landscape/fog_alt_angle", 0 .).toFloat(); fogAltAngle = landscapeIni.value("landscape/fog_alt_angle", 0 .).toFloat();
fogAngleShift = landscapeIni.value("landscape/fog_angle_shift", 0.).toFloat(); fogAngleShift = landscapeIni.value("landscape/fog_angle_shift", 0.).toFloat();
decorAltAngle = landscapeIni.value("landscape/decor_alt_angle", 0.).toFloat(); decorAltAngle = landscapeIni.value("landscape/decor_alt_angle", 0.).toFloat();
decorAngleShift = landscapeIni.value("landscape/decor_angle_shift ", 0.).toFloat(); decorAngleShift = landscapeIni.value("landscape/decor_angle_shift ", 0.).toFloat();
angleRotateZ = landscapeIni.value("landscape/decor_angle_rotat ez", 0.).toFloat(); angleRotateZ = landscapeIni.value("landscape/decor_angle_rotat ez", 0.).toFloat();
groundAngleShift = landscapeIni.value("landscape/ground_angle_shif t", 0.).toFloat(); groundAngleShift = landscapeIni.value("landscape/ground_angle_shif t", 0.).toFloat();
groundAngleRotateZ = landscapeIni.value("landscape/ground_angle_rota tez", 0.).toFloat(); groundAngleRotateZ = landscapeIni.value("landscape/ground_angle_rota tez", 0.).toFloat();
drawGroundFirst = landscapeIni.value("landscape/draw_ground_first ", 0).toInt(); drawGroundFirst = landscapeIni.value("landscape/draw_ground_first ", 0).toInt();
tanMode = landscapeIni.value("landscape/tan_mode", false) .toBool(); tanMode = landscapeIni.value("landscape/tan_mode", false) .toBool();
calibrated = landscapeIni.value("landscape/calibrated", fals e).toBool(); calibrated = landscapeIni.value("landscape/calibrated", fals e).toBool();
}
// Precompute the vertex arrays for ground display void LandscapeOldStyle::draw(StelCore* core, StelRenderer* renderer)
// Make slices_per_side=(3<<K) so that the innermost polygon of the {
fandisk becomes a triangle: if (!validLandscape) {return;}
int slices_per_side = 3*64/(nbDecorRepeat*nbSide);
if (slices_per_side<=0)
slices_per_side = 1;
// draw a fan disk instead of a ordinary disk to that the inner slic lazyInitTextures(renderer);
es renderer->setBlendMode(BlendMode_Alpha);
// are not so slender. When they are too slender, culling errors occ StelProjectorP projector =
ur core->getProjection(StelCore::FrameAltAz, StelCore::Refracti
// in cylinder projection mode. onOff);
int slices_inside = nbSide*slices_per_side*nbDecorRepeat;
int level = 0; renderer->setCulledFaces(CullFace_Back);
while ((slices_inside&1)==0 && slices_inside > 4) if (drawGroundFirst) {drawGround(core, renderer);}
drawDecor(core, renderer);
if (!drawGroundFirst) {drawGround(core, renderer);}
drawFog(core, renderer);
renderer->setCulledFaces(CullFace_None);
}
// Draw the horizon fog
void LandscapeOldStyle::drawFog(StelCore* core, StelRenderer* renderer)
{
if (!fogFader.getInterstate()) {return;}
const float vpos = radius * ((tanMode || calibrated)
? std::tan(fogAngleShift * M_PI / 180.0)
: std::sin(fogAngleShift * M_PI / 180.0));
StelProjector::ModelViewTranformP transform =
core->getAltAzModelViewTransform(StelCore::RefractionOff);
transform->combine(Mat4d::translation(Vec3d(0.,0.,vpos)));
StelProjectorP projector = core->getProjection(transform);
renderer->setBlendMode(BlendMode_Add);
const float nightModeFilter =
StelApp::getInstance().getVisionModeNight() ? 0.f : 1.f;
const float intensity = fogFader.getInterstate() * (0.1f + 0.1f * sk
yBrightness);
const float filteredIntensity = intensity * nightModeFilter;
renderer->setGlobalColor(intensity, filteredIntensity, filteredInten
sity);
fogTex->bind();
const float height = (tanMode || calibrated)
? radius * std::tan(fogAltAngle * M_PI / 180.f)
: radius * std::sin(fogAltAngle * M_PI / 180.f);
if(std::fabs(height - previousFogHeight) > 0.01)
{ {
++level; // Height has changed, need to regenerate the buffer.
slices_inside>>=1; delete fogCylinderBuffer;
fogCylinderBuffer = NULL;
previousFogHeight = height;
}
if(NULL == fogCylinderBuffer)
{
fogCylinderBuffer = renderer->createVertexBuffer<VertexP3T2>
(PrimitiveType_TriangleStrip);
StelGeometryBuilder().buildCylinder(fogCylinderBuffer, radiu
s, height, 64, true);
}
renderer->drawVertexBuffer(fogCylinderBuffer, NULL, projector);
renderer->setBlendMode(BlendMode_Alpha);
}
void LandscapeOldStyle::lazyInitTextures(StelRenderer* renderer)
{
if(texturesInitialized){return;}
for (int i = 0; i < nbSideTexs; ++i)
{
sideTexs[i].texture = renderer->createTexture(sideTexs[i].pa
th);
} }
StelPainter::computeFanDisk(radius, slices_inside, level, groundVert for (int i=0;i<nbSide;++i)
exArr, groundTexCoordArr); {
sides[i].tex = sideTexs[i].texture;
}
fogTex = renderer->createTexture(fogTexPath,
TextureParams().generateMipmap
s().wrap(TextureWrap_Repeat));
fogTexCoord.tex = fogTex;
groundTex = renderer->createTexture(groundTexPath, TextureParams().g
enerateMipmaps());
groundTexCoord.tex = groundTex;
texturesInitialized = true;
}
void LandscapeOldStyle::generatePrecomputedSides(StelRenderer* renderer)
{
// Make slicesPerSide=(3<<K) so that the innermost polygon of the fa
ndisk becomes a triangle:
const int slicesPerSide = std::max(1, 3 * 64 / (nbDecorRepeat * nbSi
de));
// Precompute the vertex arrays for side display // Precompute the vertex arrays for side display
static const int stacks = (calibrated ? 16 : 8); // GZ: 8->16, I nee d better precision. static const int stacks = (calibrated ? 16 : 8); // GZ: 8->16, I nee d better precision.
const double z0 = calibrated ? const double z0 = calibrated ?
// GZ: For calibrated, we use z=decorAngleShift...(decorAltAngle-dec orAngleShift), but we must compute the tan in the loop. // GZ: For calibrated, we use z=decorAngleShift...(decorAltAngle-dec orAngleShift), but we must compute the tan in the loop.
decorAngleShift : (tanMode ? radius * std::tan(decorAngleShift*M_PI/ 180.f) : radius * std::sin(decorAngleShift*M_PI/180.f)); decorAngleShift : (tanMode ? radius * std::tan(decorAngleShift*M_PI/ 180.f) : radius * std::sin(decorAngleShift*M_PI/180.f));
// GZ: The old formula is completely meaningless for photos with ope ning angle >90, // GZ: The old formula is completely meaningless for photos with ope ning angle >90,
// and most likely also not what was intended for other images. // and most likely also not what was intended for other images.
// Note that GZ fills this value with a different meaning! // Note that GZ fills this value with a different meaning!
const double d_z = calibrated ? decorAltAngle/stacks : (tanMode ? ra dius*std::tan(decorAltAngle*M_PI/180.f)/stacks : radius*std::sin(decorAltAn gle*M_PI/180.0)/stacks); const double d_z = calibrated ? decorAltAngle/stacks : (tanMode ? ra dius*std::tan(decorAltAngle*M_PI/180.f)/stacks : radius*std::sin(decorAltAn gle*M_PI/180.0)/stacks);
const float alpha = 2.f*M_PI/(nbDecorRepeat*nbSide*slices_per_side); const float alpha = 2.f * M_PI / (nbDecorRepeat * nbSide * slicesPer Side);
const float ca = std::cos(alpha); const float ca = std::cos(alpha);
const float sa = std::sin(alpha); const float sa = std::sin(alpha);
float y0 = radius*std::cos(angleRotateZ*M_PI/180.f); float y0 = radius*std::cos(angleRotateZ*M_PI/180.f);
float x0 = radius*std::sin(angleRotateZ*M_PI/180.f); float x0 = radius*std::sin(angleRotateZ*M_PI/180.f);
LOSSide precompSide; LOSSide precompSide;
precompSide.arr.primitiveType=StelVertexArray::Triangles; for (int n = 0; n < nbDecorRepeat; n++)
for (int n=0;n<nbDecorRepeat;n++)
{ {
for (int i=0;i<nbSide;i++) for (int i = 0; i < nbSide; i++)
{ {
int ti; if (!texToSide.contains(i))
if (texToSide.contains(i))
ti = texToSide[i];
else
{ {
qDebug() << QString("LandscapeOldStyle::load ERROR: found no corresponding tex value for side%1").arg(i); qDebug() << QString("LandscapeOldStyle::load ERROR: found no corresponding tex value for side%1").arg(i);
break; break;
} }
precompSide.arr.vertex.resize(0);
precompSide.arr.texCoords.resize(0); const int ti = texToSide[i];
precompSide.arr.indices.resize(0); precompSide.vertices =
precompSide.tex=sideTexs[ti]; renderer->createVertexBuffer<VertexP3T2>(Pri
mitiveType_Triangles);
precompSide.indices = renderer->createIndexBuffer(In
dexType_U16);
precompSide.tex = sideTexs[ti].texture;
float tx0 = sides[ti].texCoords[0]; float tx0 = sides[ti].texCoords[0];
const float d_tx0 = (sides[ti].texCoords[2]-sides[ti const float d_tx0 = (sides[ti].texCoords[2] - sides[
].texCoords[0]) / slices_per_side; ti].texCoords[0]) / slicesPerSide;
const float d_ty = (sides[ti].texCoords[3]-sides[ti] const float d_ty = (sides[ti].texCoords[3] - sides[
.texCoords[1]) / stacks; ti].texCoords[1]) / stacks;
for (int j=0;j<slices_per_side;j++) for (int j = 0; j < slicesPerSide; j++)
{ {
const float y1 = y0*ca - x0*sa; const float y1 = y0 * ca - x0 * sa;
const float x1 = y0*sa + x0*ca; const float x1 = y0 * sa + x0 * ca;
const float tx1 = tx0 + d_tx0; const float tx1 = tx0 + d_tx0;
float z = z0;
float z = z0;
float ty0 = sides[ti].texCoords[1]; float ty0 = sides[ti].texCoords[1];
for (int k=0;k<=stacks*2;k+=2)
for (int k = 0; k <= stacks * 2; k += 2)
{ {
precompSide.arr.texCoords << Vec2f(t
x0, ty0) << Vec2f(tx1, ty0); const float calibratedZ =
if (calibrated) calibrated ? radius * std::t
{ an(z * M_PI / 180.0f) : z;
float tanZ=radius * std::tan precompSide.vertices->addVertex
(z*M_PI/180.f); (VertexP3T2(Vec3f(x0, y0, ca
precompSide.arr.vertex << Ve libratedZ), Vec2f(tx0, ty0)));
c3d(x0, y0, tanZ) << Vec3d(x1, y1, tanZ); precompSide.vertices->addVertex
} else (VertexP3T2(Vec3f(x1, y1, ca
{ libratedZ), Vec2f(tx1, ty0)));
precompSide.arr.vertex << Ve z += d_z;
c3d(x0, y0, z) << Vec3d(x1, y1, z);
}
z += d_z;
ty0 += d_ty; ty0 += d_ty;
} }
unsigned int offset = j*(stacks+1)*2; const uint offset = j*(stacks+1)*2;
for (int k = 2;k<stacks*2+2;k+=2) for (int k = 2; k < stacks * 2 + 2; k += 2)
{ {
precompSide.arr.indices << offset+k- precompSide.indices->addIndex(offset
2 << offset+k-1 << offset+k; + k - 2);
precompSide.arr.indices << offset+k precompSide.indices->addIndex(offset
<< offset+k-1 << offset+k+1; + k - 1);
precompSide.indices->addIndex(offset
+ k);
precompSide.indices->addIndex(offset
+ k);
precompSide.indices->addIndex(offset
+ k - 1);
precompSide.indices->addIndex(offset
+ k + 1);
} }
y0 = y1; y0 = y1;
x0 = x1; x0 = x1;
tx0 = tx1; tx0 = tx1;
} }
precompSide.vertices->lock();
precompSide.indices->lock();
precomputedSides.append(precompSide); precomputedSides.append(precompSide);
} }
} }
} }
void LandscapeOldStyle::draw(StelCore* core)
{
StelPainter painter(core->getProjection(StelCore::FrameAltAz, StelCo
re::RefractionOff));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
painter.enableTexture2d(true);
glEnable(GL_CULL_FACE);
if (!validLandscape)
return;
if (drawGroundFirst)
drawGround(core, painter);
drawDecor(core, painter);
if (!drawGroundFirst)
drawGround(core, painter);
drawFog(core, painter);
}
// Draw the horizon fog
void LandscapeOldStyle::drawFog(StelCore* core, StelPainter& sPainter) cons
t
{
if (!fogFader.getInterstate())
return;
const float vpos = (tanMode||calibrated) ? radius*std::tan(fogAngleS
hift*M_PI/180.) : radius*std::sin(fogAngleShift*M_PI/180.);
StelProjector::ModelViewTranformP transfo = core->getAltAzModelViewT
ransform(StelCore::RefractionOff);
transfo->combine(Mat4d::translation(Vec3d(0.,0.,vpos)));
sPainter.setProjector(core->getProjection(transfo));
glBlendFunc(GL_ONE, GL_ONE);
const float nightModeFilter = StelApp::getInstance().getVisionModeNi
ght() ? 0.f : 1.f;
sPainter.setColor(fogFader.getInterstate()*(0.1f+0.1f*skyBrightness)
,
fogFader.getInterstate()*(0.1f+0.1f*skyBrightness)
*nightModeFilter,
fogFader.getInterstate()*(0.1f+0.1f*skyBrightness)
*nightModeFilter);
fogTex->bind();
const float height = (tanMode||calibrated) ? radius*std::tan(fogAltA
ngle*M_PI/180.) : radius*std::sin(fogAltAngle*M_PI/180.);
sPainter.sCylinder(radius, height, 64, 1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
// Draw the mountains with a few pieces of texture // Draw the mountains with a few pieces of texture
void LandscapeOldStyle::drawDecor(StelCore* core, StelPainter& sPainter) co nst void LandscapeOldStyle::drawDecor(StelCore* core, StelRenderer* renderer)
{ {
if (!landFader.getInterstate()) {return;}
// Patched by Georg Zotti: I located an undocumented switch tan_mode , maybe tan_mode=true means cylindrical panorama projection. // Patched by Georg Zotti: I located an undocumented switch tan_mode , maybe tan_mode=true means cylindrical panorama projection.
// anyway, the old code makes unfortunately no sense. // anyway, the old code makes unfortunately no sense.
// I added a switch "calibrated" for the ini file. If true, it works as this landscape apparently was originally intended. // I added a switch "calibrated" for the ini file. If true, it works as this landscape apparently was originally intended.
// So I corrected the texture coordinates so that decorAltAngle is t he total angle, decorAngleShift the lower angle, // So I corrected the texture coordinates so that decorAltAngle is t he total angle, decorAngleShift the lower angle,
// and the texture in between is correctly stretched. // and the texture in between is correctly stretched.
// TODO: (1) Replace fog cylinder by similar texture, which could be painted as image layer in Photoshop/Gimp. // TODO: (1) Replace fog cylinder by similar texture, which could be painted as image layer in Photoshop/Gimp.
// (2) Implement calibrated && tan_mode // (2) Implement calibrated && tan_mode
StelProjector::ModelViewTranformP transfo = core->getAltAzModelViewT StelProjector::ModelViewTranformP transform =
ransform(StelCore::RefractionOff); core->getAltAzModelViewTransform(StelCore::RefractionOff);
transfo->combine(Mat4d::zrotation(-angleRotateZOffset*M_PI/180.f)); transform->combine(Mat4d::zrotation(-angleRotateZOffset*M_PI/180.f))
;
StelProjectorP projector = core->getProjection(transform);
sPainter.setProjector(core->getProjection(transfo)); const Vec4f color = StelApp::getInstance().getVisionModeNight()
? Vec4f(skyBrightness*nightBrightness, 0.0, 0.0, l
andFader.getInterstate())
: Vec4f(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
renderer->setGlobalColor(color);
if (!landFader.getInterstate()) // Lazily generate decoration sides.
return; if(precomputedSides.empty())
if (StelApp::getInstance().getVisionModeNight()) {
sPainter.setColor(skyBrightness*nightBrightness, 0.0, 0.0, l generatePrecomputedSides(renderer);
andFader.getInterstate()); }
else
sPainter.setColor(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
// Draw decoration sides.
foreach (const LOSSide& side, precomputedSides) foreach (const LOSSide& side, precomputedSides)
{ {
side.tex->bind(); side.tex->bind();
sPainter.drawSphericalTriangles(side.arr, true, NULL, false) ; renderer->drawVertexBuffer(side.vertices, side.indices, proj ector);
} }
} }
void LandscapeOldStyle::generateGroundFanDisk(StelRenderer* renderer)
{
// Precompute the vertex buffer for ground display
// Make slicesPerSide = (3<<K) so that the
// innermost polygon of the fandisk becomes a triangle:
int slicesPerSide = std::max(1, 3 * 64 / (nbDecorRepeat * nbSide));
// draw a fan disk instead of a ordinary disk so that the inner slic
es
// are not so slender. When they are too slender, culling errors occ
ur
// in cylinder projection mode.
int slicesInside = nbSide * slicesPerSide * nbDecorRepeat;
int level = 0;
while ((slicesInside & 1) == 0 && slicesInside > 4)
{
++level;
slicesInside >>= 1;
}
groundFanDisk = renderer->createVertexBuffer<VertexP3T2>(PrimitiveTy
pe_Triangles);
groundFanDiskIndices = renderer->createIndexBuffer(IndexType_U16);
StelGeometryBuilder()
.buildFanDisk(groundFanDisk, groundFanDiskIndices, radius, s
licesInside, level);
}
// Draw the ground // Draw the ground
void LandscapeOldStyle::drawGround(StelCore* core, StelPainter& sPainter) c onst void LandscapeOldStyle::drawGround(StelCore* core, StelRenderer* renderer)
{ {
if (!landFader.getInterstate()) if (!landFader.getInterstate()) {return;}
return;
const float vshift = (tanMode || calibrated) ? const float vshift = (tanMode || calibrated)
radius*std::tan(groundAngleShift*M_PI/180.) : ? radius * std::tan(groundAngleShift * M_PI / 180
radius*std::sin(groundAngleShift*M_PI/180.); .0f)
StelProjector::ModelViewTranformP transfo = core->getAltAzModelViewT : radius * std::sin(groundAngleShift * M_PI / 180
ransform(StelCore::RefractionOff); .0f);
transfo->combine(Mat4d::zrotation((groundAngleRotateZ-angleRotateZOf
fset)*M_PI/180.f) * Mat4d::translation(Vec3d(0,0,vshift))); StelProjector::ModelViewTranformP transform =
core->getAltAzModelViewTransform(StelCore::RefractionOff);
sPainter.setProjector(core->getProjection(transfo)); transform->combine
if (StelApp::getInstance().getVisionModeNight()) (Mat4d::zrotation((groundAngleRotateZ - angleRotateZOffset)
sPainter.setColor(skyBrightness*nightBrightness, 0.0, 0.0, l * M_PI / 180.0f) *
andFader.getInterstate()); Mat4d::translation(Vec3d(0.0, 0.0, vshift)));
else
sPainter.setColor(skyBrightness, skyBrightness, skyBrightnes StelProjectorP projector = core->getProjection(transform);
s, landFader.getInterstate());
const Vec4f color = StelApp::getInstance().getVisionModeNight()
? Vec4f(skyBrightness*nightBrightness, 0.0, 0.0, l
andFader.getInterstate())
: Vec4f(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
renderer->setGlobalColor(color);
groundTex->bind(); groundTex->bind();
sPainter.setArrays((Vec3d*)groundVertexArr.constData(), (Vec2f*)grou
ndTexCoordArr.constData()); // Lazily generate the ground fan disk.
sPainter.drawFromArray(StelPainter::Triangles, groundVertexArr.size( if(NULL == groundFanDisk)
)/3); {
Q_ASSERT_X(NULL == groundFanDiskIndices, Q_FUNC_INFO,
"Vertex buffer is NULL but index buffer is alread
y generated");
generateGroundFanDisk(renderer);
}
// Draw the ground.
renderer->drawVertexBuffer(groundFanDisk, groundFanDiskIndices, proj
ector);
} }
LandscapeFisheye::LandscapeFisheye(float _radius) : Landscape(_radius) LandscapeFisheye::LandscapeFisheye(float _radius)
: Landscape(_radius)
, mapTex(NULL)
, fisheyeSphere(NULL)
{} {}
LandscapeFisheye::~LandscapeFisheye() LandscapeFisheye::~LandscapeFisheye()
{ {
if(NULL != fisheyeSphere)
{
delete fisheyeSphere;
}
if(NULL != mapTex)
{
delete mapTex;
}
} }
void LandscapeFisheye::load(const QSettings& landscapeIni, const QString& l andscapeId) void LandscapeFisheye::load(const QSettings& landscapeIni, const QString& l andscapeId)
{ {
loadCommon(landscapeIni, landscapeId); loadCommon(landscapeIni, landscapeId);
QString type = landscapeIni.value("landscape/type").toString(); QString type = landscapeIni.value("landscape/type").toString();
if(type != "fisheye") if(type != "fisheye")
{ {
qWarning() << "Landscape type mismatch for landscape "<< lan dscapeId << ", expected fisheye, found " << type << ". No landscape in use .\n"; qWarning() << "Landscape type mismatch for landscape "<< lan dscapeId << ", expected fisheye, found " << type << ". No landscape in use .\n";
skipping to change at line 467 skipping to change at line 613
landscapeIni.value("landscape/texturefov", 360).toFloat(), landscapeIni.value("landscape/texturefov", 360).toFloat(),
landscapeIni.value("landscape/angle_rotatez", 0.).toFloat()) ; landscapeIni.value("landscape/angle_rotatez", 0.).toFloat()) ;
} }
// create a fisheye landscape from basic parameters (no ini file needed) // create a fisheye landscape from basic parameters (no ini file needed)
void LandscapeFisheye::create(const QString _name, const QString& _maptex, float atexturefov, float aangleRotateZ) void LandscapeFisheye::create(const QString _name, const QString& _maptex, float atexturefov, float aangleRotateZ)
{ {
// qDebug() << _name << " " << _fullpath << " " << _maptex << " " << _texturefov; // qDebug() << _name << " " << _fullpath << " " << _maptex << " " << _texturefov;
validLandscape = 1; // assume ok... validLandscape = 1; // assume ok...
name = _name; name = _name;
mapTex = StelApp::getInstance().getTextureManager().createTexture(_m aptex, StelTexture::StelTextureParams(true)); mapTexPath = _maptex;
texFov = atexturefov*M_PI/180.f; texFov = atexturefov*M_PI/180.f;
angleRotateZ = aangleRotateZ*M_PI/180.f; angleRotateZ = aangleRotateZ*M_PI/180.f;
const SphereParams params = SphereParams(radius).resolution(cols, ro
ws).orientInside();
fisheyeSphere = StelGeometryBuilder().buildSphereFisheye(params, tex
Fov);
} }
void LandscapeFisheye::draw(StelCore* core) void LandscapeFisheye::draw(StelCore* core, StelRenderer* renderer)
{ {
if(!validLandscape) return; if(!validLandscape) return;
if(!landFader.getInterstate()) return; if(!landFader.getInterstate()) return;
StelProjector::ModelViewTranformP transfo = core->getAltAzModelViewT if(NULL == mapTex)
ransform(StelCore::RefractionOff); {
transfo->combine(Mat4d::zrotation(-(angleRotateZ+(angleRotateZOffset mapTex = renderer->createTexture(mapTexPath, TextureParams()
*M_PI/180.)))); .generateMipmaps());
const StelProjectorP prj = core->getProjection(transfo); }
StelPainter sPainter(prj);
// Normal transparency mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (StelApp::getInstance().getVisionModeNight())
sPainter.setColor(skyBrightness*nightBrightness, 0.0, 0.0, l
andFader.getInterstate());
else
sPainter.setColor(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
glEnable(GL_CULL_FACE); StelProjector::ModelViewTranformP transform = core->getAltAzModelVie
sPainter.enableTexture2d(true); wTransform(StelCore::RefractionOff);
glEnable(GL_BLEND); transform->combine(Mat4d::zrotation(-(angleRotateZ+(angleRotateZOffs
et*M_PI/180.))));
const StelProjectorP projector = core->getProjection(transform);
const Vec4f color = StelApp::getInstance().getVisionModeNight()
? Vec4f(skyBrightness*nightBrightness, 0.0, 0.0, l
andFader.getInterstate())
: Vec4f(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
renderer->setGlobalColor(color);
renderer->setCulledFaces(CullFace_Back);
renderer->setBlendMode(BlendMode_Alpha);
mapTex->bind(); mapTex->bind();
// Patch GZ: (40,20)->(cols,rows)
sPainter.sSphereMap(radius,cols,rows,texFov,1);
glDisable(GL_CULL_FACE); fisheyeSphere->draw(renderer, projector);
renderer->setCulledFaces(CullFace_None);
} }
// spherical panoramas // spherical panoramas
LandscapeSpherical::LandscapeSpherical(float _radius) : Landscape(_radius) LandscapeSpherical::LandscapeSpherical(float _radius)
{} : Landscape(_radius)
, mapTex(NULL)
{
}
LandscapeSpherical::~LandscapeSpherical() LandscapeSpherical::~LandscapeSpherical()
{ {
if(NULL != landscapeSphere)
{
delete landscapeSphere;
landscapeSphere = NULL;
}
if(NULL != mapTex)
{
delete mapTex;
}
} }
void LandscapeSpherical::load(const QSettings& landscapeIni, const QString& landscapeId) void LandscapeSpherical::load(const QSettings& landscapeIni, const QString& landscapeId)
{ {
loadCommon(landscapeIni, landscapeId); loadCommon(landscapeIni, landscapeId);
QString type = landscapeIni.value("landscape/type").toString(); QString type = landscapeIni.value("landscape/type").toString();
if (type != "spherical") if (type != "spherical")
{ {
qWarning() << "Landscape type mismatch for landscape "<< lan dscapeId qWarning() << "Landscape type mismatch for landscape "<< lan dscapeId
skipping to change at line 532 skipping to change at line 692
create(name, getTexturePath(landscapeIni.value("landscape/maptex").t oString(), landscapeId), create(name, getTexturePath(landscapeIni.value("landscape/maptex").t oString(), landscapeId),
landscapeIni.value("landscape/angle_rotatez", 0.f).toFloat() ); landscapeIni.value("landscape/angle_rotatez", 0.f).toFloat() );
} }
// create a spherical landscape from basic parameters (no ini file needed) // create a spherical landscape from basic parameters (no ini file needed)
void LandscapeSpherical::create(const QString _name, const QString& _maptex , float _angleRotateZ) void LandscapeSpherical::create(const QString _name, const QString& _maptex , float _angleRotateZ)
{ {
// qDebug() << _name << " " << _fullpath << " " << _maptex << " " << _texturefov; // qDebug() << _name << " " << _fullpath << " " << _maptex << " " << _texturefov;
validLandscape = 1; // assume ok... validLandscape = 1; // assume ok...
name = _name; name = _name;
mapTex = StelApp::getInstance().getTextureManager().createTexture(_m aptex, StelTexture::StelTextureParams(true));
angleRotateZ = _angleRotateZ*M_PI/180.f; angleRotateZ = _angleRotateZ*M_PI/180.f;
mapTexPath = _maptex;
const SphereParams params
= SphereParams(radius).resolution(64, 48).orientInside().fli
pTexture();
landscapeSphere = StelGeometryBuilder().buildSphereUnlit(params);
} }
void LandscapeSpherical::draw(StelCore* core) void LandscapeSpherical::draw(StelCore* core, StelRenderer* renderer)
{ {
if(!validLandscape) return; if(!validLandscape) return;
if(!landFader.getInterstate()) return; if(!landFader.getInterstate()) return;
if(NULL == mapTex)
{
mapTex = renderer->createTexture(mapTexPath, TextureParams()
.generateMipmaps());
}
StelProjector::ModelViewTranformP transfo = core->getAltAzModelViewT StelProjector::ModelViewTranformP transform = core->getAltAzModelVie
ransform(StelCore::RefractionOff); wTransform(StelCore::RefractionOff);
transfo->combine(Mat4d::zrotation(-(angleRotateZ+(angleRotateZOffset transform->combine(Mat4d::zrotation(-(angleRotateZ+(angleRotateZOffs
*M_PI/180.)))); et*M_PI/180.))));
const StelProjectorP prj = core->getProjection(transfo); const StelProjectorP projector = core->getProjection(transform);
StelPainter sPainter(prj);
renderer->setBlendMode(BlendMode_Alpha);
// Normal transparency mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (StelApp::getInstance().getVisionModeNight())
sPainter.setColor(skyBrightness*nightBrightness, 0.0, 0.0, l
andFader.getInterstate());
else
sPainter.setColor(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
glEnable(GL_CULL_FACE); const Vec4f color = StelApp::getInstance().getVisionModeNight()
sPainter.enableTexture2d(true); ? Vec4f(skyBrightness*nightBrightness, 0.0, 0.0, l
glEnable(GL_BLEND); andFader.getInterstate())
: Vec4f(skyBrightness, skyBrightness, skyBrightnes
s, landFader.getInterstate());
renderer->setGlobalColor(color);
renderer->setCulledFaces(CullFace_Back);
mapTex->bind(); mapTex->bind();
landscapeSphere->draw(renderer, projector);
// TODO: verify that this works correctly for custom projections // TODO: verify that this works correctly for custom projections
// seam is at East // seam is at East
//sPainter.sSphere(radius, 1.0, 40, 20, 1, true);
// GZ: Want better angle resolution, optional! // GZ: Want better angle resolution, optional!
sPainter.sSphere(radius, 1.0, cols, rows, 1, true); renderer->setCulledFaces(CullFace_None);
glDisable(GL_CULL_FACE);
} }
 End of changes. 66 change blocks. 
216 lines changed or deleted 387 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/