/********************************************************************** *< FILE: aiimp.cpp DESCRIPTION: .AI file import module CREATED BY: Tom Hudson HISTORY: created 28 June 1996 *> Copyright (c) 1996, All Rights Reserved. **********************************************************************/ #include "Stdafx.h" #include "Includes.h" /* #include #include #include #include #include #include */ #include "matrix4.h" #include "xsiimp.h" #define M_PI ( 3.14159265359f) void split_fn(char *path,char *file,char *pf) { int ix,jx,bs_loc,fn_loc; if(strlen(pf)==0) { if(path) *path=0; if(file) *file=0; return; } bs_loc=strlen(pf); for(ix=bs_loc-1; ix>=0; --ix) { if(pf[ix]=='\\') { bs_loc=ix; fn_loc=ix+1; goto do_split; } if(pf[ix]==':') { bs_loc=ix+1; fn_loc=ix+1; goto do_split; } } bs_loc= -1; fn_loc=0; do_split: if(file) strcpy(file,&pf[fn_loc]); if(path) { if(bs_loc>0) { for(jx=0; jxPrint(ident+1); sib=sib->sibling; } PrintIdent(ident); OutputDebugString("}\n"); } } }; #define PDEB (0) char *ReadToken(char *at,char *end,int &len,char **out) { char *ret=0; len=0; while (at'||*at=='{'||*at=='<'||*at=='\"')) { len++; at++; } } *out=at; #if 0 static char mess[10000]; static char str[10000]; mystrncpy(str,ret,len); sprintf(mess,"Token |%s|\n",str); OutputDebugString(mess); #endif return ret; } TxtNode *ReadANode(char *at,char *end,char **atout) { TxtNode *ret=0; int len; char *retat; char *start; //OutputDebugString("***"); start=ReadToken(at,end,len,&retat); at=retat; *atout=at; if (!start) { //OutputDebugString("Eof\n"); return 0; } if (*start=='}') { //OutputDebugString("End}\n"); return 0; } if (*start=='{') { //OutputDebugString("Start{\n"); ret=new TxtNode; TxtNode **last=&ret->child; while (1) { TxtNode *t=ReadANode(at,end,&retat); at=retat; if (!t) break; *last=t; last=&t->sibling; } } else { ret=new TxtNode; ret->text=start; ret->length=len; } *atout=at; return ret; } struct SceneNodes { char name[100]; SceneNodes *parent; Matrix4 mat; Matrix4 BaseMat; Matrix4 *animat; int nanimat; }; static SceneNodes sNodes[5000]; static nsNodes=0; int FindNodes(SceneNodes *parent,TxtNode *t) { static char tmp[1000]; if (t->child) { TxtNode *sib=t->child; while (sib) { if (sib->text&&!mystrncmp("Frame",sib->text,sib->length)) { SceneNodes tmpNode; Matrix4 tm,tmBase; tm.Identity(); sib=sib->sibling; if (!sib) return 1; assert(sib->length<100); if (!strncmp("frm-",sib->text,4)) mystrncpy(tmpNode.name,sib->text+4,sib->length-4); else mystrncpy(tmpNode.name,sib->text,sib->length); //OutputDebugString(tmpNode.name); //OutputDebugString("\n"); sib=sib->sibling; if (!sib) return 2; { TxtNode *FrameLook=sib; TxtNode *sub=sib->child; if (!sub) return 3; if (!sub->text) return 4; if (mystrncmp("FrameTransformMatrix",sub->text,sub->length)) return 5; sub=sub->sibling; { TxtNode *xf=sub->child; int r,c; #if 0 OutputDebugString("matrix\n"); #endif for (r=0;r<4;r++) { int rr=r; float sign=1.0f; if (r==1) rr=2; if (r==2) { sign=-1.0f; rr=1; } for (c=0;c<4;c++) { if (!xf||!xf->text) return 6; if (c==0) tm[rr][0]=sign*(float)myatof(xf->text,xf->length); else if (c==1) tm[rr][2]=sign*(float)myatof(xf->text,xf->length); else if (c==2) tm[rr][1]=-sign*(float)myatof(xf->text,xf->length); xf=xf->sibling; } } #if 0 for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",tm[r][0],tm[r][1],tm[r][2]); OutputDebugString(tmp); } #endif tm.CalcFlags(); } tmBase=tm; sub=sub->sibling; while (sub) { if (sub->text&&!mystrncmp("SI_FrameBasePoseMatrix",sub->text,sub->length)) { sub=sub->sibling; { TxtNode *xf=sub->child; int r,c; #if 0 OutputDebugString("pose matrix\n"); #endif for (r=0;r<4;r++) { int rr=r; float sign=1.0f; if (r==1) rr=2; if (r==2) { sign=-1.0f; rr=1; } for (c=0;c<4;c++) { if (!xf||!xf->text) return 6; if (c==0) tmBase[rr][0]=sign*(float)myatof(xf->text,xf->length); else if (c==1) tmBase[rr][2]=sign*(float)myatof(xf->text,xf->length); else if (c==2) tmBase[rr][1]=-sign*(float)myatof(xf->text,xf->length); xf=xf->sibling; } } tmBase.CalcFlags(); #if 0 for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",tmBase[r][0],tmBase[r][1],tmBase[r][2]); OutputDebugString(tmp); } #endif } } sub=sub->sibling; } tmpNode.parent=parent; tmpNode.mat=tm; Matrix4 par,tmat; if (parent) tmat.Concat(tmBase,parent->BaseMat); else tmat=tmBase; tmpNode.BaseMat=tmat; SceneNodes *newparent=sNodes+nsNodes; tmpNode.animat=0; tmpNode.nanimat=0; sNodes[nsNodes++]=tmpNode; int err=FindNodes(newparent,FrameLook); if (err) return err; } } sib=sib->sibling; } } return 0; } static int maxframe=-10000; static int minframe=10000; static int startframe=10000; static int endframe=-10000; static int CacheNodes[10000]; static int nCacheNodes=0; static char CacheName[100]; static int maxmatframe; static Matrix4 mats[1000]; static Vect3 scales[1000]; int ProcNKeys(TxtNode *t,int& foundkeys) { if (t->child) { TxtNode *sib=t->child; if (!sib->text) return 207; int tp=myatoi(sib->text,sib->length); sib=sib->sibling; if (!sib||!sib->text) return 208; int num=myatoi(sib->text,sib->length); sib=sib->sibling; int i; int lastframe=startframe-1; TxtNode *s=sib; for (i=0;itext) return 110; int frame=myatoi(s->text,s->length); if (frame>33000) frame=frame-65536; if (frameendframe) endframe=frame; if (frame-startframe>maxmatframe) maxmatframe=frame-startframe; s=s->sibling; if (!s||!s->text) return 212; int junk=myatoi(s->text,s->length); if (junk!=3) return 213; s=s->sibling; if (!s||!s->text) return 216; float x=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float y=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float z=(float)myatof(s->text,s->length); s=s->sibling; int k; if (tp==1) //scale { Vect3 v=Vect3(x,z,y); for (k=lastframe+1;k<=frame;k++) scales[k-startframe]=v; foundkeys|=4; } else if (tp==2) //translation { Vect3 v(x,-z,y); for (k=lastframe+1;k<=frame;k++) { mats[k-startframe].SetRow(3,v); mats[k-startframe].CalcFlags(); } foundkeys|=1; } else if (tp==3) //rotation { Matrix4 tmp; tmp.Rotate(-x*M_PI/180.0f,-y*M_PI/180.0f,-z*M_PI/180.0f); Vect3 t,tt; tmp.GetRow(2,t); t*=-1.0f; tmp.GetRow(1,tt); tmp.SetRow(2,tt); tmp.SetRow(1,t); for (k=0;k<3;k++) { float tt=-tmp[k][2]; tmp[k][2]=tmp[k][1]; tmp[k][1]=tt; } for (k=lastframe+1;k<=frame;k++) { int l; for (l=0;l<3;l++) { tmp.GetRow(l,t); mats[k-startframe].SetRow(l,t); mats[k-startframe].CalcFlags(); } } foundkeys|=2; } lastframe=frame; } } return 0; } int FindPKeys(TxtNode *t) { if (t->child) { TxtNode *sib=t->child; if (!sib) return 200; char framename[100]; { if (!sib->child) return 201; if (!sib->child->text) return 202; if (!strncmp("frm-",sib->child->text,4)) mystrncpy(framename,sib->child->text+4,sib->child->length-4); else { if (!strncmp("SCENE",sib->child->text,4)) return 0; mystrncpy(framename,sib->child->text,sib->child->length); } sib=sib->sibling; } int foundkeys=0; maxmatframe=0; while (sib) { if (sib->text&&!mystrncmp("SI_AnimationKey",sib->text,sib->length)) { if (!sib->sibling) return 103; sib=sib->sibling; int err=ProcNKeys(sib,foundkeys); if (err) return err; } sib=sib->sibling; } // if (foundkeys) { if (maxmatframe>maxframe) maxframe=maxmatframe; int i; for (i=0;inanimat) par=sNodes[i].parent->animat[j]; else par=sNodes[i].parent->BaseMat; tmat.Concat(xf,par); } else tmat=xf; sNodes[i].animat[j]=tmat; #if 0 par.Inverse(sNodes[i].BaseMat); tmat.Concat(par,sNodes[i].animat[j]); char tmp[1000]; int r; sprintf(tmp,"final frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",tmat[r][0],tmat[r][1],tmat[r][2]); OutputDebugString(tmp); } sprintf(tmp,"baseinv frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",par[r][0],par[r][1],par[r][2]); OutputDebugString(tmp); } sprintf(tmp,"bone frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",sNodes[i].animat[j][r][0],sNodes[i].animat[j][r][1],sNodes[i].animat[j][r][2]); OutputDebugString(tmp); } #endif } } } } } return 0; } int FindSets(TxtNode *t) { if (t->child) { TxtNode *sib=t->child; while (sib) { if (sib->text&&!mystrncmp("Animation",sib->text,sib->length)) { if (!sib->sibling) return 101; sib=sib->sibling; if (!sib->sibling) return 102; sib=sib->sibling; int err=FindPKeys(sib); if (err) return err; } sib=sib->sibling; } } return 0; } int FindAnims(TxtNode *t) { int i; for (i=0;ichild) { TxtNode *sib=t->child; while (sib) { if (sib->text&&!mystrncmp("AnimationSet",sib->text,sib->length)) { if (!sib->sibling) return 100; sib=sib->sibling; int err=FindSets(sib); if (err) return err; } sib=sib->sibling; } } return 0; } /* ** returns the number of frames loaded */ int XSI_LoadFile(const char *filename) { char *filebin=0; TxtNode *root; FILE *fp=fopen(filename,"ra"); if (!fp){ InfoBox(va("File not found: \"%s\"",filename)); return 0; } fseek(fp,0,SEEK_END); int len=ftell(fp); filebin=new char[len]; fseek(fp,0,SEEK_SET); if (fread(filebin,1,len,fp)!=(size_t)len) { fclose(fp); InfoBox(va("Bad XSI file\n",filename)); delete(filebin); return 0; } fclose(fp); char *at=filebin; char *end=filebin+len; root=new TxtNode; TxtNode **last=&root->child; char *retat; while (1) { TxtNode *t=ReadANode(at,end,&retat); if (!t) { at=end; break; } at=retat; *last=t; last=&t->sibling; } if (!root->child) { printf("Bad XSI file\n"); delete(filebin); delete root; return 0; } #if PDEB root->Print(0); #endif nsNodes=0; maxframe=-10000; minframe=10000; startframe=10000; endframe=-10000; CacheName[0]=0; int fn=FindNodes(0,root); if (!fn) { fn=FindAnims(root); } delete(filebin); delete root; if (fn==2000) { printf("XSI import failed, Missing Keys\n",fn); return 0; } if (fn) { printf("XSI import failed, code = %d",fn); return 0; } return maxframe+1; } int XSI_GetNumFrames() { if (maxframe+1>0) return maxframe+1; return 0; } int XSI_FindBone(char *bonename) { int j; for (j=0;j=0&&bone=0&&frame=0&&bone=0&&frame=0&&bone