mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-01-24 17:26:41 +00:00
split grid rendering off from Quad, to a new RenderGrid class
This commit is contained in:
parent
0f0f3e9023
commit
976ce8ff3e
12 changed files with 594 additions and 496 deletions
|
@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "RenderBase.h"
|
||||
#include "Game.h"
|
||||
#include "SplineGrid.h"
|
||||
#include "RenderGrid.h"
|
||||
|
||||
|
||||
int TIMELINE_GRIDSIZE = 10;
|
||||
|
@ -958,8 +959,9 @@ void AnimationEditor::editStripKey()
|
|||
}
|
||||
else
|
||||
{
|
||||
if(editingBone && !editingBone->getDrawGrid().empty())
|
||||
if(editingBone && editingBone->getGrid())
|
||||
{
|
||||
RenderGrid *grid = editingBone->getGrid();
|
||||
Animation *a = editSprite->getCurrentAnimation();
|
||||
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
||||
|
||||
|
@ -973,12 +975,12 @@ void AnimationEditor::editStripKey()
|
|||
assert(bk->controlpoints.size() == interp->bsp.ctrlX() * interp->bsp.ctrlY());
|
||||
|
||||
splinegrid = new SplineGrid;
|
||||
splinegrid->drawOrder = editingBone->drawOrder;
|
||||
RenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY());
|
||||
rgrid->drawOrder = grid->drawOrder;
|
||||
splinegrid->setTexture(editingBone->texture->name);
|
||||
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
||||
splinegrid->position = Vector(400, 300);
|
||||
//splinegrid->followCamera = 1;
|
||||
splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), editingBone->getDrawGrid().width(), editingBone->getDrawGrid().height(), interp->bsp.degX(), interp->bsp.degY());
|
||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
||||
//editSprite->addChild(splinegrid, PM_STATIC, RBP_OFF, CHILD_FRONT);
|
||||
//editSprite->alphaMod = 0.5f;
|
||||
|
|
|
@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
#include "Element.h"
|
||||
#include "Game.h"
|
||||
#include "RenderGrid.h"
|
||||
|
||||
ElementEffectData::ElementEffectData()
|
||||
: elementEffectType(EFX_NONE)
|
||||
|
@ -182,8 +183,8 @@ void Element::update(float dt)
|
|||
updateLife(dt);
|
||||
if (eff)
|
||||
updateEffects(dt);
|
||||
if (!drawGrid.empty())
|
||||
updateGrid(dt);
|
||||
if(grid)
|
||||
grid->update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,26 +205,8 @@ int Element::getElementEffectIndex()
|
|||
|
||||
void Element::setGridFromWavy()
|
||||
{
|
||||
if (!drawGrid.empty())
|
||||
{
|
||||
const size_t NX = drawGrid.width() - 1;
|
||||
const size_t H = drawGrid.height();
|
||||
|
||||
const float iw = 1.0f / float(getWidth());
|
||||
for (size_t x = 0; x < NX; x++)
|
||||
{
|
||||
for (size_t y = 0; y < H; y++)
|
||||
{
|
||||
const size_t wavy_y = (H - y)-1;
|
||||
if (wavy_y < 0 || wavy_y < eff->wavy.size())
|
||||
{
|
||||
const float tmp = eff->wavy[wavy_y].x * iw;
|
||||
drawGrid(x,y).x = tmp - 0.5f;
|
||||
drawGrid(x+1,y).x = tmp + 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(grid && eff->wavy.size())
|
||||
grid->setFromWavy(&eff->wavy[0], eff->wavy.size(), width);
|
||||
}
|
||||
|
||||
void Element::setElementEffectByIndex(int eidx)
|
||||
|
|
|
@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "Gradient.h"
|
||||
#include "TTFFont.h"
|
||||
#include "RoundedRect.h"
|
||||
#include "RenderGrid.h"
|
||||
|
||||
#define GEM_GRAB 10
|
||||
|
||||
|
@ -561,8 +562,12 @@ void WorldMapRender::setVis(WorldMapTile *tile)
|
|||
|
||||
if (visMethod == VIS_VERTEX)
|
||||
{
|
||||
tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
|
||||
tileDataToVis(tile, tile->q->getDrawGrid());
|
||||
RenderGrid *g = tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
|
||||
if(g)
|
||||
{
|
||||
g->drawOrder = GRID_DRAW_WORLDMAP;
|
||||
tileDataToVis(tile, g->array2d());
|
||||
}
|
||||
}
|
||||
else if (visMethod == VIS_WRITE)
|
||||
{
|
||||
|
@ -662,7 +667,6 @@ WorldMapRender::WorldMapRender() : RenderObject(), ActionMapper()
|
|||
q->setTexturePointer(texs[i]);
|
||||
q->position = pos;
|
||||
q->alphaMod = 0;
|
||||
q->drawOrder = Quad::GRID_DRAW_WORLDMAP;
|
||||
|
||||
tile->q = q;
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
int screenWidth, screenHeight;
|
||||
int textureWidth, textureHeight;
|
||||
|
||||
Vector ** drawGrid;
|
||||
Vector ** drawGrid; // TODO: make this + related code use RenderGrid
|
||||
|
||||
// returns handle > 0 on success
|
||||
int loadShaderFile(const char *vert, const char *frag);
|
||||
|
|
|
@ -72,6 +72,8 @@ set(BBGE_SRCS
|
|||
Refcounted.h
|
||||
RenderBase.cpp
|
||||
RenderBase.h
|
||||
RenderGrid.cpp
|
||||
RenderGrid.h
|
||||
RenderObject.cpp
|
||||
RenderObject.h
|
||||
RenderObject_inline.h
|
||||
|
|
442
BBGE/Quad.cpp
442
BBGE/Quad.cpp
|
@ -21,148 +21,92 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "Quad.h"
|
||||
#include "Core.h"
|
||||
#include "RenderBase.h"
|
||||
#include "RenderGrid.h"
|
||||
#include <assert.h>
|
||||
|
||||
Quad::Quad(const std::string &tex, const Vector &pos)
|
||||
: RenderObject()
|
||||
{
|
||||
renderBorderColor = Vector(1,1,1);
|
||||
initQuad();
|
||||
renderBorderColor = Vector(1,1,1);
|
||||
position = pos;
|
||||
setTexture(tex);
|
||||
}
|
||||
|
||||
Quad::Quad() : RenderObject()
|
||||
{
|
||||
initQuad();
|
||||
}
|
||||
|
||||
|
||||
void Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
||||
Quad::~Quad()
|
||||
{
|
||||
deleteGrid();
|
||||
if (x == 0 || y == 0)
|
||||
{
|
||||
doUpdateGrid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
doUpdateGrid = true;
|
||||
this->drawGridOffsetX = dgox;
|
||||
this->drawGridOffsetY = dgoy;
|
||||
this->drawGridModX = dgmx;
|
||||
this->drawGridModY = dgmy;
|
||||
this->drawGridTimeMultiplier = dgtm;
|
||||
drawGridOut = dgo;
|
||||
createGrid(x, y);
|
||||
}
|
||||
|
||||
gridTimer = 0;
|
||||
}
|
||||
|
||||
void Quad::createGrid(int xd, int yd)
|
||||
void Quad::initQuad()
|
||||
{
|
||||
drawGrid.init(xd, yd);
|
||||
resetGrid();
|
||||
Vector *dg = drawGrid.data();
|
||||
for(size_t i = 0; i < drawGrid.linearsize(); ++i)
|
||||
dg[i].z = 1.0f;
|
||||
addType(SCO_QUAD);
|
||||
borderAlpha = 0.5;
|
||||
repeatToFillScale = Vector(1,1);
|
||||
|
||||
autoWidth = autoHeight = 0;
|
||||
|
||||
renderBorder = false;
|
||||
renderCenter = true;
|
||||
width = 2; height = 2;
|
||||
|
||||
upperLeftTextureCoordinates = Vector(0,0);
|
||||
lowerRightTextureCoordinates = Vector(1,1);
|
||||
renderQuad = true;
|
||||
grid = NULL;
|
||||
}
|
||||
|
||||
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
|
||||
void Quad::deleteGrid()
|
||||
{
|
||||
if (x < drawGrid.width() && y < drawGrid.height())
|
||||
{
|
||||
drawGrid(x, y).z = alpha;
|
||||
}
|
||||
delete grid;
|
||||
grid = NULL;
|
||||
}
|
||||
|
||||
void Quad::setStripPoints(bool vert, const Vector *points, size_t n)
|
||||
void Quad::destroy()
|
||||
{
|
||||
if (drawGrid.empty()) return;
|
||||
resetGrid();
|
||||
deleteGrid();
|
||||
RenderObject::destroy();
|
||||
}
|
||||
|
||||
const float mul = float(n);
|
||||
|
||||
if (!vert) // horz
|
||||
{
|
||||
const size_t xmax = std::min(drawGrid.width(), n);
|
||||
for (size_t y = 0; y < drawGrid.height(); y++)
|
||||
{
|
||||
Vector *row = drawGrid.row(y);
|
||||
for (size_t x = 0; x < xmax; x++)
|
||||
row[x] += points[x] * mul;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t ymax = std::min(drawGrid.height(), n);
|
||||
for (size_t x = 0; x < drawGrid.width(); x++)
|
||||
for (size_t y = 0; y < ymax; y++)
|
||||
drawGrid(x, y) += points[y] * mul;
|
||||
}
|
||||
}
|
||||
|
||||
void Quad::ResetGrid(Vector* dst, size_t w, size_t h)
|
||||
RenderGrid *Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
||||
{
|
||||
assert(w > 1 && h > 1);
|
||||
const float xMulF = 1.0f / (float)(w-1);
|
||||
const float yMulF = 1.0f / (float)(h-1);
|
||||
|
||||
for (size_t y = 0; y < h; y++)
|
||||
{
|
||||
const float yval = float(y)*yMulF-0.5f;
|
||||
for (size_t x = 0; x < w; x++)
|
||||
{
|
||||
dst->x = float(x)*xMulF-0.5f;
|
||||
dst->y = yval;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
RenderGrid *g = createGrid(x, y);
|
||||
if(g)
|
||||
g->setSegs(dgox, dgoy, dgmx, dgmy, dgtm, dgo);
|
||||
return g;
|
||||
}
|
||||
|
||||
void Quad::ResetGridAndAlpha(Vector* dst, size_t w, size_t h, float alpha)
|
||||
RenderGrid *Quad::createGrid(int xd, int yd)
|
||||
{
|
||||
assert(w > 1 && h > 1);
|
||||
const float xMulF = 1.0f / (float)(w-1);
|
||||
const float yMulF = 1.0f / (float)(h-1);
|
||||
|
||||
for (size_t y = 0; y < h; y++)
|
||||
{
|
||||
const float yval = float(y)*yMulF-0.5f;
|
||||
for (size_t x = 0; x < w; x++)
|
||||
{
|
||||
dst->x = float(x)*xMulF-0.5f;
|
||||
dst->y = yval;
|
||||
dst->z = alpha;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
delete grid;
|
||||
return (grid = xd && yd
|
||||
? new RenderGrid(xd, yd)
|
||||
: NULL);
|
||||
}
|
||||
|
||||
void Quad::resetGrid()
|
||||
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
|
||||
{
|
||||
if (drawGrid.empty()) return;
|
||||
|
||||
ResetGrid(drawGrid.data(), drawGrid.width(), drawGrid.height());
|
||||
if(grid)
|
||||
grid->setAlpha(x, y, alpha);
|
||||
}
|
||||
|
||||
void Quad::initQuad()
|
||||
void Quad::setStripPoints(bool vert, const Vector *points, size_t n)
|
||||
{
|
||||
repeatToFillScale = Vector(1,1);
|
||||
gridType = GRID_WAVY;
|
||||
gridTimer = 0;
|
||||
|
||||
doUpdateGrid = false;
|
||||
|
||||
autoWidth = autoHeight = 0;
|
||||
|
||||
renderBorder = false;
|
||||
renderCenter = true;
|
||||
width = 2; height = 2;
|
||||
|
||||
|
||||
|
||||
upperLeftTextureCoordinates = Vector(0,0);
|
||||
lowerRightTextureCoordinates = Vector(1,1);
|
||||
renderQuad = true;
|
||||
if(grid)
|
||||
grid->setStripPoints(vert, points, n);
|
||||
}
|
||||
|
||||
void Quad::resetGrid()
|
||||
{
|
||||
if(grid)
|
||||
grid->reset();
|
||||
}
|
||||
|
||||
void Quad::_renderBorder(const RenderState& rs, Vector color, float borderalpha) const
|
||||
|
@ -195,27 +139,7 @@ void Quad::_renderBorder(const RenderState& rs, Vector color, float borderalpha)
|
|||
RenderObject::lastTextureApplied = 0;
|
||||
}
|
||||
|
||||
Quad::Quad() : RenderObject()
|
||||
{
|
||||
addType(SCO_QUAD);
|
||||
borderAlpha = 0.5;
|
||||
drawOrder = GRID_DRAW_DEFAULT;
|
||||
|
||||
initQuad();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Quad::deleteGrid()
|
||||
{
|
||||
drawGrid.clear();
|
||||
}
|
||||
|
||||
void Quad::destroy()
|
||||
{
|
||||
deleteGrid();
|
||||
RenderObject::destroy();
|
||||
}
|
||||
|
||||
bool Quad::isCoordinateInside(Vector coord, int minSize) const
|
||||
{
|
||||
|
@ -275,272 +199,28 @@ bool Quad::isCoordinateInsideWorldRect(const Vector &coord, int w, int h) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void Quad::updateGrid(float dt)
|
||||
{
|
||||
if (!doUpdateGrid) return;
|
||||
|
||||
if (gridType == GRID_WAVY)
|
||||
{
|
||||
gridTimer += dt * drawGridTimeMultiplier;
|
||||
resetGrid();
|
||||
size_t hx = drawGrid.width()/2;
|
||||
for (size_t x = 0; x < drawGrid.width(); x++)
|
||||
{
|
||||
float yoffset = x * drawGridOffsetY;
|
||||
float addY = 0;
|
||||
if (drawGridModY != 0)
|
||||
addY = cosf(gridTimer+yoffset)*drawGridModY;
|
||||
for (size_t y = 0; y < drawGrid.height(); y++)
|
||||
{
|
||||
float xoffset = y * drawGridOffsetX;
|
||||
if (drawGridModX != 0)
|
||||
{
|
||||
float addX = (sinf(gridTimer+xoffset)*drawGridModX);
|
||||
if (drawGridOut && x < hx)
|
||||
drawGrid(x,y).x += addX;
|
||||
else
|
||||
drawGrid(x,y).x -= addX;
|
||||
}
|
||||
drawGrid(x,y).y += addY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Quad::renderGrid(const RenderState& rs) const
|
||||
{
|
||||
if (drawGrid.width() < 2 || drawGrid.height() < 2)
|
||||
return;
|
||||
|
||||
switch(drawOrder)
|
||||
{
|
||||
case GRID_DRAW_LRTB:
|
||||
renderGrid_LRTB(rs);
|
||||
break;
|
||||
RenderState rx(rs);
|
||||
rx.color = rs.color * this->color;
|
||||
rx.alpha = rs.alpha * this->alpha.x * this->alphaMod;
|
||||
|
||||
case GRID_DRAW_LRBT:
|
||||
renderGrid_LRBT(rs);
|
||||
break;
|
||||
glPushMatrix();
|
||||
glScalef(width, height, 1);
|
||||
|
||||
case GRID_DRAW_WORLDMAP:
|
||||
renderGridWithAlpha(rs);
|
||||
break;
|
||||
}
|
||||
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
|
||||
|
||||
// debug points
|
||||
if (RenderObject::renderCollisionShape)
|
||||
{
|
||||
const size_t NX = drawGrid.width()-1;
|
||||
const size_t NY = drawGrid.height()-1;
|
||||
const float w = this->getWidth();
|
||||
const float h = this->getHeight();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glPointSize(2);
|
||||
glColor3f(1,0,0);
|
||||
glBegin(GL_POINTS);
|
||||
for (size_t y = 0; y < NY; y++)
|
||||
{
|
||||
for (size_t x = 0; x < NX; x++)
|
||||
{
|
||||
glVertex2f(w*drawGrid(x,y).x, h*drawGrid(x,y).y);
|
||||
glVertex2f(w*drawGrid(x,y+1).x, h*drawGrid(x,y+1).y);
|
||||
glVertex2f(w*drawGrid(x+1,y+1).x, h*drawGrid(x+1,y+1).y);
|
||||
glVertex2f(w*drawGrid(x+1,y).x, h*drawGrid(x+1,y).y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
grid->renderDebugPoints(rx);
|
||||
RenderObject::lastTextureApplied = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Quad::renderGrid_LRTB(const RenderState& rs) const
|
||||
{
|
||||
const float percentX = lowerRightTextureCoordinates.x - upperLeftTextureCoordinates.x;
|
||||
const float percentY = lowerRightTextureCoordinates.y - upperLeftTextureCoordinates.y;
|
||||
|
||||
const float baseX = upperLeftTextureCoordinates.x;
|
||||
const float baseY = upperLeftTextureCoordinates.y;
|
||||
|
||||
const size_t NX = drawGrid.width()-1;
|
||||
const size_t NY = drawGrid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
const float w = this->getWidth();
|
||||
const float h = this->getHeight();
|
||||
|
||||
const float red = rs.color.x * this->color.x;
|
||||
const float green = rs.color.y * this->color.y;
|
||||
const float blue = rs.color.z * this->color.z;
|
||||
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
|
||||
|
||||
glColor4f(red, green, blue, alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = drawGrid.row(y);
|
||||
const Vector *row1 = drawGrid.row(y+1);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(w*dg00.x, h*dg00.y);
|
||||
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(w*dg01.x, h*dg01.y);
|
||||
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(w*dg11.x, h*dg11.y);
|
||||
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(w*dg10.x, h*dg10.y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Quad::renderGrid_LRBT(const RenderState& rs) const
|
||||
{
|
||||
const float percentX = lowerRightTextureCoordinates.x - upperLeftTextureCoordinates.x;
|
||||
const float percentY = upperLeftTextureCoordinates.y - lowerRightTextureCoordinates.y;
|
||||
|
||||
const float baseX = upperLeftTextureCoordinates.x;
|
||||
const float baseY = lowerRightTextureCoordinates.y;
|
||||
|
||||
const size_t NX = drawGrid.width()-1;
|
||||
const size_t NY = drawGrid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
const float w = this->getWidth();
|
||||
const float h = this->getHeight();
|
||||
|
||||
const float red = rs.color.x * this->color.x;
|
||||
const float green = rs.color.y * this->color.y;
|
||||
const float blue = rs.color.z * this->color.z;
|
||||
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
|
||||
|
||||
glColor4f(red, green, blue, alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = NY; y --> 0; v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = drawGrid.row(y+1);
|
||||
const Vector *row1 = drawGrid.row(y);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(w*dg00.x, h*dg00.y);
|
||||
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(w*dg01.x, h*dg01.y);
|
||||
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(w*dg11.x, h*dg11.y);
|
||||
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(w*dg10.x, h*dg10.y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Quad::renderGridWithAlpha(const RenderState& rs) const
|
||||
{
|
||||
const float percentX = fabsf(this->lowerRightTextureCoordinates.x - this->upperLeftTextureCoordinates.x);
|
||||
const float percentY = fabsf(this->upperLeftTextureCoordinates.y - this->lowerRightTextureCoordinates.y);
|
||||
|
||||
const float baseX =
|
||||
(lowerRightTextureCoordinates.x < upperLeftTextureCoordinates.x)
|
||||
? lowerRightTextureCoordinates.x : upperLeftTextureCoordinates.x;
|
||||
const float baseY =
|
||||
(lowerRightTextureCoordinates.y < upperLeftTextureCoordinates.y)
|
||||
? lowerRightTextureCoordinates.y : upperLeftTextureCoordinates.y;
|
||||
|
||||
const size_t NX = drawGrid.width()-1;
|
||||
const size_t NY = drawGrid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
const float w = this->getWidth();
|
||||
const float h = this->getHeight();
|
||||
|
||||
const float red = rs.color.x * this->color.x;
|
||||
const float green = rs.color.y * this->color.y;
|
||||
const float blue = rs.color.z * this->color.z;
|
||||
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = 1 - percentY + baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = drawGrid.row(y);
|
||||
const Vector *row1 = drawGrid.row(y+1);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
if (dg00.z != 0 || dg01.z != 0 || dg10.z != 0 || dg11.z != 0)
|
||||
{
|
||||
glColor4f(red, green, blue, alpha*dg00.z);
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(w*dg00.x, h*dg00.y);
|
||||
|
||||
glColor4f(red, green, blue, alpha*dg01.z);
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(w*dg01.x, h*dg01.y);
|
||||
|
||||
glColor4f(red, green, blue, alpha*dg11.z);
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(w*dg11.x, h*dg11.y);
|
||||
|
||||
glColor4f(red, green, blue, alpha*dg10.z);
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(w*dg10.x, h*dg10.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void Quad::repeatTextureToFill(bool on)
|
||||
{
|
||||
|
@ -556,7 +236,7 @@ void Quad::onRender(const RenderState& rs) const
|
|||
const float _w2 = width*0.5f;
|
||||
const float _h2 = height*0.5f;
|
||||
|
||||
if (drawGrid.empty())
|
||||
if (!grid)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
|
@ -643,9 +323,9 @@ void Quad::onUpdate(float dt)
|
|||
else if (autoHeight == AUTO_VIRTUALHEIGHT)
|
||||
height = core->getVirtualHeight();
|
||||
|
||||
if (!drawGrid.empty() && alpha.x > 0 && alphaMod > 0)
|
||||
if (grid && alpha.x > 0 && alphaMod > 0)
|
||||
{
|
||||
updateGrid(dt);
|
||||
grid->update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
55
BBGE/Quad.h
55
BBGE/Quad.h
|
@ -39,12 +39,15 @@ protected:
|
|||
void onRender(const RenderState& rs) const OVERRIDE;
|
||||
};
|
||||
|
||||
class RenderGrid;
|
||||
|
||||
class Quad : public RenderObject
|
||||
{
|
||||
public:
|
||||
Quad(const std::string &tex, const Vector &pos);
|
||||
Quad();
|
||||
void createGrid(int x, int y);
|
||||
virtual ~Quad();
|
||||
RenderGrid *createGrid(int x, int y);
|
||||
void destroy() OVERRIDE;
|
||||
bool isCoordinateInside(Vector coord, int minSize=0) const;
|
||||
bool isCoordinateInsideWorld(const Vector &coord, int minSize=0) const;
|
||||
|
@ -58,78 +61,44 @@ public:
|
|||
float getWidth() const {return width;}
|
||||
float getHeight() const {return height;}
|
||||
|
||||
void setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
|
||||
RenderGrid *setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
|
||||
void setDrawGridAlpha(size_t x, size_t y, float alpha);
|
||||
void repeatTextureToFill(bool on);
|
||||
void refreshRepeatTextureToFill();
|
||||
bool isRepeatingTextureToFill() const { return repeatTexture; }
|
||||
void setStripPoints(bool vert, const Vector *points, size_t n);
|
||||
Array2d<Vector>& getDrawGrid() { return drawGrid; }
|
||||
const Array2d<Vector>& getDrawGrid() const { return drawGrid; }
|
||||
RenderGrid *getGrid() { return grid; }
|
||||
const RenderGrid *getGrid() const { return grid; }
|
||||
|
||||
void reloadDevice() OVERRIDE;
|
||||
|
||||
void deleteGrid();
|
||||
|
||||
|
||||
Vector upperLeftTextureCoordinates, lowerRightTextureCoordinates;
|
||||
|
||||
enum GridDrawOrder
|
||||
{
|
||||
GRID_DRAW_WORLDMAP = -1, // LRTB order, uses grid.z as alpha
|
||||
GRID_DRAW_LRTB = 0, // the default. ignores grid.z
|
||||
GRID_DRAW_LRBT = 1, // Y axis inverted
|
||||
|
||||
GRID_DRAW_DEFAULT = GRID_DRAW_LRTB
|
||||
};
|
||||
|
||||
enum GridType
|
||||
{
|
||||
GRID_WAVY = 0,
|
||||
GRID_STRIP = 1, // quad is in strip mode
|
||||
GRID_INTERP = 2, // quad is in grid mode
|
||||
};
|
||||
unsigned char gridType; // unsigned char to save space
|
||||
|
||||
char autoWidth, autoHeight; // char to save space
|
||||
|
||||
// TODO: this should be a bitmask
|
||||
char autoWidth, autoHeight;
|
||||
bool renderQuad, renderCenter, renderBorder;
|
||||
|
||||
Vector texOff;
|
||||
|
||||
float borderAlpha;
|
||||
Vector renderBorderColor;
|
||||
Vector repeatToFillScale;
|
||||
|
||||
static void ResetGrid(Vector *dst, size_t w, size_t h);
|
||||
static void ResetGridAndAlpha(Vector *dst, size_t w, size_t h, float alpha = 1.0f);
|
||||
protected:
|
||||
|
||||
RenderGrid *grid;
|
||||
|
||||
protected:
|
||||
float gridTimer;
|
||||
Array2d<Vector> drawGrid;
|
||||
|
||||
void resetGrid();
|
||||
void updateGrid(float dt);
|
||||
void renderGrid(const RenderState& rs) const;
|
||||
void renderGrid_LRTB(const RenderState& rs) const;
|
||||
void renderGrid_LRBT(const RenderState& rs) const;
|
||||
void renderGridWithAlpha(const RenderState& rs) const;
|
||||
|
||||
float drawGridOffsetX;
|
||||
float drawGridOffsetY;
|
||||
float drawGridModX;
|
||||
float drawGridModY;
|
||||
float drawGridTimeMultiplier;
|
||||
bool drawGridOut;
|
||||
|
||||
void onSetTexture() OVERRIDE;
|
||||
void onRender(const RenderState& rs) const OVERRIDE;
|
||||
void onUpdate(float dt) OVERRIDE;
|
||||
|
||||
public:
|
||||
GridDrawOrder drawOrder;
|
||||
private:
|
||||
bool doUpdateGrid;
|
||||
void initQuad();
|
||||
void _renderBorder(const RenderState& rs, Vector color, float borderalpha) const;
|
||||
};
|
||||
|
|
381
BBGE/RenderGrid.cpp
Normal file
381
BBGE/RenderGrid.cpp
Normal file
|
@ -0,0 +1,381 @@
|
|||
#include "RenderGrid.h"
|
||||
#include "RenderBase.h"
|
||||
#include "RenderState.h"
|
||||
|
||||
|
||||
static void ResetGrid(Vector* dst, size_t w, size_t h)
|
||||
{
|
||||
assert(w > 1 && h > 1);
|
||||
const float xMulF = 1.0f / (float)(w-1);
|
||||
const float yMulF = 1.0f / (float)(h-1);
|
||||
|
||||
for (size_t y = 0; y < h; y++)
|
||||
{
|
||||
const float yval = float(y)*yMulF-0.5f;
|
||||
for (size_t x = 0; x < w; x++)
|
||||
{
|
||||
dst->x = float(x)*xMulF-0.5f;
|
||||
dst->y = yval;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderGrid::ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha)
|
||||
{
|
||||
assert(w > 1 && h > 1);
|
||||
const float xMulF = 1.0f / (float)(w-1);
|
||||
const float yMulF = 1.0f / (float)(h-1);
|
||||
|
||||
for (size_t y = 0; y < h; y++)
|
||||
{
|
||||
const float yval = float(y)*yMulF-0.5f;
|
||||
for (size_t x = 0; x < w; x++)
|
||||
{
|
||||
dst->x = float(x)*xMulF-0.5f;
|
||||
dst->y = yval;
|
||||
dst->z = alpha;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
RenderGrid::RenderGrid(size_t w, size_t h)
|
||||
: gridTimer(0)
|
||||
, drawGridOffsetX(0), drawGridOffsetY(0), drawGridModX(0), drawGridModY(0), drawGridTimeMultiplier(0)
|
||||
, drawGridOut(false), gridType(GRID_WAVY), drawOrder(GRID_DRAW_DEFAULT)
|
||||
{
|
||||
init(w, h);
|
||||
}
|
||||
|
||||
RenderGrid::~RenderGrid()
|
||||
{
|
||||
}
|
||||
|
||||
void RenderGrid::init(size_t w, size_t h)
|
||||
{
|
||||
assert(w > 1 && h > 1);
|
||||
grid.init(w, h);
|
||||
reset();
|
||||
Vector *dg = grid.data();
|
||||
for(size_t i = 0; i < grid.linearsize(); ++i)
|
||||
dg[i].z = 1.0f;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RenderGrid::reset()
|
||||
{
|
||||
ResetGrid(grid.data(), grid.width(), grid.height());
|
||||
}
|
||||
|
||||
void RenderGrid::resetWithAlpha(float a)
|
||||
{
|
||||
ResetWithAlpha(grid.data(), grid.width(), grid.height(), a);
|
||||
}
|
||||
|
||||
void RenderGrid::update(float dt)
|
||||
{
|
||||
if (gridType == GRID_WAVY)
|
||||
{
|
||||
gridTimer += dt * drawGridTimeMultiplier;
|
||||
reset();
|
||||
size_t hx = grid.width()/2;
|
||||
for (size_t x = 0; x < grid.width(); x++)
|
||||
{
|
||||
float yoffset = x * drawGridOffsetY;
|
||||
float addY = 0;
|
||||
if (drawGridModY != 0)
|
||||
addY = cosf(gridTimer+yoffset)*drawGridModY;
|
||||
for (size_t y = 0; y < grid.height(); y++)
|
||||
{
|
||||
float xoffset = y * drawGridOffsetX;
|
||||
if (drawGridModX != 0)
|
||||
{
|
||||
float addX = (sinf(gridTimer+xoffset)*drawGridModX);
|
||||
if (drawGridOut && x < hx)
|
||||
grid(x,y).x += addX;
|
||||
else
|
||||
grid(x,y).x -= addX;
|
||||
}
|
||||
grid(x,y).y += addY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderGrid::setAlpha(size_t x, size_t y, float a)
|
||||
{
|
||||
if (x < grid.width() && y < grid.height())
|
||||
grid(x, y).z = a;
|
||||
}
|
||||
|
||||
void RenderGrid::setSegs(float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
||||
{
|
||||
drawGridOffsetX = dgox;
|
||||
drawGridOffsetY = dgoy;
|
||||
drawGridModX = dgmx;
|
||||
drawGridModY = dgmy;
|
||||
drawGridTimeMultiplier = dgtm;
|
||||
drawGridOut = dgo;
|
||||
gridTimer = 0;
|
||||
gridType = GRID_WAVY;
|
||||
}
|
||||
|
||||
void RenderGrid::setStripPoints(bool vert, const Vector* points, size_t n)
|
||||
{
|
||||
reset();
|
||||
|
||||
const float mul = float(n);
|
||||
|
||||
if (!vert) // horz
|
||||
{
|
||||
const size_t xmax = std::min(grid.width(), n);
|
||||
for (size_t y = 0; y < grid.height(); y++)
|
||||
{
|
||||
Vector *row = grid.row(y);
|
||||
for (size_t x = 0; x < xmax; x++)
|
||||
row[x] += points[x] * mul;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t ymax = std::min(grid.height(), n);
|
||||
for (size_t x = 0; x < grid.width(); x++)
|
||||
for (size_t y = 0; y < ymax; y++)
|
||||
grid(x, y) += points[y] * mul;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderGrid::setFromWavy(const Vector* wavy, size_t len, float width)
|
||||
{
|
||||
const size_t NX = grid.width() - 1;
|
||||
const size_t H = grid.height();
|
||||
|
||||
const float iw = 1.0f / width;
|
||||
for (size_t x = 0; x < NX; x++) // TODO invert loop
|
||||
{
|
||||
for (size_t y = 0; y < H; y++)
|
||||
{
|
||||
const size_t wavy_y = (H - y)-1;
|
||||
if (wavy_y < len)
|
||||
{
|
||||
const float tmp = wavy[wavy_y].x * iw;
|
||||
grid(x,y).x = tmp - 0.5f;
|
||||
grid(x+1,y).x = tmp + 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RenderGrid::render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
||||
{
|
||||
switch(drawOrder)
|
||||
{
|
||||
case GRID_DRAW_LRTB:
|
||||
render_LRTB(rs, upperLeftTexCoords, lowerRightTexCoords);
|
||||
break;
|
||||
|
||||
case GRID_DRAW_LRBT:
|
||||
render_LRBT(rs, upperLeftTexCoords, lowerRightTexCoords);
|
||||
break;
|
||||
|
||||
case GRID_DRAW_WORLDMAP:
|
||||
render_WithAlpha(rs, upperLeftTexCoords, lowerRightTexCoords);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderGrid::renderDebugPoints(const RenderState& rs) const
|
||||
{
|
||||
(void)rs; // unused
|
||||
|
||||
glPointSize(2);
|
||||
glColor3f(1,0,0);
|
||||
glBegin(GL_POINTS);
|
||||
const size_t NX = grid.width()-1;
|
||||
const size_t NY = grid.height()-1;
|
||||
for (size_t y = 0; y < NY; y++)
|
||||
{
|
||||
for (size_t x = 0; x < NX; x++)
|
||||
{
|
||||
glVertex2f(grid(x,y).x, grid(x,y).y);
|
||||
glVertex2f(grid(x,y+1).x, grid(x,y+1).y);
|
||||
glVertex2f(grid(x+1,y+1).x, grid(x+1,y+1).y);
|
||||
glVertex2f(grid(x+1,y).x, grid(x+1,y).y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void RenderGrid::render_LRTB(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
||||
{
|
||||
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
|
||||
const float percentY = lowerRightTexCoords.y - upperLeftTexCoords.y;
|
||||
|
||||
const float baseX = upperLeftTexCoords.x;
|
||||
const float baseY = upperLeftTexCoords.y;
|
||||
|
||||
const size_t NX = grid.width()-1;
|
||||
const size_t NY = grid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
glColor4f(rs.color.x, rs.color.y, rs.color.z, rs.alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = grid.row(y);
|
||||
const Vector *row1 = grid.row(y+1);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(dg00.x, dg00.y);
|
||||
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(dg01.x, dg01.y);
|
||||
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(dg11.x, dg11.y);
|
||||
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(dg10.x, dg10.y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void RenderGrid::render_LRBT(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
||||
{
|
||||
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
|
||||
const float percentY = upperLeftTexCoords.y - lowerRightTexCoords.y;
|
||||
|
||||
const float baseX = upperLeftTexCoords.x;
|
||||
const float baseY = lowerRightTexCoords.y;
|
||||
|
||||
const size_t NX = grid.width()-1;
|
||||
const size_t NY = grid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
glColor4f(rs.color.x, rs.color.y, rs.color.z, rs.alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = NY; y --> 0; v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = grid.row(y+1);
|
||||
const Vector *row1 = grid.row(y);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(dg00.x, dg00.y);
|
||||
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(dg01.x, dg01.y);
|
||||
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(dg11.x, dg11.y);
|
||||
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(dg10.x, dg10.y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void RenderGrid::render_WithAlpha(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
||||
{
|
||||
const float percentX = fabsf(lowerRightTexCoords.x - upperLeftTexCoords.x);
|
||||
const float percentY = fabsf(upperLeftTexCoords.y - lowerRightTexCoords.y);
|
||||
|
||||
const float baseX =
|
||||
(lowerRightTexCoords.x < upperLeftTexCoords.x)
|
||||
? lowerRightTexCoords.x : upperLeftTexCoords.x;
|
||||
const float baseY =
|
||||
(lowerRightTexCoords.y < upperLeftTexCoords.y)
|
||||
? lowerRightTexCoords.y : upperLeftTexCoords.y;
|
||||
|
||||
const size_t NX = grid.width()-1;
|
||||
const size_t NY = grid.height()-1;
|
||||
|
||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||
// but they may cause rounding error of around 1 part per million,
|
||||
// which could in theory cause minor graphical glitches with broken
|
||||
// OpenGL implementations. --achurch
|
||||
const float incX = percentX / float(NX);
|
||||
const float incY = percentY / float(NY);
|
||||
|
||||
const Vector c = rs.color;
|
||||
const float alpha = rs.alpha;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
float v0 = 1 - percentY + baseY;
|
||||
float v1 = v0 + incY;
|
||||
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
|
||||
{
|
||||
float u0 = baseX;
|
||||
float u1 = u0 + incX;
|
||||
const Vector *row0 = grid.row(y);
|
||||
const Vector *row1 = grid.row(y+1);
|
||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
||||
{
|
||||
const Vector dg00 = row0[x];
|
||||
const Vector dg01 = row1[x];
|
||||
const Vector dg10 = row0[x+1];
|
||||
const Vector dg11 = row1[x+1];
|
||||
|
||||
if (dg00.z != 0 || dg01.z != 0 || dg10.z != 0 || dg11.z != 0)
|
||||
{
|
||||
glColor4f(c.x, c.y, c.z, alpha*dg00.z);
|
||||
glTexCoord2f(u0, v0);
|
||||
glVertex2f(dg00.x, dg00.y);
|
||||
|
||||
glColor4f(c.x, c.y, c.z, alpha*dg01.z);
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex2f(dg01.x, dg01.y);
|
||||
|
||||
glColor4f(c.x, c.y, c.z, alpha*dg11.z);
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(dg11.x, dg11.y);
|
||||
|
||||
glColor4f(c.x, c.y, c.z, alpha*dg10.z);
|
||||
glTexCoord2f(u1, v0);
|
||||
glVertex2f(dg10.x, dg10.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
73
BBGE/RenderGrid.h
Normal file
73
BBGE/RenderGrid.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef BBGE_RENDERGRID_H
|
||||
#define BBGE_RENDERGRID_H
|
||||
|
||||
#include "Vector.h"
|
||||
#include "DataStructures.h"
|
||||
|
||||
struct RenderState;
|
||||
|
||||
enum GridDrawOrder
|
||||
{
|
||||
GRID_DRAW_WORLDMAP = -1, // LRTB order, uses grid.z as alpha
|
||||
GRID_DRAW_LRTB = 0, // the default. ignores grid.z
|
||||
GRID_DRAW_LRBT = 1, // Y axis inverted
|
||||
|
||||
GRID_DRAW_DEFAULT = GRID_DRAW_LRTB
|
||||
};
|
||||
|
||||
enum GridType
|
||||
{
|
||||
GRID_UNDEFINED = -1,
|
||||
GRID_WAVY = 0,
|
||||
GRID_STRIP = 1, // quad is in strip mode
|
||||
GRID_INTERP = 2, // quad is in grid mode
|
||||
};
|
||||
|
||||
class RenderGrid
|
||||
{
|
||||
public:
|
||||
RenderGrid(size_t w, size_t h);
|
||||
~RenderGrid();
|
||||
|
||||
void init(size_t w, size_t h);
|
||||
void reset();
|
||||
void resetWithAlpha(float a);
|
||||
void update(float dt);
|
||||
void render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
|
||||
void renderDebugPoints(const RenderState& rs) const;
|
||||
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);
|
||||
|
||||
size_t width() const { return grid.width(); }
|
||||
size_t height() const { return grid.height(); }
|
||||
size_t linearsize() const { return grid.linearsize(); }
|
||||
const Vector *data() const { return grid.data(); }
|
||||
Vector *data() { return grid.data(); }
|
||||
Array2d<Vector>& array2d() { return grid; }
|
||||
const Array2d<Vector>& array2d() const { return grid; }
|
||||
|
||||
static void ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha);
|
||||
|
||||
protected:
|
||||
Array2d<Vector> grid;
|
||||
float gridTimer;
|
||||
float drawGridOffsetX;
|
||||
float drawGridOffsetY;
|
||||
float drawGridModX;
|
||||
float drawGridModY;
|
||||
float drawGridTimeMultiplier;
|
||||
bool drawGridOut;
|
||||
public:
|
||||
unsigned char gridType; // unsigned char to save space
|
||||
unsigned char drawOrder;
|
||||
|
||||
void render_LRTB(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
|
||||
void render_LRBT(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
|
||||
void render_WithAlpha(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "ReadXML.h"
|
||||
#include "RenderBase.h"
|
||||
#include "SplineGrid.h"
|
||||
#include "RenderGrid.h"
|
||||
|
||||
#include <tinyxml2.h>
|
||||
using namespace tinyxml2;
|
||||
|
@ -129,16 +130,9 @@ void Bone::addSegment(Bone *b)
|
|||
|
||||
void Bone::createStrip(bool vert, int num)
|
||||
{
|
||||
if (!vert)
|
||||
{
|
||||
createGrid(num, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
createGrid(2, num);
|
||||
}
|
||||
RenderGrid *grid = vert ? createGrid(2, num) : createGrid(num, 2);
|
||||
stripVert = vert;
|
||||
gridType = GRID_STRIP;
|
||||
grid->gridType = GRID_STRIP;
|
||||
changeStrip.resize(num);
|
||||
}
|
||||
|
||||
|
@ -980,6 +974,7 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
|||
XMLElement *bones = xml->NewElement("Bones");
|
||||
for (i = 0; i < this->bones.size(); i++)
|
||||
{
|
||||
const RenderGrid * const grid = this->bones[i]->getGrid();
|
||||
XMLElement *bone = xml->NewElement("Bone");
|
||||
bone->SetAttribute("idx", (unsigned int) this->bones[i]->boneIdx);
|
||||
bone->SetAttribute("gfx", this->bones[i]->gfx.c_str());
|
||||
|
@ -1009,10 +1004,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
|||
bone->SetAttribute("offy", this->bones[i]->offset.y);
|
||||
if (!this->bones[i]->prt.empty())
|
||||
bone->SetAttribute("prt", this->bones[i]->prt.c_str());
|
||||
if(!this->bones[i]->getDrawGrid().empty() && this->bones[i]->gridType != Quad::GRID_STRIP)
|
||||
if(grid && grid->gridType != GRID_STRIP)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << this->bones[i]->getDrawGrid().width() << " " << this->bones[i]->getDrawGrid().height();
|
||||
os << grid->width() << " " << grid->height();
|
||||
bone->SetAttribute("grid", os.str().c_str());
|
||||
}
|
||||
else if (!this->bones[i]->changeStrip.empty())
|
||||
|
@ -1037,9 +1032,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
|||
os << this->bones[i]->originalScale.x << " " << this->bones[i]->originalScale.y;
|
||||
bone->SetAttribute("sz", os.str().c_str());
|
||||
}
|
||||
if(this->bones[i]->drawOrder != Quad::GRID_DRAW_DEFAULT)
|
||||
|
||||
if(grid && grid->drawOrder != GRID_DRAW_DEFAULT)
|
||||
{
|
||||
bone->SetAttribute("gridDrawOrder", (int)this->bones[i]->drawOrder);
|
||||
bone->SetAttribute("gridDrawOrder", (int)grid->drawOrder);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1132,9 +1128,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
|||
Bone *bone = this->getBoneByIdx(b->idx);
|
||||
if(bone)
|
||||
{
|
||||
const RenderGrid * const bgrid = bone->getGrid();
|
||||
os << b->idx << " " << b->x << " " << b->y << " " << b->rot << " ";
|
||||
// don't want to store grid points if they can be regenerated automatically
|
||||
size_t usedGridSize = bone->gridType == Quad::GRID_INTERP ? 0 : b->grid.size();
|
||||
size_t usedGridSize = (!bgrid || bgrid->gridType == GRID_INTERP) ? 0 : b->grid.size();
|
||||
os << usedGridSize << " ";
|
||||
if(usedGridSize)
|
||||
for (size_t i = 0; i < usedGridSize; i++)
|
||||
|
@ -1604,12 +1601,13 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
}
|
||||
if (bone->Attribute("grid"))
|
||||
{
|
||||
if(newb->getDrawGrid().empty())
|
||||
RenderGrid *grid = newb->getGrid();
|
||||
if(!grid)
|
||||
{
|
||||
SimpleIStringStream is(bone->Attribute("grid"), SimpleIStringStream::REUSE);
|
||||
int x, y;
|
||||
is >> x >> y;
|
||||
newb->createGrid(x, y);
|
||||
grid = newb->createGrid(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1617,11 +1615,11 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
os << "Bone idx " << newb->idx << " already has a DrawGrid, ignoring \"grid\" attribute";
|
||||
errorLog(os.str());
|
||||
}
|
||||
}
|
||||
if(const char *gdo = bone->Attribute("gridDrawOrder"))
|
||||
{
|
||||
int ord = atoi(gdo);
|
||||
newb->drawOrder = (Quad::GridDrawOrder)ord;
|
||||
if(const char *gdo = bone->Attribute("gridDrawOrder"))
|
||||
{
|
||||
int ord = atoi(gdo);
|
||||
grid->drawOrder = (GridDrawOrder)ord;
|
||||
}
|
||||
}
|
||||
bone = bone->NextSiblingElement("Bone");
|
||||
}
|
||||
|
@ -1809,7 +1807,6 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
for (size_t i = 0; i < this->bones.size(); i++)
|
||||
{
|
||||
Bone *bone = this->bones[i];
|
||||
const Array2d<Vector>& dg = bone->getDrawGrid();
|
||||
BoneKeyframe *bk = newSkeletalKeyframe.getBoneKeyframe(bone->boneIdx);
|
||||
if(!bk)
|
||||
{
|
||||
|
@ -1845,7 +1842,8 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
debugLog(os.str());
|
||||
continue;
|
||||
}
|
||||
if(bi->getDrawGrid().empty())
|
||||
RenderGrid *grid = bi->getGrid();
|
||||
if(!grid)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Interpolator specifies bone [" << bi->boneIdx << "] that has no grid";
|
||||
|
@ -1854,7 +1852,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
}
|
||||
|
||||
SplineType spline = SPLINE_BSPLINE;
|
||||
int cx = 3, cy = 3, degx = 3, degy = 3;
|
||||
unsigned cx = 3, cy = 3, degx = 3, degy = 3;
|
||||
if(const char *stype = interp->Attribute("type"))
|
||||
{
|
||||
SimpleIStringStream is(stype, SimpleIStringStream::REUSE);
|
||||
|
@ -1883,7 +1881,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
}
|
||||
}
|
||||
|
||||
bi->gridType = Quad::GRID_INTERP;
|
||||
grid->gridType = GRID_INTERP;
|
||||
// bone grid should have been created via <Bone grid=... /> earlier
|
||||
|
||||
const char *idata = interp->Attribute("data");
|
||||
|
@ -1898,7 +1896,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
bgip.bsp.resize(cx, cy, degx, degy);
|
||||
|
||||
const size_t numcp = size_t(cx) * size_t(cy);
|
||||
const size_t numgridp = bi->getDrawGrid().linearsize();
|
||||
const size_t numgridp = grid->linearsize();
|
||||
|
||||
// data format: "W H [x y x y ... (W*H times)] W H x y x y ..."
|
||||
// ^- start of 1st keyframe ^- 2nd keyframe
|
||||
|
@ -2062,7 +2060,8 @@ void AnimationLayer::updateBones()
|
|||
b->scale.x = lerp(bkey1->sx, bkey2->sx, dt, lerpType);
|
||||
b->scale.y = lerp(bkey1->sy, bkey2->sy, dt, lerpType);
|
||||
}
|
||||
if (b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && b->gridType == Quad::GRID_STRIP)
|
||||
RenderGrid *grid = b->getGrid();
|
||||
if (grid && b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && grid->gridType == GRID_STRIP)
|
||||
{
|
||||
if (bkey2->grid.size() < b->changeStrip.size())
|
||||
bkey2->grid.resize(b->changeStrip.size());
|
||||
|
@ -2074,22 +2073,21 @@ void AnimationLayer::updateBones()
|
|||
}
|
||||
b->setStripPoints(b->stripVert, &b->changeStrip[0], b->changeStrip.size());
|
||||
}
|
||||
if (b->animated==Bone::ANIM_ALL && b->gridType == Quad::GRID_INTERP)
|
||||
if (grid && b->animated==Bone::ANIM_ALL && grid->gridType == GRID_INTERP)
|
||||
{
|
||||
Array2d<Vector>& dg = b->getDrawGrid();
|
||||
const size_t N = dg.linearsize();
|
||||
const size_t N = grid->linearsize();
|
||||
if(bkey1->grid.size() < N)
|
||||
{
|
||||
bkey1->grid.resize(N);
|
||||
Quad::ResetGridAndAlpha(&bkey1->grid[0], dg.width(), dg.height(), 1.0f);
|
||||
RenderGrid::ResetWithAlpha(&bkey1->grid[0], grid->width(), grid->height(), 1.0f);
|
||||
}
|
||||
if(bkey2->grid.size() < N)
|
||||
{
|
||||
bkey2->grid.resize(N);
|
||||
Quad::ResetGridAndAlpha(&bkey2->grid[0], dg.width(), dg.height(), 1.0f);
|
||||
RenderGrid::ResetWithAlpha(&bkey2->grid[0], grid->width(), grid->height(), 1.0f);
|
||||
}
|
||||
|
||||
Vector *dst = dg.data();
|
||||
Vector *dst = grid->data();
|
||||
for(size_t i = 0; i < N; ++i)
|
||||
{
|
||||
dst[i].x = lerp(bkey1->grid[i].x, bkey2->grid[i].x, dt, lerpType);
|
||||
|
@ -2219,16 +2217,16 @@ void SkeletalSprite::selectNextBone()
|
|||
|
||||
void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
|
||||
{
|
||||
const Array2d<Vector>& dg = bone->getDrawGrid();
|
||||
const RenderGrid *grid = bone->getGrid();
|
||||
assert(bone->boneIdx == bk.idx);
|
||||
assert(bk.grid.size() == dg.linearsize());
|
||||
bsp.recalc(&bk.grid[0], dg.width(), dg.height(), &bk.controlpoints[0]);
|
||||
assert(bk.grid.size() == grid->linearsize());
|
||||
bsp.recalc(&bk.grid[0], grid->width(), grid->height(), &bk.controlpoints[0]);
|
||||
|
||||
}
|
||||
|
||||
void BoneGridInterpolator::updateGridAndBone(BoneKeyframe& bk, Bone *bone)
|
||||
{
|
||||
updateGridOnly(bk, bone);
|
||||
Vector *dst = bone->getDrawGrid().data();
|
||||
Vector *dst = bone->getGrid()->data();
|
||||
std::copy(bk.grid.begin(), bk.grid.end(), dst);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "SplineGrid.h"
|
||||
#include "RenderBase.h"
|
||||
#include "Core.h"
|
||||
#include "RenderGrid.h"
|
||||
|
||||
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
||||
|
||||
|
@ -69,7 +70,7 @@ void SplineGridCtrlPoint::onUpdate(float dt)
|
|||
}
|
||||
|
||||
SplineGrid::SplineGrid()
|
||||
: deg(0)
|
||||
: wasModified(false), deg(0)
|
||||
{
|
||||
setWidthHeight(128, 128);
|
||||
renderQuad = true;
|
||||
|
@ -80,12 +81,12 @@ SplineGrid::~SplineGrid()
|
|||
{
|
||||
}
|
||||
|
||||
void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
|
||||
RenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
|
||||
{
|
||||
size_t oldcpx = bsp.ctrlX();
|
||||
size_t oldcpy = bsp.ctrlY();
|
||||
|
||||
this->createGrid(xres, yres);
|
||||
RenderGrid *ret = this->createGrid(xres, yres);
|
||||
|
||||
std::vector<SplineGridCtrlPoint*> oldp;
|
||||
ctrlp.swap(oldp);
|
||||
|
@ -121,13 +122,18 @@ void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned d
|
|||
}
|
||||
|
||||
recalc();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SplineGrid::recalc()
|
||||
{
|
||||
exportControlPoints(&bsp.controlpoints[0]);
|
||||
bsp.recalc(drawGrid.data(), drawGrid.width(), drawGrid.height());
|
||||
wasModified = true;
|
||||
if(grid)
|
||||
{
|
||||
bsp.recalc(grid->data(), grid->width(), grid->height());
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SplineGrid::exportControlPoints(Vector* controlpoints)
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
~SplineGrid();
|
||||
|
||||
// # of control points on each axis
|
||||
void resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
|
||||
RenderGrid *resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
|
||||
void recalc();
|
||||
void exportControlPoints(Vector *controlpoints);
|
||||
void importControlPoints(const Vector *controlpoints);
|
||||
|
|
Loading…
Reference in a new issue