TOOLS1.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX - Modelling, Animation and Rendering Package
00003 -- */
00004 
00005 
00006 /* file TOOLS1.C  first designer tools file */
00007 
00008 #define MODULE_TOOLS1 1
00009 
00010 #include "design.h"
00011 
00012 #define TIME_DELAY 30
00013 
00014 typedef struct XTRAEDGE {
00015  int  ep;
00016  int  nc;
00017 } xtraedge;
00018 
00019 typedef struct VERTEXVERTEXEDGE {
00020  int  vs,vd;
00021 } vertexvertexedge;
00022 
00023 long PrimitiveType = 0;
00024 
00025 long LastToolVertex = -1;  /* used in mlibs.c */
00026 
00027 static void PullMagnet(void);
00028 static void Edge3d(void);
00029 static void Plot3d(void);
00030 static void Grab(void);
00031 static void Shape(void);
00032 static void ShapeShape(int id);
00033 static void FormerDown(void);
00034 static void FormerUp(void);
00035 static void FormerMove(void);
00036 static void ShearerDown(void);
00037 static void ShearerUp(void);
00038 static void ShearerMove(int x, int y);
00039 static void Ixpand(void);
00040 static void Irotate(void);
00041 static void Casteljau(point p, long *Vc, long i, long j, double mu);
00042 static int GetGrabberBoundingBox(int flag);
00043 static void DrawIrotateBoundBox(int i, double theta);
00044 static void RotatePointAbout(long x, long y, long X, long Y, long *tx,
00045                              long *ty, double ctheta, double stheta);
00046 
00047 static int  x_down,y_down;
00048 static BOOL PrimitiveActive=FALSE,Mxpand=FALSE,IxpandFlag=FALSE,
00049             JxpandFlag=FALSE,bFlagNotool=FALSE,bFlagMoved=FALSE,
00050             bFlagNurbs=FALSE;
00051 static long VertexCount1[50],VertexCount2[50];
00052 static long GrabonX,GrabonY,GrabonZ,GrabDx,GrabDy,GrabDz,
00053             grab_xmin,grab_ymin,grab_zmin,
00054             grab_xmax,grab_ymax,grab_zmax;
00055 static double RotatorTheta=0.0;
00056 static double shaper_angle_phi=0.0,shaper_angle_theta=0.0,shaper_size=6;
00057 static point *shaper_list=NULL;
00058 static BOOL  bShaperMoved=FALSE;
00059 static unsigned char PrimitiveFaceColour[3]={164,164,164};
00060 
00061 static void Casteljau(point p, long *Vc, long i, long j, double mu){
00062   vertex *va,*va1;
00063   point p1,p2;
00064   if(j == 1){
00065     va=(MainVp+(*(Vc+i))); va1=(MainVp+(*(Vc+i+1)));
00066     p[0] = (long)((1.0 - mu)*(double)(va->xyz[0])
00067                  + mu*(double)(va1->xyz[0]));
00068     p[1] = (long)((1.0 - mu)*(double)(va->xyz[1])
00069                  + mu*(double)(va1->xyz[1]));
00070     p[2] = (long)((1.0 - mu)*(double)(va->xyz[2])
00071                  + mu*(double)(va1->xyz[2]));
00072   }
00073   else{
00074     Casteljau(p1,Vc,i,j-1,mu);
00075     Casteljau(p2,Vc,i+1,j-1,mu);
00076     p[0]=(long)((1.0 - mu)*(double)p1[0] + mu*(double)p2[0]);
00077     p[1]=(long)((1.0 - mu)*(double)p1[1] + mu*(double)p2[1]);
00078     p[2]=(long)((1.0 - mu)*(double)p1[2] + mu*(double)p2[2]);
00079   }
00080 }
00081 
00082 void RecalibrateBezier(int id){
00083  long i,N,Npath;
00084  double mu;
00085  point p;
00086  N=Bcurves[id].Np-1;
00087  Npath=Bcurves[id].Nc;
00088  for(i=1;i<N;i++){
00089    mu=(double)i/(double)N;
00090    Casteljau(p,Bcurves[id].Vc,0,Npath-1,mu);
00091    (MainVp+Bcurves[id].Vp[i])->xyz[0]=p[0];
00092    (MainVp+Bcurves[id].Vp[i])->xyz[1]=p[1];
00093    (MainVp+Bcurves[id].Vp[i])->xyz[2]=p[2];
00094  }
00095 }
00096 
00097 void RecalibrateAllBezier(void){
00098  int i;
00099  if(N_Bcurves == 0)return;
00100  for(i=0;i<N_Bcurves;i++)RecalibrateBezier(i);
00101 }
00102 
00103 void MakeBezierCurve(void){
00104  HCURSOR hSave;
00105  vertex *Vp;
00106  long vp,vf,*va;
00107  long Npath,i,N;
00108  double mu;
00109  point p;
00110  bezier_curve *bc;
00111  if(NvertSelect<4)return;
00112  if((vf=get_closest_vertex()) < 0)return;
00113  N=RequestNumEntry(10,3,100,"No. of Edges"," Edges");
00114  if(N < 4)return;
00115  hSave=SetCursor(ghcurWait);
00116  /* found first vertex of path */
00117  /* find path connected to vf and store in array va[] */
00118  if((va=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
00119    SetCursor(hSave);
00120    SendPrgmQuery(IDQ_NOMEM2,0);
00121    return;
00122  }
00123  Save_Undo(0);
00124  Npath=0; va[0]=vf; (MainVp+va[0])->id=1;  i=NvertSelect-1;
00125  vp=0; while(vp < Nvert){
00126    Vp=(MainVp+vp);
00127    if(Vp->status == SELECTED && Vp->id == 0 && connected(va[Npath],vp)){
00128      Npath++;    /* add the point to the path list */
00129      va[Npath]=vp;
00130      Vp->id=1;   /* flag so not used again also indicates in path */
00131      i--;
00132      vp=0;  /* go back and look for the next connected vertex */
00133    }
00134    else vp++;
00135  }
00136  Npath++;       /* to make up to number of points */
00137  if(i != 0 || Npath > 9){
00138    SendPrgmQuery(IDQ_NOTSUITABLECURVE,0);
00139    goto EXIT;
00140  }
00141  if(Npath > 3){ /* at least 4 points needed */
00142    if(N_Bcurves == 0)bc=(bezier_curve *)X__Malloc(sizeof(bezier_curve));
00143    else bc=(bezier_curve *)X__Realloc(Bcurves,sizeof(bezier_curve)*(N_Bcurves+1));
00144    if(bc == NULL){
00145      SendPrgmQuery(IDQ_NOMEM2,0);
00146      goto EXIT;
00147    }
00148    Bcurves=bc; bc = &Bcurves[N_Bcurves];
00149    sprintf(bc->name,"C-%ld",N_Bcurves);
00150    if((bc->Vc = (long *)X__Malloc(Npath*sizeof(long))) == NULL){
00151      SendPrgmQuery(IDQ_NOMEM2,0);
00152      goto EXIT;
00153    }
00154    if((bc->Vp = (long *)X__Malloc((N+1)*sizeof(long))) == NULL){
00155      X__Free(bc->Vc);
00156      SendPrgmQuery(IDQ_NOMEM2,0);
00157      goto EXIT;
00158    }
00159    N_Bcurves++; bc->Nc=Npath; bc->Np=N+1;
00160    for(i=0;i<Npath;i++)bc->Vc[i] = va[i];
00161    if(!UpdateVertexHeap(Nvert+N-1)){
00162      SendPrgmQuery(IDQ_NOMEM2,0);
00163      goto EXIT;
00164    }
00165    if(!UpdateEdgeHeap(Nedge+N+1)){
00166      SendPrgmQuery(IDQ_NOMEM2,0);
00167      goto EXIT;
00168    }
00169    for(i=1;i<N;i++){
00170      mu=(double)i/(double)N;
00171      Casteljau(p,va,0,Npath-1,mu);
00172      CreateVertex();
00173      bc->Vp[i]=Nvert-1;
00174      if(i == 1)CreateEdge(va[0],Nvert-1);
00175      else      CreateEdge(Nvert-1,Nvert-2);
00176      Vp=(MainVp+Nvert-1);
00177      Vp->xyz[0]=p[0]; Vp->xyz[1]=p[1]; Vp->xyz[2]=p[2];
00178    }
00179    CreateEdge(Nvert-1,va[Npath-1]);
00180    bc->Vp[0]=va[0];
00181    bc->Vp[N]=va[Npath-1];
00182    RequestCharString(6,bc->name,"Curve ID",ghwnd_main);
00183  }
00184  EXIT:
00185  SetCursor(hSave);
00186  X__Free(va);
00187  DrawModel(); UpdateCounters();
00188  return;
00189 }
00190 
00191 int AddFace(void){
00192  vertex  *vp;
00193  long Nvs,vps0,vps1,vpn[3];     /* VertexCount max = 50 ?? */
00194  edge    *ep;
00195  int i,count1,count2,j,k,l,c;
00196  if( (NvertSelect < 2) || (NvertSelect > 3))return 0;
00197  Nvs=Nvert;
00198  vp=MainVp; i=0;
00199  for(vp=MainVp,c=0;c<Nvert;c++,vp++){
00200    if(vp->status == SELECTED){
00201      vpn[i++]=(long)c;
00202      if( i > NvertSelect)break;
00203    }
00204  }
00205  if(i == 2)i=1;  /* only one edge to add if 2 vertices only */
00206  else      i=3;  /* up to 3 edges to add if 3 vertices      */
00207  for(l=0;l<i;l++){
00208    if     (l == 0){vps0=vpn[0]; vps1=vpn[1];}
00209    else if(l == 1){vps0=vpn[1]; vps1=vpn[2];}
00210    else if(l == 2){vps0=vpn[2]; vps1=vpn[0];}
00211    ep=MainEp; count1=0; count2=0;
00212    for(c=0;c<Nedge;c++){
00213      if(ep->V[0] == vps0){VertexCount1[count1]=ep->V[1];count1++;}
00214      if(ep->V[1] == vps0){VertexCount1[count1]=ep->V[0];count1++;}
00215      if(ep->V[0] == vps1){VertexCount2[count2]=ep->V[1];count2++;}
00216      if(ep->V[1] == vps1){VertexCount2[count2]=ep->V[0];count2++;}
00217      ep++;
00218    }
00219    if((count1 > 0) && (count2 > 0)){
00220      for(j=0;j<count1;j++)for(k=0;k<count2;k++){
00221        if(VertexCount1[j] == VertexCount2[k]){
00222          if(!CheckFaceExists(vps0,vps1,VertexCount1[j],0)){
00223            UpdateFaceHeap(Nface+1);
00224            CreateFace(vps0,vps1,VertexCount1[j]);
00225          }
00226        }
00227      }
00228    }
00229    if(!CheckEdgeExists(vps0,vps1,0)){
00230      UpdateEdgeHeap(Nedge+1);
00231      CreateEdge(vps0,vps1);
00232      DrawOneEdgeOnly((MainVp+vps0),(MainVp+vps1));
00233    }
00234  }
00235  return 1;
00236 }
00237 
00238 void ToolDown(HWND hwnd, int av, int x, int y){
00239  bFlagMoved=FALSE;
00240  x_down=x; y_down=y;
00241  if(tool == NOTOOL || tool == NODETOOL){
00242    long Vid;
00243    if(SelectedBrush >= 0)GrabBrushPoint(x,y);
00244    else if(SelectedShader >= 0)GrabMaterialAxisPoint(x,y);
00245    else if(tool == NOTOOL){
00246      if(GetAsyncKeyState(VK_CONTROL) & 0x8000){;} /* do not select */
00247      else if((Vid=PickVertex()) >= 0){
00248        SelectConnectedTo(Vid);
00249        Empty_Undo();
00250      }
00251      else SelectNurbsPatch(av,x,y);
00252    }
00253    else if(tool == NODETOOL){
00254      bFlagNotool=FALSE;
00255      bFlagNurbs=FALSE;
00256      if((LastToolVertex=PickVertex()) >= 0){
00257        Empty_Undo();
00258        if((MainVp+LastToolVertex)->status == SELECTED)bFlagNotool=TRUE;
00259      }
00260      else if(GetAsyncKeyState(VK_LBUTTON) & 0x8000){
00261        if(SelectNurbsControlPoint(av,x,y)){
00262          bFlagNurbs=TRUE;
00263          bFlagNotool=TRUE;
00264          MoveNurbsControlPoint(av,x,y,1);
00265        }
00266        else if(GetAsyncKeyState(VK_LBUTTON) & 0x8000){
00267          if(GetAsyncKeyState(VK_MENU) & 0x8000)tool=DESELECTOR;
00268          else                                  tool=SELECTOR;
00269          bFlagNotool=TRUE;
00270          SelectorDown(hwnd,av,x,y);
00271        }
00272      }
00273    }
00274  }
00275  else if(tool == SELECTOR || tool == DESELECTOR){
00276    SelectorDown(hwnd,av,x,y);
00277  }
00278  else if(tool == GRABBER){
00279    GrabOn();
00280    DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
00281                       grab_xmax,grab_ymax,grab_zmax);
00282    MoveNurbsSurface(av,x,y,1);
00283  }
00284  else if(tool == EXPANDER || tool == ROTATOR){
00285    IxpandFlag=FALSE;
00286  }
00287  else if(tool == PLOT3D || tool == BUILDER){
00288    point p;
00289    if(LastToolVertex >= 0){
00290      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00291      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00292    }
00293  }
00294  else if(tool == PLOTTER){
00295    point p;
00296    if(GetAsyncKeyState(VK_MENU) & 0x8000){LastToolVertex = -1;}
00297    if(LastToolVertex >= 0){
00298      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00299      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00300    }
00301    else if(!(GetAsyncKeyState(VK_CONTROL) & 0x8000))ToolAction(x,y);
00302  }
00303  else if(tool == SHAPER){
00304    GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00305    DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
00306                     shaper_angle_theta,shaper_angle_phi,shaper_size);
00307    FormerDown();
00308  }
00309  else if(tool == MAGNETTO){
00310    GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00311    ShearerDown();
00312  }
00313  else if(tool == PRIMS){
00314    GrabDx=grab_xmin=grab_xmax=NpointerX;
00315    GrabDy=grab_ymin=grab_ymax=NpointerY;
00316    GrabDz=grab_zmin=grab_zmax=NpointerZ;
00317    SendMessage(ghwndDlgPrimitives,WM_INTERROGATE,0,0);
00318    PrimitiveActive=FALSE;
00319  }
00320  else if(sktool == YES)SkToolDown(x,y);
00321 }
00322 
00323 void ToolUp(HWND hwnd, int av, int x, int y){
00324  if(tool == NOTOOL || tool == NODETOOL){
00325    if(SelectedBrush >= 0)UnGrabBrushPoint();
00326    else if(SelectedShader >= 0)UnGrabMaterialAxisPoint();
00327    else if(tool == NODETOOL && bFlagNurbs){
00328      bFlagNotool=FALSE; bFlagNurbs=FALSE;
00329      MoveNurbsControlPoint(av,x,y,-1);
00330      DrawModel();
00331    }
00332    else if(tool == NODETOOL && LastToolVertex >= 0){
00333      if(bFlagNotool && bFlagMoved){
00334        DrawRubberLines(hwnd,av,-2,x,y);
00335        DrawModel();
00336      }
00337      else { /* change select status */
00338        vertex *vf;
00339        vf=(MainVp+LastToolVertex);
00340        if(vf->status==SELECTED){
00341          NvertSelect--; NvertDeselect++; vf->status=DESELECTED;
00342        }
00343        else{
00344          NvertSelect++; NvertDeselect--; vf->status=SELECTED;
00345        }
00346        DrawVerticesOnly(vf); UpdateCounters();
00347      }
00348      bFlagNotool=FALSE; LastToolVertex= -1;
00349    }
00350  }
00351  else if(tool == SELECTOR || tool == DESELECTOR){
00352    SelectorUp(hwnd,av,x,y,bFlagMoved,bFlagNotool);
00353    if(bFlagNotool){
00354      tool=NODETOOL; bFlagNotool=FALSE;
00355    }
00356  }
00357  else if(tool == GRABBER){
00358    MoveNurbsSurface(av,x,y,-1);
00359    Grab();
00360  }
00361  else if(tool == PLOT3D || tool == BUILDER){
00362    point p;
00363    if(LastToolVertex >= 0){
00364      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00365      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00366    }
00367  }
00368  else if(tool == PLOTTER){
00369    point p;
00370    if(LastToolVertex >= 0){
00371      vertex *vf;
00372      int ix,jy;
00373      vf=(MainVp+LastToolVertex);
00374      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00375      DrawRubber3dLine(vf->xyz,p);
00376      GetWindowCoords(ActiveView,vf->xyz[0],vf->xyz[1],vf->xyz[2],&ix,&jy);
00377      if(GetAsyncKeyState(VK_CONTROL) & 0x8000){;}
00378      else if(abs(x-ix) >2 || abs(y-jy) > 2)ToolAction(x,y);
00379    }
00380  }
00381  else if(tool == PRIMS){
00382    if(PrimitiveActive){
00383      PrimitiveActive=FALSE;
00384      DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
00385                         grab_xmax,grab_ymax,grab_zmax);
00386      UpdatePrimitiveStructure(PrimitiveType,ActiveView,
00387                               grab_xmin,grab_ymin,grab_zmin,
00388                               grab_xmax,grab_ymax,grab_zmax,
00389                               GrabDx,GrabDy,GrabDz);
00390      if(IsWindow(ghwndDlgPrimitives)){
00391        SendMessage(ghwndDlgPrimitives,WM_UPDATEPDIALOG,0,0);
00392        if(PrimStruct.auto_interactive)
00393          SendMessage(ghwndDlgPrimitives,WM_COMMAND,(WPARAM)IDOK,0);
00394      }
00395    }
00396  }
00397  else if(tool == EXPANDER || tool == ROTATOR){
00398    IxpandFlag=FALSE;
00399  }
00400  else if(tool == SHAPER){
00401    DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
00402                     shaper_angle_theta,shaper_angle_phi,shaper_size);
00403    FormerUp();
00404  }
00405  else if(tool == MAGNETTO){
00406    ShearerUp();
00407  }
00408  else if(sktool == YES)SkToolUp(x,y);
00409  if(tool == EXPANDER || tool == ROTATOR || tool == GRABBER ||
00410     tool == NODETOOL){
00411    if(ghwndOpenGLview == NULL)Draw3dView(0,0);
00412    else PostMessage(ghwndOpenGLview,(WM_USER+2),0,0); // update
00413  }
00414  return;
00415 }
00416 
00417 void ToolMove(HWND hwnd, int av, int x, int y){
00418  point p;
00419  int flag=0;
00420  POINT pt;
00421  if(!bFlagMoved && abs(x-x_down) < 2 && abs(y-y_down) < 2)return;
00422  if(tool == NOTOOL || tool == NODETOOL){
00423    if(SelectedBrush >= 0)PullBrushPoint(x,y);
00424    else if(SelectedShader >= 0)PullShaderPoint(x,y);
00425    else if(tool == NODETOOL && bFlagNurbs){
00426      MoveNurbsControlPoint(av,x,y,0);
00427    }
00428    else if(tool == NODETOOL && LastToolVertex >= 0 && bFlagNotool){
00429      if(bFlagMoved)DrawRubberLines(hwnd,av,-1,x,y);
00430      else DrawRubberLines(hwnd,av,LastToolVertex,x,y);
00431    }
00432  }
00433  else if(tool == SELECTOR || tool == DESELECTOR){
00434    SelectorMove(hwnd,av,x,y);
00435  }
00436  else if(tool == GRABBER){
00437    DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,grab_xmax,grab_ymax,grab_zmax);
00438    grab_xmin += (NpointerX-GrabDx); grab_xmax += (NpointerX-GrabDx);
00439    grab_ymin += (NpointerY-GrabDy); grab_ymax += (NpointerY-GrabDy);
00440    grab_zmin += (NpointerZ-GrabDz); grab_zmax += (NpointerZ-GrabDz);
00441    GrabDx=NpointerX; GrabDy=NpointerY; GrabDz=NpointerZ;
00442    DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,grab_xmax,grab_ymax,grab_zmax);
00443    MoveNurbsSurface(av,x,y,0);
00444  }
00445  else if(tool == PLOTTER){
00446    Move3dCursor(0,x,y);
00447    if     (x > WindowSizeX[ActiveView] - 4){
00448      flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_RIGHT1,ActiveView);
00449    }
00450    else if(x < 4){
00451      flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_LEFT1,ActiveView);
00452    }
00453    else if(y < 4){
00454      flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_UP1,ActiveView);
00455    }
00456    else if(y > WindowSizeY[ActiveView] - 4){
00457      flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_DOWN1,ActiveView);
00458    }
00459    if(flag){
00460      GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&x,&y);
00461      pt.x=x; pt.y=y;
00462      ClientToScreen(ghwnd_current,&pt);
00463      SetCursorPos(pt.x,pt.y);
00464    }
00465    if(LastToolVertex >= 0){
00466      if(!flag){
00467        p[0]=GrabDx; p[1]=GrabDy; p[2]=GrabDz;
00468        DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00469      }
00470      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00471      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00472    }
00473  }
00474  else if(tool == PLOT3D || tool == BUILDER){
00475    if(LastToolVertex >= 0){
00476      p[0]=GrabDx; p[1]=GrabDy; p[2]=GrabDz;
00477      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00478      p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00479      DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00480    }
00481  }
00482  else if(tool == PRIMS){
00483    long d,dx,dy,dz;
00484    if(PrimitiveActive){
00485      DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
00486                         grab_xmax,grab_ymax,grab_zmax);
00487    }
00488    else PrimitiveActive=TRUE;
00489    if(ActiveView == TRITOP)
00490      d=max(labs(GrabDx-NpointerX),labs(GrabDy-NpointerY));
00491    if(ActiveView == TRIFRONT)
00492      d=max(labs(GrabDx-NpointerX),labs(GrabDz-NpointerZ));
00493    if(ActiveView == TRIRIGHT)
00494      d=max(labs(GrabDy-NpointerY),labs(GrabDz-NpointerZ));
00495    if(PrimitiveType == 0){
00496      if     (ActiveView == TRITOP){
00497        dx=NpointerX-GrabDx; dy=NpointerY-GrabDy; dz=0;
00498      }
00499      else if(ActiveView == TRIFRONT){
00500        dx=NpointerX-GrabDx; dy=0; dz=NpointerZ-GrabDz;
00501      }
00502      else{
00503        dx=0; dy=NpointerY-GrabDy; dz=NpointerZ-GrabDz;
00504      }
00505      grab_xmin=GrabDx; grab_xmax=GrabDx+dx;
00506      grab_ymin=GrabDy; grab_ymax=GrabDy+dy;
00507      grab_zmin=GrabDz; grab_zmax=GrabDz+dz;
00508    }
00509    else{
00510      dx=dy=dz=d;
00511      if(PrimitiveType == 2 || PrimitiveType == 4){
00512        if     (ActiveView == TRITOP)dz=0;
00513        else if(ActiveView == TRIFRONT)dy=0;
00514        else dx=0;
00515      }
00516      else if(PrimitiveType != 7 && PrimitiveType != 8 && PrimitiveType != 9){
00517        if(GetAsyncKeyState(VK_CONTROL) & 0x8000){
00518          if     (ActiveView == TRITOP)dz=GrabDz-grab_zmin;
00519          else if(ActiveView == TRIFRONT)dy=GrabDy-grab_ymin;
00520          else dx=GrabDx-grab_xmin;
00521        }
00522      }
00523      grab_xmin=GrabDx-dx; grab_xmax=GrabDx+dx;
00524      grab_ymin=GrabDy-dy; grab_ymax=GrabDy+dy;
00525      grab_zmin=GrabDz-dz; grab_zmax=GrabDz+dz;
00526    }
00527    DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
00528                       grab_xmax,grab_ymax,grab_zmax);
00529  }
00530  else if(tool == EXPANDER || tool == ROTATOR){
00531    RotatorTheta=0.0;
00532    if(!IxpandFlag){
00533      IxpandFlag=TRUE;
00534      if(GetGrabberBoundingBox(0) == 0){
00535        grab_xmin=grab_xmax=NpointerX;
00536        grab_ymin=grab_ymax=NpointerY;
00537        grab_zmin=grab_zmax=NpointerZ;
00538      }
00539      if(tool == ROTATOR){
00540        DrawIrotateBoundBox(ActiveView,RotatorTheta);
00541        RotateNurbsSurface(av,1,0.0);
00542      }
00543      else{
00544        DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
00545                           grab_xmax,grab_ymax,grab_zmax);
00546        XpandNurbsSurface(av,1,0.0,0.0,0.0);
00547      }
00548      if(tool == EXPANDER)Ixpand();
00549      else                Irotate();
00550    }
00551  }
00552  else if(tool == SHAPER){
00553    if     (GetAsyncKeyState(VK_CONTROL) & 0x8000)ShapeShape(0);
00554 //   else if(GetAsyncKeyState(VK_SHIFT)   & 0x8000)ShapeShape(1);  // SHAPER
00555 //   else if(GetAsyncKeyState(VK_MENU)    & 0x8000)ShapeShape(2);  // SHAPER
00556    else{
00557      Move3dCursor(0,x,y);
00558      DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
00559                       shaper_angle_theta,shaper_angle_phi,shaper_size);
00560 //     GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;    // SHAPER
00561      FormerMove();
00562      DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
00563                     shaper_angle_theta,shaper_angle_phi,shaper_size);
00564    }
00565  }
00566  else if(tool == MAGNETTO){
00567    ShearerMove(x,y);
00568  }
00569  else if(sktool == YES)SkToolMove(x,y);
00570  bFlagMoved=TRUE;
00571  return;
00572 }
00573 
00574 void ToolAction(int x, int y){
00575  if     (tool == PLOT3D)Plot3d();
00576  else if(tool == PLOTTER)Plot3d();
00577  else if(tool == BUILDER)Edge3d();
00578 // else if(tool == MAGNETTO)PullMagnet();
00579 // else if(tool == SHAPER)Shape();
00580  else if(sktool == YES){;} //SkToolAction(x,y);
00581  return;
00582 }
00583 
00584 static int GetGrabberBoundingBox(int flag){
00585  int i;
00586  vertex *vp;
00587  grab_xmin=grab_ymin=grab_zmin =  MAXUNIT;
00588  grab_xmax=grab_ymax=grab_zmax = -MAXUNIT;
00589  if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00590    if(vp->status == SELECTED){
00591      if(vp->xyz[0] > grab_xmax)grab_xmax=vp->xyz[0];
00592      if(vp->xyz[0] < grab_xmin)grab_xmin=vp->xyz[0];
00593      if(vp->xyz[1] > grab_ymax)grab_ymax=vp->xyz[1];
00594      if(vp->xyz[1] < grab_ymin)grab_ymin=vp->xyz[1];
00595      if(vp->xyz[2] > grab_zmax)grab_zmax=vp->xyz[2];
00596      if(vp->xyz[2] < grab_zmin)grab_zmin=vp->xyz[2];
00597      flag=1;
00598    }
00599    vp++;
00600  }
00601  return flag;
00602 }
00603 
00604 void GrabOn(void){
00605  int flag=0;
00606  GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00607  GrabDx=NpointerX;  GrabDy=NpointerY;  GrabDz=NpointerZ;
00608  flag=GetGrabberBoundingBox(flag);
00609  if(flag == 0){
00610    grab_xmin=grab_xmax=NpointerX;
00611    grab_ymin=grab_ymax=NpointerY;
00612    grab_zmin=grab_zmax=NpointerZ;
00613  }
00614 }
00615 
00616 static void Grab(void){
00617  vertex *vp;
00618  long i,dx,dy,dz;
00619  dx=NpointerX-GrabonX; dy=NpointerY-GrabonY; dz=NpointerZ-GrabonZ;
00620  vp=MainVp; for(i=0;i<Nvert;i++){
00621    if(vp->status == SELECTED){
00622      vp->xyz[0] += dx;
00623      vp->xyz[1] += dy;
00624      vp->xyz[2] += dz;
00625    }
00626    vp++;
00627  }
00628  GrabDx=GrabonX=NpointerX;
00629  GrabDy=GrabonY=NpointerY;
00630  GrabDz=GrabonZ=NpointerZ;
00631  RecalibrateAllBezier(); RecalibrateMapLocks();
00632  do_NOT_abort=TRUE;
00633  DrawModel();
00634  if(ghwndOpenGLview != NULL)PostMessage(ghwndOpenGLview,(WM_USER+2),0,0);
00635  do_NOT_abort=FALSE;
00636 }
00637 
00638 BOOL PrimitiveOn(void){
00639  int i;
00640  PrimitiveActive=FALSE;
00641  PrimStruct.auto_interactive=TRUE;
00642  PrimStruct.nsides=12;
00643  PrimStruct.nsteps=1;
00644  PrimStruct.smooth=1;
00645  PrimStruct.faces=320;
00646  PrimStruct.nvert=9;
00647  PrimStruct.nhorz=16;
00648  PrimStruct.torus_ratio=0.5;
00649  for(i=0;i<3;i++)PrimStruct.fc[i]=PrimitiveFaceColour[i];
00650  PrimitiveType=0;
00651  UpdatePrimitiveStructure(0,ActiveView,
00652                           TVcentreX-TVsizeX/2,
00653                           TVcentreY-TVsizeY/2,
00654                           TVcentreZ-TVsizeZ/2,
00655                           TVcentreX+TVsizeX/2,
00656                           TVcentreY+TVsizeY/2,
00657                           TVcentreZ+TVsizeZ/2,
00658                           TVcentreX,TVcentreY,TVcentreZ);
00659  ghwndDlgPrimitives=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_TAB_PRIMES),
00660                                  ghwnd_main,(DLGPROC)PrimitivesDlgProc);
00661  return TRUE;
00662 }
00663 
00664 void PrimitiveOff(void){
00665  int i;
00666  PrimitiveActive=FALSE;
00667  for(i=0;i<3;i++)PrimitiveFaceColour[i]=PrimStruct.fc[i];
00668  if(IsWindow(ghwndDlgPrimitives))DestroyWindow(ghwndDlgPrimitives);
00669  ghwndDlgPrimitives=NULL;
00670 }
00671 
00672 void Plot3dOn(void){ /* for PLOT3D and BUILDER */
00673  LastToolVertex = -1;
00674 }
00675 
00676 void Plot3dOff(void){  /* for PLOT3D AND PLOTTER and BUILDER */
00677   LastToolVertex = -1;
00678 }
00679 
00680 void IxpandOn(void){
00681   Mxpand=FALSE;
00682   IxpandFlag=FALSE;
00683   GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00684 }
00685 
00686 void IrotateOn(void){
00687   Mxpand=FALSE;
00688   IxpandFlag=FALSE;
00689   RotatorTheta=0.0;
00690   GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00691 }
00692 
00693 static void Plot3d(void){ /* just make curve if ctrl key down */
00694  int vp,vps[3];
00695  edge *Ep;
00696  int ep;
00697  int count1,count2,j,k;
00698  point p;
00699  p[0]=GrabDx; p[1]=GrabDy; p[2]=GrabDz;
00700  if(LastToolVertex >= 0)DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00701  if( !(GetAsyncKeyState(VK_CONTROL) & 0x8000) && (vp=PickVertex()) >= 0
00702     && (MainVp+vp)->status == SELECTED){
00703    if(LastToolVertex >= 0 && LastToolVertex != vp){
00704      vps[0]=vp;
00705      vps[1]=LastToolVertex;
00706      count1=0; count2=0;
00707      ep=0; while(ep < Nedge){
00708        Ep=(MainEp+ep);
00709        if(Ep->V[0] == vps[0]){VertexCount1[count1]=Ep->V[1]; count1++;}
00710        if(Ep->V[1] == vps[0]){VertexCount1[count1]=Ep->V[0]; count1++;}
00711        if(Ep->V[0] == vps[1]){VertexCount2[count2]=Ep->V[1]; count2++;}
00712        if(Ep->V[1] == vps[1]){VertexCount2[count2]=Ep->V[0]; count2++;}
00713        ep++;
00714      }
00715      if((count1 > 0) && (count2 > 0)){
00716        for(j=0;j<count1;j++)for(k=0;k<count2;k++){
00717           if(VertexCount1[j] == VertexCount2[k]){
00718             if(!CheckFaceExists(vps[0],vps[1],VertexCount1[j],0)){
00719                UpdateFaceHeap(Nface+1);
00720                CreateFace(vps[0],vps[1],VertexCount1[j]);
00721             }
00722           }
00723        }
00724      }
00725      if(!CheckEdgeExists(vps[0],vps[1],0)){
00726        UpdateEdgeHeap(Nedge+1);
00727        CreateEdge(vps[0],vps[1]);
00728        DrawOneEdgeOnly((MainVp+vps[0]),(MainVp+vps[1]));
00729      }
00730      LastToolVertex=-1;
00731    }
00732    else LastToolVertex=vp;
00733  }
00734  else{
00735    UpdateVertexHeap(Nvert+1);
00736    CreateVertex();
00737    if(LastToolVertex >= 0){
00738      UpdateEdgeHeap(Nedge+1);
00739      CreateEdge(LastToolVertex,Nvert-1);
00740      DrawOneEdgeOnly((MainVp+LastToolVertex),(MainVp+Nvert-1));
00741    }
00742    else DrawVerticesOnly((MainVp+Nvert-1));
00743    LastToolVertex=Nvert-1;
00744  }
00745  p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00746  if(LastToolVertex >= 0)DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00747  UpdateCounters();
00748 }
00749 
00750 static void Edge3d(void){
00751  int vp,vps[3];
00752  edge *Ep;
00753  int ep;
00754  int count1,count2,j,k;
00755  point p;
00756  p[0]=GrabDx; p[1]=GrabDy; p[2]=GrabDz;
00757  if(LastToolVertex >= 0)DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00758  if((vp=PickVertex()) >= 0){
00759    if(LastToolVertex >= 0 && LastToolVertex != vp){
00760      vps[0]=vp;
00761      vps[1]=LastToolVertex;
00762      count1=0; count2=0;
00763      ep=0; while(ep < Nedge){
00764        Ep=(MainEp+ep);
00765        if(Ep->V[0] == vps[0]){VertexCount1[count1]=Ep->V[1]; count1++;}
00766        if(Ep->V[1] == vps[0]){VertexCount1[count1]=Ep->V[0]; count1++;}
00767        if(Ep->V[0] == vps[1]){VertexCount2[count2]=Ep->V[1]; count2++;}
00768        if(Ep->V[1] == vps[1]){VertexCount2[count2]=Ep->V[0]; count2++;}
00769        ep++;
00770      }
00771      if((count1 > 0) && (count2 > 0)){
00772        for(j=0;j<count1;j++)for(k=0;k<count2;k++){
00773           if(VertexCount1[j] == VertexCount2[k]){
00774             if(!CheckFaceExists(vps[0],vps[1],VertexCount1[j],0)){
00775               UpdateFaceHeap(Nface+1);
00776               CreateFace(vps[0],vps[1],VertexCount1[j]);
00777             }
00778           }
00779        }
00780      }
00781      if(!CheckEdgeExists(vps[0],vps[1],0)){
00782        UpdateEdgeHeap(Nedge+1);
00783        CreateEdge(vps[0],vps[1]);
00784        DrawOneEdgeOnly((MainVp+vps[0]),(MainVp+vps[1]));
00785      }
00786      LastToolVertex=-1;
00787    }
00788    else LastToolVertex=vp;
00789  }
00790  p[0]=GrabDx=NpointerX; p[1]=GrabDy=NpointerY; p[2]=GrabDz=NpointerZ;
00791  if(LastToolVertex >= 0)DrawRubber3dLine((MainVp+LastToolVertex)->xyz,p);
00792  UpdateCounters();
00793 }
00794 
00795 static void PullMagnet(void){
00796  long i;
00797  vertex *vp;
00798  double dmin,dmax,d,mu;
00799  dmin=(double)MAXUNIT * (double)MAXUNIT;
00800  dmax=0.0;
00801  if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00802    if(vp->status == SELECTED){
00803      d  = (double)(vp->xyz[0] - NpointerX)*(double)(vp->xyz[0] - NpointerX)
00804         + (double)(vp->xyz[1] - NpointerY)*(double)(vp->xyz[1] - NpointerY)
00805         + (double)(vp->xyz[2] - NpointerZ)*(double)(vp->xyz[2] - NpointerZ);
00806      d=sqrt(d);
00807      if(d < dmin)dmin=d;
00808      if(d > dmax)dmax=d;
00809    }
00810    vp++;
00811  }
00812  if(dmin <1.e-5)return;
00813  if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00814    if(vp->status == SELECTED){
00815      d  = (double)(vp->xyz[0] - NpointerX)*(double)(vp->xyz[0] - NpointerX)
00816         + (double)(vp->xyz[1] - NpointerY)*(double)(vp->xyz[1] - NpointerY)
00817         + (double)(vp->xyz[2] - NpointerZ)*(double)(vp->xyz[2] - NpointerZ);
00818      d=sqrt(d);
00819      mu=1.0-(d-dmin)/(dmax-dmin);
00820      mu = mu*mu*mu;
00821      mu=mu/2;
00822      if(GetAsyncKeyState(VK_MENU) & 0x8000)mu *= -1.0; /* repel */
00823      vp->xyz[0]=(long)((double)vp->xyz[0]+(double)(NpointerX-vp->xyz[0])*mu);
00824      vp->xyz[1]=(long)((double)vp->xyz[1]+(double)(NpointerY-vp->xyz[1])*mu);
00825      vp->xyz[2]=(long)((double)vp->xyz[2]+(double)(NpointerZ-vp->xyz[2])*mu);
00826    }
00827    vp++;
00828  }
00829  DrawModel();
00830 }
00831 
00832 BOOL AddCopy(int wait){
00833  HCURSOR hSave;
00834  vertex *vp,*V0,*V1,*V2,*Vp;
00835  edge   *ep;
00836  face   *fp;
00837  long   i,Nvert1,Nedge1,Nface1;
00838  long x,y,z;
00839  if(NvertSelect == 0)return FALSE;
00840  if(NvertSelect > 32000){
00841    SendPrgmQuery(IDQ_WIRETOOBIG,0);
00842    return FALSE;
00843  }
00844  if(wait)hSave=SetCursor(ghcurWait);
00845  if(!UpdateVertexHeap(Nvert+NvertSelect))return FALSE;
00846  for(Nedge1=0,ep=MainEp,i=0;i<Nedge;i++){
00847    V0=(MainVp+ep->V[0]); V1=(MainVp+ep->V[1]);
00848    if(V0->status == SELECTED && V1->status == SELECTED)Nedge1++;
00849    ep++;
00850  }
00851  if(!UpdateEdgeHeap(Nedge+Nedge1))return FALSE;
00852  for(Nface1=0,fp=MainFp,i=0;i<Nface;i++){
00853    V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00854    if(V0->status == SELECTED &&
00855       V1->status == SELECTED &&
00856       V2->status == SELECTED)Nface1++;
00857    fp++;
00858  }
00859  if(!UpdateFaceHeap(Nface+Nface1))return FALSE;
00860  Nvert1=Nvert; Nedge1=Nedge; Nface1=Nface;
00861  vp=MainVp; for(i=0;i<Nvert1;i++){
00862    if(vp->status == SELECTED){
00863      CreateVertex();
00864      Vp=(MainVp+Nvert-1);
00865      Vp->xyz[0]=vp->xyz[0];
00866      Vp->xyz[1]=vp->xyz[1];
00867      Vp->xyz[2]=vp->xyz[2];
00868      Vp->gp=vp->gp;
00869      if(Vp->gp == 1){
00870        Vp->x=vp->x;
00871        Vp->y=vp->y;
00872      }
00873      Vp->status=DESELECTED;
00874      vp->id=Nvert-1;
00875      NvertSelect--; NvertDeselect++;
00876    }
00877    else{
00878      vp->id = -1;  /* needed by copy+flip+weld */
00879    }
00880    vp++;
00881  }
00882  if(Nedge > 0)for(ep=MainEp,i=0;i<Nedge1;i++){
00883    V0=(MainVp+ep->V[0]); V1=(MainVp+ep->V[1]);
00884    if(V0->status == SELECTED &&
00885       V1->status == SELECTED){
00886       CreateEdge(V0->id,V1->id);
00887    }
00888    ep++;
00889  }
00890  if(Nface > 0)for(fp=MainFp,i=0;i<Nface1;i++){
00891    V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00892    if(V0->status == SELECTED &&
00893       V1->status == SELECTED &&
00894       V2->status == SELECTED) {
00895      CreateFace(V0->id,V1->id,V2->id);
00896      CopyFaceProp(fp,(MainFp+Nface-1));
00897    }
00898    fp++;
00899  }
00900  vp=MainVp; for(i=0;i<Nvert1;i++){
00901    if(vp->status == SELECTED){
00902     vp->status=DESELECTED;
00903     (MainVp+vp->id)->status=SELECTED;
00904    }
00905    vp++;
00906  }
00907  if(wait) {
00908    SetCursor(hSave);
00909 //   if((dos_key_shift() & 0x04) == 0x04){ /* ctrl */
00910 //     if(Read3Reals("Offset by",&dx_copy,&dy_copy,&dz_copy,0,0) == 0)return FALSE;
00911 //     x=(long)(dx_copy*ruler);
00912 //     y=(long)(dy_copy*ruler);
00913 //     z=(long)(dz_copy*ruler);
00914 //     vp=MainVp; while (vp != NULL){
00915 //       if(vp->status == SELECTED){
00916 //         vp->xyz[0] += x; vp->xyz[1] += y; vp->xyz[2] += z;
00917 //       }
00918 //       vp=vp->last;
00919 //     }
00920 //     ReDrawDisplay();
00921 //     return FALSE;
00922 //   }
00923  }
00924  return TRUE;
00925 }
00926 
00927 BOOL CreateAttachedCopy(int open){
00928  /* open = 1 for Selected edges and faces; open = 2 for all attached faces */
00929  vertex *Vp,*vp,*vl,*vr,*v0,*v1,*v2;
00930  edge   *ep;
00931  face   *fp;
00932  int    ne,addit;
00933  long   i,j,uuecount=0,k,Nvert1=0,Nedge1=0,Nface1=0;
00934  xtraedge *xp;
00935  vertexvertexedge *vve=NULL;
00936  if(NvertSelect > 32000 || Nvert < 1){ return FALSE; }
00937  ne=0; if(Nedge > 0)for(j=0,ep=MainEp;j<Nedge;j++,ep++){
00938    v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00939    if(v0->status == SELECTED && v1->status == SELECTED)ne++;
00940  }
00941  Nvert1=NvertSelect;
00942  Nedge1=ne;
00943  if(ne > 0){
00944    xp=(xtraedge *)
00945    X__Malloc(ne*sizeof(xtraedge));
00946    if(xp == NULL){
00947      SendPrgmQuery(IDQ_NOMEM2,0);
00948      return FALSE;
00949    }
00950    i=0; ep=MainEp; for(j=0;j<Nedge;j++,ep++){  /* selected edge */
00951      v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00952      if(v0->status == SELECTED && v1->status == SELECTED){
00953        xp[i].ep = j; xp[i].nc=0; i++;
00954      }
00955    }
00956    if(i != ne){
00957      SendPrgmQuery(IDQ_EDGEINCONSISTANT,0);
00958      X__Free(xp);
00959      return FALSE;
00960    }
00961    for(i=0;i<ne;i++){
00962      vl=(MainVp+(MainEp+xp[i].ep)->V[0]);
00963      vr=(MainVp+(MainEp+xp[i].ep)->V[1]);
00964      fp=MainFp; if(Nface > 0)for(j=0;j<Nface;j++,fp++){
00965        v0=(MainVp+fp->V[0]); v1=(MainVp+fp->V[1]); v2=(MainVp+fp->V[2]);
00966        if(v0->status == SELECTED &&
00967           v1->status == SELECTED &&
00968           v2->status == SELECTED){
00969          if((vl == v0 && vr == v1) || (vl == v1 && vr == v0))xp[i].nc++;
00970          if((vl == v1 && vr == v2) || (vl == v2 && vr == v1))xp[i].nc++;
00971          if((vl == v2 && vr == v0) || (vl == v0 && vr == v2))xp[i].nc++;
00972        }
00973      }
00974    }
00975  }
00976  fp=MainFp; if(Nface > 0)for(i=0;i<Nface;i++,fp++){
00977    v0=(MainVp+fp->V[0]); v1=(MainVp+fp->V[1]); v2=(MainVp+fp->V[2]);
00978    if(v0->status == SELECTED &&
00979       v1->status == SELECTED &&
00980       v2->status == SELECTED)Nface1++;
00981  }
00982  if(open == 2 && Nedge > 0){ /* make a list of the vertices that are joined */
00983    uuecount=0;
00984    for(i=0,ep=MainEp;i<Nedge;i++){
00985      v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00986      if((v0->status == DESELECTED && v1->status == SELECTED) ||
00987         (v1->status == DESELECTED && v0->status == SELECTED))
00988        uuecount++;
00989      ep++;
00990    }
00991    if((vve=(vertexvertexedge *)X__Malloc(uuecount*sizeof(vertexvertexedge)))
00992       == NULL){
00993      open=1; uuecount=0;
00994    }
00995    else{
00996      uuecount=0;
00997      for(i=0,ep=MainEp;i<Nedge;i++){
00998        v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00999        if((v0->status == DESELECTED && v1->status == SELECTED) ||
01000           (v1->status == DESELECTED && v0->status == SELECTED)){
01001          if(v0->status == SELECTED){
01002            vve[uuecount].vs=ep->V[0];
01003            vve[uuecount].vd=ep->V[1];
01004          }
01005          else{
01006            vve[uuecount].vs=ep->V[1];
01007            vve[uuecount].vd=ep->V[0];
01008          }
01009          uuecount++;
01010        }
01011        ep++;
01012      }
01013    }
01014  }
01015  if(!UpdateVertexHeap(Nvert+Nvert1))return FALSE;
01016  if(!UpdateEdgeHeap(Nedge+Nvert1+Nedge1*2+uuecount))return FALSE;
01017  if(!UpdateFaceHeap(Nface+Nface1+Nedge1*2+uuecount))return FALSE;
01018  Nvert1=Nvert; Nedge1=Nedge; Nface1=Nface;
01019  vp=MainVp; for(j=0;j<Nvert1;j++){
01020    if(vp->status == SELECTED) {
01021      addit=0;
01022      if(ne > 0)for(i=0;i<ne;i++){
01023        if((
01024            (MainEp+xp[i].ep)->V[0] == j || (MainEp+xp[i].ep)->V[1] == j)
01025         && (xp[i].nc < 2))addit=1;
01026      }
01027      else addit=1;
01028      CreateVertex();
01029      Vp=(MainVp+Nvert-1);
01030      Vp->xyz[0]=vp->xyz[0];
01031      Vp->xyz[1]=vp->xyz[1];
01032      Vp->xyz[2]=vp->xyz[2];
01033      Vp->gp=vp->gp;
01034      if(Vp->gp == 1){
01035        Vp->x=vp->x;
01036        Vp->y=vp->y;
01037      }
01038      if(addit)CreateEdge(j,Nvert-1);
01039      Vp->status=DESELECTED;
01040      vp->id=Nvert-1;
01041      NvertSelect--;NvertDeselect++;
01042   }
01043   vp++;
01044  }
01045  i=0; if(Nedge > 0)for(ep=MainEp,j=0;j<Nedge1;j++){
01046    v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
01047    if(v0->status == SELECTED &&
01048       v1->status == SELECTED){
01049       CreateEdge(v0->id,v1->id);
01050       if(xp[i].nc < 2){
01051         CreateEdge(v0->id,ep->V[1]);
01052         CreateFace(v0->id,v1->id,ep->V[1]);
01053         CreateFace(v0->id,ep->V[1],ep->V[0]);
01054       }
01055       i++;
01056    }
01057    ep++;
01058  }
01059  if(Nface1 > 0)for(fp=MainFp,j=0;j<Nface1;j++){ /* put in faces that are copies */
01060    v0=(MainVp+fp->V[0]); v1=(MainVp+fp->V[1]); v2=(MainVp+fp->V[2]);
01061    if(v0->status == SELECTED &&
01062       v1->status == SELECTED &&
01063       v2->status == SELECTED) {
01064      CreateFace(v0->id,v1->id,v2->id);
01065      CopyFaceProp(fp,(MainFp+Nface-1));
01066    }
01067    fp++;
01068  }
01069  if(open == 2 && uuecount > 0){ /* add the connection edge and face */
01070    for(i=0;i<uuecount;i++){
01071      k=(MainVp+vve[i].vs)->id;
01072      CreateEdge(vve[i].vd,k);
01073      CreateFace(vve[i].vd,vve[i].vs,k);
01074    }
01075    X__Free(vve);
01076  }
01077  vp=MainVp; for(j=0;j<Nvert1;j++){
01078    if(vp->status == SELECTED){
01079      vp->status=DESELECTED;
01080      (MainVp+vp->id)->status=SELECTED;
01081    }
01082    vp++;
01083  }
01084  UpdateFaceHeap(Nface);    /* release any storage that was given as  */
01085  UpdateEdgeHeap(Nedge);    /* an over estimate when it was allocated */
01086  if(ne > 0)X__Free(xp);
01087  return TRUE;
01088 }
01089 
01090 BOOL Extrude(int command){
01091  HCURSOR hSave;
01092  static double dx_extrude=0.0,dy_extrude=0.0,dz_extrude=0.0;
01093  long Vstart,i,com,loop_count=1;
01094  double dmap=1.0;
01095  vertex *vp;
01096  long x,y,z;
01097  if(NvertSelect < 1)return FALSE;
01098  if(NvertSelect > 32000){
01099    SendPrgmQuery(IDQ_WIRETOOBIG,0);
01100    return FALSE;
01101  }
01102  Vstart=Nvert;
01103 // if((dos_key_shift() & 0x04) == 0x04){
01104 //   command=1; loop_count=1;
01105 //   if((loop_count=Read3Reals("Extrude by",&dx_extrude,&dy_extrude,
01106 //      &dz_extrude,0,2)) == 0)return FALSE;
01107 //   dmap=1.0/(double)loop_count;
01108 // }
01109  hSave=SetCursor(ghcurWait);
01110 // if((dos_key_shift() & 0x08) == 0x08)com=2; /* left ALT key */
01111 // else                                com=1;
01112  com=1;
01113  NEXT_LOOP:
01114  if(!CreateAttachedCopy(com)){ /* it failed */
01115    SetCursor(hSave);
01116    return FALSE;
01117  }
01118  if(command == 0){
01119    if(Nvert > Vstart){
01120      for(i=Vstart,vp=(MainVp+Vstart);i<Nvert;i++,vp++){
01121        if(vp->status == SELECTED && vp->gp == 1){
01122           vp->y += 1.0; /* to increment the applied map */
01123        }
01124      }
01125    }
01126    return TRUE;
01127  }
01128  x=(long)(dx_extrude*ruler)+lrulerx;
01129  y=(long)(dy_extrude*ruler)+lrulery;
01130  z=(long)(dz_extrude*ruler)+lrulerz;
01131  if(Nvert > Vstart)for(i=Vstart,vp=(MainVp+Vstart);i<Nvert;i++,vp++){
01132    if(vp->status == SELECTED){
01133      vp->xyz[0] += x; vp->xyz[1] += y; vp->xyz[2] += z;
01134      if(vp->gp == 1){
01135        vp->y += dmap; /* to increment the applied map */
01136      }
01137    }
01138  }
01139  loop_count--; if(loop_count > 0)goto NEXT_LOOP;
01140  SetCursor(hSave);
01141  do_NOT_abort=TRUE;
01142  DrawModel();
01143  do_NOT_abort=FALSE;
01144  return FALSE;
01145 }
01146 
01147 static void Ixpand(void){
01148  double s,sx,sy,sz,sxx,syy,szz;
01149  int x,xo,MickeyX,I,flag=0;
01150  POINT pt;
01151  long evTime;
01152  GetCursorPos(&pt); xo=pt.x;
01153  sxx=syy=szz=1.0;
01154  ClipCursor(NULL);
01155  if(!Mxpand){
01156    GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
01157  }
01158  evTime=GetTickCount()+TIME_DELAY;
01159  do {
01160    if(evTime > GetTickCount())continue;
01161    GetCursorPos(&pt); x=pt.x;
01162    MickeyX = x-xo; xo=x;
01163    if(MickeyX != 0){
01164      flag=1;
01165      if(MickeyX > 0)I=max( 1,min( 50,MickeyX));
01166      else           I=min(-1,max(-50,MickeyX));
01167      DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
01168                         grab_xmax,grab_ymax,grab_zmax);
01169      sx=sy=sz=1.0; s=(double)(I)/55.0;
01170      if     (GetAsyncKeyState(VK_SHIFT)   & 0x8000)sy += s;
01171      else if(GetAsyncKeyState(VK_CONTROL) & 0x8000)sz += s;
01172      else if(GetAsyncKeyState(VK_MENU)    & 0x8000)sx += s;
01173      else {sx += s; sy += s; sz += s;}
01174      grab_xmin = (long)((double)(grab_xmin-GrabonX)*sx)+GrabonX;
01175      grab_xmax = (long)((double)(grab_xmax-GrabonX)*sx)+GrabonX;
01176      grab_ymin = (long)((double)(grab_ymin-GrabonY)*sy)+GrabonY;
01177      grab_ymax = (long)((double)(grab_ymax-GrabonY)*sy)+GrabonY;
01178      grab_zmin = (long)((double)(grab_zmin-GrabonZ)*sz)+GrabonZ;
01179      grab_zmax = (long)((double)(grab_zmax-GrabonZ)*sz)+GrabonZ;
01180      sxx *= sx; syy *= sy; szz *= sz;
01181      DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
01182                         grab_xmax,grab_ymax,grab_zmax);
01183      XpandNurbsSurface(ActiveView,0,sx,sy,sz);
01184    }
01185    evTime=GetTickCount()+TIME_DELAY;
01186  }
01187  while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01188  if(flag && !(GetAsyncKeyState(VK_RBUTTON) & 0x8000)){
01189    int i;
01190    vertex *vp;
01191    flag=0;
01192    grab_xmin=grab_ymin=grab_zmin =  MAXUNIT;
01193    grab_xmax=grab_ymax=grab_zmax = -MAXUNIT;
01194    if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
01195      if(vp->status == SELECTED){
01196        vp->xyz[0]=(long)((double)(vp->xyz[0]-GrabonX)*sxx)+GrabonX;
01197        vp->xyz[1]=(long)((double)(vp->xyz[1]-GrabonY)*syy)+GrabonY;
01198        vp->xyz[2]=(long)((double)(vp->xyz[2]-GrabonZ)*szz)+GrabonZ;
01199        if(vp->xyz[0] > grab_xmax)grab_xmax=vp->xyz[0];
01200        if(vp->xyz[0] < grab_xmin)grab_xmin=vp->xyz[0];
01201        if(vp->xyz[1] > grab_ymax)grab_ymax=vp->xyz[1];
01202        if(vp->xyz[1] < grab_ymin)grab_ymin=vp->xyz[1];
01203        if(vp->xyz[2] > grab_zmax)grab_zmax=vp->xyz[2];
01204        if(vp->xyz[2] < grab_zmin)grab_zmin=vp->xyz[2];
01205      }
01206      vp++;
01207    }
01208    RecalibrateAllBezier(); RecalibrateMapLocks();
01209    do_NOT_abort=1;
01210    DrawModel();
01211    do_NOT_abort=0;
01212    sxx=syy=szz=1.0;
01213  }
01214  else{
01215    DrawRubberBoundBox(grab_xmin,grab_ymin,grab_zmin,
01216                       grab_xmax,grab_ymax,grab_zmax);
01217    XpandNurbsSurface(ActiveView,-1,0.0,0.0,0.0);
01218  }
01219  return;
01220 }
01221 
01222 static void Irotate(void){
01223  double beta=0.0,ctheta=0.0,stheta=0.0;
01224  int angle=0,bngle=0,x,xo,MickeyX,I,flag=0;
01225  POINT pt;
01226  long xp,yp,evTime;
01227  GetCursorPos(&pt); xo=pt.x;
01228  RotatorTheta=0.0;
01229  ClipCursor(NULL);
01230  if(!Mxpand){
01231    GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
01232  }
01233  evTime=GetTickCount()+TIME_DELAY;
01234  do {
01235    if(evTime > GetTickCount())continue;
01236    GetCursorPos(&pt); x=pt.x;
01237    MickeyX = x-xo; xo=x;
01238    if(MickeyX != 0){
01239      flag=1;
01240      if(MickeyX > 0)I=max( 1,min( 45,MickeyX));
01241      else           I=min(-1,max(-45,MickeyX));
01242      if((GetAsyncKeyState(VK_SHIFT) & 0x8000) == 0x8000){
01243        /* constrain 45 degrees if SHIFT key */
01244        if(abs(I) < 22)I=0;
01245        else{
01246          if(I < 0)I = -45;
01247          else     I =  45;
01248        }
01249      }
01250      DrawIrotateBoundBox(ActiveView,RotatorTheta);
01251      angle -= I;
01252      if     (angle >  180)angle -= 360;
01253      else if(angle < -180)angle += 360;
01254      RotatorTheta = angle*PI/180.0;
01255      bngle -= I;
01256      if     (bngle >  180)bngle -= 360;
01257      else if(bngle < -180)bngle += 360;
01258      DrawIrotateBoundBox(ActiveView,RotatorTheta);
01259      RotateNurbsSurface(ActiveView,0,RotatorTheta);
01260    }
01261    evTime=GetTickCount()+TIME_DELAY;
01262  }
01263  while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01264  if(flag && !(GetAsyncKeyState(VK_RBUTTON) & 0x8000)){
01265    int i;
01266    vertex *vp;
01267    flag=0;
01268    beta = bngle*PI/180.0; bngle=0;
01269    ctheta=cos(beta); stheta=sin(beta);
01270    if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
01271      if(vp->status == SELECTED){
01272        if(ActiveView == TRITOP){
01273          RotatePointAbout(vp->xyz[0],vp->xyz[1],GrabonX,GrabonY,
01274                           &xp,&yp,ctheta,stheta);
01275          vp->xyz[0]=xp; vp->xyz[1]=yp;
01276        }
01277        else if(ActiveView == TRIFRONT){
01278          RotatePointAbout(vp->xyz[0],vp->xyz[2],GrabonX,GrabonZ,
01279                           &xp,&yp,ctheta,stheta);
01280          vp->xyz[0]=xp; vp->xyz[2]=yp;
01281        }
01282        else if(ActiveView == TRIRIGHT){
01283          RotatePointAbout(vp->xyz[1],vp->xyz[2],GrabonY,GrabonZ,
01284                           &xp,&yp,ctheta,stheta);
01285          vp->xyz[1]=xp; vp->xyz[2]=yp;
01286        }
01287      }
01288      vp++;
01289    }
01290    RecalibrateAllBezier(); RecalibrateMapLocks();
01291    do_NOT_abort=1;
01292    DrawModel();
01293    do_NOT_abort=0;
01294  }
01295  else {
01296    DrawIrotateBoundBox(ActiveView,RotatorTheta);
01297    RotateNurbsSurface(ActiveView,-1,0.0);
01298  }
01299  return;
01300 }
01301 
01302 static void RotatePointAbout(long x, long y, long X, long Y, long *tx,
01303                              long *ty, double ctheta, double stheta){
01304  double dx,dy;
01305  dx=(double)(x-X);
01306  dy=(double)(y-Y);
01307  *tx = X+(long)(ctheta*dx-stheta*dy);
01308  *ty = Y+(long)(stheta*dx+ctheta*dy);
01309 }
01310 
01311 static void DrawIrotateBoundBox(int i, double theta){
01312  int  xs1,xs2,xs3,xs4,ys1,ys2,ys3,ys4;
01313  long xp,yp;
01314  double c,s;
01315  RECT rc;
01316  HDC hDC;
01317  hDC=GetDC(ghwnd_triview[i]);
01318  SelectObject(hDC,ghInvertPen);
01319  SetROP2(hDC,R2_XORPEN);
01320  SelectPalette(hDC,ghpaletteScreen,FALSE);
01321  RealizePalette(hDC);
01322  c=cos(theta); s=sin(theta);
01323  if(i == TRITOP){
01324    RotatePointAbout(grab_xmin,grab_ymin,GrabonX,GrabonY,&xp,&yp,c,s);
01325    GetWindowCoords(i,xp,yp,GrabonZ,&xs1,&ys1);
01326    RotatePointAbout(grab_xmax,grab_ymin,GrabonX,GrabonY,&xp,&yp,c,s);
01327    GetWindowCoords(i,xp,yp,GrabonZ,&xs2,&ys2);
01328    RotatePointAbout(grab_xmax,grab_ymax,GrabonX,GrabonY,&xp,&yp,c,s);
01329    GetWindowCoords(i,xp,yp,GrabonZ,&xs3,&ys3);
01330    RotatePointAbout(grab_xmin,grab_ymax,GrabonX,GrabonY,&xp,&yp,c,s);
01331    GetWindowCoords(i,xp,yp,GrabonZ,&xs4,&ys4);
01332  }
01333  else if(i == TRIFRONT){
01334    RotatePointAbout(grab_xmin,grab_zmin,GrabonX,GrabonZ,&xp,&yp,c,s);
01335    GetWindowCoords(i,xp,GrabonY,yp,&xs1,&ys1);
01336    RotatePointAbout(grab_xmax,grab_zmin,GrabonX,GrabonZ,&xp,&yp,c,s);
01337    GetWindowCoords(i,xp,GrabonY,yp,&xs2,&ys2);
01338    RotatePointAbout(grab_xmax,grab_zmax,GrabonX,GrabonZ,&xp,&yp,c,s);
01339    GetWindowCoords(i,xp,GrabonY,yp,&xs3,&ys3);
01340    RotatePointAbout(grab_xmin,grab_zmax,GrabonX,GrabonZ,&xp,&yp,c,s);
01341    GetWindowCoords(i,xp,GrabonY,yp,&xs4,&ys4);
01342  }
01343  else if(i == TRIRIGHT){
01344    RotatePointAbout(grab_ymin,grab_zmin,GrabonY,GrabonZ,&xp,&yp,c,s);
01345    GetWindowCoords(i,GrabonY,xp,yp,&xs1,&ys1);
01346    RotatePointAbout(grab_ymax,grab_zmin,GrabonY,GrabonZ,&xp,&yp,c,s);
01347    GetWindowCoords(i,GrabonY,xp,yp,&xs2,&ys2);
01348    RotatePointAbout(grab_ymax,grab_zmax,GrabonY,GrabonZ,&xp,&yp,c,s);
01349    GetWindowCoords(i,GrabonY,xp,yp,&xs3,&ys3);
01350    RotatePointAbout(grab_ymin,grab_zmax,GrabonY,GrabonZ,&xp,&yp,c,s);
01351    GetWindowCoords(i,GrabonY,xp,yp,&xs4,&ys4);
01352  }
01353  DrawOne3dCursor(hDC,i);
01354  MoveToEx(hDC,xs1,ys1,NULL);
01355  LineTo(hDC,xs2,ys2); LineTo(hDC,xs3,ys3);
01356  LineTo(hDC,xs4,ys4); LineTo(hDC,xs1,ys1);
01357  DrawOne3dCursor(hDC,i);
01358  ReleaseDC(ghwnd_triview[i],hDC);
01359 }
01360 
01361 static void ShapeShape(int id){
01362  int x,xo,MickeyX,I;
01363  POINT pt;
01364  long xp,yp,evTime;
01365  double c;
01366  GetCursorPos(&pt); xo=pt.x;
01367  RotatorTheta=0.0;
01368  ClipCursor(NULL);
01369  evTime=GetTickCount()+TIME_DELAY;
01370  do {
01371    if(evTime > GetTickCount())continue;
01372    GetCursorPos(&pt); x=pt.x;
01373    MickeyX = x-xo; xo=x;
01374    if(MickeyX != 0){
01375      if(MickeyX > 0)I=max( 1,min( 50,MickeyX));
01376      else           I=min(-1,max(-50,MickeyX));
01377      DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
01378                     shaper_angle_theta,shaper_angle_phi,shaper_size);
01379      c=(1.0-(double)I/50.0); c=min(c,1.2); c=max(c,0.8);
01380      if(id == 0){     /* ctrl */
01381        shaper_size *= c;
01382        if(shaper_size < 0.3)shaper_size=0.3;
01383        if(shaper_size > 50.)shaper_size=50.;
01384      }
01385      else if(id == 1){ /* shift = longditude */
01386        shaper_angle_phi += I*PI/180;
01387        if(shaper_angle_phi >  PI)shaper_angle_phi -= PI*2;
01388        if(shaper_angle_phi < -PI)shaper_angle_phi += PI*2;
01389      }
01390      else if(id == 2){ /* alt  = latitide */
01391        shaper_angle_theta += I*PI/180;;
01392        if(shaper_angle_theta >  PI)shaper_angle_theta -= PI*2;
01393        if(shaper_angle_theta < -PI)shaper_angle_theta += PI*2;
01394      }
01395      DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
01396                     shaper_angle_theta,shaper_angle_phi,shaper_size);
01397    }
01398    evTime=GetTickCount()+TIME_DELAY;
01399  }
01400  while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01401  return;
01402 }
01403 
01404 static void Shape(void){
01405  long i;
01406  vector shaper_direction={0.0,0.0,1.0};
01407  vertex *vp;
01408  double mu1,mu2,r2,sx,sy,sz,b,c,rt;
01409  vector vnc;
01410  shaper_direction[2]=cos(shaper_angle_theta);
01411  shaper_direction[0]=cos(shaper_angle_phi)*sin(shaper_angle_theta);
01412  shaper_direction[1]=sin(shaper_angle_phi)*sin(shaper_angle_theta);
01413  r2=((double)TVsizeX/shaper_size)*((double)TVsizeX/shaper_size);
01414  vp=MainVp; if(MainVp != NULL && Nvert > 0)for(i=0;i<Nvert;i++){
01415    if(vp->status != SELECTED)continue;
01416    vnc[0]=(double)(vp->xyz[0]-GrabonX);
01417    vnc[1]=(double)(vp->xyz[1]-GrabonY);
01418    vnc[2]=(double)(vp->xyz[2]-GrabonZ);
01419    b=2*DOT(vnc,shaper_direction);
01420    c=DOT(vnc,vnc)-r2;
01421    rt=(b*b-4.0*c);
01422    if(rt > 0.0){ /* the vector intersects the sphere */
01423      rt=sqrt(rt);
01424      mu1 = (-b+rt)*0.5;
01425      mu2 = (-b-rt)*0.5;
01426      if(mu1 > mu2){  /* order the intersections */
01427        c=mu1; mu1=mu2; mu2=c;
01428      }
01429      if(mu1 < 0.0 && mu2 > 0.0){/* vertex is inside the sphere */
01430        vp->xyz[0] += (long)(mu2*shaper_direction[0]);
01431        vp->xyz[1] += (long)(mu2*shaper_direction[1]);
01432        vp->xyz[2] += (long)(mu2*shaper_direction[2]);
01433      }
01434    }
01435    vp++;
01436  }
01437  RecalibrateAllBezier(); RecalibrateMapLocks();
01438  do_NOT_abort=TRUE;
01439  DrawModel();
01440  do_NOT_abort=FALSE;
01441  DrawShaperSphere(GrabonX,GrabonY,GrabonZ,
01442                   shaper_angle_theta,shaper_angle_phi,shaper_size);
01443 }
01444 
01445 static void FormerDown(void){
01446  long i,j;
01447  vertex *vp;
01448  shaper_list=NULL;
01449  bShaperMoved=FALSE;
01450  if(NvertSelect < 1)return;
01451  if((shaper_list=X__Malloc(NvertSelect*sizeof(point))) != NULL){
01452    for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01453      if(vp->status != SELECTED)continue;
01454      VECCOPY(vp->xyz,shaper_list[j])
01455      j++;
01456    }
01457  }
01458  return;
01459 }
01460 
01461 static void FormerUp(void){
01462  if(shaper_list !=NULL)X__Free(shaper_list);
01463  shaper_list=NULL;
01464  if(!bShaperMoved)return;
01465  RecalibrateAllBezier(); RecalibrateMapLocks();
01466  if(ghwndOpenGLview != NULL)PostMessage(ghwndOpenGLview,(WM_USER+2),0,0);
01467  do_NOT_abort=TRUE;
01468  DrawModel();
01469  do_NOT_abort=FALSE;
01470 }
01471 
01472 static void FormerMove(void){
01473  long i,j;
01474  double z,zmax,scale;
01475  vertex *vp;
01476  vector po,dx,gon;
01477  bShaperMoved=TRUE;
01478  if(shaper_list == NULL)return;
01479  zmax=((double)TVsizeX/shaper_size);
01480  zmax=zmax*zmax;
01481  dx[0]=NpointerX-(gon[0]=GrabonX);
01482  dx[1]=NpointerY-(gon[1]=GrabonY);
01483  dx[2]=NpointerZ-(gon[2]=GrabonZ);
01484  for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01485    if(vp->status != SELECTED)continue;
01486    VECCOPY((double)shaper_list[j],po)
01487    z=(po[0]-gon[0])*(po[0]-gon[0])+
01488      (po[1]-gon[1])*(po[1]-gon[1])+
01489      (po[2]-gon[2])*(po[2]-gon[2]);
01490    if(z < zmax){
01491      scale=(1.0-z/zmax);
01492      if(GetAsyncKeyState(VK_SHIFT) & 0x8000){scale = scale*scale*scale*scale;}
01493      else  scale *= scale;  // different models
01494      VECSUM(po,scale*dx,vp->xyz)
01495    }
01496    j++;
01497  }
01498  DrawQuickModel();
01499 }
01500 
01501 static void ShearerDown(void){
01502  long i,j,id,c,cc;
01503  vertex *vp;
01504  shaper_list=NULL;
01505  bShaperMoved=FALSE;
01506  if(NvertSelect < 1)return;
01507  if     (ActiveView == TRITOP)  {id=2; c=NpointerZ;}
01508  else if(ActiveView == TRIFRONT){id=1; c=NpointerY;}
01509  else if(ActiveView == TRIRIGHT){id=0; c=NpointerX;}
01510  GrabDx=0;
01511  if((shaper_list=X__Malloc(NvertSelect*sizeof(point))) != NULL){
01512    for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01513      if(vp->status != SELECTED)continue;
01514      if((cc=labs(vp->xyz[id]-c)) > GrabDx)GrabDx=cc;
01515      VECCOPY(vp->xyz,shaper_list[j])
01516      j++;
01517    }
01518  }
01519  return;
01520 }
01521 
01522 static void ShearerUp(void){
01523  if(shaper_list !=NULL)X__Free(shaper_list);
01524  shaper_list=NULL;
01525  if(!bShaperMoved)return;
01526  RecalibrateAllBezier(); RecalibrateMapLocks();
01527  if(ghwndOpenGLview != NULL)PostMessage(ghwndOpenGLview,(WM_USER+2),0,0);
01528  do_NOT_abort=TRUE;
01529  DrawModel();
01530  do_NOT_abort=FALSE;
01531 }
01532 
01533 static void ShearerMove(int x, int y){
01534  long i,j,id,type;
01535  vertex *vp;
01536  vector po,dx,gon;
01537  double z,l;
01538  bShaperMoved=TRUE;
01539  if(shaper_list == NULL)return;
01540 
01541  if((GetAsyncKeyState(VK_MENU) & 0x8000) &&
01542     (GetAsyncKeyState(VK_CONTROL) & 0x8000)){ // curl
01543    long id1,id2,c1,c2,cc;
01544    l=(double)(x-x_down);
01545    if(l > 0.0)l=min(360.0,l*1.5);
01546    else       l=max(-360.0,l*1.5);
01547    if     (ActiveView == TRITOP)  {id1=1; c1=GrabonY;}
01548    else if(ActiveView == TRIFRONT){id1=2; c1=GrabonZ;}
01549    else if(ActiveView == TRIRIGHT){id1=2; c1=GrabonZ;}
01550    GrabDx=0;
01551    for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01552      if(vp->status != SELECTED)continue;
01553      if((cc=labs((long)shaper_list[j][id1]-c1)) > GrabDx)GrabDx=cc;
01554      j++;
01555    }
01556    gon[0]=GrabonX;
01557    gon[1]=GrabonY;
01558    gon[2]=GrabonZ;
01559    for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01560      if(vp->status != SELECTED)continue;
01561      VECCOPY((double)shaper_list[j],po)
01562      z=fabs(po[id1]-gon[id1]);
01563      if(GrabDx > 1.0){
01564        long xp,yp;
01565        double beta,ctheta,stheta;
01566        if(GetAsyncKeyState(VK_SHIFT) & 0x8000)z=(1.0 - z/(double)GrabDx);
01567        else                                   z=z/(double)GrabDx;
01568        beta = l*z*PI/180.0;
01569        ctheta=cos(beta); stheta=sin(beta);
01570        if(ActiveView == TRITOP){
01571          RotatePointAbout((long)po[0],(long)po[1],GrabonX,GrabonY,
01572                           &xp,&yp,ctheta,stheta);
01573          vp->xyz[0]=xp; vp->xyz[1]=yp;
01574        }
01575        else if(ActiveView == TRIFRONT){
01576          RotatePointAbout((long)po[0],(long)po[2],GrabonX,GrabonZ,
01577                           &xp,&yp,ctheta,stheta);
01578          vp->xyz[0]=xp; vp->xyz[2]=yp;
01579        }
01580        else if(ActiveView == TRIRIGHT){
01581          RotatePointAbout((long)po[1],(long)po[2],GrabonY,GrabonZ,
01582                           &xp,&yp,ctheta,stheta);
01583          vp->xyz[1]=xp; vp->xyz[2]=yp;
01584                 }
01585      }
01586      j++;
01587    }
01588    DrawQuickModel();
01589    return;
01590  }
01591 
01592 
01593  dx[0]=NpointerX-(gon[0]=GrabonX);
01594  dx[1]=NpointerY-(gon[1]=GrabonY);
01595  dx[2]=NpointerZ-(gon[2]=GrabonZ);
01596  if     (ActiveView == TRITOP)  {dx[2]=0; id=2;}
01597  else if(ActiveView == TRIFRONT){dx[1]=0; id=1;}
01598  else if(ActiveView == TRIRIGHT){dx[0]=0; id=0;}
01599  if(GetAsyncKeyState(VK_MENU) & 0x8000){  // taper
01600    l=(double)(x-x_down);
01601    if(l < 0.0)l =  min(1.0,fabs(l)/100.0);
01602    else       l = -min(1.0,l/100.0);
01603    type=1;
01604  }
01605  else if(GetAsyncKeyState(VK_CONTROL) & 0x8000){ // twist
01606    l=(double)(x-x_down);
01607    if(l > 0.0)l=min(360.0,l*1.5);
01608    else       l=max(-360.0,l*1.5);
01609    type=2;
01610  }
01611  else{
01612    type=0;
01613  }
01614  for(i=0,j=0,vp=MainVp;i<Nvert;i++,vp++){
01615    if(vp->status != SELECTED)continue;
01616    VECCOPY((double)shaper_list[j],po)
01617    z=fabs(po[id]-gon[id]);
01618    if(GrabDx > 1.0){
01619      z=(1.0 - z/(double)GrabDx);
01620      if(GetAsyncKeyState(VK_SHIFT) & 0x8000)z=z*z;
01621      if(type == 1){ // taper
01622        vector d;
01623        VECSUB(gon,po,d)
01624        if     (ActiveView == TRITOP)  d[2]=0;
01625        else if(ActiveView == TRIFRONT)d[1]=0;
01626        else if(ActiveView == TRIRIGHT)d[0]=0;
01627        VECSUM(po,l*z*d,vp->xyz)
01628      }
01629      else if(type == 2){  // twist
01630        long xp,yp;
01631        double beta,ctheta,stheta;
01632        beta = l*z*PI/180.0;
01633        ctheta=cos(beta); stheta=sin(beta);
01634        if(ActiveView == TRITOP){
01635          RotatePointAbout((long)po[0],(long)po[1],GrabonX,GrabonY,
01636                           &xp,&yp,ctheta,stheta);
01637          vp->xyz[0]=xp; vp->xyz[1]=yp;
01638        }
01639        else if(ActiveView == TRIFRONT){
01640          RotatePointAbout((long)po[0],(long)po[2],GrabonX,GrabonZ,
01641                           &xp,&yp,ctheta,stheta);
01642          vp->xyz[0]=xp; vp->xyz[2]=yp;
01643        }
01644        else if(ActiveView == TRIRIGHT){
01645          RotatePointAbout((long)po[1],(long)po[2],GrabonY,GrabonZ,
01646                           &xp,&yp,ctheta,stheta);
01647          vp->xyz[1]=xp; vp->xyz[2]=yp;
01648        }
01649      }
01650      else{ // shear
01651        VECSUM(po,z*dx,vp->xyz)
01652      }
01653    }
01654    j++;
01655  }
01656  DrawQuickModel();
01657 }
01658 
01659 static int PanX,PanY,ZoomX,ZoomY,ZoomRX,ZoomRY;
01660 static BOOL ZoomInFlag=FALSE,PanMoveFlag=FALSE;
01661 static HDC hDCzoom;
01662 
01663 void PanToolUp(int x, int y, BOOL ctrl, BOOL shift, HWND hwnd){
01664  double zf=2.0;
01665  long a,b,c,d,e,f,stor;
01666  if(ZoomInFlag){
01667    Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
01668    ReleaseDC(hwnd,hDCzoom);
01669    ZoomInFlag=FALSE;
01670    if(!ctrl)return;
01671    if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
01672 //     SendPrgmMessage(IDS_NOZOOMIN,1);
01673      MessageBeep(MB_OK);
01674      return;
01675    }
01676    if(ActiveView == TRITOP){
01677      stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
01678    }
01679    else if(ActiveView == TRIFRONT){
01680      stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
01681    }
01682    else{
01683      stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
01684    }
01685    GetWorldCoords(ActiveView,&a,&b,&c,(ZoomX+ZoomRX)/2,(ZoomY+ZoomRY)/2);
01686    zf=(double)max(abs(ZoomX-ZoomRX),abs(ZoomY-ZoomRY))/
01687       (double)(max(WindowSizeX[ActiveView],WindowSizeY[ActiveView]));
01688    TVsizeX=(long)((double)TVsizeX*zf);
01689    TVsizeY=(long)((double)TVsizeY*zf);
01690    TVsizeZ=(long)((double)TVsizeZ*zf);
01691    WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
01692    TVpointX=a-TVsizeX/2; TVcentreX=a;
01693    TVpointY=b-TVsizeY/2; TVcentreY=b;
01694    TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
01695    if(ActiveView == TRITOP)NpointerZ=stor;
01696    else if(ActiveView == TRIFRONT)NpointerY=stor;
01697    else NpointerX=stor;
01698  }
01699  else if(ctrl){
01700    if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
01701 //     SendPrgmMessage(IDS_NOZOOMIN,1);
01702      MessageBeep(MB_OK);
01703    }
01704    else{
01705      if(ActiveView == TRITOP){
01706        stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
01707      }
01708      else if(ActiveView == TRIFRONT){
01709        stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
01710      }
01711      else{
01712        stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
01713      }
01714      GetWorldCoords(ActiveView,&a,&b,&c,x,y);
01715      TVsizeX=(long)((double)TVsizeX/zf);   /* like a zoom */
01716      TVsizeY=(long)((double)TVsizeY/zf);
01717      TVsizeZ=(long)((double)TVsizeZ/zf);
01718      WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
01719      TVpointX=a-TVsizeX/2; TVcentreX=a;
01720      TVpointY=b-TVsizeY/2; TVcentreY=b;
01721      TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
01722      if(ActiveView == TRITOP)NpointerZ=stor;
01723      else if(ActiveView == TRIFRONT)NpointerY=stor;
01724      else NpointerX=stor;
01725    }
01726  }
01727  else if(shift){
01728    if(TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT){
01729 //     SendPrgmMessage(IDS_NOZOOMOUT,1);
01730      MessageBeep(MB_OK);
01731    }
01732    else{
01733      if(ActiveView == TRITOP){
01734        stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
01735      }
01736      else if(ActiveView == TRIFRONT){
01737        stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
01738      }
01739      else{
01740        stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
01741      }
01742      GetWorldCoords(ActiveView,&a,&b,&c,x,y);
01743      TVsizeX=(long)((double)TVsizeX*zf);
01744      TVsizeY=(long)((double)TVsizeY*zf);
01745      TVsizeZ=(long)((double)TVsizeZ*zf);
01746      WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
01747      TVpointX=a-TVsizeX/2; TVcentreX=a;
01748      TVpointY=b-TVsizeY/2; TVcentreY=b;
01749      TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
01750      if(ActiveView == TRITOP)NpointerZ=stor;
01751      else if(ActiveView == TRIFRONT)NpointerY=stor;
01752      else NpointerX=stor;
01753    }
01754  }
01755  if(NpointerX < TVpointX)NpointerX=TVpointX+TVsizeX/2;
01756  if(NpointerX > TVpointX+TVsizeX)NpointerX=TVpointX+TVsizeX/2;
01757  if(NpointerY < TVpointY)NpointerY=TVpointY+TVsizeY/2;
01758  if(NpointerY > TVpointY+TVsizeY)NpointerY=TVpointY+TVsizeY/2;
01759  if(NpointerZ < TVpointZ)NpointerZ=TVpointZ+TVsizeZ/2;
01760  if(NpointerZ > TVpointZ+TVsizeZ)NpointerZ=TVpointZ+TVsizeZ/2;
01761  if(ghwndOpenGLview != NULL)PostMessage(ghwndOpenGLview,(WM_USER+2),0,0);
01762  do_NOT_abort=TRUE;
01763  DrawModel();
01764  do_NOT_abort=FALSE;
01765  UpdateCounters();
01766 }
01767 
01768 BOOL PanToolDown(int x, int y, BOOL ctrl, BOOL shift, HWND hwnd){
01769  PanX=x; PanY=y;
01770  ZoomInFlag=FALSE; PanMoveFlag=FALSE;
01771  ZoomX=x; ZoomY=y;
01772  return TRUE;
01773 }
01774 
01775 void PanToolMove(int x, int y, BOOL ctrl, BOOL shift,HWND hwnd){
01776  long a,b,c,d,e,f,gqd;
01777  if(ctrl || ZoomInFlag){
01778    if(!ZoomInFlag && (abs(x-ZoomX) > 2 || abs(y-ZoomY) > 2)){
01779      ZoomInFlag=TRUE;
01780      hDCzoom=GetDC(hwnd);
01781      SelectObject(hDCzoom,GetStockObject(NULL_BRUSH));
01782      SelectObject(hDCzoom,ghSelectedPen);
01783      SetROP2(hDCzoom,R2_XORPEN);
01784      SelectPalette(hDCzoom,ghpaletteScreen,FALSE);
01785      RealizePalette(hDCzoom);
01786      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
01787    }
01788    if(ZoomInFlag){
01789      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
01790      ZoomRX=x; ZoomRY=y;
01791      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
01792    }
01793    return;
01794  }
01795  else if(shift)return;
01796  PanMoveFlag=TRUE;
01797  GetWorldCoords(ActiveView,&a,&b,&c,PanX,PanY);
01798  GetWorldCoords(ActiveView,&d,&e,&f,x,y);
01799  TVpointX += (a-d);
01800  TVpointY += (b-e);
01801  TVpointZ += (c-f);
01802  TVcentreX += (a-d);
01803  TVcentreY += (b-e);
01804  TVcentreZ += (c-f);
01805  PanX=x; PanY=y;
01806  DrawQuickModel();
01807 }
01808 
01809 void ZoomView(int x, int y){
01810  BOOL bRedraw=FALSE,bUpdate=FALSE;
01811  unsigned int SaveDrawStatus;
01812  int xo;
01813  POINT pt;
01814  long gqd,evTime;
01815  double zf,dx,dy,dz;
01816  GetCursorPos(&pt); xo=pt.x;
01817 // evTime=GetTickCount()+TIME_DELAY;
01818  do {
01819    Sleep(10);
01820  //  if(evTime > GetTickCount())continue;
01821    if(!(GetAsyncKeyState(VK_LBUTTON) & 0x8000))break;
01822    GetCursorPos(&pt); y=pt.x;
01823    if(y < 1){
01824     x= 0; SetCursorPos(pt.x+20,pt.y); xo=pt.x+20;
01825    }
01826    else if(y > Xres-2){
01827     x= 0; SetCursorPos(pt.x-20,pt.y); xo=pt.x-20;
01828    }
01829    else{
01830      x = y-xo; xo=y;
01831    }
01832    if(x != 0){
01833      dx=(double)(NpointerX-TVpointX)/(double)TVsizeX;
01834      dy=(double)(NpointerY-TVpointY)/(double)TVsizeY;
01835      dz=(double)(NpointerZ-TVpointZ)/(double)TVsizeZ;
01836      if(x > 0){
01837        zf=1.1;
01838      }
01839      else{
01840        zf=0.9090909;
01841      }
01842      if(zf < 1.0 &&
01843         (TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT)){
01844        MessageBeep(MB_OK);
01845      }
01846      else{
01847        TVsizeX=(long)((double)TVsizeX/zf);
01848        TVsizeY=(long)((double)TVsizeY/zf);
01849        TVsizeZ=(long)((double)TVsizeZ/zf);
01850        WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
01851        TVpointX=NpointerX-(long)(dx*(double)TVsizeX); TVcentreX=TVpointX+TVsizeX/2;
01852        TVpointY=NpointerY-(long)(dy*(double)TVsizeY); TVcentreY=TVpointY+TVsizeY/2;
01853        TVpointZ=NpointerZ-(long)(dz*(double)TVsizeZ); TVcentreZ=TVpointZ+TVsizeZ/2;
01854        DrawQuickModel();
01855        bRedraw=TRUE;
01856        bUpdate=TRUE;
01857      }
01858    }
01859 //   evTime=GetTickCount()+TIME_DELAY;
01860    {MSG msg;
01861     if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
01862       TranslateMessage(&msg);
01863       DispatchMessage(&msg);
01864     }
01865    }
01866    if(bUpdate){
01867      DrawQuickModel();
01868      bUpdate=FALSE;
01869    }
01870  }
01871  while(1);
01872  if(bRedraw){
01873    if(ghwndOpenGLview != NULL)PostMessage(ghwndOpenGLview,(WM_USER+2),0,0);
01874    do_NOT_abort=TRUE;
01875    DrawModel();
01876    do_NOT_abort=FALSE;
01877    UpdateCounters();
01878  }
01879  return;
01880 }

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