/********************************************************************** *< 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_ // Turn on the following to enable Face Data in PolyObjects: #define MNMESH_FACEDATA_IMPL #include "export.h" #include "baseinterface.h" #include #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_LOCAL_SEL (1<<17) // Alternate selections (not passed up the pipe). #define MN_HITTEST_CULLED (1<<18) // used to indicate "culled" components (neither selected nor not selected) in window-region hit testing #define MN_USER (1<<24) // Anything above this can be used by applications. // Vertex flags #define MN_VERT_DONE (1<<8) #define MN_VERT_WELDED (1<<9) // CAL-04/07/03: ANDY: New flag here, to track which vertices are direct "descendants" of // the original cage vertices in subdivision. #define MN_VERT_SUBDIVISION_CORNER (1<<10) class IHardwareShader; class TriStrip; class MNMesh; class MNVert : public FlagUser { public: Point3 p; int orig; // Original point this vert comes from MNVert () { orig = -1; } DllExport MNVert & operator= (MNVert & from); bool operator==(MNVert & from) { return (from.p==p)&&(from.ExportFlags()==ExportFlags()); } }; // Edge flags #define MN_EDGE_INVIS (1<<8) #define MN_EDGE_NOCROSS (1<<9) #define MN_EDGE_MAP_SEAM (1<<10) // CAL-03/14/03: ANDY: New flag here, to track which edges are direct "descendants" of // the original cage edges in subdivision. #define MN_EDGE_SUBDIVISION_BOUNDARY (1<<11) // SCA - 6/20/04 - new flag to track unwanted edges created by Cut, so they might // be removed later. #define MN_EDGE_CUT_EXTRA (1<<12) // 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); bool operator==(MNEdge & f) { return (f.v1==v1)&&(f.v2==v2)&&(f.f1==f1)&&(f.f2==f2)&&(f.ExportFlags()==ExportFlags()); } int& operator[](int i) { return i ? v2 : v1; } const int& operator[](int i) const { return i ? v2 : v1; } DllExport void MNDebugPrint (); }; class MNFace; class MNMapFace { friend class MNMesh; int dalloc; public: int deg; int *tv; MNMapFace() { Init(); } DllExport MNMapFace (int d); ~MNMapFace () { Clear(); } DllExport void Init(); DllExport void Clear(); DllExport void SetAlloc (int d); void SetSize (int d) { SetAlloc(d); deg=d; } 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 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 MNMapFace & operator= (const MNFace & from); DllExport bool operator== (const MNMapFace & from); DllExport void MNDebugPrint (); }; // 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) // The following macro has been added // in 3ds max 4.2. If your plugin utilizes this new // mechanism, be sure that your clients are aware that they // must run your plugin with 3ds max version 4.2 or higher. #define MN_FACE_CULLED (1<<11) // Used during hit-testing. // End of 3ds max 4.2 Extension // Diagonal sorting algorithm: // Puts diagonals in increase-by-last-index, decrease-by-first order: DllExport void DiagSort (int dnum, int *diag); class MNFace : public FlagUser { friend class MNMesh; int dalloc; 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; // edges on this face. int *diag; // Diagonals DWORD smGroup; MtlID material; int track; // Keep track of whatever -- MNMesh internal use only. BitArray visedg, edgsel; BitArray bndedg; // CAL-03/18/03: boundary edges MNFace() { Init(); } MNFace (int d) { Init(); SetDeg (d); } DllExport MNFace (const MNFace *from); ~MNFace () { Clear(); } DllExport void Init(); DllExport void SetDeg (int d); DllExport void Clear(); int TriNum() { return deg-2; } DllExport int FindTriPoint (int edge); // finds point that makes tri with this edge. DllExport int FindTriPoint (int a, int b); // does the same for nonsequential verts - result is between a,b. DllExport void GetTriangles (Tab &tri); DllExport void SetAlloc (int d); 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 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 bool operator== (const MNFace &from); int& operator[](int i) { return vtx[i]; } const int& operator[](int i) const { return vtx[i]; } DllExport void MNDebugPrint (bool triprint=FALSE); DllExport IOResult Save (ISave *isave); DllExport IOResult Load (ILoad *iload); }; 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 mapChannel, 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 #define EDATA_CREASE 1 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_HITTEST_REQUIRE_ALL (1<<8) // Force faces to be hit only if all triangles are hit. (Internal use.) #define MN_MESH_CACHE_FLAGS (MN_MESH_FILLED_IN|MN_MESH_NO_BAD_VERTS|MN_MESH_VERTS_ORDERED) // These flags are for internal use only. #define MN_MESH_TEMP_1 (1<<13) #define MN_MESH_TEMP_2 (1<<14) class MNMeshBorder; class MNChamferData; class MNFaceClusters; // MNMesh selection levels: // MNM_SL_CURRENT is an acceptable argument to methods that take a selection level, // indicating "use the current mesh selection level". enum PMeshSelLevel { MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, MNM_SL_FACE, MNM_SL_CURRENT }; // 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 #define MNDISP_DIAGONALS 0x80 // CAL-03/14/03: ANDY: New display flag here for the behavior we want. #define MNDISP_HIDE_SUBDIVISION_INTERIORS 0x100 // Flags for sub object hit test // NOTE: these are the same bits used for object level. //#define SUBHIT_SELONLY (1<<0) //#define SUBHIT_UNSELONLY (1<<2) //#define SUBHIT_ABORTONHIT (1<<3) //#define SUBHIT_SELSOLID (1<<4) #define SUBHIT_MNUSECURRENTSEL (1<<22) // When this bit is set, the sel only and unsel only tests will use the current level (edge or face) selection when doing a vertex level hit test #define SUBHIT_OPENONLY (1<<23) #define SUBHIT_MNVERTS (1<<24) #define SUBHIT_MNFACES (1<<25) #define SUBHIT_MNEDGES (1<<26) #define SUBHIT_MNDIAGONALS (1<<27) #define SUBHIT_MNTYPEMASK (SUBHIT_MNVERTS|SUBHIT_MNFACES|SUBHIT_MNEDGES|SUBHIT_MNDIAGONALS) class MNDiagonalHitData : public HitData { public: int mFace, mDiag; MNDiagonalHitData (int face, int diagonal) : mFace(face), mDiag(diagonal) { } ~MNDiagonalHitData () { } }; // Subdivision flags: #define MN_SUBDIV_NEWMAP 0x01 #define MN_SUBDIV_HIDE_INTERNAL_EDGES 0x10 class MNMesh : public FlagUser, public BaseInterfaceServer { friend class HardwareMNMesh; friend void gfxCleanup(void *data); friend class MNNormalSpec; private: static int refCount; static HANDLE workMutex; static HANDLE workEndEvent; 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 // SCA revision for Max 5.0 - value of 0 for unbuilt, 1 for built according to legacy 4.0 scheme, // and 2 for built according to new scheme - this is so that we refresh normals if the user changes // the "Use Legacy 4.0 Vertex Normals" checkbox. int normalsBuilt; float norScale; // Hidden map channels // There are always NUM_HIDDENMAPS of these, but we dynamically allocate them // so that M(mapChannel) can be a const method. (This wouldn't work if we had hmap[NUM_HIDDENMAPS].) MNMap *hmap; // Formerly public normal map channels: MNMap *m; // Vertex color arrays - for display use. int curVCChan; // current map channel to use for colors (default = 0) UVVert *curVCVerts; // possible external color array (default = NULL) MNMapFace *curVCFaces; // possible external face array (default = NULL) DWTab norInd; // indirection array for fast normal lookup int normalCount; // total number of normals Point3 * gfxNormals; // flattened list of normals // Derived arrays to contain generated texture coordinates int numTexCoords[GFX_MAX_TEXTURES]; Point3 * texCoords[GFX_MAX_TEXTURES]; // Derived table of TriStrips, depends on topology Tab *tstab; // Internal part of SabinDoo method: void SDVEdgeFace (int id, int vid, int *fv, Tab *> & fmv, int 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); // Internal data cache stuff (MNPipe.cpp) void buildBoundingBox (); void buildFaceNormals (); GraphicsWindow *getCacheGW() { return cacheGW; } void setCacheGW (GraphicsWindow *gw) { cacheGW = gw; } // New MNMesh routines to drive HardwareShaders bool CanDrawTriStrips(DWORD rndMode, int numMtls, Material *mtl); bool BuildTriStrips(DWORD rndMode, int numMtls, Material *mtl); void TriStripify(DWORD rndMode, int numTex, TVFace *tvf[], TriStrip *s, StripData *sd, int vtx); void Draw3DTriStrips(IHardwareShader *phs, int numMat, Material *ma); void Draw3DWireTriStrips(IHardwareShader *phs, int numMat, Material *ma); void Draw3DVisEdgeList(IHardwareShader *phs, DWORD flags); int render3DTriStrips(IHardwareShader *phs, int kmat, int kstrips); int render3DWireTriStrips(IHardwareShader *phs, int kmat, int kstrips); int render3DFaces(IHardwareShader *phs, DWORD index, int *custVis=NULL); // Vertex Removal approaches - Luna task 748O bool RemoveInternalVertex (int vertex); bool RemoveBorderVertex (int vertex); // Renders without any color handling - used only in hit-testing at this point. void renderSingleDiagonal (GraphicsWindow *gw, int ff, int d); public: MNVert *v; MNEdge *e; MNFace *f; int numv, nume, numf, numm; // Vertex Data -- handled as in Meshes: PerData *vd; BitArray vdSupport; // Edge Data PerData *ed; BitArray edSupport; int 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; } DllExport ~MNMesh(); // Initialization: void DefaultFlags () { ClearAllFlags (); } DllExport void Init (); // Array allocation: these functions (& Init) have sole control over nvalloc, etc. DllExport void VAlloc (int num, bool keep=TRUE); DllExport void VShrink (int num=-1); // default means "Shrink array allocation to numv" DllExport void freeVEdge(); DllExport void VEdgeAlloc(); DllExport void freeVFace(); DllExport void VFaceAlloc(); DllExport void EAlloc (int num, bool keep=TRUE); DllExport void EShrink (int num=-1); DllExport void FAlloc (int num, bool keep=TRUE); DllExport void FShrink (int num=-1); DllExport void MAlloc (int num, bool keep=TRUE); DllExport 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; } DllExport MNMap *M(int mapChannel) const; DllExport void SetMapNum (int mpnum); DllExport void InitMap (int mapChannel); // Inits to current MNMesh topology. DllExport void ClearMap (int mapChannel); DllExport UVVert MV (int mapChannel, int i) const; DllExport MNMapFace *MF (int mapChannel, int i) const; DllExport int TriNum () const; // Per Vertex Data: DllExport void setNumVData (int ct, BOOL keep=FALSE); int VDNum () const { return vdSupport.GetSize(); } DllExport BOOL vDataSupport (int vdChannel) const; DllExport void setVDataSupport (int vdChannel, BOOL support=TRUE); void *vertexData (int vdChannel) const { return vDataSupport(vdChannel) ? vd[vdChannel].data : NULL; } float *vertexFloat (int vdChannel) const { return (float *) vertexData (vdChannel); } DllExport void freeVData (int vdChannel); DllExport void freeAllVData (); // Two specific vertex data: these VDATA constants are defined in mesh.h float *getVertexWeights () { return vertexFloat(VDATA_WEIGHT); } void SupportVertexWeights () { setVDataSupport (VDATA_WEIGHT); } void freeVertexWeights () { freeVData (VDATA_WEIGHT); } float *getVSelectionWeights () { return vertexFloat(VDATA_SELECT); } void SupportVSelectionWeights () { setVDataSupport (VDATA_SELECT); } void freeVSelectionWeights () { freeVData (VDATA_SELECT); } // Per Edge Data: DllExport void setNumEData (int ct, BOOL keep=FALSE); int EDNum () const { return edSupport.GetSize(); } DllExport BOOL eDataSupport (int edChannel) const; DllExport void setEDataSupport (int edChannel, BOOL support=TRUE); void *edgeData (int edChannel) const { return eDataSupport(edChannel) ? ed[edChannel].data : NULL; } float *edgeFloat (int edChannel) const { return (float *) edgeData (edChannel); } DllExport void freeEData (int edChannel); DllExport void freeAllEData (); // One specific edge data: this EDATA constant is defined above float *getEdgeKnots () { return edgeFloat(EDATA_KNOT); } void SupportEdgeKnots () { setEDataSupport (EDATA_KNOT); } void freeEdgeKnots () { freeEData (EDATA_KNOT); } // Vertex face/edge list methods: DllExport void VClear (int vv); DllExport void VInit (int vv); DllExport int VFaceIndex (int vv, int ff, int ee=-1); DllExport int VEdgeIndex (int vv, int ee); void VDeleteEdge (int vv, int ee) { if (vedg) vedg[vv].Delete (VEdgeIndex(vv, ee), 1); } DllExport void VDeleteFace (int vv, int ff); DllExport void VReplaceEdge (int vv, int oe, int ne); DllExport void VReplaceFace (int vv, int of, int nf); DllExport void CopyVert (int nv, int ov); // copies face & edge too if appropriate DllExport void MNVDebugPrint (int vv); // Adding new components -- all allocation should go through here! DllExport int NewTri (int a, int b, int c, DWORD smG=0, MtlID mt=0); DllExport int NewTri (int *vv, DWORD smG=0, MtlID mt=0); DllExport int NewQuad (int a, int b, int c, int d, DWORD smG=0, MtlID mt=0); DllExport int NewQuad (int *vv, DWORD smG=0, MtlID mt=0); DllExport int NewFace (int initFace, int degg=0, int *vv=NULL, bool *vis=NULL, bool *sel=NULL); DllExport int AppendNewFaces (int nfnum); DllExport void setNumFaces (int nfnum); DllExport int RegisterEdge (int v1, int v2, int f, int fpos); DllExport int SimpleNewEdge (int v1, int v2); DllExport int NewEdge (int v1, int v2, int f, int fpos); DllExport int AppendNewEdges (int nenum); DllExport void setNumEdges (int nenum); DllExport int NewVert (Point3 & p); DllExport int NewVert (Point3 & p, int vid); DllExport int NewVert (int vid); DllExport int NewVert (int v1, int v2, float prop); DllExport int AppendNewVerts (int nvnum); DllExport void setNumVerts (int nvnum); // To delete, set MN_*_DEAD flag and use following routines, which are all o(n). DllExport void CollapseDeadVerts (); DllExport void CollapseDeadEdges (); DllExport void CollapseDeadFaces (); DllExport void CollapseDeadStructs(); DllExport void Clear (); // Deletes everything. DllExport void ClearAndFree (); // Deletes everything, frees all memory DllExport void freeVerts(); DllExport void freeEdges(); DllExport void freeFaces(); DllExport void freeMap(int mapChannel); DllExport void freeMaps(); // En Masse flag-clearing and setting: void ClearVFlags (DWORD fl) { for (int i=0; i & lp, Tab & mv, int mapChannel); // Following functions can be used to find & fix holes in a mesh, if any. DllExport void GetBorder (MNMeshBorder & brd, int selLevel=MNM_SL_OBJECT, DWORD targetFlag=MN_SEL); DllExport void FillInBorders (MNMeshBorder *b=NULL); DllExport void FindOpenRegions (); // Doubled mapping verts are individual map vertices that are used to correspond // to different regular vertices. For instance, a box could have a single (1,1,0) // vertex that it uses in the upper-right corner of all quads. This design is // harmful to some of our algorithms, such as the various Tessellators. So the // following two methods detect and fix such vertices. // This method is not really appropriate for release, it's more of a debugging // tool. All doubled mapping verts will be DebugPrinted. DllExport BOOL CheckForDoubledMappingVerts(); // This one's ok and encouraged for release. (Linear-time algorithm.) DllExport void EliminateDoubledMappingVerts(); DllExport void EliminateIsoMapVerts(); DllExport void EliminateIsoMapVerts(int mapChannel); // 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) // Luna task 747: Someday these should all support specified normals - but not today. 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, Tab *newTVerts); 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 bool Slice (Point3 & N, float off, float thresh, bool split, bool remove, bool flaggedFacesOnly=false, DWORD faceFlags=MN_SEL); DllExport void DeleteFlaggedFaces (DWORD deathflags, DWORD nvCopyFlags=0x0); DllExport bool WeldVerts (int a, int b); DllExport bool WeldEdge (int ee); // Tessellation methods: (MNTess.cpp) // Luna task 747: Someday these should all support specified normals - but not today. DllExport void TessellateByEdges (float bulge, MeshOpProgress *mop=NULL); DllExport bool AndersonDo (float interp, int selLevel, MeshOpProgress *mop=NULL, DWORD subdivFlags=0); DllExport void TessellateByCenters (MeshOpProgress *mop=NULL); // Sabin-Doo tessellation: (MNSabDoo.cpp) // Luna task 747: Someday these should both support specified normals - but not today. DllExport void SabinDoo (float interp, int selLevel, MeshOpProgress *mop=NULL, Tab *offsets=NULL); DllExport void SabinDooVert (int vid, float interp, int selLevel, Point3 *ctr, Tab *offsets=NULL); // Non-uniform Rational Mesh Smooth (NURMS.cpp) // Luna task 747: Someday this should support specified normals - but not today. DllExport void CubicNURMS (MeshOpProgress *mop=NULL, Tab *offsets=NULL, DWORD subdivFlags=0); //DllExport void CubicNURMSMesh (Mesh & out, MeshOpProgress *mop=NULL, DWORD subdivFlags=0); // Boolean functions: (MNBool.cpp) // Luna task 747: Someday these should all support specified normals - but not today. 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); DllExport void Connect (MNMeshBorder & borderList, int segs, float tension, bool sm_bridge, bool sm_ends, Tab *vsep=NULL); DllExport void ConnectLoops (Tab & loop1, Tab & loop2, int segs, float tension, DWORD smGroup, MtlID mat, bool sm_ends); // Small-scale Operations - in MNOps.cpp // Luna task 747: Someday these should all support specified normals - but not today. DllExport void FacePointBary (int ff, Point3 & p, Tab & bary); DllExport void CloneVerts (DWORD cloneFlag = MN_SEL, bool clear_orig=TRUE); DllExport void CloneFaces (DWORD cloneFlag = MN_SEL, bool clear_orig=TRUE); DllExport int DivideFace (int ff, Tab & bary); DllExport int CreateFace (int degg, int *vv); // Moves the flagged subobjects to their average plane. DllExport bool MakeFlaggedPlanar (int selLev, DWORD flag=MN_SEL, Point3 *delta=NULL); // Moves flagged vertices to the plane given, or produces an array of offsets which would do so. DllExport bool MoveVertsToPlane (Point3 & norm, float offset, DWORD flag=MN_SEL, Point3 *delta=NULL); DllExport bool SplitFlaggedVertices (DWORD flag=MN_SEL); DllExport bool SplitFlaggedEdges (DWORD flag=MN_SEL); DllExport bool DetachFaces (DWORD flag=MN_SEL); DllExport bool DetachElementToObject (MNMesh & nmesh, DWORD fflags=MN_SEL, bool delDetached=true); DllExport bool ExtrudeFaceClusters (MNFaceClusters & fclust); DllExport bool ExtrudeFaceCluster (MNFaceClusters & fclust, int cl); DllExport bool ExtrudeFaces (DWORD flag=MN_SEL); // Does each face separately // Bug fix: second version of GetExtrudeDirection so that a faceFlag can be // passed in when there are no relevant face clusters. -sca 2001.12.12 // Version which accepts faceFlag is NEW FOR 5.0! // Do not use if you wish to maintain backward compatibility with 4.0! DllExport void GetExtrudeDirection (MNChamferData *mcd, DWORD faceFlag); DllExport void GetExtrudeDirection (MNChamferData *mcd, MNFaceClusters *fclust=NULL, Point3 *clustNormals=NULL); DllExport bool SetVertColor (UVVert clr, int mapChannel, DWORD flag=MN_SEL); DllExport bool SetFaceColor (UVVert clr, int mapChannel, DWORD flag=MN_SEL); DllExport bool ChamferVertices (DWORD flag=MN_SEL, MNChamferData *mcd=NULL); DllExport bool ChamferEdges (DWORD flag=MN_SEL, MNChamferData *mcd=NULL); DllExport bool FlipElementNormals (DWORD flag=MN_SEL); DllExport void SmoothByCreases (DWORD creaseFlag); DllExport int CutFace (int f1, Point3 & p1, Point3 & p2, Point3 & Z, bool split); DllExport int CutEdge (int e1, float prop1, int e2, float prop2, Point3 & Z, bool split); DllExport int Cut (int startv, Point3 & end, Point3 & Z, bool split); DllExport bool WeldBorderVerts (int v1, int v2, Point3 *destination); DllExport bool WeldBorderEdges (int e1, int e2); DllExport bool WeldBorderVerts (float thresh, DWORD flag=MN_SEL); // Pipeline object requirements. (MNPipe.cpp) DllExport void ApplyMapper (UVWMapper & mapChannel, int channel=0, BOOL useSel=FALSE); DllExport void InvalidateGeomCache (); DllExport void InvalidateTopoCache (); DllExport void UpdateDisplayVertexColors (); DllExport void SetDisplayVertexColors (int chan); DllExport void SetDisplayVertexColors (UVVert *mv, MNMapFace *mf); DllExport void PrepForPipeline (); DllExport void allocRVerts (); DllExport void updateRVerts (GraphicsWindow *gw); DllExport void freeRVerts (); DllExport void checkNormals (BOOL illum); DllExport void buildNormals (); DllExport void buildRenderNormals (); DllExport void UpdateBackfacing (GraphicsWindow *gw, bool force); // This method can be used to invalidate any display-technology-specific caches of the MNMesh. // In particular, it's currently used to invalidate the DirectX cache of the mesh. // This is important to call, for example, after changing Vertex Colors or Texture coordinates, if // you don't already call InvalidateGeomCache (). // "DWORD keepFlags" should be zero. We may someday add flags indicating that some parts of // the hardware mesh cache should be kept, but for now, the whole cache is invalidated. // (An example usage is in maxsdk\samples\mesh\EditablePoly\PolyEdOps.cpp.) DllExport void InvalidateHardwareMesh (DWORD keepFlags=0); // 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, InterfaceServer *pi=NULL); DllExport void renderFace (GraphicsWindow *gw, int ff); DllExport void render3DFace (GraphicsWindow *gw, int ff); DllExport void render3DDiagonals (GraphicsWindow *gw, DWORD compFlags); DllExport void renderDiagonals (GraphicsWindow *gw, DWORD compFlags); DllExport void renderDiagonal (GraphicsWindow *gw, int ff, bool useSegments=false, bool *lastColorSubSel=NULL); DllExport void render3DEdges (GraphicsWindow *gw, DWORD compFlags); DllExport void renderEdges (GraphicsWindow *gw, DWORD compFlags); DllExport void renderEdge (GraphicsWindow *gw, int ee, bool useSegments=false, bool *lastColorSubSel=NULL); DllExport BOOL select (GraphicsWindow *gw, Material *ma, HitRegion *hr, int abortOnHit=FALSE, int numMat=1); 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, Tab & bary); DllExport BitArray VertexTempSel (DWORD fmask=MN_DEAD|MN_SEL, DWORD fset=MN_SEL); DllExport void ShallowCopy(MNMesh *amesh, ULONG_PTR channels); // WIN64 Cleanup: Shuler DllExport void NewAndCopyChannels(ULONG_PTR channels); // WIN64 Cleanup: Shuler DllExport void FreeChannels (ULONG_PTR channels, BOOL zeroOthers=1); // WIN64 Cleanup: Shuler DllExport IOResult Save (ISave *isave); DllExport IOResult Load (ILoad *iload); DllExport void ClearFlag (DWORD fl); // --- from InterfaceServer DllExport BaseInterface* GetInterface(Interface_ID id); // Luna task 748 - New operations for 5.0 // Source in MNOps2.cpp // NOT AVAILABLE IN PREVIOUS VERSIONS - AVOID FOR BACKWARD COMPATIBILITY DllExport bool SeparateMapVerticesInFaceCluster (MNFaceClusters & fclust, int clusterID); DllExport bool ExtrudeFaceClusterAlongPath (Tab tFrenets, MNFaceClusters & fclust, int clusterID, bool align); DllExport bool LiftFaceClusterFromEdge (int liftEdge, float liftAngle, int segments, MNFaceClusters & fclust, int clusterID); DllExport bool IsEdgeMapSeam (int mapChannel, int edge); DllExport void MultiDivideEdge (int edge, int segments); DllExport bool ConnectEdges (DWORD edgeFlag, int segments=2); DllExport bool ConnectVertices (DWORD vertexFlag); DllExport void SelectEdgeLoop (BitArray & edgeSel); DllExport void SelectEdgeRing (BitArray & edgeSel); DllExport bool ExtrudeVertices (DWORD vertexFlag, MNChamferData *pMCD, Tab & tUpDir); DllExport bool ExtrudeEdges (DWORD edgeFlag, MNChamferData *pMCD, Tab & tUpDir); DllExport bool WeldOpposingEdges (DWORD edgeFlag); DllExport bool FlipFaceNormals (DWORD faceFlag); DllExport bool RemoveVertex (int vertex); // Luna task 748O DllExport bool RemoveSpur (int spur); // Used both by WeldEdge and in Luna task 748O DllExport int InsertSpur (int face, int vertIndex, Tab *ptMapVertArray=NULL); // New for task 748F DllExport void FindFaceBaryVector (int face, int vertIndex, Point3 & vector, Tab & tBary); DllExport bool SplitFacesUsingBothSidesOfEdge (DWORD edgeFlag=0x0); // Luna task 747 - New operations for 5.0 // Source in MNNormals.cpp // NOT AVAILABLE IN PREVIOUS VERSIONS - AVOID FOR BACKWARD COMPATIBILITY DllExport MNNormalSpec *GetSpecifiedNormals(); // Returns NULL if SpecifyNormals() has not been called. DllExport MNNormalSpec *GetSpecifiedNormalsForDisplay(); // Returns NULL if no specified normals, or if specified normals not ready to use for display. DllExport void ClearSpecifiedNormals (); DllExport void SpecifyNormals (); // Copies bare geometry only - no per-vertex data, maps, normals, etc. DllExport void CopyBasics (const MNMesh & from, bool copyEdges = false); }; class MNMeshBorder { friend class MNMesh; Tab *> bdr; BitArray btarg; public: ~MNMeshBorder () { Clear(); } DllExport void Clear (); int Num () { return bdr.Count(); } Tab *Loop (int i) { return bdr[i]; } bool LoopTarg (int i) { return ((i>=0) && (i elem; int count; DllExport MNFaceElement (MNMesh &mesh); int operator[](int i) {return elem[i];} }; class MNFaceClusters { public: // Cluster #, one for each face - non-selected faces have -1 for their id. Tab clust; int count; // Makes clusters from distinct selected components. DllExport MNFaceClusters (MNMesh & mesh, DWORD clusterFlags); // This version separates cluster also using a minimum angle and optionally by flags. DllExport MNFaceClusters (MNMesh & mesh, float angle, DWORD clusterFlags); int operator[](int i) { return (i & vclust); DllExport void GetNormalsCenters (MNMesh &mesh, Tab & norm, Tab & ctr); DllExport void GetBorder (MNMesh &mesh, int clustID, Tab & cbord); DllExport void GetOutlineVectors (MNMesh & m, Tab & cnorms, Tab & odir); }; class MNEdgeClusters { public: Tab clust; int count; DllExport MNEdgeClusters (MNMesh &mesh, DWORD clusterFlags); int operator[](int i) {return clust[i];} DllExport void MakeVertCluster (MNMesh &mesh, Tab & vclust); DllExport void GetNormalsCenters (MNMesh &mesh, Tab & norm, Tab & ctr); }; class MNChamferData { Tab hmdir[NUM_HIDDENMAPS]; public: Tab vdir; Tab vmax; Tab *mdir; MNChamferData () { mdir=NULL; } MNChamferData (const MNMesh & m) { mdir=NULL; InitToMesh(m); } DllExport ~MNChamferData (); DllExport void InitToMesh (const MNMesh & m); DllExport void setNumVerts (int nv, bool keep=TRUE, int resizer=0); DllExport void ClearLimits (); DllExport void GetDelta (float amount, Tab & delta); DllExport bool GetMapDelta (MNMesh & mm, int mapChannel, float amount, Tab & delta); Tab & MDir (int mapChannel) { return (mapChannel<0) ? hmdir[-1-mapChannel] : mdir[mapChannel]; } }; // The following function has been added // in 3ds max 4.2. If your plugin utilizes this new // mechanism, be sure that your clients are aware that they // must run your plugin with 3ds max version 4.2 or higher. DllExport void MNChamferDataDebugPrint (MNChamferData & mcd, int mapNum); // End of 3ds max 4.2 Extension class MNTempData : public BaseInterfaceServer { private: MNEdgeClusters *edgeCluster; MNFaceClusters *faceCluster; Tab *vertCluster; Tab *normals; Tab *centers; Tab *vnormals; Tab *> *clustDist; Tab *selDist; Tab *vsWeight; MNChamferData *chamData; Tab *outlineDir; MNMesh *mesh; public: DllExport MNTempData (); DllExport MNTempData (MNMesh *m); DllExport ~MNTempData (); void SetMesh (MNMesh *m) { mesh = m; } DllExport MNFaceClusters *FaceClusters (DWORD clusterFlags=MN_SEL); DllExport MNEdgeClusters *EdgeClusters (DWORD clusterFlags=MN_SEL); DllExport Tab *VertexClusters (int sl, DWORD clusterFlags=MN_SEL); DllExport Tab *ClusterNormals (int sl, DWORD clusterFlags=MN_SEL); DllExport Tab *ClusterCenters (int sl, DWORD clusterFlags=MN_SEL); DllExport Matrix3 ClusterTM (int clust); DllExport Tab *VertexNormals (); DllExport Tab *VSWeight (BOOL useEdgeDist, int edgeIts, BOOL ignoreBack, float falloff, float pinch, float bubble, DWORD selFlags=MN_SEL); DllExport Tab *SelectionDist (BOOL useEdgeDist, int edgeIts, DWORD selFlags=MN_SEL); DllExport Tab *ClusterDist (int sl, DWORD clusterFlags, int clustId, BOOL useEdgeDist, int edgeIts); //DllExport Tab *FaceExtDir (int extrusionType); DllExport Tab *OutlineDir (int extrusionType, DWORD clusterFlags=MN_SEL); DllExport MNChamferData *ChamferData(); DllExport void Invalidate (DWORD part); DllExport void InvalidateDistances (); DllExport void InvalidateSoftSelection (); DllExport void freeClusterDist (); DllExport void freeBevelInfo (); DllExport void freeChamferData(); DllExport void freeAll (); }; DllExport void SelectionDistance (MNMesh & mesh, float *selDist, DWORD selFlags); DllExport void SelectionDistance (MNMesh & mesh, float *selDist, int iters, DWORD selFlags); DllExport void ClustDistances (MNMesh & mesh, int numClusts, int *vclust, Tab **clustDist); DllExport void ClustDistances (MNMesh & mesh, int numClusts, int *vclust, Tab **clustDist, int iters); // Made into a class to match design rules. class BasisFinder { public: DllExport static void BasisFromZDir (Point3 & zDir, Point3 & xDir, Point3 & yDir); }; const int kMNNurmsHourglassLimit = 2500; // between 4 and 5 iterations on a box. //#define MNM_SELCONV_IGNORE_BACK 0x01 // Doesn't work - can't get good BACKFACING info. #define MNM_SELCONV_REQUIRE_ALL 0x02 class MNMeshSelectionConverter : public FlagUser { public: DllExport void FaceToElement (MNMesh & mesh, BitArray & faceSel, BitArray & elementSel); DllExport void EdgeToBorder (MNMesh & mesh, BitArray & edgeSel, BitArray & borderSel); DllExport void VertexToEdge (MNMesh & mesh, BitArray & vertexSel, BitArray & edgeSel); DllExport void VertexToFace (MNMesh & mesh, BitArray & vertexSel, BitArray & faceSel); }; /// /// This class is new with Max 7.0. /// It contains new methods we'd like to put in MNMesh, but can't, /// because we don't want to break the 6.0 SDK. /// class MNMeshUtilities { private: MNMesh *mpMesh; // Private methods used by public ones: // Bridge stuff: void GetBorderVertices (Tab & border, Tab & verts, bool reversedLoop=false); void GetBorderMapVertices (Tab & border, Tab & mapVerts, int mapChannel, bool reversedLoop=false); void InterpolateVertices (int v1, int v2, float f, int outputVert); void GetBridgeSmoothingGroups (Tab & smVerts, Tab & lgVerts, Tab & match, float smoothThresh, Tab & smoothers); MtlID GetBridgeMaterial (Tab & smaller, Tab & larger); bool PolygonToBorder (int face, int start, Tab & border); bool OrientBorders (Tab & border1, Tab & border2); bool SynchBorders (Tab & border1, Tab & border2); bool BridgeLoops (Tab & smaller, Tab & larger, float smoothThresh); bool BridgeLoops (Tab & smaller, Tab & larger, float smoothThresh, int segments, float taper, float bias); void MatchLoops (Tab *> & loopList, Tab & loopMatch, Tab *loopClusterID=NULL, Tab *clusterMatch=NULL); public: /// /// Constructor. Takes MNMesh pointer, which is the mesh that is operated upon /// in all MNMeshUtilities methods. /// MNMeshUtilities (MNMesh *mesh) { mpMesh = mesh; } DllExport bool GetBorderFromEdge (int edge, Tab & border); DllExport bool AutoSmooth (float threshold, DWORD faceFlag); DllExport bool FlipHingeAngle (Point3 & origin, Point3 & axis, int hingeEdge, DWORD faceFlag); DllExport bool HingeFromEdge (Point3 & origin, Point3 & axis, float angle, int segments, MNFaceClusters & fclust, int clusterID); /// /// Determines an average plane of the flagged subobjects, and moves vertices toward it /// according to their soft selection value. /// DllExport bool MakeFlaggedPlanar (int selLev, DWORD flag, float *softSel, Point3 *delta=NULL); /// /// Moves soft-selected vertices toward the plane given according to their soft selection value, /// or produces an array of offsets which would do so. (Similar to MNMesh::MoveVertsToPlane, /// but with soft selection support.) /// DllExport bool MoveVertsToPlane (Point3 & norm, float offset, float *softSel, Point3 *delta=NULL); /// /// Edge-based collapse function - all edges with the given flag will be collapsed, /// which means their vertex endpoints will be joined into a single vertex. /// DllExport bool CollapseEdges (DWORD edgeFlag); /// /// Constrains the vectors given for each vertex so that they are limited to travel /// along a neighboring edge. It's acceptable for deltaIn to be equal to deltaOut. /// DllExport void ConstrainDeltaToEdges (Tab *deltaIn, Tab *deltaOut); /// /// Constrains the vectors given for each vertex so that they are limited to travel /// along a neighboring face. It's acceptable for deltaIn to be equal to deltaOut. /// DllExport void ConstrainDeltaToFaces (Tab *deltaIn, Tab *deltaOut); /// /// Extrude method which creates new faces along open edges. /// /// The edges which should be extruded. /// (Non-open edges that have this flag set always have it cleared.) /// If true, the "edgeFlag" is cleared on the edges /// used as the base of the extrusion. /// If true, the new edges at the "top" of the extrusion have /// their "track" data member set to the edge at the base of their extrusion. DllExport bool ExtrudeOpenEdges (DWORD edgeFlag, bool clearFlagOnOldEdges, bool useTracking); DllExport bool BridgeBorders (int edge1, int twist1, int edge2, int twist2, float smoothThresh, int segments, float taper, float bias); DllExport bool BridgePolygons (int face1, int twist1, int face2, int twist2, float smoothThresh, int segments, float taper, float bias); DllExport bool BridgePolygonClusters (DWORD polyFlag, float smoothThresh, int segments, float taper, float bias, int twist1, int twist2); DllExport bool BridgeSelectedBorders (DWORD edgeFlag, float smoothThresh, int segments, float taper, float bias, int twist1, int twist2); DllExport int FindDefaultBridgeTwist (int face1, int face2); //DllExport bool TurnEdge (int edge); DllExport bool TurnDiagonal (int face, int diagonal); DllExport bool Relax (DWORD vertexFlag, float *softSel, float relaxAmount, int relaxIters, bool holdBoundaryPts, bool holdOuterPts, Point3 *delta=NULL); DllExport int SelectPolygonsByAngle (int startPolygon, float angle, BitArray & polySel); DllExport void CutPrepare (); DllExport void CutCleanup (); }; class MNMapPreserveData { private: Tab mFcx, mFcy; // face corner x and y directions. Tab mMapXDir, mMapYDir; int mDegreeSum; bool mProtectVertexColors; public: MNMapPreserveData () : mDegreeSum(0), mProtectVertexColors(true) { } ~MNMapPreserveData () { Clear(); } DllExport void Clear (); DllExport void Initialize (MNMesh & mm, const MapBitArray & mapsToDo); DllExport void Apply (MNMesh & mm, Point3 *pDelta, int numDeltas); }; #endif