Skip to content

Commit

Permalink
Added new 3D terrain model feature to 3D view perspective.
Browse files Browse the repository at this point in the history
  • Loading branch information
hengli committed Oct 29, 2010
1 parent 1dc379f commit c1613c0
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 39 deletions.
16 changes: 9 additions & 7 deletions src/ui/map3D/Imagery.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void
Imagery::prefetch3D(double radius, double tileResolution,
double xOrigin, double yOrigin,
double viewXOffset, double viewYOffset,
const QString& utmZone)
const QString& utmZone, bool useHeightModel)
{
int32_t minTileX, minTileY, maxTileX, maxTileY;
int32_t zoomLevel;
Expand All @@ -183,7 +183,7 @@ Imagery::prefetch3D(double radius, double tileResolution,
{
QString url = getTileLocation(c, r, zoomLevel, tileResolution);

TexturePtr t = textureCache->get(url);
TexturePtr t = textureCache->get(url, useHeightModel);
}
}
}
Expand All @@ -192,7 +192,7 @@ void
Imagery::draw3D(double radius, double tileResolution,
double xOrigin, double yOrigin,
double viewXOffset, double viewYOffset,
const QString& utmZone)
const QString& utmZone, bool useHeightModel)
{
int32_t minTileX, minTileY, maxTileX, maxTileY;
int32_t zoomLevel;
Expand All @@ -213,7 +213,7 @@ Imagery::draw3D(double radius, double tileResolution,
double x1, y1, x2, y2, x3, y3, x4, y4;
imageBounds(c, r, tileResolution, x1, y1, x2, y2, x3, y3, x4, y4);

TexturePtr t = textureCache->get(tileURL);
TexturePtr t = textureCache->get(tileURL, useHeightModel);

if (!t.isNull())
{
Expand Down Expand Up @@ -257,7 +257,8 @@ Imagery::imageBounds(int32_t tileX, int32_t tileY, double tileResolution,
LLtoUTM(lat2, lon2, x3, y3, utmZone);
LLtoUTM(lat2, lon1, x4, y4, utmZone);
}
else if (currentImageryType == SWISSTOPO_SATELLITE)
else if (currentImageryType == SWISSTOPO_SATELLITE ||
currentImageryType == SWISSTOPO_SATELLITE_3D)
{
double utmMultiplier = tileResolution * 200.0;
double minX = tileX * utmMultiplier;
Expand Down Expand Up @@ -294,7 +295,8 @@ Imagery::tileBounds(double tileResolution,
UTMtoTile(maxUtmX, maxUtmY, utmZone, tileResolution,
maxTileX, minTileY, zoomLevel);
}
else if (currentImageryType == SWISSTOPO_SATELLITE)
else if (currentImageryType == SWISSTOPO_SATELLITE ||
currentImageryType == SWISSTOPO_SATELLITE_3D)
{
double utmMultiplier = tileResolution * 200;

Expand Down Expand Up @@ -570,7 +572,7 @@ Imagery::getTileLocation(int32_t tileX, int32_t tileY, int32_t zoomLevel,
oss << "http://khm.google.com/vt/lbw/lyrs=y&x=" << tileX
<< "&y=" << tileY << "&z=" << zoomLevel;
break;
case SWISSTOPO_SATELLITE:
case SWISSTOPO_SATELLITE: case SWISSTOPO_SATELLITE_3D:
oss << "../map/eth_zurich_swissimage_025/200/color/" << tileY
<< "/tile-";
if (tileResolution < 1.0)
Expand Down
7 changes: 4 additions & 3 deletions src/ui/map3D/Imagery.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class Imagery
{
GOOGLE_MAP = 0,
GOOGLE_SATELLITE = 1,
SWISSTOPO_SATELLITE = 2
SWISSTOPO_SATELLITE = 2,
SWISSTOPO_SATELLITE_3D = 3
};

void setImageryType(ImageryType type);
Expand All @@ -63,11 +64,11 @@ class Imagery
void prefetch3D(double radius, double tileResolution,
double xOrigin, double yOrigin,
double viewXOffset, double viewYOffset,
const QString& utmZone);
const QString& utmZone, bool useHeightModel);
void draw3D(double radius, double tileResolution,
double xOrigin, double yOrigin,
double viewXOffset, double viewYOffset,
const QString& utmZone);
const QString& utmZone, bool useHeightModel);

bool update(void);

Expand Down
21 changes: 18 additions & 3 deletions src/ui/map3D/QMap3DWidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ QMap3DWidget::buildLayout(void)
imageryComboBox->addItem("Map (Google)");
imageryComboBox->addItem("Satellite (Google)");
imageryComboBox->addItem("Satellite (Swisstopo)");
imageryComboBox->addItem("3D Satellite (Swisstopo)");

QPushButton* recenterButton = new QPushButton(this);
recenterButton->setText("Recenter Camera");
Expand Down Expand Up @@ -547,6 +548,10 @@ QMap3DWidget::showImagery(const QString& text)
{
imagery->setImageryType(Imagery::SWISSTOPO_SATELLITE);
}
else if (text.compare("3D Satellite (Swisstopo)") == 0)
{
imagery->setImageryType(Imagery::SWISSTOPO_SATELLITE_3D);
}
displayImagery = true;
}
}
Expand Down Expand Up @@ -678,6 +683,7 @@ QMap3DWidget::drawImagery(double originX, double originY, double originZ,
double minResolution = 0.25;
double centerResolution = cameraPose.distance / 100.0;
double maxResolution = 1048576.0;
bool useHeightModel = false;

if (imageryComboBox->currentText().compare("Map (Google)") == 0)
{
Expand All @@ -692,6 +698,12 @@ QMap3DWidget::drawImagery(double originX, double originY, double originZ,
minResolution = 0.25;
maxResolution = 0.25;
}
else if (imageryComboBox->currentText().compare("3D Satellite (Swisstopo)") == 0)
{
minResolution = 0.25;
maxResolution = 0.25;
useHeightModel = true;
}

double resolution = minResolution;
while (resolution * 2.0 < centerResolution)
Expand All @@ -704,21 +716,24 @@ QMap3DWidget::drawImagery(double originX, double originY, double originZ,
}

imagery->draw3D(viewingRadius, resolution, originX, originY,
cameraPose.xOffset, cameraPose.yOffset, zone);
cameraPose.xOffset, cameraPose.yOffset, zone,
useHeightModel);

if (prefetch)
{
if (resolution / 2.0 >= minResolution)
{
imagery->prefetch3D(viewingRadius / 2.0, resolution / 2.0,
originX, originY,
cameraPose.xOffset, cameraPose.yOffset, zone);
cameraPose.xOffset, cameraPose.yOffset, zone,
useHeightModel);
}
if (resolution * 2.0 <= maxResolution)
{
imagery->prefetch3D(viewingRadius * 2.0, resolution * 2.0,
originX, originY,
cameraPose.xOffset, cameraPose.yOffset, zone);
cameraPose.xOffset, cameraPose.yOffset, zone,
useHeightModel);
}
}

Expand Down
88 changes: 76 additions & 12 deletions src/ui/map3D/Texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This file is part of the QGROUNDCONTROL project
#include "Texture.h"

Texture::Texture()
: _is3D(false)
{

}
Expand All @@ -54,9 +55,11 @@ Texture::sync(const WebImagePtr& image)
state = static_cast<State>(image->getState());

if (image->getState() != WebImage::UNINITIALIZED &&
sourceURL != image->getSourceURL())
(sourceURL != image->getSourceURL() ||
_is3D != image->is3D()))
{
sourceURL = image->getSourceURL();
_is3D = image->is3D();
}

