UTILITY.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX - Modelling, Animation and Rendering Package
00003 -- */
00004 
00005 
00006 /* file UTILITY.C  utility files for the designer */
00007 
00008 // Include the code to generate the primitive shapes
00009 
00010 #define MODULE_UTILS 1
00011 
00012 #include "design.h"
00013 
00014 char *TruncateTextString(char *input, char *output, long length){
00015  if(strlen(input) < length)return input;
00016  strncpy(output,input,3); output[3]='\0';
00017  strcat(output,"....\\");
00018  strcat(output,FileInPath(input));
00019  if(strlen(output) > length)return FileInPath(input);
00020  return output;
00021 }
00022 
00023 static long VertexHeapSize=0,EdgeHeapSize=0,FaceHeapSize=0;
00024 
00036 void EraseAll(short what){  /* What = 1 = all  =0  VEFS only */
00037  char filename[MAX_DIR];
00038  long i,j;
00039  if(MainFp != NULL)X__Free(MainFp); MainFp=NULL;
00040  if(MainVp != NULL)X__Free(MainVp); MainVp=NULL;
00041  if(MainEp != NULL)X__Free(MainEp); MainEp=NULL;
00042  Nvert=0; Nface=0; Nedge=0; NvertSelect=0; NvertDeselect=0;
00043  VertexHeapSize=0,EdgeHeapSize=0,FaceHeapSize=0;
00044  if(Bcurves != NULL && N_Bcurves > 0){
00045    for(i=0;i<N_Bcurves;i++){
00046      if(Bcurves[i].Vc != NULL)X__Free(Bcurves[i].Vc);
00047      if(Bcurves[i].Vp != NULL)X__Free(Bcurves[i].Vp);
00048    }
00049    X__Free(Bcurves); Bcurves=NULL; N_Bcurves=0;
00050  }
00051  EraseAllSkeleton();
00052  EraseAllNurbs();
00053  if(what == 0)return;
00054  if(nImaps > 0){
00055    for(i=0;i<nImaps;i++){
00056      if(iMap[i].s && iMap[i].S != NULL)X__Free(iMap[i].S);
00057      iMap[i].S=NULL; iMap[i].s=0;
00058      if(iMap[i].r && iMap[i].R != NULL)X__Free(iMap[i].R);
00059      iMap[i].R=NULL; iMap[i].r=0;
00060      if(iMap[i].b && iMap[i].B != NULL)X__Free(iMap[i].B);
00061      iMap[i].B=NULL; iMap[i].b=0;
00062      if(iMap[i].t && iMap[i].T != NULL)X__Free(iMap[i].T);
00063      iMap[i].T=NULL; iMap[i].t=0;
00064      UnloadRamImage(&(iMap[i].si));
00065      UnloadRamImage(&(iMap[i].ri));
00066      UnloadRamImage(&(iMap[i].bi));
00067      UnloadRamImage(&(iMap[i].ti));
00068    }
00069    nImaps=0; nLockediMaps=0;
00070  }
00071  if(nMats > 0){ // need to free 
00072    for(i=0;i<nMats;i++)for(j=0;j<4;j++){
00073     if(iMat[i].Shader[j].in_use && iMat[i].Shader[j].parameters != NULL)X__Free(iMat[i].Shader[j].parameters);
00074     if(iMat[i].Shader[j].in_use && iMat[i].Shader[j].xname != NULL)X__Free(iMat[i].Shader[j].xname);
00075    }
00076  }
00077  nMats=0; 
00078  if(w_frame.p != NULL)X__Free(w_frame.p); w_frame.p=NULL; w_frame.Np=0;
00079  if(w_frame.e != NULL)X__Free(w_frame.e); w_frame.e=NULL; w_frame.Ne=0;
00080  ShadowFlag=NO;
00081  MirrorFlag = -1;
00082  CheckMenuItem(GetMenu(ghwnd_main),IDM_ATTRIBUTES_SHADOW,MF_UNCHECKED);
00083  ObjectAxis.Origin.xyz[0]=ObjectAxis.Origin.xyz[1]=ObjectAxis.Origin.xyz[2]=0;
00084  ObjectAxis.Offset.xyz[0]=ObjectAxis.Offset.xyz[1]=ObjectAxis.Offset.xyz[2]=0;
00085  GetTriview(TRUE);
00086  grid_size=UNIT;
00087  NpointerX=0; NpointerY=0; NpointerZ=0;
00088  sprintf(filename,"%sW_$.SCR",TempPath);
00089  remove(filename);
00090  sprintf(filename,"%sW_$.MFX",TempPath);
00091  remove(filename);
00092  EDIT_ACTION=NO;
00093 }
00094 
00095 void EraseAllSkeleton(void){
00096  skel *temps;
00097  long i;
00098  if(Nvert > 0)for(i=0;i<Nvert;i++){
00099    (MainVp+i)->sp=NULL;
00100  }
00101  while(MainSp != NULL)
00102  { temps=MainSp->last; X__Free(MainSp); MainSp=temps;
00103  } Nskel=0;
00104  CreateSkeleton(NULL); /* leave at least a root node for skeleton */
00105  FirstSp=MainSp;
00106  current_skeleton=FirstSp;
00107  FirstSp->xyz[0]=FirstSp->xyz[1]=FirstSp->xyz[2]=0;
00108  UpdateSkTreeView();
00109 }
00110 
00111 void Delete_Bcurve(void){
00112   long i,j,n,flag=1;
00113   long *v;
00114   vertex *Vp;
00115   if(Bcurves == NULL || N_Bcurves == 0)return;
00116   for(i=0;i<N_Bcurves;i++){
00117     Bcurves[i].flag=0;
00118     if((v=Bcurves[i].Vc) != NULL)for(j=0;j<Bcurves[i].Nc;j++){
00119       if(Vp->status == SELECTED){Bcurves[i].flag=1; flag=0; break;}
00120     }
00121     if((v=Bcurves[i].Vp) != NULL)for(j=0;j<Bcurves[i].Np;j++){
00122       Vp=(MainVp+v[j]);
00123       if(Vp->status == SELECTED){Bcurves[i].flag=1; flag=0; break;}
00124     }
00125   }
00126   if(flag)return;   /* nothing to delete */
00127   n=N_Bcurves-1;
00128   for(i=n;i>=0;i--){
00129     if(Bcurves[i].flag){
00130       if(Bcurves[i].Vc != NULL)X__Free(Bcurves[i].Vc);
00131       if(Bcurves[i].Vp != NULL)X__Free(Bcurves[i].Vp);
00132       if(i < N_Bcurves-1){ /* shift the list if necessary */
00133         for(j=i;j<N_Bcurves-1;j++){
00134           Bcurves[j].Nc = Bcurves[j+1].Nc; Bcurves[j].Vc = Bcurves[j+1].Vc;
00135           Bcurves[j].Np = Bcurves[j+1].Np; Bcurves[j].Vp = Bcurves[j+1].Vp;
00136           strcpy(Bcurves[j].name,Bcurves[j+1].name);
00137         }
00138       }
00139       N_Bcurves--;
00140     }
00141   }
00142   /* this will reduce memory so no need to check but do it anyway */
00143   Bcurves = (bezier_curve *)X__Realloc(Bcurves,sizeof(bezier_curve)*N_Bcurves);
00144   if(Bcurves == NULL)N_Bcurves=0; /* just silently loose everything */
00145   /* some RAM may be lost permanently but if Bcurves is NULL then we have */
00146   /* so little RAM left that we will have to close down anyway */
00147 }
00148 
00149 void Delete_MapLock(void){
00150  long i;
00151  vertex *vp0,*vp1,*vp2;
00152  if(nLockediMaps == 0)return;
00153  for(i=0;i<nImaps;i++){
00154    if(iMap[i].Lock){
00155      vp0=(MainVp+iMap[i].Vlock[0]);
00156      vp1=(MainVp+iMap[i].Vlock[1]);
00157      vp2=(MainVp+iMap[i].Vlock[2]);
00158      if(vp0->status == SELECTED ||
00159         vp1->status == SELECTED ||
00160         vp2->status == SELECTED){
00161        iMap[i].Lock=0;
00162        nLockediMaps--;
00163      }
00164    }
00165  }
00166  if(nLockediMaps < 0)nLockediMaps=0;
00167 }
00168 
00169 void RecalibrateMapLocks(void){
00170  long i,j;
00171  if(nLockediMaps == 0)return;
00172  for(i=0;i<nImaps;i++){
00173    if(iMap[i].Lock){
00174      for(j=0;j<3;j++){
00175        iMap[i].P[j] = (MainVp+iMap[i].Vlock[0])->xyz[j];
00176        iMap[i].X[j] = (MainVp+iMap[i].Vlock[1])->xyz[j];
00177        iMap[i].Y[j] = (MainVp+iMap[i].Vlock[2])->xyz[j];
00178      }
00179    }
00180  }
00181 }
00182 
00183 short EraseSkeleton(skel *thisone){
00184  skel *sp,*sptemp;
00185  if(thisone == FirstSp){ /* cannot delete the main node */
00186    SendPrgmQuery(IDQ_NODELETESKROOT,0);
00187    return 0;
00188  }
00189 // NB this will be needed later         thisone->at->offset=0;
00190  current_skeleton=thisone->at;
00191  sp=MainSp;
00192  while(sp != NULL){ /* reset any bones attached to this one */
00193    if(sp->at == thisone)sp->at = thisone->at;
00194    sp=sp->last;
00195  }
00196  sp=MainSp;
00197  while(sp != NULL){
00198    if(sp == thisone){ /* delete this bone */
00199      if(sp == MainSp){
00200        MainSp=sp->last;
00201        if(MainSp != NULL)MainSp->next=NULL;
00202        X__Free(sp); sp=MainSp;
00203      }
00204      else{
00205        (sp->next)->last=sp->last;
00206        if(sp->last != NULL)(sp->last)->next=sp->next;
00207        sptemp=sp->last;
00208        X__Free(sp);
00209        sp=sptemp;
00210      }
00211      Nskel--;
00212      return 1;
00213    }
00214    sp=sp->last;
00215  }
00216  return 0;
00217 }
00218 
00219 int EraseEdge(int mem_update){
00220  int idid=NO;
00221  long  i,NewC;
00222  face *fp;
00223  edge *ep;
00224  vertex *V0,*V1,*V2;
00225  NewC=Nface; fp=MainFp; if(MainFp != NULL)for(i=0;i<Nface;i++){
00226    V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00227    if(  (V0->status == SELECTED && V1->status == SELECTED)
00228       ||(V1->status == SELECTED && V2->status == SELECTED)
00229       ||(V2->status == SELECTED && V0->status == SELECTED) ){
00230      if(i < Nface-1)CopyMemory(fp,(MainFp+NewC-1),sizeof(face));
00231      NewC--;
00232    }
00233    else fp++;
00234  }
00235  if(NewC != Nface){
00236    idid=YES;
00237    Nface=NewC;
00238    if(mem_update)UpdateFaceHeap(Nface);
00239  }
00240  NewC=Nedge; ep=MainEp; if(MainEp != NULL)for(i=0;i<Nedge;i++){
00241    V0=(MainVp+ep->V[0]); V1=(MainVp+ep->V[1]);
00242    if(V0->status == SELECTED  && V1->status == SELECTED){
00243      if(i < Nedge-1)CopyMemory(ep,(MainEp+NewC-1),sizeof(edge));
00244      NewC--;
00245    }
00246    else ep++;
00247  }
00248  if(NewC != Nedge){
00249    idid=YES;
00250    Nedge=NewC;
00251    if(mem_update)UpdateEdgeHeap(Nedge);
00252  }
00253  return idid;
00254 }
00255 
00256 int EraseVertex(int mem_update){
00257  int idid=NO;
00258  long  i,k,NewC;
00259  vertex *vp,*vo;
00260  face   *fp;
00261  edge   *ep;
00262  vertex *V0,*V1,*V2;
00263  NewC=Nface; fp=MainFp; if(MainFp != NULL)for(i=0;i<Nface;i++){
00264    V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00265    if(   V0->status == SELECTED
00266       || V1->status == SELECTED
00267       || V2->status == SELECTED ){
00268      if(i < Nface-1)CopyMemory(fp,(MainFp+NewC-1),sizeof(face));
00269      NewC--;
00270    }
00271    else fp++;
00272  }
00273  if(NewC != Nface){
00274    idid=YES;
00275    Nface=NewC;
00276    if(mem_update)UpdateFaceHeap(Nface);
00277  }
00278  NewC=Nedge; ep=MainEp; if(MainEp != NULL)for(i=0;i<Nedge;i++){
00279    V0=(MainVp+ep->V[0]); V1=(MainVp+ep->V[1]);
00280    if(V0->status == SELECTED  || V1->status == SELECTED){
00281      if(i < Nedge-1)CopyMemory(ep,(MainEp+NewC-1),sizeof(edge));
00282      NewC--;
00283    }
00284    else ep++;
00285  }
00286  if(NewC != Nedge){
00287    idid=YES;
00288    Nedge=NewC;
00289    if(mem_update)UpdateEdgeHeap(Nedge);
00290  }
00291  Delete_Bcurve(); Delete_MapLock();
00292  NewC=Nvert; vp=MainVp; if(MainVp != NULL)for(i=0,k=0;i<Nvert;i++){
00293    if(vp->status == SELECTED){
00294      NvertSelect--;
00295      if(i < Nvert-1){
00296        vo=(MainVp+NewC-1);
00297        CopyMemory(vp,vo,sizeof(vertex));
00298        vo->id=k; /* indicate where moved vertex is going */
00299      }
00300      NewC--;
00301    }
00302    else {
00303      vp++; k++;
00304    }
00305  }
00306  if(NewC != Nvert){
00307    idid=YES;
00308    Nvert=NewC;
00309    /* re-vector the face/edge data structures */
00310    if(Nface > 0 && MainFp != NULL)for(i=0,fp=MainFp;i<Nface;i++,fp++){
00311      if(fp->V[0] >= Nvert)fp->V[0]=(MainVp+fp->V[0])->id;
00312      if(fp->V[1] >= Nvert)fp->V[1]=(MainVp+fp->V[1])->id;
00313      if(fp->V[2] >= Nvert)fp->V[2]=(MainVp+fp->V[2])->id;
00314    }
00315    if(Nedge > 0 && MainEp != NULL)for(i=0,ep=MainEp;i<Nedge;i++,ep++){
00316      if(ep->V[0] >= Nvert)ep->V[0]=(MainVp+ep->V[0])->id;
00317      if(ep->V[1] >= Nvert)ep->V[1]=(MainVp+ep->V[1])->id;
00318    }
00319    if(mem_update)UpdateVertexHeap(Nvert);
00320  }
00321  return idid;
00322 }
00323 
00324 void EraseVertexMapping(void){
00325  int i;
00326  vertex *vp;
00327  if(MainVp != NULL && Nvert > 0)for(vp=MainVp,i=0;i<Nvert;i++,vp++){
00328    if(vp->gp == 1){
00329      vp->gp = 0;
00330    }
00331  }
00332 }
00333 
00334 void CreateEdge(long v1, long v2){
00335 if(Nedge+1 > EdgeHeapSize)MessageBeep(MB_OK);
00336  if(Nedge+1 > EdgeHeapSize)UpdateEdgeHeap(Nedge+1);
00337  (MainEp+Nedge)->V[0]=v1;
00338  (MainEp+Nedge)->V[1]=v2;
00339  Nedge++;
00340 }
00341 
00342 void CreateFace(long v1, long v2, long v3){
00343  face  *temp;
00344 if(Nface+1 > FaceHeapSize)MessageBeep(MB_OK);
00345  if(Nface+1 > FaceHeapSize)UpdateFaceHeap(Nface+1);
00346  temp=(MainFp+Nface);
00347  temp->V[0]=v1;
00348  temp->V[1]=v2;
00349  temp->V[2]=v3;
00350  temp->color[0]=FaceColour[0];
00351  temp->color[1]=FaceColour[1];
00352  temp->color[2]=FaceColour[2];
00353  temp->imagemap=-1;
00354  temp->material=-1;
00355  temp->gp=FALSE;
00356  temp->x[0]=temp->x[1]=temp->x[2]=0.0; 
00357  temp->y[0]=temp->y[1]=temp->y[2]=0.0;
00358  temp->bSmooth=FALSE;
00359  Nface++;
00360 }
00361 
00362 void CreateVertex(void){
00363  vertex  *temp;
00364 if(Nvert+1 > VertexHeapSize)MessageBeep(MB_OK);
00365  if(Nvert+1 > VertexHeapSize)UpdateVertexHeap(Nvert+1);
00366  temp=(MainVp+Nvert);
00367  temp->xyz[0]=NpointerX;
00368  temp->xyz[1]=NpointerY;
00369  temp->xyz[2]=NpointerZ;
00370  temp->status=SELECTED;
00371  temp->sp =  NULL;
00372  temp->gp = 0;
00373  temp->x=0.0; temp->y=0.0;
00374  Nvert++;
00375  NvertSelect++;
00376 }
00377 
00378 BOOL UpdateVertexHeap(long n){
00379  vertex *temp;
00380  if(n == VertexHeapSize)return TRUE;
00381  if(n == 0){
00382    if(MainVp != NULL)X__Free(MainVp);
00383    temp=NULL;
00384  }
00385  else if(VertexHeapSize == 0){
00386    if((temp=(vertex *)X__Malloc(n*sizeof(vertex))) == NULL)longjmp(j_buf,0);
00387  }
00388  else{
00389    if((temp=(vertex *)X__Realloc(MainVp,n*sizeof(vertex))) == NULL)longjmp(j_buf,0);
00390  }
00391  MainVp=temp;
00392  VertexHeapSize=n;
00393  return TRUE;
00394 }
00395 
00396 BOOL UpdateEdgeHeap(long n){
00397  edge *temp;
00398  if(n == EdgeHeapSize)return TRUE;
00399  if(n == 0){
00400    if(MainEp != NULL)X__Free(MainEp);
00401    temp=NULL;
00402  }
00403  else if(EdgeHeapSize == 0){
00404    if((temp=(edge *)X__Malloc(n*sizeof(edge))) == NULL)longjmp(j_buf,0);
00405  }
00406  else{
00407    if((temp=(edge *)X__Realloc(MainEp,n*sizeof(edge))) == NULL)longjmp(j_buf,0);
00408  }
00409  MainEp=temp;
00410  EdgeHeapSize=n;
00411  return TRUE;
00412 }
00413 
00414 BOOL UpdateFaceHeap(long n){
00415  face *temp;
00416  if(n == FaceHeapSize)return TRUE;
00417  if(n == 0){
00418    if(MainFp != NULL)X__Free(MainFp);
00419    temp=NULL;
00420  }
00421  else if(FaceHeapSize == 0){
00422    if((temp=(face *)X__Malloc(n*sizeof(face))) == NULL)longjmp(j_buf,0);
00423  }
00424  else{
00425    if((temp=(face *)X__Realloc(MainFp,n*sizeof(face))) == NULL)longjmp(j_buf,0);
00426  }
00427  MainFp=temp;
00428  FaceHeapSize=n;
00429  return TRUE;
00430 }
00431 
00432 void CreateSkeleton(skel *at){
00433  skel *temp;
00434  int i,j;
00435  if(( temp=(skel *)X__Malloc(sizeof(skel)) ) == NULL)longjmp(j_buf,0);
00436  if(MainSp != NULL)MainSp->next=temp;
00437  temp->last=MainSp;
00438  temp->xyz[0]=NpointerX;
00439  temp->xyz[1]=NpointerY;
00440  temp->xyz[2]=NpointerZ;
00441  temp->next=NULL;
00442  temp->at=at;
00443  temp->id=0;
00444  temp->offset=0;
00445  temp->weight=1.0;
00446  temp->wrange=1.0;
00447  temp->wzone=0.1;
00448  temp->u[0]=1.0; temp->u[1]=0.0; temp->u[2]=0.0;
00449  temp->v[0]=0.0; temp->v[1]=1.0; temp->v[2]=0.0;
00450  temp->w[0]=0.0; temp->w[1]=0.0; temp->w[2]=1.0;
00451  temp->lParam=0; /* used as user available data */
00452  for(i=0;i<8;i++){
00453    temp->bx[i][0]=NpointerX;
00454    temp->bx[i][1]=NpointerY;
00455    temp->bx[i][2]=NpointerZ;
00456  }
00457  for(i=0;i<4;i++)for(j=0;j<4;j++){
00458    temp->t[i][j]=0.0;
00459    if(i == j)temp->t[i][j]=1.0;
00460  }
00461  MainSp=temp;
00462  Nskel++;
00463  if(Nskel == 1)strcpy(temp->name,"Root");
00464  else sprintf(temp->name,"%ld",Nskel-1);
00465 }
00466 
00467 short intriview(vertex  *vp){
00468  if(vp->status == HIDDEN)return 0;
00469  if( ((vp->xyz[0] > TVpointX) && (vp->xyz[0] < TVpointX+TVsizeX))
00470   && ((vp->xyz[1] > TVpointY) && (vp->xyz[1] < TVpointY+TVsizeY))
00471   && ((vp->xyz[2] > TVpointZ) && (vp->xyz[2] < TVpointZ+TVsizeZ))
00472    )return 1;
00473  return 0;
00474 }
00475 
00476 int EraseIndicatedEdge(void){
00477  int i,sh1,sh2,sv1,sv2,npx,npy;
00478  double x,y,z,mu,a,b,c,d,dmin;
00479  edge     *ep,*epid;
00480  vertex   *vp,*vp1,*vp2;
00481  if(Nedge == 0 || MainEp == NULL || MainVp == NULL)return NO;
00482  dmin=(double)TVsizeX*(double)TVsizeX;
00483  epid=NULL;
00484  for(ep=MainEp,i=0;i<Nedge;i++,ep++){
00485    vp1=(MainVp+ep->V[0]); vp2=(MainVp+ep->V[1]);
00486    if(intriview(vp1) || intriview(vp2)){
00487      GetWindowCoords(ActiveView,
00488                      vp1->xyz[0],vp1->xyz[1],vp1->xyz[2],&sh1,&sv1);
00489      GetWindowCoords(ActiveView,
00490                      vp2->xyz[0],vp2->xyz[1],vp2->xyz[2],&sh2,&sv2);
00491      a=(double)(sh2-sh1); b=(double)(sv2-sv1);
00492      GetWindowCoords(ActiveView,
00493                      NpointerX,NpointerY,NpointerZ,&npx,&npy);
00494      if((sh2-sh1) != 0 ||  (sv2-sv1) != 0){
00495        x=(double)npx; y=(double)npy;
00496        mu=(a*(x-(double)sh1) + b*(y-(double)sv1))/(a*a+b*b);
00497        if(mu > 0.0001 && mu < 0.9999){
00498          x=a*mu+(double)sh1; y=b*mu+(double)sv1;
00499          sh1=(short)x; sv1=(short)y;
00500          if(abs(npx-sh1) < 3 && abs(npy-sv1) < 3){/* in 2D range */
00501            a=(double)(vp2->xyz[0]-vp1->xyz[0]);
00502            b=(double)(vp2->xyz[1]-vp1->xyz[1]);
00503            c=(double)(vp2->xyz[2]-vp1->xyz[2]);
00504            mu=(a*((double)NpointerX-(double)(vp1->xyz[0]))
00505               +b*((double)NpointerY-(double)(vp1->xyz[1]))
00506               +c*((double)NpointerZ-(double)(vp1->xyz[2])))/(a*a+b*b+c*c);
00507            x=a*mu+(double)(vp1->xyz[0]);
00508            y=b*mu+(double)(vp1->xyz[1]);
00509            z=c*mu+(double)(vp1->xyz[2]);
00510            d=(x-(double)NpointerX)*(x-(double)NpointerX)
00511             +(y-(double)NpointerY)*(y-(double)NpointerY)
00512             +(z-(double)NpointerZ)*(z-(double)NpointerZ);
00513            if(d < dmin){/* closest in 3D */
00514              dmin=d;
00515              epid=ep;
00516            }
00517          }
00518        }
00519      }
00520    }
00521  }
00522  if(epid == NULL)return NO;
00523  vp1=(MainVp+epid->V[0]); vp2=(MainVp+epid->V[1]);
00524  sh1=(int)vp1->status; sh2=(int)vp2->status;
00525  for(i=0,vp=MainVp;i<Nvert;i++){
00526    if(vp->status == SELECTED)vp->status = INEDITOR;
00527    vp++;
00528  }
00529  vp1->status=SELECTED;
00530  vp2->status=SELECTED;
00531  EraseEdge(1);
00532  for(i=0,vp=MainVp;i<Nvert;i++){
00533    if(vp->status == INEDITOR)vp->status = SELECTED;
00534    vp++;
00535  }
00536  vp1->status=(unsigned char)sh1; vp2->status=(unsigned char)sh2;
00537  return YES;
00538 }
00539 
00540 int EraseIndicatedVertex(void){
00541  vertex *vp,*vps;
00542  double d,dmin;
00543  int i,sho,svo,npx,npy;
00544  if(Nvert == 0 || MainVp == NULL)return NO;
00545  dmin=(double)TVsizeX*(double)TVsizeX;
00546  vps=NULL;
00547  GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&npx,&npy);
00548  for(vp=MainVp,i=0;i<Nvert;i++,vp++){
00549    if(intriview(vp)){
00550      GetWindowCoords(ActiveView,vp->xyz[0],vp->xyz[1],vp->xyz[2],&sho,&svo);
00551      if( (sho > npx-4) && (sho < npx+4)
00552       && (svo > npy-4) && (svo < npy+4)){
00553        d=(double)(vp->xyz[0]-NpointerX)*(double)(vp->xyz[0]-NpointerX)
00554         +(double)(vp->xyz[1]-NpointerY)*(double)(vp->xyz[1]-NpointerY)
00555         +(double)(vp->xyz[2]-NpointerZ)*(double)(vp->xyz[2]-NpointerZ);
00556        if(d < dmin){
00557          dmin=d;
00558          vps=vp;
00559        }
00560      }
00561    }
00562  }
00563  if(vps == NULL)return NO;
00564  if(vps->status==DESELECTED){NvertDeselect--; NvertSelect++;}
00565  for(vp=MainVp,i=0;i<Nvert;i++,vp++){
00566   if(vp->status == SELECTED)vp->status = INEDITOR;
00567  }
00568  vps->status=SELECTED;
00569  EraseVertex(1);
00570  if(MainVp == NULL || Nvert == 0)return YES;
00571  for(vp=MainVp,i=0;i<Nvert;i++,vp++){
00572    if(vp->status == INEDITOR)vp->status = SELECTED;
00573  }
00574  return YES;
00575 }
00576 
00577 BOOL CheckFaceExists(long v1, long v2, long v3, long limit){
00578  long i;
00579  face *fp;
00580  if(Nface == 0)return FALSE;
00581  fp=(MainFp+Nface-1); for(i=Nface-1;i>=limit;i--){
00582    if(   ((fp->V[0] == v1) && (fp->V[1] == v2) && (fp->V[2] == v3))
00583       || ((fp->V[0] == v1) && (fp->V[1] == v3) && (fp->V[2] == v2))
00584       || ((fp->V[0] == v2) && (fp->V[1] == v3) && (fp->V[2] == v1))
00585       || ((fp->V[0] == v2) && (fp->V[1] == v1) && (fp->V[2] == v3))
00586       || ((fp->V[0] == v3) && (fp->V[1] == v1) && (fp->V[2] == v2))
00587       || ((fp->V[0] == v3) && (fp->V[1] == v2) && (fp->V[2] == v1))
00588      )return TRUE;
00589    fp--;
00590  }
00591  return FALSE;
00592 }
00593 
00594 BOOL CheckEdgeExists(long v1, long v2, long limit){
00595  int i;
00596  edge *ep;
00597  if(Nedge == 0)return FALSE;
00598  ep=(MainEp+Nedge-1); for(i=Nedge-1;i>=limit;i--){
00599    if(   ((ep->V[0] == v1) && (ep->V[1] == v2))
00600       || ((ep->V[0] == v2) && (ep->V[1] == v1)) )return TRUE;
00601 
00602    ep--;
00603  }
00604  return FALSE;
00605 }
00606 
00607 void CopyFaceProp(face *fin, face *fout){
00608   fout->color[0] = fin->color[0];
00609   fout->color[1] = fin->color[1];
00610   fout->color[2] = fin->color[2];
00611   fout->bSmooth = fin->bSmooth;
00612   fout->material=fin->material;
00613   fout->imagemap=fin->imagemap;
00614   fout->gp=fin->gp;
00615   fout->x[0]=fin->x[0]; fout->y[0]=fin->y[0];
00616   fout->x[1]=fin->x[1]; fout->y[1]=fin->y[1];
00617   fout->x[2]=fin->x[2]; fout->y[2]=fin->y[2];
00618 }
00619 
00620 int IdentifyIndicatedFace(void){
00621  int i,sh1,sh2,sv1,sv2,sh3,sv3,npx,npy,shmin,shmax,svmin,svmax;
00622  double dv1[2],dv2[2],dv3[2];
00623  double l,dv12,dv23,dv31,t1,t2,t3,ta;
00624  face     *fp;
00625  vertex   *vp,*vp1,*vp2,*vp3;
00626  if(Nface == 0 || MainFp == NULL || MainVp == NULL)return -1;
00627  //dmin=(double)TVsizeX*(double)TVsizeX;
00628  for(fp=MainFp,i=0;i<Nface;i++,fp++){
00629    vp1=(MainVp+fp->V[0]); vp2=(MainVp+fp->V[1]); vp3=(MainVp+fp->V[2]);
00630    if(intriview(vp1) && intriview(vp2) && intriview(vp3) &&
00631       vp1->status == SELECTED && vp2->status == SELECTED && vp3->status == SELECTED){
00632      GetWindowCoords(ActiveView,
00633                      vp1->xyz[0],vp1->xyz[1],vp1->xyz[2],&sh1,&sv1);
00634      GetWindowCoords(ActiveView,
00635                      vp2->xyz[0],vp2->xyz[1],vp2->xyz[2],&sh2,&sv2);
00636      GetWindowCoords(ActiveView,
00637                      vp3->xyz[0],vp3->xyz[1],vp3->xyz[2],&sh3,&sv3);
00638      GetWindowCoords(ActiveView,
00639                      NpointerX,NpointerY,NpointerZ,&npx,&npy);
00640      shmin=min(sh1,min(sh2,sh3));
00641      shmax=max(sh1,max(sh2,sh3));
00642      svmin=min(sv1,min(sv2,sv3));
00643      svmax=max(sv1,max(sv2,sv3));
00644      if(npx > shmin && npx < shmax && npy > svmin && npy < svmax){ // inside face bounding box
00645        // determine if vectors from cursor to vertices have any angle > 90 => inside
00646        dv1[0]=(double)sh1-(double)npx; dv1[1]=(double)sv1-(double)npy;
00647        dv2[0]=(double)sh2-(double)npx; dv2[1]=(double)sv2-(double)npy;
00648        dv3[0]=(double)sh3-(double)npx; dv3[1]=(double)sv3-(double)npy;
00649        l=sqrt(DOT2(dv1,dv1)); dv1[0] /= l; dv1[1] /= l;
00650        l=sqrt(DOT2(dv2,dv2)); dv2[0] /= l; dv2[1] /= l;
00651        l=sqrt(DOT2(dv3,dv3)); dv3[0] /= l; dv3[1] /= l;
00652        dv12=DOT2(dv2,dv1); t1=acos(dv12)*180.0/PI;
00653        dv23=DOT2(dv3,dv2); t2=acos(dv23)*180.0/PI;
00654        dv31=DOT2(dv1,dv3); t3=acos(dv31)*180.0/PI;
00655        ta=t1+t2+t3; 
00656        //{char ttt[256]; sprintf(ttt,"Inside face box=%ld (%4.1lf %4.1lf %4.1lf ) [%6.1lf]",i,t1,t2,t3,ta); MessageBox(NULL,ttt,"Testing",MB_OK);}
00657        if(ta > 359.8)return i;
00658      }
00659    }
00660  }
00661  return -1;
00662 }
00663 
00664 
00665 // Primitive creation code
00666 
00667 static void Line(void);
00668 static void Helix(int);
00669 static void Plot3D(void);
00670 static BOOL MakeLatLongSphere(long, long, long);
00671 static BOOL MakeTorus(long, long, double, long);
00672 
00673 static short LastNumberSides=12;
00674 
00675 void SpecialFunction(int item){
00676  switch(item){
00677    case IDM_ACTIONS_SPECIAL_3DPLOT:    Plot3D(); break;
00678    case IDM_ACTIONS_SPECIAL_HELIX:     Helix(0); break;
00679    case IDM_ACTIONS_SPECIAL_SPIRAL:    Helix(1); break;
00680    case IDM_ACTIONS_SPECIAL_3DSPIRAL:  Helix(2); break;
00681    case IDM_ACTIONS_SPECIAL_LINE:      Line();   break;
00682    case IDM_ACTIONS_SPECIAL_BUTTERFLY:
00683      AddPolygon(0,TVsizeX/4,ActiveView);  // Added /4
00684      DrawModel();
00685      break;
00686    default: break;
00687  }
00688  UpdateCounters();
00689 }
00690 
00691 static void Helix(int choice){/* 0 = Helix. 1 = Spiral. 2 = 3D Spiral */
00692  struct np {int type,n,r;} d;
00693  double fx, fy, alpha, radius=2000.00;
00694  vertex  *Vp=NULL;
00695  int range,i,spiral=0,Npoints;
00696  if((double)TVsizeX / (double)4000 <= 1.00) {
00697    SendPrgmQuery(IDQ_SCALETOOSMALL,0);
00698    return;
00699  }
00700  if(choice == 1 || choice == 2) {
00701    d.type=spiral;
00702    d.n=20;
00703    d.r=500;
00704    if(DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_SPIRAL),ghwnd_main,
00705             (DLGPROC)SpiralsDlgProc,(LPARAM)&d) != OK)return;
00706    spiral=d.type;
00707    Npoints=d.n;
00708    range=d.r;
00709  }
00710  else{ /* choice = 0  Helices  range 800 */
00711    Npoints=RequestNumEntry(20,5,90,"No of Vertices"," Vertices");
00712    range=800;
00713  }
00714  if(Npoints <= 0)return;
00715  if(!UpdateVertexHeap(Nvert+Npoints)){
00716    SendPrgmQuery(IDQ_NOMEM2,0);
00717    return;
00718  }
00719  if(!UpdateEdgeHeap(Nedge+Npoints-1)){
00720    SendPrgmQuery(IDQ_NOMEM2,0);
00721    return;
00722  }
00723  for(i=0;i<Npoints;i++) {
00724    alpha=(range/Npoints)*i;
00725    alpha=alpha*0.0175;
00726    fx=cos(alpha)*radius;
00727    fy=sin(alpha)*radius;
00728    CreateVertex();
00729    Vp=(MainVp+Nvert-1);
00730    Vp->xyz[0]=(long)fx;
00731    Vp->xyz[1]=(long)fy;
00732    Vp->xyz[0]*=TVsizeX/4000;
00733    Vp->xyz[1]*=TVsizeY/4000;
00734    Vp->xyz[0]+=NpointerX;
00735    Vp->xyz[1]+=NpointerY;
00736    if(choice == 0){ /* helices */
00737      Vp->xyz[2]=(long)(alpha*2000);
00738      Vp->xyz[2]*=TVsizeZ/4000;
00739    }
00740    else if(choice == 2){  /* 3D Spiral */
00741      Vp->xyz[2]=(long)(radius);
00742      Vp->xyz[2]*=TVsizeZ/4000;
00743    }
00744    if(i > 0)CreateEdge(Nvert-1,Nvert-2);
00745    if(choice == 1 || choice == 2) {        // For 3D and normal spirals.
00746      if(spiral == 0) radius-=2000/Npoints;  // Archimedean spiral.
00747      else if(spiral == 1) radius*=1.05;     // Logarithmic spiral.
00748    }
00749  }
00750  DrawModel();
00751 }
00752 
00753 void AddPolygon(int ns, long radius, int axis){
00754  double fx, fy, alpha;
00755  char x,y,z;
00756  int i,Npoints,fv;
00757  long px,py;
00758  vertex *Vp=NULL;
00759  if((double)TVsizeX / (double)4000 <= 1.00) {
00760    SendPrgmQuery(IDQ_SCALETOOSMALL,0);
00761    return;
00762  }
00763  if(ns == 0)Npoints=RequestNumEntry(LastNumberSides,4,90,
00764                                     "No of Sides"," Sides");
00765  else Npoints=ns;
00766  if(Npoints <= 0)return;
00767  LastNumberSides=Npoints;
00768  switch(axis) {
00769   case TRITOP:   x=0; y=1; z=2; px=NpointerX; py=NpointerY; break;
00770   case TRIFRONT: x=0; y=2; z=1; px=NpointerX; py=NpointerZ; break;
00771   case TRIRIGHT: x=1; y=2; z=0; px=NpointerY; py=NpointerZ; break;
00772   default: return; break;
00773  }
00774  if(!UpdateVertexHeap(Nvert+Npoints)){
00775    SendPrgmQuery(IDQ_NOMEM2,0);
00776    return;
00777  }
00778  if(!UpdateEdgeHeap(Nedge+Npoints)){
00779    SendPrgmQuery(IDQ_NOMEM2,0);
00780    return;
00781  }
00782  for(i=0; i<Npoints; ++i) {
00783    alpha=(360.0/(double)Npoints)*(double)i;
00784    alpha*=0.0175;
00785    fx=cos(alpha)*(double)radius;
00786    fy=sin(alpha)*(double)radius;
00787    CreateVertex();
00788    Vp=(MainVp+Nvert-1);
00789    Vp->xyz[x]=(long)fx;
00790    Vp->xyz[y]=(long)fy;
00791    Vp->xyz[x]+=px;
00792    Vp->xyz[y]+=py;
00793    if(i == 0)fv=Nvert-1;
00794    else CreateEdge(Nvert-1,Nvert-2);
00795  }
00796  CreateEdge(Nvert-1,fv);
00797 }
00798 
00799 static void Plot3D(void){
00800  struct np {int t,x,y;} d;
00801  long double fx, fy, fz;
00802  int choice, gridx=15, gridz=15, range=360, count, zcount;
00803  int  vp,tvp,fvp = -1;
00804  vertex *Vp;
00805  if((double)TVsizeX / (double)12000 <= 1.00) {
00806    SendPrgmQuery(IDQ_SCALETOOSMALL,0);
00807    return;
00808  }
00809  d.t=0; d.x=15; d.y=15;
00810  if(DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_FPLOT),ghwnd_main,
00811             (DLGPROC)FunctionPlotDlgProc,(LPARAM)&d) != OK)return;
00812  choice=d.t;
00813  gridx=d.x;
00814  gridz=d.y;
00815  if(gridx < 0 || gridz < 0)return;
00816  if(!UpdateVertexHeap(Nvert+gridx*gridz)){
00817    SendPrgmQuery(IDQ_NOMEM2,0);
00818    return;
00819  }
00820  if(!UpdateEdgeHeap(Nedge+(gridx-1)*gridz+(gridz-1)*gridx+
00821                           (gridx-1)*(gridz-1))){
00822    SendPrgmQuery(IDQ_NOMEM2,0);
00823    return;
00824  }
00825  if(!UpdateFaceHeap(Nface+(gridx-1)*(gridz-1)*2)){
00826    SendPrgmQuery(IDQ_NOMEM2,0);
00827    return;
00828  }
00829  for(zcount=0; zcount<gridz; ++zcount) {
00830    fz=(range/gridz)*zcount;
00831    fz=fz*0.0175;
00832    vp = -1;
00833    for(count=0; count<gridx; ++count) {
00834      fx=(range/gridx)*count;
00835      fx=fx*0.0175;          // Degrees to radians.
00836      switch(choice) {
00837        case 0: fy=0;                                   break;
00838        case 1: fy=sin(fx);                             break;
00839        case 2: fy=tan(fx);                             break;
00840        case 3: fy=exp(-1*(pow(fx-PI,2)+pow(fz-PI,2))); break;
00841        case 4: fy=sin(fx)*sin(fz);                     break;
00842        case 5: fy=sin(fx*fz);                          break;
00843        case 6: fy=sin(fx)*sin(3*fz);                   break;
00844        case 7: fy=sin(fx)+cos(fz);                     break;
00845        default: break;
00846      }
00847      CreateVertex();
00848      Vp=(MainVp+Nvert-1);
00849      Vp->xyz[0]=(long)(fx*2000.00);
00850      Vp->xyz[2]=(long)(fy*2000.00);
00851      Vp->xyz[1]=(long)(fz*2000.00);
00852      Vp->xyz[0]*=TVsizeX/12000;    // Scale curve.
00853      Vp->xyz[1]*=TVsizeY/12000;
00854      Vp->xyz[2]*=TVsizeZ/12000;
00855      Vp->xyz[0]+=NpointerX;
00856      Vp->xyz[1]+=NpointerY;
00857      if(vp >= 0)CreateEdge(vp,Nvert-1);
00858      if(fvp < 0)fvp=Nvert-1;
00859      vp=Nvert-1;
00860    }
00861  }
00862  for(range=0; range<gridz-1; ++range) {
00863    for(count=0; count<gridx; ++count) {
00864      tvp=fvp+gridx;
00865      CreateEdge(tvp,fvp);
00866      if(count<gridx-1) {
00867        CreateEdge(tvp,fvp+1);
00868        CreateFace(tvp,fvp+1,fvp);
00869        CreateFace(tvp+1,fvp+1,tvp);
00870      }
00871      fvp++;
00872    }
00873  }
00874  DrawModel();
00875 }
00876 
00877 static void Line(void){
00878  int Npoints=8, c;
00879  long i;
00880  double r=1.3;
00881  char response[16];
00882  vertex *Vp=NULL;
00883  if(Read1Int1Real("Create Line","Number of Vertices","Spacing Ratio",
00884      &Npoints,2,90,&r,-2.0,2.0,ghwnd_main) == FAIL)return;
00885  if(Npoints < 0) return;
00886  if(r>2.00 || r<-2.00 || r==0.00){
00887    SendPrgmQuery(IDQ_BADRATIO,0);
00888    return;
00889  }
00890  if(!UpdateVertexHeap(Nvert+Npoints)){
00891    SendPrgmQuery(IDQ_NOMEM2,0);
00892    return;
00893  }
00894  if(!UpdateEdgeHeap(Nedge+Npoints-1)){
00895    SendPrgmQuery(IDQ_NOMEM2,0);
00896    return;
00897  }
00898  i=TVpointX/Npoints;
00899  for(c=0; c<Npoints; ++c) {
00900   CreateVertex();
00901   Vp=(MainVp+Nvert-1);
00902   Vp->xyz[0]=i;
00903   Vp->xyz[1]=NpointerY;
00904   Vp->xyz[2]=NpointerZ;
00905   if(c != 0)CreateEdge(Nvert-1,Nvert-2);
00906   i = (long)((double)i*r);
00907  }
00908  DrawModel();
00909 }
00910 
00911 static void RotatePointXY(point p, int angle){
00912  double theta,ctheta,stheta,dx,dy;
00913  theta = (double)angle*PI/180.0;
00914  ctheta=cos(theta);
00915  stheta=sin(theta);
00916  dx=(double)(p[0]-NpointerX);
00917  dy=(double)(p[1]-NpointerY);
00918  p[0]=NpointerX+(long)(ctheta*dx-stheta*dy);
00919  p[1]=NpointerY+(long)(stheta*dx+ctheta*dy);
00920 }
00921 
00922 void UpdatePrimitiveStructure(long primitivetype, int view,
00923                               long xmin, long ymin, long zmin,
00924                               long xmax, long ymax, long zmax,
00925                               long xc,   long yc,   long zc){
00926  int i,ml,mw;
00927  PrimStruct.ml=1; PrimStruct.mw=1;
00928  PrimStruct.lr=(double)(xc-lrulerx)/ruler;
00929  PrimStruct.fb=(double)(yc-lrulery)/ruler;
00930  PrimStruct.ud=(double)(zc-lrulerz)/ruler;
00931  PrimStruct.length=(double)labs(ymax-ymin)/ruler;
00932  PrimStruct.width=(double)labs(xmax-xmin)/ruler;
00933  PrimStruct.height=(double)labs(zmax-zmin)/ruler;
00934  if     (view == TRITOP  )PrimStruct.radius=max(PrimStruct.length,PrimStruct.width)/2.0;
00935  else if(view == TRIFRONT)PrimStruct.radius=max(PrimStruct.width,PrimStruct.height)/2.0;
00936  else if(view == TRIRIGHT)PrimStruct.radius=max(PrimStruct.length,PrimStruct.height)/2.0;
00937  switch (primitivetype){
00938    case 0: /* rectangle */
00939      if(view == TRITOP){
00940        if(xmin > xmax)mw = -1; else mw = 1;
00941        if(ymin > ymax)ml = -1; else ml = 1;
00942        PrimStruct.width=(double)labs(xmax-xmin)/ruler;
00943        PrimStruct.length=(double)labs(ymax-ymin)/ruler;
00944      }
00945      else if(view == TRIFRONT){
00946        if(xmin > xmax)mw = -1; else mw = 1;
00947        if(zmin > zmax)ml = -1; else ml = 1;
00948        PrimStruct.width=(double)labs(xmax-xmin)/ruler;
00949        PrimStruct.length=(double)labs(zmax-zmin)/ruler;
00950      }
00951      else if(view == TRIRIGHT){
00952        if(ymin > ymax)mw = -1; else mw = 1;
00953        if(zmin > zmax)ml = -1; else ml = 1;
00954        PrimStruct.width=(double)labs(ymax-ymin)/ruler;
00955        PrimStruct.length=(double)labs(zmax-zmin)/ruler;
00956      }
00957      PrimStruct.ml=ml;
00958      PrimStruct.mw=mw;
00959      break;
00960    case 1: /* cube      */
00961      break;
00962    case 2: /* polygon  */
00963      break;
00964    case 3: /* tube     */
00965      if     (view == TRITOP  )PrimStruct.length=(double)labs(zmax-zmin)/ruler;
00966      else if(view == TRIFRONT)PrimStruct.length=(double)labs(ymax-ymin)/ruler;
00967      else if(view == TRIRIGHT)PrimStruct.length=(double)labs(xmax-xmin)/ruler;
00968      break;
00969    case 4: /* disk     */
00970      break;
00971    case 5: /* cylinder */
00972      if     (view == TRITOP  )PrimStruct.length=(double)labs(zmax-zmin)/ruler;
00973      else if(view == TRIFRONT)PrimStruct.length=(double)labs(ymax-ymin)/ruler;
00974      else if(view == TRIRIGHT)PrimStruct.length=(double)labs(xmax-xmin)/ruler;
00975      break;
00976    case 6: /* cone     */
00977      if     (view == TRITOP  )PrimStruct.length=(double)labs(zmax-zmin)/ruler;
00978      else if(view == TRIFRONT)PrimStruct.length=(double)labs(ymax-ymin)/ruler;
00979      else if(view == TRIRIGHT)PrimStruct.length=(double)labs(xmax-xmin)/ruler;
00980      break;
00981    case 7: /* sphere   */
00982      break;
00983    case 8: /* sphere2  */
00984      break;
00985    default: break;
00986  }
00987  return;
00988 }
00989 
00990 static BOOL MakeTorus(long npoly, long nring, double prop, long view){
00991  //double prop=0.5;   // 0.1 -> 1.0
00992  long radius,view1;
00993  if     (view == TRITOP){
00994    radius=prop*(TVsizeZ/4);
00995    NpointerX=TVpointX+TVsizeX-radius;
00996    view1=TRIFRONT;
00997  }
00998  else if(view == TRIFRONT){
00999    radius=prop*(TVsizeY/4);
01000    NpointerX=TVpointX+TVsizeY-radius;
01001    view1=TRITOP;
01002  }
01003  else if(view == TRIRIGHT){
01004    radius=prop*(TVsizeX/4);
01005    NpointerY=TVpointY+TVsizeX-radius;
01006    view1=TRITOP;
01007  }
01008  AddPolygon(npoly,radius,view1);
01009  NpointerX=TVpointX+TVsizeX/2;
01010  NpointerY=TVpointY+TVsizeY/2;
01011  NpointerZ=TVpointZ+TVsizeZ/2;
01012  Spin(1,nring,TRUE,view);
01013  return TRUE;
01014 }
01015 
01016 static BOOL MakeLatLongSphere(long nlat, long nlong, long view){
01017  long i,j,radius,*lastrow;
01018  double dv,angle=0.0,dangle=PI/(double)(nlat-1);
01019 // dv=(double)TVsizeZ/2;
01020  if     (view == TRITOP  )dv=(double)TVsizeZ/2;
01021  else if(view == TRIFRONT)dv=(double)TVsizeY/2;
01022  else if(view == TRIRIGHT)dv=(double)TVsizeX/2;
01023  if((lastrow=(long *)X__Malloc(nlong*sizeof(long))) == NULL)return FALSE;
01024  for(i=0;i<nlat;i++){
01025 //   NpointerZ=TVpointZ+TVsizeZ/2+(long)(dv*cos(angle));
01026    if     (view == TRITOP  )NpointerZ=TVpointZ+TVsizeZ/2+(long)(dv*cos(angle));
01027    else if(view == TRIFRONT)NpointerY=TVpointY+TVsizeY/2+(long)(dv*cos(angle));
01028    else if(view == TRIRIGHT)NpointerX=TVpointX+TVsizeX/2+(long)(dv*cos(angle));
01029    if(i == 0){
01030      if(!UpdateVertexHeap(Nvert+1))return FALSE;
01031      CreateVertex();
01032    }
01033    else if(i == (nlat-1)){
01034      if(!UpdateVertexHeap(Nvert+1))return FALSE;
01035      CreateVertex();
01036      if(!UpdateEdgeHeap(Nedge+nlong))return FALSE;
01037      if(!UpdateFaceHeap(Nface+nlong))return FALSE;
01038      for(j=Nvert-nlong-1;j<Nvert-1;j++){
01039        CreateEdge(j,Nvert-1);
01040        if(j == Nvert-nlong-1)CreateFace(j,Nvert-2,Nvert-1);
01041        else                  CreateFace(j,j-1,Nvert-1);
01042      }
01043    }
01044    else {
01045      radius=(long)(dv*sin(angle));
01046      AddPolygon(nlong,radius,view);
01047      if(i == 1){
01048        if(!UpdateEdgeHeap(Nedge+nlong))return FALSE;
01049        if(!UpdateFaceHeap(Nface+nlong))return FALSE;
01050        for(j=Nvert-nlong;j<Nvert;j++){
01051          CreateEdge(j,Nvert-nlong-1);
01052          if(j == Nvert-nlong)CreateFace(j,Nvert-nlong-1,Nvert-1);
01053          else                CreateFace(j,Nvert-nlong-1,j-1);
01054        }
01055      }
01056      else {
01057        if(!UpdateEdgeHeap(Nedge+2*nlong))return FALSE;
01058        if(!UpdateFaceHeap(Nface+2*nlong))return FALSE;
01059        for(j=Nvert-nlong;j<Nvert;j++){
01060          CreateEdge(j,j-nlong);
01061          if(j == Nvert-nlong){
01062            CreateEdge(j,j-1);
01063            CreateFace(j,j-nlong,j-1);
01064            CreateFace(j,j-1,j+nlong-1);
01065          }
01066          else{
01067            CreateEdge(j,j-nlong-1);
01068            CreateFace(j,j-nlong,j-nlong-1);
01069            CreateFace(j,j-nlong-1,j-1);
01070          }
01071        }
01072      }
01073    }
01074    angle += dangle;
01075  }
01076  X__Free(lastrow);
01077  return TRUE;
01078 }
01079 
01080 void BuildPrimitive(long primitivetype, int view){
01081  vertex *Vp;
01082  long n_face_list,*face_list,last_face;
01083  long n,x,y,z,tvx,tvy,tvz,tvpx,tvpy,tvpz;
01084  long v1,v2,v3,v4,v5,v6,v7,v8,opx,opy,opz,dx,dy,dz,LastMainFp,
01085       LastMainEp,LastMainVp,radius,height,vs[12];
01086  int i,j,fp,vp;
01087  int fid[30]={0,6,5,
01088               6,0,1,
01089               1,7,6,
01090               7,1,2,
01091               2,8,7,
01092               8,2,3,
01093               3,9,8,
01094               9,3,4,
01095               4,5,9,
01096               5,4,0};
01097  face *Fp;
01098  x=NpointerX; y=NpointerY; z=NpointerZ;
01099  tvx=TVsizeX; tvy=TVsizeY; tvz=TVsizeZ;
01100  tvpx=TVpointX; tvpy=TVpointY; tvpz=TVpointZ;
01101  LastMainFp=Nface;
01102  LastMainEp=Nedge;
01103  LastMainVp=Nvert;
01104  vp=0; Vp=MainVp; while(vp < Nvert){
01105    if(Vp->status == SELECTED)Vp->status=INEDITOR;
01106     vp++; Vp++;
01107  }
01108  switch (primitivetype){
01109    case 0: /* rectangle */
01110      opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01111      opy=(long)(PrimStruct.fb*ruler)+lrulery;
01112      opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01113      dx=(long)(PrimStruct.width*ruler)*PrimStruct.mw;
01114      dy=(long)(PrimStruct.length*ruler)*PrimStruct.ml;
01115      if(!UpdateVertexHeap(Nvert+4))goto ABRT;
01116      if(!UpdateEdgeHeap(Nedge+5))goto ABRT;
01117      if(!UpdateFaceHeap(Nface+2))goto ABRT;
01118      CreateVertex(); v1=Nvert-1;  CreateVertex(); v2=Nvert-1;
01119      CreateVertex(); v3=Nvert-1;  CreateVertex(); v4=Nvert-1;
01120      CreateEdge(v1,v2); CreateEdge(v2,v3);
01121      CreateEdge(v3,v4); CreateEdge(v4,v1);
01122      CreateEdge(v1,v3);
01123      CreateFace(v1,v3,v2); CreateFace(v1,v4,v3);
01124      fp=LastMainFp; while(fp < Nface){
01125        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01126        fp++;
01127      }
01128      if(view == TRITOP){
01129        (MainVp+v1)->xyz[2]=(MainVp+v2)->xyz[2]=
01130        (MainVp+v3)->xyz[2]=(MainVp+v4)->xyz[2]=opz;
01131        (MainVp+v1)->xyz[0]=(MainVp+v4)->xyz[0]=opx;
01132        (MainVp+v2)->xyz[0]=(MainVp+v3)->xyz[0]=opx+dx;
01133        (MainVp+v1)->xyz[1]=(MainVp+v2)->xyz[1]=opy;
01134        (MainVp+v3)->xyz[1]=(MainVp+v4)->xyz[1]=opy+dy;
01135      }
01136      else if(view == TRIFRONT){
01137        (MainVp+v1)->xyz[1]=(MainVp+v2)->xyz[1]=
01138        (MainVp+v3)->xyz[1]=(MainVp+v4)->xyz[1]=opy;
01139        (MainVp+v1)->xyz[0]=(MainVp+v4)->xyz[0]=opx;
01140        (MainVp+v2)->xyz[0]=(MainVp+v3)->xyz[0]=opx+dx;
01141        (MainVp+v1)->xyz[2]=(MainVp+v2)->xyz[2]=opz;
01142        (MainVp+v3)->xyz[2]=(MainVp+v4)->xyz[2]=opz+dy;
01143      }
01144      else if(view == TRIRIGHT){
01145        (MainVp+v1)->xyz[0]=(MainVp+v2)->xyz[0]=
01146        (MainVp+v3)->xyz[0]=(MainVp+v4)->xyz[0]=opx;
01147        (MainVp+v1)->xyz[1]=(MainVp+v4)->xyz[1]=opy;
01148        (MainVp+v2)->xyz[1]=(MainVp+v3)->xyz[1]=opy+dx;
01149        (MainVp+v1)->xyz[2]=(MainVp+v2)->xyz[2]=opz;
01150        (MainVp+v3)->xyz[2]=(MainVp+v4)->xyz[2]=opz+dy;
01151      }
01152      break;
01153    case 1: /* cube      */
01154      opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01155      opy=(long)(PrimStruct.fb*ruler)+lrulery;
01156      opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01157      dx=(long)(PrimStruct.width*ruler)/2;
01158      dy=(long)(PrimStruct.length*ruler)/2;
01159      dz=(long)(PrimStruct.height*ruler)/2;
01160      if(!UpdateVertexHeap(Nvert+8))goto ABRT;
01161      if(!UpdateEdgeHeap(Nedge+18))goto ABRT;
01162      if(!UpdateFaceHeap(Nface+12))goto ABRT;
01163      CreateVertex(); v1=Nvert-1; CreateVertex(); v2=Nvert-1;
01164      CreateVertex(); v3=Nvert-1; CreateVertex(); v4=Nvert-1;
01165      CreateVertex(); v5=Nvert-1; CreateVertex(); v6=Nvert-1;
01166      CreateVertex(); v7=Nvert-1; CreateVertex(); v8=Nvert-1;
01167      CreateEdge(v1,v2); CreateEdge(v2,v3);   /* top */
01168      CreateEdge(v3,v4); CreateEdge(v4,v1);
01169      CreateEdge(v1,v3);
01170      CreateEdge(v5,v6); CreateEdge(v6,v7);   /* bottom */
01171      CreateEdge(v7,v8); CreateEdge(v8,v5);
01172      CreateEdge(v5,v7);
01173      CreateEdge(v1,v5); CreateEdge(v2,v6);   /* sides */
01174      CreateEdge(v3,v7); CreateEdge(v4,v8);
01175      CreateEdge(v1,v6); CreateEdge(v2,v7);   /* side diagonal */
01176      CreateEdge(v3,v8); CreateEdge(v4,v5);
01177      CreateFace(v1,v2,v3); CreateFace(v1,v3,v4); /* top */
01178      CreateFace(v5,v7,v6); CreateFace(v5,v8,v7); /* bottom */
01179      CreateFace(v1,v6,v2); CreateFace(v1,v5,v6); /* sides */
01180      CreateFace(v2,v7,v3); CreateFace(v2,v6,v7);
01181      CreateFace(v3,v8,v4); CreateFace(v3,v7,v8);
01182      CreateFace(v4,v5,v1); CreateFace(v4,v8,v5);
01183      (MainVp+v1)->xyz[2]=(MainVp+v2)->xyz[2]=
01184      (MainVp+v3)->xyz[2]=(MainVp+v4)->xyz[2]=opz+dz;
01185      (MainVp+v1)->xyz[0]=(MainVp+v4)->xyz[0]=opx+dx;
01186      (MainVp+v2)->xyz[0]=(MainVp+v3)->xyz[0]=opx-dx;
01187      (MainVp+v1)->xyz[1]=(MainVp+v2)->xyz[1]=opy+dy;
01188      (MainVp+v3)->xyz[1]=(MainVp+v4)->xyz[1]=opy-dy;
01189      (MainVp+v5)->xyz[2]=(MainVp+v6)->xyz[2]=
01190      (MainVp+v7)->xyz[2]=(MainVp+v8)->xyz[2]=opz-dz;
01191      (MainVp+v5)->xyz[0]=(MainVp+v8)->xyz[0]=opx+dx;
01192      (MainVp+v6)->xyz[0]=(MainVp+v7)->xyz[0]=opx-dx;
01193      (MainVp+v5)->xyz[1]=(MainVp+v6)->xyz[1]=opy+dy;
01194      (MainVp+v7)->xyz[1]=(MainVp+v8)->xyz[1]=opy-dy;
01195      fp=LastMainFp; while(fp < Nface){
01196        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01197        fp++;
01198      }
01199      break;
01200    case 2: /* polygon  */
01201      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01202      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01203      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01204      radius=(long)(PrimStruct.radius*ruler);
01205      AddPolygon(PrimStruct.nsides,radius,view);
01206      break;
01207    case 3: /* tube     */
01208      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01209      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01210      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01211      radius=(long)(PrimStruct.radius*ruler);
01212      height=(long)(PrimStruct.length*ruler)/2;
01213      n=PrimStruct.nsteps;
01214      if     (view == TRITOP  )NpointerZ -= height;
01215      else if(view == TRIFRONT)NpointerY -= height;
01216      else if(view == TRIRIGHT)NpointerX -= height;
01217      last_face=Nface;
01218      AddPolygon(PrimStruct.nsides,radius,view);
01219      j=height*2/n;
01220      for(i=0;i<n;i++){
01221        CreateAttachedCopy(1);
01222        vp=LastMainVp; while(vp < Nvert){
01223          Vp=(MainVp+vp);
01224          if(Vp->status == SELECTED){
01225            if(view == TRITOP  )Vp->xyz[2] = NpointerZ+j*(i+1);
01226            if(view == TRIFRONT)Vp->xyz[1] = NpointerY+j*(i+1);
01227            if(view == TRIRIGHT)Vp->xyz[0] = NpointerX+j*(i+1);
01228          }
01229          vp++;
01230        }
01231      }
01232      n_face_list=0;
01233      fp=LastMainFp; while(fp < Nface){
01234        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01235        (MainFp+fp)->bSmooth=TRUE;
01236        n_face_list++;
01237        fp++;
01238      }
01239      if(n_face_list > 0 &&
01240        (face_list = (long *)X__Malloc(n_face_list*sizeof(long))) != NULL){
01241        for(j=0,i=last_face;i<Nface;i++,j++)face_list[j]=i;
01242        if(j == n_face_list){
01243          OrientateFaceNormals(face_list[0],n_face_list,face_list);
01244          if(view == TRIFRONT)ReverseFaceOrientation(n_face_list,face_list);
01245        }
01246        X__Free(face_list);
01247      }
01248      break;
01249    case 4: /* disk     */
01250      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01251      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01252      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01253      radius=(long)(PrimStruct.radius*ruler);
01254      AddPolygon(PrimStruct.nsides,radius,view);
01255      if(Nvert <= LastMainVp)break;
01256      AutoFillFace(LastMainVp);
01257      fp=LastMainFp; while(fp < Nface){
01258        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01259        fp++;
01260      }
01261      break;
01262    case 5: /* cylinder */
01263      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01264      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01265      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01266      radius=(long)(PrimStruct.radius*ruler);
01267      height=(long)(PrimStruct.length*ruler)/2;
01268      n=PrimStruct.nsteps;
01269      if     (view == TRITOP  )NpointerZ -= height;
01270      else if(view == TRIFRONT)NpointerY -= height;
01271      else if(view == TRIRIGHT)NpointerX -= height;
01272      last_face=LastMainFp;
01273      AddPolygon(PrimStruct.nsides,radius,view);
01274      if(Nvert <= LastMainVp)break;
01275 
01276      AutoFillFace(LastMainVp);
01277 //     (MainVp+Nvert-1)->status=SELECTED;
01278 //     NvertSelect++; NvertDeselect--;
01279      j=height*2/n;
01280      for(i=0;i<n;i++){
01281        CreateAttachedCopy(1);
01282        vp=LastMainVp; while(vp < Nvert){
01283          Vp=(MainVp+vp);
01284          if(Vp->status == SELECTED){
01285            if(view == TRITOP  )Vp->xyz[2] = NpointerZ+j*(i+1);
01286            if(view == TRIFRONT)Vp->xyz[1] = NpointerY+j*(i+1);
01287            if(view == TRIRIGHT)Vp->xyz[0] = NpointerX+j*(i+1);
01288          }
01289          vp++;
01290        }
01291      }
01292      if     (view == TRITOP  )NpointerZ += height*2;
01293      else if(view == TRIFRONT)NpointerY += height*2;
01294      else if(view == TRIRIGHT)NpointerX += height*2;
01295      AutoFillFace(LastMainVp);
01296      (MainVp+Nvert-1)->status=SELECTED;
01297      NvertSelect++; NvertDeselect--;
01298 
01299      n_face_list=0;
01300      fp=LastMainFp; while(fp < Nface){
01301        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01302        (MainFp+fp)->bSmooth=TRUE; /* assume smoothing */
01303        n_face_list++;
01304        fp++;
01305      }
01306      if(n_face_list > 0 &&
01307        (face_list = (long *)X__Malloc(n_face_list*sizeof(long))) != NULL){
01308        for(j=0,i=last_face;i<Nface;i++,j++)face_list[j]=i;
01309        if(j == n_face_list){
01310          OrientateFaceNormals(face_list[0],n_face_list,face_list);
01311          if(TRIFRONT != view)ReverseFaceOrientation(n_face_list,face_list);
01312        }
01313        X__Free(face_list);
01314      }
01315      break;
01316    case 6: /* cone     */
01317      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01318      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01319      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01320      radius=(long)(PrimStruct.radius*ruler);
01321      height=(long)(PrimStruct.length*ruler)/2;
01322      if     (view == TRITOP  )NpointerZ -= height;
01323      else if(view == TRIFRONT)NpointerY -= height;
01324      else if(view == TRIRIGHT)NpointerX -= height;
01325      AddPolygon(PrimStruct.nsides,radius,view);
01326      if(Nvert <= LastMainVp)break;
01327      AutoFillFace(LastMainVp);
01328      AutoFillFace(LastMainVp);
01329      Vp=(MainVp+Nvert-1);
01330      if(view == TRITOP  )Vp->xyz[2] = NpointerZ+height*2;
01331      if(view == TRIFRONT)Vp->xyz[1] = NpointerY+height*2;
01332      if(view == TRIRIGHT)Vp->xyz[0] = NpointerX+height*2;
01333      Vp->status=SELECTED;
01334      NvertSelect++; NvertDeselect--;
01335      fp=LastMainFp; while(fp < Nface){
01336        for(i=0;i<3;i++)(MainFp+fp)->color[i]=PrimStruct.fc[i];
01337        (MainFp+fp)->bSmooth=TRUE; /* assume smoothing */
01338        fp++;
01339      }
01340      break;
01341    case 7: /* sphere   */
01342      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01343      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01344      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01345      radius=(long)(PrimStruct.radius*ruler);
01346      TVsizeZ=TVsizeX=TVsizeY=radius*2;
01347      TVpointX=opx-radius;
01348      TVpointY=opy-radius;
01349      TVpointZ=opz-radius;
01350      if(!UpdateVertexHeap(Nvert+12))goto ABRT;
01351      if(!UpdateEdgeHeap(Nedge+30))goto ABRT;
01352      if(!UpdateFaceHeap(Nface+20))goto ABRT;
01353      for(i=0;i<12;i++){
01354        CreateVertex(); vs[i]=Nvert-1;
01355        if(i < 10)(MainVp+vs[i])->xyz[0]=TVpointX;
01356      }
01357      (MainVp+vs[10])->xyz[2]=TVpointZ;
01358      (MainVp+vs[11])->xyz[2]=TVpointZ+TVsizeZ;
01359      for(i=0;i<5;i++){
01360        (MainVp+vs[i])->xyz[2]=TVpointZ+TVsizeZ/4;
01361        (MainVp+vs[i+5])->xyz[2]=TVpointZ+(TVsizeZ*3)/4;
01362        RotatePointXY((MainVp+vs[i+5])->xyz,i*72);
01363        RotatePointXY((MainVp+vs[i])->xyz,i*72+36);
01364      }
01365      for(i=0;i<4;i++){
01366        CreateEdge(vs[i],vs[i+1]); CreateEdge(vs[i+5],vs[i+6]);
01367        CreateEdge(vs[i],vs[i+5]); CreateEdge(vs[i],vs[i+6]);
01368        CreateEdge(vs[i],vs[10]);  CreateEdge(vs[i+5],vs[11]);
01369      }
01370      CreateEdge(vs[4],vs[0]);  CreateEdge(vs[9],vs[5]);
01371      CreateEdge(vs[4],vs[5]);  CreateEdge(vs[4],vs[9]);
01372      CreateEdge(vs[4],vs[10]); CreateEdge(vs[9],vs[11]);
01373      for(i=0;i<30;i+=3){
01374        CreateFace(vs[fid[i]],vs[fid[i+1]],vs[fid[i+2]]);
01375      }
01376      for(i=0;i<4;i++){
01377        CreateFace(vs[10],vs[i+1],vs[i]);
01378        CreateFace(vs[11],vs[i+5],vs[i+6]);
01379      }
01380      CreateFace(vs[10],vs[0],vs[4]);
01381      CreateFace(vs[11],vs[9],vs[5]);
01382      Explode(0);
01383      if(PrimStruct.faces > 20){
01384        Subdivide(LastMainFp,LastMainEp,0);
01385        Explode(0);
01386        if(PrimStruct.faces > 80){
01387          Subdivide(LastMainFp,LastMainEp,0);
01388          Explode(0);
01389          if(PrimStruct.faces > 320){
01390            Subdivide(LastMainFp,LastMainEp,0);
01391            Explode(0);
01392          }
01393        }
01394      }
01395      fp=LastMainFp; while(fp < Nface){
01396        Fp=(MainFp+fp);
01397        for(i=0;i<3;i++)Fp->color[i]=PrimStruct.fc[i];
01398        if(PrimStruct.smooth)Fp->bSmooth=TRUE;
01399        else        Fp->bSmooth=FALSE;
01400        fp++;
01401      }
01402      break;
01403    case 8: /* second segmented sphere  */
01404    case 9: /* torus */
01405      NpointerX=opx=(long)(PrimStruct.lr*ruler)+lrulerx;
01406      NpointerY=opy=(long)(PrimStruct.fb*ruler)+lrulery;
01407      NpointerZ=opz=(long)(PrimStruct.ud*ruler)+lrulerz;
01408      radius=(long)(PrimStruct.radius*ruler);
01409      TVsizeZ=TVsizeX=TVsizeY=radius*2;
01410      TVpointX=opx-radius;
01411      TVpointY=opy-radius;
01412      TVpointZ=opz-radius;
01413      if(primitivetype == 8){
01414        if(!MakeLatLongSphere(PrimStruct.nvert,PrimStruct.nhorz,
01415                              view))goto ABRT;
01416      }
01417      if(primitivetype == 9){
01418        if(!MakeTorus(PrimStruct.nvert,PrimStruct.nhorz,
01419                      PrimStruct.torus_ratio,view))goto ABRT;
01420      }
01421      fp=LastMainFp; while(fp < Nface){
01422        Fp=(MainFp+fp);
01423        for(i=0;i<3;i++)Fp->color[i]=PrimStruct.fc[i];
01424        if(PrimStruct.smooth)Fp->bSmooth=TRUE;
01425        else        Fp->bSmooth=FALSE;
01426        fp++;
01427      }
01428      break;
01429    default: break;
01430  }
01431  vp=0; Vp=MainVp; while(vp < LastMainVp){
01432    if(Vp->status == INEDITOR)Vp->status=SELECTED;
01433    vp++; Vp++;
01434  }
01435  vp=LastMainVp; Vp=(MainVp+LastMainVp); while(vp < Nvert){
01436    if(Vp->status == DESELECTED){
01437      Vp->status=SELECTED;
01438      NvertSelect++;
01439      NvertDeselect--;
01440    }
01441    vp++; Vp++;
01442  }
01443  NpointerX=x; NpointerY=y; NpointerZ=z;
01444  TVsizeX=tvx; TVsizeY=tvy; TVsizeZ=tvz;
01445  TVpointX=tvpx; TVpointY=tvpy; TVpointZ=tvpz;
01446  DrawModel();
01447  UpdateCounters();
01448  if(ghwndOpenGLview == NULL)Draw3dView(0,0);
01449  else PostMessage(ghwndOpenGLview,(WM_USER+2),0,0); // update
01450  return;
01451  ABRT:
01452  vp=0; Vp=MainVp; while(vp < LastMainVp){ /* reset status */
01453    if(Vp->status == INEDITOR)Vp->status=SELECTED;
01454    vp++; Vp++;
01455  }
01456  return;
01457 }
01458 
01459 void ExecutePrimitivesMenu(HWND hWnd){
01460   long idata[9]={IDBM_MENU1_1,IDBM_MENU1_2,IDBM_MENU1_3,
01461                  IDBM_MENU1_4,IDBM_MENU1_5,IDBM_MENU1_6,
01462                  IDBM_MENU1_7,IDBM_MENU1_8,IDBM_MENU1_9
01463                 };
01464   long icommand[9]={
01465                     IDM_PRIMITIVE_QADD_1,
01466                     IDM_PRIMITIVE_QADD_2,
01467                     IDM_PRIMITIVE_QADD_3,
01468                     IDM_PRIMITIVE_QADD_4,
01469                     IDM_PRIMITIVE_QADD_5,
01470                     IDM_PRIMITIVE_QADD_6,
01471                     IDM_PRIMITIVE_QADD_7,
01472                     IDM_PRIMITIVE_QADD_8,
01473                     IDM_PRIMITIVE_QADD_9
01474                    };
01475   int i;
01476   POINT pt;
01477   HMENU hMenu=CreatePopupMenu();
01478   HBITMAP hBitmap[9];
01479   RECT rc;
01480   UINT align=TPM_LEFTALIGN;
01481   GetWindowRect(GetDlgItem(ghwndTools,10),&rc);
01482   if(bToolpannelLeft){pt.x=rc.right; align=TPM_LEFTALIGN; }
01483   else               {pt.x=rc.left;  align=TPM_RIGHTALIGN;}
01484   pt.y=rc.top;
01485 //  GetCursorPos(&pt);
01486   for(i=0;i<9;i++){
01487     hBitmap[i]=LoadBitmap(ghinst_main,MAKEINTRESOURCE(idata[i]));
01488     AppendMenu(hMenu,MF_ENABLED|MF_BITMAP,icommand[i],(LPCSTR)hBitmap[i]);
01489     if(i == 6)
01490       AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
01491   }
01492   TrackPopupMenu(hMenu,align | TPM_LEFTBUTTON,
01493                         pt.x,pt.y,0,hWnd,NULL);
01494   DestroyMenu(hMenu);
01495   for(i=0;i<9;i++){
01496     if(hBitmap[i] != NULL)DeleteObject(hBitmap);
01497   }
01498   InvalidateRect(ghwndTools,NULL,FALSE);
01499 }
01500 
01501 void AddSinglePrimitive(long command){
01502  long i;
01503  EDIT_ACTION=YES;
01504  memset(&PrimStruct,0,sizeof(PRIMITIVE));
01505  PrimStruct.nsides=12;
01506  PrimStruct.smooth=1;
01507  PrimStruct.faces=320;
01508  PrimStruct.nsteps=2;
01509  for(i=0;i<3;i++)PrimStruct.fc[i]=FaceColour[i];
01510  UpdatePrimitiveStructure(0,ActiveView,
01511                           TVcentreX-max(TVsizeX,TVsizeY)/8,
01512                           TVcentreY-max(TVsizeX,TVsizeY)/8,
01513                           TVcentreZ-max(TVsizeX,TVsizeY)/8,
01514                           TVcentreX+max(TVsizeX,TVsizeY)/8,
01515                           TVcentreY+max(TVsizeX,TVsizeY)/8,
01516                           TVcentreZ+max(TVsizeX,TVsizeY)/8,
01517                           NpointerX,NpointerY,NpointerZ);
01518   switch (command){
01519     case IDM_PRIMITIVE_QADD_1:  // cube
01520       BuildPrimitive(1,ActiveView);
01521       break;
01522     case IDM_PRIMITIVE_QADD_2:  // sphere
01523       BuildPrimitive(7,ActiveView);
01524       break;
01525     case IDM_PRIMITIVE_QADD_3:  // rectangle
01526       BuildPrimitive(0,ActiveView);
01527       break;
01528     case IDM_PRIMITIVE_QADD_4:  // cylinder
01529       BuildPrimitive(5,ActiveView);
01530       break;
01531     case IDM_PRIMITIVE_QADD_5:  // cone
01532       BuildPrimitive(6,ActiveView);
01533       break;
01534     case IDM_PRIMITIVE_QADD_6:  // polygon
01535       BuildPrimitive(2,ActiveView);
01536       break;
01537     case IDM_PRIMITIVE_QADD_7:  // tube
01538       BuildPrimitive(3,ActiveView);
01539       break;
01540     default: break;
01541  }
01542 }
01543 
01544 // end of Primitive creation code
01545 
01546 void MakeAutoWireFrame(void){
01547  HCURSOR lhcurSave;
01548  vertex *vp,*vf,*V0,*V1;
01549  edge *ep;
01550  int e1[12]={0,1,2,3,4,5,6,7,0,1,2,3};
01551  int e2[12]={1,2,3,0,5,6,7,4,4,5,6,7};
01552  int i,k,ki,ei,flag,kount;
01553  int type=0;
01554  long xmin,ymin,zmin,xmax,ymax,zmax;
01555  if(w_frame.p != NULL || w_frame.e != NULL ||
01556        w_frame.Np > 0 || w_frame.Ne > 0 ){
01557    SendPrgmQuery(IDQ_WIREEXISTS,0);
01558    return;
01559  }
01560  if(Nvert < 1 || Nedge < 1 || MainVp == NULL || MainEp == NULL)return;
01561  EDIT_ACTION=YES;
01562  lhcurSave=SetCursor(ghcurWait);
01563  if(type == 0){
01564    vp=MainVp;
01565    vf=NULL;
01566    for(vp=MainVp,i=0;i<Nvert;i++,vp++)vp->id=0;
01567    kount=0;
01568    while(TRUE){
01569      flag=0;
01570      for(vp=MainVp,i=0;i<Nvert;i++,vp++){
01571        if(vp->id == 0){
01572          vf=vp;
01573          kount++;
01574          goto GOTNEXT;
01575        }
01576      }
01577      goto NOMORE;
01578      GOTNEXT:
01579      vp=vf;
01580      vp->id=kount;
01581      flag=1;
01582      while(flag){
01583        flag=0;
01584        ep=MainEp; for(i=0;i<Nedge;i++){
01585          V0=(MainVp+ep->V[0]);
01586          V1=(MainVp+ep->V[1]);
01587          if(V0->id == kount && V1->id == 0 && V1->status != HIDDEN){
01588            V1->id = kount; flag=1;
01589          }
01590          if(V1->id == kount && V0->id == 0 && V0->status != HIDDEN){
01591            V0->id = kount; flag=1;
01592          }
01593          ep++;
01594        }
01595      }
01596    }
01597    NOMORE: /* now make up the bounding boxes */
01598    if(kount > 0 && kount < 100){
01599      if((w_frame.p=(point *)X__Malloc(8*kount*sizeof(point))) == NULL){
01600        SendPrgmQuery(IDQ_NOMEM1,0);
01601        goto XXIT;
01602      }
01603      w_frame.Np=kount*8;
01604      if((w_frame.e=(twoLongs *)X__Malloc(12*kount*sizeof(twoLongs))) == NULL){
01605        if(w_frame.p != NULL)X__Free(w_frame.p);
01606        w_frame.p=NULL;
01607        SendPrgmQuery(IDQ_NOMEM1,0);
01608        goto XXIT;
01609      }
01610      w_frame.Ne=kount*12;
01611      for(k=0;k<kount;k++){ /* do each bound */
01612        xmax=ymax=zmax = -MAXUNIT;
01613        xmin=ymin=zmin =  MAXUNIT;
01614        for(vp=MainVp,i=0;i<Nvert;i++,vp++){
01615          if(vp->id == k+1){
01616            if(vp->xyz[0] > xmax)xmax=vp->xyz[0];
01617            if(vp->xyz[0] < xmin)xmin=vp->xyz[0];
01618            if(vp->xyz[1] > ymax)ymax=vp->xyz[1];
01619            if(vp->xyz[1] < ymin)ymin=vp->xyz[1];
01620            if(vp->xyz[2] > zmax)zmax=vp->xyz[2];
01621            if(vp->xyz[2] < zmin)zmin=vp->xyz[2];
01622          }
01623        }
01624        ki=k*8;
01625        w_frame.p[ki  ][0] = xmin;
01626        w_frame.p[ki  ][1] = ymin;
01627        w_frame.p[ki  ][2] = zmin;
01628        w_frame.p[ki+1][0] = xmax;
01629        w_frame.p[ki+1][1] = ymin;
01630        w_frame.p[ki+1][2] = zmin;
01631        w_frame.p[ki+2][0] = xmax;
01632        w_frame.p[ki+2][1] = ymax;
01633        w_frame.p[ki+2][2] = zmin;
01634        w_frame.p[ki+3][0] = xmin;
01635        w_frame.p[ki+3][1] = ymax;
01636        w_frame.p[ki+3][2] = zmin;
01637        w_frame.p[ki+4][0] = xmin;
01638        w_frame.p[ki+4][1] = ymin;
01639        w_frame.p[ki+4][2] = zmax;
01640        w_frame.p[ki+5][0] = xmax;
01641        w_frame.p[ki+5][1] = ymin;
01642        w_frame.p[ki+5][2] = zmax;
01643        w_frame.p[ki+6][0] = xmax;
01644        w_frame.p[ki+6][1] = ymax;
01645        w_frame.p[ki+6][2] = zmax;
01646        w_frame.p[ki+7][0] = xmin;
01647        w_frame.p[ki+7][1] = ymax;
01648        w_frame.p[ki+7][2] = zmax;
01649        ei=k*12;
01650        for(i=0;i<12;i++){
01651          w_frame.e[ei+i][0] = ki+e1[i];
01652          w_frame.e[ei+i][1] = ki+e2[i];
01653        }
01654      }
01655    }
01656    else SendPrgmQuery(IDQ_WIRETOOBIG,0);
01657  }
01658  XXIT:
01659  SetCursor(lhcurSave);
01660 }
01661 
01662 int MakeWireFrame(void){
01663  long vp,ep;
01664  vertex *Vp,*V0,*V1;
01665  edge *Ep;
01666  long i,w_size=0;
01667  if(NvertSelect == 0){
01668    SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
01669    return FAIL;
01670  }
01671  if(NvertSelect > 400){
01672    SendPrgmQuery(IDQ_WIRETOOBIG,0);
01673    return FAIL;
01674  }
01675  ep=0; Ep=MainEp; while(ep < Nedge){
01676    if((MainVp+Ep->V[0])->status == SELECTED &&
01677       (MainVp+Ep->V[1])->status == SELECTED)w_size++;
01678    ep++; Ep++;
01679  }
01680  if(w_size == 0){
01681    SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
01682    return FAIL;
01683  }
01684  if((w_frame.p=(point *)X__Malloc(NvertSelect*sizeof(point))) == NULL){
01685    SendPrgmQuery(IDQ_NOMEM1,0);
01686    return FAIL;
01687  }
01688  EDIT_ACTION=YES;
01689  i=0; vp=0; Vp=MainVp; while(vp < Nvert){
01690    if(Vp->status == SELECTED){
01691      w_frame.p[i][0] = Vp->xyz[0];
01692      w_frame.p[i][1] = Vp->xyz[1];
01693      w_frame.p[i][2] = Vp->xyz[2];
01694      Vp->id=i; i++;
01695    }
01696    vp++; Vp++;
01697  }
01698  if(i != NvertSelect){
01699    if(w_frame.p != NULL)X__Free(w_frame.p);
01700    w_frame.p=NULL;
01701    SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
01702    return FAIL;
01703  }
01704  w_frame.Np=i;
01705  if((w_frame.e=(twoLongs *)X__Malloc(w_size*sizeof(twoLongs))) == NULL){
01706    if(w_frame.p != NULL)X__Free(w_frame.p);
01707    w_frame.p=NULL;
01708    SendPrgmQuery(IDQ_NOMEM1,0);
01709    return FAIL;
01710  }
01711  w_frame.Ne=w_size;
01712  i=0; ep=0; Ep=MainEp; while(ep < Nedge){
01713    V0=(MainVp+Ep->V[0]); V1=(MainVp+Ep->V[1]);
01714    if(V0->status == SELECTED && V1->status == SELECTED){
01715      w_frame.e[i][0] = V0->id;
01716      w_frame.e[i][1] = V1->id;
01717      i++;
01718    }
01719    ep++; Ep++;
01720  }
01721  if(i != w_size){
01722    if(w_frame.p != NULL)X__Free(w_frame.p); w_frame.p=NULL; w_frame.Np=0;
01723    if(w_frame.e != NULL)X__Free(w_frame.e); w_frame.e=NULL; w_frame.Ne=0;
01724    SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
01725    return FAIL;
01726  }
01727  return OK;
01728 }
01729 
01730 void ClearWireFrame(void){
01731  long i;
01732  long *vtemp;
01733  if(w_frame.p == NULL || w_frame.e == NULL){
01734    SendPrgmQuery(IDQ_WIRENOEXISTS,0);
01735    return;
01736  }
01737  EDIT_ACTION=YES;
01738  X__Free(w_frame.p); w_frame.p=NULL; w_frame.Np=0;
01739  X__Free(w_frame.e); w_frame.e=NULL; w_frame.Ne=0;
01740 }
01741 
01742 void UnMakeWireFrame(void){
01743  long i;
01744  long *vtemp;
01745  if(w_frame.p == NULL || w_frame.e == NULL){
01746    SendPrgmQuery(IDQ_WIRENOEXISTS,0);
01747    return;
01748  }
01749  if((vtemp=(long *)X__Malloc(w_frame.Np*sizeof(long))) == NULL){
01750    return;
01751  }
01752  EDIT_ACTION=YES;
01753  if(!UpdateVertexHeap(Nvert+w_frame.Np)){
01754    SendPrgmQuery(IDQ_NOMEM1,0);
01755    return;
01756  }
01757  if(!UpdateEdgeHeap(Nedge+w_frame.Ne)){
01758    SendPrgmQuery(IDQ_NOMEM1,0);
01759    return;
01760  }
01761  for(i=0;i<w_frame.Np;i++){
01762    CreateVertex();
01763    vtemp[i]=Nvert-1;
01764    (MainVp+Nvert-1)->xyz[0]=w_frame.p[i][0];
01765    (MainVp+Nvert-1)->xyz[1]=w_frame.p[i][1];
01766    (MainVp+Nvert-1)->xyz[2]=w_frame.p[i][2];
01767  }
01768  for(i=0;i<w_frame.Ne;i++)CreateEdge(vtemp[w_frame.e[i][0]],
01769                                      vtemp[w_frame.e[i][1]]);
01770  X__Free(vtemp);
01771  X__Free(w_frame.p); w_frame.p=NULL; w_frame.Np=0;
01772  X__Free(w_frame.e); w_frame.e=NULL; w_frame.Ne=0;
01773  DrawModel();
01774  UpdateCounters();
01775 }
01776 
01777 void Nudge(int command){
01778  vertex *vp;
01779  long i,dx,dy,dz;
01780  int sx,sy,step=1;
01781  if(tool == ROTATOR){
01782    int axis;
01783    double angle;
01784    if     (GetAsyncKeyState(VK_SHIFT  ) & 0x8000)angle = 5.0;
01785    else                                          angle = 1.0;
01786    if(command == IDM_PAN_LEFT || command == IDM_PAN_RIGHT){
01787      Save_Undo(1);
01788      if(command == IDM_PAN_RIGHT)angle *= -1.0;
01789      ActionRotate(ActiveView,angle,0);
01790      do_NOT_abort=TRUE;
01791      DrawModel();
01792      do_NOT_abort=FALSE;
01793    }
01794    return;
01795  }
01796  dx=NpointerX; dy=NpointerY; dz=NpointerZ;
01797  GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&sx,&sy);
01798  if(GetAsyncKeyState(VK_SHIFT  ) & 0x8000)step=5;
01799  if(command == IDM_PAN_LEFT) sx -= step; /* use PAN commands as ID's */
01800  if(command == IDM_PAN_RIGHT)sx += step;
01801  if(command == IDM_PAN_UP)   sy -= step;
01802  if(command == IDM_PAN_DOWN) sy += step;
01803  Draw3dCursor();
01804  GetWorldCoords(ActiveView,&NpointerX,&NpointerY,&NpointerZ,sx,sy);
01805  Draw3dCursor();
01806  if(coords_visible)UpdateRuler(0);
01807  if(tool == GRABBER){
01808    dx=NpointerX-dx; dy=NpointerY-dy; dz=NpointerZ-dz;
01809    vp=MainVp; for(i=0;i<Nvert;i++){
01810      if(vp->status == SELECTED){
01811        vp->xyz[0] += dx;
01812        vp->xyz[1] += dy;
01813        vp->xyz[2] += dz;
01814      }
01815      vp++;
01816    }
01817    RecalibrateAllBezier(); RecalibrateMapLocks();
01818    do_NOT_abort=TRUE;
01819    DrawModel();
01820    do_NOT_abort=FALSE;
01821  }
01822 }
01823 
01824 void LoadUtility(char *program, char *class, int message, char *arguments){
01825  BOOL n=FALSE;
01826  int result;
01827  char modulename[255];
01828  HWND hWnd=NULL;
01829  if((class == NULL) || ((hWnd=FindWindow(class,NULL)) == NULL)){
01830    strcpy(modulename,gszHomeDir);strcat(modulename,program);
01831    if(arguments != NULL){strcat(modulename,"  "); strcat(modulename,arguments);}
01832    result=WinExec(modulename,SW_SHOW);
01833    n=TRUE;
01834    if(result < 32){
01835      return;
01836    }
01837    if(class != NULL)hWnd=FindWindow(class,NULL);
01838  }
01839  if(hWnd != NULL && IsWindow(hWnd)){
01840    SetForegroundWindow(hWnd);
01841    BringWindowToTop(hWnd);
01842    ShowWindow(hWnd,SW_SHOW);
01843    if(n)PostMessage(hWnd,WM_COMMAND,message,0);
01844  }
01845  return;
01846 }
01847 
01848 int SelectDirectoryName(char *szfile, char *szdir,
01849                         char *szTitle, char *szfilter,
01850                         HWND parent){
01851  int i;
01852  OPENFILENAME ofn;
01853  char szFilter[80],szdummy[MAX_FILE];
01854  szdummy[0]='\0';
01855  strcpy(szFilter,szfilter);
01856  i=0; while(szFilter[i] != '\0'){
01857    if(szFilter[i] == '|')szFilter[i]='\0'; i++;
01858  }
01859  memset(&ofn,0,sizeof(OPENFILENAME));
01860  ofn.lStructSize=sizeof(OPENFILENAME);
01861  ofn.hwndOwner=parent;
01862  ofn.lpstrFilter=szFilter;
01863  ofn.nFilterIndex=1;
01864  ofn.lpstrFile=szfile;              /* will contain file + path */
01865  ofn.nMaxFile=MAX_FILE;
01866  ofn.lpstrFileTitle=szdummy;         /* file name only */
01867  ofn.nMaxFileTitle=MAX_FILE;
01868  ofn.lpstrInitialDir=szdir;
01869  ofn.lpstrTitle=szTitle;
01870  ofn.hInstance=ghinst_main;
01871  ofn.lpfnHook=NULL;
01872  ofn.lpTemplateName="DIRECTORYOPEN";
01873  ofn.Flags=OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|
01874             OFN_ENABLETEMPLATE|OFN_NONETWORKBUTTON|
01875             OFN_NOTESTFILECREATE; 
01876  i=(int)(GetSaveFileName(&ofn));
01877  if(i){
01878    strcpy(szdummy,szfile);
01879    *AnsiPrev(szdummy,FileInPath(szdummy)) = '\0';
01880    strcpy(szdir,szdummy);
01881  }
01882  return i;
01883 }

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