/********************************************************************** *< FILE: MNMesh.h DESCRIPTION: Special mesh structures useful for face and edge based mesh operations. CREATED BY: Steve Anderson, working for Kinetix! HISTORY: created March 1997 from old SDMesh and WMesh. *> Copyright (c) 1996 Autodesk, Inc., All Rights Reserved. **********************************************************************/ // Necessary prior inclusions: max.h // Classes: // MNMesh // MNVert // MNEdge // MNFace // MNMeshBorder #ifndef __MN_MESH_H_ #define __MN_MESH_H_ #define REALLOC_SIZE 10 // Boolean types: we use the same ones defined in mesh.h //#define MESHBOOL_UNION 1 //#define MESHBOOL_INTERSECTION 2 //#define MESHBOOL_DIFFERENCE 3 // General flags for all components // For MNVerts, MNEdges, and MNFaces, bits 0-7 are used for common characteristics // of all components. Bits 8-15 are used for component-specific flags. Bits 16-23 are reserved // for temporary use in MNMesh algorithms. Bits 24-31 are reserved for MNMath.lib users. #define MN_SEL (1<<0) #define MN_DEAD (1<<1) #define MN_TARG (1<<2) #define MN_BACKFACING (1<<3) #define MN_HIDDEN (1<<4) #define MN_WHATEVER (1<<16) // Temporary flag used internally for whatever. #define MN_USER (1<<24) // Anything above this can be used by applications. // Vertex flags #define MN_VERT_DONE (1<<8) #define MN_VERT_HIDDEN (1<<9) // different from MN_HIDDEN - means a vert is on a face's hvtx list. class MNMesh; class MNVert : public FlagUser { public: Point3 p; int orig; // Original point this vert comes from. -- STEVE, remove, only used in connect. MNVert () { orig = -1; } DllExport MNVert & operator= (MNVert & from); }; // Edge flags #define MN_EDGE_INVIS (1<<8) #define MN_EDGE_NOCROSS (1<<9) #define MN_EDGE_MAP_SEAM (1<<10) // Edge goes from v1 to v2 // f1 is forward-indexing face (face on "left" if surface normal above, v2 in front) // f2 is backward-indexing face, or -1 if no such face exists. (Face on "right") class MNEdge : public FlagUser { public: int v1, v2; int f1, f2; int track; // Keep track of whatever. MNEdge() { Init(); } MNEdge (int vv1, int vv2, int fc) { f1=fc; f2=-1; v1=vv1; v2=vv2; track=-1; } void Init() { v1=v2=f1=0; f2=-1; track=-1; } int OtherFace (int ff) { return (ff==f1) ? f2 : f1; } int OtherVert (int vv) { return (vv==v1) ? v2 : v1; } void Invert () { int hold=v1; v1=v2; v2=hold; hold=f1; f1=f2; f2=hold; } DllExport void ReplaceFace (int of, int nf, int vv1=-1); void ReplaceVert (int ov, int nv) { if (v1 == ov) v1 = nv; else { MaxAssert (v2==ov); v2 = nv; } } DllExport bool Uncrossable (); DllExport MNEdge & operator= (const MNEdge & from); DllExport void MNDebugPrint (); }; class MNMapFace { friend class MNMesh; int dalloc, halloc; public: int deg, hdeg; int *tv, *htv; MNMapFace() { Init(); } DllExport MNMapFace (int d, int h=0); ~MNMapFace () { Clear(); } DllExport void Init(); DllExport void Clear(); DllExport void SetAlloc (int d, int h=0); void SetSize (int d, int h=0) { SetAlloc(d,h); deg=d; hdeg=h; } DllExport void MakePoly (int fdeg, int *tt); DllExport void Insert (int pos, int num=1); DllExport void Delete (int pos, int num=1); DllExport void HInsert (int pos, int num=1); DllExport void HDelete (int pos, int num=1); DllExport void RotateStart (int newstart); DllExport void Flip (); // Reverses order of verts. 0 remains start. DllExport int VertIndex (int vv); DllExport void ReplaceVert (int ov, int nv); DllExport MNMapFace & operator= (const MNMapFace & from); DllExport void MNDebugPrint (bool hinfo=TRUE); }; // MNFace flags: #define MN_FACE_OPEN_REGION (1<<8) // Face is not part of closed submesh. #define MN_FACE_CHECKED (1<<9) // for recursive face-and-neighbor-checking #define MN_FACE_CHANGED (1<<10) class MNFace : public FlagUser { friend class MNMesh; int dalloc, halloc, talloc; void Init(); void SwapContents (MNFace & from); public: int deg; // Degree: number of vtx's and edg's that are relevant. int *vtx; // Defining verts of this face. int *edg; int *tri; // Triangulation int hdeg; int *hvtx; // Hidden verts DWORD smGroup; MtlID material; int track; // Keep track of whatever -- MNMesh internal use only. BitArray visedg, edgsel; MNFace() { Init(); } DllExport MNFace (int d, int h=0); DllExport MNFace (const MNFace *from); ~MNFace () { Clear(); } DllExport void Clear(); int TriNum() { return deg - 2 + 2*hdeg; } DllExport int TriVert(int k); DllExport void SetAlloc (int d, int h=0); DllExport void MakePoly (int fdeg, int *vv, bool *vis=NULL, bool *sel=NULL); DllExport void Insert (int pos, int num=1); DllExport bool Delete (int pos, int num=1, int edir=1, bool fixtri=TRUE); DllExport void HInsert (int pos, int num=1); DllExport void HDelete (int pos, int num=1); DllExport void RotateStart (int newstart); DllExport void Flip (); // Reverses order of verts. 0 remains start. DllExport int VertIndex (int vv, int ee=-1); DllExport int EdgeIndex (int ee, int vv=-1); DllExport void ReplaceVert (int ov, int nv, int ee=-1); DllExport void ReplaceEdge (int oe, int ne, int vv=-1); DllExport MNFace & operator= (const MNFace & from); DllExport void MNDebugPrint (bool triprint=FALSE, bool hinfo=TRUE); DllExport IOResult Save (ISave *isave); DllExport IOResult Load (ILoad *iload); }; /* class MNFaceTriCache { friend class MNMesh; int fid; int deg; int *tri; int hdeg; int *htri; double *hbary; MNFaceTriCache () { tri=NULL; htri=NULL; hbary=NULL; hdeg=0; deg=0; fid=-1; } ~MNFaceTriCache () { if (tri) delete [] tri; if (htri) delete [] htri; if (hbary) delete [] hbary; } DllExport void SetDeg (int degg); DllExport void SetHDeg (int hdegg); }; */ class MNMap : public FlagUser { friend class MNMesh; int nv_alloc, nf_alloc; public: MNMapFace *f; UVVert *v; int numv, numf; MNMap () { Init(); } ~MNMap () { ClearAndFree (); } // Initialization, allocation: DllExport void Init (); DllExport void VAlloc (int num, bool keep=TRUE); DllExport void FAlloc (int num, bool keep=TRUE); // Data access: int VNum () const { return numv; } UVVert V(int i) const { return v[i]; } int FNum () const { return numf; } MNMapFace *F(int i) const { return &(f[i]); } // Adding new components -- all allocation should go through here! DllExport int NewTri (int a, int b, int c); DllExport int NewTri (int *vv); DllExport int NewQuad (int a, int b, int c, int d); DllExport int NewQuad (int *vv); DllExport int NewFace (int degg=0, int *vv=NULL); DllExport void setNumFaces (int nfnum); DllExport int NewVert (UVVert p, int uoff=0, int voff=0); DllExport void setNumVerts (int nvnum); DllExport void CollapseDeadVerts (MNFace *faces); // Figures out which are dead. DllExport void CollapseDeadFaces (MNFace *faces); DllExport void Clear (); // Deletes everything. DllExport void ClearAndFree (); // Deletes everything, frees all memory DllExport void Transform (Matrix3 & xfm); // o(n) -- transforms verts // operators and debug printing DllExport MNMap & operator= (const MNMap & from); DllExport MNMap & operator+= (const MNMap & from); DllExport MNMap & operator+= (const MNMesh & from); DllExport void ShallowCopy (const MNMap & from); DllExport void NewAndCopy (); DllExport void MNDebugPrint (MNFace *faces); DllExport bool CheckAllData (int mp, int nf, MNFace *faces); DllExport IOResult Save (ISave *isave, MNFace *faces=NULL); DllExport IOResult Load (ILoad *iload, MNFace *faces=NULL); }; // Per-edge data #define MAX_EDGEDATA 10 #define EDATA_KNOT 0 DllExport int EdgeDataType (int edID); DllExport void *EdgeDataDefault (int edID); #define MN_MESH_NONTRI (1<<0) // At least 2 triangles have been joined #define MN_MESH_FILLED_IN (1<<1) // All topological links complete #define MN_MESH_RATSNEST (1<<2) // Set if we've replicated points to avoid rats' nest meshes. #define MN_MESH_NO_BAD_VERTS (1<<3) // Set if we've established that each vert has exactly one connected component of faces & edges. #define MN_MESH_VERTS_ORDERED (1<<4) // Set if we've ordered the fac, edg tables in each vert. #define MN_MESH_HAS_VOLUME (1<<7) // Some subset of mesh describes closed surface of solid #define MN_MESH_CACHE_FLAGS (MN_MESH_FILLED_IN|MN_MESH_NO_BAD_VERTS|MN_MESH_VERTS_ORDERED) class MNMeshBorder; typedef MNMap * MNMP; // MNMesh selection levels: #define MNM_SL_OBJECT 0 #define MNM_SL_VERTEX 1 #define MNM_SL_EDGE 2 #define MNM_SL_FACE 3 #define MNM_SL_TRI 4 // MNMesh display flags #define MNDISP_VERTTICKS 0x01 #define MNDISP_SELVERTS 0x02 #define MNDISP_SELFACES 0x04 #define MNDISP_SELEDGES 0x08 #define MNDISP_NORMALS 0x10 #define MNDISP_SMOOTH_SUBSEL 0x20 #define MNDISP_BEEN_DISP 0x40 class MNMesh : public FlagUser { private: int nv_alloc, ne_alloc, nf_alloc, nm_alloc; // Cache geometric data for quick rendering Box3 bdgBox; Point3 *fnorm; RVertex *rVerts; // <<< instance specific. GraphicsWindow *cacheGW; // identifies rVerts cache int normalsBuilt; float norScale; //Tab tcache; // Internal part of SabinDoo method: void SDVEdgeFace (int id, int vid, int *fv, Tab *> & fmv, DWORD selLevel); // Internal part of recursive smoothing-group search. DWORD FindReplacementSmGroup (int ff, DWORD os, int call); // Internal parts of Boolean. (MNBool.cpp) int BooleanZip (DWORD sortFlag, float weldThresh); bool BoolZipSeam (Tab *lpi, Tab *lpj, int & starth, int & startk, float weldThresh); void BoolPaintClassification (int ff, DWORD classification, int calldepth); // Internal data cache stuff (MNPipe.cpp) void buildBoundingBox (); void buildFaceNormals (); public: MNVert *v; MNEdge *e; MNFace *f; MNMap *m; int numv, nume, numf, numm; // Vertex Data -- handled as in Meshes: PerData *vd; BitArray vdSupport; // Edge Data PerData *ed; BitArray edSupport; DWORD selLevel; DWORD dispFlags; // Derived data: Tab *vedg; Tab *vfac; // Basic class ops MNMesh () { Init(); DefaultFlags (); } MNMesh (const Mesh & from) { Init(); SetFromTri (from); FillInMesh (); } MNMesh (const MNMesh & from) { Init(); DefaultFlags(); *this = from; } ~MNMesh() { ClearAndFree (); } // Initialization: void DefaultFlags () { ClearAllFlags (); } DllExport void Init (); // Array allocation: these functions (& Init) have sole control over nvalloc, etc. void VAlloc (int num, bool keep=TRUE); void VShrink (int num=-1); // default means "Shrink array allocation to numv" void freeVEdge(); void VEdgeAlloc(); void freeVFace(); void VFaceAlloc(); void EAlloc (int num, bool keep=TRUE); void EShrink (int num=-1); void FAlloc (int num, bool keep=TRUE); void FShrink (int num=-1); void MAlloc (int num, bool keep=TRUE); void MShrink (int num=-1); // Access to components int VNum () const { return numv; } MNVert *V(int i) const { return &(v[i]); } Point3 & P(int i) const { return v[i].p; } int ENum () const { return nume; } MNEdge *E(int i) const { return &(e[i]); } int FNum () const { return numf; } MNFace *F(int i) const { return &(f[i]); } int MNum () const { return numm; } MNMap *M(int i) const { return &(m[i]); } DllExport void SetMapNum (int mpnum); DllExport void InitMap (int mp); // Inits to current MNMesh topology. void ClearMap (int mp) { if (mp & lp, Tab & mv, int mp); // Following functions can be used to find & fix holes in a mesh, if any. DllExport void GetBorder (MNMeshBorder & brd, DWORD selLevel=MESH_OBJECT); DllExport void FillInBorders (MNMeshBorder *b=NULL); DllExport void FindOpenRegions (); // To make hidden verts behave when moving real ones, use following: DllExport void PrepForGeomChange (); DllExport void CompleteGeomChange (); // operators and debug printing (MNFace.cpp) DllExport MNMesh & operator= (const MNMesh & from); DllExport MNMesh & operator+= (const MNMesh & from); DllExport void MNDebugPrint (bool triprint=FALSE); DllExport void MNDebugPrintVertexNeighborhood (int vv, bool triprint=FALSE); DllExport bool CheckAllData (); // Split functions maintain topological info. (MNSplit.cpp) DllExport int SplitTriEdge (int ee, float prop=.5f, float thresh=MNEPS, bool neVis=TRUE, bool neSel=FALSE); DllExport int SplitTriFace (int ff, double *bary=NULL, float thresh=MNEPS, bool neVis=TRUE, bool neSel=FALSE); DllExport void SplitTri6 (int ff, double *bary=NULL, int *nv=NULL); DllExport int SplitEdge (int ee, float prop=.5f); DllExport int SplitEdge (int ee, float prop, int *ntv); DllExport int SplitEdge (int ff, int ed, float prop, bool right, int *nf=NULL, int *ne=NULL, bool neVis=FALSE, bool neSel=FALSE, bool allconvex=FALSE); DllExport int IndentFace (int ff, int ei, int nv, int *ne=NULL, bool nevis=TRUE, bool nesel=FALSE); DllExport void SeparateFace (int ff, int a, int b, int & nf, int & ne, bool neVis=FALSE, bool neSel=FALSE); DllExport void Slice (Point3 & N, float off, float thresh, bool split, bool remove, DWORD selLevel); DllExport void DeleteFlaggedFaces (DWORD deathflags, DWORD nvCopyFlags=0x0); DllExport bool WeldVerts (int a, int b); DllExport bool WeldEdge (int ee); // Tessellation methods: (MNTess.cpp) DllExport void TessellateByEdges (float bulge, MeshOpProgress *mop=NULL); DllExport bool AndersonDo (float interp, DWORD selLevel, MeshOpProgress *mop=NULL); DllExport void TessellateByCenters (MeshOpProgress *mop=NULL); // Sabin-Doo tessellation: (MNSabDoo.cpp) DllExport void SabinDoo (float interp, DWORD selLevel, MeshOpProgress *mop=NULL, Tab *offsets=NULL); DllExport void SabinDooVert (int vid, float interp, DWORD selLevel, Point3 *ctr, Tab *offsets=NULL); // Non-uniform Rational Mesh Smooth (NURMS.cpp) DllExport void CubicNURMS (MeshOpProgress *mop=NULL, Tab *offsets=NULL); DllExport void QuadraticNURMS (MeshOpProgress *mop=NULL, Tab *offsets=NULL); // Boolean functions: (MNBool.cpp) DllExport void PrepForBoolean (); DllExport bool BooleanCut (MNMesh & m2, int cutType, int fstart=0, MeshOpProgress *mop=NULL); DllExport bool MakeBoolean (MNMesh & m1, MNMesh & m2, int type, MeshOpProgress *mop=NULL); // New functionality: mostly pipeline object requirements. (MNPipe.cpp) DllExport void ApplyMapper (UVWMapper & mp, BOOL channel=0, BOOL useSel=FALSE); DllExport void InvalidateGeomCache (); DllExport void InvalidateTopoCache (); DllExport void allocRVerts (); DllExport void updateRVerts (GraphicsWindow *gw); DllExport void freeRVerts (); GraphicsWindow *getCacheGW() { return cacheGW; } void setCacheGW(GraphicsWindow *gw) { cacheGW = gw; } DllExport void checkNormals (BOOL illum); DllExport void buildNormals (); DllExport void buildRenderNormals (); DllExport void UpdateBackfacing (GraphicsWindow *gw, bool force); // Display flags void SetDispFlag(DWORD f) { dispFlags |= f; } DWORD GetDispFlag(DWORD f) { return dispFlags & f; } void ClearDispFlag(DWORD f) { dispFlags &= ~f; } DllExport void render(GraphicsWindow *gw, Material *ma, RECT *rp, int compFlags, int numMat=1); DllExport void renderFace (GraphicsWindow *gw, int ff); DllExport void renderEdge (GraphicsWindow *gw, int ee); DllExport BOOL select (GraphicsWindow *gw, Material *ma, HitRegion *hr, int abortOnHit=FALSE, int numMat=1); DllExport void snap(GraphicsWindow *gw, SnapInfo *snap, IPoint2 *p, Matrix3 &tm); DllExport BOOL SubObjectHitTest(GraphicsWindow *gw, Material *ma, HitRegion *hr, DWORD flags, SubObjHitList& hitList, int numMat=1 ); DllExport int IntersectRay (Ray& ray, float& at, Point3& norm); DllExport int IntersectRay (Ray& ray, float& at, Point3& norm, int &fi, int &ti, Point3 &bary); DllExport BitArray VertexTempSel (DWORD fmask=MN_DEAD, DWORD fset=0); DllExport void ShallowCopy(MNMesh *amesh, DWORD channels); DllExport void NewAndCopyChannels(DWORD channels); DllExport void FreeChannels (DWORD channels, BOOL zeroOthers=1); DllExport IOResult Save (ISave *isave); DllExport IOResult Load (ILoad *iload); }; class MNMeshBorder { friend class MNMesh; Tab *> bdr; BitArray btarg; public: ~MNMeshBorder () { Clear(); } void Clear () { for (int i=0; i *Loop (int i) { return bdr[i]; } bool LoopTarg (int i) { return ((i>=0) && (i