提供: wiki
移動先: 案内検索

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 

 *             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);