SIMPLIFY.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 -  OpenFX Development Team
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 You may contact the OpenFX development team via elecronic mail
00020 at core@openfx.org, or visit our website at http://openfx.org for
00021 further information and support details.
00022 -- */
00023 
00024 /*  SIMPLIFY.C  */
00025 
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <math.h>
00029 #include <windows.h>
00030 
00031 #include "struct.h"
00032 #include "dstruct.h"
00033 
00034 #include "simplify.h"
00035 
00036 static HWND      hParent;
00037 static HINSTANCE hThisInstance;
00038 
00039 #if __WATCOMC__
00040 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00041 #else
00042 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00043 #endif
00044   switch (dwReason) {
00045     case DLL_PROCESS_ATTACH: {
00046       hThisInstance=hDLL;
00047       if(hDLL == NULL)MessageBox( GetFocus()," NULL instance",NULL, MB_OK);
00048       break;
00049     }
00050     case DLL_PROCESS_DETACH:
00051       break;
00052   }
00053   return TRUE;
00054 }
00055 
00056 BOOL _Xmodeler
00057  (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00058  HCURSOR hSave;
00059  static struct bp {long iter; double ean,fan;} d;
00060  double fan=5.0,ean=5.0;
00061  long   nloop=5;
00062  lpEVI=lpevi;
00063  hParent=parent_window;
00064  d.iter=nloop; d.fan=fan; d.ean=ean;
00065  if(DialogBoxParam(hThisInstance,MAKEINTRESOURCE(DLG_SIM),hParent,
00066              (DLGPROC)SimplifyDlgProc,(LPARAM)&d) == FALSE)return FALSE;
00067  nloop=d.iter; ean=d.ean; fan=d.fan;
00068  hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00069  SimplifyObject(nloop,fan,ean);
00070  SetCursor(hSave);
00071  return TRUE;
00072 }
00073 
00074 static BOOL CALLBACK SimplifyDlgProc(HWND hwnd, UINT msg,
00075                              WPARAM wparam, LPARAM lparam){
00076  BOOL err;
00077  int i;
00078  static struct bp {long iter; double ean,fan;} *dp;
00079  double angle;
00080  char str[32];
00081  switch( msg ) {
00082    case WM_INITDIALOG:
00083      dp=(struct bp *)lparam;
00084      SetDlgItemInt(hwnd,DLG_SIM_ITER,dp->iter,FALSE);
00085      sprintf(str,"%.2lf",dp->fan);
00086      SetDlgItemText(hwnd,DLG_SIM_FACE,(LPCTSTR)str);
00087      SendDlgItemMessage(hwnd,DLG_SIM_FACE,EM_LIMITTEXT,(WPARAM)12,0);
00088      sprintf(str,"%.2lf",dp->ean);
00089      SetDlgItemText(hwnd,DLG_SIM_EDGE,(LPCTSTR)str);
00090      SendDlgItemMessage(hwnd,DLG_SIM_EDGE,EM_LIMITTEXT,(WPARAM)12,0);
00091      CentreDlgOnS(hwnd);
00092      return (TRUE);
00093    case WM_COMMAND:
00094       switch(LOWORD(wparam)){
00095         case IDCANCEL:
00096           EndDialog(hwnd,FALSE);
00097           return(TRUE);
00098         case IDOK:
00099           if(GetDlgItemText(hwnd,DLG_SIM_FACE,str,10) == 0){
00100             EndDialog(hwnd,FAIL);
00101             return TRUE;
00102           }
00103           angle=atof(str);
00104           if(angle < 0.1 || angle > 45.0){
00105             EndDialog(hwnd,FAIL);
00106             return TRUE;
00107           }
00108           dp->fan=angle;
00109           if(GetDlgItemText(hwnd,DLG_SIM_EDGE,str,10) == 0){
00110             EndDialog(hwnd,FAIL);
00111             return TRUE;
00112           }
00113           angle=atof(str);
00114           if(angle < 0.1 || angle > 45.0){
00115             EndDialog(hwnd,FAIL);
00116             return TRUE;
00117           }
00118           dp->ean=angle;
00119           i=GetDlgItemInt(hwnd,DLG_SIM_ITER,&err,FALSE);
00120           if(err)dp->iter=i;
00121           EndDialog(hwnd,TRUE);
00122           return(TRUE);
00123         default:
00124           break;
00125       }
00126       break;
00127     default: break;
00128  }
00129  return(FALSE);
00130 }
00131 
00132 static vtyadj *ListAdjFaces(selectedface *wf, long nf,
00133                             selectededge *we, long ne, long *nvll){
00134  edge *e;
00135  face *f;
00136  vertex *vp;
00137  vtyadj *vl=NULL;
00138  long c,nvl=0;
00139  long *fl,i,j,k,id,id0,id1,id2,fjd,fkd,n,m,kk,nl[3],ml[3];
00140  vp=MainVp; for(c=0;c<Nvert;c++){
00141    if(vp->status == DESELECTED){ /* work vertex */
00142      vp->id=nvl;
00143      nvl++;
00144    }
00145    else vp->id = -10;
00146    vp++;
00147  }
00148  if((vl=(vtyadj *)X__Malloc(nvl*sizeof(vtyadj))) == NULL)return 0;
00149  for(i=0;i<nvl;i++){
00150    vl[i].nf=0; vl[i].ne=0;
00151    vl[i].flist=NULL; vl[i].elist=NULL;
00152  }
00153  i=0; vp=MainVp; for(c=0;c<Nvert;c++){
00154    if(vp->status == DESELECTED){
00155      vl[i].v=c;
00156      i++;
00157    }
00158    vp++;
00159  }
00160  for(i=0;i<nf;i++){ /* make list of work faces attached to each vertex */
00161    f=(MainFp+wf[i].f);
00162    for(j=0;j<3;j++){
00163      id=(MainVp+(f->V[j]))->id;
00164      fl=vl[id].flist;
00165      n=vl[id].nf;
00166      if(fl == NULL){
00167        if((fl=(long *)X__Malloc(sizeof(long))) == NULL)return NULL;
00168      }
00169      else{
00170        if((fl=(long *)X__Realloc(fl,(n+1)*sizeof(long))) == NULL)return NULL;
00171      }
00172      fl[n]=i;
00173      vl[id].flist=fl;
00174      vl[id].nf=n+1;
00175    }
00176  }
00177  for(i=0;i<nf;i++){ /* find faces that are adjacent to face i */
00178    f=(MainFp+wf[i].f);
00179    id0=(MainVp+(f->V[0]))->id;
00180    id1=(MainVp+(f->V[1]))->id;
00181    id2=(MainVp+(f->V[2]))->id;
00182    nl[0]=id0; ml[0]=id1;
00183    nl[1]=id1; ml[1]=id2;
00184    nl[2]=id2; ml[2]=id0;
00185    for(kk=0;kk<3;kk++){
00186      wf[i].fa[kk] = -1;
00187      if((n=vl[nl[kk]].nf) > 0 && (m=vl[ml[kk]].nf) > 0){
00188        for(j=0;j<n;j++){
00189          fjd=vl[nl[kk]].flist[j];
00190          for(k=0;k<m;k++){
00191            fkd=vl[ml[kk]].flist[k];
00192            if(fkd == fjd && fkd != i){
00193              wf[i].fa[kk]=fkd;
00194              goto ENDF;
00195            }
00196          }
00197        }
00198      }
00199      ENDF:;
00200    }
00201  }
00202  for(i=0;i<ne;i++){ /* find faces that are adjacent to edge i */
00203    e=(MainEp+we[i].e);
00204    id0=(MainVp+(e->V[0]))->id; id1=(MainVp+(e->V[1]))->id;
00205    kk=0; we[i].ea[0] = we[i].ea[1] = -1;
00206    if((n=vl[id0].nf) > 0 && (m=vl[id1].nf) > 0){
00207      for(j=0;j<n;j++){
00208        fjd=vl[id0].flist[j];
00209        for(k=0;k<m;k++){
00210          fkd=vl[id1].flist[k];
00211          if(fkd == fjd){
00212            we[i].ea[kk]=fkd;
00213            kk++;
00214            if(kk == 2)goto ENDEE;  /* terminate when we have two */
00215          }
00216        }
00217      }
00218      ENDEE:;
00219    }
00220  }
00221  for(i=0;i<ne;i++){ /* make list of work edges attached to each vertex */
00222    e=(MainEp+we[i].e);
00223    for(j=0;j<2;j++){
00224      id=(MainVp+(e->V[j]))->id;
00225      fl=vl[id].elist;
00226      n=vl[id].ne;
00227      if(fl == NULL){
00228        if((fl=(long *)X__Malloc(sizeof(long))) == NULL)return NULL;
00229      }
00230      else {
00231        if((fl=(long *)X__Realloc(fl,(n+1)*sizeof(long))) == NULL)return NULL;
00232      }
00233      fl[n]=i;
00234      vl[id].elist=fl;
00235      vl[id].ne=n+1;
00236    }
00237  }
00238  for(i=0;i<nf;i++){ /* find edges that are adjacent to face i */
00239    f=(MainFp+wf[i].f);
00240    id0=(MainVp+(f->V[0]))->id;
00241    id1=(MainVp+(f->V[1]))->id;
00242    id2=(MainVp+(f->V[2]))->id;
00243    nl[0]=id0; ml[0]=id1;
00244    nl[1]=id1; ml[1]=id2;
00245    nl[2]=id2; ml[2]=id0;
00246    for(kk=0;kk<3;kk++){
00247      wf[i].ea[kk] = -1;
00248      if((n=vl[nl[kk]].ne) > 0 && (m=vl[ml[kk]].ne) > 0){
00249        for(j=0;j<n;j++){
00250          fjd=vl[nl[kk]].elist[j];
00251          for(k=0;k<m;k++){
00252            fkd=vl[ml[kk]].elist[k];
00253            if(fkd == fjd){
00254              wf[i].ea[kk]=fkd;
00255              goto ENDE;
00256            }
00257          }
00258        }
00259      }
00260      ENDE:;
00261    }
00262  }
00263  *nvll=nvl;
00264  return vl;
00265 }
00266 
00267 static void FreeAdjFaces(vtyadj *vl,long nvl){
00268  int i;
00269  if(vl != NULL && nvl > 0){
00270    for(i=0;i<nvl;i++){
00271      if(vl[i].flist != NULL)X__Free(vl[i].flist);
00272      if(vl[i].elist != NULL)X__Free(vl[i].elist);
00273    }
00274    X__Free(vl);
00275  }
00276 }
00277 
00278 static void SimplifyObject(long nloop, double fan, double ean){
00279  selectededge *we;
00280  selectedface *w;
00281  face *f;
00282  vertex *vp,*v0,*v1,*v2;
00283  edge *e;
00284  vector du,dv,n,p0,p1,p2;
00285  long c,i,loop,n_work_face,n_work_edge,phase,nvl;
00286  vtyadj *vl;
00287  if(NvertSelect == 0)return;
00288  if(NvertSelect > 32000)return;
00289  if(MainFp == NULL)return;
00290  fan=cos(fan*0.0174532);
00291  ean=cos(ean*0.0174532);
00292  vp=MainVp; for(i=0;i<Nvert;i++){
00293    if(vp->status == SELECTED){
00294      vp->status=DESELECTED;
00295      NvertSelect--; NvertDeselect++;
00296    }
00297    else if(vp->status == DESELECTED){
00298      vp->status=INEDITOR;
00299    }
00300    vp->id=0;
00301    vp++;
00302  }
00303  phase=0;
00304  PHASE:
00305  n_work_face=0,n_work_edge=0;
00306  w=NULL; we=NULL;
00307  f=MainFp; for(c=0;c<Nface;c++){
00308   v0=(MainVp+f->V[0]); v1=(MainVp+f->V[1]); v2=(MainVp+f->V[2]);
00309   if(v0->status == DESELECTED &&
00310      v1->status == DESELECTED &&
00311      v1->status == DESELECTED)n_work_face++;
00312   f++;
00313  }
00314  e=MainEp; for(c=0;c<Nedge;c++){ /* get all tool edges */
00315    v0=(MainVp+e->V[0]); v1=(MainVp+e->V[1]);
00316    if(v0->status == DESELECTED && v1->status == DESELECTED)n_work_edge++;
00317    e++;
00318  }
00319  if((w=(selectedface *)X__Malloc((n_work_face+1)*(long)sizeof(selectedface)))
00320     == NULL)goto BERR;
00321  if((we=(selectededge *)X__Malloc((n_work_edge+1)*(long)sizeof(selectededge)))
00322     == NULL)goto BERR;
00323  n_work_face=0; n_work_edge=0;
00324  f=MainFp; for(c=0;c<Nface;c++){
00325   v0=(MainVp+f->V[0]); v1=(MainVp+f->V[1]); v2=(MainVp+f->V[2]);
00326   POINT2VECTOR(v0->xyz,p0)
00327   POINT2VECTOR(v1->xyz,p1)
00328   POINT2VECTOR(v2->xyz,p2)
00329   VECSUB(p1,p0,dv)
00330   VECSUB(p2,p0,du)
00331   if(v0->status == DESELECTED &&
00332      v1->status == DESELECTED &&
00333      v2->status == DESELECTED){
00334     w[n_work_face].f=c;
00335     w[n_work_face].del=0;
00336     for(i=0;i<3;i++){
00337       w[n_work_face].fa[i] = -1;
00338       w[n_work_face].ea[i] = -1;
00339     }
00340     CROSS(dv,du,n)
00341     if(O_normalize(n) == FAIL){
00342       VECSUB(p0,p1,dv)
00343       VECSUB(p2,p1,du)
00344       CROSS(dv,du,n)
00345       if(O_normalize(n) == FAIL){
00346         VECSUB(p0,p2,dv)
00347         VECSUB(p1,p2,du)
00348         CROSS(dv,du,n)
00349         if(O_normalize(n) == FAIL)goto BERR2;
00350       }
00351     }
00352     VECCOPY(n,w[n_work_face].n)
00353     n_work_face++;
00354   }
00355   f++;
00356  }
00357  e=MainEp; for(c=0;c<Nedge;c++){ /* get all tool edges */
00358    v0=(MainVp+e->V[0]); v1=(MainVp+e->V[1]);
00359    if(v0->status == DESELECTED && v1->status == DESELECTED){
00360      we[n_work_edge].e=c;    /* are the original selectedface edges, pass 1 */
00361      we[n_work_edge].ea[0] = we[n_work_edge].ea[1] = -1;
00362      n_work_edge++;
00363    }
00364    e++;
00365  }
00366  if(n_work_face == 0)goto QUIT;
00367  vl=ListAdjFaces(w,n_work_face,we,n_work_edge,&nvl);
00368  /* simplify straight edges */
00369  if(phase == 0)for(loop=0;loop<nloop;loop++){
00370    if(!Simplify1(vl,nvl,w,n_work_face,we,n_work_edge,fan,ean))break;
00371  }
00372  /*  try to delete tesselated vertices */
00373  if(phase == 1)for(loop=0;loop<nloop;loop++){
00374    if(!DeTesselate(vl,nvl,w,n_work_face,we,n_work_edge,fan))break;
00375  }
00376 
00377  EraseVertex(1);
00378  FreeAdjFaces(vl,nvl);
00379  goto QUIT;
00380  BERR2:
00381  MessageBox(NULL,"Normal - Problem",NULL,MB_OK); goto QUIT;
00382  goto QUIT;
00383  BERR:
00384  MessageBox(NULL,"Memory Error",NULL,MB_OK);
00385  QUIT:
00386  if(w != NULL)X__Free(w);
00387  if(we != NULL)X__Free(we);
00388  if(phase == 0){phase=1; goto PHASE;}
00389  vp=MainVp; for(c=0;c<Nvert;c++){
00390    if(vp->status == INEDITOR)vp->status=DESELECTED;
00391    vp++;
00392  }
00393  return;
00394 }
00395 
00396 static int co_attrib(long if1, long if2){
00397  int i;
00398  face *f1,*f2;
00399  f1=(MainFp+if1); f2=(MainFp+if2);
00400  if(f1->material != f2->material)return 0;
00401  if(f1->imagemap != f2->imagemap)return 0;
00402  return 1;
00403 }
00404 
00405 static int co_planar(vector n1, vector n2, double angle){
00406  if(fabs(DOT(n1,n2)) > angle)return 1; /* if planar */
00407  return 0;
00408 }
00409 
00410 static int co_linear(long e1, long e2, selectededge *we, double angle){
00411  vertex *v0,*v1;
00412  vector a,b;
00413  edge *ep;
00414  if(e1 < 0 || e2 < 0){
00415    return 0;
00416  }
00417  ep=(MainEp+we[e1].e);
00418  v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00419  VECSUB((double)v0->xyz,(double)v1->xyz,a)
00420  if(O_normalize(a) == FAIL)return 0;
00421  ep=(MainEp+we[e2].e);
00422  v0=(MainVp+ep->V[0]); v1=(MainVp+ep->V[1]);
00423  VECSUB((double)v0->xyz,(double)v1->xyz,b)
00424  if(O_normalize(b) == FAIL)return 0;
00425  if(fabs(DOT(a,b)) > angle)return 1;
00426  return 0;
00427 }
00428 
00429 static void IdentifyGeometry(long i, long j,
00430                              long *f0, long *f1, long *f2,
00431                              long *e0, long *e1, long *e2,
00432                              long *fx, long *ex,
00433                              long *fxx, long *exx,
00434                              long *fxxx, long *exxx,
00435                              long *v0, long *v1, long *v2,
00436                              long *vll, long *vlll,
00437                              selectedface *wf,selectededge *we){
00438  face *f;
00439  long va,vb;
00440  long k,l,ll,e,m[3]={1,2,0},n[3]={2,0,1};
00441  *f0=wf[i].fa[j]; *f1=wf[i].fa[m[j]]; *f2=wf[i].fa[n[j]];
00442  *e0=wf[i].ea[j]; *e1=wf[i].ea[m[j]]; *e2=wf[i].ea[n[j]];
00443  f=(MainFp+wf[i].f);
00444  *v0 = f->V[j]; *v1 = f->V[m[j]]; *v2=f->V[n[j]];
00445  *fx = -1; *ex = -1; *fxx = -1; *exx = -1; *vll = -1;
00446  *fxxx = -1; *exxx = -1; *vlll = -1;
00447  if(*f1 >= 0){
00448    for(k=0;k<3;k++){
00449     if(wf[*f1].fa[k] != i){
00450       e=wf[*f1].ea[k]; if(e < 0)return;
00451       va=(MainEp+(we[e].e))->V[0]; vb=(MainEp+(we[e].e))->V[1];
00452       if(*v1 == va || *v1 == vb){
00453         *ex=e; *fx=wf[*f1].fa[k];
00454         if(*fx < 0 || e < 0)return;
00455         if((MainEp+(we[e].e))->V[0] != *v1) *vll = (MainEp+(we[e].e))->V[0];
00456         else                                *vll = (MainEp+(we[e].e))->V[1];
00457         for(l=0;l<3;l++){
00458           if(wf[*fx].fa[l] != *f1){
00459             e=wf[*fx].ea[l];
00460             if(e >= 0){
00461               va=(MainEp+(we[e].e))->V[0]; vb=(MainEp+(we[e].e))->V[1];
00462               if(*v1 == va || *v1 == vb){
00463                 if(e != *e0){
00464                   *exx=e; *fxx=wf[*fx].fa[l];
00465                   if(*fxx < 0 || e < 0)return;
00466                   if((MainEp+(we[e].e))->V[0] != *v1)
00467                     *vlll = (MainEp+(we[e].e))->V[0];
00468                   else
00469                     *vlll = (MainEp+(we[e].e))->V[1];
00470                   for(ll=0;ll<3;ll++){
00471                     if(wf[*fxx].fa[ll] != *f1){
00472                       e=wf[*fxx].ea[ll];
00473                       if(e >= 0){
00474                         va=(MainEp+(we[e].e))->V[0];
00475                         vb=(MainEp+(we[e].e))->V[1];
00476                         if(*v1 == va || *v1 == vb){
00477                           if(e != *e0){
00478                             *exxx=e; *fxxx=wf[*fxx].fa[ll];
00479                             return;
00480                           }
00481                         }
00482                       }
00483                     }
00484                   }
00485                   return;
00486                 }
00487               }
00488             }
00489           }
00490         }
00491         return;
00492       }
00493     }
00494    }
00495  }
00496  return;
00497 }
00498 
00499 static void IdentifyAdjacent(long i,long f0, long v0, long v1,
00500                              long *fl, long *el, long *fn, long *en,
00501                              long  *fnn, long *vn, long *vnn,
00502                              selectedface *wf,selectededge *we){
00503  long k,l;
00504  face *f;
00505  edge *e;
00506  *vn = -1; *vnn = -1;
00507  *fl = *fn = *el = *en = *fnn = -1;
00508  for(k=0;k<3;k++){
00509    f=(MainFp+wf[f0].f);
00510    if(f->V[k] != v0 && f->V[k] != v1)*vn=f->V[k];
00511    if((l=wf[f0].fa[k]) != i){
00512      if(l >= 0){
00513        f=(MainFp+wf[l].f);
00514        if(f->V[0] == v0 || f->V[1] == v0 || f->V[2] == v0) *fl = l;
00515        if(f->V[0] == v1 || f->V[1] == v1 || f->V[2] == v1) *fn = l;
00516      }
00517      if(wf[f0].ea[k] >= 0){
00518        e=(MainEp+we[wf[f0].ea[k]].e);
00519        if(e->V[0] == v0 || e->V[1] == v0) *el = wf[f0].ea[k];
00520        if(e->V[0] == v1 || e->V[1] == v1) *en = wf[f0].ea[k];
00521      }
00522    }
00523  }
00524  if(*fn >= 0){
00525    for(k=0;k<3;k++){
00526      f=(MainFp+wf[*fn].f);
00527      if(f->V[k] != v1 && f->V[k] != *vn)*vnn=f->V[k];
00528      if((l=wf[*fn].fa[k]) != f0){
00529        if(l >= 0){
00530          f=(MainFp+wf[l].f);
00531          if(f->V[0] == v1 || f->V[1] == v1 || f->V[2] == v1) *fnn = l;
00532        }
00533      }
00534    }
00535  }
00536 }
00537 
00538 static int BadAngle(long iv0, long iv1, long ivn, long ivnn){
00539  vector a,b,c;
00540  double c1,c2;
00541  vertex *v0,*v1,*vn,*vnn;
00542  if(iv0 < 0 || iv1 < 0 || ivn < 0 || ivnn < 0)return 1;
00543  v0=(MainVp+iv0);  v1=(MainVp+iv1); vn=(MainVp+ivn); vnn=(MainVp+ivnn);
00544  if(v0 == NULL || v1 == NULL || vn == NULL || vnn == NULL)return 1;
00545  VECSUB((double)vnn->xyz,(double)vn->xyz,a)
00546  VECSUB((double)v1->xyz,(double)vn->xyz,b)
00547  VECSUB((double)v0->xyz,(double)vn->xyz,c)
00548  if(O_normalize(a) == FAIL)return 1;    /* angle v0->vn-vnn (inc v1) > PI */
00549  if(O_normalize(b) == FAIL)return 1;
00550  if(O_normalize(c) == FAIL)return 1;
00551  if(acos(DOT(b,a))+acos(DOT(b,c)) > PI - 0.1)return 1;
00552  return 0;
00553 }
00554 
00555 static int Simplify1(vtyadj *vl, long nvl,
00556                         selectedface *w, long nf,
00557                         selectededge *we, long ne,
00558                         double fan, double ean){
00559  face *ff;
00560  edge *ee;
00561  long f,e;
00562  long vp,v0,v1,v2,vn,vnn,vll,vlll;
00563  long c,h,i,j,k,l,m,n,second_type=0;
00564  long f0,f1,f2,e0,e1,e2,fx,ex,fxx,exx,fxxx,exxx,fl,fn,el,en,fnn,ev;
00565  int reduc;
00566  reduc=0;
00567  for(i=0;i<nf;i++){
00568    if(w[i].del)continue;  /* face is gone */
00569    for(h=0;h<2;h++){/* reverse direction of face */
00570      for(j=0;j<3;j++){
00571        IdentifyGeometry(i,j,&f0,&f1,&f2,&e0,&e1,&e2,
00572                             &fx,&ex,&fxx,&exx,&fxxx,&exxx,
00573                             &v0,&v1,&v2,&vll,&vlll,
00574                             w,we);
00575        if(f1 >= 0){                         /* possible reduction         */
00576          if(co_planar(w[i].n,w[f1].n,fan) &&
00577             co_attrib(w[i].f,w[f1].f)){     /* faces i + f1 planar        */
00578            if(co_linear(e0,ex,we,ean)){     /* edge e0                    */
00579              second_type=0;
00580              SECONDTYPE:
00581              if(f0 < 0 && fx >= 0)goto LOOP;    /* can't do these         */
00582              if(f0 >= 0 && fx < 0)goto LOOP;    /* either                 */
00583              if(f0 >= 0){
00584                IdentifyAdjacent(i,f0,v0,v1,&fl,&el,&fn,&en,&fnn,&vn,&vnn,w,we);
00585                if(fn == fx)fnn = -1;
00586                else if(BadAngle(v0,v1,vn,vnn))goto LOOP;/* test angle v0-vn-vnn */
00587                if(fn != fx && fnn != fx)goto LOOP;
00588                if(fn < 0)goto LOOP;
00589                if(!co_attrib(w[f0].f,w[fn].f))goto LOOP;
00590                if(fnn >= 0 && !co_attrib(w[fn].f,w[fnn].f))goto LOOP;
00591              }
00592              w[i].del=1;
00593              if(e2 < 0)goto LOOP;
00594              for(k=0;k<2;k++){
00595                if(we[e2].ea[k] == i)we[e2].ea[k]=f1;
00596              }
00597              for(k=0;k<3;k++){
00598                if(w[f1].fa[k] ==  i)w[f1].fa[k]=f2;
00599                if(w[f1].ea[k] == e1)w[f1].ea[k]=e2;
00600                if(f2 >= 0){ /* fix up adjacent to i */
00601                  if(w[f2].fa[k] ==  i)w[f2].fa[k]=f1;
00602                }
00603              }
00604              /* label vertex for deletion                             */
00605              /* re-vector faces and edges away from deleted vector    */
00606              /* leave attached any edge or face that is to be deleted */
00607              /* then EraseVertex will take care of it                 */
00608              f=w[f1].f; ff=(MainFp+f);
00609              for(k=0;k<3;k++){
00610                if(ff->V[k] == v1)ff->V[k]=v0;
00611              }
00612              e=we[ex].e; ee=(MainEp+e);
00613              for(k=0;k<2;k++){
00614                if(ee->V[k] == v1)ee->V[k]=v0;
00615              }
00616              (MainVp+v1)->status=SELECTED;
00617              NvertSelect++; NvertDeselect--; reduc=1;
00618              if(second_type > 0){
00619                f=w[fxx].f; ff=(MainFp+f);
00620                for(k=0;k<3;k++){
00621                  if(ff->V[k] == v1)ff->V[k]=v0;
00622                }
00623                e=we[exx].e; ee=(MainEp+e);
00624                for(k=0;k<2;k++){
00625                  if(ee->V[k] == v1)ee->V[k]=v0;
00626                }
00627                if(second_type > 1){
00628                  f=w[fxxx].f; ff=(MainFp+f);
00629                  for(k=0;k<3;k++){
00630                    if(ff->V[k] == v1)ff->V[k]=v0;
00631                  }
00632                  e=we[exxx].e; ee=(MainEp+e);
00633                  for(k=0;k<2;k++){
00634                    if(ee->V[k] == v1)ee->V[k]=v0;
00635                  }
00636                }
00637              }
00638              /* reset faces adjacent to f0/en which will also disappear */
00639              /* any faces and edges pointing to v1 should be revectored */
00640              /* or left attached for deletion                           */
00641              if(f0 >= 0){ /* delete adjacent faces  */
00642                w[f0].del=1;
00643                f=w[fn].f; ff=(MainFp+f);
00644                for(k=0;k<3;k++){
00645                  if(fl >= 0)if(w[fl].fa[k] == f0)w[fl].fa[k]=fn;
00646                  if(fn >= 0)if(w[fn].fa[k] == f0)w[fn].fa[k]=fl;
00647                  if(fn >= 0)if(w[fn].ea[k] == en)w[fn].ea[k]=el;
00648                  if(ff->V[k] == v1)ff->V[k]=v0;
00649                }
00650                for(k=0;k<2;k++){
00651                  if(we[el].ea[k] == f0)we[el].ea[k]=fn;
00652                }
00653                if(fnn >= 0){
00654                  f=w[fnn].f; ff=(MainFp+f);
00655                  for(k=0;k<3;k++){
00656                    if((l=w[fnn].ea[k]) >= 0){
00657                      e=we[l].e; ee=(MainEp+e);
00658                      if(ee->V[0] == v1)ee->V[0]=v0;
00659                      if(ee->V[1] == v1)ee->V[1]=v0;
00660                    }
00661                    if(ff->V[k] == v1)ff->V[k]=v0;
00662                  }
00663                }
00664              }
00665              goto BREAKOUT;
00666            }
00667            else{ /* Try for case with exx linear with e0 */
00668              if(fx >= 0 && ex >= 0 && e0 >= 0 && exx >= 0 && vll >= 0){
00669                if(co_planar(w[i].n,w[fx].n,fan) &&
00670                   co_attrib(w[i].f,w[fx].f) &&
00671                   !BadAngle(v0,v1,v2,vll)){ /* test angle v0-v2-vll */
00672                  if(co_linear(e0,exx,we,ean)){
00673                    m=fx; fx=fxx;  fxx=m;
00674                    m=ex; ex=exx;  exx=m;
00675                    second_type=1;
00676                    goto SECONDTYPE;
00677                  }
00678                  else if(fxx >= 0 && exxx >= 0 && vlll >= 0){
00679                    if(co_planar(w[i].n,w[fxx].n,fan) &&
00680                       co_attrib(w[i].f,w[fxx].f) &&
00681                       !BadAngle(v2,v1,vll,vlll) &&
00682                       co_linear(e0,exxx,we,ean)){
00683                      m=fx; fx=fxxx;  n=fxx; fxx=m;  fxxx=n;
00684                      m=ex; ex=exxx;  n=exx; exx=m;  exxx=n;
00685                      second_type=2;
00686                      goto SECONDTYPE;
00687                    }
00688                  }
00689                }
00690              }
00691            }
00692          }
00693        }
00694        LOOP:;
00695      } /* try other orientation */
00696      f=w[i].f; ff=(MainFp+f);
00697      vp=ff->V[0]; ff->V[0]=ff->V[2]; ff->V[2]=vp;
00698      k=w[i].fa[0]; w[i].fa[0]=w[i].fa[1]; w[i].fa[1]=k;
00699      k=w[i].ea[0]; w[i].ea[0]=w[i].ea[1]; w[i].ea[1]=k;
00700    }
00701    BREAKOUT:;
00702  }
00703  return reduc;
00704 }
00705 
00706 
00707 static int VertexAdj(vtyadj vl, selectedface *wf, selectededge *we,
00708                      long *f0, long *f1, long *f2,
00709                      long *e0, long *e1, long *e2){
00710   face *f;
00711   edge *e;
00712   long i,j,l,nf=0,ne=0;
00713   *f0 = *f1 = *f2 = *e0 = *e1 =*e2 = -1;
00714   if((MainVp+(vl.v))->status == SELECTED)goto XXIT;
00715   if(vl.nf < 3 || vl.ne < 3)goto XXIT;
00716   for(i=0;i<vl.nf;i++){
00717     l=vl.flist[i];  f=(MainFp+wf[l].f);
00718     for(j=0;j<3;j++){  /* don't count any selected vertex */
00719       if((MainVp+f->V[j])->status == SELECTED)goto JUMPIT;
00720     }
00721     if(l == *f0 || l == *f1 || l == *f2)goto JUMPIT; /* don't count same faces */
00722     if(nf == 0) *f0 = l;   /* same faces will occur in second interations */
00723     if(nf == 1) *f1 = l;
00724     if(nf == 2) *f2 = l;
00725     nf++;
00726     JUMPIT:
00727     if(nf > 3)goto XXIT;
00728   }
00729   for(i=0;i<vl.ne;i++){
00730     l=vl.elist[i];  e=(MainEp+we[l].e);
00731     if((MainVp+e->V[0])->status == DESELECTED &&
00732        (MainVp+e->V[1])->status == DESELECTED){
00733       if(ne == 0) *e0 = l;
00734       if(ne == 1) *e1 = l;
00735       if(ne == 2) *e2 = l;
00736       ne++;
00737       if(ne > 3){ nf=0; goto XXIT; }
00738     }
00739   }
00740   XXIT:
00741   return nf;
00742 }
00743 
00744 static void GetOppositeFaceEdge(long v, long f, selectedface *wf,
00745                                 long *fo, long *eo){
00746  long i,m[3]={1,2,0};
00747  face *ff;
00748  *fo = *eo = -1;
00749  ff= (MainFp+wf[f].f);
00750  for(i=0;i<3;i++){
00751    if(ff->V[i] == v){
00752      *fo = wf[f].fa[m[i]];
00753      *eo = wf[f].ea[m[i]];
00754    }
00755  }
00756  return;
00757 }
00758 
00759 
00760 static long GetCommonVertex(long v, long f1, long f2){
00761  long i,j;
00762  long vp;
00763  for(i=0;i<3;i++){
00764    vp=(MainFp+f1)->V[i];
00765    for(j=0;j<3;j++){
00766      if((MainFp+f2)->V[j] == vp){
00767        if(vp != v)return vp;
00768      }
00769    }
00770  }
00771  return -1;
00772 }
00773 
00774 static int DeTesselate(vtyadj *vl, long nvl,
00775                         selectedface *wf, long nf,
00776                         selectededge *we, long ne,
00777                         double angle){
00778  int reduc=0;
00779  long i,j,k,l;
00780  long f0,f1,f2,e0,e1,e2,fo1,fo2,eo1,eo2;
00781  long v,vid;
00782  face *f;
00783  for(i=0;i<nvl;i++){
00784    if(VertexAdj(vl[i],wf,we,&f0,&f1,&f2,&e0,&e1,&e2) == 3 &&   /* case 3 */
00785       co_planar(wf[f0].n,wf[f1].n,angle) && co_attrib(wf[f0].f,wf[f1].f) &&
00786       co_planar(wf[f0].n,wf[f2].n,angle) && co_attrib(wf[f0].f,wf[f2].f)){
00787      v=vl[i].v;
00788      (MainVp+v)->status=SELECTED; NvertSelect++; NvertDeselect--; reduc=1;
00789      GetOppositeFaceEdge(v,f1,wf,&fo1,&eo1);
00790      GetOppositeFaceEdge(v,f2,wf,&fo2,&eo2);
00791      if((vid=GetCommonVertex(v,wf[f1].f,wf[f2].f)) < 0)return 0;
00792      f=(MainFp+wf[f0].f);
00793      wf[f1].del=1;
00794      wf[f2].del=1;
00795      for(j=0;j<3;j++){
00796        /* fix up vertex adjacency */
00797        l=(long)((MainVp+(MainFp+(wf[f1].f))->V[j])->id);
00798        for(k=0;k<vl[l].nf;k++){
00799          if(vl[l].flist[k] == f1 || vl[l].flist[k] == f2)vl[l].flist[k]=f0;
00800        }
00801        l=(long)((MainVp+(MainFp+(wf[f2].f))->V[j])->id);
00802        for(k=0;k<vl[l].nf;k++){
00803          if(vl[l].flist[k] == f1 || vl[l].flist[k] == f2)vl[l].flist[k]=f0;
00804        }
00805        /* set adjacency in f0 */
00806        if(wf[f0].fa[j] == f1){
00807          wf[f0].fa[j]=fo1;
00808          wf[f0].ea[j]=eo1;
00809        }
00810        if(wf[f0].fa[j] == f2){
00811          wf[f0].fa[j]=fo2;
00812          wf[f0].ea[j]=eo2;
00813        }
00814        /* fix up face adjacency */
00815        if(f->V[j] == v)f->V[j]=vid;
00816        if((l=wf[f1].fa[j]) >= 0 && l != f0 && l != f1 && l != f2){
00817          for(k=0;k<3;k++)if(wf[l].fa[k] == f1)wf[l].fa[k]=f0;
00818        }
00819        if((l=wf[f2].fa[j]) >= 0 && l != f0 && l != f1 && l != f2){
00820          for(k=0;k<3;k++)if(wf[l].fa[k] == f2)wf[l].fa[k]=f0;
00821        }
00822      }
00823      for(j=0;j<2;j++){
00824        if(we[eo1].ea[j] == f1)we[eo1].ea[j]=f0;
00825        if(we[eo2].ea[j] == f2)we[eo2].ea[j]=f0;
00826      }
00827    }
00828  }
00829  return reduc;
00830 }
00831 

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