mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-07-02 22:14:37 +00:00
wip towards Element draw refactor; still using old render path
This commit is contained in:
parent
578c8ecc45
commit
c09098e13c
12 changed files with 444 additions and 151 deletions
|
@ -109,6 +109,12 @@ set(BBGE_SRCS
|
|||
TextureMgr.h
|
||||
TTFFont.cpp
|
||||
TTFFont.h
|
||||
Tile.cpp
|
||||
Tile.h
|
||||
TileRender.cpp
|
||||
TileRender.h
|
||||
Tileset.cpp
|
||||
Tileset.h
|
||||
Vector.cpp
|
||||
Vector.h
|
||||
Window.cpp
|
||||
|
|
|
@ -205,6 +205,7 @@ public:
|
|||
|
||||
// Defined in RenderObject_inline.h
|
||||
inline Vector getFollowCameraPosition() const;
|
||||
inline Vector getFollowCameraPosition(const Vector& pos) const;
|
||||
|
||||
void lookAt(const Vector &pos, float t, float minAngle, float maxAngle, float offset=0);
|
||||
inline RenderObject *getParent() const {return parent;}
|
||||
|
|
|
@ -33,19 +33,42 @@ inline bool RenderObject::isOnScreen() const
|
|||
}
|
||||
|
||||
Vector RenderObject::getFollowCameraPosition() const
|
||||
{
|
||||
return getFollowCameraPosition(position);
|
||||
}
|
||||
|
||||
Vector RenderObject::getFollowCameraPosition(const Vector& v) const
|
||||
{
|
||||
assert(layer != LR_NONE);
|
||||
assert(!parent); // this makes no sense when we're not a root object
|
||||
const RenderObjectLayer &rl = core->renderObjectLayers[layer];
|
||||
Vector mul = rl.followCameraMult;
|
||||
float f = followCamera;
|
||||
if(!f)
|
||||
f = rl.followCamera;
|
||||
if (f <= 0)
|
||||
return position;
|
||||
Vector M = rl.followCameraMult;
|
||||
float F = followCamera;
|
||||
if(!F)
|
||||
F = rl.followCamera;
|
||||
if (F <= 0)
|
||||
return v;
|
||||
|
||||
const Vector pos = (position - core->screenCenter) * f + core->screenCenter;
|
||||
return position * (Vector(1,1) - mul) + (pos * mul); // lerp
|
||||
/* Originally, not accounting for parallax lock on an axis, this was:
|
||||
pos = v - core->screenCenter;
|
||||
pos *= F;
|
||||
pos = core->screenCenter + pos;
|
||||
*/
|
||||
|
||||
// uppercase are effectively constants that are not per-object
|
||||
// lowercase are per-object
|
||||
|
||||
// more concise math:
|
||||
//const Vector pos = (v - core->screenCenter) * F + core->screenCenter;
|
||||
//return v * (Vector(1,1) - M) + (pos * M); // lerp
|
||||
|
||||
// optimized and rearranged
|
||||
const Vector C = core->screenCenter;
|
||||
const Vector M1 = Vector(1,1) - M;
|
||||
const Vector T = C * (1 - F);
|
||||
|
||||
const Vector pos = T + (F * v);
|
||||
return v * M1 + (pos * M); // lerp, used to select whether to use original v or parallax-corrected v
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
2
BBGE/Tile.cpp
Normal file
2
BBGE/Tile.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "Tile.h"
|
||||
|
60
BBGE/Tile.h
Normal file
60
BBGE/Tile.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef BBGE_TILE_H
|
||||
#define BBGE_TILE_H
|
||||
|
||||
#include <vector>
|
||||
#include "Vector.h"
|
||||
|
||||
class ElementTemplate;
|
||||
class Texture;
|
||||
|
||||
// A Tile is a very stripped down RenderObject that bypasses the default
|
||||
// rendering pipeline for efficiency reasons.
|
||||
// Use a TileRender to draw a list of Tiles.
|
||||
|
||||
/* Properties of tiles:
|
||||
- Lots of these exist. Need to store & render efficiently
|
||||
- Usually no dynamic behavior, BUT:
|
||||
* can have a TileEffect that requires updating (sometimes)
|
||||
* can react to entities nearby (rare)
|
||||
* may have a draw grid (wobbly plants etc)
|
||||
- Only modified in the editor -> Can be slow to modify or reorder
|
||||
- Render order must be strictly followed to get the correct visual overlapping
|
||||
- Never part of a parent/child hierarchy, all tiles are standalone
|
||||
- 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
|
||||
*/
|
||||
|
||||
enum TileFlags
|
||||
{
|
||||
TILEFLAG_NONE = 0,
|
||||
TILEFLAG_REPEAT = 0x01, // texture repeats and uses texscale for the repeat factor
|
||||
TILEFLAG_SOLID = 0x02, // generates OT_INVISIBLE
|
||||
TILEFLAG_SOLID_THICK = 0x04, // generates more OT_INVISIBLE
|
||||
TILEFLAG_SOLID_IN = 0x08, // instead of OT_INVISIBLE, generate OT_INVISIBLEIN
|
||||
TILEFLAG_HURT = 0x10, // always generate OT_HURT
|
||||
TILEFLAG_FH = 0x20, // flipped horizontally
|
||||
};
|
||||
|
||||
// sort-of-POD
|
||||
struct TileData
|
||||
{
|
||||
float x, y, rotation, texscale;
|
||||
Vector scale, beforeScaleOffset;
|
||||
int efx;
|
||||
unsigned flags; // TileFlags
|
||||
unsigned tag;
|
||||
ElementTemplate *et;
|
||||
};
|
||||
|
||||
|
||||
class TileStorage
|
||||
{
|
||||
public:
|
||||
std::vector<TileData> tiles;
|
||||
void refresh(); // call when adding/removing/reordering tiles or changing efx
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // BBGE_TILE_H
|
135
BBGE/TileRender.cpp
Normal file
135
BBGE/TileRender.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include "TileRender.h"
|
||||
#include "RenderBase.h"
|
||||
#include "Core.h"
|
||||
#include "Tileset.h"
|
||||
|
||||
TileRender::TileRender(const TileStorage& tiles)
|
||||
: storage(tiles)
|
||||
{
|
||||
}
|
||||
|
||||
TileRender::~TileRender()
|
||||
{
|
||||
}
|
||||
|
||||
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 float F = rl.followCamera;
|
||||
|
||||
// Formula from RenderObject::getFollowCameraPosition() and optimized for speed
|
||||
const Vector C = core->screenCenter;
|
||||
const Vector M1 = Vector(1,1) - M;
|
||||
const Vector T = C * (1 - F);
|
||||
|
||||
unsigned lastTexRepeat = false;
|
||||
unsigned lastTexId = 0;
|
||||
BlendType blend = BLEND_DEFAULT; // TODO: influenced by efx
|
||||
const bool renderBorders = true; // TODO: when layer selected in editor
|
||||
|
||||
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
||||
{
|
||||
const TileData& tile = storage.tiles[i];
|
||||
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())
|
||||
{
|
||||
unsigned texid = tex->gltexid;
|
||||
unsigned rep = tile.flags & TILEFLAG_REPEAT;
|
||||
if(texid != lastTexId || rep != lastTexRepeat)
|
||||
{
|
||||
lastTexId = texid;
|
||||
lastTexRepeat = rep;
|
||||
tex->apply(!!rep);
|
||||
}
|
||||
}
|
||||
else
|
||||
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)
|
||||
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);
|
||||
|
||||
glScalef(tile.scale.x, tile.scale.y, 1);
|
||||
|
||||
// TODO: only need to do this when prev. tile had different alpha
|
||||
{
|
||||
const float alpha = 1; // TODO: via efx
|
||||
Vector col = rs.color;
|
||||
glColor4f(col.x, col.y, col.z, rs.alpha*alpha);
|
||||
}
|
||||
|
||||
const float _w2 = float(int(et->w)) * 0.5f;
|
||||
const float _h2 = float(int(et->h)) * 0.5f;
|
||||
|
||||
// render texture
|
||||
{
|
||||
const Vector upperLeftTextureCoordinates(et->tu1, et->tv1);
|
||||
const Vector lowerRightTextureCoordinates(et->tu2, et->tv2);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(upperLeftTextureCoordinates.x, 1.0f-upperLeftTextureCoordinates.y);
|
||||
glVertex2f(-_w2, +_h2);
|
||||
|
||||
glTexCoord2f(lowerRightTextureCoordinates.x, 1.0f-upperLeftTextureCoordinates.y);
|
||||
glVertex2f(+_w2, +_h2);
|
||||
|
||||
glTexCoord2f(lowerRightTextureCoordinates.x, 1.0f-lowerRightTextureCoordinates.y);
|
||||
glVertex2f(+_w2, -_h2);
|
||||
|
||||
glTexCoord2f(upperLeftTextureCoordinates.x, 1.0f-lowerRightTextureCoordinates.y);
|
||||
glVertex2f(-_w2, -_h2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if(renderBorders)
|
||||
{
|
||||
lastTexId = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Vector color(0.5f,0.5f,0.5f); // TODO: (1,1,1) when selected
|
||||
|
||||
|
||||
glColor4f(color.x, color.y, color.z, 1.0f);
|
||||
glPointSize(16);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2f(0,0);
|
||||
glEnd();
|
||||
|
||||
glLineWidth(2);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(_w2, _h2);
|
||||
glVertex2f(_w2, -_h2);
|
||||
glVertex2f(-_w2, -_h2);
|
||||
glVertex2f(-_w2, _h2);
|
||||
glVertex2f(_w2, _h2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
RenderObject::lastTextureApplied = lastTexId;
|
||||
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
||||
}
|
||||
|
||||
void TileRender::onUpdate(float dt)
|
||||
{
|
||||
}
|
24
BBGE/TileRender.h
Normal file
24
BBGE/TileRender.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef BBGE_TILERENDER_H
|
||||
#define BBGE_TILERENDER_H
|
||||
|
||||
#include "RenderObject.h"
|
||||
#include "Tile.h"
|
||||
|
||||
class Tileset;
|
||||
|
||||
class TileRender : public RenderObject
|
||||
{
|
||||
private:
|
||||
const TileStorage& storage;
|
||||
public:
|
||||
|
||||
TileRender(const TileStorage& tiles);
|
||||
virtual ~TileRender();
|
||||
virtual void onRender(const RenderState& rs) const;
|
||||
virtual void onUpdate(float dt);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // BBGE_TILERENDER_H
|
94
BBGE/Tileset.cpp
Normal file
94
BBGE/Tileset.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "Tileset.h"
|
||||
#include "SimpleIStringStream.h"
|
||||
#include "Base.h"
|
||||
#include "ttvfs_stdio.h"
|
||||
#include "TextureMgr.h"
|
||||
#include "Core.h"
|
||||
|
||||
bool Tileset::loadFile(const char *fn, const unsigned char *usedIdx, size_t usedIdxLen)
|
||||
{
|
||||
elementTemplates.clear();
|
||||
|
||||
InStream in(fn);
|
||||
if(!in)
|
||||
return false;
|
||||
|
||||
std::string line, gfx;
|
||||
while (std::getline(in, line))
|
||||
{
|
||||
int idx=-1, w=0, h=0;
|
||||
SimpleIStringStream is(line.c_str(), SimpleIStringStream::REUSE);
|
||||
is >> idx >> gfx >> w >> h;
|
||||
if(idx > 0)
|
||||
{
|
||||
ElementTemplate t;
|
||||
t.idx = idx;
|
||||
t.gfx = gfx;
|
||||
t.w = w;
|
||||
t.h = h;
|
||||
elementTemplates.push_back(t);
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
|
||||
std::sort(elementTemplates.begin(), elementTemplates.end());
|
||||
|
||||
// begin preloading textures
|
||||
|
||||
std::vector<std::string> usedTex;
|
||||
usedTex.reserve(elementTemplates.size()); // optimistically assume all textures in the tileset are used
|
||||
|
||||
for (size_t i = 0; i < elementTemplates.size(); i++)
|
||||
{
|
||||
size_t idx = elementTemplates[i].idx;
|
||||
if (!usedIdx || (idx < usedIdxLen && usedIdx[idx]))
|
||||
usedTex.push_back(elementTemplates[i].gfx);
|
||||
}
|
||||
std::sort(usedTex.begin(), usedTex.end());
|
||||
// drop duplicates
|
||||
usedTex.resize(std::distance(usedTex.begin(), std::unique(usedTex.begin(), usedTex.end())));
|
||||
|
||||
std::ostringstream os;
|
||||
os << "Loading " << usedTex.size()
|
||||
<< " used textures out of the " << elementTemplates.size() << " tileset entries";
|
||||
debugLog(os.str());
|
||||
|
||||
// preload all used textures
|
||||
if(usedTex.size())
|
||||
core->texmgr.loadBatch(NULL, &usedTex[0], usedTex.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::clear()
|
||||
{
|
||||
elementTemplates.clear();
|
||||
}
|
||||
|
||||
ElementTemplate *Tileset::getByIdx(size_t idx)
|
||||
{
|
||||
for (size_t i = 0; i < elementTemplates.size(); i++)
|
||||
{
|
||||
if (elementTemplates[i].idx == idx)
|
||||
{
|
||||
return &elementTemplates[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture* ElementTemplate::getTexture()
|
||||
{
|
||||
if(tex)
|
||||
return tex.content();
|
||||
|
||||
tex = core->getTexture(gfx);
|
||||
if(!w)
|
||||
w = tex->width;
|
||||
if(!h)
|
||||
h = tex->height;
|
||||
|
||||
return tex.content();
|
||||
|
||||
}
|
||||
|
40
BBGE/Tileset.h
Normal file
40
BBGE/Tileset.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef BBGE_TILESET_H
|
||||
#define BBGE_TILESET_H
|
||||
|
||||
#include "Vector.h"
|
||||
#include <vector>
|
||||
#include "Texture.h"
|
||||
|
||||
class ElementTemplate
|
||||
{
|
||||
public:
|
||||
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; }
|
||||
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
||||
|
||||
Texture *getTexture(); // loads if not already loaded
|
||||
|
||||
// lazily assigned when tex is loaded
|
||||
CountedPtr<Texture> tex;
|
||||
unsigned w,h; // custom size if used, otherwise texture size
|
||||
|
||||
// fixed
|
||||
float tu1, tu2, tv1, tv2; // texcoords
|
||||
size_t idx;
|
||||
std::string gfx;
|
||||
};
|
||||
|
||||
class Tileset
|
||||
{
|
||||
public:
|
||||
// pass usedIdx == NULL to preload all textures from tileset
|
||||
// pass usedIdx != NULL to preload only textures where usedIdx[i] != 0
|
||||
bool loadFile(const char *fn, const unsigned char *usedIdx, size_t usedIdxLen);
|
||||
void clear();
|
||||
|
||||
ElementTemplate *getByIdx(size_t idx);
|
||||
|
||||
std::vector<ElementTemplate> elementTemplates;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue