/********************************************************************** *< FILE: patch.h DESCRIPTION: Main include file for bezier patches CREATED BY: Tom Hudson HISTORY: Created June 21, 1995 June 17, 1997 TH -- Added second texture mapping channel 12-10-98 Peter Watje added hide interior edge support and hidding patches 12-31-98 Peter Watje added hook patches, patch extrusion and bevels *> Copyright (c) 1995, All Rights Reserved. **********************************************************************/ #ifndef _PATCH_H_ #define _PATCH_H_ #include "coreexp.h" #include "meshlib.h" #include #include "maxtess.h" // Uncomment the following to check for missed triangular patch 'aux' computation //#define CHECK_TRI_PATCH_AUX // Handy-dandy integer table class typedef Tab IntTab; // Value for undefined patches and vertices #define PATCH_UNDEFINED -1 // TH 5/17/99 -- Commented out MULTI_PROCESSING, it wasn't being used and was causing // am obscure memory leak (Defect 180889) //#define MULTI_PROCESSING TRUE // TRUE turns on mp vertex transformation class HookPoint { public: int upperPoint, lowerPoint; int upperVec,lowerVec; int upperHookVec, lowerHookVec; int hookPoint; int upperPatch, lowerPatch, hookPatch; int hookEdge, upperEdge, lowerEdge; }; class ExtrudeData { public: int u,l,uvec,lvec; //3-10-99 watje Point3 edge; Point3 bevelDir; }; class ISave; class ILoad; class PatchMesh; #define NEWPATCH // PRVertex flags: contain clip flags, number of normals at the vertex // and the number of normals that have already been rendered. // fine PLANE_MASK 0x00003f00UL -- now in gfx.h #define NORCT_MASK 0x000000ffUL #define SPECIFIED_NORMAL 0x00004000UL #define OUT_LEFT 0x00010000UL #define OUT_RIGHT 0x00020000UL #define OUT_TOP 0x00040000UL #define OUT_BOTTOM 0x00080000UL #define RECT_MASK 0x000f0000UL #define RND_MASK 0xfff00000UL #define RND_NOR0 0x00100000UL #define RND_NOR(n) (RND_NOR0 << (n)) class PRVertex { public: PRVertex() { rFlags = 0; /*ern = NULL;*/ } CoreExport ~PRVertex(); DWORD rFlags; int pos[3]; }; // Patch vector flags #define PVEC_INTERIOR (1<<0) // Patch vectors class PatchVec { public: Point3 p; // Location int vert; // Vertex which owns this vector int patches[2]; // Patches using this vector DWORD flags; int aux1; // Used to track topo changes during editing (Edit Patch) int aux2; // Used to track topo changes during editing (PatchMesh) CoreExport PatchVec(); CoreExport PatchVec(PatchVec &from); void ResetData() { vert = patches[0] = patches[1] = PATCH_UNDEFINED; } CoreExport BOOL AddPatch(int index); CoreExport PatchVec& operator=(PatchVec& from); void Transform(Matrix3 &tm) { p = p * tm; } CoreExport IOResult Save(ISave* isave); CoreExport IOResult Load(ILoad* iload); }; // Patch vertex flags #define PVERT_COPLANAR (1<<0) #define PVERT_CORNER (0) #define PVERT_TYPE_MASK 0xfffffffe //watje 12-10-98 #define PVERT_HIDDEN (1<<1) // Patch vertex class PatchVert { public: Point3 p; // Location IntTab vectors; // List of vectors attached to this vertex IntTab patches; // List of patches using this vertex DWORD flags; int aux1; // Used to track topo changes during editing (Edit Patch) int aux2; // Used to track topo changes during editing (PatchMesh) CoreExport PatchVert(); CoreExport PatchVert(PatchVert &from); ~PatchVert() { ResetData(); } CoreExport PatchVert& operator=(PatchVert& from); void ResetData() { vectors.Delete(0,vectors.Count()); patches.Delete(0,patches.Count()); } CoreExport int FindVector(int index); CoreExport void AddVector(int index); CoreExport void DeleteVector(int index); CoreExport int FindPatch(int index); CoreExport void AddPatch(int index); CoreExport void DeletePatch(int index); void Transform(Matrix3 &tm) { p = p * tm; } //watje 12-10-98 CoreExport void SetHidden(BOOL sw = TRUE) { if(sw) flags |= PVERT_HIDDEN; else flags &= ~PVERT_HIDDEN; } //watje 12-10-98 BOOL IsHidden() { return (flags & PVERT_HIDDEN) ? TRUE : FALSE; } CoreExport IOResult Save(ISave* isave); CoreExport IOResult Load(ILoad* iload); }; class PatchEdge { public: int v1; // Index of first vertex int vec12; // Vector from v1 to v2 int vec21; // Vector from v2 to v1 int v2; // Index of second vertex int patch1; // Index of first patch int patch2; // Index of second patch int aux1; // Used to track topo changes during editing (Edit Patch) int aux2; // Used to track topo changes during editing (PatchMesh) CoreExport PatchEdge(); CoreExport PatchEdge(PatchEdge &from); CoreExport PatchEdge(int v1, int vec12, int vec21, int v2, int p1, int p2, int aux1=-1, int aux2=-1); // Dump the patch edge structure via DebugPrints CoreExport void Dump(); }; // Patch types #define PATCH_UNDEF 0 // Undefined (watch out!) #define PATCH_TRI 3 // Triangular patch #define PATCH_QUAD 4 // Quadrilateral patch // Patch Flags: #define PATCH_AUTO (1<<0) // Interior verts computed automatically if set #define PATCH_MANUAL (0) // Interior verts stored in 'interior' array #define PATCH_INTERIOR_MASK 0xfffffffe //watje 12-10-98 #define PATCH_HIDDEN (1<<1) //patch is hidden // The mat ID is stored in the HIWORD of the patch flags #define PATCH_MATID_SHIFT 16 #define PATCH_MATID_MASK 0xFFFF class Patch { public: int type; // See types, above int v[4]; // Can have three or four vertices int vec[8]; // Can have six or eight vector points int interior[4]; // Can have one or four interior vertices Point3 aux[9]; // Used for triangular patches only -- Degree 4 control points int adjacent[4]; // Adjacent patches -- Can have three or four int edge[4]; // Pointers into edge list -- Can have three or four DWORD smGroup; // Defaults to 1 -- All patches smoothed in a PatchMesh DWORD flags; // See flags, above int aux1; // Used to track topo changes during editing (Edit Patch) int aux2; // Used to track topo changes during editing (PatchMesh) #ifdef CHECK_TRI_PATCH_AUX Point3 auxSource[9]; CoreExport void CheckTriAux(PatchMesh *pMesh); #endif //CHECK_TRI_PATCH_AUX CoreExport Patch(); // WARNING: This does not allocate arrays -- Use SetType(type) or Patch(type) CoreExport Patch(int type); CoreExport Patch(Patch& fromPatch); CoreExport ~Patch(); CoreExport void Init(); void setVerts(int *vrt) { memcpy(v, vrt, type * sizeof(int)); } void setVerts(int a, int b, int c) { assert(type == PATCH_TRI); v[0]=a; v[1]=b; v[2]=c; } void setVerts(int a, int b, int c, int d) { assert(type == PATCH_QUAD); v[0]=a; v[1]=b; v[2]=c; v[3]=d; } void setVecs(int ab, int ba, int bc, int cb, int ca, int ac) { assert(type == PATCH_TRI); vec[0]=ab; vec[1]=ba; vec[2]=bc; vec[3]=cb; vec[4]=ca; vec[5]=ac; } void setVecs(int ab, int ba, int bc, int cb, int cd, int dc, int da, int ad) { assert(type == PATCH_QUAD); vec[0]=ab; vec[1]=ba; vec[2]=bc; vec[3]=cb; vec[4]=cd; vec[5]=dc; vec[6]=da, vec[7]=ad; } void setInteriors(int a, int b, int c) { assert(type == PATCH_TRI); interior[0]=a; interior[1]=b; interior[2]=c; } void setInteriors(int a, int b, int c, int d) { assert(type == PATCH_QUAD); interior[0]=a; interior[1]=b; interior[2]=c; interior[3]=d; } int getVert(int index) { return v[index]; } int * getAllVerts(void) { return v; } MtlID getMatID() {return (int)((flags>>FACE_MATID_SHIFT)&FACE_MATID_MASK);} void setMatID(MtlID id) {flags &= 0xFFFF; flags |= (DWORD)(id<screen transform; else will attempt to use cache #define COMP_IGN_RECT 0x0002 // forces all polys to be rendered; else only those intersecting the box will be #define COMP_LIGHTING 0x0004 // forces re-lighting of all verts (as when a light moves); else only relight moved verts #define COMP_ALL 0x00ff // If this bit is set then the node being displayed by this mesh is selected. // Certain display flags only activate when this bit is set. #define COMP_OBJSELECTED (1<<8) #define COMP_OBJFROZEN (1<<9) typedef int (*INTRFUNC)(); CoreExport void setPatchIntrFunc(INTRFUNC fn); // Special types for patch vertex hits -- Allows us to distinguish what they hit on a pick #define PATCH_HIT_PATCH 0 #define PATCH_HIT_EDGE 1 #define PATCH_HIT_VERTEX 2 #define PATCH_HIT_VECTOR 3 #define PATCH_HIT_INTERIOR 4 class PatchSubHitRec { private: PatchSubHitRec *next; public: DWORD dist; PatchMesh *patch; int index; int type; PatchSubHitRec( DWORD dist, PatchMesh *patch, int index, int type, PatchSubHitRec *next ) { this->dist = dist; this->patch = patch; this->index = index; this->type = type; this->next = next; } PatchSubHitRec *Next() { return next; } }; class SubPatchHitList { private: PatchSubHitRec *first; public: SubPatchHitList() { first = NULL; } ~SubPatchHitList() { PatchSubHitRec *ptr = first, *fptr; while ( ptr ) { fptr = ptr; ptr = ptr->Next(); delete fptr; } first = NULL; } PatchSubHitRec *First() { return first; } void AddHit( DWORD dist, PatchMesh *patch, int index, int type ) { first = new PatchSubHitRec(dist,patch,index,type,first); } }; // Special storage class for hit records so we can know which object was hit class PatchHitData : public HitData { public: PatchMesh *patch; int index; int type; PatchHitData(PatchMesh *patch, int index, int type) { this->patch = patch; this->index = index; this->type = type; } ~PatchHitData() {} }; // Flags for sub object hit test // NOTE: these are the same bits used for object level. #define SUBHIT_PATCH_SELONLY (1<<0) #define SUBHIT_PATCH_UNSELONLY (1<<2) #define SUBHIT_PATCH_ABORTONHIT (1<<3) #define SUBHIT_PATCH_SELSOLID (1<<4) #define SUBHIT_PATCH_VERTS (1<<24) #define SUBHIT_PATCH_VECS (1<<25) #define SUBHIT_PATCH_PATCHES (1<<26) #define SUBHIT_PATCH_EDGES (1<<27) #define SUBHIT_PATCH_TYPEMASK (SUBHIT_PATCH_VERTS|SUBHIT_PATCH_VECS|SUBHIT_PATCH_EDGES|SUBHIT_PATCH_PATCHES) // Display flags #define DISP_VERTTICKS (1<<0) #define DISP_SELVERTS (1<<10) #define DISP_SELPATCHES (1<<11) #define DISP_SELEDGES (1<<12) #define DISP_SELPOLYS (1<<13) #define DISP_LATTICE (1<<16) #define DISP_VERTS (1<<17) // Selection level bits. #define PATCH_OBJECT (1<<0) #define PATCH_VERTEX (1<<1) #define PATCH_PATCH (1<<2) #define PATCH_EDGE (1<<3) // Types for Subdivision, below: #define SUBDIV_EDGES 0 #define SUBDIV_PATCHES 1 // PatchMesh flags class PatchMesh { friend class Patch; private: #if MULTI_PROCESSING static int refCount; static HANDLE xfmThread; static HANDLE xfmMutex; static HANDLE xfmStartEvent; static HANDLE xfmEndEvent; friend DWORD WINAPI xfmFunc(LPVOID ptr); #endif // derived data-- can be regenerated PRVertex *rVerts; // <<< instance specific. GraphicsWindow *cacheGW; // identifies rVerts cache Box3 bdgBox; // object space--depends on geom+topo // The number of interpolations this patch will use for mesh conversion int meshSteps; //3-18-99 watje to support render steps int meshStepsRender; BOOL showInterior; BOOL adaptive; // GAP tessellation TessApprox viewTess; // tessellation control for the interactive renderer TessApprox prodTess; // tessellation control for the production renderer TessApprox dispTess; // displacment tessellation control for the production renderer BOOL mViewTessNormals; // use normals from the tesselator BOOL mProdTessNormals; // use normals from the tesselator BOOL mViewTessWeld; // Weld the mesh after tessellation BOOL mProdTessWeld; // Weld the mesh after tessellation // Vertex and patch work arrays -- for snap code int snapVCt; int snapPCt; char *snapV; char *snapP; // ------------------------------------- // DWORD flags; // work flags- int renderPatch( GraphicsWindow *gw, int index, BOOL force=FALSE); int renderEdge( GraphicsWindow *gw, int index, BOOL force=FALSE); void checkRVertsAlloc(void); void setCacheGW(GraphicsWindow *gw) { cacheGW = gw; } GraphicsWindow *getCacheGW(void) { return cacheGW; } void freeVerts(); void freeTVerts(int channel=0); void freeVecs(); void freePatches(); void freeTVPatches(int channel=0); void freeEdges(); void freeRVerts(); void freeSnapData(); int buildSnapData(GraphicsWindow *gw,int verts,int edges); public: // Topology int numVerts; int numVecs; int numPatches; int numEdges; Patch * patches; PatchVec * vecs; PatchEdge * edges; Tab hooks; //watje 4-16-99 to handle hooks and changes in topology Tab hookTopoMarkers; Tab hookTopoMarkersA; Tab hookTopoMarkersB; CoreExport int HookFixTopology() ; // Geometry PatchVert * verts; // Texture Coord assignment Tab numTVerts; Tab tVerts; Tab tvPatches; // Material assignment MtlID mtlIndex; // object material // Selection BitArray vertSel; // selected vertices BitArray edgeSel; // selected edges BitArray patchSel; // selected patches // If hit bezier vector, this is its info: int bezVecVert; // Display attribute flags DWORD dispFlags; // Selection level DWORD selLevel; // Mesh cache Mesh mesh; int cacheSteps; // meshSteps used for the cache BOOL cacheAdaptive; // adaptive switch used for cache BOOL meshValid; CoreExport PatchMesh(); CoreExport PatchMesh(PatchMesh& fromPatch); CoreExport void Init(); CoreExport ~PatchMesh(); CoreExport PatchMesh& operator=(PatchMesh& fromPatchMesh); CoreExport PatchMesh& operator=(Mesh& fromMesh); // The following is similar to operator=, but just takes the major components, // not the display flags, selection level, etc. CoreExport void CopyPatchDataFrom(PatchMesh &fromPatchMesh); CoreExport BOOL setNumVerts(int ct, BOOL keep = FALSE); int getNumVerts(void) { return numVerts; } CoreExport BOOL setNumVecs(int ct, BOOL keep = FALSE); int getNumVecs(void) { return numVecs; } CoreExport BOOL setNumPatches(int ct, BOOL keep = FALSE); int getNumPatches(void) { return numPatches; } CoreExport BOOL setNumEdges(int ct, BOOL keep = FALSE); int getNumEdges(void) { return numEdges; } void setVert(int i, const Point3 &xyz) { verts[i].p = xyz; } void setVert(int i, float x, float y, float z) { verts[i].p.x=x; verts[i].p.y=y; verts[i].p.z=z; } void setVec(int i, const Point3 &xyz) { vecs[i].p = xyz; } void setVec(int i, float x, float y, float z) { vecs[i].p.x=x; vecs[i].p.y=y; vecs[i].p.z=z; } PatchVert & getVert(int i) { return verts[i]; } PatchVert * getVertPtr(int i) { return verts+i; } PatchVec & getVec(int i) { return vecs[i]; } PatchVec * getVecPtr(int i) { return vecs+i; } PRVertex & getRVert(int i) { return rVerts[i]; } PRVertex * getRVertPtr(int i) { return rVerts+i; } // Two versions of following methods, to cope with necessary change in map indexing between 2.5 and 3. // Old TV/VC methods are given with "TV" in the name. For these methods, channel 0 is the original map // channel, 1, while any nonzero channel is vertex colors. (No higher channels!) BOOL setNumTVertsChannel(int mp, int ct, BOOL keep=FALSE) { return setNumMapVerts (mp?0:1, ct, keep); } BOOL setNumTVerts(int ct, BOOL keep=FALSE) { return setNumMapVerts (1, ct, keep); } int getNumTVertsChannel(int mp) const { return numTVerts[mp?0:1]; } int getNumTVerts() const { return getNumMapVerts(1); } // New methods have "Map" in the name, and accept normal Object-level map indexing: 0 is VC channel, 1 or more // are map channels. CoreExport BOOL setNumMapVerts (int mp, int ct, BOOL keep = FALSE); int getNumMapVerts (int mp) const { return (mp extrudeDeltas; Tab extrudeData; //creates initial extrude faces and temporary data used in move normal CoreExport void CreateExtrusion(); //computes the average normals of the selected faces CoreExport Point3 AverageNormals(); CoreExport Point3 PatchNormal(int index); CoreExport void MoveNormal(float amount, BOOL useLocalNorms); //creates temporary data used in Bevel BitArray bevelEdges; Tab edgeDistances; CoreExport void CreateBevel(); CoreExport void Bevel(float amount, int smoothStart, int smoothEnd); //computes the bevel direction of patch based on which edges are open Point3 GetBevelDir(int patchVertID); // Attach a second PatchMesh, adjusting materials CoreExport void Attach(PatchMesh *attPatch, int mtlOffset); // Change the interior type of a patch or selected patches (index < 0) CoreExport void ChangePatchInterior(int index, int type); // Change the type of a vertex or selected vertices (index < 0) CoreExport void ChangeVertType(int index, int type); CoreExport BOOL SelVertsSameType(); // Are all selected vertices the same type? CoreExport BOOL SelPatchesSameType(); // Are all selected patches the same type? // Dump the patch mesh structure via DebugPrints CoreExport void Dump(); #ifdef CHECK_TRI_PATCH_AUX CoreExport void CheckTriAux(); #endif //CHECK_TRI_PATCH_AUX // Ready the mesh cache CoreExport void PrepareMesh(); // Get the Mesh version CoreExport Mesh& GetMesh(); CoreExport int IntersectRay(Ray& ray, float& at, Point3& norm); CoreExport IOResult Save(ISave* isave); CoreExport IOResult Load(ILoad* iload); }; #endif // _PATCH_H_