LOADER.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX - Modelling, Animation and Rendering Package
00003 -- */
00004 
00005 /* file loader.c  - loads/saves the models from their files on disk  */
00006 
00007 #define MODULE_LOADER 1
00008 
00009 #include "design.h"
00010 
00011 extern long LastToolVertex;
00012 
00013 static void ReadModWireframe(long clen);
00014 static void ReadOldOldFaces(long clen, short shader);
00015 static void ReadOldFaces(long clen, BOOL short_form);
00016 static void ReadFaces(long clen);
00017 static void ReadEdges(long clen, BOOL short_form);
00018 static void ReadVertices(long clen);
00019 static void ReadVerticesSelection(long clen);
00020 static void ReadVertexMapping(long clen, long version);
00021 static void ReadSkeleton(long clen, short version);
00022 static int ReadImageMaps(long clen, short relation, BOOL bNew, long f_map);
00023 static void ReadModWireframe(long clen);
00024 static void ReadEmbeddedImages(long clen, long n_maps, long f_map);
00025 static void ReadMaterials(long id, long clen, short relation, long f_mat);
00026 static void ReadFaceMapping(long clen);
00027 static unsigned char getlon(long *);
00028 static unsigned char getsht(short *);
00029 static unsigned char getusht(unsigned short *);
00030 static void outsht(short);
00031 static void outusht(unsigned short);
00032 static void outlng(long);
00033 static void getchunk(long clen);
00034 static void WriteImageMaps(void);
00035 static void WriteMaterials(void);
00036 static void WriteEmbeddedImages(void);
00037 static void WriteVertices(short status);
00038 static void WriteVerticesSelection(short status);
00039 static void WriteVertexMapping(short status);
00040 static void WriteEdges(BOOL );
00041 static void WriteFaces(void);
00042 static void WriteSkeleton(void);
00043 static void WriteWireframe(void);
00044 static void WriteFaceMapping(void);
00045 static void WriteByteBuffer(long lng, unsigned char *b);
00046 
00047 #define BRUSHBIT   0x40
00048 #define SMOOTHBIT  0x80
00049 #define TILEBIT    0x20;
00050 
00051 static DWORD dwRead;
00052 static HANDLE fq;
00053 static FILE *fo;
00054 static long newface,newedge,newvert,newglue,minX,minY,minZ,maxX,maxY,maxZ;
00055 static char str[10];
00056 static key_points TempAxis;
00057 static long FaceBase,EdgeBase,VertexBase;
00058 
00060 
00061 static unsigned char getlon(long *val){
00062  long l,l0,l1,l2,l3;
00063  ReadFile(fq,&l,sizeof(long),&dwRead,NULL);
00064  l0 = (l >> 24) & 0x000000ff;
00065  l1 = (l >> 16) & 0x000000ff;
00066  l2 = (l >>  8) & 0x000000ff;
00067  l3 = (l      ) & 0x000000ff;
00068  *val = (l3 << 24) | (l2 << 16) | (l1 <<  8) | l0;
00069  return 1;
00070 }
00071 
00072 unsigned char ReadLongInteger(long *val, HANDLE h){
00073  long l,l0,l1,l2,l3;
00074  ReadFile(h,&l,sizeof(long),&dwRead,NULL);
00075  l0 = (l >> 24) & 0x000000ff;
00076  l1 = (l >> 16) & 0x000000ff;
00077  l2 = (l >>  8) & 0x000000ff;
00078  l3 = (l      ) & 0x000000ff;
00079  *val = (l3 << 24) | (l2 << 16) | (l1 <<  8) | l0;
00080  return 1;
00081 }
00082 
00083 static unsigned char getsht(short * val){
00084  short s,s0,s1;
00085  ReadFile(fq,&s,sizeof(short),&dwRead,NULL);
00086  s0 = (s >>  8) & 0x00ff;
00087  s1 = (s      ) & 0x00ff;
00088  *val = (s1 <<  8) | s0;
00089  return 1;
00090 }
00091 
00092 static unsigned char getusht(unsigned short * val){
00093  unsigned short s,s0,s1;
00094  ReadFile(fq,&s,sizeof(short),&dwRead,NULL);
00095  s0 = (s >>  8) & 0x00ff;
00096  s1 = (s      ) & 0x00ff;
00097  *val = (s1 <<  8) | s0;
00098  return 1;
00099 }
00100 
00101 static void getchunk(long clen){ // dump this chunk
00102  SetFilePointer(fq,clen,NULL,FILE_CURRENT);
00103 }
00104 
00105 static unsigned short GetUshortFromBuffer(unsigned char *b){
00106  return ((unsigned short)(*b) <<  8) | (unsigned short)(*(b+1));
00107 }
00108 
00109 static short GetShortFromBuffer(unsigned char *b){
00110  return ((short)(*b) <<  8) | (short)(*(b+1));
00111 }
00112 
00113 static long GetLongFromBuffer(unsigned char *b){
00114  return ((long)(*b) << 24) | ((long)(*(b+1)) << 16) |
00115         ((long)(*(b+2)) <<  8) | (long)(*(b+3));
00116 }
00117 
00118 static void outsht(short sht){
00119  fputc((char)(sht >>  8),fo);
00120  fputc((char)(sht      ),fo);
00121 }
00122 
00123 static void outusht(unsigned short sht){
00124  fputc((char)(sht >>  8),fo);
00125  fputc((char)(sht      ),fo);
00126 }
00127 
00128 static void outlng(long lng){
00129  fputc((char)(lng >> 24),fo);
00130  fputc((char)(lng >> 16),fo);
00131  fputc((char)(lng >>  8),fo);
00132  fputc((char)(lng      ),fo);
00133 }
00134 
00135 void WriteLongInteger(long lng, FILE *ff){
00136  fputc((char)(lng >> 24),ff);
00137  fputc((char)(lng >> 16),ff);
00138  fputc((char)(lng >>  8),ff);
00139  fputc((char)(lng      ),ff);
00140 }
00141 
00142 static void WriteByteBuffer(long lng, unsigned char *b){
00143   int i;
00144   char cc;
00145   for (i=0;i<lng;i++){
00146     cc=(char)*(b+i);
00147     fputc(cc,fo);
00148   }
00149 }
00150   
00151 
00152 char *short_form(char *filename){
00153  char *sps,*spc;
00154  if(filename == NULL)return NULL;
00155  sps=spc=filename;
00156  while((spc=strchr(spc,'\\')) != NULL){spc++; sps=spc;}
00157  return sps;
00158 }
00159 
00161 
00162 int LoadObject(char *FileName, short relation){
00163 /* relation = 0 for full load
00164             = 1 for local load
00165             = 2 abs load
00166             = 3 rescale the incoming model to match the vertex scales  
00167 */
00168  // CHUNKsize is the size of the data chunk excluding the chunk name and the chunksize  
00169  BOOL bReadFaceMapping=FALSE,bReadVertexMapping=FALSE;
00170  int fail=OK;
00171  long CHUNKsize,FORMsize,i,uxx,reset_ruler=1;
00172  long n_maps,f_map,f_mat;
00173  vertex *v;
00174  face   *f;
00175  double local_ruler=(double)UNIT;
00176  long   local_lrulerx=0,local_lrulery=0,local_lrulerz=0;
00177  char   local_ruler_name[8]="None";
00178  if(relation > 0)EDIT_ACTION=YES;
00179  maxX = maxY = maxZ = -MAXUNIT;
00180  minX = minY = minZ =  MAXUNIT;
00181  FaceBase=Nface; EdgeBase=Nedge; VertexBase=Nvert;
00182  n_maps=0; f_map=nImaps; f_mat=nMats;
00183  SendPrgmMessage(IDS_LOADING,0);
00184  fq=CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
00185     FILE_ATTRIBUTE_READONLY,(HANDLE)NULL);
00186  if(fq == INVALID_HANDLE_VALUE){
00187    SendPrgmMessage(IDS_FILEOPENFAIL,1);
00188    return FAIL;
00189  }
00190  LOADOPERATION=1;
00191  TempAxis.Origin.xyz[0]=0;         /* make sure all local variables */
00192  TempAxis.Origin.xyz[1]=0;         /* are  reset before using for   */
00193  TempAxis.Origin.xyz[2]=0;         /* the loading process           */
00194  newface=0; newedge=0; newvert=0; newglue=0;
00195  ReadFile(fq,str,4,&dwRead,NULL);
00196  if (dwRead != 4 || strcmp(str,"FORM") != 0){
00197    fail=FAIL;
00198    goto end;
00199  }
00200  getlon(&FORMsize);
00201  ReadFile(fq,str,4,&dwRead,NULL);
00202  if (dwRead != 4 || (strcmp(str,"OFXM") != 0 && strcmp(str,"AAPO") != 0)){
00203    fail=FAIL;
00204    goto end;
00205 }
00206 loop:
00207  if(!ReadFile(fq,str,4,&dwRead,NULL))goto end;
00208  if(dwRead != 4)goto end;
00209  getlon(&CHUNKsize);
00210  if     (strcmp(str,"VERT") == 0)ReadVertices(CHUNKsize);
00211  else if(strcmp(str,"VSEL") == 0)ReadVerticesSelection(CHUNKsize);
00212  else if(strcmp(str,"edge") == 0)ReadEdges(CHUNKsize,TRUE);
00213  else if(strcmp(str,"EDGE") == 0)ReadEdges(CHUNKsize,FALSE);
00214  else if(strcmp(str,"NFCE") == 0)ReadFaces(CHUNKsize);
00215  else if(strcmp(str,"SFCE") == 0)ReadOldFaces(CHUNKsize,TRUE);
00216  else if(strcmp(str,"LFCE") == 0)ReadOldFaces(CHUNKsize,FALSE);
00217  else if(strcmp(str,"FACE") == 0)ReadOldOldFaces(CHUNKsize,0);
00218  else if(strcmp(str,"SFAC") == 0)ReadOldOldFaces(CHUNKsize,1);
00219  else if(strcmp(str,"VTEX") == 0){ReadVertexMapping(CHUNKsize,0); bReadVertexMapping=TRUE;}
00220  else if(strcmp(str,"VTX2") == 0){ReadVertexMapping(CHUNKsize,1); bReadVertexMapping=TRUE;}
00221  else if(strcmp(str,"FTEX") == 0){ReadFaceMapping(CHUNKsize); bReadFaceMapping=TRUE;}
00222  else if(strcmp(str,"AXIS") == 0){
00223    getlon(&TempAxis.Origin.xyz[0]);
00224    getlon(&TempAxis.Origin.xyz[1]);
00225    getlon(&TempAxis.Origin.xyz[2]);
00226    for(i=0;i<9;i++)getlon(&uxx); // ignore the axis information   -- use for additional markers
00227    if(relation == 0){ /* full load */
00228      for(i=0;i<3;i++)ObjectAxis.Origin.xyz[i]=TempAxis.Origin.xyz[i];
00229    }
00230  }
00231  else if(strcmp(str,"OFFS") == 0  && relation == 0){/* only for full clean load*/
00232    getlon(&i);   /* no of offsets 1 for now allows possible expansion */
00233    getlon(&ObjectAxis.Offset.xyz[0]);  /* offset for objects to follow */
00234    getlon(&ObjectAxis.Offset.xyz[1]);  /* this one */
00235    getlon(&ObjectAxis.Offset.xyz[2]);
00236  }
00237  else if(strcmp(str,"IMAP") == 0)n_maps=ReadImageMaps(CHUNKsize,relation,FALSE,f_map);
00238  else if(strcmp(str,"IMA2") == 0)n_maps=ReadImageMaps(CHUNKsize,relation,TRUE,f_map);
00239  else if(strcmp(str,"EMAP") == 0)ReadEmbeddedImages(CHUNKsize,n_maps,f_map); 
00240  else if(strcmp(str,"MTL1") == 0)ReadMaterials(1,CHUNKsize,relation,f_mat); 
00241  else if(strcmp(str,"MTL2") == 0)ReadMaterials(2,CHUNKsize,relation,f_mat); 
00242  else if(strcmp(str,"SKEL") == 0 && relation == 0)ReadSkeleton(CHUNKsize,0);
00243  else if(strcmp(str,"SK01") == 0 && relation == 0)ReadSkeleton(CHUNKsize,1);
00244  else if(strcmp(str,"SK02") == 0 && relation == 0)ReadSkeleton(CHUNKsize,2);
00245  else if(strcmp(str,"SK03") == 0 && relation == 0)ReadSkeleton(CHUNKsize,3);
00246  else if(strcmp(str,"SK04") == 0 && relation == 0)ReadSkeleton(CHUNKsize,4);
00247  else if(strcmp(str,"UNIT") == 0){
00248    if(relation == 0){
00249      getlon(&i);  ruler = (double)i;
00250      ReadFile(fq,ruler_name,8,&dwRead,NULL);  if(dwRead != 8)goto end;
00251      getlon(&lrulerx);   getlon(&lrulery);   getlon(&lrulerz);
00252      rulerx = lrulerx; rulery = lrulery; rulerz = lrulerz;
00253      getlon(&i);   getlon(&i);   getlon(&i); /* don't use : is relative ruler */
00254      reset_ruler=0;
00255    }
00256    else{
00257      getlon(&i); local_ruler = (double)i;
00258      ReadFile(fq,local_ruler_name,8,&dwRead,NULL); if(dwRead != 8)goto end;
00259      getlon(&local_lrulerx);   getlon(&local_lrulery);   getlon(&local_lrulerz);
00260      getlon(&i);   getlon(&i);   getlon(&i);
00261    }
00262  }
00263  else if(strcmp(str,"GRID") == 0 && relation == 0){ /* not for local */
00264    getlon(&i);
00265    grid_size = (double)i;
00266    getlon(&i); /* unused */
00267  }
00268  else if(strcmp(str,"WFRM") == 0 && relation == 0)ReadModWireframe(CHUNKsize);
00269  else if(strcmp(str,"NURB") == 0)ReadNurbs(CHUNKsize,relation,fq);
00270 // put Nurbs here
00271  else getchunk(CHUNKsize);
00272  goto loop;
00273 end:
00274  CloseHandle(fq);
00275  if(bReadVertexMapping && !bReadFaceMapping){ // no face mapping so use vertex mapping to construct face mapping
00276    vertex *v0,*v1,*v2;
00277    //MessageBox(NULL,"NO face mapping","Making from Vertex data",MB_OK);
00278    if(Nface > FaceBase)for(i=FaceBase,f=(MainFp+FaceBase);i<Nface;i++,f++){
00279      if(f->imagemap >= 0 && f->imagemap < nImaps){ // valid image map
00280        if(iMap[f->imagemap].Map == MAP_BY_VERTEX){// using vertex coords
00281          v0=(MainVp + f->V[0]); v1=(MainVp + f->V[1]); v2=(MainVp + f->V[2]);
00282          if(v0->gp && v1->gp && v2->gp){
00283            f->gp=1; 
00284            f->x[0]=v0->x; f->y[0]=v0->y;
00285            f->x[1]=v1->x; f->y[1]=v1->y;
00286            f->x[2]=v2->x; f->y[2]=v2->y;
00287          }
00288        }
00289      }
00290    }   
00291  }
00292  if(relation == 1){   /* apply local offset  */
00293    v=(MainVp+VertexBase);  /* object origin is placed at cursor */
00294    for(i=VertexBase;i<Nvert;i++){/* the existing origin is retained */
00295      v->xyz[0] += NpointerX-TempAxis.Origin.xyz[0];
00296      v->xyz[1] += NpointerY-TempAxis.Origin.xyz[1];
00297      v->xyz[2] += NpointerZ-TempAxis.Origin.xyz[2];
00298      v++;
00299    }
00300  }
00301  else if(relation == 2){;} // do nothing 
00302  else if(relation == 3){   /* load using coords  */
00303    double tx,ty,tz;
00304    v=(MainVp+VertexBase);  /* object origin is placed at old coord origin */
00305    for(i=VertexBase;i<Nvert;i++){/* the existing origin is retained */
00306      tx = ((double)(v->xyz[0]-local_lrulerx))/local_ruler;
00307      ty = ((double)(v->xyz[1]-local_lrulery))/local_ruler;
00308      tz = ((double)(v->xyz[2]-local_lrulerz))/local_ruler;
00309      v->xyz[0] = (long)(tx*ruler)+lrulerx;
00310      v->xyz[1] = (long)(ty*ruler)+lrulery;
00311      v->xyz[2] = (long)(tz*ruler)+lrulerz;
00312      v++;
00313    }
00314  }
00315  else  EDIT_ACTION=NO;
00316  if(Nvert > 0 && (relation == 0 || relation == 3)){
00317 //
00318    reset_mod_maxview(1);
00319  }
00320  if(relation == 0 && reset_ruler){  // units got garbled
00321    strcpy(ruler_name,"None");
00322    ruler=(double)UNIT;
00323    rulerx=0;rulery=0;rulerz=0;
00324    lrulerx=0;lrulery=0;lrulerz=0;
00325  }
00326  LOADOPERATION=0;
00327  return fail;
00328 }
00329 
00330 static void ReadOldOldFaces(long clen, short shader){
00331   long i;
00332   long id;
00333   face *Fp;
00334   unsigned char texture,brush,attrib;
00335   unsigned char *buffer=NULL,*b;
00336   if(shader)newface=clen/21;
00337   else      newface=clen/20;
00338   if(newface == 0)return;
00339   buffer=(unsigned char *)X__Malloc(clen);
00340   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00341   ReadFile(fq,buffer,clen,&dwRead,NULL);
00342   UpdateFaceHeap(Nface+newface);
00343   Fp=(MainFp+FaceBase);
00344   for(i=0;i<newface;i++){
00345     Fp=(MainFp+FaceBase+i);
00346     Fp->material = -1;
00347     Fp->imagemap = -1;
00348     Fp->gp=FALSE;
00349     Fp->V[0]=VertexBase+GetLongFromBuffer(b); b+= 4;
00350     Fp->V[1]=VertexBase+GetLongFromBuffer(b); b+= 4;
00351     Fp->V[2]=VertexBase+GetLongFromBuffer(b); b+= 4;
00352     memcpy(Fp->color,b,3); b+= 3;
00353     texture = *b++;
00354     b+= 3; // old matco
00355     brush = *b++;
00356     if(shader)/*Fp->axis = * */ b++;
00357     /* make texture byte correspond to new arrangement */
00358     attrib=(texture & 0xf0) | (brush >> 4);
00359     if((attrib & 0x40) == 0x40)Fp->imagemap = (short)(brush & 0x1f);
00360     else Fp->imagemap = -1;
00361     if((attrib & 0x80) == 0x80)Fp->bSmooth=TRUE;
00362     else Fp->bSmooth=FALSE;
00363     Nface++;
00364     Fp++;
00365   }
00366   X__Free(buffer);
00367   return;
00368 }
00369 
00370 static void ReadOldFaces(long clen, BOOL short_form){
00371   long i;
00372   long id;
00373   unsigned short ids;
00374   unsigned char  attrib,map;
00375   face *Fp;
00376   unsigned char texture,brush;
00377   unsigned char *buffer=NULL,*b;
00378   if(short_form)newface=clen/18;
00379   else          newface=clen/24;
00380   if(newface == 0)return;
00381   buffer=(unsigned char *)X__Malloc(clen);
00382   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00383   ReadFile(fq,buffer,clen,&dwRead,NULL);
00384   UpdateFaceHeap(Nface+newface);
00385   Fp=(MainFp+FaceBase);
00386   for(i=0;i<newface;i++){
00387     Fp=(MainFp+FaceBase+i);
00388     Fp->material = -1;
00389     Fp->gp=FALSE;
00390     if(short_form){
00391       Fp->V[0]=VertexBase+(long)GetUshortFromBuffer(b); b+= 2;
00392       Fp->V[1]=VertexBase+(long)GetUshortFromBuffer(b); b+= 2;
00393       Fp->V[2]=VertexBase+(long)GetUshortFromBuffer(b); b+= 2;
00394     }
00395     else{
00396       Fp->V[0]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00397       Fp->V[1]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00398       Fp->V[2]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00399     }
00400     memcpy(Fp->color,b,3);  b += 3;
00401     /*memcpy(Fp->matcol,b,3);*/  b += 3;
00402     attrib = *b++; 
00403     /*Fp->param  = * */ b++;
00404     map  = *b++;
00405     if((attrib & 0x40) == 0x40)Fp->imagemap=map;
00406     else Fp->imagemap= -1;
00407     if((attrib & 0x80) == 0x80)Fp->bSmooth=TRUE;
00408     else Fp->bSmooth=FALSE;
00409     /*Fp->shader = * */ b++;
00410     /*Fp->axis   = * */ b++;
00411     /*Fp->pad    = * */ b++;
00412     Nface++;
00413     Fp++;
00414   }
00415   X__Free(buffer);
00416   return;
00417 }
00418 
00419 static void ReadFaces(long clen){
00420   long i;
00421   long id;
00422   unsigned short ids;
00423   face *Fp;
00424   unsigned char texture,brush;
00425   unsigned char *buffer=NULL,*b;
00426   newface=clen/20;
00427   if(newface == 0)return;
00428   buffer=(unsigned char *)X__Malloc(clen);
00429   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00430   ReadFile(fq,buffer,clen,&dwRead,NULL);
00431   UpdateFaceHeap(Nface+newface);
00432   Fp=(MainFp+FaceBase);
00433   for(i=0;i<newface;i++){
00434     Fp=(MainFp+FaceBase+i);
00435     Fp->V[0]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00436     Fp->V[1]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00437     Fp->V[2]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00438     memcpy(Fp->color,b,3);  b += 3;
00439     Fp->bSmooth = *b++;
00440     Fp->material=GetShortFromBuffer(b); b+= 2;
00441     Fp->imagemap=GetShortFromBuffer(b); b+= 2;
00442     Fp->gp=FALSE;
00443     Nface++;
00444     Fp++;
00445   }
00446   X__Free(buffer);
00447   return;
00448 }
00449 
00450 static void ReadFaceMapping(long clen){
00451   long i,j,ix,iy,nn;
00452   face *Fp;
00453   unsigned char *buffer=NULL,*b;
00454   nn=clen/28;
00455   if(nn == 0)return;
00456   buffer=(unsigned char *)X__Malloc(clen);
00457   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00458   ReadFile(fq,buffer,clen,&dwRead,NULL);
00459   if(nn == newface){
00460 //MessageBox(NULL,"Reading Face Mapping",NULL,MB_OK);
00461     Fp=(MainFp+FaceBase);
00462     for(i=0;i<nn;i++){
00463       Fp=(MainFp+FaceBase+i);
00464       Fp->gp=(BOOL)GetLongFromBuffer(b); b+= 4;
00465       for(j=0;j<3;j++){
00466         ix=GetLongFromBuffer(b); b+= 4;
00467         iy=GetLongFromBuffer(b); b+= 4;
00468         Fp->x[j]=(float)ix*0.000001;
00469         Fp->y[j]=(float)iy*0.000001;
00470       }
00471       Fp++;
00472     }
00473   }
00474   X__Free(buffer);
00475   return;
00476 }
00477 
00478 static void ReadEdges(long clen, BOOL short_form){
00479   long i;
00480   long id1,id2;
00481   unsigned short ids1,ids2;
00482   edge *Ep;
00483   unsigned char *buffer=NULL,*b;
00484   if(short_form)newedge=clen/4;
00485   else          newedge=clen/8;
00486   if(newedge == 0)return;
00487   buffer=(unsigned char *)X__Malloc(clen);
00488   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00489   ReadFile(fq,buffer,clen,&dwRead,NULL);
00490   UpdateEdgeHeap(Nedge+newedge);
00491   Ep=(MainEp+EdgeBase);
00492   for(i=0;i<newedge;i++){
00493     if(short_form){
00494       Ep->V[0]=VertexBase+(long)GetUshortFromBuffer(b); b+= 2;
00495       Ep->V[1]=VertexBase+(long)GetUshortFromBuffer(b); b+= 2;
00496     }
00497     else{
00498       Ep->V[0]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00499       Ep->V[1]=VertexBase+(long)GetLongFromBuffer(b); b+= 4;
00500     }
00501     Ep++;
00502     Nedge++;
00503   }
00504   X__Free(buffer);
00505   return;
00506 }
00507 
00508 static void ReadVertices(long clen){
00509   vertex *Vp;
00510   char c;
00511   long i,j;
00512   unsigned char *buffer=NULL,*b;
00513   newvert=clen/12;
00514   if(newvert == 0)return;
00515   buffer=(unsigned char *)X__Malloc(clen);
00516   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00517   ReadFile(fq,buffer,clen,&dwRead,NULL);
00518   UpdateVertexHeap(Nvert+newvert);
00519   Vp=(MainVp+VertexBase);
00520   for(i=0;i<newvert;i++){
00521     Vp->status=SELECTED;   
00522     Vp->sp =  NULL;
00523     Vp->gp = 0;
00524     Vp->xyz[0]=GetLongFromBuffer(b); b+= 4;
00525     Vp->xyz[1]=GetLongFromBuffer(b); b+= 4;
00526     Vp->xyz[2]=GetLongFromBuffer(b); b+= 4;
00527     Vp->sp=NULL;
00528     if(Vp->xyz[0] > maxX)maxX=Vp->xyz[0];
00529     if(Vp->xyz[0] < minX)minX=Vp->xyz[0];
00530     if(Vp->xyz[1] > maxY)maxY=Vp->xyz[1];
00531     if(Vp->xyz[1] < minY)minY=Vp->xyz[1];
00532     if(Vp->xyz[2] > maxZ)maxZ=Vp->xyz[2];
00533     if(Vp->xyz[2] < minZ)minZ=Vp->xyz[2];
00534     NvertSelect++;
00535     Nvert++;
00536     Vp++;
00537   }
00538   X__Free(buffer);
00539   return;
00540 }
00541 
00542 static void ReadVerticesSelection(long clen){
00543   vertex *Vp;
00544   char c;
00545   long i,j,nv;
00546   unsigned char *buffer=NULL,*b;
00547   nv=clen;
00548   if(nv == 0 || nv != newvert)return;
00549   buffer=(unsigned char *)X__Malloc(clen);
00550   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00551   ReadFile(fq,buffer,clen,&dwRead,NULL);
00552   Vp=(MainVp+VertexBase);
00553   for(i=0;i<nv;i++){
00554     c = *b; b++;
00555     if     (c == 0){Vp->status=SELECTED; }
00556     else if(c == 1){Vp->status=DESELECTED; NvertSelect--; NvertDeselect++;}
00557     else if(c == 2){Vp->status=HIDDEN;  NvertSelect--; NvertDeselect++;}
00558     Vp++;
00559   }
00560   X__Free(buffer);
00561   return;
00562 }
00563 
00564 static void ReadVertexMapping(long clen, long version){
00565   long i,id,ix,iy,szz,ida;
00566   vertex *Vp;
00567   unsigned char *buffer=NULL,*b;
00568   newglue=clen/12;
00569   if(newglue == 0)return;
00570   if(newglue > newvert){ /* dump the mapping */
00571     MessageBox(NULL,"Bad vertex mapping",NULL,MB_OK);
00572     for(i=0;i<newglue;i++){
00573       getlon(&id); getlon(&ix); getlon(&iy);
00574     }
00575     return;
00576   }
00577   buffer=(unsigned char *)X__Malloc(clen);
00578   if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00579   ReadFile(fq,buffer,clen,&dwRead,NULL);
00580   //if(version == 0)MessageBox(NULL,"Old vertex mapping",NULL,MB_OK);
00581   //else MessageBox(NULL,"New Vertex Mapping",NULL,MB_OK);
00582   for(i=0;i<newglue;i++){
00583     id=GetLongFromBuffer(b); b+= 4;
00584     if(version == 0)ida=id; else ida=i;
00585     ix=GetLongFromBuffer(b); b+= 4;
00586     iy=GetLongFromBuffer(b); b+= 4;
00587     Vp=(MainVp+VertexBase+ida);
00588     if(version == 0)Vp->gp=1;   // just some vertices mapped
00589     else            Vp->gp=id;  // every vertex mapped/or not this gives value (1 or 0)
00590     Vp->x=(float)ix*0.000001;
00591     Vp->y=(float)iy*0.000001;
00592   }
00593   X__Free(buffer);
00594   return;
00595 }
00596 
00597 static void DumpSkeleton(long nskel,long clen){
00598 {char xxx[256]; sprintf(xxx,"Skeleton size %ld ",nskel); MessageBox(NULL,xxx,"Dumping Skeleton: Too large",MB_OK);}
00599  getchunk(clen-4);  // have already read the first long
00600 }
00601 
00602 static void ReadSkeleton(long clen, short version){
00603   vertex *v;
00604   char c;
00605   long i,j,k,l,szz,n,x,y,z,nskel;
00606   skel *sp,**s;
00607   short dummy;
00608   long dummyl; 
00609   getlon(&n);
00610   if(n == 0)return; nskel=n;
00611   EraseAllSkeleton();  /* start with new skeleton */
00612   if(nskel > 512){DumpSkeleton(nskel,clen); return;}
00613   szz=sizeof(skel *);
00614   s=(skel  **)X__Malloc((long)(szz*n));
00615   if(s == NULL){
00616     SendPrgmQuery(IDQ_NOMEM2,0);
00617     CloseHandle(fq);
00618     longjmp(j_buf,0);
00619   }
00620   getlon(&MainSp->xyz[0]); /* first Node into root node */
00621   getlon(&MainSp->xyz[1]);
00622   getlon(&MainSp->xyz[2]);
00623   if(version < 3){getsht(&dummy);  dummyl=(long)dummy;}
00624   else           {getlon(&dummyl);}
00625   if(dummyl < 0 || dummyl >= nskel){MainSp->id=0; MessageBox(NULL,"SkeletonError",NULL,MB_OK);}
00626   else MainSp->id = dummyl;
00627   if(version > 0){
00628     ReadFile(fq,MainSp->name,sizeof(char)*16,&dwRead,NULL);
00629     if(version > 3){
00630       getlon(&dummyl); MainSp->weight=((double)dummyl)/1000.0; 
00631       getlon(&dummyl); MainSp->wrange=((double)dummyl)/1000.0; 
00632       getlon(&dummyl); MainSp->wzone=((double)dummyl)/1000.0; 
00633     }
00634   }
00635   if(version > 1){
00636     for(j=0;j<3;j++){getlon(&l); MainSp->u[j] = ((double)l)*1.0e-8;}
00637     for(j=0;j<3;j++){getlon(&l); MainSp->v[j] = ((double)l)*1.0e-8;}
00638     for(j=0;j<3;j++){getlon(&l); MainSp->w[j] = ((double)l)*1.0e-8;}
00639     for(j=0;j<8;j++)for(k=0;k<3;k++)getlon(&(MainSp->bx[j][k]));
00640   }
00641   MainSp->at=NULL;
00642   *s = MainSp;
00643   if(n > 1)for(i=1;i<n;i++){
00644     CreateSkeleton(NULL);
00645     getlon(&MainSp->xyz[0]);
00646     getlon(&MainSp->xyz[1]);
00647     getlon(&MainSp->xyz[2]);
00648     if(version < 3){getsht(&dummy); MainSp->id=(long)dummy;}
00649     else           {getlon(&dummyl); MainSp->id = dummyl;}
00650     if(version > 0){
00651       ReadFile(fq,MainSp->name,sizeof(char)*16,&dwRead,NULL);
00652       if(version > 3){
00653         getlon(&dummyl); MainSp->weight=((double)dummyl)/1000.0; 
00654         getlon(&dummyl); MainSp->wrange=((double)dummyl)/1000.0; 
00655         getlon(&dummyl); MainSp->wzone=((double)dummyl)/1000.0; 
00656       }
00657     }
00658     if(version > 1){
00659       for(j=0;j<3;j++){getlon(&l); MainSp->u[j] = ((double)l)*1.0e-8;}
00660       for(j=0;j<3;j++){getlon(&l); MainSp->v[j] = ((double)l)*1.0e-8;}
00661       for(j=0;j<3;j++){getlon(&l); MainSp->w[j] = ((double)l)*1.0e-8;}
00662       for(j=0;j<8;j++)for(k=0;k<3;k++)getlon(&(MainSp->bx[j][k]));
00663     }
00664     *(s+i)=MainSp;
00665   }
00666   if((sp = FirstSp->next) != NULL)while(sp != NULL){ /* fix up pointers */
00667     if(sp->id < 0 || sp->id >= nskel)sp->at = *s;
00668     else sp->at = *(s + (long)sp->id);
00669     sp=sp->next;
00670   }
00671   getlon(&n);
00672   if(n != newvert){
00673     SendPrgmQuery(IDQ_HERROR,0);
00674     for(i=0;i<n;i++){
00675       if(version < 3)getsht(&dummy);
00676       else           getlon(&dummyl);
00677     }
00678   }
00679   else{
00680     v=(MainVp+VertexBase);
00681     for(i=0;i<n;i++){
00682       if(version < 3){getsht(&dummy); dummyl=(long)dummy;}   /* put into new vertex the pointer to the sk joint */
00683       else            getlon(&dummyl);
00684 if(dummyl >= nskel)MessageBox(NULL,"Skeleton Error",NULL,MB_OK);
00685       if(dummyl > 0 && dummyl < nskel)v->sp = *(s+(long)dummyl);
00686       else          v->sp = NULL;
00687       v++;
00688     }
00689   }
00690   if(version < 2){ /* work out bounding boxes for old versions */
00691     TidyUpOldSkeltonType();
00692   }
00693   X__Free(s);
00694 }
00695 
00696 //RSFx
00697 int AddExternalSkeleton(char *FileName){ // This loads a skeleton from another model and maps it onto the model
00698   // there must be the same number of vertices.
00699  long CHUNKsize,FORMsize,vc=0;
00700  BOOL bCanImport=FALSE; 
00701  FaceBase=0; EdgeBase=0; VertexBase=0;
00702  fq=CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
00703     FILE_ATTRIBUTE_READONLY,(HANDLE)NULL);
00704  if(fq == INVALID_HANDLE_VALUE){
00705    SendPrgmMessage(IDS_FILEOPENFAIL,1);
00706    return FAIL;
00707  }
00708  ReadFile(fq,str,4,&dwRead,NULL);
00709  if (dwRead != 4 || strcmp(str,"FORM") != 0){
00710    goto end;
00711  }
00712  getlon(&FORMsize);
00713  ReadFile(fq,str,4,&dwRead,NULL);
00714  if (dwRead != 4 || (strcmp(str,"OFXM") != 0 && strcmp(str,"AAPO") != 0)){
00715    goto end;
00716 }
00717 loop:
00718  if(!ReadFile(fq,str,4,&dwRead,NULL))goto end;
00719  if(dwRead != 4)goto end;
00720  getlon(&CHUNKsize);
00721 //  newvert=clen/12;
00722  if     (strcmp(str,"VERT") == 0){
00723    if((vc=CHUNKsize/12) == Nvert)bCanImport=TRUE;
00724    getchunk(CHUNKsize);
00725  }
00726  else if(strcmp(str,"SKEL") == 0 && bCanImport)ReadSkeleton(CHUNKsize,0);
00727  else if(strcmp(str,"SK01") == 0 && bCanImport)ReadSkeleton(CHUNKsize,1);
00728  else if(strcmp(str,"SK02") == 0 && bCanImport)ReadSkeleton(CHUNKsize,2);
00729  else if(strcmp(str,"SK03") == 0 && bCanImport)ReadSkeleton(CHUNKsize,3);
00730  else if(strcmp(str,"SK04") == 0 && bCanImport)ReadSkeleton(CHUNKsize,4);
00731  else getchunk(CHUNKsize);
00732  goto loop;
00733 end:
00734  CloseHandle(fq);
00735  if(!bCanImport)MessageBox(NULL,"Incompatible Skeletons",NULL,MB_OK);
00736  //{char sss[256]; sprintf(sss,"F=[%s] Nvert=%d Vskel=%d",FileName,Nvert,vc);
00737  //MessageBox(NULL,sss,"Add in skeleton",MB_OK);}
00738  return OK;
00739 }
00740 
00741 
00742 static int ReadImageMaps(long clen, short relation, BOOL bNew, long ts){
00743  face *f;
00744  long j,i,k,l,m,tid,temp,temp1;
00745  short temps;
00746  char temp_str[256];
00747  unsigned char *buffer=NULL,*b;
00748  buffer=(unsigned char *)X__Malloc(clen);
00749  if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00750  ReadFile(fq,buffer,clen,&dwRead,NULL);
00751  j=GetLongFromBuffer(b); b+= 4; /* number of image maps in this model */
00752  if(j > 0){   
00753    for(i=0;i<j;i++){
00754      k=nImaps; // this will be the first image map
00755      if(CreateImageMap() == FAIL)goto ERR;  // nImaps will be up one by this
00756      iMap[k].P[0]=GetLongFromBuffer(b); b+= 4;
00757      iMap[k].P[1]=GetLongFromBuffer(b); b+= 4;
00758      iMap[k].P[2]=GetLongFromBuffer(b); b+= 4;
00759      iMap[k].X[0]=GetLongFromBuffer(b); b+= 4;
00760      iMap[k].X[1]=GetLongFromBuffer(b); b+= 4;
00761      iMap[k].X[2]=GetLongFromBuffer(b); b+= 4;
00762      iMap[k].Y[0]=GetLongFromBuffer(b); b+= 4;
00763      iMap[k].Y[1]=GetLongFromBuffer(b); b+= 4;
00764      iMap[k].Y[2]=GetLongFromBuffer(b); b+= 4;
00765      iMap[k].Type=(char)GetLongFromBuffer(b);  b+= 4;   b+= 4; b+= 4; b+= 4;// include not used items
00766      iMap[k].TypeR=(char)GetLongFromBuffer(b); b+= 4;   b+= 4; b+= 4; b+= 4;
00767      iMap[k].TypeB=(char)GetLongFromBuffer(b); b+= 4;   b+= 4; b+= 4; b+= 4;
00768      iMap[k].TypeT=(char)GetLongFromBuffer(b); b+= 4;   b+= 4; b+= 4; b+= 4;
00769       b+=4;   // skip skeleton attachment
00770      iMap[k].Map=(char)GetLongFromBuffer(b); b+=4;       /* 0 plane 1 cylinder     */
00771      iMap[k].Angle=360.0;  /* default */         /* 2 = pl-moz 3 = cyl-moz */
00772      iMap[k].Lock=0;
00773      iMap[k].Vlock[0] = -1; iMap[k].Vlock[1] = -1; iMap[k].Vlock[2] = -1;
00774      iMap[k].Angle=GetLongFromBuffer(b); b+=4;
00775      b += 4; //iMap[k].Lock = (char)GetLongFromBuffer(b); b+=4; // not used
00776      b += (3*4); // locking is not used now
00777      memcpy(iMap[k].N,b,32);  b+= 32;   // read map name
00778      iMap[k].s = *b++;
00779      iMap[k].r = *b++;
00780      iMap[k].b = *b++;
00781      iMap[k].t = *b++;
00782      iMap[k].Key = *b++;
00783      iMap[k].sp=GetShortFromBuffer(b); b+= 2;
00784      iMap[k].rp=GetShortFromBuffer(b); b+= 2;
00785      iMap[k].bp=GetShortFromBuffer(b); b+= 2;
00786      iMap[k].tp=GetShortFromBuffer(b); b+= 2;
00787      memcpy(iMap[k].d_colour,b,3); b += 3;
00788      memcpy(iMap[k].s_colour,b,3); b += 3;
00789      memcpy(iMap[k].a_colour,b,3); b += 3;
00790      memcpy(iMap[k].k_colour,b,3); b += 3;
00791      // get the filenames 
00792      memset(temp_str,0,256); memcpy(temp_str,b,250); b += 256; // to make sure some zeros
00793      //{char ttt[256]; sprintf(ttt,"String [%s]length=%ld",temp_str,strlen(temp_str));
00794      //MessageBox(NULL,ttt,"Image map string",MB_OK);}
00795      if(iMap[k].s){
00796        if((iMap[k].S=(char *)X__Malloc(strlen(temp_str)+1)) == NULL)iMap[k].s=0;
00797        else strcpy(iMap[k].S,temp_str);
00798      }
00799      else iMap[k].S=NULL;
00800      memset(temp_str,0,256); memcpy(temp_str,b,250); b += 256;
00801      if(iMap[k].r){
00802        if((iMap[k].R=(char *)X__Malloc(strlen(temp_str)+1)) == NULL)iMap[k].r=0;
00803        else strcpy(iMap[k].R,temp_str);
00804      }
00805      else iMap[k].R=NULL;
00806      memset(temp_str,0,256); memcpy(temp_str,b,250); b += 256;
00807      if(iMap[k].b){
00808        if((iMap[k].B=(char *)X__Malloc(strlen(temp_str)+1)) == NULL)iMap[k].b=0;
00809        else strcpy(iMap[k].B,temp_str);
00810      }
00811      else iMap[k].B=NULL;
00812      memset(temp_str,0,256); memcpy(temp_str,b,250); b += 256;
00813      if(iMap[k].t){
00814        if((iMap[k].T=(char *)X__Malloc(strlen(temp_str)+1)) == NULL)iMap[k].t=0;
00815        else strcpy(iMap[k].T,temp_str);
00816      }
00817      else iMap[k].T=NULL;
00818      if(bNew){
00819        b +=4 ; //will be version
00820        iMap[k].bDecal  = (BOOL)GetLongFromBuffer(b); b += 4;
00821        iMap[k].bShaded = (BOOL)GetLongFromBuffer(b); b += 4;
00822        iMap[k].bTiled  = (BOOL)GetLongFromBuffer(b); b += 4;
00823      }
00824      // end of read for this MAP
00825      if(relation == 1){ /* the brush must be repositioned to new offset */
00826        iMap[k].P[0] += NpointerX-TempAxis.Origin.xyz[0];
00827        iMap[k].P[1] += NpointerY-TempAxis.Origin.xyz[1];
00828        iMap[k].P[2] += NpointerZ-TempAxis.Origin.xyz[2];
00829        iMap[k].X[0] += NpointerX-TempAxis.Origin.xyz[0];
00830        iMap[k].X[1] += NpointerY-TempAxis.Origin.xyz[1];
00831        iMap[k].X[2] += NpointerZ-TempAxis.Origin.xyz[2];
00832        iMap[k].Y[0] += NpointerX-TempAxis.Origin.xyz[0];
00833        iMap[k].Y[1] += NpointerY-TempAxis.Origin.xyz[1];
00834        iMap[k].Y[2] += NpointerZ-TempAxis.Origin.xyz[2];
00835      }
00836    }
00837    //  fix up the faces to match the imagemaps
00838    if(FaceBase > 0){               /* set new faces for appropriate brush */
00839      f=(MainFp+FaceBase); for(m=0;m<newface;m++){
00840        if(f->imagemap >= 0){
00841          tid = f->imagemap;              /* extract the brush identifier */
00842          tid += ts;                 /* get the new brush id         */
00843          if(tid >= nImaps){
00844            tid=nImaps-1;
00845            MessageBox(NULL,"Map Load Error",NULL,MB_OK);
00846          }
00847          f->imagemap=(short)tid; /* put it back                  */
00848        }
00849        f++;
00850      }
00851    }
00852  }
00853  X__Free(buffer);
00854  return j;
00855  ERR:
00856  if(buffer != NULL)X__Free(buffer);
00857  MessageBox(NULL,"Bad Read Image Map",NULL,MB_OK);
00858  CloseHandle(fq);
00859  longjmp(j_buf,0);
00860  return 0;
00861 }
00862 
00863 static void ReadEmbeddedImages(long clen, long n_maps, long f_map){
00864  // read the embedded images - this must come after the read Image Maps chunk
00865  int i,j;
00866  //{char xxx[256]; sprintf(xxx,"Emb chunk size=%ld  %ld maps  first map=%ld",clen,n_maps,f_map);
00867  //MessageBox(NULL,xxx,"Reading Ram Image",MB_OK);}
00868  getlon(&i);
00869  if(i != n_maps)MessageBox(NULL,"MAP MISMATCH",NULL,MB_OK);
00870  for(i=0;i<n_maps;i++){
00871    j=i+f_map;
00872    if(j < 0 || j >= nImaps){
00873      MessageBox(NULL,"Bad Map Index",NULL,MB_OK);
00874    }
00875    ReadRamImage((&iMap[j].si),fq);
00876    ReadRamImage((&iMap[j].ri),fq);
00877    ReadRamImage((&iMap[j].bi),fq);
00878    ReadRamImage((&iMap[j].ti),fq);
00879  }
00880 }
00881 
00882 static void ReadModWireframe(long clen){
00883  long i,ne,np;
00884  getlon(&np);  getlon(&ne);
00885  i=((np*3)+(ne*2)+2)*sizeof(long);
00886  if(clen != i){   /* if chunk is void */
00887    getchunk(clen-2);
00888    return;
00889  }
00890  w_frame.p = (point *)X__Malloc(np*sizeof(point));
00891  w_frame.e = (twoLongs *)X__Malloc(ne*sizeof(twoLongs));
00892  if(w_frame.p == NULL || w_frame.e == NULL){
00893    if(w_frame.p != NULL)X__Free(w_frame.p); w_frame.p=NULL;
00894    if(w_frame.e != NULL)X__Free(w_frame.e); w_frame.e=NULL;
00895    getchunk(clen-2);
00896    return;
00897  }
00898  w_frame.Np=np;  w_frame.Ne=ne;
00899  for(i=0;i<w_frame.Np;i++){
00900    getlon(&w_frame.p[i][0]);
00901    getlon(&w_frame.p[i][1]);
00902    getlon(&w_frame.p[i][2]);
00903  }
00904  for(i=0;i<w_frame.Ne;i++){
00905    getlon(&w_frame.e[i][0]);
00906    getlon(&w_frame.e[i][1]);
00907  }
00908 }
00909 
00910 static void ReadMaterials(long id, long clen, short relation, long f_mat){
00911  face *f;
00912  long i,j,k,n,s_in_use,ln,lp;
00913  char temp_name[32];
00914  long tid,ts;
00915  unsigned char *buffer=NULL,*b;
00916  buffer=(unsigned char *)X__Malloc(clen);
00917  if(buffer == NULL)longjmp(j_buf,0);  b=buffer;
00918  ReadFile(fq,buffer,clen,&dwRead,NULL);
00919  n=GetLongFromBuffer(b); b+= 4; /* number of materials in this model */
00920  ts=f_mat;       /* the present no of materials loaded */
00921  if(n > 0)for(i=0;i<n;i++){
00922    k=nMats;
00923    if(CreateMaterial(FALSE) == FAIL)goto ERR;  // nImaps will be up one by this
00924    iMat[k].version = (long)GetLongFromBuffer(b); b+=4;
00925    memcpy(iMat[k].name,b,32);  b+= 32;
00926    //MessageBox(NULL,iMat[k].name,"Creating New material",MB_OK);
00927    memcpy(iMat[k].mcolour1,b,3); b+=3;
00928    memcpy(iMat[k].mcolour2,b,3); b+=3;
00929    memcpy(iMat[k].acolour,b,3); b+=3;
00930    memcpy(iMat[k].scolour,b,3); b+=3;
00931    memcpy(iMat[k].xcolour,b,3); b+=3;
00932    memcpy(iMat[k].ycolour,b,3); b+=3;
00933    memcpy(iMat[k].zcolour,b,3); b+=3;
00934    iMat[k].gloss = (unsigned char)GetLongFromBuffer(b); b+=4;
00935    iMat[k].refl = (unsigned char)GetLongFromBuffer(b); b+=4;
00936    iMat[k].transp = (unsigned char)GetLongFromBuffer(b); b+=4;
00937    iMat[k].refractive_index = (long)GetLongFromBuffer(b); b+=4;
00938    iMat[k].bInternalShader = (BOOL)GetLongFromBuffer(b); b+=4;
00939    iMat[k].internalShaderID = (int)GetLongFromBuffer(b); b+=4;
00940    for(j=0;j<3;j++){iMat[k].ax.P[j] = GetLongFromBuffer(b); b+=4;}
00941    for(j=0;j<3;j++){iMat[k].ax.X[j] = GetLongFromBuffer(b); b+=4;}
00942    for(j=0;j<3;j++){iMat[k].ax.Y[j] = GetLongFromBuffer(b); b+=4;}
00943    for(j=0;j<4;j++){
00944      iMat[k].Shader[j].version=GetLongFromBuffer(b); b+=4;
00945      iMat[k].Shader[j].bActive=(BOOL)GetLongFromBuffer(b); b+=4;
00946      s_in_use=iMat[k].Shader[j].in_use=GetLongFromBuffer(b); b+=4;
00947      if(s_in_use){
00948        //{char ttt[256]; sprintf(ttt,"Material %ld Shader %ld in use active=%ld",k,j,iMat[k].Shader[j].bActive);
00949        // MessageBox(NULL,ttt,"Shader",MB_OK);}
00950        ln=GetLongFromBuffer(b); b+=4; // length of shader name string
00951        lp=GetLongFromBuffer(b); b+=4; // lenght of shader paramter string
00952        if(lp == 0 || ln == 0)MessageBox(NULL,"Inconsistent Material",NULL,MB_OK);
00953        if(ln > 0){
00954          if((iMat[k].Shader[j].xname=(char *)X__Malloc(ln+1)) == NULL)goto ERR;
00955          memcpy(iMat[k].Shader[j].xname,b,ln+1); b += (ln+1);
00956          if((iMat[k].Shader[j].parameters=(char *)X__Malloc(lp+1)) == NULL)goto ERR;
00957          memcpy(iMat[k].Shader[j].parameters,b,lp+1); b += (lp+1);
00958          //{char ttt[256]; sprintf(ttt,"Mat %ld Shader %ld - ln=%ld lp=%ld [%s] [%s]",k,j,ln,lp,
00959          //iMat[k].Shader[j].parameters,iMat[k].Shader[j].xname);
00960          //MessageBox(NULL,ttt,"Reading Shader",MB_OK);}
00961        }
00962      }
00963    }
00964    iMat[k].bSmooth = (BOOL)GetLongFromBuffer(b); b+=4;
00965    iMat[k].bShiny = (BOOL)GetLongFromBuffer(b); b+=4;
00966    iMat[k].bClear = (BOOL)GetLongFromBuffer(b); b+=4;
00967    iMat[k].bGlassEdge = (BOOL)GetLongFromBuffer(b); b+=4;
00968    iMat[k].bUseSurfaceMapping = (BOOL)GetLongFromBuffer(b); b+=4;
00969    for(j=0;j<16;j++){iMat[k].params[j] = (unsigned char)GetLongFromBuffer(b); b+=4;}
00970    for(j=0;j<16;j++){iMat[k].pad[j]=GetLongFromBuffer(b); b+=4;}  // padding
00971    if(id > 1){ // for material versions > 1
00972      memcpy(iMat[k].other_properties,b,512); b+= 512;
00973      sscanf(iMat[k].other_properties,"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
00974        &(iMat[k].mmw[0]),&(iMat[k].mmw[1]),&(iMat[k].mmw[2]),
00975        &(iMat[k].mmw[3]),&(iMat[k].mmw[4]),&(iMat[k].mmw[5]),
00976        &(iMat[k].mmw[6]),&(iMat[k].mmw[7]),&(iMat[k].mmw[8]),
00977        &(iMat[k].mmw[9]),&(iMat[k].mmw[10]),&(iMat[k].mmw[11]),
00978        &(iMat[k].mmw[12]),&(iMat[k].mmw[13]),&(iMat[k].mmw[14]));
00979      if(iMat[k].mmw[5] > 2.5)strcpy(iMat[k].mmw_brdf,&(iMat[k].other_properties[300])); //copy in BRDF file  
00980    }
00981    // end of read for this material
00982    if(relation == 1){ /* the material must be repositioned to new offset */
00983      iMat[k].ax.P[0] += NpointerX-TempAxis.Origin.xyz[0];
00984      iMat[k].ax.P[1] += NpointerY-TempAxis.Origin.xyz[1];
00985      iMat[k].ax.P[2] += NpointerZ-TempAxis.Origin.xyz[2];
00986      iMat[k].ax.X[0] += NpointerX-TempAxis.Origin.xyz[0];
00987      iMat[k].ax.X[1] += NpointerY-TempAxis.Origin.xyz[1];
00988      iMat[k].ax.X[2] += NpointerZ-TempAxis.Origin.xyz[2];
00989      iMat[k].ax.Y[0] += NpointerX-TempAxis.Origin.xyz[0];
00990      iMat[k].ax.Y[1] += NpointerY-TempAxis.Origin.xyz[1];
00991      iMat[k].ax.Y[2] += NpointerZ-TempAxis.Origin.xyz[2];
00992    }
00993  }
00994  // now fix up faces when adding to existing material list
00995  // check
00996  if(FaceBase > 0 && MainFp != NULL){
00997  //if(debug != NULL)fprintf(debug,"Fixing material %ld (%ld) faces  Before %ld materials Now %ld\n",Nface,FaceBase,ts,nMats);
00998   f=(MainFp+FaceBase); for(j=FaceBase;j<Nface;j++,f++){
00999     tid = f->material;          /* extract the mateiral id      */
01000     if(tid >= 0){
01001       tid += ts;               
01002       if(tid >= nMats)tid=0;   
01003       f->material=tid;         
01004     }
01005   }
01006  }
01007  X__Free(buffer);
01008  return;
01009  ERR:
01010  if(buffer != NULL)X__Free(buffer);
01011  MessageBox(NULL,"Bad Read Image Map",NULL,MB_OK);
01012  CloseHandle(fq);
01013  longjmp(j_buf,0);
01014 }
01015 
01016 // Save the MFX file  /////////////////////////////
01017 
01018 
01019 void SaveObject(char *Filename, short status){
01020   long pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,posB,
01021        posG,posH,pose,posIs,posIe,posMs,posMe,posXs,posXe,posVXs,posVXe;
01022   long i,FORMsize;
01023   HCURSOR hSave;
01024   short id;
01025   FORMsize=0; newvert=0; newface=0; newedge=0; newglue=0;
01026   /* status = 3 -> saving with - no extra display  save everything!! */
01027   /* status = 4 -> save as "1" but without file check                */
01028   if(status < 3){   /* no memory problem */
01029     if( (fo=fopen(Filename,"r")) != NULL){ /* check for old file */
01030       fclose(fo);
01031       if(SendPrgmQuery(IDQ_FILEEXISTS,1) != IDYES)return;
01032     }
01033   }
01034   if(status == 4)status=1;
01035   if( (fo=fopen(Filename,"wb")) == NULL){   /* now open for reading */
01036     SendPrgmQuery(IDQ_FILEOPENFAIL,0);
01037     return;
01038   }
01039   if(status < 2)SendPrgmMessage(IDS_SAVING,0);
01040   if(status < 3)hSave=SetCursor(ghcurWait);
01041   if(status == 1 || status == 3)EDIT_ACTION=NO;
01042   fprintf(fo,"FORM");
01043   pos1=ftell(fo); outlng(FORMsize);
01044   fprintf(fo,"OFXM");
01045   fprintf(fo,"AXIS"); outlng(48L); /* size of data chunk */
01046   if(status == 2){  /* dont use offset for rendering in triview */
01047     outlng(0); outlng(0); outlng(0);
01048   }
01049   else{
01050     outlng(ObjectAxis.Origin.xyz[0]);
01051     outlng(ObjectAxis.Origin.xyz[1]);
01052     outlng(ObjectAxis.Origin.xyz[2]);
01053   }
01054   for(i=0;i<9;i++)outlng(0);
01055   fprintf(fo,"OFFS"); outlng(16L);      /* follow point */
01056   outlng(3L);
01057   outlng(ObjectAxis.Offset.xyz[0]);
01058   outlng(ObjectAxis.Offset.xyz[1]);
01059   outlng(ObjectAxis.Offset.xyz[2]);
01060   pos2 = -1; if(Nvert > 0){
01061     fprintf(fo,"VERT"); pos2=ftell(fo); outlng(0L); /* filled in later */
01062     WriteVertices(status);
01063     if(newvert == 0){ // no vertices - so reset the file pointer
01064       fseek(fo,pos2-4,0);
01065     }
01066   }
01067   pos3 = -1; if(Nedge > 0 && newvert > 1){
01068     if(Nedge < 65536){
01069       fprintf(fo,"edge"); pos3=ftell(fo); outlng(0L); WriteEdges(TRUE);
01070     }
01071     else {
01072       fprintf(fo,"EDGE"); pos3=ftell(fo); outlng(0L); WriteEdges(FALSE);
01073     }
01074   }
01075   pos4 = -1; if(Nface > 0 && newvert > 2){
01076     fprintf(fo,"NFCE"); pos4=ftell(fo); outlng(0L); WriteFaces();
01077     if(newface == 0)fseek(fo,pos4-4,0); // no faces written so remove segment
01078   }
01079   posB = -1; if(Nvert > 0 && newvert > 0){
01080     fprintf(fo,"VTX2"); posB=ftell(fo); outlng(0L);
01081     WriteVertexMapping(status);
01082   }
01083   posXs = -1; if(Nface > 0 && newvert > 2 && newface > 1){
01084     fprintf(fo,"FTEX"); posXs=ftell(fo); outlng(0L); 
01085     WriteFaceMapping();
01086     posXe=ftell(fo);
01087   }
01088   posMs = -1; if(nMats > 0){
01089     //fprintf(fo,"MTL1"); posMs=ftell(fo); outlng(0L);
01090     fprintf(fo,"MTL2"); posMs=ftell(fo); outlng(0L);
01091     WriteMaterials();
01092     posMe=ftell(fo);
01093   }
01094   pos5 = -1; if(nImaps > 0){
01095     fprintf(fo,"IMA2"); pos5=ftell(fo); outlng(0L);
01096     WriteImageMaps();
01097     pos6=ftell(fo);
01098   }
01099   posIs = -1; if(nImaps > 0){
01100     fprintf(fo,"EMAP"); posIs=ftell(fo); outlng(0L);
01101     WriteEmbeddedImages();
01102     posIe=ftell(fo);
01103   } 
01104   pos7 = -1; if((status == 1 || status == 3) &&
01105       Nskel > 1){/* if saving whole object then save skeleton */
01106     fprintf(fo,"SK04"); pos7=ftell(fo); outlng(0L);
01107     WriteSkeleton();
01108     pos8=ftell(fo);
01109   }
01110   posVXs = -1; if(Nvert > 0 && newvert > 0){ // write out the vertex selection
01111     fprintf(fo,"VSEL"); posVXs=ftell(fo); outlng(0L);
01112     WriteVerticesSelection(status);
01113     posVXe=ftell(fo); 
01114   }
01115   fprintf(fo,"UNIT"); outlng((long)(7*sizeof(long)+8));
01116   outlng((long)ruler);
01117   fwrite(ruler_name,1,8,fo);
01118   outlng(lrulerx); outlng(lrulery); outlng(lrulerz);
01119   outlng(rulerx);  outlng(rulery);  outlng(rulerz);
01120   fprintf(fo,"GRID"); outlng((long)(2*sizeof(long)));
01121   outlng(grid_size); outlng(grid_size); /* second is unused */
01122   WriteWireframe();
01123   posH = -1; if(Nnurbs > 0){
01124     fprintf(fo,"NURB"); posH=ftell(fo); outlng(0);
01125     WriteNurbs(fo);
01126     posG=ftell(fo);
01127   }
01128   pose=ftell(fo);    /* the end of the object */
01129   // FIX UP the FILE lengths
01130   if(pos2 > 0){fseek(fo,pos2,0); outlng(12*newvert); }  // vertex chunk
01131   if(pos3 > 0){fseek(fo,pos3,0); // size of edge chunk 
01132     if(Nedge < 65536)outlng(4*newedge); else  outlng(8*newedge);
01133   }
01134   if(pos4   > 0){fseek(fo,pos4,0);   outlng(20*newface);}     // size of face chunk
01135   if(posB   > 0){fseek(fo,posB,0);   outlng(12*newglue);}     // Glue vertex coords
01136   if(pos5   > 0){fseek(fo,pos5,0);   outlng(pos6-pos5-4);}    /* image map !inc size */
01137   if(posMs  > 0){fseek(fo,posMs,0);  outlng(posMe-posMs-4);}  /* materials           */
01138   if(posIs  > 0){fseek(fo,posIs,0);  outlng(posIe-posIs-4);}  /* embedded images     */
01139   if(posXs  > 0){fseek(fo,posXs,0);  outlng(posXe-posXs-4);}  /* Face mapping coords */
01140   if(pos7   > 0){fseek(fo,pos7,0);   outlng(pos8-pos7-4);}    /* skeleton            */
01141   if(posH   > 0){fseek(fo,posH,0);   outlng(posG-posH-4);}    /* Nurbs surfaces      */
01142   if(posVXs > 0){fseek(fo,posVXs,0); outlng(posVXe-posVXs-4);}/* vertex selection    */
01143   fseek(fo,pos1,0); outlng(pose-8);
01144   fclose(fo);
01145   if(status < 2)SendPrgmMessage(IDS_CURRENT,0);
01146   if(status < 3)SetCursor(hSave);
01147   return;
01148 }
01149 
01150 static void WriteImageMaps(void){
01151  long i,temp,j;
01152  skel *sp;
01153  long v,zero=0;
01154  char n256[256];
01155  i=0;
01156  memset(n256,0,256);
01157  sp=FirstSp; while(sp != NULL){ /* set up sk id */
01158    sp->id=i; i++;
01159    sp=sp->next;
01160  }
01161  outlng((long)nImaps);
01162  for(i=0;i<nImaps;i++){
01163    outlng(iMap[i].P[0]); outlng(iMap[i].P[1]); outlng(iMap[i].P[2]);
01164    outlng(iMap[i].X[0]); outlng(iMap[i].X[1]); outlng(iMap[i].X[2]);
01165    outlng(iMap[i].Y[0]); outlng(iMap[i].Y[1]); outlng(iMap[i].Y[2]);
01166    temp=iMap[i].Type;    outlng(temp); for(j=0;j<3;j++)outlng(zero);
01167    temp=iMap[i].TypeR;   outlng(temp); for(j=0;j<3;j++)outlng(zero);  
01168    temp=iMap[i].TypeB;   outlng(temp); for(j=0;j<3;j++)outlng(zero);  
01169    temp=iMap[i].TypeT;   outlng(temp); for(j=0;j<3;j++)outlng(zero);
01170    temp=0; outlng(temp); // No skeleton attachment is recorded
01171    temp=iMap[i].Map; outlng(temp);   /* 0 = plane 1 = cyl. map  2/3 = moz */
01172    temp=iMap[i].Angle; outlng(temp); /* angle for cylinder brushes */
01173    // Locking is not stored any more
01174    temp=0; outlng(temp); outlng(temp); outlng(temp); outlng(temp);
01175    fwrite(iMap[i].N,1,32,fo);
01176    fwrite(&iMap[i].s,1,1,fo);
01177    fwrite(&iMap[i].r,1,1,fo);
01178    fwrite(&iMap[i].b,1,1,fo);
01179    fwrite(&iMap[i].t,1,1,fo);
01180    fwrite(&iMap[i].Key,1,1,fo);
01181    outsht(iMap[i].sp);
01182    outsht(iMap[i].rp);
01183    outsht(iMap[i].bp);
01184    outsht(iMap[i].tp);
01185    fwrite(iMap[i].d_colour,1,3,fo);
01186    fwrite(iMap[i].s_colour,1,3,fo);
01187    fwrite(iMap[i].a_colour,1,3,fo);
01188    fwrite(iMap[i].k_colour,1,3,fo);
01189    memset(n256,0,256); 
01190    if(iMap[i].s && iMap[i].S != NULL)sprintf(n256,"%s",iMap[i].S);
01191    fwrite(n256,1,256,fo);
01192    memset(n256,0,256); 
01193    if(iMap[i].r && iMap[i].R != NULL)sprintf(n256,"%s",iMap[i].R);
01194    fwrite(n256,1,256,fo);
01195    memset(n256,0,256); 
01196    if(iMap[i].b && iMap[i].B != NULL)sprintf(n256,"%s",iMap[i].B);
01197    fwrite(n256,1,256,fo);
01198    memset(n256,0,256);
01199    if(iMap[i].t && iMap[i].T != NULL)sprintf(n256,"%s",iMap[i].T);  
01200    fwrite(n256,1,256,fo);
01201    temp=(long)iMap[i].version;  outlng(temp);
01202    temp=(long)iMap[i].bDecal;   outlng(temp);
01203    temp=(long)iMap[i].bShaded;  outlng(temp);
01204    temp=(long)iMap[i].bTiled;   outlng(temp);
01205  }
01206 }
01207 
01208 static void  WriteEmbeddedImages(void){
01209  int i;
01210  outlng((long)nImaps);
01211  for(i=0;i<nImaps;i++){
01212    WriteRamImage((&iMap[i].si),fo);
01213    WriteRamImage((&iMap[i].ri),fo);
01214    WriteRamImage((&iMap[i].bi),fo);
01215    WriteRamImage((&iMap[i].ti),fo);
01216  } 
01217 }
01218 
01219 static void WriteMaterials(void){
01220  int j,k;
01221  long temp,ln,lp;
01222  outlng((long)nMats);  /* number of materials in this model */
01223  for(k=0;k<nMats;k++){
01224    temp=iMat[k].version; outlng(temp);
01225    fwrite(iMat[k].name,1,32,fo);
01226    fwrite(iMat[k].mcolour1,1,3,fo); 
01227    fwrite(iMat[k].mcolour2,1,3,fo); 
01228    fwrite(iMat[k].acolour,1,3,fo);
01229    fwrite(iMat[k].scolour,1,3,fo);
01230    fwrite(iMat[k].xcolour,1,3,fo);
01231    fwrite(iMat[k].ycolour,1,3,fo);
01232    fwrite(iMat[k].zcolour,1,3,fo);
01233    temp=(long)iMat[k].gloss; outlng(temp);
01234    temp=(long)iMat[k].refl; outlng(temp);
01235    temp=(long)iMat[k].transp; outlng(temp);
01236    temp=(long)iMat[k].refractive_index; outlng(temp);
01237    temp=(long)iMat[k].bInternalShader; outlng(temp);
01238    temp=(long)iMat[k].internalShaderID; outlng(temp);
01239    for(j=0;j<3;j++){temp=(long)iMat[k].ax.P[j]; outlng(temp);}
01240    for(j=0;j<3;j++){temp=(long)iMat[k].ax.X[j]; outlng(temp);}
01241    for(j=0;j<3;j++){temp=(long)iMat[k].ax.Y[j]; outlng(temp);}
01242    for(j=0;j<4;j++){
01243      temp=(long)iMat[k].Shader[j].version; outlng(temp);
01244      temp=(long)iMat[k].Shader[j].bActive; outlng(temp);
01245      temp=(long)iMat[k].Shader[j].in_use; outlng(temp);
01246      if(iMat[k].Shader[j].in_use){
01247        temp=ln=(long)strlen(iMat[k].Shader[j].xname); outlng(temp);
01248        temp=lp=(long)strlen(iMat[k].Shader[j].parameters); outlng(temp);
01249        fwrite(iMat[k].Shader[j].xname,1,ln+1,fo);
01250        fwrite(iMat[k].Shader[j].parameters,1,lp+1,fo);
01251        //{char ttt[256]; sprintf(ttt,"Mat %ld Shader %ld - ln=%ld lp=%ld [%s] [%s]",k,j,ln,lp,
01252        //iMat[k].Shader[j].parameters,iMat[k].Shader[j].xname);
01253        //MessageBox(NULL,ttt,"Shader",MB_OK);}
01254      }
01255    }
01256    temp=(long)iMat[k].bSmooth; outlng(temp);
01257    temp=(long)iMat[k].bShiny; outlng(temp);
01258    temp=(long)iMat[k].bClear; outlng(temp);
01259    temp=(long)iMat[k].bGlassEdge; outlng(temp);
01260    temp=(long)iMat[k].bUseSurfaceMapping; outlng(temp);
01261    for(j=0;j<16;j++){temp=(long)iMat[k].params[j]; outlng(temp);}
01262    for(j=0;j<16;j++){temp=(long)iMat[k].pad[j]; outlng(temp);}  // padding
01263    sprintf(iMat[k].other_properties,"%.3lf %.3lf %.3lf %.3lf %3lf %.3lf %.3lf %.3lf %.3lf %.5lf %.5lf %.3lf %.5lf %.5lf %.3lf",
01264        (iMat[k].mmw[ 0]),(iMat[k].mmw[ 1]),(iMat[k].mmw[ 2]),
01265        (iMat[k].mmw[ 3]),(iMat[k].mmw[ 4]),(iMat[k].mmw[ 5]),
01266        (iMat[k].mmw[ 6]),(iMat[k].mmw[ 7]),(iMat[k].mmw[ 8]),
01267        (iMat[k].mmw[ 9]),(iMat[k].mmw[10]),(iMat[k].mmw[11]),
01268        (iMat[k].mmw[12]),(iMat[k].mmw[13]),(iMat[k].mmw[14]));
01269    if(iMat[k].mmw[5] > 2.0)strcpy(&(iMat[k].other_properties[300]),iMat[k].mmw_brdf);   //copy in the BRDF filename
01270    else iMat[k].other_properties[300]=0;
01271    WriteByteBuffer(512,iMat[k].other_properties);  // for other material properties
01272  }
01273  return;
01274 }
01275 
01276 static void WriteVertices(short status){
01277  long i,j;
01278  vertex  *vp;
01279  i=0;
01280  vp=MainVp; for(j=0;j<Nvert;j++){
01281   if(status == 2){ /* for use in renderer */
01282     if(intriview(vp)){
01283       outlng(vp->xyz[0]); outlng(vp->xyz[1]); outlng(vp->xyz[2]);
01284       vp->id=i;
01285       i++; newvert++;
01286     }
01287     else vp->id = -1;
01288   }
01289   else if( (status==1) || (status == 3) || (vp->status==SELECTED) ){
01290     outlng(vp->xyz[0]); outlng(vp->xyz[1]); outlng(vp->xyz[2]);
01291     vp->id=i;
01292     i++; newvert++;
01293   }
01294   else vp->id = -1;
01295   vp++;
01296  }
01297 }
01298 
01299 static void WriteVerticesSelection(short status){
01300  long i,j;
01301  char t;
01302  vertex  *vp;
01303  i=0;
01304  vp=MainVp; for(j=0;j<Nvert;j++){
01305   if(status == 2){ /* for use in renderer */
01306     if(intriview(vp)){
01307       if(vp->status == SELECTED)t=0;
01308       else if(vp->status == DESELECTED)t=1;
01309       else if(vp->status == HIDDEN)t=2;
01310       fwrite(&t,1,1,fo);
01311       i++;
01312     }
01313     else vp->id = -1;
01314   }
01315   else if( (status==1) || (status == 3) || (vp->status==SELECTED) ){
01316     if(vp->status == SELECTED)t=0;
01317     else if(vp->status == DESELECTED)t=1;
01318     else if(vp->status == HIDDEN)t=2;
01319     fwrite(&t,1,1,fo);
01320     i++; 
01321   }
01322   vp++;
01323  }
01324 }
01325 
01326 
01327 static void WriteVertexMapping(short status){ // new structure - every vertex
01328  long j,i,ix,iy,temp;
01329  vertex *vp;
01330  i=0;
01331  vp=MainVp; for(j=0;j<Nvert;j++){
01332   if(status == 2){ /* for use in renderer */
01333     if(intriview(vp)){
01334       ix=(long)(vp->x * 1.0e6); iy=(long)(vp->y * 1.0e6);
01335       temp=(long)vp->gp; outlng(temp); outlng(ix); outlng(iy);
01336       newglue++;
01337       i++;
01338     }
01339   }
01340   else if( (status==1) || (status == 3) || (vp->status==SELECTED) ){
01341     ix=(long)(vp->x * 1.0e6); iy=(long)(vp->y * 1.0e6);
01342     temp=(long)vp->gp; outlng(temp); outlng(ix); outlng(iy);
01343     newglue++;
01344     i++;
01345   }
01346   vp++;
01347  }
01348 }
01349 
01350 static void WriteFaceMapping(void){
01351  face *f;
01352  long i,j,ix,iy,temp;
01353  vertex *V0,*V1,*V2;
01354  f=MainFp;
01355  for(i=0;i<Nface;i++){
01356    V0=(MainVp+f->V[0]); V1=(MainVp+f->V[1]); V2=(MainVp+f->V[2]);
01357    if((V0->id >= 0) &&
01358       (V1->id >= 0) &&
01359       (V2->id >= 0)){
01360      temp=(long)f->gp; outlng(temp); 
01361      for(j=0;j<3;j++){
01362        ix=(long)(f->x[j] * 1.0e6); iy=(long)(f->y[j] * 1.0e6); 
01363        outlng(ix); outlng(iy);
01364      }
01365    }
01366    f++;
01367  }
01368 }
01369 
01370 
01371 static void WriteEdges(BOOL short_form){
01372  unsigned short ids1,ids2;
01373  long i,idl1,idl2;
01374  edge *ep;
01375  vertex *V0,*V1;
01376  ep=MainEp;
01377  for(i=0;i<Nedge;i++){
01378    V0=(MainVp+ep->V[0]); V1=(MainVp+ep->V[1]);
01379    if((V0->id >= 0) && (V1->id >= 0)){
01380      if(short_form){
01381        ids1=(unsigned short)V0->id; ids2=(unsigned short)V1->id;
01382        outusht(ids1); outusht(ids2);
01383      }
01384      else{
01385        idl1=V0->id; idl2=V1->id;
01386        outlng(idl1); outlng(idl2);
01387      }
01388      newedge++;
01389    }
01390    ep++;
01391  }
01392 }
01393 
01394 static void WriteFaces(void){
01395  face *f;
01396  unsigned short ids;
01397  long i,idl;
01398  vertex *V0,*V1,*V2;
01399  f=MainFp;
01400  for(i=0;i<Nface;i++){
01401    V0=(MainVp+f->V[0]); V1=(MainVp+f->V[1]); V2=(MainVp+f->V[2]);
01402    if((V0->id >= 0) &&
01403       (V1->id >= 0) &&
01404       (V2->id >= 0)){
01405      idl=V0->id; outlng(idl);
01406      idl=V1->id; outlng(idl);
01407      idl=V2->id; outlng(idl);
01408      fwrite(f->color,1,3,fo);
01409      fwrite(&f->bSmooth,1,1,fo);
01410      outsht(f->material);
01411      outsht(f->imagemap);
01412      newface++;
01413    }
01414    f++;
01415  }
01416 }
01417 
01418 static void WriteSkeleton(void){
01419  long i,j;
01420  skel *sp;
01421  vertex *vp;
01422  long l;
01423  long k;
01424  i=0;
01425  sp=FirstSp; while(sp != NULL){
01426    sp->id=i; i++;
01427    sp=sp->next;
01428  }
01429  outlng(Nskel);
01430  sp=FirstSp; while(sp != NULL){
01431    outlng(sp->xyz[0]); outlng(sp->xyz[1]); outlng(sp->xyz[2]);
01432    if(sp->at != NULL)outlng(sp->at->id);
01433    else              outlng(0);
01434    fwrite(sp->name,sizeof(char),16,fo);
01435    l=(long)(sp->weight*1000.0); outlng(l);
01436    l=(long)(sp->wrange*1000.0); outlng(l);
01437    l=(long)(sp->wzone*1000.0); outlng(l);
01438    for(j=0;j<3;j++){l=(long)(sp->u[j]*1.0e8); outlng(l);}
01439    for(j=0;j<3;j++){l=(long)(sp->v[j]*1.0e8); outlng(l);}
01440    for(j=0;j<3;j++){l=(long)(sp->w[j]*1.0e8); outlng(l);}
01441    for(i=0;i<8;i++)for(j=0;j<3;j++)outlng(sp->bx[i][j]);
01442    sp=sp->next;
01443  }
01444  outlng(Nvert);
01445  vp=MainVp; for(k=0;k<Nvert;k++){
01446    if(vp->sp != NULL)outlng(vp->sp->id);
01447    else              outlng(0);
01448    vp++;
01449  }
01450 }
01451 
01452 static void WriteWireframe(void){
01453  long i;
01454  if(w_frame.Np == 0 || w_frame.Ne == 0)return;
01455  fprintf(fo,"WFRM");
01456  outlng((long)(((w_frame.Np*3)+(w_frame.Ne*2)+2)*sizeof(long)));
01457  outlng(w_frame.Np); outlng(w_frame.Ne);
01458  for(i=0;i<w_frame.Np;i++){
01459    outlng(w_frame.p[i][0]);
01460    outlng(w_frame.p[i][1]);
01461    outlng(w_frame.p[i][2]);
01462  }
01463  for(i=0;i<w_frame.Ne;i++){
01464    outlng(w_frame.e[i][0]); outlng(w_frame.e[i][1]);
01465  }
01466 }
01467 
01469 
01470 
01471 void LoadAApoly(int aa_or_not_aa, char *filename){  // loads paths
01472  FILE *fpp;
01473  long vp,vpf;
01474  short  fail,points,x,y,z,i;
01475  long xx,yy,zz;
01476  unsigned char closed,magic;
01477  long   packer;
01478  if((fpp=fopen(filename,"rb")) == NULL){
01479    SendPrgmQuery(IDQ_FILEOPENFAIL,0);
01480    return;
01481  }
01482  if(fread(&points,2,1,fpp) != 1)goto NOREAD;
01483  if(fread(&packer,4,1,fpp) != 1)goto NOREAD;
01484  if(fread(&closed,1,1,fpp) != 1)goto NOREAD;
01485  if(aa_or_not_aa){
01486    if(fread(&magic,1,1 ,fpp)  != 1 || magic != 0x99)goto NOREAD;
01487  }
01488  else{
01489    if(fread(&magic,1,1 ,fpp)  != 1 || magic != 0x88)goto NOREAD;
01490  }
01491  if(points == 0)goto NOREAD;
01492  if(!UpdateVertexHeap(Nvert+(long)points))goto NOREAD;
01493  if(!UpdateEdgeHeap(Nedge+(long)points+1))goto NOREAD;
01494  for(i=0; i< points; i++){
01495    if(aa_or_not_aa){
01496      if(fread(&x,2,1,fpp) != 1)goto NOREAD;
01497      if(fread(&y,2,1,fpp) != 1)goto NOREAD;
01498      if(fread(&z,2,1,fpp) != 1)goto NOREAD;
01499      vp=Nvert-1;
01500      CreateVertex();
01501      (MainVp+Nvert-1)->xyz[0] = ((long)x-160)*200;
01502      (MainVp+Nvert-1)->xyz[1] = 0;
01503      (MainVp+Nvert-1)->xyz[2] = ((long)y-100)*(-200);
01504    }
01505    else{
01506      if(fread(&xx,4,1,fpp) != 1)goto NOREAD;
01507      if(fread(&yy,4,1,fpp) != 1)goto NOREAD;
01508      if(fread(&zz,4,1,fpp) != 1)goto NOREAD;
01509      vp=Nvert-1;
01510      CreateVertex();
01511      (MainVp+Nvert-1)->xyz[0] = xx;
01512      (MainVp+Nvert-1)->xyz[1] = yy;
01513      (MainVp+Nvert-1)->xyz[2] = zz;
01514    }
01515    if(i > 0 && vp >= 0){
01516      CreateEdge(Nvert-1,vp);
01517    }
01518    else if(i == 0)vpf=Nvert-1;
01519  }
01520  if(closed == 1 && vpf >= 0)CreateEdge(vpf,Nvert-1);
01521  goto READOK;
01522  NOREAD:
01523  if(aa_or_not_aa)SendPrgmQuery(IDQ_NOTAAPROPATH,0);
01524  else            SendPrgmQuery(IDQ_NOTPATHFILE,0);
01525  READOK:
01526  fclose(fpp);
01527  UpdateVertexHeap(Nvert);
01528  UpdateEdgeHeap(Nedge);
01529  return;
01530 }
01531 
01532 void SavePath(void){
01533  vertex *Va;
01534  long *va;
01535  int a,id,Np;
01536  char closed;
01537  unsigned char magic;
01538  FILE *fpp;
01539  long Npath,packer=0,i;
01540  if((va=GetPathList(&Npath)) != NULL){
01541    a=MessageBox (ghwnd_main,"Save as Closed Path","Save Path",
01542                  MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL);
01543    if    (a == IDYES)id=1;
01544    else if(a == IDNO)id=0;
01545    else id = -1;
01546    if(id == 0 || id == 1){
01547      if(SelectSfxFileName(1,gszPTHfile,gszPTHdir,IDX_MISC_WRITEPATH,
01548         "(*.PTH)|*.pth|",ghwnd_main) == TRUE){
01549        AppendFileExtension(gszPTHfile,".pth");
01550        closed = (char)id;
01551        if((fpp=fopen(gszPTHfile,"wb")) == NULL){
01552          SendPrgmQuery(IDQ_FILEOPENFAIL,0);
01553          goto XXIT;
01554        }
01555        Np=(short)Npath;
01556        if(fwrite(&Np,2,1,fpp) != 1)goto NOWRITE;
01557        if(fwrite(&packer,4,1,fpp) != 1)goto NOWRITE;
01558        if(fwrite(&closed,1,1,fpp) != 1)goto NOWRITE;
01559        magic = 0x88;
01560        if(fwrite(&magic,1,1 ,fpp)  != 1)goto NOWRITE;
01561        if(Npath == 0)goto NOWRITE;
01562        for(i=0; i< Npath; i++){
01563          Va=(MainVp+va[i]);
01564          if(fwrite(&(Va->xyz[0]),4,1,fpp) != 1)goto NOWRITE;
01565          if(fwrite(&(Va->xyz[1]),4,1,fpp) != 1)goto NOWRITE;
01566          if(fwrite(&(Va->xyz[2]),4,1,fpp) != 1)goto NOWRITE;
01567        }
01568        goto READOK;
01569        NOWRITE:
01570        SendPrgmQuery(IDQ_SAVINGERROR,0);
01571        READOK:
01572        fclose(fpp);
01573      }
01574    }
01575    XXIT:
01576    X__Free(va);
01577    DrawVerticesOnly(NULL);
01578    UpdateCounters();
01579  }
01580  else{
01581    SendPrgmQuery(IDQ_NOPATHSTART,0);
01582  }
01583 }
01584 
01586 
01587 static long  Undo_Vertex = -1;
01588 static long  Undo_Edge   = -1;
01589 static long  Undo_Face   = -1;
01590 static short Undo_Active  = 0;
01591 static BOOL *Undo_Flag=NULL;
01592 
01593 void Save_Undo(short model){
01594   long sizz,i,j;
01595   vertex *vp;
01596   skel *sp;
01597   char workfile[128],*ud;
01598   EDIT_ACTION=YES;
01599   if(!UNDO_ON)return;
01600   Empty_Undo();
01601   if(Nvert == 0)return; 
01602   vp=MainVp; for(j=0;j<Nvert;j++){
01603     vp->status_undo=vp->status;  vp++;
01604   }
01605   if(model == 0){/* need only current numbers and statis flags */
01606     Undo_Vertex=Nvert;
01607     Undo_Edge=Nedge;
01608     Undo_Face=Nface;
01609     Undo_Active=1;
01610   }
01611   else if(model == 1){/* need to save position info as well */
01612     Undo_Vertex=Nvert;
01613     Undo_Edge=Nedge;
01614     Undo_Face=Nface;
01615     Undo_Active=2;
01616     vp=MainVp; for(j=0;j<Nvert;j++){
01617      memcpy(vp->xyz_undo,vp->xyz,3*sizeof(long)); // status already copied
01618      vp++;
01619     }
01620     if(Nskel > 0){
01621       sp=FirstSp; while(sp != NULL){
01622         VECCOPY(sp->xyz,sp->xyz_undo)
01623         for(j=0;j<8;j++)VECCOPY(sp->bx[j],sp->bx_undo[j])
01624         sp=sp->next;
01625       }
01626     }
01627   }
01628   else{  /* model = 2 use  temp device */
01629     sprintf(workfile,"%sundo_$.$$$",TempPath);
01630     if((fo=fopen(workfile,"wb")) == NULL){
01631       SendPrgmQuery(IDQ_NOUNDOSPACE,0);
01632       return;
01633     }
01634     if((Undo_Flag=(BOOL *)X__Malloc(Nvert*sizeof(BOOL))) != NULL){
01635       for(vp=MainVp,j=0;j<Nvert;j++,vp++)Undo_Flag[j]=vp->status;
01636     }
01637     newvert=0; newface=0; newedge=0; newglue=0;
01638     outlng(12*(long)Nvert);
01639     outlng(12*(long)Nvert);  // size of Vertex Mapping data
01640     outlng( 8*(long)Nedge);
01641     outlng(20*(long)Nface);  // number of bytes written
01642     outlng(   (long)Nskel);
01643     outlng(   (long)Nnurbs);
01644     outlng(28*(long)Nface);
01645     if(Nvert  > 0)WriteVertices(1);
01646     if(Nedge  > 0)WriteEdges(FALSE);
01647     if(Nface  > 0)WriteFaces();
01648     if(Nface  > 0)WriteFaceMapping();
01649     if(Nskel  > 1)WriteSkeleton();
01650     if(Nvert  > 0)WriteVertexMapping(1);
01651     if(Nnurbs > 0)WriteNurbs(fo);
01652     fclose(fo);
01653     Undo_Active=3;
01654   }
01655 }
01656 
01657 void Restore_Undo(void){
01658  short id;
01659  char workfile[128];
01660  long i,j,nv,ne,nf,ns,nn,ng,nm;
01661  vertex *vp;
01662  skel *sp;
01663  if(Undo_Active == 0){
01664    SendPrgmQuery(IDQ_NOUNDO,0);
01665    return;
01666  }
01667  else if(SelectedBrush >= 0 || SelectedShader >= 0){
01668    SendPrgmQuery(IDQ_UNDONOTREADY,0);
01669    return;
01670  }
01671  LastToolVertex= -1;    /* incase undo in middle of tool */
01672  if(Undo_Active < 3){   /* undo for extras or positions  */
01673     if(Nvert > Undo_Vertex){  /* get rid of effects of deleted vertices */
01674      vp=(MainVp+Undo_Vertex); for(i=Undo_Vertex;i<Nvert;i++){
01675        vp->status=SELECTED;
01676        vp++;
01677      }
01678      Delete_Bcurve(); Delete_MapLock();
01679    }
01680    UpdateVertexHeap(Undo_Vertex); Nvert=Undo_Vertex;
01681    UpdateEdgeHeap(Undo_Edge);     Nedge=Undo_Edge;
01682    UpdateFaceHeap(Undo_Face);     Nface=Undo_Face;
01683 }
01684 if(Undo_Active == 1){
01685    NvertSelect=0;  NvertDeselect=0; // restore and status
01686    if(Nvert > 0 && MainVp != NULL){
01687      vp=MainVp; for(i=0;i<Nvert;i++){
01688        vp->status=vp->status_undo;
01689        if(vp->status == SELECTED)NvertSelect++;
01690        else                      NvertDeselect++;
01691        vp++;
01692      }
01693    }
01694 }
01695 else if(Undo_Active == 2){
01696    NvertSelect=0;  NvertDeselect=0; // restore positions and status
01697    if(Nvert > 0 && MainVp != NULL){
01698      vp=MainVp; for(i=0;i<Nvert;i++){
01699        memcpy(vp->xyz,vp->xyz_undo,3*sizeof(long));
01700        vp->status=vp->status_undo;
01701        if(vp->status == SELECTED)NvertSelect++;
01702        else                      NvertDeselect++;
01703        vp++;
01704      }
01705    }
01706    if(Nskel > 0){
01707      sp=FirstSp; while(sp != NULL){
01708        VECCOPY(sp->xyz_undo,sp->xyz)
01709        for(j=0;j<8;j++)VECCOPY(sp->bx_undo[j],sp->bx[j])
01710        sp=sp->next;
01711      }
01712    }
01713  }
01714  else { /*  UNDO 3    off disk */
01715    sprintf(workfile,"%sundo_$.$$$",TempPath);
01716    fq=CreateFile(workfile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
01717       FILE_ATTRIBUTE_READONLY,(HANDLE)NULL);
01718    if(fq == INVALID_HANDLE_VALUE){
01719      SendPrgmQuery(IDQ_NOUNDOSPACE,0);
01720      Empty_Undo();
01721      return;
01722    }
01723    getlon(&nv);
01724    getlon(&ng);
01725    getlon(&ne);
01726    getlon(&nf);
01727    getlon(&ns);
01728    getlon(&nn);
01729    getlon(&nm);
01730    EraseAll(0);  /* erase all vertices faces edges nurbs and skeleton no redraw */
01731    if(nv > 0)ReadVertices(nv);
01732    if(ne > 0)ReadEdges(ne,FALSE);
01733    if(nf > 0)ReadFaces(nf);
01734    if(nm > 0)ReadFaceMapping(nm);
01735    if(ns > 1)ReadSkeleton(0L,3);  /* no size necessary */ 
01736    if(nv > 0)ReadVertexMapping(ng,1);
01737    if(nn > 0)ReadNurbs(0,0,fq);
01738    CloseHandle(fq);
01739    remove(workfile);
01740    NvertSelect=0;  NvertDeselect=0; 
01741    if(nv > 0 && Undo_Flag != NULL){
01742     for(vp=MainVp,j=0;j<Nvert;j++,vp++){
01743       vp->status=Undo_Flag[j];
01744       if(vp->status == SELECTED)NvertSelect++;
01745       else                      NvertDeselect++;
01746     }
01747    }
01748    if(Undo_Flag != NULL)X__Free(Undo_Flag);  Undo_Flag=NULL; 
01749  }
01750  Empty_Undo();
01751  DrawModel();
01752  UpdateCounters();
01753  if(tool > INZOOM)Save_Undo(1);
01754 }
01755 
01756 void Empty_Undo(void){
01757  char workfile[256];
01758  if(Undo_Active == 1 || Undo_Active == 2){
01759    Undo_Vertex = -1;
01760    Undo_Edge   = -1;
01761    Undo_Face   = -1;
01762  }
01763  else if(Undo_Active == 3){
01764    if(Undo_Flag != NULL)X__Free(Undo_Flag);  Undo_Flag=NULL; 
01765    sprintf(workfile,"%sundo_$.$$$",TempPath);
01766    remove(workfile);
01767  }
01768  Undo_Active=0;
01769 }
01770 
01772 #if 0
01773 static void ReadAndAddSkeleton(long clen, short version, short relaTion){  //  NOT USED NOW
01774   vertex *v;
01775   char c;
01776   long i,j,k,l,szz,n,x,y,z,nskel;
01777   skel *sp,**s,*RootSp;
01778   short dummy;
01779   long dummyl,ol[3]={0,0,0}; 
01780   getlon(&n);
01781   if(n == 0)return; nskel=n;
01782   if(nskel > 512){DumpSkeleton(nskel,clen); return;}
01783   szz=sizeof(skel *);
01784   s=(skel  **)X__Malloc((long)(szz*n));
01785   if(s == NULL){
01786     SendPrgmQuery(IDQ_NOMEM2,0);
01787     CloseHandle(fq);
01788     longjmp(j_buf,0);
01789   }
01790   if(relation == 1){ /* the brush must be repositioned to new offset */
01791     ol[0]=NpointerX-TempAxis.Origin.xyz[0]; // offsets
01792     ol[1]=NpointerY-TempAxis.Origin.xyz[1]; // offsets
01793     ol[2]=NpointerZ-TempAxis.Origin.xyz[2]; // offsets
01794   }
01795   CreateSkeleton(NULL);   // This is a root node for the new part, join it to the main Skeleton
01796   for(j=0;j<3;j++){getlon(&MainSp->xyz[j]);  MainSp->xyz[j] += ol[j];}
01797 
01798   if(version < 3){getsht(&dummy);  dummyl=(long)dummy;}
01799   else           {getlon(&dummyl);}
01800   if(dummyl < 0 || dummyl >= nskel){MainSp->id=0;}
01801   else MainSp->id = dummyl;
01802   if(version > 0){
01803     ReadFile(fq,MainSp->name,sizeof(char)*16,&dwRead,NULL);
01804   }
01805   if(version > 1){
01806     for(j=0;j<3;j++){getlon(&l); MainSp->u[j] = ((double)l)*1.0e-8;}
01807     for(j=0;j<3;j++){getlon(&l); MainSp->v[j] = ((double)l)*1.0e-8;}
01808     for(j=0;j<3;j++){getlon(&l); MainSp->w[j] = ((double)l)*1.0e-8;}
01809     for(j=0;j<8;j++)for(k=0;k<3;k++){getlon(&(MainSp->bx[j][k])); MainSp->bx[j][k] += ol[k]; } 
01810   }
01811   RootSp=MainSp;
01812   MainSp->at=FirstSp; 
01813   *s = MainSp;
01814   if(n > 1)for(i=1;i<n;i++){
01815     CreateSkeleton(NULL);
01816     for(j=0;j<3;j++){getlon(&MainSp->xyz[j]); MainSp->xyz[j] += ol[j]; }
01817     if(version < 3){getsht(&dummy); MainSp->id=(long)dummy;}
01818     else           {getlon(&dummyl); MainSp->id = dummyl;}
01819     if(version > 0){
01820       ReadFile(fq,MainSp->name,sizeof(char)*16,&dwRead,NULL);
01821     }
01822     if(version > 1){
01823       for(j=0;j<3;j++){getlon(&l); MainSp->u[j] = ((double)l)*1.0e-8;}
01824       for(j=0;j<3;j++){getlon(&l); MainSp->v[j] = ((double)l)*1.0e-8;}
01825       for(j=0;j<3;j++){getlon(&l); MainSp->w[j] = ((double)l)*1.0e-8;}
01826       for(j=0;j<8;j++)for(k=0;k<3;k++){getlon(&(MainSp->bx[j][k])); MainSp->bx[j][k] += ol[k]; }
01827     }
01828     *(s+i)=MainSp;
01829   }
01830   if((sp = RootSp->next) != NULL)while(sp != NULL){ /* fix up pointers */
01831     sp->at = *(s + (long)sp->id);
01832     sp=sp->next;
01833   }
01834   getlon(&n);
01835   if(n != newvert){
01836     SendPrgmQuery(IDQ_HERROR,0);
01837     for(i=0;i<n;i++){
01838       if(version < 3)getsht(&dummy);
01839       else           getlon(&dummyl);
01840     }
01841   }
01842   else{
01843     v=(MainVp+VertexBase);
01844     for(i=0;i<n;i++){
01845                 if(version < 3){getsht(&dummy); dummyl=(long)dummy;}   /* put into new vertex the pointer to the sk joint */
01846       else          getlon(&dummyl);
01847       if(dummyl > 0 && dummyl < nskel)v->sp = *(s+(long)dummyl);
01848       else                            v->sp = NULL;
01849       v++;
01850     }
01851   }
01852   X__Free(s);
01853 }
01854 #endif
01855 
01856 
01857 
01858 

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