Tilemap: Finally get rid of that terrible name 'ScanRow'

Replacement: ZLayer
I'd really have loved to have used something alluding to physical
roof tiles (as that's the closest image I have to them), but without
reusing the word "tiles".. yeah, impossible.
This commit is contained in:
Jonas Kulla 2014-08-17 03:58:01 +02:00
parent 9311aff017
commit 724d52f61e
2 changed files with 97 additions and 97 deletions

View File

@ -65,7 +65,7 @@ protected:
friend class SceneElement; friend class SceneElement;
friend class Window; friend class Window;
friend class WindowVX; friend class WindowVX;
friend struct ScanRow; friend struct ZLayer;
}; };
class SceneElement class SceneElement

View File

@ -66,7 +66,7 @@ static const int tsLaneW = tilesetW / 2;
static const int viewpW = 21; static const int viewpW = 21;
static const int viewpH = 16; static const int viewpH = 16;
static const size_t scanrowsMax = viewpH + 5; static const size_t zlayersMax = viewpH + 5;
/* Vocabulary: /* Vocabulary:
* *
@ -91,7 +91,7 @@ static const size_t scanrowsMax = viewpH + 5;
* Tile atlas * Tile atlas
* *-----------------------*--------------* * *-----------------------*--------------*
* | | | | | ¦ | * | | | | | ¦ |
* | AT1 | AT1 | AT1 | AT1 | ¦ | * | AT0 | AT0 | AT0 | AT0 | ¦ |
* | FR0 | FR1 | FR2 | FR3 | | ¦ | | * | FR0 | FR1 | FR2 | FR3 | | ¦ | |
* |-----|-----|-----|-----| v ¦ v | * |-----|-----|-----|-----| v ¦ v |
* | | | | | ¦ | * | | | | | ¦ |
@ -101,7 +101,7 @@ static const size_t scanrowsMax = viewpH + 5;
* |[...]| | | | ¦ | * |[...]| | | | ¦ |
* |-----|-----|-----|-----| ¦ | * |-----|-----|-----|-----| ¦ |
* | | | | | | ¦ | | * | | | | | | ¦ | |
* | AT7 | | | | v ¦ v | * | AT6 | | | | v ¦ v |
* | | | | | ¦ | * | | | | | ¦ |
* |-----|-----|-----|-----| ¦ | * |-----|-----|-----|-----| ¦ |
* | Empty space | | | * | Empty space | | |
@ -128,21 +128,21 @@ static const size_t scanrowsMax = viewpH + 5;
* Elements: * Elements:
* Even though the Tilemap carries similarities with other * Even though the Tilemap carries similarities with other
* SceneElements, it is not one itself but composed of multiple * SceneElements, it is not one itself but composed of multiple
* such elements (GroundLayer and ScanRows). * such elements (GroundLayer and ZLayers).
* *
* GroundLayer: * GroundLayer:
* Every tile with priority=0 is drawn at z=0, so we * Every tile with priority=0 is drawn at z=0, so we
* collect all such tiles in one big quad array and * collect all such tiles in one big quad array and
* draw them at once. * draw them at once.
* *
* ScanRow: * ZLayer:
* Each tile in row n with priority=m is drawn at the same * Each tile in row n with priority=m is drawn at the same
* z as every tile in row n-1 with priority=m-1. This means * z as every tile in row n-1 with priority=m-1. This means
* we can collect all tiles sharing the same z in one quad * we can collect all tiles sharing the same z in one quad
* array and draw them at once. I call these collections * array and draw them at once. I call these collections
* 'scanrows', as they're drawn from the top part of the map * 'zlayers'. They're drawn from the top part of the map
* (lowest z) to the bottom part (highest z). * (lowest z) to the bottom part (highest z).
* Objects that would end up on the same scanrow are eg. trees. * Objects that would end up on the same zlayer are eg. trees.
* *
* Map viewport: * Map viewport:
* This rectangle describes the subregion of the map that is * This rectangle describes the subregion of the map that is
@ -206,22 +206,22 @@ struct GroundLayer : public ViewportElement
void onGeometryChange(const Scene::Geometry &geo); void onGeometryChange(const Scene::Geometry &geo);
}; };
struct ScanRow : public ViewportElement struct ZLayer : public ViewportElement
{ {
size_t index; size_t index;
GLintptr vboOffset; GLintptr vboOffset;
GLsizei vboCount; GLsizei vboCount;
TilemapPrivate *p; TilemapPrivate *p;
/* If this row is part of a batch and not /* If this layer is part of a batch and not
* the head, it is 'muted' via this flag */ * the head, it is 'muted' via this flag */
bool batchedFlag; bool batchedFlag;
/* If this row is a batch head, this variable /* If this layer is a batch head, this variable
* holds the element count of the entire batch */ * holds the element count of the entire batch */
GLsizei vboBatchCount; GLsizei vboBatchCount;
ScanRow(TilemapPrivate *p, Viewport *viewport); ZLayer(TilemapPrivate *p, Viewport *viewport);
void setIndex(int value); void setIndex(int value);
@ -231,7 +231,7 @@ struct ScanRow : public ViewportElement
static int calculateZ(TilemapPrivate *p, int index); static int calculateZ(TilemapPrivate *p, int index);
void initUpdateZ(); void initUpdateZ();
void finiUpdateZ(ScanRow *prev); void finiUpdateZ(ZLayer *prev);
}; };
struct TilemapPrivate struct TilemapPrivate
@ -276,12 +276,12 @@ struct TilemapPrivate
/* Ground layer vertices */ /* Ground layer vertices */
SVVector groundVert; SVVector groundVert;
/* Scanrow vertices */ /* ZLayer vertices */
SVVector scanrowVert[scanrowsMax]; SVVector zlayerVert[zlayersMax];
/* Base quad indices of each scanrow /* Base quad indices of each zlayer
* in the shared buffer */ * in the shared buffer */
size_t scanrowBases[scanrowsMax+1]; size_t zlayerBases[zlayersMax+1];
/* Shared buffers for all tiles */ /* Shared buffers for all tiles */
struct struct
@ -308,19 +308,19 @@ struct TilemapPrivate
struct struct
{ {
GroundLayer *ground; GroundLayer *ground;
ScanRow* scanrows[scanrowsMax]; ZLayer* zlayers[zlayersMax];
/* Used rows out of 'scanrows' (rest is hidden) */ /* Used layers out of 'zlayers' (rest is hidden) */
size_t activeRows; size_t activeLayers;
Scene::Geometry sceneGeo; Scene::Geometry sceneGeo;
Vec2i sceneOffset; Vec2i sceneOffset;
/* The ground and scanrow elements' creationStamp /* The ground and zlayer elements' creationStamp
* should be aquired once (at Tilemap construction) * should be aquired once (at Tilemap construction)
* instead of regenerated everytime the elements are * instead of regenerated everytime the elements are
* (re)created. Scanrows can share one stamp because * (re)created. ZLayers can share one stamp because
* their z always differs anway */ * their z always differs anway */
unsigned int groundStamp; unsigned int groundStamp;
unsigned int scanrowStamp; unsigned int zlayerStamp;
} elem; } elem;
/* Affected by: autotiles, tileset */ /* Affected by: autotiles, tileset */
@ -399,12 +399,12 @@ struct TilemapPrivate
flash.alphaIdx = 0; flash.alphaIdx = 0;
elem.groundStamp = shState->genTimeStamp(); elem.groundStamp = shState->genTimeStamp();
elem.scanrowStamp = shState->genTimeStamp(); elem.zlayerStamp = shState->genTimeStamp();
elem.ground = new GroundLayer(this, viewport); elem.ground = new GroundLayer(this, viewport);
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
elem.scanrows[i] = new ScanRow(this, viewport); elem.zlayers[i] = new ZLayer(this, viewport);
prepareCon = shState->prepareDraw.connect prepareCon = shState->prepareDraw.connect
(sigc::mem_fun(this, &TilemapPrivate::prepare)); (sigc::mem_fun(this, &TilemapPrivate::prepare));
@ -414,8 +414,8 @@ struct TilemapPrivate
{ {
/* Destroy elements */ /* Destroy elements */
delete elem.ground; delete elem.ground;
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
delete elem.scanrows[i]; delete elem.zlayers[i];
shState->releaseAtlasTex(atlas.gl); shState->releaseAtlasTex(atlas.gl);
@ -716,8 +716,8 @@ struct TilemapPrivate
} }
else else
{ {
int scanInd = y + prio; int layerInd = y + prio;
targetArray = &scanrowVert[scanInd]; targetArray = &zlayerVert[layerInd];
} }
/* Check for autotile */ /* Check for autotile */
@ -746,8 +746,8 @@ struct TilemapPrivate
{ {
groundVert.clear(); groundVert.clear();
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
scanrowVert[i].clear(); zlayerVert[i].clear();
} }
void buildQuadArray() void buildQuadArray()
@ -765,9 +765,9 @@ struct TilemapPrivate
return quadCount * sizeof(SVertex) * 4; return quadCount * sizeof(SVertex) * 4;
} }
size_t scanrowSize(size_t index) size_t zlayerSize(size_t index)
{ {
return scanrowBases[index+1] - scanrowBases[index]; return zlayerBases[index+1] - zlayerBases[index];
} }
void uploadBuffers() void uploadBuffers()
@ -776,26 +776,26 @@ struct TilemapPrivate
size_t groundQuadCount = groundVert.size() / 4; size_t groundQuadCount = groundVert.size() / 4;
size_t quadCount = groundQuadCount; size_t quadCount = groundQuadCount;
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
{ {
scanrowBases[i] = quadCount; zlayerBases[i] = quadCount;
quadCount += scanrowVert[i].size() / 4; quadCount += zlayerVert[i].size() / 4;
} }
scanrowBases[scanrowsMax] = quadCount; zlayerBases[zlayersMax] = quadCount;
VBO::bind(tiles.vbo); VBO::bind(tiles.vbo);
VBO::allocEmpty(quadDataSize(quadCount)); VBO::allocEmpty(quadDataSize(quadCount));
VBO::uploadSubData(0, quadDataSize(groundQuadCount), &groundVert[0]); VBO::uploadSubData(0, quadDataSize(groundQuadCount), &groundVert[0]);
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
{ {
if (scanrowVert[i].empty()) if (zlayerVert[i].empty())
continue; continue;
VBO::uploadSubData(quadDataSize(scanrowBases[i]), VBO::uploadSubData(quadDataSize(zlayerBases[i]),
quadDataSize(scanrowSize(i)), &scanrowVert[i][0]); quadDataSize(zlayerSize(i)), &zlayerVert[i][0]);
} }
VBO::unbind(); VBO::unbind();
@ -883,37 +883,37 @@ struct TilemapPrivate
shState->ensureQuadIBO(flash.quadCount); shState->ensureQuadIBO(flash.quadCount);
} }
void updateActiveElements(std::vector<int> &scanrowInd) void updateActiveElements(std::vector<int> &zlayerInd)
{ {
elem.ground->updateVboCount(); elem.ground->updateVboCount();
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
{ {
if (i < scanrowInd.size()) if (i < zlayerInd.size())
{ {
int index = scanrowInd[i]; int index = zlayerInd[i];
elem.scanrows[i]->setVisible(visible); elem.zlayers[i]->setVisible(visible);
elem.scanrows[i]->setIndex(index); elem.zlayers[i]->setIndex(index);
} }
else else
{ {
/* Hide unused rows */ /* Hide unused layers */
elem.scanrows[i]->setVisible(false); elem.zlayers[i]->setVisible(false);
} }
} }
} }
void updateSceneElements() void updateSceneElements()
{ {
/* Only allocate elements for non-emtpy scanrows */ /* Only allocate elements for non-emtpy zlayers */
std::vector<int> scanrowInd; std::vector<int> zlayerInd;
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
if (scanrowVert[i].size() > 0) if (zlayerVert[i].size() > 0)
scanrowInd.push_back(i); zlayerInd.push_back(i);
updateActiveElements(scanrowInd); updateActiveElements(zlayerInd);
elem.activeRows = scanrowInd.size(); elem.activeLayers = zlayerInd.size();
zOrderDirty = false; zOrderDirty = false;
} }
@ -921,63 +921,63 @@ struct TilemapPrivate
{ {
elem.ground->setVisible(false); elem.ground->setVisible(false);
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
elem.scanrows[i]->setVisible(false); elem.zlayers[i]->setVisible(false);
} }
void updateZOrder() void updateZOrder()
{ {
if (elem.activeRows == 0) if (elem.activeLayers == 0)
return; return;
for (size_t i = 0; i < elem.activeRows; ++i) for (size_t i = 0; i < elem.activeLayers; ++i)
elem.scanrows[i]->initUpdateZ(); elem.zlayers[i]->initUpdateZ();
ScanRow *prev = elem.scanrows[0]; ZLayer *prev = elem.zlayers[0];
prev->finiUpdateZ(0); prev->finiUpdateZ(0);
for (size_t i = 1; i < elem.activeRows; ++i) for (size_t i = 1; i < elem.activeLayers; ++i)
{ {
ScanRow *row = elem.scanrows[i]; ZLayer *layer = elem.zlayers[i];
row->finiUpdateZ(prev); layer->finiUpdateZ(prev);
prev = row; prev = layer;
} }
} }
/* When there are two or more scanrows with no other /* When there are two or more zlayers with no other
* elements between them in the scene list, we can * elements between them in the scene list, we can
* render them in a batch (as the scanrow data itself * render them in a batch (as the zlayer data itself
* is ordered sequentially in VRAM). Every frame, we * is ordered sequentially in VRAM). Every frame, we
* scan the scene list for such sequential rows and * scan the scene list for such sequential layers and
* batch them up for drawing. The first row of the batch * batch them up for drawing. The first layer of the batch
* (the "batch head") executes the draw call, all others * (the "batch head") executes the draw call, all others
* are muted via the 'batchedFlag'. For simplicity, * are muted via the 'batchedFlag'. For simplicity,
* single sized batches are possible. */ * single sized batches are possible. */
void prepareScanrowBatches() void prepareZLayerBatches()
{ {
ScanRow *const *scanrows = elem.scanrows; ZLayer *const *zlayers = elem.zlayers;
for (size_t i = 0; i < elem.activeRows; ++i) for (size_t i = 0; i < elem.activeLayers; ++i)
{ {
ScanRow *batchHead = scanrows[i]; ZLayer *batchHead = zlayers[i];
batchHead->batchedFlag = false; batchHead->batchedFlag = false;
GLsizei vboBatchCount = batchHead->vboCount; GLsizei vboBatchCount = batchHead->vboCount;
IntruListLink<SceneElement> *iter = &batchHead->link; IntruListLink<SceneElement> *iter = &batchHead->link;
for (i = i+1; i < elem.activeRows; ++i) for (i = i+1; i < elem.activeLayers; ++i)
{ {
iter = iter->next; iter = iter->next;
ScanRow *row = scanrows[i]; ZLayer *layer = zlayers[i];
/* Check if the next SceneElement is also /* Check if the next SceneElement is also
* the next scanrow in our list. If not, * the next zlayer in our list. If not,
* the current batch is complete */ * the current batch is complete */
if (iter != &row->link) if (iter != &layer->link)
break; break;
vboBatchCount += row->vboCount; vboBatchCount += layer->vboCount;
row->batchedFlag = true; layer->batchedFlag = true;
} }
batchHead->vboBatchCount = vboBatchCount; batchHead->vboBatchCount = vboBatchCount;
@ -1070,7 +1070,7 @@ struct TilemapPrivate
zOrderDirty = false; zOrderDirty = false;
} }
prepareScanrowBatches(); prepareZLayerBatches();
tilemapReady = true; tilemapReady = true;
} }
@ -1086,7 +1086,7 @@ GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport)
void GroundLayer::updateVboCount() void GroundLayer::updateVboCount()
{ {
vboCount = p->scanrowBases[0] * 6; vboCount = p->zlayerBases[0] * 6;
} }
void GroundLayer::draw() void GroundLayer::draw()
@ -1138,8 +1138,8 @@ void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
p->updatePosition(); p->updatePosition();
} }
ScanRow::ScanRow(TilemapPrivate *p, Viewport *viewport) ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 0, p->elem.scanrowStamp), : ViewportElement(viewport, 0, p->elem.zlayerStamp),
index(0), index(0),
vboOffset(0), vboOffset(0),
vboCount(0), vboCount(0),
@ -1147,18 +1147,18 @@ ScanRow::ScanRow(TilemapPrivate *p, Viewport *viewport)
vboBatchCount(0) vboBatchCount(0)
{} {}
void ScanRow::setIndex(int value) void ZLayer::setIndex(int value)
{ {
index = value; index = value;
z = calculateZ(p, index); z = calculateZ(p, index);
scene->reinsert(*this); scene->reinsert(*this);
vboOffset = p->scanrowBases[index] * sizeof(index_t) * 6; vboOffset = p->zlayerBases[index] * sizeof(index_t) * 6;
vboCount = p->scanrowSize(index) * 6; vboCount = p->zlayerSize(index) * 6;
} }
void ScanRow::draw() void ZLayer::draw()
{ {
if (batchedFlag) if (batchedFlag)
return; return;
@ -1176,22 +1176,22 @@ void ScanRow::draw()
GLMeta::vaoUnbind(p->tiles.vao); GLMeta::vaoUnbind(p->tiles.vao);
} }
void ScanRow::drawInt() void ZLayer::drawInt()
{ {
gl.DrawElements(GL_TRIANGLES, vboBatchCount, _GL_INDEX_TYPE, (GLvoid*) vboOffset); gl.DrawElements(GL_TRIANGLES, vboBatchCount, _GL_INDEX_TYPE, (GLvoid*) vboOffset);
} }
int ScanRow::calculateZ(TilemapPrivate *p, int index) int ZLayer::calculateZ(TilemapPrivate *p, int index)
{ {
return 32 * (index + p->viewpPos.y + 1) - p->offset.y; return 32 * (index + p->viewpPos.y + 1) - p->offset.y;
} }
void ScanRow::initUpdateZ() void ZLayer::initUpdateZ()
{ {
unlink(); unlink();
} }
void ScanRow::finiUpdateZ(ScanRow *prev) void ZLayer::finiUpdateZ(ZLayer *prev)
{ {
z = calculateZ(p, index); z = calculateZ(p, index);
@ -1290,8 +1290,8 @@ void Tilemap::setViewport(Viewport *value)
p->elem.ground->setViewport(value); p->elem.ground->setViewport(value);
for (size_t i = 0; i < scanrowsMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
p->elem.scanrows[i]->setViewport(value); p->elem.zlayers[i]->setViewport(value);
} }
#endif #endif
@ -1374,8 +1374,8 @@ void Tilemap::setVisible(bool value)
return; return;
p->elem.ground->setVisible(value); p->elem.ground->setVisible(value);
for (size_t i = 0; i < p->elem.activeRows; ++i) for (size_t i = 0; i < p->elem.activeLayers; ++i)
p->elem.scanrows[i]->setVisible(value); p->elem.zlayers[i]->setVisible(value);
} }
void Tilemap::setOX(int value) void Tilemap::setOX(int value)