mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-01 15:35:47 +00:00
383 lines
9.1 KiB
C++
383 lines
9.1 KiB
C++
#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();
|
|
const size_t w = grid.width();
|
|
const size_t h = grid.height();
|
|
|
|
size_t nx = w;
|
|
if(drawGridOut)
|
|
nx /= 2;
|
|
|
|
for (size_t y = 0; y < h; y++)
|
|
{
|
|
Vector * const row = grid.row(y);
|
|
const float xoffset = y * drawGridOffsetX;
|
|
const float addx = sinf(gridTimer+xoffset)*drawGridModX;
|
|
|
|
size_t x;
|
|
for (x = 0; x < nx; x++)
|
|
row[x].x -= addx;
|
|
for (; x < w; x++)
|
|
row[x].x += addx;
|
|
|
|
if(const float dgmy = drawGridModY)
|
|
for (x = 0; x < w; x++)
|
|
{
|
|
float yoffset = x * drawGridOffsetY;
|
|
row[x].y += cosf(gridTimer+yoffset)*dgmy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 float* 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 y = 0; y < H; y++)
|
|
{
|
|
const size_t wavy_y = (H - y)-1;
|
|
if (wavy_y < len)
|
|
{
|
|
const float tmp = wavy[wavy_y] * iw;
|
|
Vector * const row = grid.row(y);
|
|
for (size_t x = 0; x < NX; x++)
|
|
{
|
|
row[x].x = tmp - 0.5f;
|
|
row[x+1].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 W = grid.width();
|
|
const size_t H = grid.height();
|
|
for (size_t y = 0; y < H; y++)
|
|
{
|
|
const Vector * const row = grid.row(y);
|
|
for (size_t x = 0; x < W; x++)
|
|
glVertex2f(row[x].x, row[x].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();
|
|
}
|
|
|