mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-29 03:33:48 +00:00
more drafting for tile redering optimization
This is the last commit before the old Element class gets ripped
This commit is contained in:
parent
0818fbcdb4
commit
e8c405cd9e
11 changed files with 591 additions and 65 deletions
|
@ -133,11 +133,11 @@ void Element::updateEffects(float dt)
|
|||
weight = 1.0f-weight;
|
||||
if (weight < 0.125f)
|
||||
weight *= 0.5f;
|
||||
eff->wavy[i].x = sinf(eff->wavyAngleOffset + (float(i)/wavySz)*PI)*float(eff->wavyMagnitude*eff->effectMult)*weight;
|
||||
eff->wavy[i] = sinf(eff->wavyAngleOffset + (float(i)/wavySz)*PI)*float(eff->wavyMagnitude*eff->effectMult)*weight;
|
||||
if (!eff->wavySave.empty())
|
||||
{
|
||||
if (eff->wavyLerpIn < 1)
|
||||
eff->wavy[i].x = eff->wavy[i].x*eff->wavyLerpIn + (eff->wavySave[i].x*(1.0f-eff->wavyLerpIn));
|
||||
eff->wavy[i] = eff->wavy[i]*eff->wavyLerpIn + (eff->wavySave[i]*(1.0f-eff->wavyLerpIn));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,12 +237,8 @@ void Element::setElementEffectByIndex(int eidx)
|
|||
case EFX_WAVY:
|
||||
{
|
||||
|
||||
eff->wavy.resize(e.segsy);
|
||||
eff->wavy.resize(e.segsy, 0.0f);
|
||||
float bity = float(getHeight())/float(e.segsy);
|
||||
for (size_t i = 0; i < eff->wavy.size(); i++)
|
||||
{
|
||||
eff->wavy[i] = Vector(0, -(i*bity));
|
||||
}
|
||||
eff->wavyFlip = e.wavy_flip;
|
||||
eff->wavyMin = bity;
|
||||
eff->wavyMax = bity*1.2f;
|
||||
|
|
|
@ -25,6 +25,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
class Entity;
|
||||
|
||||
enum EFXType
|
||||
{
|
||||
EFX_NONE =-1,
|
||||
EFX_SEGS =0,
|
||||
EFX_ALPHA ,
|
||||
EFX_WAVY ,
|
||||
EFX_MAX
|
||||
};
|
||||
|
||||
enum ElementFlag
|
||||
{
|
||||
|
@ -52,7 +60,7 @@ struct ElementEffectData
|
|||
float hitPerc, effectMult;
|
||||
bool wavyWaving, wavyFlip, touching;
|
||||
Vector touchVel;
|
||||
std::vector<Vector> wavy, wavySave;
|
||||
std::vector<float> wavy, wavySave;
|
||||
int elementEffectIndex; // used by editor only
|
||||
};
|
||||
|
||||
|
|
|
@ -202,15 +202,6 @@ enum FormUpgradeType
|
|||
FORMUPGRADE_MAX
|
||||
};
|
||||
|
||||
enum EFXType
|
||||
{
|
||||
EFX_NONE =-1,
|
||||
EFX_SEGS =0,
|
||||
EFX_ALPHA ,
|
||||
EFX_WAVY ,
|
||||
EFX_MAX
|
||||
};
|
||||
|
||||
enum EmoteType
|
||||
{
|
||||
EMOTE_NAIJAEVILLAUGH = 0,
|
||||
|
|
|
@ -154,7 +154,7 @@ void RenderGrid::setStripPoints(bool vert, const Vector* points, size_t n)
|
|||
}
|
||||
}
|
||||
|
||||
void RenderGrid::setFromWavy(const Vector* wavy, size_t len, float width)
|
||||
void RenderGrid::setFromWavy(const float* wavy, size_t len, float width)
|
||||
{
|
||||
const size_t NX = grid.width() - 1;
|
||||
const size_t H = grid.height();
|
||||
|
@ -165,7 +165,7 @@ void RenderGrid::setFromWavy(const Vector* wavy, size_t len, float width)
|
|||
const size_t wavy_y = (H - y)-1;
|
||||
if (wavy_y < len)
|
||||
{
|
||||
const float tmp = wavy[wavy_y].x * iw;
|
||||
const float tmp = wavy[wavy_y] * iw;
|
||||
Vector * const row = grid.row(y);
|
||||
for (size_t x = 0; x < NX; x++)
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
void setAlpha(size_t x, size_t y, float a);
|
||||
void setSegs(float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
|
||||
void setStripPoints(bool vert, const Vector *points, size_t n);
|
||||
void setFromWavy(const Vector *wavy, size_t len, float width);
|
||||
void setFromWavy(const float *wavy, size_t len, float width);
|
||||
|
||||
size_t width() const { return grid.width(); }
|
||||
size_t height() const { return grid.height(); }
|
||||
|
|
|
@ -32,6 +32,7 @@ class Core;
|
|||
class StateData;
|
||||
class Texture;
|
||||
|
||||
// TODO: move all the other bools from RenderObject here
|
||||
enum RenderObjectFlags
|
||||
{
|
||||
RO_CLEAR = 0x00,
|
||||
|
|
354
BBGE/Tile.cpp
354
BBGE/Tile.cpp
|
@ -1,2 +1,356 @@
|
|||
#include "Tile.h"
|
||||
#include "RenderGrid.h"
|
||||
#include "Tileset.h"
|
||||
#include "Base.h"
|
||||
|
||||
TileStorage::TileStorage(const TileEffectStorage& eff)
|
||||
: effstore(eff)
|
||||
{
|
||||
}
|
||||
|
||||
TileStorage::~TileStorage()
|
||||
{
|
||||
destroyAll();
|
||||
}
|
||||
|
||||
void TileStorage::moveToFront(size_t idx)
|
||||
{
|
||||
_moveToFront(idx);
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
void TileStorage::moveToBack(size_t idx)
|
||||
{
|
||||
_moveToBack(idx);
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
void TileStorage::update(float dt)
|
||||
{
|
||||
for(size_t i = 0; i < indicesToUpdate.size(); ++i)
|
||||
{
|
||||
TileData& t = tiles[indicesToUpdate[i]];
|
||||
assert(t.flags & TILEFLAG_OWN_EFFDATA); // known to be set if this ends up on the list
|
||||
t.eff->update(dt, &t);
|
||||
}
|
||||
}
|
||||
|
||||
void TileStorage::doInteraction(const Vector& pos, const Vector& vel, float mult, float touchWidth)
|
||||
{
|
||||
for(size_t i = 0; i < indicesToCollide.size(); ++i)
|
||||
{
|
||||
TileData& t = tiles[indicesToCollide[i]];
|
||||
t.eff->doInteraction(t, pos, vel, mult, touchWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void TileStorage::_moveToFront(size_t idx)
|
||||
{
|
||||
// move tile to front -> move it to the back of the list, to be rendered last aka on top of everything else
|
||||
TileData tile = tiles[idx];
|
||||
tiles.erase(tiles.begin() + idx);
|
||||
tiles.push_back(tile);
|
||||
}
|
||||
|
||||
void TileStorage::_moveToBack(size_t idx)
|
||||
{
|
||||
// move tile to back -> move it to the front of the list, to be rendered first aka underneath everything else
|
||||
TileData tile = tiles[idx];
|
||||
tiles.erase(tiles.begin() + idx);
|
||||
tiles.insert(tiles.begin(), tile);
|
||||
}
|
||||
|
||||
void TileStorage::moveToOther(TileStorage& other, const size_t *indices, size_t n)
|
||||
{
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
other.tiles.push_back(tiles[indices[i]]);
|
||||
|
||||
std::vector<TileData> tmp;
|
||||
tmp.swap(tiles);
|
||||
tiles.reserve(tmp.size() - n);
|
||||
for(size_t i = 0; i < tmp.size(); ++i)
|
||||
{
|
||||
for(size_t k = 0; k < n; ++i) // not particularly efficient, could be much better by sorting first but eh
|
||||
if(indices[k] == i)
|
||||
goto skip;
|
||||
|
||||
tiles.push_back(tmp[i]);
|
||||
|
||||
skip: ;
|
||||
}
|
||||
|
||||
refreshAll();
|
||||
other.refreshAll();
|
||||
}
|
||||
|
||||
static void dropAttachments(TileData& t)
|
||||
{
|
||||
if(t.flags & TILEFLAG_OWN_EFFDATA)
|
||||
{
|
||||
delete t.eff;
|
||||
t.flags &= ~TILEFLAG_OWN_EFFDATA;
|
||||
}
|
||||
t.eff = NULL;
|
||||
}
|
||||
|
||||
void TileStorage::deleteSome(const size_t* indices, size_t n)
|
||||
{
|
||||
std::vector<TileData> tmp;
|
||||
tmp.swap(tiles);
|
||||
tiles.reserve(tmp.size() - n);
|
||||
|
||||
for(size_t i = 0; i < tmp.size(); ++i)
|
||||
{
|
||||
for(size_t k = 0; k < n; ++i) // not particularly efficient, could be much better by sorting first but eh
|
||||
if(indices[k] == i)
|
||||
{
|
||||
dropAttachments(tmp[i]);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
tiles.push_back(tmp[i]);
|
||||
|
||||
skip: ;
|
||||
}
|
||||
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
void TileStorage::destroyAll()
|
||||
{
|
||||
const size_t n = tiles.size();
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
dropAttachments(tiles[i]);
|
||||
tiles.clear();
|
||||
indicesToCollide.clear();
|
||||
indicesToUpdate.clear();
|
||||
}
|
||||
|
||||
void TileStorage::setTag(unsigned tag, const size_t* indices, size_t n)
|
||||
{
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
tiles[indices[i]].tag = tag;
|
||||
// don't need to refresh here
|
||||
}
|
||||
|
||||
void TileStorage::setEffect(int idx, const size_t* indices, size_t n)
|
||||
{
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
effstore.assignEffect(tiles[indices[i]], idx);
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
void TileStorage::refreshAll()
|
||||
{
|
||||
indicesToCollide.clear();
|
||||
indicesToUpdate.clear();
|
||||
|
||||
const size_t n = tiles.size();
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
{
|
||||
const TileData& t = tiles[i];
|
||||
if(const TileEffectData *e = t.eff)
|
||||
{
|
||||
if(t.flags & TILEFLAG_OWN_EFFDATA)
|
||||
{
|
||||
indicesToUpdate.push_back(i);
|
||||
if(e->efxtype == EFX_WAVY)
|
||||
indicesToCollide.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileStorage::clearSelection()
|
||||
{
|
||||
const size_t n = tiles.size();
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
tiles[i].flags &= ~TILEFLAG_SELECTED;
|
||||
}
|
||||
|
||||
TileEffectData::TileEffectData(const TileEffectConfig& cfg)
|
||||
: efxtype(cfg.type), efxidx(cfg.index)
|
||||
, grid(NULL), blend(BLEND_DEFAULT)
|
||||
{
|
||||
switch(cfg.type)
|
||||
{
|
||||
case EFX_WAVY:
|
||||
{
|
||||
float bity = 20; // FIXME
|
||||
wavy.wavy.resize(cfg.u.wavy.segsy, 0.0f);
|
||||
wavy.flip = cfg.u.wavy.flip;
|
||||
wavy.min = bity;
|
||||
wavy.max = bity*1.2f;
|
||||
|
||||
RenderGrid *g = new RenderGrid(2, cfg.u.wavy.segsy);
|
||||
grid = g;
|
||||
g->gridType = GRID_UNDEFINED; // by default it's GRID_WAVY, but that would reset during update
|
||||
|
||||
wavy.angleOffset = 0;
|
||||
wavy.magnitude = 0;
|
||||
wavy.lerpIn = 0;
|
||||
wavy.hitPerc = 0;
|
||||
wavy.effectMult = 0;
|
||||
wavy.waving = false;
|
||||
wavy.flip = false;
|
||||
wavy.touching = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case EFX_SEGS:
|
||||
{
|
||||
RenderGrid *g = new RenderGrid(cfg.u.segs.x, cfg.u.segs.y);
|
||||
grid = g;
|
||||
g->setSegs(cfg.u.segs.dgox, cfg.u.segs.dgoy, cfg.u.segs.dgmx, cfg.u.segs.dgmy, cfg.u.segs.dgtm, cfg.u.segs.dgo);
|
||||
}
|
||||
break;
|
||||
|
||||
case EFX_ALPHA:
|
||||
{
|
||||
alpha.x = cfg.u.alpha.val0;
|
||||
alpha.interpolateTo(cfg.u.alpha.val1, cfg.u.alpha.time, -1, cfg.u.alpha.pingpong, cfg.u.alpha.ease);
|
||||
blend = cfg.u.alpha.blend;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TileEffectData::~TileEffectData()
|
||||
{
|
||||
delete grid;
|
||||
}
|
||||
|
||||
void TileEffectData::Wavy::update(float dt)
|
||||
{
|
||||
if (touching)
|
||||
{
|
||||
touching = false;
|
||||
float ramp = touchVel.getLength2D()/800.0f;
|
||||
if (ramp < 0) ramp = 0;
|
||||
if (ramp > 1) ramp = 1;
|
||||
|
||||
magnitude = 100 * ramp + 16;
|
||||
|
||||
if (touchVel.x < 0)
|
||||
magnitude = -magnitude;
|
||||
|
||||
angleOffset = (hitPerc-0.5f)*PI;
|
||||
|
||||
wavySave = wavy;
|
||||
lerpIn = 0;
|
||||
}
|
||||
|
||||
if (waving)
|
||||
{
|
||||
// TODO: set waving=false if magnitude==0 ?
|
||||
float spd = PI*1.1f;
|
||||
float magRedSpd = 48;
|
||||
float lerpSpd = 5.0;
|
||||
float wavySz = float(wavy.size());
|
||||
for (size_t i = 0; i < wavy.size(); i++)
|
||||
{
|
||||
float weight = float(i)/wavySz;
|
||||
if (flip)
|
||||
weight = 1.0f-weight;
|
||||
if (weight < 0.125f)
|
||||
weight *= 0.5f;
|
||||
wavy[i] = sinf(angleOffset + (float(i)/wavySz)*PI)*(magnitude*effectMult)*weight;
|
||||
if (!wavySave.empty())
|
||||
{
|
||||
if (lerpIn < 1)
|
||||
wavy[i] = wavy[i] * lerpIn + (wavySave[i] * (1.0f-lerpIn));
|
||||
}
|
||||
}
|
||||
|
||||
if (lerpIn < 1)
|
||||
{
|
||||
lerpIn += dt*lerpSpd;
|
||||
if (lerpIn > 1)
|
||||
lerpIn = 1;
|
||||
}
|
||||
angleOffset += dt*spd;
|
||||
if (magnitude > 0)
|
||||
{
|
||||
magnitude -= magRedSpd*dt;
|
||||
if (magnitude < 0)
|
||||
magnitude = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
magnitude += magRedSpd*dt;
|
||||
if (magnitude > 0)
|
||||
magnitude = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileEffectData::update(float dt, const TileData *t)
|
||||
{
|
||||
switch(efxtype)
|
||||
{
|
||||
case EFX_WAVY:
|
||||
wavy.update(dt);
|
||||
if(const size_t N = wavy.wavy.size())
|
||||
grid->setFromWavy(&wavy.wavy[0], N, t->et->w);
|
||||
break;
|
||||
|
||||
case EFX_SEGS:
|
||||
grid->update(dt);
|
||||
break;
|
||||
|
||||
case EFX_ALPHA:
|
||||
alpha.update(dt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TileEffectData::doInteraction(const TileData& t, const Vector& pos, const Vector& vel, float mult, float touchWidth)
|
||||
{
|
||||
assert(efxtype == EFX_WAVY);
|
||||
|
||||
const Vector tp(t.x, t.y);
|
||||
|
||||
if (pos.x > tp.x-touchWidth && pos.x < tp.x+touchWidth)
|
||||
{
|
||||
float h = t.et->h*t.scaley;
|
||||
float h2 = h * 0.5f;
|
||||
if (pos.y < tp.y+h2 && pos.y > tp.y-h2)
|
||||
{
|
||||
wavy.touching = true;
|
||||
wavy.waving = true;
|
||||
float hitPerc = tp.y - h2 - pos.y;
|
||||
hitPerc /= h;
|
||||
hitPerc = (1.0f-hitPerc)-1.0f;
|
||||
wavy.hitPerc = hitPerc;
|
||||
wavy.touchVel = vel;
|
||||
wavy.effectMult = mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileEffectStorage::assignEffect(TileData& t, int index) const
|
||||
{
|
||||
dropAttachments(t);
|
||||
|
||||
if(index < 0)
|
||||
return;
|
||||
|
||||
size_t idx = size_t(index);
|
||||
|
||||
if(idx < prepared.size() && prepared[idx])
|
||||
{
|
||||
t.eff = prepared[idx];
|
||||
}
|
||||
else if(idx < configs.size())
|
||||
{
|
||||
t.eff = new TileEffectData(configs[idx]);
|
||||
t.flags |= TILEFLAG_OWN_EFFDATA;
|
||||
}
|
||||
}
|
||||
|
||||
void TileEffectStorage::update(float dt)
|
||||
{
|
||||
for(size_t i = 0; i < prepared.size(); ++i)
|
||||
if(TileEffectData *eff = prepared[i])
|
||||
eff->update(dt, NULL);
|
||||
}
|
||||
|
|
137
BBGE/Tile.h
137
BBGE/Tile.h
|
@ -3,9 +3,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include "Vector.h"
|
||||
|
||||
class ElementTemplate;
|
||||
class Texture;
|
||||
#include "EngineEnums.h"
|
||||
|
||||
// A Tile is a very stripped down RenderObject that bypasses the default
|
||||
// rendering pipeline for efficiency reasons.
|
||||
|
@ -23,8 +21,61 @@ class Texture;
|
|||
- Does not have offset, internalOffset, gravity, etc etc that RenderObject has
|
||||
- Parallax scroll factor is solely influenced by layer, not individually
|
||||
- RGB is never tinted, alpha may come from efx
|
||||
|
||||
Further observations:
|
||||
- Aside from EFX_WAVY, all tiles with the same effect index can share a global modulator,
|
||||
ie. the alpha value is the same per-tile unless the tile is spawned when the map is in progress.
|
||||
And on map reload everything is back to the same value for each tile with the same effect and params.
|
||||
So we can totally exclude the editor.
|
||||
|
||||
Gotaches:
|
||||
- Keeping a pointer to a TileData is not safe.
|
||||
*/
|
||||
|
||||
class ElementTemplate;
|
||||
class Texture;
|
||||
class RenderGrid;
|
||||
class TileRender;
|
||||
|
||||
enum EFXType
|
||||
{
|
||||
EFX_SEGS,
|
||||
EFX_ALPHA,
|
||||
EFX_WAVY
|
||||
};
|
||||
|
||||
// static configuration for one effect type
|
||||
struct TileEffectConfig
|
||||
{
|
||||
public:
|
||||
EFXType type;
|
||||
unsigned index;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int x, y;
|
||||
float dgox, dgoy, dgmx, dgmy, dgtm;
|
||||
bool dgo;
|
||||
} segs;
|
||||
|
||||
struct
|
||||
{
|
||||
float radius, min, max;
|
||||
int segsy;
|
||||
bool flip;
|
||||
} wavy;
|
||||
|
||||
struct
|
||||
{
|
||||
float val0, val1, time;
|
||||
bool pingpong, ease;
|
||||
BlendType blend;
|
||||
} alpha;
|
||||
} u;
|
||||
};
|
||||
|
||||
enum TileFlags
|
||||
{
|
||||
TILEFLAG_NONE = 0,
|
||||
|
@ -34,25 +85,95 @@ enum TileFlags
|
|||
TILEFLAG_SOLID_IN = 0x08, // instead of OT_INVISIBLE, generate OT_INVISIBLEIN
|
||||
TILEFLAG_HURT = 0x10, // always generate OT_HURT
|
||||
TILEFLAG_FH = 0x20, // flipped horizontally
|
||||
TILEFLAG_OWN_EFFDATA = 0x40, // tile owns its TileEffectData, can modify & must delete
|
||||
TILEFLAG_HIDDEN = 0x80, // don't render tile
|
||||
TILEFLAG_SELECTED = 0x100
|
||||
};
|
||||
|
||||
// sort-of-POD
|
||||
struct TileData;
|
||||
|
||||
struct TileEffectData
|
||||
{
|
||||
TileEffectData(const TileEffectConfig& cfg);
|
||||
~TileEffectData();
|
||||
void update(float dt, const TileData *t); // optional t needed for EFX_WAVY
|
||||
void doInteraction(const TileData& t, const Vector& pos, const Vector& vel, float mult, float touchWidth);
|
||||
|
||||
const EFXType efxtype;
|
||||
const unsigned efxidx; // index to ElementEffect
|
||||
RenderGrid *grid;
|
||||
InterpolatedVector alpha;
|
||||
BlendType blend;
|
||||
|
||||
struct Wavy
|
||||
{
|
||||
std::vector<float> wavy, wavySave;
|
||||
Vector touchVel;
|
||||
float angleOffset, magnitude, lerpIn;
|
||||
float min, max;
|
||||
float hitPerc, effectMult;
|
||||
bool waving, flip, touching;
|
||||
void update(float dt);
|
||||
};
|
||||
Wavy wavy;
|
||||
};
|
||||
|
||||
// POD and as compact as possible
|
||||
// the idea is that these are linearly adjacent in memory in the order they are rendered,
|
||||
// to maximize cache & prefetch efficiency
|
||||
struct TileData
|
||||
{
|
||||
float x, y, rotation, texscale;
|
||||
Vector scale, beforeScaleOffset;
|
||||
int efx;
|
||||
float scalex, scaley;
|
||||
float beforeScaleOffsetX, beforeScaleOffsetY;
|
||||
unsigned flags; // TileFlags
|
||||
unsigned tag;
|
||||
ElementTemplate *et;
|
||||
ElementTemplate *et; // texture, texcoords, etc is here
|
||||
TileEffectData *eff;
|
||||
};
|
||||
|
||||
class TileEffectStorage
|
||||
{
|
||||
public:
|
||||
void assignEffect(TileData& t, int index) const;
|
||||
void update(float dt);
|
||||
|
||||
std::vector<TileEffectData*> prepared;
|
||||
std::vector<TileEffectConfig> configs;
|
||||
};
|
||||
|
||||
class TileStorage
|
||||
{
|
||||
friend class TileRender;
|
||||
public:
|
||||
TileStorage(const TileEffectStorage& eff);
|
||||
~TileStorage();
|
||||
|
||||
void moveToFront(size_t idx);
|
||||
void moveToBack(size_t idx);
|
||||
void moveToOther(TileStorage& other, const size_t *indices, size_t n);
|
||||
void deleteSome(const size_t *indices, size_t n);
|
||||
|
||||
void setTag(unsigned tag, const size_t *indices, size_t n);
|
||||
void setEffect(int idx, const size_t *indices, size_t n);
|
||||
|
||||
void update(float dt);
|
||||
void doInteraction(const Vector& pos, const Vector& vel, float mult, float touchWidth);
|
||||
void refreshAll(); // call this after changing properties or moving to front/back
|
||||
void destroyAll();
|
||||
|
||||
void clearSelection();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<TileData> tiles;
|
||||
void refresh(); // call when adding/removing/reordering tiles or changing efx
|
||||
std::vector<size_t> indicesToUpdate;
|
||||
std::vector<size_t> indicesToCollide;
|
||||
const TileEffectStorage& effstore;
|
||||
|
||||
void _refreshTile(const TileData& t);
|
||||
void _moveToFront(size_t idx);
|
||||
void _moveToBack(size_t idx);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
#include "RenderBase.h"
|
||||
#include "Core.h"
|
||||
#include "Tileset.h"
|
||||
#include "RenderGrid.h"
|
||||
#include "RenderObject.h"
|
||||
|
||||
|
||||
TileRender::TileRender(const TileStorage& tiles)
|
||||
: storage(tiles)
|
||||
: storage(tiles), renderBorders(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -12,11 +15,36 @@ TileRender::~TileRender()
|
|||
{
|
||||
}
|
||||
|
||||
// shamelessly ripped from paint.net default palette
|
||||
static const Vector s_tagColors[] =
|
||||
{
|
||||
/* 0 */ Vector(0.5f, 0.5f, 0.5f),
|
||||
/* 1 */ Vector(1,0,0),
|
||||
/* 2 */ Vector(1, 0.415686f, 0),
|
||||
/* 3 */ Vector(1,0.847059f, 0),
|
||||
/* 4 */ Vector(0.298039f,1,0),
|
||||
/* 5 */ Vector(0,1,1),
|
||||
/* 6 */ Vector(0,0.580392,1),
|
||||
/* 7 */ Vector(0,0.149020f,1),
|
||||
/* 8 */ Vector(0.282353f,0,1),
|
||||
/* 9 */ Vector(0.698039f,0,1),
|
||||
|
||||
/* 10 */ Vector(1,0,1), // anything outside of the pretty range
|
||||
};
|
||||
|
||||
static inline const Vector& getTagColor(int tag)
|
||||
{
|
||||
const unsigned idx = std::min<unsigned>(unsigned(tag), Countof(s_tagColors)-1);
|
||||
return s_tagColors[idx];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TileRender::onRender(const RenderState& rs) const
|
||||
{
|
||||
// prepare. get parallax scroll factors
|
||||
const RenderObjectLayer& rl = core->renderObjectLayers[this->layer];
|
||||
Vector M = rl.followCameraMult; // affected by parallaxLock
|
||||
const Vector M = rl.followCameraMult; // affected by parallaxLock
|
||||
const float F = rl.followCamera;
|
||||
|
||||
// Formula from RenderObject::getFollowCameraPosition() and optimized for speed
|
||||
|
@ -26,18 +54,20 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
|
||||
unsigned lastTexRepeat = false;
|
||||
unsigned lastTexId = 0;
|
||||
BlendType blend = BLEND_DEFAULT; // TODO: influenced by efx
|
||||
const bool renderBorders = true; // TODO: when layer selected in editor
|
||||
|
||||
const bool renderBorders = this->renderBorders;
|
||||
//bool mustSetColor = false;
|
||||
|
||||
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
||||
{
|
||||
const TileData& tile = storage.tiles[i];
|
||||
if(tile.flags & TILEFLAG_HIDDEN)
|
||||
continue;
|
||||
|
||||
const Vector tilepos(tile.x, tile.y);
|
||||
const Vector tmp = T + (F * tilepos);
|
||||
const Vector pos = tilepos * M1 + (tmp * M); // lerp, used to select whether to use original v or parallax-corrected v
|
||||
|
||||
rs.gpu.setBlend(blend);
|
||||
|
||||
ElementTemplate * const et = tile.et;
|
||||
if(Texture * const tex = et->tex.content())
|
||||
{
|
||||
|
@ -51,35 +81,48 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastTexId = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // unlikely
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(pos.x, pos.y, pos.z);
|
||||
|
||||
glRotatef(tile.rotation, 0, 0, 1);
|
||||
if(tile.flags & TILEFLAG_FH)
|
||||
if(tile.flags & TILEFLAG_FH) // TODO: This is not necessary! Since we have no children, flipped texcoords are fine
|
||||
glRotatef(180, 0, 1, 0);
|
||||
|
||||
// this is only relevant in editor mode and is always 0 otherwise
|
||||
glTranslatef(tile.beforeScaleOffset.x, tile.beforeScaleOffset.y, tile.beforeScaleOffset.z);
|
||||
glTranslatef(tile.beforeScaleOffsetX, tile.beforeScaleOffsetY, 0);
|
||||
|
||||
glScalef(tile.scale.x, tile.scale.y, 1);
|
||||
glScalef(tile.scalex * et->w, tile.scaley * et->h, 1);
|
||||
//glScalef(tile.scalex * et->w, tile.scaley * et->h, 1); // TODO use this + fixed verts
|
||||
|
||||
// TODO: only need to do this when prev. tile had different alpha
|
||||
BlendType blend = BLEND_DEFAULT;
|
||||
float alpha = rs.alpha;
|
||||
RenderGrid *grid = NULL;
|
||||
const TileEffectData * const eff = tile.eff;
|
||||
if(eff)
|
||||
{
|
||||
const float alpha = 1; // TODO: via efx
|
||||
Vector col = rs.color;
|
||||
glColor4f(col.x, col.y, col.z, rs.alpha*alpha);
|
||||
grid = eff->grid;
|
||||
alpha *= eff->alpha.x;
|
||||
blend = eff->blend;
|
||||
}
|
||||
|
||||
const float _w2 = float(int(et->w)) * 0.5f;
|
||||
const float _h2 = float(int(et->h)) * 0.5f;
|
||||
rs.gpu.setBlend(blend);
|
||||
|
||||
// TODO: only need to do this when prev. tile had different alpha
|
||||
glColor4f(rs.color.x, rs.color.y, rs.color.z, alpha);
|
||||
|
||||
// render texture
|
||||
{
|
||||
const Vector upperLeftTextureCoordinates(et->tu1, et->tv1);
|
||||
const Vector lowerRightTextureCoordinates(et->tu2, et->tv2);
|
||||
|
||||
if(!grid)
|
||||
{
|
||||
const float _w2 = et->w * 0.5f;
|
||||
const float _h2 = et->h * 0.5f;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(upperLeftTextureCoordinates.x, 1.0f-upperLeftTextureCoordinates.y);
|
||||
|
@ -96,14 +139,29 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
}
|
||||
glEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderState rx(rs);
|
||||
rx.alpha = alpha;
|
||||
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
|
||||
if (RenderObject::renderCollisionShape)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
grid->renderDebugPoints(rs);
|
||||
lastTexId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(renderBorders)
|
||||
{
|
||||
lastTexId = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Vector color(0.5f,0.5f,0.5f); // TODO: (1,1,1) when selected
|
||||
|
||||
float c = (tile.flags & TILEFLAG_SELECTED) ? 1.0f : 0.5f;
|
||||
Vector color(c,c,c);
|
||||
color *= getTagColor(tile.tag);
|
||||
const float _w2 = et->w * 0.5f;
|
||||
const float _h2 = et->h * 0.5f;
|
||||
|
||||
glColor4f(color.x, color.y, color.z, 1.0f);
|
||||
glPointSize(16);
|
||||
|
@ -129,7 +187,3 @@ void TileRender::onRender(const RenderState& rs) const
|
|||
RenderObject::lastTextureApplied = lastTexId;
|
||||
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
||||
}
|
||||
|
||||
void TileRender::onUpdate(float dt)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ public:
|
|||
TileRender(const TileStorage& tiles);
|
||||
virtual ~TileRender();
|
||||
virtual void onRender(const RenderState& rs) const;
|
||||
virtual void onUpdate(float dt);
|
||||
|
||||
bool renderBorders;
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
|
||||
// lazily assigned when tex is loaded
|
||||
CountedPtr<Texture> tex;
|
||||
unsigned w,h; // custom size if used, otherwise texture size
|
||||
float w,h; // custom size if used, otherwise texture size
|
||||
|
||||
// fixed
|
||||
float tu1, tu2, tv1, tv2; // texcoords
|
||||
|
|
Loading…
Reference in a new issue