Dev:Source/Modeling/HeMesh/MeshAPI
Update: Circulators and Iterators
I've written a basic proposed API for iterators and circulators to be used in hemesh. Bascially, circulators seem to be iterators that allow access to the item you started iterating with--not necassarily the first item in a "list," as the list can be circular (e.g. half-edges).
Basically I'd like most of hemesh to use these iterator/circulator functions, including circulating the edges around a vert, circulating any extra solids around a vert (I believe the proper term is inner boundary vertex holes, if I'm not mistaken, though I may be), iterating through all edge-info structs (or half-edge pairs if we decide to kill the HE_EdgeInfo struct), etc.
typedef struct HE_Circulator {
void *beginElem;
void *data;
/*->next returns the next element, plus increments the
circulator to the next element too, same for ->prev*/
void *(*next)(struct HE_Circulator *self);
void *(*prev)(struct HE_Circulator *self);
void (*dealloc)(struct HE_Circulator *self);
} HE_Circulator;
typedef struct HE_Iterator {
void *start;
void *data;
void *(*next)(struct HE_Iterator *self);
void *(*prev)(struct HE_Iterator *self);
void (*dealloc)(struct HE_Iterator *self);
} HE_Iterator;
Proposed API for modifying the internal HE mesh
This is my new proposed API for handling mesh operations, HE_Operations. It has it's own module prefix, HEOP, for HE Operations.
Here is the code:
/****************HALF-Edge Mesh Modifyer API***********
* *
* *
* --Rules of using hemesh operations API: *
* NEVER CHANGE A THING about the data except for *
* flags and vertex coordinates. ESPECIALLY the *
* pointers! *
* *
* Theres no point in creating a wrapper structure if *
* it can be at all avoided. BUT this means no *
* modifying the mesh outside these functions! That's *
* why TryMerge is in this API, just in case I'm *
* forced to use the hackish method of merging *
* *shudder*. *
******************************************************/
/****************************************************
* Query Operations *
****************************************************/
/*the all-important euler validation function,
throws HE_NON_MANIFOLD if the mesh doesn't pass.*/
void HE_CheckEuler(HE_EditMesh *em)
/*returns the first edge info in the mesh*/
HE_EditEdgeInfo *HEOP_getFirstEditEdgeInfo(HE_EditMesh *em)
/*returns the first face in the mesh*/
HE_EditFace *HEOP_getFirstFace(HE_EditMesh *em)
/*Note: all these vert-query functions return NULL-stopped arrays.*/
/*returns a null-stopped list of the solids around a vert, using nice circular-vert
system. the list is populated with half-edges, one for each incident disc.*/
HE_EditEdge **HEOP_getSolidsAroundVerts(HE_EditMesh *em, HE_EditVert *eve)
{
}
/*returns a null-stopped list of the edges around a vert*/
HE_EditEdge **HEOP_getHalfEdgesAroundVert(HE_EditMesh *em, HE_EditVert *eve);
/*returns a null-stopped list of the faces around a vert*/
HE_EditFace **HEOP_getFacesAroundVert(HE_EditMesh *em, HE_EditVert *eve);
/*returns a null-stopped list of the vertices around a vert*/
HE_EditVert **HEOP_getVertsAroundVerts(HE_EditMesh *em, HE_EditVert *eve);
/*sets the variables pointer by the pointers to various mesh info, such as
number of vert, number of edges (not counting half-edge duplicates), number
of faces and the number of materials associated with the mesh.*/
void HEOP_getMeshInfo(HE_EditMesh *em, int *totface, int *totinfoedge, int *totvert,
int *totmat);
/****************************************************
* Additive Operations *
****************************************************/
/*creates a vert inside of a face, triangulating? that face.
retains the origional face as one of the new quads?.*/
HE_EditVert *HEOP_makeVertInFace(HE_EditMesh *em, HE_EditFace *efa, float co[3]);
HE_EditVert *HEOP_makeVertInEdge(HE_EditMesh *em, HE_EditFace *efa, float co[3]);
/*Slices a face between two edges. Raises HE_INVALID_ARGUMENT if the edges
are not on the same face.*/
HE_EditFace *HEOP_splitFaceBetweenTwoEdges(HE_EditMesh *em, HE_EditFace *efa,
HE_EditEdge *e1, HE_EditEdge *e2)
/*Splits a series of connected edges off of a face, and forms a new one.
returns the newly formed face. Raises HE_INVALID_ARGUMENT if the edges
are not adjacent and on the same face.*/
HE_EditFace *HEOP_splitEdgesOffFace(HE_EditMesh *em, HE_EditFace *efa, HE_EditEdge
**elist);
/****************************************************
* Subtractive Operations *
****************************************************/
/*Returns the newly formed face, which will likely simply be f1.*/
HE_EditFace *HEOP_joinAdjacentFaces(HE_EditMesh *em, HE_EditFace *f1, HE_EditMest *f2);
/*This returns the new face created when the vert was removed*/
HE_EditFace *HEOP_deleteVert(HE_EditMesh *em, HE_EditFace *f1);
/*This returns the new vert formed by the collapsed edge, which is really just edge->v1*/
HE_EditVert *HEOP_collapseEdge(HE_EditMesh *em, HE_EditEdge *e1);
/*Collapse a face*/
HE_EditVert *HEOP_collapseFace(HE_EditMesh *em, HE_EditEdge *e1);
/*this attempts to merge geomerty with the flag "flag" set in the flag variable at
index "flagvar", and raises a NON_MANIFOLD_ERROR if unsuccessful.
it works on a copy of HE_EditMesh, so it won't corrupt anything.
This operation is to faciliate a generic merge tool, and will likely
be written to break down into euler ops (should be possible, although
the more hackish way of brute-force merging the verts and then re-creating
the editmesh may be faster (but that's a bad way of doing it).
*/
void HEOP_tryToMerge(HE_EditMesh *em, int flagvar, int flag);
/****************************************************
* A Very Simple Error API *
****************************************************/
/*
*This (really simple) error system is how hemesh passes *fatal* messages around.
*So, if an operation borks and messess up the euler, HEOP_CheckEuler will
*set an error. In HEOP_tryToMerge, if it fails merging it will set an error
*(which your supposed to catch). In the case of HEOP_tryToMerge, it restores
*a damaged mesh, but in most cases after an error you have to clear the error
*stack and restore the mesh to a previous state.
*
*this is why I've left a more intact generic way of calling user tools in place;
*it's transparent even to blender (much less a user), and it will allow catching
*these errors.
*/
int HEOP_CheckError(HE_EditMesh *em)
static char *he_error_string(HE_EditMesh *em)
char *HEOP_ErrorCodeToString(int code, HE_EditMesh *em)
int HEOP_CatchError(HE_EditMesh *em, int errorcode)
void HEOP_PrintErrorStack(HE_EditMesh *em)
void HEOP_RaiseError(HE_EditMesh *em, char *from_name, int errorcode)
/*str is NOT mem_freeN'd!*/
void HEOP_RaiseErrorString(HE_EditMesh *em, char *str);