blitz3d/blitz3d/md2model.cpp

130 lines
2.9 KiB
C++

#include "std.h"
#include "md2rep.h"
#include "md2model.h"
struct MD2Model::Rep : public MD2Rep{
int ref_cnt;
Rep( const string &f):MD2Rep( f ),
ref_cnt(1){
}
};
MD2Model::MD2Model( const string &f ):
rep( d_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=d_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;
}