LOADMESH.C

Go to the documentation of this file.
00001 // loadmesh.cpp  -- This file contains the code to load
00002 //                  the mesh models
00003 //
00004 
00005 #define MODULE_LOADER
00006 
00007 #include "render.h"
00008 
00009 extern char gszHomeDir[];
00010 
00011 extern char TempPath[];
00012 
00013 typedef double quaternion[4];
00014 
00015 static void InterpolateRobot(double mr, long n, skel *sk1, skel *sk2);
00016 static long RenderReadNurbs(long, long clen);
00017 static long *RenderReadSkeleton(long clen, short version, skel **sp, long *);
00018 static short R_ReadAxis(long, long clen);
00019 static short R_ReadFaces(long, long  clen, int version);
00020 static short R_ReadVertices(long, long clen);
00021 static short R_ReadVertText(long, long clen, BOOL);
00022 static short R_ReadFaceMapping(long ObjectID, long clen);
00023 static short R_ReadImaps(long, long clen, long frame,
00024                     char *objectfilename, char *str, BOOL new_type);
00025 static unsigned char *ReadShaderFromBuffer(long id, matl *Mat, unsigned char *b);
00026 static short R_ReadMaterial(long id, long, long clen);
00027 static void CompleteImageMapLoading(long, char *);
00028 static void LoadEmbededImageMaps(long, long clen, char *objectfilename);
00029 static short R_ReadMorphShader(long clen,
00030                     char *objectfilename, char *str);
00031 static void R_MorphVector(long, vector b, ivector Mx, double mr);
00032 static int IdentifyImageFileType(char *fn);
00033 
00034 HANDLE fp;
00035 DWORD dwRead;
00036 static char str[10]={0,0,0,0,0, 0,0,0,0,0};
00037 static long newface,newvert;
00038 static int  number_of_file_extensions=6;
00039 static char *image_file_extensions[]={".gif",".tga",".tif",".jpg",".png",".bmp"};
00040 static double ruler_length;
00041 static int IdentifyImageFileType(char *fn){
00042  int i; char last4[5];
00043  last4[4]=0;
00044  strncpy(last4,(fn+strlen(fn)-4),4);
00045  strlwr(last4);
00046  for(i=0;i<number_of_file_extensions;i++){
00047    if(strncmp((char *)last4,image_file_extensions[i],4) == 0)return i;
00048  }
00049  return -1; 
00050 }
00051 
00052 char R_getl(long *val){
00053  long l,l0,l1,l2,l3;
00054  ReadFile(fp,&l,sizeof(long),&dwRead,NULL);
00055  l0 = (l >> 24) & 0x000000ff;
00056  l1 = (l >> 16) & 0x000000ff;
00057  l2 = (l >>  8) & 0x000000ff;
00058  l3 = (l      ) & 0x000000ff;
00059  *val = (l3 << 24) | (l2 << 16) | (l1 <<  8) | l0;
00060  return(1);
00061 }
00062 
00063 char R_getsht(short * val){
00064  short s,s0,s1;
00065  ReadFile(fp,&s,sizeof(short),&dwRead,NULL);
00066  s0 = (s >>  8) & 0x00ff;
00067  s1 = (s      ) & 0x00ff;
00068  *val = (s1 <<  8) | s0;
00069  return(1);
00070 }
00071 
00072 char R_getusht(unsigned short * val){
00073  unsigned short s,s0,s1;
00074  ReadFile(fp,&s,sizeof(short),&dwRead,NULL);
00075  s0 = (s >>  8) & 0x00ff;
00076  s1 = (s      ) & 0x00ff;
00077  *val = (s1 <<  8) | s0;
00078  return(1);
00079 }
00080 
00081 static unsigned short GetUshortFromBuffer(unsigned char *b){
00082  return ((unsigned short)(*b) <<  8) | (unsigned short)(*(b+1));
00083 }
00084 
00085 static short GetShortFromBuffer(unsigned char *b){
00086  return ((short)(*b) <<  8) | (short)(*(b+1));
00087 }
00088 
00089 static long GetLongFromBuffer(unsigned char *b){
00090  return ((long)(*b) << 24) | ((long)(*(b+1)) << 16) |
00091         ((long)(*(b+2)) <<  8) | (long)(*(b+3));
00092 }
00093 
00095 
00096 static void R_MorphVector(long ObjectID, vector b, ivector Mx, double mr){
00097  long i,j;
00098  for(i=0;i<3;i++){
00099    R_getl(&j); j=j+Object[ObjectID].Centre[i]-Mx[i];
00100    b[i]=(b[i]-(double)j)*mr + (double)j;
00101  }
00102 }
00103 
00104 #define MORPH1(a,b,m) { a = (unsigned char)(((double)b -(double)a)*(m) + (double)a);}
00105 #define MORPH2(a,b,m) { a = (unsigned char)(((double)b -(double)a)*(m) + (double)a);}
00106 
00107 static unsigned char *ReadMorphShaderFromBuffer(long id, matl *Mat, unsigned char *b){
00108  char tempname[256],tempparam[512];  // must be long enough for longest !
00109  long version,active,in_use,ln,lp;
00110  version=GetLongFromBuffer(b); b+= 4;
00111  active =GetLongFromBuffer(b); b+= 4;
00112  in_use =GetLongFromBuffer(b); b+= 4;
00113  Mat->shaderID[id] = -1;  // NOT used until loaded
00114  if(in_use){
00115    ln=GetLongFromBuffer(b); b+= 4; // length of name
00116    lp=GetLongFromBuffer(b); b+= 4; // length of parameter list
00117    memcpy(tempname,b,ln+1);  b += ln+1;
00118    memcpy(tempparam,b,lp+1); b += lp+1;
00119 // // Use shader MORPH function
00120 //   if(active && LoadExte rnalTexture(tempname,tempparam) == OK){ // needs to be thought out
00121 //     Mat->shaderID[id]=Nshader-1;
00122 //   }
00123  }
00124  return b;
00125 }
00126 
00127 static short MorphMaterial(long id, long ObjectID, long clen, double mr){
00128  long i,j,v,l,n;
00129  unsigned char *buffer=NULL,*b,color[3],texco[3];
00130  matl *Mat;
00131  buffer=(unsigned char *)X__Malloc(clen);
00132  if(buffer == NULL)return -1;
00133  ReadFile(fp,buffer,clen,&dwRead,NULL);
00134  b=buffer; n=GetLongFromBuffer(b); b+= 4;  
00135  if(n > 0){
00136    //if(debug != NULL)fprintf(debug,"Reading %ld MORPH materials\n",n);
00137    n=min(n,Object[ObjectID].NoMats);
00138    for(i=0;i<n;i++){
00139      Mat=(Object[ObjectID].Tbase+(long)i);
00140      b+= 4; b+= 32; 
00141      memcpy(color,b,3); b+= 3;
00142      memcpy(texco,b,3); b+= 3;
00143      for(j=0;j<3;j++)MORPH1(Mat->color[j],color[j],1.0-mr)
00144      for(j=0;j<3;j++)MORPH1(Mat->texco[j],texco[j],1.0-mr)
00145      b += 5*3;  b+= 24; 
00146      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; MORPH2(Mat->ax.bo[j],l,mr) }
00147      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; MORPH2(Mat->ax.bu[j],l,mr) }
00148      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; MORPH2(Mat->ax.bv[j],l,mr) }
00149      VECCOPY(Mat->ax.bo,Mat->ax.boin)
00150      VECCOPY(Mat->ax.bu,Mat->ax.buin)
00151      VECCOPY(Mat->ax.bv,Mat->ax.bvin)
00152      for(j=0;j<4;j++)b=ReadMorphShaderFromBuffer(j,Mat,b);
00153      b+= 20;   b += 16*4;  b += 16*4; 
00154      if(id > 1)b += 512; // to skip over extra parameters
00155    }
00156  }
00157  X__Free(buffer);
00158  return 0;
00159 }
00160 
00161 static short MorphFaces(long ObjectID, long  clen, int version, double mo){
00162   long i,j,nf,sf;
00163   unsigned char color[3];
00164   unsigned char *buffer=NULL,*b;
00165   face   *f;
00166   if     (version == 0)nf=clen/18;
00167   else if(version == 1)nf=clen/24;
00168   else                 nf=clen/20;
00169   if(nf == 0)return -1;
00170   sf=sizeof(face);
00171   buffer=(unsigned char *)X__Malloc(clen);
00172   if(buffer == NULL)return -1;
00173   ReadFile(fp,buffer,clen,&dwRead,NULL);
00174   nf=min(nf,Object[ObjectID].NoFaces);
00175   f=Object[ObjectID].Fbase;
00176   b=buffer;
00177   //if(debug != NULL)fprintf(debug,"Morphing %ld faces\n",nf);
00178   for(i=0;i<nf;i++,f++){
00179     if(version == 0)  b+= 6; else b+= 12; 
00180     memcpy(color,b,3);b+=3;
00181     if(version == 2)  b+= 5; else b+= 9;
00182     for(j=0;j<3;j++)MORPH1(f->color[j],color[j],1.0-mo)
00183   }
00184   X__Free(buffer);
00185   return 0;
00186 }
00187 
00188 long LoadMorphObject(long ObjectID, short mo, char *FileName,double mr,
00189                      char *QmorphFile,double qr){
00190  unsigned char *buffer=NULL,*b;
00191  long CHUNKsize,FORMsize,i,j,nm;
00192  ivector Mx,Mv,Mq;
00193  vector V0,V1,VM;
00194  vertex *v;
00195  face   *f;
00196  int    same=1;
00197  Mx[0]=0; Mx[1]=0; Mx[2]=0;
00198  if((fp=GetRenderRelativeHandle((char *)strlwr(FileName),NULL,NULL))
00199    == INVALID_HANDLE_VALUE){ Render_Message(20,1,NULL);   goto X__ERROR;
00200  }
00201  ReadFile(fp,str,4,&dwRead,NULL);
00202  if(dwRead != 4 || strcmp(str,"FORM") != 0){
00203    Render_Message(21,1,NULL);   CloseHandle(fp);   goto X__ERROR;
00204  }
00205  ReadFile(fp,&FORMsize,4,&dwRead,NULL); ReadFile(fp,str,4,&dwRead,NULL);
00206  if(dwRead != 4 || (strcmp(str,"OFXM"))){
00207    Render_Message(22,1,NULL); CloseHandle(fp);   goto X__ERROR;
00208  }
00209 loop:
00210  if(!ReadFile(fp,str,4,&dwRead,NULL))goto end;
00211  if(dwRead != 4)goto end;
00212  if (R_getl(&CHUNKsize) != 1)goto end;
00213  if(strcmp(str,"AXIS") == 0){/* Axis is assumed to be first chunk */
00214    R_getl(&j); Mx[0] = j; R_getl(&j); Mx[1] = j; R_getl(&j); Mx[2] = j; 
00215    R_MorphVector(ObjectID,Object[ObjectID].Abase.bo,Mx,mr); /* Tx origin */
00216    R_MorphVector(ObjectID,Object[ObjectID].Abase.bu,Mx,mr); /* Tx X      */
00217    R_MorphVector(ObjectID,Object[ObjectID].Abase.bv,Mx,mr); /* Tx X      */
00218    VECCOPY(Object[ObjectID].Abase.bo,Object[ObjectID].Abase.boin)
00219    VECCOPY(Object[ObjectID].Abase.bu,Object[ObjectID].Abase.buin)
00220    VECCOPY(Object[ObjectID].Abase.bv,Object[ObjectID].Abase.bvin)
00221  }
00222  else if (strcmp(str,"VERT") == 0){ 
00223    nm=CHUNKsize/12;
00224    nm=min(nm,Object[ObjectID].NoVertices);
00225    v=Object[ObjectID].Vbase;
00226    for(i=0;i<nm;i++){
00227      R_getl(&j); Mv[0] = j+Object[ObjectID].Centre[0]-Mx[0];
00228      R_getl(&j); Mv[1] = j+Object[ObjectID].Centre[1]-Mx[1];
00229      R_getl(&j); Mv[2] = j+Object[ObjectID].Centre[2]-Mx[2];
00230      v[i].p[0] = (v[i].p[0]-(double)Mv[0])*mr + (double)Mv[0];
00231      v[i].p[1] = (v[i].p[1]-(double)Mv[1])*mr + (double)Mv[1];
00232      v[i].p[2] = (v[i].p[2]-(double)Mv[2])*mr + (double)Mv[2];
00233    }
00234  }
00235  else if(strcmp(str,"SFCE") == 0){if(MorphFaces(ObjectID,CHUNKsize,0,mr) < 0); goto end;}
00236  else if(strcmp(str,"LFCE") == 0){if(MorphFaces(ObjectID,CHUNKsize,1,mr) < 0); goto end;}
00237  else if(strcmp(str,"NFCE") == 0){if(MorphFaces(ObjectID,CHUNKsize,2,mr) < 0) goto end;}
00238  else if(strcmp(str,"MTL1") == 0){MorphMaterial(1,ObjectID,CHUNKsize,mr); goto end;}
00239  else if(strcmp(str,"MTL2") == 0){MorphMaterial(2,ObjectID,CHUNKsize,mr); goto end;}
00240  else if(strcmp(str,"IMAP") == 0)goto end; // Dont morph maps
00241  else if(strcmp(str,"IMA2") == 0)goto end;
00242  else if(strcmp(str,"EMAP") == 0)goto end;
00243  else R_getchunk(CHUNKsize); /* read any unused chunks */
00244  goto loop;
00245 end: CloseHandle(fp);
00246  return 1;
00247  X__ERROR:
00248  return 0;
00249 }
00250 
00251 // END of MORPHING code  ////////////////////////////////////////////
00252 
00253 static long *RenderReadSkeleton(long clen, short version, skel **sp, long *ns){
00254  short ss;
00255  long  s;
00256  skel *Skeleton;
00257  long n,i,j,k,l,l0,l1,l2,*jj,*Skid;
00258  char name[32];
00259  Skeleton=NULL;
00260  Skid=NULL;
00261  R_getl(&n); *ns=n;
00262  if((*sp=(skel *)X__Malloc(n*(long)sizeof(skel))) != NULL)Skeleton=*sp;
00263  for(i=0;i<n;i++){ /* dump the original skeleton */
00264    R_getl(&l0);  R_getl(&l1);  R_getl(&l2);  
00265    if(version > 2)R_getl(&s);
00266    else{R_getsht(&ss); s=(long)ss;}
00267    if(Skeleton != NULL){
00268      (Skeleton+i)->id=(long)s;
00269      (Skeleton+i)->p[0] = (double)(l0);
00270      (Skeleton+i)->p[1] = (double)(l1);
00271      (Skeleton+i)->p[2] = (double)(l2);
00272      VECCOPY((Skeleton+i)->p,(Skeleton+i)->pcopy)
00273    }
00274    if(version > 0){
00275      ReadFile(fp,name,sizeof(char)*16,&dwRead,NULL);
00276      if(version > 3){
00277       R_getl(&l);
00278       (Skeleton+i)->weight=(double)l/1000.0;
00279       R_getl(&l);
00280       (Skeleton+i)->wrange=(double)l/1000.0;
00281       R_getl(&l);
00282       (Skeleton+i)->wzone=(double)l/1000.0;
00283      }
00284      else { (Skeleton+i)->weight=1.0; (Skeleton+i)->wrange=1000.0; (Skeleton+i)->wzone=1.0;}
00285    }
00286    if(version > 1){
00287      for(j=0;j<3;j++){R_getl(&l);}
00288      for(j=0;j<3;j++){R_getl(&l);}
00289      for(j=0;j<3;j++){R_getl(&l);}
00290      for(j=0;j<8;j++)for(k=0;k<3;k++)R_getl(&l);
00291    }
00292  }
00293  R_getl(&n);  /* get number of vertices in skeleton structure */
00294  if(n > 0){
00295    if(n == newvert){ /* if skeleton assignment is consitent with newvert */
00296      if((Skid=(long *)X__Malloc(n*(long)sizeof(long))) != NULL)jj=Skid;
00297    }
00298    for(i=0;i<n;i++){
00299      if(version > 2)R_getl(&s);
00300      else {R_getsht(&ss); s=(long)ss;}
00301      if(Skid != NULL)*jj++ = (long)s;
00302    }
00303  }
00304  return Skid;
00305 }
00306 
00307 typedef struct tVECTOR4tag {
00308  tDOUBLE x,y,z,w;
00309  BOOL   selected;
00310  char   pad[4];
00311 } tvector4;
00312 
00313 static long RenderReadNurbs(long ObjectID, long clen){
00314  DWORD dwRead;
00315  BOOL readit=TRUE;
00316  long i,j,k,N;
00317  nurbs *n,*Np;
00318  vector4 *p;
00319  tvector4 P;
00320  tDOUBLE tD;
00321 //{ char ttt[256];
00322 //sprintf(ttt,"size of prop %ld  vec4=%ld tvec4=%ld vec=%ld BOOL=%ld tD=%ld",
00323 //sizeof(NurbsProperties),
00324 //sizeof(vector4),sizeof(tvector4),
00325 //sizeof(vector),
00326 //sizeof(BOOL),sizeof(tDOUBLE));
00327 //MessageBox(NULL,ttt,"Write",MB_OK);
00328 //}
00329  ReadFile(fp,&N,sizeof(long),&dwRead,NULL);
00330  if(N == 0)return -1;
00331  if((Np=(nurbs *)X__Malloc(N*sizeof(nurbs))) == NULL)return -1;
00332  for(k=0;k<N;k++){
00333    n=(Np+k);
00334    ReadFile(fp,&(n->properties),sizeof(NurbsProperties),&dwRead,NULL);
00335    ReadFile(fp,&(n->numU),sizeof(long),&dwRead,NULL);
00336    ReadFile(fp,&(n->numV),sizeof(long),&dwRead,NULL);
00337    ReadFile(fp,&(n->orderU),sizeof(long),&dwRead,NULL);
00338    ReadFile(fp,&(n->orderV),sizeof(long),&dwRead,NULL);
00339    AllocNurbs(n,NULL,NULL);
00340    for(i=0;i<n->numU + n->orderU; i++){
00341      ReadFile(fp,&tD,sizeof(tDOUBLE),&dwRead,NULL);
00342      n->kvU[i]=(double)tD;
00343    }
00344    for(i=0;i<n->numV + n->orderV; i++){
00345      ReadFile(fp,&tD,sizeof(tDOUBLE),&dwRead,NULL);
00346      n->kvV[i]=(double)tD;
00347    }
00348    for(i=0;i<n->numV; i++)
00349    for(j=0;j<n->numU; j++){
00350      ReadFile(fp,&P,sizeof(tvector4),&dwRead,NULL);
00351      p=&(n->points[i][j]);
00352      p->x=(double)P.x;
00353      p->y=(double)P.y;
00354      p->z=(double)P.z;
00355      p->w=(double)P.w;
00356    }
00357  }
00358  if(readit){
00359    Object[ObjectID].Nbase=Np;
00360    Object[ObjectID].NoNurbs=N;
00361  }
00362  return 0;
00363 }
00364 
00365 static void CompleteImageMapLoading(long ObjectID, char *objectfilename){
00366  // Load any outstanding image maps that haven been found as embedded maps
00367  // in the MFX file.
00368  int i,n,l,m;
00369  imap *Map;
00370  if((n=Object[ObjectID].NoMaps) > 0 &&
00371     (Map=Object[ObjectID].Mbase) != NULL){
00372    //if(debug != NULL)fprintf(debug,"\n",n);
00373    for(i=0;i<n;i++,Map++){
00374      //if(debug != NULL){fprintf(debug,"Getting Non Embedded Parts Map %ld Object[%s]\n",i,objectfilename); fflush(debug);}
00375      if(SetupImageMap(Map,objectfilename) != 1){
00376        // Map not loaded so drop the map - this action should never be done - each individual map should be switched out
00377        Render_Message(28,0,NULL);
00378        if((m=Object[ObjectID].NoFaces) > 0)for(l=0;l<m;l++){
00379          if(Object[ObjectID].Fbase[l].ffmap >= 0)/* map    */
00380           if(Object[ObjectID].Fbase[l].ffmap == i) /* this one */
00381              Object[ObjectID].Fbase[l].ffmap = -1;
00382        } /*  clear to no map */
00383      }
00384    }
00385  }
00386 }
00387 
00388 #define temp_image_name "OFX_R_$$"
00389 
00390 static void LoadEmbededImageMaps(long ObjectID, long clen, char *objectfilename){
00391  HANDLE fq;
00392  char *buffer;
00393  char name[256],tempfile[256];
00394  long i,j,n,l,m,v,in_use,f_size;
00395  int id;
00396  DWORD dwRead,dwSize,dwWrite;
00397  imap *Map;
00398  R_getl(&n); if(n != Object[ObjectID].NoMaps){
00399    MessageBox(NULL,"Map reading error",NULL,MB_OK);
00400    R_getchunk(clen-4);
00401    return;
00402  }
00403  //if(debug != NULL)fprintf(debug,"\nLoading %ld embedded maps\n",n);
00404  if((n=Object[ObjectID].NoMaps) > 0 &&
00405     (Map=Object[ObjectID].Mbase) != NULL){
00406    for(i=0;i<n;i++,Map++){
00407    for(j=0;j<4;j++){ // four types of map
00408      R_getl(&v);     // version
00409      R_getl(&in_use);
00410      //if(debug != NULL)fprintf(debug,"Map %ld (of %ld) Image %ld  in-use=%ld\n",i+1,n,j,in_use);
00411      if(!in_use)continue;
00412      R_getl(&l);  // string name length
00413      R_getl(&f_size);  // file size
00414      ReadFile(fp,name,l+1,&dwRead,NULL);
00415      //if(debug != NULL)fprintf(debug,"Embed map %ld, (part %ld)  name [%s] length=%ld size= %ld\n",i,j,name,l,f_size);
00416      if((buffer=(unsigned char*)X__Malloc(f_size)) == NULL){
00417        R_getchunk(f_size);
00418        continue;
00419      }
00420      ReadFile(fp,buffer,f_size,&dwRead,NULL);
00421      id=IdentifyImageFileType(name);
00422      if(id < 0){
00423        MessageBox(NULL,"Bad Type",NULL,MB_OK);
00424      }
00425      if(!CheckSingleRenderImageMap(Map,name,objectfilename,tempfile,j)){
00426        if(id < 0){
00427 // USE this for loading directly from the buffer // still TODO
00428 //         LoadSingleRenderImageMapFromFile(buffer,Map,"ZZZZ",image_file_extensions[id]);
00429          goto FREEPOINT;
00430        }
00431        sprintf(tempfile,"%s%s%s",TempPath,temp_image_name,image_file_extensions[id]);
00432        // MessageBox(NULL,tempfile,"TempFile",MB_OK);
00433        //if(debug != NULL)fprintf(debug,"Temp file [%s]\n",tempfile);
00434        fq=CreateFile(tempfile,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,
00435                     FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
00436        if(fq == INVALID_HANDLE_VALUE){
00437          MessageBox(NULL,tempfile,"Bad Handle",MB_OK);
00438        }
00439        else{
00440          dwSize=f_size;
00441          if(WriteFile(fq,buffer,dwSize,&dwWrite,NULL) != 0 && dwWrite == dwSize){
00442            CloseHandle(fq);
00443            LoadSingleRenderImageMap(Map,name,objectfilename,tempfile,j);
00444            remove(tempfile);
00445          }
00446          else CloseHandle(fq);
00447        }
00448      }
00449      FREEPOINT: X__Free(buffer); 
00450    }
00451    }
00452  }
00453 }
00454 
00455 static short R_ReadImaps(long ObjectID, long clen, long frame, char *objectfilename,
00456                         char *str, BOOL new_type){
00457   unsigned char *buffer=NULL,*b;
00458   imap *temp_map,*Map;
00459   unsigned char t_colour[3];
00460   char brushmaptype,moziac,p,r,q,t;
00461   char fsurf[256],frefl[256],fbump[256],ftran[256],tempstr[256];
00462   long i,j,k,l,m,brushangle;
00463   long m_p,ff_p,fd_p,lf_p,
00464        m_r,ff_r,fd_r,lf_r,
00465        m_b,ff_b,fd_b,lf_b,
00466        m_t,ff_t,fd_t,lf_t;
00467   short s;
00468   buffer=(unsigned char *)X__Malloc(clen);
00469   if(buffer == NULL)return -1;
00470   ReadFile(fp,buffer,clen,&dwRead,NULL);
00471   b=buffer;
00472   j=GetLongFromBuffer(b); b+= 4;  /* read number of maps */
00473   if(j > 0){
00474     temp_map = (imap *)X__Malloc(j*sizeof(imap));
00475     if(temp_map == NULL){
00476       Render_Message(13,0,NULL);
00477       X__Free(buffer);
00478       return -1;
00479     }
00480     memset(temp_map,0,j*sizeof(imap));
00481     Object[ObjectID].Mbase=temp_map;
00482     Object[ObjectID].NoMaps=j;
00483     for(i=0;i<j;i++){
00484       Map=(temp_map+(long)i);
00485       Map->bLoadedS=FALSE; Map->bLoadedR=FALSE;
00486       Map->bLoadedB=FALSE; Map->bLoadedT=FALSE;
00487       Map->bAnimS=Map->bAnimR=Map->bAnimB=Map->bAnimT=FALSE;
00488       Map->map     = PLANE;
00489       Map->angle   = 1.0;
00490       Map->moziac  = NO;
00491       Map->p24R     = Map->p24G     = Map->p24B     = NULL;
00492       Map->p24Rrefl = Map->p24Grefl = Map->p24Brefl = NULL;
00493       Map->p24Rbump = Map->p24Gbump = Map->p24Bbump = NULL;
00494       Map->p24Rtran = Map->p24Gtran = Map->p24Btran = NULL;
00495       Map->p[0]=(double)GetLongFromBuffer(b); b+= 4;
00496       Map->p[1]=(double)GetLongFromBuffer(b); b+= 4;
00497       Map->p[2]=(double)GetLongFromBuffer(b); b+= 4;
00498       VECCOPY(Map->p,Map->pin)
00499       Map->x[0]=(double)GetLongFromBuffer(b); b+= 4;
00500       Map->x[1]=(double)GetLongFromBuffer(b); b+= 4;
00501       Map->x[2]=(double)GetLongFromBuffer(b); b+= 4;
00502       VECCOPY(Map->x,Map->xin)
00503       Map->y[0]=(double)GetLongFromBuffer(b); b+= 4;
00504       Map->y[1]=(double)GetLongFromBuffer(b); b+= 4;
00505       Map->y[2]=(double)GetLongFromBuffer(b); b+= 4;
00506       VECCOPY(Map->y,Map->yin)
00507       m_p =GetLongFromBuffer(b); b+= 4; b+= 12; // skip anim flags no longer used
00508       m_r =GetLongFromBuffer(b); b+= 4; b+= 12;
00509       m_b =GetLongFromBuffer(b); b+= 4; b+= 12;
00510       m_t =GetLongFromBuffer(b); b+= 4; b+= 12;
00511       l=GetLongFromBuffer(b); b+= 4; /* used by skeleton for br. assign. not used by renderer */
00512       l=GetLongFromBuffer(b); b+= 4; brushmaptype=(char)l;
00513       brushangle=GetLongFromBuffer(b); b+= 4;
00514       for(k=0;k<4;k++){
00515         m=GetLongFromBuffer(b); b+= 4; /* dump the brush lock info */
00516       }
00517       memcpy(tempstr,b,32); b+= 32;
00518       p = *b++;  // =1 => surface map present
00519       r = *b++;
00520       q = *b++;
00521       t = *b++;  // =1 => transparent map present     
00522       Map->kt = *b++;
00523       Map->pp=GetShortFromBuffer(b); b+= 2; /* these will be set to -1 */
00524       Map->rp=GetShortFromBuffer(b); b+= 2; /* if a map of this type   */
00525       Map->bp=GetShortFromBuffer(b); b+= 2; /* is not used in Material */
00526       b+=2;                                 /* no transparency slider  */
00527       if(t > 0)Map->tp=255; else Map->tp=0; // if there is a tansparency map we set fraction to max
00528       memcpy(t_colour,b,3); b+=3;  /* not used yet */
00529       memcpy(t_colour,b,3); b+=3;
00530       memcpy(t_colour,b,3); b+=3;  /* ------------ */
00531       memcpy(Map->kc,b,3); b+=3;   /* key colour   */
00532       memset(fsurf,0,256);   memcpy(fsurf,b,250); b+=256; 
00533       if((m=strlen(fsurf)) == 0 || m > 248)p=0; // dump the map - might be corrupt
00534       memset(frefl,0,256);   memcpy(frefl,b,250); b+=256;
00535       if((m=strlen(frefl)) == 0 || m > 248)r=0; // dump the map - might be corrupt
00536       memset(fbump,0,256);   memcpy(fbump,b,250); b+=256;
00537       if((m=strlen(fbump)) == 0 || m > 248)q=0; // dump the map - might be corrupt
00538       memset(ftran,0,256);   memcpy(ftran,b,250); b+=256;
00539       if((m=strlen(ftran)) == 0 || m > 248)t=0; // dump the map - might be corrupt
00540       if(new_type){
00541         b+= 4;  // version
00542         Map->bDecal=(BOOL)GetLongFromBuffer(b); b+= 4;
00543         Map->bShaded=(BOOL)GetLongFromBuffer(b); b+= 4;
00544         Map->bTiled=(BOOL)GetLongFromBuffer(b); b+= 4;
00545       }
00546       else{ // check to see if any face uses this and reqires NO tiling ??
00547         Map->bShaded=TRUE; 
00548         Map->bTiled=TRUE;   
00549         Map->bDecal=FALSE;
00550       }
00551       moziac=NO;
00552       if(brushmaptype == PLANE_MOZIAC)   { brushmaptype = PLANE;    moziac=YES;}
00553       if(brushmaptype == CYLINDER_MOZIAC){ brushmaptype = CYLINDER; moziac=YES;}
00554       if(p && m_p == ANIMBRUSH)Map->bAnimS=TRUE;
00555       if(r && m_r == ANIMBRUSH)Map->bAnimR=TRUE;
00556       if(q && m_b == ANIMBRUSH)Map->bAnimB=TRUE;
00557       if(t && m_t == ANIMBRUSH)Map->bAnimT=TRUE;
00558       if(p) strcpy(Map->filename,fsurf); else Map->pp = -1;
00559       if(r) strcpy(Map->frefl,frefl);    else Map->rp = -1;
00560       if(q) strcpy(Map->fbump,fbump);    else Map->bp = -1;
00561       if(t) strcpy(Map->ftran,ftran);    else Map->tp = -1;
00562       //if(debug != NULL)fprintf(debug,"Map Name [%s] present %ld, \n",Map->filename, Map->pp);
00563       //if(debug != NULL)fprintf(debug,"Map Name [%s] present %ld, \n",Map->frefl, Map->rp);
00564       //if(debug != NULL)fprintf(debug,"Map Name [%s] present %ld, \n",Map->fbump, Map->bp);
00565       //if(debug != NULL)fprintf(debug,"Map Name [%s] present %ld, \n",Map->ftran, Map->tp);
00566       Map->map=(short)brushmaptype;
00567       Map->angle=360.0/(double)brushangle;
00568       Map->moziac=moziac;
00569     }
00570   }
00571   X__Free(buffer);
00572   return 0;
00573 }
00574 
00575 static unsigned char *ReadShaderFromBuffer(long id, matl *Mat, unsigned char *b){
00576  char tempname[256],tempparam[512];  // must be long enough for longest !
00577  long version,active,in_use,ln,lp;
00578  version=GetLongFromBuffer(b); b+= 4;
00579  active =GetLongFromBuffer(b); b+= 4;
00580  in_use =GetLongFromBuffer(b); b+= 4;
00581  //if(debug != NULL)fprintf(debug,"Loading shader %ld active=%ld in_use=%ld\n",id,active,in_use);
00582  Mat->shaderID[id] = -1;  // NOT used until loaded
00583  if(in_use){
00584    ln=GetLongFromBuffer(b); b+= 4; // length of name
00585    lp=GetLongFromBuffer(b); b+= 4; // length of parameter list
00586    memcpy(tempname,b,ln+1);  b += ln+1;
00587    memcpy(tempparam,b,lp+1); b += lp+1;
00588    if(active && LoadExternalTexture(tempname,tempparam) == OK){
00589      Mat->shaderID[id]=Nshader-1;
00590      //if(debug != NULL)fprintf(debug,"Shader %ld loaded from [%s] is active\n"
00591      //     ,Nshader-1,tempname); 
00592    }
00593    //else if(debug != NULL)fprintf(debug,"Shader (active=%ld) not loaded\n",active);
00594  }
00595  return b;
00596 }
00597 
00598 static short R_ReadMaterial(long id, long ObjectID, long clen){
00599  long i,j,v,l,n;
00600  unsigned char *buffer=NULL,*b;
00601  matl *temp_mat,*Mat;
00602  buffer=(unsigned char *)X__Malloc(clen);
00603  if(buffer == NULL)return -1;
00604  ReadFile(fp,buffer,clen,&dwRead,NULL);
00605  b=buffer;
00606  n=GetLongFromBuffer(b); b+= 4;  /* read number of materials */
00607  //{char ttt[255]; sprintf(ttt,"Loading %ld materials",n); MessageBox(NULL,ttt,NULL,MB_OK);}
00608  if(n > 0){
00609    //if(debug != NULL)fprintf(debug,"Reading %ld materials\n",n);
00610    temp_mat = (matl *)X__Malloc(n*sizeof(matl));
00611    if(temp_mat == NULL){
00612      Render_Message(13,0,NULL);
00613      X__Free(buffer);
00614      return -1;
00615    }
00616    Object[ObjectID].Tbase=temp_mat;
00617    Object[ObjectID].NoMats=n;
00618    for(i=0;i<n;i++){
00619      Mat=(temp_mat+(long)i);
00620      v=GetLongFromBuffer(b); b+= 4; // version
00621      //if(debug!=NULL)fprintf(debug,"Material %ld [%s]\n",i,b); 
00622      b+=32; //skip name
00623      memcpy(Mat->color,b,3); b+= 3;
00624      memcpy(Mat->texco,b,3); b+= 3;
00625      b += 5*3;  // 5 colours to be used later
00626      l=GetLongFromBuffer(b); b+= 4;  Mat->gloss=min(15,l/255);
00627      l=GetLongFromBuffer(b); b+= 4;  Mat->refl=l;
00628      l=GetLongFromBuffer(b); b+= 4;  Mat->transp=l;
00629      l=GetLongFromBuffer(b); b+= 4;  if(l < 100)l=1000; Mat->refractive_index=l;   //1000 = 1.0
00630      l=GetLongFromBuffer(b); b+= 4;  Mat->bInternalShader=(BOOL)l;
00631      l=GetLongFromBuffer(b); b+= 4;  Mat->internalShaderID=l;
00632      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; Mat->ax.bo[j]=(double)l;}
00633      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; Mat->ax.bu[j]=(double)l;}
00634      for(j=0;j<3;j++){l=GetLongFromBuffer(b); b+= 4; Mat->ax.bv[j]=(double)l;}
00635      VECCOPY(Mat->ax.bo,Mat->ax.boin)
00636      VECCOPY(Mat->ax.bu,Mat->ax.buin)
00637      VECCOPY(Mat->ax.bv,Mat->ax.bvin)
00638      for(j=0;j<4;j++)b=ReadShaderFromBuffer(j,Mat,b);
00639      l=GetLongFromBuffer(b); b+= 4;  Mat->bSmooth=(BOOL)l;
00640      l=GetLongFromBuffer(b); b+= 4;  Mat->bShiny=(BOOL)l;
00641      l=GetLongFromBuffer(b); b+= 4;  Mat->bClear=(BOOL)l;
00642      l=GetLongFromBuffer(b); b+= 4;  Mat->bGlassEdge=(BOOL)l;
00643      l=GetLongFromBuffer(b); b+= 4;  Mat->bUseSurfaceMapping=(BOOL)l;
00644      for(j=0;j<16;j++){l=GetLongFromBuffer(b); b+= 4; Mat->params[j]=(unsigned char)l;}
00645      b += 16*4; // ignore the 16 pab lings
00646      //if(debug != NULL)fprintf(debug,"smooth=%ld shiny=%ld internal(%ld)ID=%ld\n",
00647      //   Mat->bSmooth,Mat->bShiny,Mat->bInternalShader,Mat->internalShaderID);
00648      //if(debug != NULL)fprintf(debug,"reflectivity=%ld transparency=%ld gloss=%ld\n",
00649      //   Mat->refl,Mat->transp,Mat->gloss);
00650      if(id > 1){ // for material versions > 1
00651        memcpy(Mat->other_properties,b,512); b+= 512;
00652        sscanf(Mat->other_properties,"%lf %lf %lf %lf %lf %lf",
00653        &(Mat->mmw_params[0]),&(Mat->mmw_params[1]),&(Mat->mmw_params[2]),
00654        &(Mat->mmw_params[3]),&(Mat->mmw_params[4]),&(Mat->mmw_params[5]));
00655      }
00656    }
00657  }
00658  X__Free(buffer);
00659  return 0;
00660 }
00661 
00662 static short R_ReadFaces(long ObjectID, long  clen, int version){
00663   long i,sf;
00664   long mm;
00665   unsigned char texture,brush,pad,attrib;
00666   unsigned char *buffer=NULL,*b;
00667   face   *f;
00668   if     (version == 0)newface=clen/18;
00669   else if(version == 1)newface=clen/24;
00670   else                 newface=clen/20;
00671   if(newface == 0)return -1;
00672   sf=sizeof(face);
00673   mm=newface*(long)sf;
00674   Object[ObjectID].Fbase=(face  *)X__Malloc(mm);
00675   Object[ObjectID].NoFaces=newface;
00676   f=Object[ObjectID].Fbase;
00677   if(f == NULL){Render_Message(9,0,NULL); return -1;}
00678   buffer=(unsigned char *)X__Malloc(clen);
00679   if(buffer == NULL)return -1;
00680   ReadFile(fp,buffer,clen,&dwRead,NULL);
00681   b=buffer;
00682   for(i=0;i<newface;i++){
00683     if(version == 0){
00684       f->V[0]=(UNSIGNED)GetUshortFromBuffer(b); b+= 2;
00685       f->V[1]=(UNSIGNED)GetUshortFromBuffer(b); b+= 2;
00686       f->V[2]=(UNSIGNED)GetUshortFromBuffer(b); b+= 2;
00687     }
00688     else{
00689       f->V[0]=(UNSIGNED)GetLongFromBuffer(b); b+= 4;
00690       f->V[1]=(UNSIGNED)GetLongFromBuffer(b); b+= 4;
00691       f->V[2]=(UNSIGNED)GetLongFromBuffer(b); b+= 4;
00692     }
00693     memcpy(f->color,b,3); b+=3;
00694     if(version == 2){
00695       f->bShiny = FALSE;
00696       f->bSmooth= *b++;
00697       f->ffmat   = GetShortFromBuffer(b); b+= 2;
00698       f->ffmap   = GetShortFromBuffer(b); b+= 2;
00699     }
00700     else{ // old face map attributes now done through material
00701       *b++;   *b++;  *b++; // spec trans refl
00702       attrib = *b++;       // attrib
00703       *b++;                // param 
00704       f->ffmap   = (short)(*b++);
00705       f->ffmat   = -1;  // No material for old faces
00706       if(attrib & 0x80)f->bSmooth=TRUE; else f->bSmooth=FALSE;
00707       if(attrib & 0x20)f->bShiny=TRUE; else f->bShiny=FALSE;
00708       if(!(attrib & 0x40))f->ffmap = -1;  // NO image map
00709       *b++;   *b++;   *b++; // shader - axis - pad (ignored)
00710     }
00711     f->bFmc=FALSE;
00712     f->pn[0][0]=0.0; f->pn[0][1]=0.0; f->pn[0][2]=0.0;
00713     f->pn[1][0]=0.0; f->pn[1][1]=0.0; f->pn[1][2]=0.0;
00714     f->pn[2][0]=0.0; f->pn[2][1]=0.0; f->pn[2][2]=0.0;
00715     f->n[0]=0.0; f->n[1]=0.0; f->n[2]=0.0;
00716     f->c=0.0;
00717     f++;
00718   }
00719   X__Free(buffer);
00720   return 0;
00721 }
00722 
00723 static short R_ReadVertices(long ObjectID, long clen){
00724   vertex   *v;
00725   long i,mm,sv;
00726   unsigned char *buffer=NULL,*b;
00727   newvert=clen/12;
00728   if(newvert == 0)return -1;
00729   sv=sizeof(vertex);
00730   mm=newvert*(long)sv;
00731   if(newvert > 65535L && sizeof(UNSIGNED) < 4){
00732     Render_Message(16,0,NULL);
00733     return -1;
00734   }
00735   Object[ObjectID].Vbase=(vertex *)X__Malloc(mm);
00736   Object[ObjectID].NoVertices=newvert;
00737   v=Object[ObjectID].Vbase;
00738   if(v == NULL){
00739     Render_Message(9,0,NULL);
00740     return -1;
00741   }
00742   buffer=(unsigned char *)X__Malloc(clen);
00743   if(buffer == NULL)return -1;
00744   ReadFile(fp,buffer,clen,&dwRead,NULL);
00745   b=buffer;
00746   for(i=0;i<newvert;i++){
00747     v->p[0]=(double)GetLongFromBuffer(b); b+= 4;
00748     v->p[1]=(double)GetLongFromBuffer(b); b+= 4;
00749     v->p[2]=(double)GetLongFromBuffer(b); b+= 4;
00750     v->x=0; v->y=0; // mapping coords
00751     v->u=0; v->v=0; // mapping coords
00752     v++;
00753   }
00754   X__Free(buffer);
00755   return 0;
00756 }
00757 
00758 static short R_ReadVertText(long ObjectID, long clen, BOOL vtx2){
00759   vertex *v;
00760   long i,n,xx,id;
00761   unsigned char *buffer=NULL,*b;
00762   n=clen/12;
00763   i=Object[ObjectID].NoVertices;
00764   if(n == 0)return 0;
00765   if(n > i)return -1;
00766   buffer=(unsigned char *)X__Malloc(clen);
00767   if(buffer == NULL)return -1;
00768   ReadFile(fp,buffer,clen,&dwRead,NULL);
00769   b=buffer;
00770   v=Object[ObjectID].Vbase;
00771   for(i=0;i<n;i++){
00772     id=GetLongFromBuffer(b); b+= 4;
00773     if(vtx2)id=i;
00774     xx=GetLongFromBuffer(b); b+= 4; v[id].u=(double)xx*0.000001;
00775     xx=GetLongFromBuffer(b); b+= 4; v[id].v=(1.0 - (double)xx*0.000001); // to match ordinary map
00776   }
00777   X__Free(buffer);
00778   return 0;
00779 }
00780 
00781 static short R_ReadFaceMapping(long ObjectID, long clen){
00782   long i,j,nn,ix,iy;
00783   face *f;
00784   unsigned char *buffer=NULL,*b;
00785   nn=clen/28;
00786   i=Object[ObjectID].NoFaces;
00787   if(nn > i)return -1;
00788   if(nn == 0)return 0;
00789   buffer=(unsigned char *)X__Malloc(clen);
00790   if(buffer == NULL)return -1;
00791   ReadFile(fp,buffer,clen,&dwRead,NULL);
00792   b=buffer;
00793   f=Object[ObjectID].Fbase;
00794   for(i=0;i<nn;i++){
00795     f->bFmc=(BOOL)GetLongFromBuffer(b); b+= 4;
00796     for(j=0;j<3;j++){
00797       ix=GetLongFromBuffer(b); b+= 4;
00798       iy=GetLongFromBuffer(b); b+= 4;
00799       f->uu[j]=(double)ix*0.000001;
00800       f->vv[j]=(1.0 - (double)iy*0.000001); // to match OFX mapping scheme
00801       f->ww[j]=0.5;
00802       //if(debug != NULL)fprintf(debug,"Face %ld Mapped=%ld V %ld x=%lf y=%lf\n",i,f->bFmc,j,f->uu[j],f->vv[j]);
00803     }
00804     f++;
00805   }
00806   X__Free(buffer);
00807   return 0;
00808 }
00809 
00810 
00811 long FindNumberVertices(char *ofile, long *nvs){
00812  long CHUNKsize,FORMsize;
00813  char FileName[256];
00814  strcpy(FileName,ofile);
00815  *nvs = -1;
00816  if((fp=GetRenderRelativeHandle((char *)strlwr(FileName),NULL,NULL))
00817        == INVALID_HANDLE_VALUE){
00818    return 0;
00819  }
00820  ReadFile(fp,str,4,&dwRead,NULL);
00821  if (dwRead != 4 || strcmp(str,"FORM") != 0)goto end;
00822  ReadFile(fp,&FORMsize,4,&dwRead,NULL);
00823  ReadFile(fp,str,4,&dwRead,NULL);
00824  if (dwRead != 4 || (strcmp(str,"OFXM") != 0 && strcmp(str,"AAPO") != 0))goto end;
00825 loop:
00826  if(!ReadFile(fp,str,4,&dwRead,NULL))goto end;
00827  if(dwRead != 4 )goto end;
00828  if(R_getl(&CHUNKsize) != 1)goto end;
00829  if(strcmp(str,"VERT") == 0){
00830    *nvs=CHUNKsize/12;
00831    goto end;
00832  }
00833  else R_getchunk(CHUNKsize);
00834  goto loop;
00835 end:
00836  CloseHandle(fp);
00837  return 1;
00838 }
00839 
00840 long R_LoadObject(long ObjectID, char *FileName, long frame, short robo, 
00841                   double robo_ratio,
00842                    char *robo_file1, char *robo_file2){
00843  long CHUNKsize,FORMsize,l;
00844  long nsk,*Skids=NULL;
00845  skel *Skeleton=NULL;
00846  // All object values set to ZERO or NULL before reading 
00847  if((fp=GetRenderRelativeHandle((char *)strlwr(FileName),NULL,NULL))
00848        == INVALID_HANDLE_VALUE){
00849    Render_Message(30,1,FileName);
00850    return 0;
00851  }
00852  newface=0; newvert=0; nsk=0;
00853  ReadFile(fp,str,4,&dwRead,NULL);
00854  //if(debug != NULL)fprintf(debug,"Reading Model from[%s]\n",FileName);
00855  if(strcmp(str,"FORM") != 0){
00856    Render_Message(21,1,NULL);
00857    return 0;
00858  }
00859  ReadFile(fp,&FORMsize,sizeof(long),&dwRead,NULL);
00860  ReadFile(fp,str,4,&dwRead,NULL);
00861  //MessageBox(NULL,str,"ReadingChunk",MB_OK);
00862  // allow old models
00863  if(dwRead != 4 || (strcmp(str,"OFXM") != 0  && strcmp(str,"AAPO") != 0)){
00864    Render_Message(22,1,NULL);
00865    return 0;
00866  }
00867  Object[ObjectID].Centre[0]=0;   /* initialize in case no axis */
00868  Object[ObjectID].Centre[1]=0;   /* present */
00869  Object[ObjectID].Centre[2]=0;
00870 
00871  Object[ObjectID].Abase.bo[0]=0;
00872  Object[ObjectID].Abase.bo[1]=0;
00873  Object[ObjectID].Abase.bo[2]=0;
00874  Object[ObjectID].Abase.bu[0]=UNIT;
00875  Object[ObjectID].Abase.bu[1]=0;
00876  Object[ObjectID].Abase.bu[2]=0;
00877  Object[ObjectID].Abase.bv[0]=0;
00878  Object[ObjectID].Abase.bv[1]=UNIT;
00879  Object[ObjectID].Abase.bv[2]=0;
00880 loop:
00881  if(!ReadFile(fp,str,4,&dwRead,NULL))goto end;
00882  //MessageBox(NULL,str,"Reading Chunk",MB_OK);
00883  if(dwRead != 4)goto end;
00884  if (R_getl(&CHUNKsize) != 1)goto end;
00885  if     (strcmp(str,"VERT") == 0){if(R_ReadVertices(ObjectID,CHUNKsize)       < 0)return -1;}
00886  else if(strcmp(str,"VTEX") == 0){if(R_ReadVertText(ObjectID,CHUNKsize,FALSE) < 0)return -1;}
00887  else if(strcmp(str,"VTX2") == 0){if(R_ReadVertText(ObjectID,CHUNKsize,TRUE)  < 0)return -1;}
00888  else if(strcmp(str,"SFCE") == 0){if(R_ReadFaces(ObjectID,CHUNKsize,0)        < 0)return -1;}
00889  else if(strcmp(str,"LFCE") == 0){if(R_ReadFaces(ObjectID,CHUNKsize,1)        < 0)return -1;}
00890  else if(strcmp(str,"NFCE") == 0){if(R_ReadFaces(ObjectID,CHUNKsize,2)        < 0)return -1;}
00891  else if(strcmp(str,"FTEX") == 0){if(R_ReadFaceMapping(ObjectID,CHUNKsize)    < 0)return -1;}
00892  else if(strcmp(str,"AXIS") == 0){if(R_ReadAxis(ObjectID,CHUNKsize)           < 0)return -1;}
00893  else if(strcmp(str,"IMAP") == 0)R_ReadImaps(ObjectID,CHUNKsize,frame,FileName,str,FALSE);
00894  else if(strcmp(str,"IMA2") == 0)R_ReadImaps(ObjectID,CHUNKsize,frame,FileName,str,TRUE);
00895  else if(strcmp(str,"EMAP") == 0)LoadEmbededImageMaps(ObjectID,CHUNKsize,FileName);
00896  else if(strcmp(str,"MTL1") == 0)R_ReadMaterial(1,ObjectID,CHUNKsize);
00897  else if(strcmp(str,"MTL2") == 0)R_ReadMaterial(2,ObjectID,CHUNKsize);
00898  else if(strcmp(str,"SK04") == 0 && robo == YES)Skids=RenderReadSkeleton(CHUNKsize,4,&Skeleton,&nsk);
00899  else if(strcmp(str,"SK03") == 0 && robo == YES)Skids=RenderReadSkeleton(CHUNKsize,3,&Skeleton,&nsk);
00900  else if(strcmp(str,"SK02") == 0 && robo == YES)Skids=RenderReadSkeleton(CHUNKsize,2,&Skeleton,&nsk);
00901  else if(strcmp(str,"SK01") == 0 && robo == YES)Skids=RenderReadSkeleton(CHUNKsize,1,&Skeleton,&nsk);
00902  else if(strcmp(str,"SKEL") == 0 && robo == YES)Skids=RenderReadSkeleton(CHUNKsize,0,&Skeleton,&nsk);
00903  else if(strcmp(str,"NURB") == 0){
00904    if(RenderReadNurbs(ObjectID,CHUNKsize) < 0)return -1;
00905    MeshNurbsSurfaces(ObjectID);
00906  }
00907  else if(strcmp(str,"UNIT") == 0){
00908    long dummy;
00909    char dummys[16];
00910    R_getl(&dummy); ruler_length=(double)dummy;
00911    ReadFile(fp,dummys,8,&dwRead,NULL);
00912    R_getl(&dummy);   R_getl(&dummy);   R_getl(&dummy);
00913    R_getl(&dummy);   R_getl(&dummy);   R_getl(&dummy); /* don't use : is relative ruler */
00914  }
00916  else R_getchunk(CHUNKsize);
00917  goto loop;
00918 end:
00919  CloseHandle(fp);
00920  CompleteImageMapLoading(ObjectID,FileName);
00921  Object[ObjectID].Skeleton=Skeleton;
00922  Object[ObjectID].Skids=Skids;
00923  Object[ObjectID].NoSkeleton=nsk;
00924  return 1;
00925 }
00926 
00927 void  R_getchunk(long clen){
00928  SetFilePointer(fp,clen,NULL,FILE_CURRENT);
00929 }
00930 
00931 static short R_ReadAxis(long ObjectID, long clen){
00932  long j;
00933  R_getl(&j); Object[ObjectID].Centre[0]=j; /* origin of Object (in object coords */
00934  R_getl(&j); Object[ObjectID].Centre[1]=j;
00935  R_getl(&j); Object[ObjectID].Centre[2]=j;
00936  R_getl(&j); Object[ObjectID].Abase.bo[0]=j;  /* shader axis point */
00937  R_getl(&j); Object[ObjectID].Abase.bo[1]=j;
00938  R_getl(&j); Object[ObjectID].Abase.bo[2]=j;
00939  R_getl(&j); Object[ObjectID].Abase.bu[0]=j;  /* texture axis off x */
00940  R_getl(&j); Object[ObjectID].Abase.bu[1]=j;
00941  R_getl(&j); Object[ObjectID].Abase.bu[2]=j;
00942  R_getl(&j); Object[ObjectID].Abase.bv[0]=j;  /* texture axis off y */
00943  R_getl(&j); Object[ObjectID].Abase.bv[1]=j;
00944  R_getl(&j); Object[ObjectID].Abase.bv[2]=j;
00945  VECCOPY(Object[ObjectID].Abase.bo,Object[ObjectID].Abase.boin)
00946  VECCOPY(Object[ObjectID].Abase.bu,Object[ObjectID].Abase.buin)
00947  VECCOPY(Object[ObjectID].Abase.bv,Object[ObjectID].Abase.bvin)
00948  return 0;
00949 }
00950 
00952 
00953 #define EPSILON 1.0e-6
00954 
00955 void InvertRotationMatrix(double T[4][4], double t[4][4]){
00956  int i,j;
00957  double a[3][3];
00958  double det;
00959  R_null_transform(t);
00960  for(i=0;i<3;i++)for(j=0;j<3;j++)a[i][j]=T[i][j];
00961  det=a[0][0]*(a[1][1]*a[2][2] - a[2][1]*a[1][2])
00962     -a[0][1]*(a[1][0]*a[2][2] - a[2][0]*a[1][2])
00963     +a[0][2]*(a[1][0]*a[2][1] - a[2][0]*a[1][1]);
00964  if(fabs(det) < 1.e-10)return;
00965  det = 1.0/det;
00966  t[0][0] = +(a[1][1]*a[2][2] - a[2][1]*a[1][2])*det;
00967  t[1][0] = -(a[1][0]*a[2][2] - a[2][0]*a[1][2])*det;
00968  t[2][0] = +(a[1][0]*a[2][1] - a[2][0]*a[1][1])*det;
00969  t[0][1] = -(a[0][1]*a[2][2] - a[2][1]*a[0][2])*det;
00970  t[1][1] = +(a[0][0]*a[2][2] - a[2][0]*a[0][2])*det;
00971  t[2][1] = -(a[0][0]*a[2][1] - a[2][0]*a[0][1])*det;
00972  t[0][2] = +(a[0][1]*a[1][2] - a[1][1]*a[0][2])*det;
00973  t[1][2] = -(a[0][0]*a[1][2] - a[1][0]*a[0][2])*det;
00974  t[2][2] = +(a[0][0]*a[1][1] - a[1][0]*a[0][1])*det;
00975 }
00976 
00977 #ifdef _SUNSTYLE
00978 #else
00979 static void MatrixToQuaternion(double m[4][4], quaternion q){
00980 #endif
00981  double w4,x2;
00982  q[0]=0.25*(1.0+m[0][0]+m[1][1]+m[2][2]);
00983  if(q[0] > EPSILON){
00984    q[0]=sqrt(q[0]);
00985    w4=1.0/(4.0*q[0]);
00986    q[1]=(m[1][2]-m[2][1])*w4;
00987    q[2]=(m[2][0]-m[0][2])*w4;
00988    q[3]=(m[0][1]-m[1][0])*w4;
00989  }
00990  else{
00991    q[0]=0.0;
00992    q[1]= -0.5*(m[1][1]+m[2][2]);
00993    if(q[1] > EPSILON){
00994      q[1]=sqrt(q[1]);
00995      x2=1.0/(2.0*q[1]);
00996      q[2]=m[0][1]*x2;
00997      q[3]=m[0][2]*x2;
00998    }
00999    else{
01000      q[1]=0.0;
01001      q[2]=0.5*(1.0-m[2][2]);
01002      if(q[2] > EPSILON){
01003        q[2]=sqrt(q[2]);
01004        q[3]=m[1][2]/(2.0*q[2]);
01005      }
01006      else{
01007        q[2]=0.0;
01008        q[3]=1.0;
01009      }
01010    }
01011  }
01012  return;
01013 }
01014 
01015 static void QuaternionToMatrix(quaternion q, double m[4][4]){
01016  double w,x,y,z,x2,y2,z2;
01017  w=q[0]; x=q[1]; y=q[2]; z=q[3]; x2=x*x; y2=y*y; z2=z*z;
01018  m[0][0]=1.0-2*y2-2*z2; m[0][1]=2*x*y+2*w*z;   m[0][2]=2*x*z-2*w*y;
01019  m[1][0]=2*x*y-2*w*z;   m[1][1]=1.0-2*x2-2*z2; m[1][2]=2*y*z+2*w*x;
01020  m[2][0]=2*x*z+2*w*y;   m[2][1]=2*y*z-2*w*x;   m[2][2]=1.0-2*x2-2*y2;
01021  m[3][3]=1.0; m[0][3]=m[1][3]=m[2][3]=m[3][0]=m[3][1]=m[3][2]=0.0;
01022  return;
01023 }
01024 
01025 static void Slerp(double mr, quaternion q1, quaternion q2, quaternion q){
01026  double sum,beta1,beta2,theta;
01027  sum=q1[0]*q2[0]+q1[1]*q2[1]+q1[2]*q2[2]+q1[3]*q2[3];
01028  if(sum < 0.0)sum=0.0;
01029  if(sum > 1.0)sum=1.0;
01030  theta=acos(sum);
01031  if(theta < EPSILON){ beta1=1.0-mr; beta2=mr;}
01032  else{
01033   beta1=sin((1.0-mr)*theta)/sin(theta);
01034   beta2=sin(mr*theta)/sin(theta);
01035  }
01036  q[0]=beta1*q1[0]+beta2*q2[0];
01037  q[1]=beta1*q1[1]+beta2*q2[1];
01038  q[2]=beta1*q1[2]+beta2*q2[2];
01039  q[3]=beta1*q1[3]+beta2*q2[3];
01040 }
01041 
01042 static int  nSkeleton;
01043 static skel *Skeleton;
01044 
01045 static void ApplyTransformToChildren(int id, double T[4][4]){
01046  static double x,y,z;
01047  static double sst[4][4],t1[4][4],t2[4][4];
01048  int i;
01049  for(i=1;i<nSkeleton;i++){ /* must start at one since root is never a child */
01050    if(Skeleton[i].id == id){
01051      R_tram(t1,-(Skeleton+id)->p[0],-(Skeleton+id)->p[1],-(Skeleton+id)->p[2]);
01052      R_m4by4((Skeleton+i)->Q,t1,t2);
01053      R_tram(t1, (Skeleton+id)->p[0], (Skeleton+id)->p[1], (Skeleton+id)->p[2]);
01054      R_m4by4(t1,t2,sst);
01055      R_m4by4(T,sst,Skeleton[i].T);
01056      ApplyTransformToChildren(i,Skeleton[i].T);
01057    }
01058  }
01059  return;
01060 }
01061 
01062 static void InterpolateRobot(double mr, long n, skel *sk1, skel *sk2){
01063  int i;
01064  quaternion q,q1,q2;
01065  nSkeleton=n;
01066  Skeleton=sk1;
01067  if(mr < 1.0){
01068    /* interpopate rotation matrices using Quaternion tweening */
01069    /* this interpolation always from last frame rotation as origin */
01070    quaternion Qi={1.0,0.0,0.0,0.0};
01071    double Q[4][4],Ri[4][4];
01072    for(i=0;i<nSkeleton;i++){
01073      InvertRotationMatrix((sk2+i)->R,Ri);
01074      R_m4by4((Skeleton+i)->R,Ri,Q);
01075      MatrixToQuaternion(Q,q2);
01076      Slerp(mr,Qi,q2,q);
01077      QuaternionToMatrix(q,Q);
01078      R_m4by4(Q,(sk2+i)->R,(Skeleton+i)->Q);   // Q is rotation applied to bone "i" to be applied about the parent node.
01079    }
01080  }
01081  else{
01082    for(i=0;i<nSkeleton;i++)R_c4to4((Skeleton+i)->R,(Skeleton+i)->Q);
01083  }
01084  ApplyTransformToChildren(0,Skeleton[0].T);
01085  return;
01086 }
01087 
01088 void RenderTransformToRobot(long O,
01089                             long *Skid, skel *Skel, double mr,
01090                             char *robo_f1, char *robo_f2){
01091   long i,j,n1=0,n2=0;
01092   FILE *frobot;
01093   skel *sk1=NULL,*sk2=NULL;
01094   vertex *v;
01095   double x1,y1,z1;
01096   if((frobot = fopen(robo_f1,"r")) != NULL){
01097     fscanf(frobot,"%ld\n",&n1);
01098     if(n1 > 0){  /* sk1 is the Robot  sk2 is version is moving from */
01099       if((sk1=Skel) == NULL)goto FINISHED;
01100       for(i=0;i<n1;i++){
01101         R_null_transform(sk1->R);
01102         R_null_transform(sk1->Q);
01103         R_null_transform(sk1->T);
01104         for(j=0;j<4;j++)fscanf(frobot,GET_MATX,
01105          &sk1[i].R[j][0], &sk1[i].R[j][1],
01106          &sk1[i].R[j][2], &sk1[i].R[j][3]);
01107       }
01108     }
01109     fclose(frobot);
01110   }
01111   if((frobot = fopen(robo_f2,"r")) != NULL){
01112     fscanf(frobot,"%ld\n",&n2);
01113     if(n2 > 0){
01114       if((sk2 = (skel *)X__Malloc(n2*(long)sizeof(skel))) == NULL)
01115            goto FINISHED;
01116       for(i=0;i<n2;i++){
01117         R_null_transform(sk2->R);
01118         R_null_transform(sk2->Q);
01119         R_null_transform(sk2->T);
01120         for(j=0;j<4;j++)fscanf(frobot,GET_MATX,
01121          &sk2[i].R[j][0], &sk2[i].R[j][1],
01122          &sk2[i].R[j][2], &sk2[i].R[j][3]);
01123       }
01124     }
01125     fclose(frobot);
01126   }
01127   if(n1 != n2 || n1 == 0 || n2 == 0)goto FINISHED;
01128   InterpolateRobot(mr,n1,sk1,sk2);
01129   v=Object[O].Vbase;
01130   for(i=0;i<Object[O].NoVertices;i++){
01131     R_m4by1(sk1[Skid[i]].T,v[i].p[0],v[i].p[1],v[i].p[2],&x1,&y1,&z1);
01132     v[i].p[0]=x1;
01133     v[i].p[1]=y1;
01134     v[i].p[2]=z1;
01135   }
01136   FINISHED:
01137   if(sk2 != NULL)X__Free(sk2);
01138   return;
01139 }
01140 
01141 static double GetBoneRelativeDistance(vector v, vector s, vector sp, vector d, double len, double *l, vector r){
01142  vector dp,q;
01143  double ll;
01144  VECSUB((double)v,(double)s,dp)
01145  ll=DOT(dp,d);
01146  if(ll < 0){ // closest point is behind start
01147    *l=0.0;     // fraction of bone to offset vector
01148    //*l=-0.1;     // fraction of bone to offset vector  //RSFx
01149    VECSUB((double)v,(double)s,r)
01150  }
01151  else if(ll > len){ // closest point is beyond end
01152    *l=1.0;
01153    //*l=1.1;   //RSFx
01154    VECSUB((double)v,(double)sp,r)
01155  }
01156  else{
01157    *l=ll/len;
01158    VECSUM((double)s,ll*d,q)
01159    VECSUB((double)v,q,r)
01160  }  
01161  return sqrt(DOT(r,r));  // closest distance of v to bone from (s to sp) 
01162 } 
01163 
01164 static void ApplyParentDeform(skel *s, skel *sp, vector p, vertex *v){//get pskp  (p is suggested position
01165   double dist,lab,h,h1;
01166   vector d,r;
01167   VECSUB(sp->p,s->p,d)
01168   VECSCALE(1.0/s->bLength,d,d);
01169   dist=GetBoneRelativeDistance(v->p,s->p,sp->p,d,s->bLength,&lab,r);  // original vertex's relative position
01170   h=1.0-lab; // lab is 0 at parent/child junction
01171   if(h < 0.0 || h > 1.0){
01172     if(dist > s->wrange)h=0.0;
01173     else h=(dist/s->wrange)*s->weight;
01174   }
01175   else h=h*h*s->weight;
01176   h1=1.0-h;
01177   VECSUM(h*p,h1*(v->p),v->pskp)  //this deforms the parent vertex
01178   v->bskp=TRUE;
01179 }
01180 static void ApplyChildDeform(skel *s, skel *sp, vector p, vertex *v){//get pskc (p is 
01181   double dist,lab,h,h1;
01182   vector d,r;
01183   VECSUB(sp->p,s->p,d)
01184   VECSCALE(1.0/s->bLength,d,d);
01185   dist=GetBoneRelativeDistance(v->p,s->p,sp->p,d,s->bLength,&lab,r);  // original vertex's relative position
01186   h=lab; // lab is 1 at parent/child junction
01187   if(h < 0.0 || h > 1.0){
01188     if(dist > s->wrange*ruler_length)h=0.0;
01189     else h=(dist/(s->wrange*ruler_length))*s->weight;
01190   }
01191   else h=h*h*s->weight;  // use a Zero Weight to exclude this bone or reduce its influence
01192   h1=1.0-h;
01193   VECSUM(h*p,h1*(v->p),v->pskc)  //this deforms the parent vertex
01194   v->bskc=TRUE;
01195 }
01196 
01197 
01198 void RenderRubberBones(long O, int nSk, long *Skid, skel *Skeleton){
01199  // Skid identifiles to which skeleton node the vertex belongs
01200  // Skeleton is the obkject's skeleton
01201  int i,j,pid,ppid;
01202  double x,y,z;
01203  double Q[4][4],Qi[4][4],t1[4][4],t2[4][4];
01204  vector p;
01205  vertex *v;
01206  // start by transforming skeleton
01207  for(i=1;i<nSk;i++){
01208    VECSUB((Skeleton+((Skeleton+i)->id))->p,(Skeleton+i)->p,p)
01209    (Skeleton+i)->bLength=sqrt(DOT(p,p)); // length of bone 
01210    R_m4by1((Skeleton+i)->T,(Skeleton+i)->p[0],(Skeleton+i)->p[1],(Skeleton+i)->p[2],&x,&y,&z);
01211    (Skeleton+i)->p[0]=x; (Skeleton+i)->p[1]=y; (Skeleton+i)->p[2]=z;
01212    Skeleton->weight=min(1.0,Skeleton->weight);
01213  }
01214  v=Object[O].Vbase;
01215  for(j=0;j<Object[O].NoVertices;j++)v[j].bskc=v[j].bskp=FALSE;
01216  // apply model by deforming the mesh around bone i and its parent by applying weighted Q(i) to parent and q-1(i) to (i).
01217  for(i=1;i<nSk;i++){
01218    pid=Skeleton[i].id;
01219    R_c4to4(Skeleton[i].Q,Q);
01220    for(j=0;j<3;j++)Q[3][j]=Q[j][3]=0.0; Q[3][3]=1.0;
01221    InvertRotationMatrix(Q,Qi);
01222    R_tram(t1,-(Skeleton+pid)->p[0],-(Skeleton+pid)->p[1],-(Skeleton+pid)->p[2]);
01223    R_m4by4(Q,t1,t2);
01224    R_tram(t1, (Skeleton+pid)->p[0], (Skeleton+pid)->p[1], (Skeleton+pid)->p[2]);
01225    R_m4by4(t1,t2,Q);  // transform parent vertices by rotating round parent end of bone
01226    R_tram(t1,-(Skeleton+pid)->p[0],-(Skeleton+pid)->p[1],-(Skeleton+pid)->p[2]);
01227    R_m4by4(Qi,t1,t2);
01228    R_tram(t1, (Skeleton+pid)->p[0], (Skeleton+pid)->p[1], (Skeleton+pid)->p[2]);
01229    R_m4by4(t1,t2,Qi);  // transform vertices by rotating round parent end of bone by inverse transform
01230 //fprintf(debug,"Bone %d parent %d\nRotation Matrix\n",i,pid);
01231 //for(j=0;j<4;j++)fprintf(debug,"%8.3f %8.3f %8.3f %8.3f\n", Skeleton[i].Q[j][0], Skeleton[i].Q[j][1], Skeleton[i].Q[j][2], Skeleton[i].Q[j][3]);
01232 //fprintf(debug,"Transform Matrix\n");for(j=0;j<4;j++)fprintf(debug,"%8.3f %8.3f %8.3f %8.3f\n",Q[j][0],Q[j][1],Q[j][2],Q[j][3]);
01233    for(j=0;j<Object[O].NoVertices;j++){
01234      if(Skid[j] == pid){ // apply deform to parent bone
01235        ppid=(Skeleton+pid)->id; // parent's parent ID
01236        R_m4by1(Q,v[j].p[0],v[j].p[1],v[j].p[2],&p[0],&p[1],&p[2]);
01237        ApplyParentDeform((Skeleton+pid),(Skeleton+ppid),p,(v+j)); // p is new postion of vertex (v+j)
01238      }
01239      else if(Skid[j] == i){// child (this bone)
01240        R_m4by1(Qi,v[j].p[0],v[j].p[1],v[j].p[2],&p[0],&p[1],&p[2]);
01241        ApplyChildDeform((Skeleton+i),(Skeleton+pid),p,(v+j));
01242      }
01243    }
01244  }
01245  // all new positions found from blend
01246  for(i=0;i<Object[O].NoVertices;i++){
01247    if(Skid[i] > 0) { // not the root
01248      if(v[i].bskp && v[i].bskc){ 
01249        v[i].p[0]=0.5*(v[i].pskp[0]+v[i].pskc[0]);
01250        v[i].p[1]=0.5*(v[i].pskp[1]+v[i].pskc[1]);
01251        v[i].p[2]=0.5*(v[i].pskp[2]+v[i].pskc[2]);
01252      }
01253      else if(v[i].bskc)VECCOPY(v[i].pskc,v[i].p)
01254      else if(v[i].bskp)VECCOPY(v[i].pskp,v[i].p)
01255    }
01256  }
01257  for(i=1;i<nSk;i++){ // put back the skeleton
01258    VECCOPY((Skeleton+i)->pcopy,(Skeleton+i)->p)
01259  }
01260  return;
01261 }

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6