146 lines
3.1 KiB
C++
146 lines
3.1 KiB
C++
|
|
#include "md2model.hpp"
|
|
#include "md2rep.hpp"
|
|
#include "std.hpp"
|
|
|
|
struct MD2Model::Rep : public MD2Rep {
|
|
int ref_cnt;
|
|
|
|
Rep(const string& f) : MD2Rep(f), ref_cnt(1) {}
|
|
};
|
|
|
|
MD2Model::MD2Model(const string& f)
|
|
: rep(new Rep(f)), anim_mode(0), anim_time(0), render_a(0), render_b(0), render_t(0), trans_verts(0)
|
|
{}
|
|
|
|
MD2Model::MD2Model(const MD2Model& t)
|
|
: Model(t), rep(t.rep), anim_mode(0), anim_time(0), render_a(0), render_b(0), render_t(0), trans_verts(0)
|
|
{
|
|
++rep->ref_cnt;
|
|
}
|
|
|
|
MD2Model::~MD2Model()
|
|
{
|
|
if (!--rep->ref_cnt)
|
|
delete rep;
|
|
if (trans_verts)
|
|
delete[] trans_verts;
|
|
}
|
|
|
|
void MD2Model::startMD2Anim(int first, int last, int mode, float speed, float trans)
|
|
{
|
|
if (last < first)
|
|
std::swap(first, last);
|
|
|
|
if (first < 0)
|
|
first = 0;
|
|
else if (first >= rep->numFrames())
|
|
first = rep->numFrames() - 1;
|
|
|
|
if (last < 0)
|
|
last = 0;
|
|
else if (last >= rep->numFrames())
|
|
last = rep->numFrames() - 1;
|
|
|
|
if (trans > 0) {
|
|
if (!trans_verts)
|
|
trans_verts = new MD2Rep::Vert[rep->numVertices()];
|
|
|
|
if (anim_mode & 0x8000)
|
|
rep->render(trans_verts, anim_time, trans_time);
|
|
else
|
|
rep->render(trans_verts, render_a, render_b, render_t);
|
|
trans_speed = 1.0f / trans;
|
|
trans_time = 0;
|
|
mode |= 0x8000;
|
|
}
|
|
|
|
anim_first = first;
|
|
anim_last = last;
|
|
anim_len = last - first;
|
|
anim_speed = speed;
|
|
anim_time = ((mode & 0x7fff) == Animator::ANIM_MODE_LOOP || anim_speed >= 0) ? anim_first : anim_last;
|
|
anim_mode = mode;
|
|
|
|
if (!anim_speed || !anim_len) {
|
|
render_a = render_b = anim_time;
|
|
render_t = 0;
|
|
anim_mode &= 0x8000;
|
|
}
|
|
}
|
|
|
|
void MD2Model::animate(float e)
|
|
{
|
|
Model::animate(e);
|
|
if (!anim_mode)
|
|
return;
|
|
if (anim_mode & 0x8000) {
|
|
trans_time += trans_speed;
|
|
if (trans_time < 1)
|
|
return;
|
|
anim_mode &= ~0x8000;
|
|
if (!anim_mode)
|
|
return;
|
|
}
|
|
anim_time = anim_time + anim_speed * e;
|
|
if (anim_time < anim_first) {
|
|
switch (anim_mode) {
|
|
case Animator::ANIM_MODE_LOOP:
|
|
anim_time += anim_len;
|
|
break;
|
|
case Animator::ANIM_MODE_PINGPONG:
|
|
anim_time = anim_first + (anim_first - anim_time);
|
|
anim_speed = -anim_speed;
|
|
break;
|
|
default:
|
|
anim_time = anim_first;
|
|
anim_mode = 0;
|
|
break;
|
|
}
|
|
} else if (anim_time >= anim_last) {
|
|
switch (anim_mode) {
|
|
case Animator::ANIM_MODE_LOOP:
|
|
anim_time -= anim_len;
|
|
break;
|
|
case Animator::ANIM_MODE_PINGPONG:
|
|
anim_time = anim_last - (anim_time - anim_last);
|
|
anim_speed = -anim_speed;
|
|
break;
|
|
default:
|
|
anim_time = anim_last;
|
|
anim_mode = 0;
|
|
break;
|
|
}
|
|
}
|
|
render_a = floor(anim_time);
|
|
render_b = render_a + 1;
|
|
if (anim_mode == Animator::ANIM_MODE_LOOP && render_b == anim_last)
|
|
render_b = anim_first;
|
|
render_t = anim_time - render_a;
|
|
}
|
|
|
|
bool MD2Model::render(const RenderContext& rc)
|
|
{
|
|
static Frustum f;
|
|
new (&f) Frustum(rc.getWorldFrustum(), -getRenderTform());
|
|
if (!f.cull(rep->getBox()))
|
|
return false;
|
|
|
|
if (anim_mode & 0x8000) {
|
|
rep->render(this, trans_verts, anim_time, trans_time);
|
|
} else {
|
|
rep->render(this, render_a, render_b, render_t);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int MD2Model::getMD2AnimLength() const
|
|
{
|
|
return rep->numFrames();
|
|
}
|
|
|
|
bool MD2Model::getValid() const
|
|
{
|
|
return rep->numFrames() > 0;
|
|
}
|