Files
BlitzNext/Runtime/blitz3d/sprite.cpp
T

152 lines
3.3 KiB
C++
Raw Normal View History

2014-01-31 08:23:00 +13:00
2019-01-18 15:55:06 +01:00
#include "sprite.hpp"
2019-01-18 17:04:17 +01:00
#include "std.hpp"
2014-01-31 08:23:00 +13:00
extern float stats3d[];
2019-01-18 17:04:17 +01:00
static float null[] = {0, 0, 0};
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
static float tex_coords0[2][2] = {{0, 0}, {0, 0}};
static float tex_coords1[2][2] = {{1, 0}, {1, 0}};
static float tex_coords2[2][2] = {{1, 1}, {1, 1}};
static float tex_coords3[2][2] = {{0, 1}, {0, 1}};
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
extern gxRuntime* gx_runtime;
extern gxGraphics* gx_graphics;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
static gxMesh* mesh;
static int mesh_size;
2014-01-31 08:23:00 +13:00
static vector<int> mesh_indices;
2019-01-18 17:04:17 +01:00
static int allocIndex()
{
if (!mesh_indices.size()) {
if (mesh_size)
gx_graphics->freeMesh(mesh);
for (int k = 0; k < 256; ++k) {
mesh_indices.push_back(mesh_size++);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
mesh = gx_graphics->createMesh(mesh_size * 4, mesh_size * 2, 0);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
int n = mesh_indices.back();
2014-01-31 08:23:00 +13:00
mesh_indices.pop_back();
return n;
}
2019-01-18 17:04:17 +01:00
static void freeIndex(int n)
{
mesh_indices.push_back(n);
if (mesh_indices.size() != mesh_size)
return;
gx_graphics->freeMesh(mesh);
2014-01-31 08:23:00 +13:00
mesh_indices.clear();
2019-01-18 17:04:17 +01:00
mesh_size = 0;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
Sprite::Sprite() : view_mode(VIEW_MODE_FREE), xhandle(0), yhandle(0), rot(0), xscale(1), yscale(1), captured(false)
{
setRenderSpace(RENDER_SPACE_WORLD);
mesh_index = allocIndex();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
Sprite::Sprite(const Sprite& t)
: Model(t), view_mode(t.view_mode), xhandle(t.xhandle), yhandle(t.yhandle), rot(t.rot), xscale(t.xscale),
yscale(t.yscale), captured(false)
{
mesh_index = allocIndex();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
Sprite::~Sprite()
{
freeIndex(mesh_index);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Sprite::setRotation(float angle)
{
rot = angle;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Sprite::setScale(float x, float y)
{
xscale = x;
yscale = y;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Sprite::setHandle(float x, float y)
{
xhandle = x;
yhandle = y;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Sprite::setViewmode(int mode)
{
view_mode = mode;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Sprite::capture()
{
2014-01-31 08:23:00 +13:00
Model::capture();
2019-01-18 17:04:17 +01:00
r_rot = rot;
r_xscale = xscale;
r_yscale = yscale;
captured = true;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
bool Sprite::beginRender(float tween)
{
Model::beginRender(tween);
if (tween == 1 || !captured) {
r_rot = rot;
r_xscale = xscale;
r_yscale = yscale;
} else {
r_rot = (rot - r_rot) * tween + r_rot;
r_xscale = (xscale - r_xscale) * tween + r_xscale;
r_yscale = (yscale - r_yscale) * tween + r_yscale;
2014-01-31 08:23:00 +13:00
}
return true;
}
2019-01-18 17:04:17 +01:00
bool Sprite::render(const RenderContext& rc)
{
Transform t = getRenderTform();
if (view_mode == VIEW_MODE_FREE) {
t.m = rc.getCameraTform().m;
} else if (view_mode == VIEW_MODE_UPRIGHT) {
t.m.k = rc.getCameraTform().m.k;
t.m.orthogonalize();
} else if (view_mode == VIEW_MODE_UPRIGHT2) {
t.m = yawMatrix(matrixYaw(rc.getCameraTform().m)) * t.m;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
t.m = t.m * rollMatrix(r_rot) * scaleMatrix(r_xscale, r_yscale, 1);
2014-01-31 08:23:00 +13:00
static Vector verts[4];
2019-01-18 17:04:17 +01:00
verts[0] = t * Vector(-1 - xhandle, 1 - yhandle, 0);
verts[1] = t * Vector(1 - xhandle, 1 - yhandle, 0);
verts[2] = t * Vector(1 - xhandle, -1 - yhandle, 0);
verts[3] = t * Vector(-1 - xhandle, -1 - yhandle, 0);
if (!rc.getWorldFrustum().cull(verts, 4))
return false;
mesh->lock(false);
int fv = mesh_index * 4, ft = mesh_index * 2;
mesh->setVertex(fv + 0, &verts[0].x, null, tex_coords0);
mesh->setVertex(fv + 1, &verts[1].x, null, tex_coords1);
mesh->setVertex(fv + 2, &verts[2].x, null, tex_coords2);
mesh->setVertex(fv + 3, &verts[3].x, null, tex_coords3);
if (rc.isReflected()) {
mesh->setTriangle(ft + 0, 0, 2, 1);
mesh->setTriangle(ft + 1, 0, 3, 2);
} else {
mesh->setTriangle(ft + 0, 0, 1, 2);
mesh->setTriangle(ft + 1, 0, 2, 3);
2014-01-31 08:23:00 +13:00
}
mesh->unlock();
2019-01-18 17:04:17 +01:00
enqueue(mesh, fv, 4, ft, 2);
2014-01-31 08:23:00 +13:00
return false;
}