2013-09-01 14:27:21 +00:00
|
|
|
/*
|
|
|
|
** tilemap.cpp
|
|
|
|
**
|
|
|
|
** This file is part of mkxp.
|
|
|
|
**
|
|
|
|
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
|
|
|
**
|
|
|
|
** mkxp is free software: you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation, either version 2 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** mkxp is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "tilemap.h"
|
|
|
|
|
|
|
|
#include "viewport.h"
|
|
|
|
#include "bitmap.h"
|
|
|
|
#include "table.h"
|
|
|
|
|
2013-10-09 10:30:33 +00:00
|
|
|
#include "sharedstate.h"
|
2013-09-01 14:27:21 +00:00
|
|
|
#include "glstate.h"
|
|
|
|
#include "gl-util.h"
|
|
|
|
#include "etc-internal.h"
|
|
|
|
#include "quadarray.h"
|
|
|
|
#include "texpool.h"
|
|
|
|
#include "quad.h"
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
#include "tileatlas.h"
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-04 16:48:37 +00:00
|
|
|
#include <sigc++/connection.h>
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
2013-12-08 12:19:22 +00:00
|
|
|
#include <algorithm>
|
2013-12-26 19:18:33 +00:00
|
|
|
#include <vector>
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-04 16:48:37 +00:00
|
|
|
#include <SDL_surface.h>
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
extern const StaticRect autotileRects[];
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
typedef std::vector<SVertex> SVVector;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
typedef struct { SVVector v[4]; } TileVBuffer;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
/* Check if [C]ontainer contains [V]alue */
|
|
|
|
template<typename C, typename V>
|
|
|
|
inline bool contains(const C &c, const V &v)
|
|
|
|
{
|
|
|
|
return std::find(c.begin(), c.end(), v) != c.end();
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
static const int tilesetW = 8 * 32;
|
|
|
|
static const int autotileW = 3 * 32;
|
|
|
|
static const int autotileH = 4 * 32;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
static const int autotileCount = 7;
|
|
|
|
|
|
|
|
static const int atAreaW = autotileW * 4;
|
|
|
|
static const int atAreaH = autotileH * autotileCount;
|
|
|
|
|
|
|
|
static const int tsLaneW = tilesetW / 2;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Vocabulary:
|
|
|
|
*
|
|
|
|
* Atlas: A texture containing both the tileset and all
|
|
|
|
* autotile images. This is so the entire tilemap can
|
|
|
|
* be drawn from one texture (for performance reasons).
|
|
|
|
* This means that we have to watch the 'modified' signals
|
|
|
|
* of all Bitmaps that make up the atlas, and update it
|
|
|
|
* as required during runtime.
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
* The atlas is tightly packed, with the autotiles located
|
|
|
|
* in the top left corener and the tileset image filing the
|
|
|
|
* remaining open space (below the autotiles as well as
|
|
|
|
* besides it). The tileset is vertically cut in half, where
|
|
|
|
* the first half fills available texture space, and then the
|
|
|
|
* other half (as if the right half was cut and pasted below
|
|
|
|
* the left half before fitting it all into the atlas).
|
|
|
|
* Internally these halves are called "tileset lanes".
|
|
|
|
*
|
|
|
|
* Tile atlas
|
|
|
|
* *-----------------------*--------------*
|
|
|
|
* | | | | | ¦ |
|
|
|
|
* | AT1 | AT1 | AT1 | AT1 | ¦ |
|
|
|
|
* | FR0 | FR1 | FR2 | FR3 | | ¦ | |
|
|
|
|
* |-----|-----|-----|-----| v ¦ v |
|
|
|
|
* | | | | | ¦ |
|
|
|
|
* | AT1 | | | | ¦ |
|
|
|
|
* | | | | | ¦ |
|
|
|
|
* |-----|-----|-----|-----| ¦ |
|
|
|
|
* |[...]| | | | ¦ |
|
|
|
|
* |-----|-----|-----|-----| ¦ |
|
|
|
|
* | | | | | | ¦ | |
|
|
|
|
* | AT7 | | | | v ¦ v |
|
|
|
|
* | | | | | ¦ |
|
|
|
|
* |-----|-----|-----|-----| ¦ |
|
|
|
|
* | ¦ ¦ ¦ ¦ |
|
|
|
|
* | Tile- ¦ | ¦ | ¦ ¦ |
|
|
|
|
* | set ¦ v ¦ v ¦ ¦ |
|
|
|
|
* | ¦ ¦ ¦ | ¦ | |
|
|
|
|
* | | ¦ ¦ ¦ v ¦ v |
|
|
|
|
* | v ¦ | ¦ | ¦ ¦ |
|
|
|
|
* | ¦ v ¦ v ¦ ¦ |
|
|
|
|
* | ¦ ¦ ¦ ¦ |
|
|
|
|
* *---------------------------------------*
|
2013-09-01 14:27:21 +00:00
|
|
|
*
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
* When allocating the atlas size, we first expand vertically
|
|
|
|
* until all the space immediately below the autotile area
|
|
|
|
* is used up, and then, when the max texture size
|
|
|
|
* is reached, horizontally.
|
2013-09-01 14:27:21 +00:00
|
|
|
*
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
* To animate the autotiles, we keep 4 buffers (packed into
|
|
|
|
* one big VBO and accessed using offsets) with vertex data
|
|
|
|
* corresponding to the respective animation frame. Likewise,
|
|
|
|
* the IBO is expanded to 4 times its usual size. In practice
|
|
|
|
* this means that all vertex data which does not stem from an
|
|
|
|
* animated autotile is duplicated across all 4 buffers.
|
|
|
|
* The range of one such buffer inside the VBO is called
|
|
|
|
* buffer frame, and tiles.bufferFrameSize * bufferIndex gives
|
|
|
|
* us the base offset into the IBO to access it.
|
|
|
|
* If there are no animated autotiles attached, we only use
|
|
|
|
* the first buffer.
|
2013-09-01 14:27:21 +00:00
|
|
|
*
|
|
|
|
* Elements:
|
|
|
|
* Even though the Tilemap carries similarities with other
|
|
|
|
* SceneElements, it is not one itself but composed of multiple
|
|
|
|
* such elements (GroundLayer and ScanRows).
|
|
|
|
*
|
|
|
|
* GroundLayer:
|
|
|
|
* Every tile with priority=0 is drawn at z=0, so we
|
|
|
|
* collect all such tiles in one big quad array and
|
|
|
|
* draw them at once.
|
|
|
|
*
|
|
|
|
* ScanRow:
|
|
|
|
* 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
|
|
|
|
* we can collect all tiles sharing the same z in one quad
|
|
|
|
* array and draw them at once. I call these collections
|
|
|
|
* 'scanrows', as they're drawn from the top part of the map
|
|
|
|
* (lowest z) to the bottom part (highest z).
|
|
|
|
* Objects that would end up on the same scanrow are eg. trees.
|
|
|
|
*
|
|
|
|
* Replica:
|
|
|
|
* A tilemap is not drawn as one rectangular object, but
|
|
|
|
* "tiled" if there is an area on the screen that would
|
|
|
|
* otherwise not be covered by it. RGSS does this so when the
|
|
|
|
* game orders a screen shake which draws the tilemap at slightly
|
|
|
|
* different x-offsets, black area isn't exposed (this would
|
|
|
|
* always happen for 20x15 maps). 'Replicas' describes where the
|
|
|
|
* tilemap needs to be drawn again to achieve this tiled effect
|
|
|
|
* (above the tilemap, to the right, above and right etc.).
|
|
|
|
* 'Normal' means no replica needs to be drawn.
|
|
|
|
* Because the minimum map size in RMXP covers the entire screen,
|
|
|
|
* we don't have to worry about ever drawing more than one replica
|
|
|
|
* in each dimension.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Replica positions */
|
|
|
|
enum Position
|
|
|
|
{
|
|
|
|
Normal = 1 << 0,
|
|
|
|
|
|
|
|
Left = 1 << 1,
|
|
|
|
Right = 1 << 2,
|
|
|
|
Top = 1 << 3,
|
|
|
|
Bottom = 1 << 4,
|
|
|
|
|
|
|
|
TopLeft = Top | Left,
|
|
|
|
TopRight = Top | Right,
|
|
|
|
BottomLeft = Bottom | Left,
|
|
|
|
BottomRight = Bottom | Right
|
|
|
|
};
|
|
|
|
|
|
|
|
static const Position positions[] =
|
|
|
|
{
|
|
|
|
Normal,
|
|
|
|
Left, Right, Top, Bottom,
|
|
|
|
TopLeft, TopRight, BottomLeft, BottomRight
|
|
|
|
};
|
|
|
|
|
|
|
|
static elementsN(positions);
|
|
|
|
|
2013-10-09 09:52:39 +00:00
|
|
|
/* Autotile animation */
|
|
|
|
static const uint8_t atAnimation[16*4] =
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
|
|
|
|
};
|
|
|
|
|
|
|
|
static elementsN(atAnimation);
|
|
|
|
|
|
|
|
/* Flash tiles pulsing opacity */
|
2013-09-23 06:27:28 +00:00
|
|
|
static const uint8_t flashAlpha[] =
|
|
|
|
{
|
|
|
|
/* Fade in */
|
|
|
|
0x3C, 0x3C, 0x3C, 0x3C, 0x4B, 0x4B, 0x4B, 0x4B,
|
|
|
|
0x5A, 0x5A, 0x5A, 0x5A, 0x69, 0x69, 0x69, 0x69,
|
|
|
|
/* Fade out */
|
|
|
|
0x78, 0x78, 0x78, 0x78, 0x69, 0x69, 0x69, 0x69,
|
|
|
|
0x5A, 0x5A, 0x5A, 0x5A, 0x4B, 0x4B, 0x4B, 0x4B
|
|
|
|
};
|
|
|
|
|
|
|
|
static elementsN(flashAlpha);
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
struct GroundLayer : public ViewportElement
|
|
|
|
{
|
|
|
|
GLsizei vboCount;
|
|
|
|
TilemapPrivate *p;
|
|
|
|
|
|
|
|
GroundLayer(TilemapPrivate *p, Viewport *viewport);
|
|
|
|
|
|
|
|
void draw();
|
|
|
|
void drawInt();
|
|
|
|
void drawFlashInt();
|
|
|
|
|
|
|
|
void onGeometryChange(const Scene::Geometry &geo);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ScanRow : public ViewportElement
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
const size_t index;
|
2013-09-01 14:27:21 +00:00
|
|
|
GLintptr vboOffset;
|
|
|
|
GLsizei vboCount;
|
|
|
|
TilemapPrivate *p;
|
|
|
|
|
2013-10-13 20:00:38 +00:00
|
|
|
/* If this row is part of a batch and not
|
|
|
|
* the head, it is 'muted' via this flag */
|
|
|
|
bool batchedFlag;
|
|
|
|
|
|
|
|
/* If this row is a batch head, this variable
|
|
|
|
* holds the element count of the entire batch */
|
|
|
|
GLsizei vboBatchCount;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
ScanRow(TilemapPrivate *p, Viewport *viewport, size_t index);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
void draw();
|
|
|
|
void drawInt();
|
|
|
|
|
2013-09-27 02:42:22 +00:00
|
|
|
void initUpdateZ();
|
2013-10-13 10:58:56 +00:00
|
|
|
void finiUpdateZ(ScanRow *prev);
|
2013-09-01 14:27:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct TilemapPrivate
|
|
|
|
{
|
|
|
|
Viewport *viewport;
|
|
|
|
|
|
|
|
Tilemap::Autotiles autotilesProxy;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
Bitmap *autotiles[autotileCount];
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
Bitmap *tileset;
|
|
|
|
Table *mapData;
|
|
|
|
Table *flashData;
|
|
|
|
Table *priorities;
|
|
|
|
bool visible;
|
|
|
|
Vec2i offset;
|
|
|
|
|
|
|
|
Vec2i dispPos;
|
|
|
|
|
|
|
|
/* Tile atlas */
|
|
|
|
struct {
|
2013-09-06 10:26:41 +00:00
|
|
|
TEXFBO gl;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
Vec2i size;
|
|
|
|
|
2013-09-29 23:38:46 +00:00
|
|
|
/* Effective tileset height,
|
|
|
|
* clamped to a multiple of 32 */
|
|
|
|
int efTilesetH;
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
/* Indices of usable
|
|
|
|
* (not null, not disposed) autotiles */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<uint8_t> usableATs;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
/* Indices of animated autotiles */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<uint8_t> animatedATs;
|
2013-09-01 14:27:21 +00:00
|
|
|
} atlas;
|
|
|
|
|
|
|
|
/* Map size in tiles */
|
|
|
|
int mapWidth;
|
|
|
|
int mapHeight;
|
|
|
|
|
|
|
|
/* Ground layer vertices */
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
TileVBuffer groundVert;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Scanrow vertices */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<TileVBuffer> scanrowVert;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Base quad indices of each scanrow
|
|
|
|
* in the shared buffer */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<int> scanrowBases;
|
|
|
|
size_t scanrowCount;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Shared buffers for all tiles */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
VAO::ID vao;
|
|
|
|
VBO::ID vbo;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
bool animated;
|
|
|
|
|
|
|
|
/* Size of an IBO buffer frame, in bytes */
|
|
|
|
GLintptr bufferFrameSize;
|
|
|
|
|
|
|
|
/* Animation state */
|
|
|
|
uint8_t frameIdx;
|
|
|
|
uint8_t aniIdx;
|
2013-09-01 14:27:21 +00:00
|
|
|
} tiles;
|
|
|
|
|
|
|
|
/* Flash buffers */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
VAO::ID vao;
|
|
|
|
VBO::ID vbo;
|
2013-12-26 19:18:33 +00:00
|
|
|
size_t quadCount;
|
2013-09-23 06:27:28 +00:00
|
|
|
uint8_t alphaIdx;
|
2013-09-01 14:27:21 +00:00
|
|
|
} flash;
|
|
|
|
|
|
|
|
/* Scene elements */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
GroundLayer *ground;
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<ScanRow*> scanrows;
|
2013-09-01 14:27:21 +00:00
|
|
|
Scene::Geometry sceneGeo;
|
|
|
|
Vec2i sceneOffset;
|
2013-09-27 02:42:22 +00:00
|
|
|
|
|
|
|
/* The ground and scanrow elements' creationStamp
|
|
|
|
* should be aquired once (at Tilemap construction)
|
|
|
|
* instead of regenerated everytime the elements are
|
|
|
|
* (re)created. Scanrows can share one stamp because
|
|
|
|
* their z always differs anway */
|
|
|
|
unsigned int groundStamp;
|
|
|
|
unsigned int scanrowStamp;
|
2013-09-01 14:27:21 +00:00
|
|
|
} elem;
|
|
|
|
|
|
|
|
/* Replica bitmask */
|
2013-09-04 11:30:14 +00:00
|
|
|
uint8_t replicas;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Affected by: autotiles, tileset */
|
|
|
|
bool atlasSizeDirty;
|
|
|
|
/* Affected by: autotiles(.changed), tileset(.changed), allocateAtlas */
|
|
|
|
bool atlasDirty;
|
|
|
|
/* Affected by: mapData(.changed), priorities(.changed) */
|
|
|
|
bool buffersDirty;
|
|
|
|
/* Affected by: oy */
|
|
|
|
bool zOrderDirty;
|
|
|
|
/* Affected by: flashData, buffersDirty */
|
|
|
|
bool flashDirty;
|
|
|
|
|
|
|
|
/* Resources are sufficient and tilemap is ready to be drawn */
|
|
|
|
bool tilemapReady;
|
|
|
|
|
|
|
|
/* Change watches */
|
|
|
|
sigc::connection tilesetCon;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
sigc::connection autotilesCon[autotileCount];
|
2013-09-01 14:27:21 +00:00
|
|
|
sigc::connection mapDataCon;
|
|
|
|
sigc::connection prioritiesCon;
|
|
|
|
sigc::connection flashDataCon;
|
|
|
|
|
|
|
|
/* Dispose watches */
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
sigc::connection autotilesDispCon[autotileCount];
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Draw prepare call */
|
|
|
|
sigc::connection prepareCon;
|
|
|
|
|
|
|
|
TilemapPrivate(Viewport *viewport)
|
|
|
|
: viewport(viewport),
|
|
|
|
tileset(0),
|
|
|
|
mapData(0),
|
|
|
|
flashData(0),
|
|
|
|
priorities(0),
|
|
|
|
visible(true),
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
mapWidth(0),
|
|
|
|
mapHeight(0),
|
2013-09-01 14:27:21 +00:00
|
|
|
replicas(Normal),
|
|
|
|
atlasSizeDirty(false),
|
|
|
|
atlasDirty(false),
|
|
|
|
buffersDirty(false),
|
|
|
|
zOrderDirty(false),
|
|
|
|
flashDirty(false),
|
|
|
|
tilemapReady(false)
|
|
|
|
{
|
|
|
|
memset(autotiles, 0, sizeof(autotiles));
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
atlas.animatedATs.reserve(autotileCount);
|
2013-09-29 23:38:46 +00:00
|
|
|
atlas.efTilesetH = 0;
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
tiles.animated = false;
|
|
|
|
tiles.frameIdx = 0;
|
|
|
|
tiles.aniIdx = 0;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Init tile buffers */
|
|
|
|
tiles.vbo = VBO::gen();
|
|
|
|
|
|
|
|
tiles.vao = VAO::gen();
|
|
|
|
VAO::bind(tiles.vao);
|
2013-09-23 05:15:01 +00:00
|
|
|
|
|
|
|
glEnableVertexAttribArray(Shader::Position);
|
|
|
|
glEnableVertexAttribArray(Shader::TexCoord);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VBO::bind(tiles.vbo);
|
2013-10-09 10:30:33 +00:00
|
|
|
shState->bindQuadIBO();
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), SVertex::posOffset());
|
|
|
|
glVertexAttribPointer(Shader::TexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), SVertex::texPosOffset());
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VAO::unbind();
|
|
|
|
VBO::unbind();
|
|
|
|
IBO::unbind();
|
|
|
|
|
|
|
|
/* Init flash buffers */
|
|
|
|
flash.vbo = VBO::gen();
|
|
|
|
flash.vao = VAO::gen();
|
|
|
|
flash.quadCount = 0;
|
2013-09-23 06:27:28 +00:00
|
|
|
flash.alphaIdx = 0;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VAO::bind(flash.vao);
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
glEnableVertexAttribArray(Shader::Color);
|
|
|
|
glEnableVertexAttribArray(Shader::Position);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VBO::bind(flash.vbo);
|
2013-10-09 10:30:33 +00:00
|
|
|
shState->bindQuadIBO();
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
glVertexAttribPointer(Shader::Color, 4, GL_FLOAT, GL_FALSE, sizeof(CVertex), CVertex::colorOffset());
|
|
|
|
glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(CVertex), CVertex::posOffset());
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VAO::unbind();
|
|
|
|
VBO::unbind();
|
|
|
|
IBO::unbind();
|
|
|
|
|
|
|
|
elem.ground = 0;
|
|
|
|
|
2013-10-09 10:30:33 +00:00
|
|
|
elem.groundStamp = shState->genTimeStamp();
|
|
|
|
elem.scanrowStamp = shState->genTimeStamp();
|
2013-09-27 02:42:22 +00:00
|
|
|
|
2013-10-09 10:30:33 +00:00
|
|
|
prepareCon = shState->prepareDraw.connect
|
2013-09-01 14:27:21 +00:00
|
|
|
(sigc::mem_fun(this, &TilemapPrivate::prepare));
|
|
|
|
}
|
|
|
|
|
|
|
|
~TilemapPrivate()
|
|
|
|
{
|
|
|
|
destroyElements();
|
|
|
|
|
2013-10-22 04:36:13 +00:00
|
|
|
shState->releaseAtlasTex(atlas.gl);
|
2013-09-01 14:27:21 +00:00
|
|
|
VAO::del(tiles.vao);
|
|
|
|
VBO::del(tiles.vbo);
|
|
|
|
|
|
|
|
VAO::del(flash.vao);
|
|
|
|
VBO::del(flash.vbo);
|
|
|
|
|
|
|
|
tilesetCon.disconnect();
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < autotileCount; ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
autotilesCon[i].disconnect();
|
|
|
|
autotilesDispCon[i].disconnect();
|
|
|
|
}
|
|
|
|
mapDataCon.disconnect();
|
|
|
|
prioritiesCon.disconnect();
|
|
|
|
flashDataCon.disconnect();
|
|
|
|
|
|
|
|
prepareCon.disconnect();
|
|
|
|
}
|
|
|
|
|
2013-09-24 18:11:55 +00:00
|
|
|
uint8_t bufferCount() const
|
|
|
|
{
|
|
|
|
return tiles.animated ? 4 : 1;
|
|
|
|
}
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
void updateAtlasInfo()
|
|
|
|
{
|
|
|
|
if (!tileset || tileset->isDisposed())
|
|
|
|
{
|
|
|
|
atlas.size = Vec2i();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-09-29 23:38:46 +00:00
|
|
|
int tsH = tileset->height();
|
|
|
|
atlas.efTilesetH = tsH - (tsH % 32);
|
|
|
|
|
|
|
|
atlas.size = TileAtlas::minSize(atlas.efTilesetH, glState.caps.maxTexSize);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
if (atlas.size.x < 0)
|
|
|
|
throw Exception(Exception::MKXPError,
|
|
|
|
"Cannot allocate big enough texture for tileset atlas");
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateAutotileInfo()
|
|
|
|
{
|
|
|
|
/* Check if and which autotiles are animated */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<uint8_t> &usableATs = atlas.usableATs;
|
|
|
|
std::vector<uint8_t> &animatedATs = atlas.animatedATs;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
usableATs.clear();
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < autotileCount; ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
|
|
|
if (!autotiles[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (autotiles[i]->isDisposed())
|
|
|
|
continue;
|
|
|
|
|
2013-10-09 16:07:19 +00:00
|
|
|
if (autotiles[i]->megaSurface())
|
|
|
|
continue;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
usableATs.push_back(i);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
if (autotiles[i]->width() > autotileW)
|
2013-12-26 19:18:33 +00:00
|
|
|
animatedATs.push_back(i);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tiles.animated = !animatedATs.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateMapDataInfo()
|
|
|
|
{
|
|
|
|
if (!mapData)
|
|
|
|
{
|
|
|
|
mapWidth = 0;
|
|
|
|
mapHeight = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapWidth = mapData->xSize();
|
|
|
|
mapHeight = mapData->ySize();
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
void updateSceneGeometry(const Scene::Geometry &geo)
|
|
|
|
{
|
|
|
|
elem.sceneOffset.x = geo.rect.x - geo.xOrigin;
|
|
|
|
elem.sceneOffset.y = geo.rect.y - geo.yOrigin;
|
|
|
|
elem.sceneGeo = geo;
|
|
|
|
}
|
|
|
|
|
|
|
|
void updatePosition()
|
|
|
|
{
|
|
|
|
if (mapWidth == 0 || mapHeight == 0)
|
|
|
|
return;
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
dispPos.x = -offset.x + elem.sceneOffset.x;
|
|
|
|
dispPos.y = -offset.y + elem.sceneOffset.y;
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
dispPos.x %= mapWidth * 32;
|
|
|
|
dispPos.y %= mapHeight * 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute necessary replicas and store this
|
|
|
|
* information in a bitfield */
|
|
|
|
void updateReplicas()
|
|
|
|
{
|
|
|
|
replicas = Normal;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
if (mapWidth == 0 || mapHeight == 0)
|
|
|
|
return;
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
const IntRect &sRect = elem.sceneGeo.rect;
|
|
|
|
|
|
|
|
if (dispPos.x > sRect.x)
|
|
|
|
replicas |= Left;
|
|
|
|
if (dispPos.y > sRect.y)
|
|
|
|
replicas |= Top;
|
|
|
|
if (dispPos.x+mapWidth*32 < sRect.x+sRect.w)
|
|
|
|
replicas |= Right;
|
|
|
|
if (dispPos.y+mapHeight*32 < sRect.y+sRect.h)
|
|
|
|
replicas |= Bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidateAtlasSize()
|
|
|
|
{
|
|
|
|
atlasSizeDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidateAtlasContents()
|
|
|
|
{
|
|
|
|
atlasDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidateBuffers()
|
|
|
|
{
|
|
|
|
buffersDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidateFlash()
|
|
|
|
{
|
|
|
|
flashDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks for the minimum amount of data needed to display */
|
|
|
|
bool verifyResources()
|
|
|
|
{
|
|
|
|
if (!tileset)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (tileset->isDisposed())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!mapData)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocates correctly sized TexFBO for atlas */
|
|
|
|
void allocateAtlas()
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
updateAtlasInfo();
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Aquire atlas tex */
|
2013-10-22 04:36:13 +00:00
|
|
|
shState->releaseAtlasTex(atlas.gl);
|
|
|
|
shState->requestAtlasTex(atlas.size.x, atlas.size.y, atlas.gl);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
atlasDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assembles atlas from tileset and autotile bitmaps */
|
|
|
|
void buildAtlas()
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
updateAutotileInfo();
|
|
|
|
|
2014-01-16 18:16:09 +00:00
|
|
|
TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Clear atlas */
|
2013-09-06 12:56:30 +00:00
|
|
|
FBO::bind(atlas.gl.fbo, FBO::Draw);
|
2013-09-01 14:27:21 +00:00
|
|
|
glState.clearColor.pushSet(Vec4());
|
|
|
|
glState.scissorTest.pushSet(false);
|
|
|
|
|
2013-10-01 11:10:14 +00:00
|
|
|
FBO::clear();
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
glState.scissorTest.pop();
|
|
|
|
glState.clearColor.pop();
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
/* Blit autotiles */
|
2013-12-27 05:19:30 +00:00
|
|
|
for (size_t i = 0; i < atlas.usableATs.size(); ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
2013-12-27 05:19:30 +00:00
|
|
|
const uint8_t atInd = atlas.usableATs[i];
|
|
|
|
Bitmap *autotile = autotiles[atInd];
|
|
|
|
|
|
|
|
int blitW = std::min(autotile->width(), atAreaW);
|
|
|
|
int blitH = std::min(autotile->height(), atAreaH);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-27 05:19:30 +00:00
|
|
|
FBO::bind(autotile->getGLTypes().fbo, FBO::Read);
|
|
|
|
FBO::blit(0, 0, 0, atInd*autotileH, blitW, blitH);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
2013-09-01 14:27:21 +00:00
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
/* Blit tileset */
|
|
|
|
if (tileset->megaSurface())
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
/* Mega surface tileset */
|
|
|
|
FBO::unbind(FBO::Draw);
|
|
|
|
TEX::bind(atlas.gl.tex);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
SDL_Surface *tsSurf = tileset->megaSurface();
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < blits.size(); ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
2013-12-27 05:11:18 +00:00
|
|
|
const TileAtlas::Blit &blitOp = blits[i];
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-10-16 17:20:36 +00:00
|
|
|
PixelStore::setupSubImage(tsSurf->w, blitOp.src.x, blitOp.src.y);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-10-16 17:20:36 +00:00
|
|
|
TEX::uploadSubImage(blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf->pixels, GL_RGBA);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
2013-10-16 17:20:36 +00:00
|
|
|
|
|
|
|
PixelStore::reset();
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Regular tileset */
|
|
|
|
FBO::bind(tileset->getGLTypes().fbo, FBO::Read);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < blits.size(); ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
2013-12-27 05:11:18 +00:00
|
|
|
const TileAtlas::Blit &blitOp = blits[i];
|
2013-09-01 14:27:21 +00:00
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
FBO::blit(blitOp.src.x, blitOp.src.y, blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h);
|
|
|
|
}
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int samplePriority(int tileInd)
|
|
|
|
{
|
|
|
|
if (!priorities)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (tileInd > priorities->xSize()-1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int value = priorities->at(tileInd);
|
|
|
|
|
|
|
|
if (value > 5)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
FloatRect getAutotilePieceRect(int x, int y, /* in pixel coords */
|
|
|
|
int corner)
|
|
|
|
{
|
|
|
|
switch (corner)
|
|
|
|
{
|
|
|
|
case 0 : break;
|
|
|
|
case 1 : x += 16; break;
|
|
|
|
case 2 : x += 16; y += 16; break;
|
|
|
|
case 3 : y += 16; break;
|
|
|
|
default: abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
return FloatRect(x, y, 16, 16);
|
|
|
|
}
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
void handleAutotile(int x, int y, int tileInd, TileVBuffer *array)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
/* Which autotile [0-7] */
|
|
|
|
int atInd = tileInd / 48 - 1;
|
|
|
|
/* Which tile pattern of the autotile [0-47] */
|
|
|
|
int subInd = tileInd % 48;
|
|
|
|
|
|
|
|
const StaticRect *pieceRect = &autotileRects[subInd*4];
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
/* Iterate over the 4 tile pieces */
|
2013-09-01 14:27:21 +00:00
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
FloatRect posRect = getAutotilePieceRect(x*32, y*32, i);
|
|
|
|
FloatRect texRect = pieceRect[i];
|
|
|
|
|
|
|
|
/* Adjust to atlas coordinates */
|
|
|
|
texRect.y += atInd * autotileH;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t k = 0; k < bufferCount(); ++k)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
|
|
|
FloatRect _texRect = texRect;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
if (contains(atlas.animatedATs, atInd))
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
_texRect.x += autotileW*k;
|
|
|
|
|
|
|
|
SVertex v[4];
|
|
|
|
Quad::setTexPosRect(v, _texRect, posRect);
|
|
|
|
|
|
|
|
/* Iterate over 4 vertices */
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < 4; ++i)
|
|
|
|
array->v[k].push_back(v[i]);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleTile(int x, int y, int z)
|
|
|
|
{
|
|
|
|
int tileInd = mapData->at(x, y, z);
|
|
|
|
|
|
|
|
/* Check for empty space */
|
|
|
|
if (tileInd < 48)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int prio = samplePriority(tileInd);
|
|
|
|
|
|
|
|
/* Check for faulty data */
|
|
|
|
if (prio == -1)
|
|
|
|
return;
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
TileVBuffer *targetArray;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
/* Prio 0 tiles are all part of the same ground layer */
|
|
|
|
if (prio == 0)
|
|
|
|
{
|
|
|
|
targetArray = &groundVert;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int scanInd = y + prio;
|
|
|
|
targetArray = &scanrowVert[scanInd];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for autotile */
|
|
|
|
if (tileInd < 48*8)
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
handleAutotile(x, y, tileInd, targetArray);
|
2013-09-01 14:27:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tsInd = tileInd - 48*8;
|
|
|
|
int tileX = tsInd % 8;
|
|
|
|
int tileY = tsInd / 8;
|
|
|
|
|
2013-09-29 23:38:46 +00:00
|
|
|
Vec2i texPos = TileAtlas::tileToAtlasCoor(tileX, tileY, atlas.efTilesetH, atlas.size.y);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
FloatRect texRect((float) texPos.x+.5, (float) texPos.y+.5, 31, 31);
|
2013-09-01 14:27:21 +00:00
|
|
|
FloatRect posRect(x*32, y*32, 32, 32);
|
|
|
|
|
|
|
|
SVertex v[4];
|
|
|
|
Quad::setTexPosRect(v, texRect, posRect);
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t k = 0; k < bufferCount(); ++k)
|
|
|
|
for (size_t i = 0; i < 4; ++i)
|
|
|
|
targetArray->v[k].push_back(v[i]);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void clearQuadArrays()
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < 4; ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
groundVert.v[i].clear();
|
2013-12-26 19:18:33 +00:00
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
scanrowVert.clear();
|
|
|
|
scanrowBases.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void buildQuadArray()
|
|
|
|
{
|
|
|
|
clearQuadArrays();
|
|
|
|
|
|
|
|
int mapDepth = mapData->zSize();
|
|
|
|
|
|
|
|
scanrowVert.resize(mapHeight + 5);
|
|
|
|
|
|
|
|
for (int x = 0; x < mapWidth; ++x)
|
|
|
|
for (int y = 0; y < mapHeight; ++y)
|
|
|
|
for (int z = 0; z < mapDepth; ++z)
|
|
|
|
handleTile(x, y, z);
|
|
|
|
}
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
static size_t quadDataSize(size_t quadCount)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
return quadCount * sizeof(SVertex) * 4;
|
|
|
|
}
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
size_t scanrowSize(size_t index)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
return scanrowBases[index+1] - scanrowBases[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
void uploadBuffers()
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
scanrowCount = scanrowVert.size();
|
2013-09-01 14:27:21 +00:00
|
|
|
scanrowBases.resize(scanrowCount + 1);
|
|
|
|
|
|
|
|
/* Calculate total quad count */
|
2013-12-26 19:18:33 +00:00
|
|
|
size_t groundQuadCount = groundVert.v[0].size() / 4;
|
|
|
|
size_t quadCount = groundQuadCount;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < scanrowCount; ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
scanrowBases[i] = quadCount;
|
2013-12-26 19:18:33 +00:00
|
|
|
quadCount += scanrowVert[i].v[0].size() / 4;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
scanrowBases[scanrowCount] = quadCount;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
size_t bufferFrameQuadCount = quadCount;
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
tiles.bufferFrameSize = quadCount * 6 * sizeof(uint32_t);
|
|
|
|
|
2013-09-24 18:11:55 +00:00
|
|
|
quadCount *= bufferCount();
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
VBO::bind(tiles.vbo);
|
|
|
|
VBO::allocEmpty(quadDataSize(quadCount));
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t k = 0; k < bufferCount(); ++k)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
VBO::uploadSubData(k*quadDataSize(bufferFrameQuadCount),
|
2013-12-26 19:18:33 +00:00
|
|
|
quadDataSize(groundQuadCount), &groundVert.v[k][0]);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < scanrowCount; ++i)
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
{
|
|
|
|
if (scanrowVert[i].v[0].empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VBO::uploadSubData(k*quadDataSize(bufferFrameQuadCount) + quadDataSize(scanrowBases[i]),
|
2014-01-01 11:56:45 +00:00
|
|
|
quadDataSize(scanrowSize(i)), &scanrowVert[i].v[k][0]);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
}
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VBO::unbind();
|
|
|
|
|
|
|
|
/* Ensure global IBO size */
|
2013-10-09 10:30:33 +00:00
|
|
|
shState->ensureQuadIBO(quadCount*bufferCount());
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
void bindAtlas(SimpleShader &shader)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
2013-09-06 10:26:41 +00:00
|
|
|
TEX::bind(atlas.gl.tex);
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
shader.setTexSize(atlas.size);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Vec2i getReplicaOffset(Position pos)
|
|
|
|
{
|
|
|
|
Vec2i offset;
|
|
|
|
|
|
|
|
if (pos & Left)
|
|
|
|
offset.x -= mapWidth*32;
|
|
|
|
if (pos & Right)
|
|
|
|
offset.x += mapWidth*32;
|
|
|
|
if (pos & Top)
|
|
|
|
offset.y -= mapHeight*32;
|
|
|
|
if (pos & Bottom)
|
|
|
|
offset.y += mapHeight*32;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
void setTranslation(Position replicaPos, ShaderBase &shader)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
Vec2i repOff = getReplicaOffset(replicaPos);
|
2013-09-23 05:15:01 +00:00
|
|
|
repOff += dispPos;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
shader.setTranslation(repOff);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool sampleFlashColor(Vec4 &out, int x, int y)
|
|
|
|
{
|
|
|
|
const int _x = x % flashData->xSize();
|
|
|
|
const int _y = y % flashData->ySize();
|
|
|
|
|
|
|
|
int16_t packed = flashData->at(_x, _y);
|
|
|
|
|
|
|
|
if (packed == 0)
|
|
|
|
return false;
|
|
|
|
|
2013-09-23 06:27:28 +00:00
|
|
|
const float max = 0xF;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-09-23 06:27:28 +00:00
|
|
|
float b = ((packed & 0x000F) >> 0) / max;
|
|
|
|
float g = ((packed & 0x00F0) >> 4) / max;
|
|
|
|
float r = ((packed & 0x0F00) >> 8) / max;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
out = Vec4(r, g, b, 1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateFlash()
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<CVertex> vertices;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
for (int x = 0; x < mapWidth; ++x)
|
|
|
|
for (int y = 0; y < mapHeight; ++y)
|
|
|
|
{
|
|
|
|
Vec4 color;
|
|
|
|
if (!sampleFlashColor(color, x, y))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
FloatRect posRect(x*32, y*32, 32, 32);
|
|
|
|
|
|
|
|
CVertex v[4];
|
|
|
|
Quad::setPosRect(v, posRect);
|
|
|
|
Quad::setColor(v, color);
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < 4; ++i)
|
|
|
|
vertices.push_back(v[i]);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
flash.quadCount = vertices.size() / 4;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
if (flash.quadCount == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VBO::bind(flash.vbo);
|
2013-12-26 19:18:33 +00:00
|
|
|
VBO::uploadData(sizeof(CVertex) * vertices.size(), &vertices[0]);
|
2013-09-01 14:27:21 +00:00
|
|
|
VBO::unbind();
|
|
|
|
|
|
|
|
/* Ensure global IBO size */
|
2013-10-09 10:30:33 +00:00
|
|
|
shState->ensureQuadIBO(flash.quadCount);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void destroyElements()
|
|
|
|
{
|
|
|
|
delete elem.ground;
|
|
|
|
elem.ground = 0;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < elem.scanrows.size(); ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
delete elem.scanrows[i];
|
|
|
|
|
|
|
|
elem.scanrows.clear();
|
|
|
|
}
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
void generateElements(std::vector<int> &scanrowInd)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
elem.ground = new GroundLayer(this, viewport);
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < scanrowInd.size(); ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
int index = scanrowInd[i];
|
2013-12-26 19:18:33 +00:00
|
|
|
elem.scanrows.push_back(new ScanRow(this, viewport, index));
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void generateSceneElements()
|
|
|
|
{
|
|
|
|
destroyElements();
|
|
|
|
|
|
|
|
/* Only generate elements for non-emtpy scanrows */
|
2013-12-26 19:18:33 +00:00
|
|
|
std::vector<int> scanrowInd;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < scanrowCount; ++i)
|
|
|
|
if (scanrowVert[i].v[0].size() > 0)
|
|
|
|
scanrowInd.push_back(i);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
generateElements(scanrowInd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateZOrder()
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
if (elem.scanrows.empty())
|
2013-10-13 10:58:56 +00:00
|
|
|
return;
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < elem.scanrows.size(); ++i)
|
2013-09-27 02:42:22 +00:00
|
|
|
elem.scanrows[i]->initUpdateZ();
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
ScanRow *prev = elem.scanrows.front();
|
2013-10-13 10:58:56 +00:00
|
|
|
prev->finiUpdateZ(0);
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 1; i < elem.scanrows.size(); ++i)
|
2013-10-13 10:58:56 +00:00
|
|
|
{
|
|
|
|
ScanRow *row = elem.scanrows[i];
|
|
|
|
row->finiUpdateZ(prev);
|
|
|
|
prev = row;
|
|
|
|
}
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-10-13 20:00:38 +00:00
|
|
|
/* When there are two or more scanrows with no other
|
|
|
|
* elements between them in the scene list, we can
|
|
|
|
* render them in a batch (as the scanrow data itself
|
|
|
|
* is ordered sequentially in VRAM). Every frame, we
|
|
|
|
* scan the scene list for such sequential rows and
|
|
|
|
* batch them up for drawing. The first row of the batch
|
|
|
|
* (the "batch head") executes the draw call, all others
|
|
|
|
* are muted via the 'batchedFlag'. For simplicity,
|
|
|
|
* single sized batches are possible. */
|
|
|
|
void prepareScanrowBatches()
|
|
|
|
{
|
2013-12-26 19:18:33 +00:00
|
|
|
const std::vector<ScanRow*> &scanrows = elem.scanrows;
|
2013-10-13 20:00:38 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < scanrows.size(); ++i)
|
2013-10-13 20:00:38 +00:00
|
|
|
{
|
|
|
|
ScanRow *batchHead = scanrows[i];
|
|
|
|
batchHead->batchedFlag = false;
|
|
|
|
|
|
|
|
GLsizei vboBatchCount = batchHead->vboCount;
|
|
|
|
IntruListLink<SceneElement> *iter = &batchHead->link;
|
|
|
|
|
|
|
|
for (i = i+1; i < scanrows.size(); ++i)
|
|
|
|
{
|
|
|
|
iter = iter->next;
|
|
|
|
ScanRow *row = scanrows[i];
|
|
|
|
|
|
|
|
/* Check if the next SceneElement is also
|
|
|
|
* the next scanrow in our list. If not,
|
|
|
|
* the current batch is complete */
|
|
|
|
if (iter != &row->link)
|
|
|
|
break;
|
|
|
|
|
|
|
|
vboBatchCount += row->vboCount;
|
|
|
|
row->batchedFlag = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
batchHead->vboBatchCount = vboBatchCount;
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
void prepare()
|
|
|
|
{
|
|
|
|
if (!verifyResources())
|
|
|
|
{
|
|
|
|
if (elem.ground)
|
|
|
|
destroyElements();
|
|
|
|
tilemapReady = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (atlasSizeDirty)
|
|
|
|
{
|
|
|
|
allocateAtlas();
|
|
|
|
atlasSizeDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (atlasDirty)
|
|
|
|
{
|
|
|
|
buildAtlas();
|
|
|
|
atlasDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffersDirty)
|
|
|
|
{
|
|
|
|
buildQuadArray();
|
|
|
|
uploadBuffers();
|
|
|
|
generateSceneElements();
|
|
|
|
buffersDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flashDirty)
|
|
|
|
{
|
|
|
|
updateFlash();
|
|
|
|
flashDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zOrderDirty)
|
|
|
|
{
|
|
|
|
updateZOrder();
|
|
|
|
zOrderDirty = false;
|
|
|
|
}
|
|
|
|
|
2013-10-13 20:00:38 +00:00
|
|
|
prepareScanrowBatches();
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
tilemapReady = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport)
|
2013-09-27 02:42:22 +00:00
|
|
|
: ViewportElement(viewport, 0, p->elem.groundStamp),
|
2013-09-01 14:27:21 +00:00
|
|
|
p(p)
|
|
|
|
{
|
|
|
|
vboCount = p->scanrowBases[0] * 6;
|
|
|
|
|
|
|
|
onGeometryChange(scene->getGeometry());
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroundLayer::draw()
|
|
|
|
{
|
2013-12-11 04:22:13 +00:00
|
|
|
SimpleShader &shader = shState->shaders().simple;
|
2013-09-23 05:15:01 +00:00
|
|
|
shader.bind();
|
|
|
|
shader.applyViewportProj();
|
|
|
|
|
|
|
|
p->bindAtlas(shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VAO::bind(p->tiles.vao);
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
p->setTranslation(Normal, shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < positionsN; ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
const Position pos = positions[i];
|
|
|
|
|
|
|
|
if (!(p->replicas & pos))
|
|
|
|
continue;
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
p->setTranslation(pos, shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
drawInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->flash.quadCount > 0)
|
|
|
|
{
|
|
|
|
VAO::bind(p->flash.vao);
|
|
|
|
glState.blendMode.pushSet(BlendAddition);
|
|
|
|
glState.texture2D.pushSet(false);
|
|
|
|
|
2013-12-11 04:22:13 +00:00
|
|
|
FlashMapShader &shader = shState->shaders().flashMap;
|
2013-09-23 05:15:01 +00:00
|
|
|
shader.bind();
|
|
|
|
shader.applyViewportProj();
|
2013-09-23 06:27:28 +00:00
|
|
|
shader.setAlpha(flashAlpha[p->flash.alphaIdx] / 255.f);
|
2013-09-23 05:15:01 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < positionsN; ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
const Position pos = positions[i];
|
|
|
|
|
|
|
|
if (!(p->replicas & pos))
|
|
|
|
continue;
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
p->setTranslation(pos, shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
drawFlashInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
glState.texture2D.pop();
|
|
|
|
glState.blendMode.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
VAO::unbind();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroundLayer::drawInt()
|
|
|
|
{
|
|
|
|
glDrawElements(GL_TRIANGLES, vboCount,
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
GL_UNSIGNED_INT, (GLvoid*) (p->tiles.frameIdx * p->tiles.bufferFrameSize));
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GroundLayer::drawFlashInt()
|
|
|
|
{
|
|
|
|
glDrawElements(GL_TRIANGLES, p->flash.quadCount * 6, GL_UNSIGNED_INT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
|
|
|
|
{
|
|
|
|
p->updateSceneGeometry(geo);
|
|
|
|
p->updatePosition();
|
|
|
|
p->updateReplicas();
|
|
|
|
}
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
ScanRow::ScanRow(TilemapPrivate *p, Viewport *viewport, size_t index)
|
2013-09-27 02:42:22 +00:00
|
|
|
: ViewportElement(viewport, 32 + index*32, p->elem.scanrowStamp),
|
2013-09-01 14:27:21 +00:00
|
|
|
index(index),
|
2013-10-13 20:00:38 +00:00
|
|
|
p(p),
|
|
|
|
vboBatchCount(0)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
vboOffset = p->scanrowBases[index] * sizeof(uint32_t) * 6;
|
2013-09-01 14:27:21 +00:00
|
|
|
vboCount = p->scanrowSize(index) * 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanRow::draw()
|
|
|
|
{
|
2013-10-13 20:00:38 +00:00
|
|
|
if (batchedFlag)
|
|
|
|
return;
|
|
|
|
|
2013-12-11 04:22:13 +00:00
|
|
|
SimpleShader &shader = shState->shaders().simple;
|
2013-09-23 05:15:01 +00:00
|
|
|
shader.bind();
|
|
|
|
shader.applyViewportProj();
|
|
|
|
|
|
|
|
p->bindAtlas(shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
VAO::bind(p->tiles.vao);
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
p->setTranslation(Normal, shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < positionsN; ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
|
|
|
const Position pos = positions[i];
|
|
|
|
|
|
|
|
if (!(p->replicas & pos))
|
|
|
|
continue;
|
|
|
|
|
2013-09-23 05:15:01 +00:00
|
|
|
p->setTranslation(pos, shader);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
drawInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
VAO::unbind();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanRow::drawInt()
|
|
|
|
{
|
2013-10-13 20:00:38 +00:00
|
|
|
glDrawElements(GL_TRIANGLES, vboBatchCount,
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
GL_UNSIGNED_INT, (GLvoid*) (vboOffset + p->tiles.frameIdx * p->tiles.bufferFrameSize));
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-09-27 02:42:22 +00:00
|
|
|
void ScanRow::initUpdateZ()
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
2013-09-27 02:42:22 +00:00
|
|
|
unlink();
|
|
|
|
}
|
|
|
|
|
2013-10-13 10:58:56 +00:00
|
|
|
void ScanRow::finiUpdateZ(ScanRow *prev)
|
2013-09-27 02:42:22 +00:00
|
|
|
{
|
|
|
|
z = 32 * (index+1) - p->offset.y;
|
|
|
|
|
2013-10-13 10:58:56 +00:00
|
|
|
if (prev)
|
|
|
|
scene->insertAfter(*this, *prev);
|
|
|
|
else
|
|
|
|
scene->insert(*this);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (i < 0 || i > autotileCount-1)
|
2013-09-01 14:27:21 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (p->autotiles[i] == bitmap)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->autotiles[i] = bitmap;
|
|
|
|
|
|
|
|
p->invalidateAtlasContents();
|
|
|
|
|
|
|
|
p->autotilesCon[i].disconnect();
|
|
|
|
p->autotilesCon[i] = bitmap->modified.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateAtlasContents));
|
|
|
|
|
|
|
|
p->autotilesDispCon[i].disconnect();
|
|
|
|
p->autotilesDispCon[i] = bitmap->wasDisposed.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateAtlasContents));
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
p->updateAutotileInfo();
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap *Tilemap::Autotiles::get(int i) const
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (i < 0 || i > autotileCount-1)
|
2013-09-01 14:27:21 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return p->autotiles[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
Tilemap::Tilemap(Viewport *viewport)
|
|
|
|
{
|
|
|
|
p = new TilemapPrivate(viewport);
|
|
|
|
p->autotilesProxy.p = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
Tilemap::~Tilemap()
|
|
|
|
{
|
|
|
|
dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::update()
|
|
|
|
{
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (!p->tilemapReady)
|
|
|
|
return;
|
|
|
|
|
2013-09-23 06:27:28 +00:00
|
|
|
/* Animate flash */
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (++p->flash.alphaIdx >= flashAlphaN)
|
2013-09-23 06:27:28 +00:00
|
|
|
p->flash.alphaIdx = 0;
|
|
|
|
|
|
|
|
/* Animate autotiles */
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (!p->tiles.animated)
|
2013-09-01 14:27:21 +00:00
|
|
|
return;
|
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
p->tiles.frameIdx = atAnimation[p->tiles.aniIdx];
|
2013-09-01 14:27:21 +00:00
|
|
|
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
if (++p->tiles.aniIdx >= atAnimationN)
|
|
|
|
p->tiles.aniIdx = 0;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Tilemap::Autotiles &Tilemap::getAutotiles() const
|
|
|
|
{
|
|
|
|
return p->autotilesProxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DISP_CLASS_NAME "tilemap"
|
|
|
|
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, Viewport, Viewport*, p->viewport)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, Tileset, Bitmap*, p->tileset)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, MapData, Table*, p->mapData)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, FlashData, Table*, p->flashData)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, Priorities, Table*, p->priorities)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->offset.x)
|
|
|
|
DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y)
|
|
|
|
|
2013-10-06 07:55:27 +00:00
|
|
|
#ifdef RGSS2
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
void Tilemap::setViewport(Viewport *value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->viewport == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->viewport = value;
|
|
|
|
|
|
|
|
if (!p->tilemapReady)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->elem.ground->setViewport(value);
|
|
|
|
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < p->elem.scanrows.size(); ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
p->elem.scanrows[i]->setViewport(value);
|
|
|
|
}
|
|
|
|
|
2013-10-06 07:55:27 +00:00
|
|
|
#endif
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
void Tilemap::setTileset(Bitmap *value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->tileset == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->tileset = value;
|
|
|
|
|
|
|
|
p->invalidateAtlasSize();
|
|
|
|
p->tilesetCon.disconnect();
|
|
|
|
p->tilesetCon = value->modified.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateAtlasSize));
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
p->updateAtlasInfo();
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setMapData(Table *value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->mapData == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->mapData = value;
|
|
|
|
|
|
|
|
p->invalidateBuffers();
|
|
|
|
p->mapDataCon.disconnect();
|
|
|
|
p->mapDataCon = value->modified.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateBuffers));
|
Implement a new tileset atlas layout to allow for bigger tilesets
The atlas packing algorithm has been reworked to pack autotiles
and tileset very efficiently into a texture, splitting the tileset
in multiple ways and eliminating the previous duplication of image
data in the atlas across "frames". Animation, which these frames
were designed for, is now done via duplicated buffer frames,
ie. each animation frame has its own VBO and IBO data. This was
not done to save on VRAM (hardly less memory is used), but to
make place for the new atlas layout.
Thanks to this new layout, even with a max texture size of 2048,
one can use tilesets with up to 15000 height. Of course, such
a tileset couldn't be stored in a regular Bitmap to begin with,
which is why I also introduced a hack called "mega surfaces":
software surfaces stored in RAM and wrapped inside a Bitmap,
whose sole purpose is to be passed to a Tilemap as tilesets.
Various other minor changes and fixes are included.
2013-09-23 20:21:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
p->updateMapDataInfo();
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setFlashData(Table *value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->flashData == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->flashData = value;
|
|
|
|
|
|
|
|
p->invalidateFlash();
|
|
|
|
p->flashDataCon.disconnect();
|
|
|
|
p->flashDataCon = value->modified.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateFlash));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setPriorities(Table *value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->priorities == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->priorities = value;
|
|
|
|
|
|
|
|
p->invalidateBuffers();
|
|
|
|
p->prioritiesCon.disconnect();
|
|
|
|
p->prioritiesCon = value->modified.connect
|
|
|
|
(sigc::mem_fun(p, &TilemapPrivate::invalidateBuffers));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setVisible(bool value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->visible == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->visible = value;
|
|
|
|
|
|
|
|
if (!p->tilemapReady)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->elem.ground->setVisible(value);
|
2013-12-26 19:18:33 +00:00
|
|
|
for (size_t i = 0; i < p->elem.scanrows.size(); ++i)
|
2013-09-01 14:27:21 +00:00
|
|
|
p->elem.scanrows[i]->setVisible(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setOX(int value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->offset.x == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->offset.x = value;
|
|
|
|
p->updatePosition();
|
|
|
|
p->updateReplicas();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tilemap::setOY(int value)
|
|
|
|
{
|
|
|
|
GUARD_DISPOSED
|
|
|
|
|
|
|
|
if (p->offset.y == value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p->offset.y = value;
|
|
|
|
p->updatePosition();
|
|
|
|
p->updateReplicas();
|
|
|
|
|
2013-09-27 02:42:22 +00:00
|
|
|
p->zOrderDirty = true;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tilemap::releaseResources()
|
|
|
|
{
|
|
|
|
delete p;
|
|
|
|
}
|