if (image->getState() == WebImage::READY && image->getSyncFlag())
Expand Down Expand Up @@ -91,7 +94,9 @@ Texture::sync(const WebImagePtr& image)

glBindTexture(GL_TEXTURE_2D, id);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageWidth, imageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, image->getData());
GL_RGBA, GL_UNSIGNED_BYTE, image->getImageData());

heightModel = image->getHeightModel();
}
}

Expand Down Expand Up @@ -140,18 +145,77 @@ Texture::draw(float x1, float y1, float x2, float y2,
}

glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
if (!_is3D)
{
glBegin(GL_QUADS);
glTexCoord2f(dx, maxV - dy);
glVertex3f(x1, y1, 0.0f);
glTexCoord2f(maxU - dx, maxV - dy);
glVertex3f(x2, y2, 0.0f);
glTexCoord2f(maxU - dx, dy);
glVertex3f(x3, y3, 0.0f);
glTexCoord2f(dx, dy);
glVertex3f(x4, y4, 0.0f);
glEnd();
}
else
{
float scaleX = 1.0f / static_cast<float>(heightModel.size() - 1);

for (int32_t i = 0; i < heightModel.size() - 1; ++i)
{
float scaleI = scaleX * static_cast<float>(i);

glTexCoord2f(dx, maxV - dy);
glVertex2f(x1, y1);
glTexCoord2f(maxU - dx, maxV - dy);
glVertex2f(x2, y2);
glTexCoord2f(maxU - dx, dy);
glVertex2f(x3, y3);
glTexCoord2f(dx, dy);
glVertex2f(x4, y4);
float scaleY =
1.0f / static_cast<float>(heightModel[i].size() - 1);

glEnd();
float x1i = x1 + scaleI * (x4 - x1);
float x1f = x2 + scaleI * (x3 - x2);
float x2i = x1i + scaleX * (x4 - x1);
float x2f = x1f + scaleX * (x3 - x2);

for (int32_t j = 0; j < heightModel[i].size() - 1; ++j)
{
float scaleJ = scaleY * static_cast<float>(j);

float y1i = y1 + scaleJ * (y2 - y1);
float y1f = y4 + scaleJ * (y3 - y4);
float y2i = y1i + scaleY * (y2 - y1);
float y2f = y1f + scaleY * (y3 - y4);

float nx1 = x1i + scaleJ * (x1f - x1i);
float nx2 = x1i + (scaleJ + scaleY) * (x1f - x1i);
float nx3 = x2i + (scaleJ + scaleY) * (x2f - x2i);
float nx4 = x2i + scaleJ * (x2f - x2i);
float ny1 = y1i + scaleI * (y1f - y1i);
float ny2 = y2i + scaleI * (y2f - y2i);
float ny3 = y2i + (scaleI + scaleX) * (y2f - y2i);
float ny4 = y1i + (scaleI + scaleX) * (y1f - y1i);

glBegin(GL_QUADS);
glTexCoord2f(dx + scaleJ * (maxU - dx * 2.0f),
dy + (1.0f - scaleI) * (maxV - dy * 2.0f));
glVertex3f(nx1, ny1, -static_cast<float>(heightModel[i][j]));
glTexCoord2f(dx + (scaleJ + scaleY) * (maxU - dx * 2.0f),
dy + (1.0f - scaleI) * (maxV - dy * 2.0f));
glVertex3f(nx2, ny2, -static_cast<float>(heightModel[i][j + 1]));
glTexCoord2f(dx + (scaleJ + scaleY) * (maxU - dx * 2.0f),
dy + (1.0f - scaleI - scaleX) * (maxV - dy * 2.0f));
glVertex3f(nx3, ny3, -static_cast<float>(heightModel[i + 1][j + 1]));
glTexCoord2f(dx + scaleJ * (maxU - dx * 2.0f),
dy + (1.0f - scaleI - scaleX) * (maxV - dy * 2.0f));
glVertex3f(nx4, ny4, -static_cast<float>(heightModel[i + 1][j]));

glEnd();
}
}
}

