41 laAnimatedModel::laAnimatedModel(
void)
50 _bInterpolation = M_TRUE;
51 _bTraceEffect = M_FALSE;
54 laAnimatedModel::~laAnimatedModel(
void) {
58 void laAnimatedModel::discard() {
59 if(_arFrames)
delete [] _arFrames;
63 bool laAnimatedModel::load(
char* strFile)
66 ASSERT(strnlen(strFile, 64) < 64,
"Invalid file name");
69 static char junk[1024];
72 static int nverts,ntverts,nfaces;
74 _pCR = ::laSystemIntegrator::getRenderer();
78 if( strstr(strFile,
".jrm") )
83 _bInterpolation = M_FALSE;
85 _arFrames[0].load(strFile);
86 setTexture( _arFrames[0]._nTex, _arFrames[0]._bEmissive, _arFrames[0]._nShininess);
91 MLOG(
"Loading animated model '%s'...", strFile);
95 if(!_bAddDirectoryPrefix) strFilePath[0]=
'\0';
96 strcat(strFilePath, strFile);
98 try{ f.fileOpen(strFilePath); }
catch(
laError& ){
throw laError(
"Unable to open model file '%s'", strFile); }
102 try{ f.readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section separator expected but not found (while parsing '%s')", strFile); }
104 if(strcmp(junk,
"GENERAL INFORMATION"))
throw laError(
"Section [GENERAL INFORMATION] expected, [%s] found ('%s')", junk, strFile);
109 ASSERT( !strcmp(ver,
"Animated JRM 1"),
"Unappropriate model format '%s' (while parsing '%s')", ver, f.getFileName());
114 f.readInt(&ntverts, M_FALSE);
115 f.readInt(&nfaces, M_FALSE);
117 ASSERT( nverts && ntverts && nverts,
"Corrupted file '%s'", f.getFileName());
120 throw laError(
"Section [GENERAL INFORMATION] appears to be corrupted (while parsing '%s')", f.getFileName());
125 try{ f.readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section separator expected but not found (while parsing '%s')", strFile); }
127 ASSERT(!strcmp(junk,
"TEXTURE"),
"Section [TEXTURE] expected, [%s] found ('%s')", junk, strFile);
131 f.readBool(&_bEmissive);
134 _nShininess = (unsigned) (sh*100);
137 throw laError(
"Section [TEXTURE] appears to be corrupted (while parsing '%s')", f.getFileName());
145 try{ f.readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section separator expected but not found (while parsing '%s')", strFile); }
146 ASSERT( !strcmp(_strupr(junk),
"ANIMATION"),
"Section [ANIMATION] expected, [%s] found ('%s')", junk, strFile);
149 f.ctlSetSeparators(
" f");
151 f.readUnsigned(&_nFrameCnt);
152 f.readDouble(&_dSPF);
153 f.ctlSetSeparators(
" ");
159 throw laError(
"Section [ANIMATION] appears to be corrupted (while parsing '%s')", f.getFileName());
164 char strCacheFile[256];
165 sprintf(strCacheFile,
"%s.cache", strFilePath);
166 FILE* fCache_Read = fopen(strCacheFile,
"rb");
170 for(
unsigned i=0; i<_nFrameCnt; i++)
172 _arFrames[i].create(nfaces);
173 _arFrames[i].setTexture(_nTex, _bEmissive, _nShininess);
174 _arFrames[i]._cache_load(fCache_Read);
181 FILE* fCache_Write = fopen(strCacheFile,
"wb");
182 ASSERT(fCache_Write,
"Cannot open cache for writing (%s)", strCacheFile);
184 for(
unsigned i=0; i<_nFrameCnt; i++)
186 char strExpectedTitle[128], ss[2];
187 sprintf(strExpectedTitle,
"FRAME %d", i+1);
189 f.ctlGetSectionSep(ss);
190 f.ctlSetSectionSep(
"##");
192 try{ f.readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Frame label expected but not found (while parsing '%s')", strFile); }
193 ASSERT(! strcmp(_strupr(junk), strExpectedTitle),
"Frame %d expected, #%s# found (while parsing '%s')", strExpectedTitle, junk, strFile);
194 f.ctlSetSectionSep(ss);
197 _arFrames[i].load(&f, nfaces, nverts, ntverts);
198 _arFrames[i].setTexture(_nTex, _bEmissive, _nShininess);
200 _arFrames[i]._cache_save(fCache_Write);
203 throw laError(
"%s\n\nFrame %d appears to be corrupted (while parsing '%s')", pe.getText(), i, f.getFileName());
206 fclose(fCache_Write);
218 ASSERT( pPose1->vertexCount() == pPose2->vertexCount(),
"Incompatible poses");
220 if( frameCount() != 2 ) {
226 _arFrames[0].instantiate( pPose1 );
227 _arFrames[1].instantiate( pPose2 );
229 _bInterpolation = M_TRUE;
236 setTexture( *(pPose1->texture()), pPose1->_bEmissive, pPose1->_nShininess);
248 laPoint3 *vt, *v1,* v2;
249 laPoint3 *nt, *n1, *n2;
253 inline void _blend(
const _blend_data &bd)
255 for(
unsigned i=bd.n_first; i < bd.n; i++) {
256 bd.vt[i] = bd.w1*bd.v1[i] + bd.w2*bd.v2[i];
257 bd.nt[i] = bd.w1*bd.n1[i] + bd.w2*bd.n2[i];
260 memcpy(bd.uvt+bd.n_first, bd.uv1+bd.n_first,
sizeof(
laPoint2)*bd.n);
279 PROFILE_REN(laAnimatedModel_snapshot);
285 laStaticModel *pnext = _arFrames + ( ((_nCrFrame+1)>=_nFrameCnt) ? (_bCycle?0:_nCrFrame) : _nCrFrame+1 );
289 if( pm->isLightweight() || (pm->vertexCount() != pcurrent->vertexCount()) ) {
291 pm->create( pcurrent->vertexCount()/3 );
293 pm->setTexture( *(pcurrent->texture()), pcurrent->_bEmissive, pcurrent->_nShininess );
298 bd.w2 = M_MIN(1, _dTimeElapsed/_dSPF); bd.w1 = 1-bd.w2;
299 bd.vt = pm->_arFlatVertex; bd.v1 = pcurrent->_arFlatVertex; bd.v2 = pnext->_arFlatVertex;
300 bd.nt = pm->_arFlatNormal; bd.n1 = pcurrent->_arFlatNormal; bd.n2 = pnext->_arFlatNormal;
301 bd.uvt = pm->_arFlatTex; bd.uv1 = pcurrent->_arFlatTex; bd.uv2 = pnext->_arFlatTex;
302 bd.n_first = 0; bd.n = pm->vertexCount();
317 laPoint3 laAnimatedModel::sample(
unsigned nVertexIndex)
320 ASSERT(_arFrames && _nFrameCnt,
"Nil frameset");
323 laStaticModel *pnext = _arFrames + ( ((_nCrFrame+1)>=_nFrameCnt) ? (_bCycle?0:_nCrFrame) : _nCrFrame+1 );
324 ASSERT(nVertexIndex < pcurrent->vertexCount(),
"Requested vertex sample out of bounds", nVertexIndex);
326 double w2 = M_MIN(1, _dTimeElapsed/_dSPF), w1 = 1-w2;
328 return ( w1*(pcurrent->_arFlatVertex[nVertexIndex]) + w2*(pnext->_arFlatVertex[nVertexIndex]) );
337 PROFILE_REN(laAnimatedModel_draw);
338 ASSERT(_arFrames && _nFrameCnt,
"Nil frameset");
339 ASSERT(_nCrFrame < _nFrameCnt,
"Invalid frame");
342 _arFrames[0].draw(pr);
375 if(_bInterpolation) { snapshot( &_snapshot ); _snapshot.draw( pr ); }
376 else _arFrames[_nCrFrame].draw(pr);
381 void laAnimatedModel::animate(laTimer &t)
383 if( _nFrameCnt<=1 )
return;
385 if( (_nCrFrame>=(_nFrameCnt-1)) && (!_bCycle) ) {
386 _nCrFrame = _nFrameCnt-1;
390 _dTimeElapsed += t.delta();
392 while(_dTimeElapsed >= _dSPF)
394 _dTimeElapsed -= _dSPF;
397 if(_nCrFrame>=_nFrameCnt)
399 if(_bCycle) _nCrFrame=0;
402 _nCrFrame = _nFrameCnt-1;
413 _arFrames[0].buildCollisionData(pDomain, pTrap);
416 char* laAnimatedModel::strTexture() {
417 return _arFrames[_nCrFrame].strTexture();
420 unsigned laAnimatedModel::vertexCount() {
421 return _arFrames[_nCrFrame].vertexCount();
424 laPoint3 laAnimatedModel::boundaryMin() {
return _arFrames[0].boundaryMin(); }
425 laPoint3 laAnimatedModel::boundaryMax() {
return _arFrames[0].boundaryMax(); }
427 void laAnimatedModel::edScale(laPoint3 sz) {
428 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edScale(sz);
431 void laAnimatedModel::edTranslate(laPoint3 pos) {
432 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edTranslate(pos);
435 void laAnimatedModel::edNormalize() {
436 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edNormalize();
439 void laAnimatedModel::edMinaxis() {
440 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edMinaxis();
443 void laAnimatedModel::edMaxaxis() {
444 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edMaxaxis();
447 void laAnimatedModel::edCentralize() {
448 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edCentralize();
451 void laAnimatedModel::edSnap() {
452 for(
unsigned i=0; i<_nFrameCnt; i++) _arFrames[i].edSnap();
455 void laAnimatedModel::edInvertAnimation()
459 for(
unsigned i=0; i<_nFrameCnt/2; i++)
461 f.instantiate( _arFrames+i );
462 _arFrames[i].instantiate( _arFrames + _nFrameCnt-i-1 );
463 _arFrames[_nFrameCnt-i-1].instantiate( &f );
#define M_DIR_MODEL
3D models directory
Virtual interface for the Engine graphics renderer.