140 lines
2.8 KiB
C++
140 lines
2.8 KiB
C++
#include "model.hpp"
|
|
|
|
extern gxScene* gx_scene;
|
|
|
|
class Model::MeshQueue {
|
|
union {
|
|
gxMesh* mesh;
|
|
MeshQueue* next;
|
|
};
|
|
int fv, vc, ft, tc;
|
|
Brush brush;
|
|
int q_type;
|
|
// bool opaque;
|
|
|
|
static MeshQueue* pool;
|
|
|
|
public:
|
|
MeshQueue() {}
|
|
|
|
MeshQueue(gxMesh* m, int fv, int vc, int ft, int tc, const Brush& b)
|
|
: mesh(m), fv(fv), vc(vc), ft(ft), tc(tc), brush(b)
|
|
{
|
|
int n = brush.getBlend();
|
|
q_type = (n == gxScene::BLEND_REPLACE) ? QUEUE_OPAQUE : QUEUE_TRANSPARENT;
|
|
}
|
|
|
|
int getQueueType() const
|
|
{
|
|
return q_type;
|
|
}
|
|
void render()
|
|
{
|
|
gx_scene->setRenderState(brush.getRenderState());
|
|
gx_scene->render(mesh, fv, vc, ft, tc);
|
|
}
|
|
void* operator new(size_t sz)
|
|
{
|
|
static const int GROW = 256;
|
|
if (!pool) {
|
|
pool = new MeshQueue[GROW];
|
|
for (int k = 0; k < GROW - 1; ++k)
|
|
pool[k].next = &pool[k + 1];
|
|
pool[GROW - 1].next = 0;
|
|
}
|
|
MeshQueue* t = pool;
|
|
pool = t->next;
|
|
return t;
|
|
}
|
|
void operator delete(void* q)
|
|
{
|
|
MeshQueue* t = (MeshQueue*)q;
|
|
t->next = pool;
|
|
pool = t;
|
|
}
|
|
};
|
|
|
|
Model::MeshQueue* Model::MeshQueue::pool;
|
|
|
|
Model::Model() : space(RENDER_SPACE_LOCAL), auto_fade(false), captured_alpha(1), w_brush(true) {}
|
|
|
|
Model::Model(const Model& t)
|
|
: Object(t), space(t.space), brush(t.brush), auto_fade(t.auto_fade), auto_fade_nr(t.auto_fade_nr),
|
|
auto_fade_fr(t.auto_fade_fr), captured_alpha(t.captured_alpha), w_brush(true)
|
|
{}
|
|
|
|
void Model::capture()
|
|
{
|
|
Object::capture();
|
|
captured_alpha = brush.getAlpha();
|
|
}
|
|
|
|
bool Model::beginRender(float t)
|
|
{
|
|
Object::beginRender(t);
|
|
tweened_alpha = brush.getAlpha();
|
|
if (t != 1 && tweened_alpha != captured_alpha) {
|
|
//
|
|
//render tweening of alpha
|
|
//
|
|
tweened_alpha = (tweened_alpha - captured_alpha) * t + captured_alpha;
|
|
}
|
|
return tweened_alpha > 0;
|
|
}
|
|
|
|
bool Model::doAutoFade(const Vector& eye)
|
|
{
|
|
float alpha = tweened_alpha;
|
|
if (auto_fade) {
|
|
//
|
|
//autofading of alpha
|
|
//
|
|
float d = eye.distance(getRenderTform().v);
|
|
if (d >= auto_fade_fr)
|
|
return false;
|
|
if (d >= auto_fade_nr) {
|
|
float t = 1 - (d - auto_fade_nr) / (auto_fade_fr - auto_fade_nr);
|
|
alpha *= t;
|
|
if (alpha <= 0)
|
|
return false;
|
|
}
|
|
}
|
|
if (w_brush)
|
|
render_brush = brush;
|
|
|
|
if (alpha != render_brush.getAlpha()) {
|
|
render_brush.setAlpha(alpha);
|
|
} else if (!w_brush) {
|
|
return true;
|
|
}
|
|
|
|
setRenderBrush(render_brush);
|
|
w_brush = false;
|
|
return true;
|
|
}
|
|
|
|
void Model::enqueue(MeshQueue* q)
|
|
{
|
|
queues[q->getQueueType()].push_back(q);
|
|
}
|
|
|
|
void Model::enqueue(gxMesh* mesh, int fv, int vc, int ft, int tc)
|
|
{
|
|
enqueue(new MeshQueue(mesh, fv, vc, ft, tc, render_brush));
|
|
}
|
|
|
|
void Model::enqueue(gxMesh* mesh, int fv, int vc, int ft, int tc, const Brush& brush)
|
|
{
|
|
enqueue(new MeshQueue(mesh, fv, vc, ft, tc, brush));
|
|
}
|
|
|
|
void Model::renderQueue(int type)
|
|
{
|
|
std::vector<MeshQueue*>* que = &queues[type];
|
|
for (; que->size(); que->pop_back()) {
|
|
MeshQueue* q = que->back();
|
|
q->render();
|
|
delete q;
|
|
}
|
|
}
|