glDisable(GL_TEXTURE_2D);
}

bool
Texture::is3D(void) const
{
return _is3D;
}
5 changes: 5 additions & 0 deletions src/ui/map3D/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class Texture
float x3, float y3, float x4, float y4,
bool smoothInterpolation) const;

bool is3D(void) const;

private:
enum State
{
Expand All @@ -77,6 +79,9 @@ class Texture
int32_t imageWidth;
int32_t imageHeight;

bool _is3D;
QVector< QVector<int32_t> > heightModel;

float maxU;
float maxV;
};
Expand Down
14 changes: 8 additions & 6 deletions src/ui/map3D/TextureCache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,20 @@ TextureCache::TextureCache(uint32_t _cacheSize)
}

TexturePtr
TextureCache::get(const QString& tileURL)
TextureCache::get(const QString& tileURL, bool useHeightModel)
{
QPair<TexturePtr, int32_t> p1 = lookup(tileURL);
QPair<TexturePtr, int32_t> p1 = lookup(tileURL, useHeightModel);
if (!p1.first.isNull())
{
return p1.first;
}

QPair<WebImagePtr, int32_t> p2 = imageCache->lookup(tileURL);
QPair<WebImagePtr, int32_t> p2 =
imageCache->lookup(tileURL, useHeightModel);
if (!p2.first.isNull())
{
textures[p2.second]->sync(p2.first);
p1 = lookup(tileURL);
p1 = lookup(tileURL, useHeightModel);

return p1.first;
}
Expand All @@ -85,11 +86,12 @@ TextureCache::sync(void)
}

QPair<TexturePtr, int32_t>
TextureCache::lookup(const QString& tileURL)
TextureCache::lookup(const QString& tileURL, bool useHeightModel)
{
for (int32_t i = 0; i < textures.size(); ++i)
{
if (textures[i]->getSourceURL() == tileURL)
if (textures[i]->getSourceURL() == tileURL &&
textures[i]->is3D() == useHeightModel)
{
return qMakePair(textures[i], i);
}
Expand Down
5 changes: 3 additions & 2 deletions src/ui/map3D/TextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ class TextureCache
public:
explicit TextureCache(uint32_t cacheSize);

TexturePtr get(const QString& tileURL);
TexturePtr get(const QString& tileURL, bool useHeightModel = false);

void sync(void);

private:
QPair<TexturePtr, int32_t> lookup(const QString& tileURL);
QPair<TexturePtr, int32_t> lookup(const QString& tileURL,
bool useHeightModel);

bool requireSync(void) const;

Expand Down
Loading

0 comments on commit c1613c0

Please sign in to comment.