Update of /cvsroot/atlas/Atlas/src
In directory vz-cvs-4.sog:/tmp/cvs-serv28491
Modified Files:
TileMapper.cxx TileMapper.hxx
Log Message:
Added maxPossibleLevel() class method, improved documentation, added a
few more error checks, and rearranged some of the code to make it more
logically organized.
Index: TileMapper.cxx
===================================================================
RCS file: /cvsroot/atlas/Atlas/src/TileMapper.cxx,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- TileMapper.cxx 19 Sep 2011 02:14:12 -0000 1.11
+++ TileMapper.cxx 30 Sep 2011 20:26:47 -0000 1.12
@@ -24,6 +24,7 @@
#include <cassert>
#include <stdexcept>
+// #include <GL/glew.h>
#include <plib/pu.h>
#include <simgear/misc/sg_path.hxx>
@@ -32,13 +33,44 @@
using namespace std;
-TileMapper::TileMapper(Palette *p, unsigned int maxLevel,
+unsigned int TileMapper::maxPossibleLevel()
+{
+ unsigned int result = TileManager::MAX_MAP_LEVEL;
+ GLint textureSize = 0x1 << result;
+
+ // Theoretically this isn't quite correct, as it's possible that
+ // *no* texture sizes are allowed (not even 1x1, which is what a
+ // result of 0 implies). However, in reality I don't think that
+ // can ever happen.
+ while (result > 0) {
+ GLint tmp;
+ // For this test to be accurate, we need to make the
+ // parameters (GL_RGB, ...) the same as the ones we'll use in
+ // Atlas when loading the texture.
+ glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGB,
+ textureSize, textureSize, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
+ GL_TEXTURE_WIDTH, &tmp);
+ if ((tmp != 0) || (textureSize == 1)) {
+ // We found an acceptable size.
+ break;
+ }
+ textureSize /= 2;
+ result--;
+ };
+
+ return result;
+}
+
+TileMapper::TileMapper(Palette *p, unsigned int maxDesiredLevel,
bool discreteContours, bool contourLines,
float azimuth, float elevation, bool lighting,
bool smoothShading):
- _palette(p), _maxLevel(maxLevel), _discreteContours(discreteContours),
- _contourLines(contourLines), _azimuth(azimuth), _elevation(elevation),
- _lighting(lighting), _smoothShading(smoothShading), _fbo(0), _to(0)
+ _palette(p), _maxLevel(maxDesiredLevel),
+ _discreteContours(discreteContours), _contourLines(contourLines),
+ _azimuth(azimuth), _elevation(elevation), _lighting(lighting),
+ _smoothShading(smoothShading), _tile(NULL), _fbo(0), _to(0)
{
// We must have a palette.
if (!_palette) {
@@ -56,6 +88,10 @@
Bucket::palette = _palette;
Bucket::discreteContours = _discreteContours;
Bucket::contourLines = _contourLines;
+
+ // Create the framebuffer object.
+ glGenFramebuffersEXT(1, &_fbo);
+ assert(_fbo != 0);
}
TileMapper::~TileMapper()
@@ -64,77 +100,61 @@
glDeleteFramebuffersEXT(1, &_fbo);
}
-// Tells TileMapper which tile is to be rendered.
+// Tells TileMapper which tile is to be rendered. We load the tile's
+// buckets, and set _maximumElevation.
void TileMapper::set(Tile *t)
{
// Remove any old information we have.
_unloadBuckets();
_tile = t;
- if (_tile) {
- const vector<long int>* buckets = _tile->bucketIndices();
- for (unsigned int i = 0; i < buckets->size(); i++) {
- long int index = buckets->at(i);
-
- Bucket *b = new Bucket(_tile->sceneryDir(), index);
- b->load(Bucket::RECTANGULAR);
+ if (!_tile) {
+ // EYE - throw an error, like when checking for a palette?
+ return;
+ }
- _buckets.push_back(b);
+ const vector<long int>* buckets = _tile->bucketIndices();
+ for (unsigned int i = 0; i < buckets->size(); i++) {
+ long int index = buckets->at(i);
- if (b->maximumElevation() > _maximumElevation) {
- _maximumElevation = b->maximumElevation();
- }
- }
- }
+ Bucket *b = new Bucket(_tile->sceneryDir(), index);
+ b->load(Bucket::RECTANGULAR);
- // Silently reduce (if necessary) _maxLevel to a value we can
- // actually handle.
+ _buckets.push_back(b);
- // EYE - Does this really belong here?
- GLint textureSize = 0x1 << _maxLevel;
- while (true) {
- GLint tmp;
- // For this test to be accurate, we need to make the
- // parameters (GL_RGB, ...) the same as the ones we'll use in
- // Atlas when loading the texture.
- glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGB,
- textureSize, textureSize, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
- GL_TEXTURE_WIDTH, &tmp);
- if ((tmp != 0) || (textureSize == 1)) {
- break;
+ if (b->maximumElevation() > _maximumElevation) {
+ _maximumElevation = b->maximumElevation();
}
- fprintf(stderr, "Max level (%d) too big, reducing\n", _maxLevel);
- textureSize /= 2;
- _maxLevel--;
- };
-
- // Calculate the proper width and height for the given level.
- _tile->mapSize(_maxLevel, &_width, &_height);
+ }
}
// Draws the tile into a texture attached to a framebuffer.
void TileMapper::render()
{
- // EYE - remove this
+ // EYE - remove this eventually
assert(glGetError() == GL_NO_ERROR);
- // Set up the framebuffer object, if it hasn't been done already.
- // We delay until now so that a TileMapper can be created without
- // having an OpenGL context.
- if (_fbo == 0) {
- glGenFramebuffersEXT(1, &_fbo);
+ if (!_palette || !_tile) {
+ // EYE - throw an error?
+ return;
}
// Bind the framebuffer so that all rendering goes to it.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
+ // EYE - assert _to is 0?
+
+ // Calculate the proper width and height for the given level.
+ // Note that we don't check if _maxLevel is reasonable - that's up
+ // to the caller.
+ _tile->mapSize(_maxLevel, &_width, &_height);
+
// Create a texture object.
// EYE - we also need to see if our current buffer is big enough.
// This is where we could add the tiling code.
// EYE - necessary to enable? We don't actually do any texturing.
// glEnable(GL_TEXTURE_2D);
+ // EYE - do I need to attach a depth buffer too?
glGenTextures(1, &_to);
glBindTexture(GL_TEXTURE_2D, _to);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB,
@@ -156,12 +176,7 @@
// When our buckets were loaded, all points were converted to
// lat, lon. We need to stretch them to fill the buffer
- // correctly. Note that tiles use special latitudes (0 - 179)
- // and longitudes (0 - 359), so we need to adjust them to
- // "normal" values.
-
- // EYE - Do we really? And should we have special accessors
- // in tiles?
+ // correctly.
int lat = _tile->lat();
int lon = _tile->lon();
int w = _tile->width();
@@ -272,10 +287,9 @@
glFinish();
- assert(glGetError() == GL_NO_ERROR);
-
- // Create mimaps and unbind the framebuffer. We should now have a
- // map of the appropriate size in the texture object _to.
+ // Create mipmaps and unbind the framebuffer. We should now
+ // have a map of the appropriate size in the texture object
+ // _to.
glGenerateMipmapEXT(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@@ -293,6 +307,10 @@
// (given in the constructor).
void TileMapper::save(unsigned int level, ImageType t, unsigned int jpegQuality)
{
+ if (!_palette || !_tile) {
+ return;
+ }
+
// First, calculate the desired map size in pixels.
int shrinkage = _maxLevel - level;
int width = _width / (1 << shrinkage),
@@ -342,15 +360,15 @@
delete _buckets[i];
}
_buckets.clear();
+ _tile = NULL;
// This might be overkill, but presumably if we're unloading
// buckets, that means we can no longer trust the maximum
// elevation figure.
-
- // EYE - should be a constant somewhere - Tile? Bucket::NanE?
- _maximumElevation = -std::numeric_limits<float>::max();
+ _maximumElevation = Bucket::NanE;
// Delete the texture object. We need to do this because
// different tiles may have different sizes.
glDeleteTextures(1, &_to);
+ _to = 0;
}
Index: TileMapper.hxx
===================================================================
RCS file: /cvsroot/atlas/Atlas/src/TileMapper.hxx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- TileMapper.hxx 26 Sep 2011 04:24:07 -0000 1.9
+++ TileMapper.hxx 30 Sep 2011 20:26:47 -0000 1.10
@@ -7,17 +7,25 @@
This class will render maps for a tile and write them to a file.
The rendering style is fixed for the duration of the object, so to
- change the style you have to create a new object.
+ change the style you have to create a new object. This may seem a
+ bit of an odd approach, but the motiviation is that we tend to
+ render all maps in the same way; all that changes are the tiles
+ being mapped. A TileMapper can be thought of as an encapsulation of
+ a certain rendering style, which is then applied to various tiles.
To create maps for a tile, first set() the tile, render() it (once
only), then call save() for each file that needs to be created.
- Note that you cannot save a file of higher resolution than maxLevel
- (given in the constructor).
+ Note that you cannot save a file of higher resolution than
+ maxDesiredLevel (given in the constructor).
Rendering is done by creating an OpenGL framebuffer object and
- rendering to an attached texture of a size given by maxLevel
+ rendering to an attached texture of a size given by maxDesiredLevel
(therefore your graphics card has to be able to support textures of
- that size).
+ that size - this can be checked with the maxPossibleLevel() class
+ method).
+
+ There must be an valid OpenGL context when a TileMapper object is
+ created and used.
This file is part of Atlas.
@@ -48,20 +56,30 @@
class TileMapper {
public:
+ // Returns the maximum map level that this computer's graphics
+ // card can handle. A map level of n means that the card can
+ // handle textures of 2^n x 2^n. The result should be treated
+ // with a grain of salt as it is just an estimate - in reality,
+ // the you might have to decrease the maximum level by 1.
+ static unsigned int maxPossibleLevel();
+
+ // Create a tile mapper with the given rendering parameters.
TileMapper(Palette *p,
- unsigned int maxLevel = 10,
- bool discreteContours = true,
- bool contourLines = false,
- float azimuth = 315.0,
- float elevation = 55.0,
- bool lighting = true,
- bool smoothShading = true);
+ unsigned int maxDesiredLevel = 10,
+ bool discreteContours = true,
+ bool contourLines = false,
+ float azimuth = 315.0,
+ float elevation = 55.0,
+ bool lighting = true,
+ bool smoothShading = true);
~TileMapper();
enum ImageType {PNG, JPEG};
// Specify the tile upon which future operations will operate.
- // This will load the scenery for the tile.
+ // This will load the scenery for the tile. If t is NULL, this
+ // essentially clears the current values (and calls to render() or
+ // save() are ignored).
void set(Tile *t);
// Renders the current tile at the size given by maxLevel.
@@ -69,14 +87,14 @@
// texture. This only needs to be done once per tile.
void render();
- // Save the current image to a file at the given level. You must
- // call render() before the first call to save() (for each tile).
- // EYE - put in a check?
+ // Save the current image to a file at the given level (<=
+ // maxDesiredLevel). You must call render() before the first call
+ // to save() (for each tile).
void save(unsigned int level, ImageType t, unsigned int jpegQuality = 75);
// Accessors.
const Palette *palette() const { return _palette; }
- unsigned int maxLevel() const { return _maxLevel; }
+ unsigned int maxDesiredLevel() const { return _maxLevel; }
bool discreteContours() const { return _discreteContours; }
float azimuth() const { return _azimuth; }
float elevation() const { return _elevation; }
|