SUBDCURV.CPP

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - 2007 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 /* SUBDCURV.CPP  */
00025 
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <math.h>
00029 #include <windows.h>
00030 
00031 #ifdef __cplusplus
00032 extern "C" {
00033 #endif
00034 
00035 #include "struct.h"
00036 #include "dstruct.h"
00037 
00038 #ifdef __cplusplus
00039 }
00040 #endif
00041 
00042 #include "subdcurv.h"
00043 
00044 #define DESELECTED 0
00045 #define SELECTED   1
00046 #define HIDDEN     2
00047 #define INEDITOR   3
00048 #define FAIL      -1
00049 #define OK         1
00050 
00051 static HWND      hParent;
00052 static HINSTANCE hThisInstance;
00053 
00054 #if __WATCOMC__
00055 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00056 #else
00057 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00058 #endif
00059   switch (dwReason) {
00060     case DLL_PROCESS_ATTACH: {
00061       hThisInstance=(HINSTANCE)hDLL;
00062       if(hDLL == NULL)MessageBox ( GetFocus()," NULL instance",NULL, MB_OK);
00063       break;
00064     }
00065     case DLL_PROCESS_DETACH:
00066       break;
00067   }
00068   return TRUE;
00069 }
00070 
00071 #if __SC__
00072 #pragma startaddress(DllMain)
00073 #endif
00074 
00075 static int Subdivide(long, long);
00076 static void SmoothOutCurve(long, long *, BOOL);
00077 
00078 extern "C" BOOL _Xmodeler
00079  (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00080  lpEVI=lpevi;
00081  hParent=parent_window;
00082 // if(MessageBox(hParent,"Subdivide selected faces ?","Subdivide",MB_OKCANCEL)
00083 //               == IDCANCEL)return FALSE;
00084 // else
00085  {
00086    HCURSOR hSave;
00087    if(NvertSelect == 0 || NvertSelect > 32000)return FALSE;
00088    hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00089    Subdivide(0,0);
00090    SetCursor(hSave);
00091  }
00092  return TRUE;
00093 }
00094 
00095 #define VECCOPY(a,b)    { b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
00096 #define VECSUB(a,b,c)   { c[0]=a[0]-b[0]; c[1]=a[1]-b[1]; c[2]=a[2]-b[2];}
00097 #define VECSUM(a,b,c)   { c[0]=a[0]+b[0]; c[1]=a[1]+b[1]; c[2]=a[2]+b[2];}
00098 #define VECSCALE(a,b,c) { c[0]=(a)*b[0]; c[1]=(a)*b[1]; c[2]=(a)*b[2];}
00099 #define DOT(a,b)        ( (a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]) )
00100 #define CROSS(v1,v2,r)  { \
00101                           r[0] = (v1[1]*v2[2]) - (v2[1]*v1[2]);  \
00102                           r[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]);  \
00103                           r[2] = (v1[0]*v2[1]) - (v2[0]*v1[1]);  \
00104                          }
00105 
00106 typedef struct tagVERTEXVERTEX{
00107  long vl,vr;
00108 } VERTEXVERTEX;
00109 
00110 typedef struct tagFACEEXTRA{
00111  long extra,xxtra;
00112 } FACEEXTRA;
00113 
00114 #include "splines.c"
00115 
00116 BOOL intriview(vertex *vp){
00117  if(vp->status == HIDDEN)return FALSE;
00118  if( ((vp->xyz[0] > TVpointX) && (vp->xyz[0] < TVpointX+TVsizeX))
00119   && ((vp->xyz[1] > TVpointY) && (vp->xyz[1] < TVpointY+TVsizeY))
00120   && ((vp->xyz[2] > TVpointZ) && (vp->xyz[2] < TVpointZ+TVsizeZ))
00121    )return TRUE;
00122  return FALSE;
00123 }
00124 
00125 BOOL IdentifyCurve(long *Np, long **Va, BOOL *loop){
00126  vertex *Vp;
00127  long vp,vf,*va;
00128  double d,dmin,drange;
00129  long Npath;
00130  *Va=NULL;
00131  *Np=0;
00132  if(NvertSelect < 1)return FALSE;
00133  if(NvertSelect > 1000)return FALSE;
00134  dmin=(double)TVsizeX*(double)TVsizeX;
00135  drange=dmin/1024;
00136  vp=0; vf= -1;
00137  while(vp < Nvert){
00138    Vp=(MainVp+vp);
00139    if(Vp->status == SELECTED && intriview(Vp)){
00140      d=(double)(Vp->xyz[0]-NpointerX)*(double)(Vp->xyz[0]-NpointerX)
00141       +(double)(Vp->xyz[1]-NpointerY)*(double)(Vp->xyz[1]-NpointerY)
00142       +(double)(Vp->xyz[2]-NpointerZ)*(double)(Vp->xyz[2]-NpointerZ);
00143      if(d < dmin && d < drange){
00144        dmin=d;
00145        vf=vp;
00146      }
00147    }
00148    Vp->id=0; /* use this bit for found flag */
00149    vp++;
00150  }
00151  if(vf < 0)return FALSE;
00152  if((va=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
00153    return FALSE;
00154  }
00155  *Va=va;
00156  Npath=0; va[0]=vf; (MainVp+va[0])->id=1;
00157  vp=0; while(vp < Nvert){
00158    Vp=(MainVp+vp);
00159    if(Vp->status == SELECTED && Vp->id == 0 && Connected(va[Npath],vp)){
00160      Npath++;
00161      va[Npath]=vp;
00162      Vp->id=1;
00163      vp=0;
00164    }
00165    else vp++;
00166  }
00167  if(Connected(va[Npath],va[0]))*loop = TRUE;
00168  else                          *loop = FALSE;
00169  if(*loop){
00170    if((va=(long *)X__Realloc(va,(Npath+2)*sizeof(long))) == NULL){
00171      return FALSE;
00172    }
00173    *Va=va;
00174    Npath++;
00175    va[Npath]=va[0];
00176  }
00177  Npath++;
00178  if(Npath < 4)return FALSE;
00179  *Np=Npath;
00180  return TRUE;
00181 }
00182 
00183 static int Subdivide(long down_to_f, long down_to_e){
00184  face *fp;
00185  edge *ep;
00186  vertex *vp,*V0,*V1,*V2;
00187  long i,j,vl,vr,id,nf=0,ne=0,n,Nedge1,Nface1,Nv1;
00188  long Npath=0,*Vpath=NULL;
00189  VERTEXVERTEX *vlist=NULL;
00190  FACEEXTRA    *MainLp=NULL,*lp;
00191  HCURSOR hSave;
00192  BOOL loop;
00193  // identity the curve
00194  if(!IdentifyCurve(&Npath,&Vpath,&loop)){
00195    if(Vpath != NULL)X__Free(Vpath);
00196    return FAIL;
00197  }
00198  for(i=0;i<Npath;i++)(MainVp+Vpath[i])->status=INEDITOR;
00199  X__Free(Vpath);
00200  // unidentity any selected vertices NOT on curve
00201  for(i=0;i<Nvert;i++){
00202    if(     (MainVp+i)->status == SELECTED)(MainVp+i)->status=INEDITOR;
00203    else if((MainVp+i)->status == INEDITOR)(MainVp+i)->status=SELECTED;
00204  }
00205  /* get upper bound for number of faces selected */
00206  if(down_to_f < Nface){
00207    if((MainLp=(FACEEXTRA *)X__Malloc(Nface*sizeof(FACEEXTRA))) == NULL){
00208      return FAIL;
00209    }
00210    fp=(MainFp+down_to_f); lp=(MainLp+down_to_f); nf=0;
00211    for(i=down_to_f;i<Nface;i++){
00212      lp->extra = -1;
00213      lp->xxtra = -1;
00214      V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00215      if((V0->status == SELECTED && V1->status == SELECTED) ||
00216         (V1->status == SELECTED && V2->status == SELECTED) ||
00217         (V2->status == SELECTED && V0->status == SELECTED)){
00218        nf++;
00219      }
00220      fp++; lp++;
00221    }
00222  }
00223  for(ep=(MainEp+down_to_e),ne=0,i=down_to_e;i<Nedge;i++){
00224    if((MainVp+ep->V[0])->status == SELECTED &&
00225       (MainVp+ep->V[1])->status == SELECTED)ne++; // number of edges to be divided
00226    ep++;
00227  }
00228  if(ne == 0){
00229    if(MainLp != NULL)X__Free(MainLp);
00230    return FAIL;
00231  }
00232  /* extend the Vertices Edges and Faces arrays to their upper bounds */
00233  if((vlist=(VERTEXVERTEX *)X__Malloc(ne*sizeof(VERTEXVERTEX))) == NULL){
00234    if(MainLp != NULL)X__Free(MainLp);
00235    return FAIL;
00236  }
00237  if(!UpdateVertexHeap(Nvert+ne))goto EP1;
00238  if(!UpdateEdgeHeap(Nedge+ne+nf*3))goto EP1;
00239  if(!UpdateFaceHeap(Nface+nf*3))goto EP1;
00240  Nface1=Nface; Nedge1=Nedge;
00241  ep=(MainEp+down_to_e); n=0;
00242  for(i=down_to_e;i<Nedge1;i++){
00243    vl=ep->V[0]; V0=(MainVp+vl); vr=ep->V[1]; V1=(MainVp+vr);
00244    if(V0->status == SELECTED && V1->status == SELECTED){
00245      CreateVertex(); Nv1=Nvert-1;
00246      vlist[n].vl=vl; vlist[n].vr=vr; (MainVp+Nv1)->id=n; n++;
00247      (MainVp+Nv1)->xyz[0]=(V0->xyz[0] + V1->xyz[0])/2;
00248      (MainVp+Nv1)->xyz[1]=(V0->xyz[1] + V1->xyz[1])/2;
00249      (MainVp+Nv1)->xyz[2]=(V0->xyz[2] + V1->xyz[2])/2;
00250      CreateEdge(Nv1,ep->V[1]);
00251      ep->V[1]=Nv1;
00252      if(down_to_f < Nface1){
00253        fp=(MainFp+down_to_f); lp=(MainLp+down_to_f);
00254        for(j=down_to_f;j<Nface1;j++){
00255         id=0;
00256         if     ((fp->V[0] == vl && fp->V[1] == vr) ||
00257                 (fp->V[0] == vr && fp->V[1] == vl) )id=1;
00258         else if((fp->V[1] == vl && fp->V[2] == vr) ||
00259                 (fp->V[1] == vr && fp->V[2] == vl) )id=2;
00260         else if((fp->V[2] == vl && fp->V[0] == vr) ||
00261                 (fp->V[2] == vr && fp->V[0] == vl) )id=3;
00262         if(id != 0){
00263           if(lp->extra < 0)lp->extra=Nv1;
00264           else{
00265             if(lp->xxtra < 0)lp->xxtra=Nv1;
00266             else{
00267                CreateEdge(Nv1,lp->extra);
00268                CreateEdge(Nv1,lp->xxtra);
00269                CreateEdge(lp->extra,lp->xxtra);
00270                if     (id == 1){
00271                  if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00272                              fp->V[2],lp->xxtra,lp->extra))
00273                    CreateFace(fp->V[2],lp->xxtra,lp->extra);
00274                  else
00275                    CreateFace(fp->V[2],lp->extra,lp->xxtra);
00276                  CopyFaceProp(fp,(MainFp+Nface-1));
00277                  if(vlist[(MainVp+lp->extra)->id].vl == fp->V[0] ||
00278                     vlist[(MainVp+lp->extra)->id].vr == fp->V[0]){
00279                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00280                                fp->V[0],Nv1,lp->extra))
00281                      CreateFace(fp->V[0],Nv1,lp->extra);
00282                    else
00283                      CreateFace(fp->V[0],lp->extra,Nv1);
00284                    CopyFaceProp(fp,(MainFp+Nface-1));
00285                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00286                                fp->V[1],Nv1,lp->xxtra))
00287                      CreateFace(fp->V[1],Nv1,lp->xxtra);
00288                    else
00289                      CreateFace(fp->V[1],lp->xxtra,Nv1);
00290                    CopyFaceProp(fp,(MainFp+Nface-1));
00291                  }
00292                  else{
00293                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00294                                fp->V[1],Nv1,lp->extra))
00295                      CreateFace(fp->V[1],Nv1,lp->extra);
00296                    else
00297                      CreateFace(fp->V[1],lp->extra,Nv1);
00298                    CopyFaceProp(fp,(MainFp+Nface-1));
00299                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00300                                fp->V[0],Nv1,lp->xxtra))
00301                      CreateFace(fp->V[0],Nv1,lp->xxtra);
00302                    else
00303                      CreateFace(fp->V[0],lp->xxtra,Nv1);
00304                    CopyFaceProp(fp,(MainFp+Nface-1));
00305                  }
00306                }
00307                else if(id == 2){
00308                  if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00309                              fp->V[0],lp->xxtra,lp->extra))
00310                    CreateFace(fp->V[0],lp->xxtra,lp->extra);
00311                  else
00312                    CreateFace(fp->V[0],lp->extra,lp->xxtra);
00313                  CopyFaceProp(fp,(MainFp+Nface-1));
00314                  if(vlist[(MainVp+lp->extra)->id].vl == fp->V[1] ||
00315                     vlist[(MainVp+lp->extra)->id].vr == fp->V[1]){
00316                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00317                                fp->V[1],Nv1,lp->extra))
00318                      CreateFace(fp->V[1],Nv1,lp->extra);
00319                    else
00320                      CreateFace(fp->V[1],lp->extra,Nv1);
00321                    CopyFaceProp(fp,(MainFp+Nface-1));
00322                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00323                                fp->V[2],Nv1,lp->xxtra))
00324                      CreateFace(fp->V[2],Nv1,lp->xxtra);
00325                    else
00326                      CreateFace(fp->V[2],lp->xxtra,Nv1);
00327                    CopyFaceProp(fp,(MainFp+Nface-1));
00328                  }
00329                  else{
00330                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00331                                fp->V[2],Nv1,lp->extra))
00332                      CreateFace(fp->V[2],Nv1,lp->extra);
00333                    else
00334                      CreateFace(fp->V[2],lp->extra,Nv1);
00335                    CopyFaceProp(fp,(MainFp+Nface-1));
00336                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00337                                fp->V[1],Nv1,lp->xxtra))
00338                      CreateFace(fp->V[1],Nv1,lp->xxtra);
00339                    else
00340                      CreateFace(fp->V[1],lp->xxtra,Nv1);
00341                    CopyFaceProp(fp,(MainFp+Nface-1));
00342                  }
00343                }
00344                else if(id == 3){
00345                  if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00346                              fp->V[1],lp->xxtra,lp->extra))
00347                    CreateFace(fp->V[1],lp->xxtra,lp->extra);
00348                  else
00349                    CreateFace(fp->V[1],lp->extra,lp->xxtra);
00350                  CopyFaceProp(fp,(MainFp+Nface-1));
00351                  if(vlist[(MainVp+lp->extra)->id].vl == fp->V[2] ||
00352                     vlist[(MainVp+lp->extra)->id].vr == fp->V[2]){
00353                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00354                                fp->V[2],Nv1,lp->extra))
00355                      CreateFace(fp->V[2],Nv1,lp->extra);
00356                    else
00357                      CreateFace(fp->V[2],lp->extra,Nv1);
00358                    CopyFaceProp(fp,(MainFp+Nface-1));
00359                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00360                                fp->V[0],Nv1,lp->xxtra))
00361                      CreateFace(fp->V[0],Nv1,lp->xxtra);
00362                    else
00363                      CreateFace(fp->V[0],lp->xxtra,Nv1);
00364                    CopyFaceProp(fp,(MainFp+Nface-1));
00365                  }
00366                  else{
00367                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00368                                fp->V[0],Nv1,lp->extra))
00369                      CreateFace(fp->V[0],Nv1,lp->extra);
00370                    else
00371                     CreateFace(fp->V[0],lp->extra,Nv1);
00372                    CopyFaceProp(fp,(MainFp+Nface-1));
00373                    if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00374                                fp->V[2],Nv1,lp->xxtra))
00375                      CreateFace(fp->V[2],Nv1,lp->xxtra);
00376                    else
00377                      CreateFace(fp->V[2],lp->xxtra,Nv1);
00378                    CopyFaceProp(fp,(MainFp+Nface-1));
00379                  }
00380                }
00381                if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00382                           lp->xxtra,lp->extra,Nv1)){
00383                  fp->V[0]=lp->xxtra;
00384                  fp->V[1]=lp->extra;
00385                  fp->V[2]=Nv1;
00386                }
00387                else{
00388                  fp->V[0]=lp->xxtra;
00389                  fp->V[1]=Nv1;
00390                  fp->V[2]=lp->extra;
00391                }
00392                lp->extra = -1;
00393                lp->xxtra = -1;
00394             }
00395           }
00396         }
00397         fp++; lp++;
00398        }
00399      }
00400    }
00401    ep++;
00402  }
00403  if(down_to_f < Nface1){
00404    fp=(MainFp+down_to_f); lp=(MainLp+down_to_f);
00405    for(i=down_to_f;i<Nface1;i++){
00406      V0=(MainVp+fp->V[0]);
00407      V1=(MainVp+fp->V[1]);
00408      V2=(MainVp+fp->V[2]);
00409      if(lp->extra >= 0){
00410        if(V0->status == DESELECTED){
00411          if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00412                       fp->V[0],lp->extra,fp->V[2]))
00413            CreateFace(fp->V[0],lp->extra,fp->V[2]);
00414          else
00415            CreateFace(fp->V[0],fp->V[2],lp->extra);
00416          CopyFaceProp(fp,(MainFp+Nface-1));
00417          CreateEdge(fp->V[0],lp->extra);
00418          fp->V[2] = lp->extra;
00419        }
00420        else if(V1->status == DESELECTED){
00421          if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00422                       fp->V[1],lp->extra,fp->V[0]))
00423            CreateFace(fp->V[1],lp->extra,fp->V[0]);
00424          else
00425            CreateFace(fp->V[1],fp->V[0],lp->extra);
00426          CopyFaceProp(fp,(MainFp+Nface-1));
00427          CreateEdge(fp->V[1],lp->extra);
00428          fp->V[0] = lp->extra;
00429        }
00430        else if(V2->status == DESELECTED){
00431          if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00432                       fp->V[2],lp->extra,fp->V[1]))
00433            CreateFace(fp->V[2],lp->extra,fp->V[1]);
00434          else
00435            CreateFace(fp->V[2],fp->V[1],lp->extra);
00436          CopyFaceProp(fp,(MainFp+Nface-1));
00437          CreateEdge(fp->V[2],lp->extra);
00438          fp->V[1] = lp->extra;
00439        }
00440      }
00441      fp++; lp++;
00442    }
00443  }
00444  X__Free(vlist);
00445  if(MainLp != NULL)X__Free(MainLp);
00446  // get the new curve included subdivied vertices
00447  if(!IdentifyCurve(&Npath,&Vpath,&loop)){
00448    if(Vpath != NULL)X__Free(Vpath);
00449    return FAIL;
00450  }
00451  // relabel any INEDITOR vertex
00452  for(i=0;i<Nvert;i++){
00453    if((MainVp+i)->status == INEDITOR)(MainVp+i)->status=SELECTED;
00454  }
00455  // smooth out the divided curve
00456  SmoothOutCurve(Npath,Vpath,loop);
00457  X__Free(Vpath);
00458  return OK;
00459  EP1:
00460  if(MainLp != NULL)X__Free(MainLp);
00461  X__Free(vlist);
00462  return FAIL;
00463 }
00464 
00465 static void SmoothOutCurve(long Npath, long *Vpath, BOOL loop){
00466  long c,i,j,l,n;
00467  double vl,v1,v2,vn,k[4];
00468 //{char str[256]; sprintf(str,"Npath %ld Selected %ld",Npath,NvertSelect);
00469 // if(loop)MessageBox(NULL,str,"LOOP",MB_OK);
00470 // else MessageBox(NULL,str,"NO LOOP",MB_OK);
00471 //}
00472  for(i=0;i<Npath-2;i+=2){
00473    for(c=0;c<3;c++){
00474      j=i+2;
00475      v1=(double)(MainVp+Vpath[i])->xyz[c];
00476      v2=(double)(MainVp+Vpath[j])->xyz[c];
00477      if(i == 0){
00478        if(loop)vl=(double)(MainVp+Vpath[Npath-3])->xyz[c];
00479        else    vl=(double)(2*((MainVp+Vpath[i])->xyz[c]) -
00480                               (MainVp+Vpath[j])->xyz[c]);
00481        vn=(double)(MainVp+Vpath[j+2])->xyz[c];
00482      }
00483      else if(i == Npath-3){
00484        vl=(double)(MainVp+Vpath[i-2])->xyz[c];
00485        if(loop)vn=(double)(MainVp+Vpath[2])->xyz[c];
00486        else    vn=(double)(2*((MainVp+Vpath[j])->xyz[c]) -
00487                               (MainVp+Vpath[i])->xyz[c]);
00488      }
00489      else{
00490        vl=(double)(MainVp+Vpath[i-2])->xyz[c];
00491        vn=(double)(MainVp+Vpath[j+2])->xyz[c];
00492      }
00493      SplinesK(k,vl,v1,v2,vn);
00494      (MainVp+Vpath[i+1])->xyz[c] = (long)SplinesR(k,0.5);
00495    }
00496  }
00497  return;
00498 }

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