提供: wiki
移動先: 案内検索
This system is create an abstract API to access different mesh structures. It's 
split into three parts: modeling, querying, and drawing.  Each part is in its own 
struct, and all three structs are included in the final AbstractMesh structure.

The mesh backends themselves are required to store all basic data (e.g. vertex 
coordinates, vertex/face normals, flags, etc) as customdata layers.  The 
customdata API will be refactored a little.  It'll be a little more flexible 
where modifiers and tools are concerned, so that tools can, for example, add new 
flags to verts/edges/faces (thus preventing all the hacked code we have for 
edgesplit and bevel).

Per-face-vertex data will be presented to users of AbstractMesh as a new Loop 
element type.  This will be presented as a geometric element type, however 
back-ends may or may not actually use loops in their own behind-the-scenes 

Each vert/edge/face will will be referenced by a backend-specific intptr_t, an 
integer that can store a pointer as well.  These integers can be used to retrieve 
Abstract***Iterator wrappers. These iterator wrappers contain utility pointers to 
various customdata (such as vertex location, vertex normal, etc).  There will also 
be an interface to access the raw customdata layers using these intptr_ts.

Each backend will have a bitmask specifying which of various optional interfaces 
it supports, such as an adjacency querying interface.  YOU SHOULD ALWAYS CHECK

Using this system, it should be possible to write a single function that will 
convert from one back-end to another.  Such conversions should only happen as 
absolutely necassary, such as for tools that require bmesh.

struct AbstractVertIterator;
struct AbstractEdgeIterator;
struct AbstractLoopIterator;
struct AbstractFaceIterator;

typedef struct AbstractDrawer {
	void (*drawFaces)(void *self, int layermask);
	void (*drawEdges)(void *self);

	/*this is for e.g. halo mode material*/
	void (*drawPoints)(void *self);

	/*callback for mesh selection drawing in editmode,
	  should base indices off of ORIGINDEX layer if
	  it exists (e.g. we're not operating on the original
	   mesh data, we're in modifier mode).*/
	void (*drawBackbufferSelect)(void *self);
	/*these are the actual editmesh drawing functions.*/
	void (*drawMappedTranspFaces)(void *self);
	void (*drawMappedFaceDots)(void *self);
	void (*drawMappedEdges)(void *self, int do_interp);
	void (*drawMappedVerts)(void *self);
} AbstractDrawer;

/*AbstractDrawer->drawFaces layermask argument*/
#define ADL_SHADED	1
#define ADL_TEXTURE	2
#define ADL_GLLIGHT	4
#define ADL_VCOL	8
/*for weight paint drawing, I suppose, not sure how this should work*/
#define ADL_WCOL	16

/*Each of these operations work on
  "tagged" elements, tagged via
  the tagging functions, which
  live here and not in the query
typedef struct AbstractModeler {
	/*ensure we have adjacency info.*/
	void (*ensureAdjacencyInfo)(void *self);.

	/*strips adjacency info.  should always return
	  success, even on back-ends without adjacency
	void (*stripAdjacencyInfo)(void *self);
	/* Preparation callback called before performing
	   any modeling operation.  Don't forget to call
	   endModeling afterwords.
	  * ensure_adj: passing a nonzero value to ensure_adj
	    will have beginModeling call ensureAdjacencyInfo.
	void (*beginModeling)(void *self, int ensure_adj);

	/* Callback called when an operation has finished.*/
	void (*endModeling)(void *self, int strip_adj);

	/* Tagging functions to tag verts/edges/faces for various
	void (*resetTagging)(void *self, int doverts, int doedges, int dofaces);

	/*state is the tag value, can be either 0 or 1.  0 clears the
	  tag state, while 1 sets it.*/
	void (*tagVert)(void *self, intptr_t vert, int state);
	void (*tagEdge)(void *self, intptr_t edge, int state);
	void (*tagFace)(void *self, intptr_t face, int state);
	/*this duplicates all tagged elements, preserving
	  the tags on the copied elements but removing them
	  from the source elements.*/
	void (*duplicateTaggedElements)(void *self);
	void (*findDoubles)(void *self, float limit, 
                                intptr_t **source_target_pais, int **totvert);
	void (*weld)(void *self, intptr_t *source_target_pairs, int totvert);
	/*simple (non-winged) edge extrude*/
	void (*extrudeEdges)(void *self);
	void (*extrudeFaceRegions)(void *self);	
	void (*extrudeFaces)(void *self)
	/*each of these returns an intptr_t identifyer to the new element.
	  NOTE: you cannot directly create or destroy loops.*/
	intptr_t (*makeVert)(void *self, intptr_t *returnvert, float *co, float *no, short flags,
                              intptr_t data_to_copy);
	intptr_t (*makeEdge)(void *self, intptr_t *retedge, intptr_t v1, intptr_t v2, 
                              intptr_t data_to_copy);
	intptr_t (*makeFace)(void *self, intptr_t *retface, intptr_t *verts, int len, 
                              intptr_t data_to_copy);
	/*deletes tagged verts/edges/faces*/
	void (*deleteVert)(void *self, intptr_t vert);
	void (*deleteEdge)(void *self, intptr_t edge);
	/*will delete associated per-face data.*/
	void (*deleteFace)(void *self, intptr_t face);
	void (*recalcNormals)(void *self);
} DerivedModeler;

/*all vert/edge/loop/face data is queried via this "iterator" system.
  Each iterator stores all the needed data for an element type.  These iterators
  can be used as generic containers for vert/edge/loop/face data.  Allocation
  of them can be handled by preallocating a limited number of them in a pool,
  sortof similar to a basic program stack.
  Note that many of these "iterators" contain convienence pointers to the active
  layers of custom data, such as UV texture information, vertex locations, etc.
  Such pointers always point to the data in the *active* custom data layer of
  its type.  If you want data from other layers, used the customdata query

typedef struct AbstractIterator {
	/*backend-specific id, can be an index, a pointer,
	  etc.  It is *not* an Element ID.*/
	intptr_t id;

	/*flag set when iteration ends*/
	int at_end;
	/*set when an element is tagged, note that this
	  is essentially read-only, to set the tag state
	  use the tagging functions.*/
	int is_tagged;
	Itervoid error;

	/*release this iterator*/
	void (*release)(void *mesh, void *self);

	/*replaces the data in this iterator with the next element in the
	void (*next)(void *mesh, void *self);
} AbstractIterator ;

/*accesses vert information.  Note that next may simply modify self
  and return it.*/
typedef struct AbstractVertIterator {
	AbstractWrapper main;
	/*note that these are convienence pointers, all this data is
	  stored as customdata.*/
	float *co, *no;
	MDeformVert *dvert;
	/*returns an iterator capable of iterating over the edges
	  around a vert.*/
	AbstractEdgeIterator *(*getEdge)(void *mesh, void *self);
} AbstractVertIterator;

typedef struct AbstractEdgeIterator {
	AbstractWrapper main;
	/*remember, crease is a customdata layer just like
	  everything else.*/
	float *crease;
	/*flags is also a customdata layer.*/
	AbstractFlags *flags;
	/*these could be replaced by indices/element IDs (whichever ones
	  we decide to use).*/
	AbstractVertIterator *(*getV1)(void *mesh, void *self);
	AbstractVertIterator *(*getV2)(void *mesh, void *self);
	/*adjacency stuff, you should always check to make sure the
	  abstractmesh supports this.*/
	AbstractVertIterator *(*nextRadialAroundV1)(void *mesh, void *self);
	AbstractVertIterator *(*nextRadialAroundV2)(void *mesh, void *self);
	AbstractVertIterator *(*firstFaceAroundEdge)(void *mesh, void *self);
} AbstractEdgeIterator;

/*accesses loops.  Note that next may modify self and return it.*/
typedef struct AbstractLoopIterator {
	AbstractWrapper main;
	/*active UV col*/
	float (*uv)[2], (*col)[2];

	/*adjacency stuff, you should always check to make sure the
	  abstractmesh supports this.*/
	AbstractFaceIterator *(*getFace)(void *mesh, void *self);
	AbstractVertIterator *(*getVert)(void *mesh, void *self);
	AbstractEdgeIterator *(*getEdge)(void *mesh, void *self);
} AbstractLoopIterator;

typedef struct AbstractFaceIterator {
	void *data, *next, *customdata;
	/*backend-specific id, can be an index, a pointer,
	  etc.  it is *not* an Element ID.*/
	intptr_t id;
	AbstractVertIterator verts;
	AbstractEdgeIterator edges;
	AbstractLoopIterator loops;
	float *normal;
	int *mat;
} AbstractVertIterator;

typedef struct AbstractQuery {
	int (*hasAdjacencyInfo)(void *self);

	AbstractFaceIterator *(*iterFaces)(void *self);
	AbstractEdgeIterator *(*iterEdges)(void *self);
	AbstractVertIterator *(*iterVerts)(void *self);
	/*backbuffer select will need these.  They shouldn't be used
	  by anything else.  The begin/endSelectPicking functions are so
      the back-end can prepare various optimizations, if needed,
      before having to process a lot of picking index lookups.
      They are optional, and shouldn't be use if simply picking
      a few elements (like during normal rightmouse select). */
	void (*beginSelectPicking)(void *self, int doverts, int doedges, int dofaces);
	AbstractVertIterator *(*getVertAtIndex)(void *self, int index);
	AbstractEdgeIterator *(*getEdgeAtIndex)(void *self, int index);
	AbstractFaceIterator *(*getFaceAtIndex)(void *self, int index);
	void (*endSelectPicking)(void *self);
	/*get vert/edge/loop/face descriptive iterator from a backend-specfic
	  intptr_t value.*/
	AbstractVertIterator *(*getVert)(void *self, intptr_t ref);
	AbstractEdgeIterator *(*getEdge)(void *self, intptr_t ref);
	AbstractLoopIterator *(*getLoop)(void *self, intptr_t ref);
	AbstractFaceIterator *(*getFace)(void *self, intptr_t ref);
} AbstractQuery;

typedef struct AbstractMeshType {
	AbstractDrawer *drawer;
	AbstractModeler *model;
	AbstractQuery *query;
	/*should free all related data.*/
	void (*release)(void *self);
	void *(*newMesh);

	/*-------internal customdata stuff-------*/

	/*adds a new layer of type type.  If name is passed as NULL, then the default name is used.
	  automatically allocates layer to the proper size, by testing which data (vertData, faceData,
	  etc) was passed in.*/
	void (*customdata_add_layer(void *self, CustomData *data, int type, char *name);
	void (*customdata_rem_layer)(CustomData *data, int type, int sublayer, int can_free, int free_all);
	void (*customdata_set_active_layer_index)(CustomData *data, int type, int sublayer, int set_render);
	void (*customdata_set_active_layer)(CustomData *data, int type, CustomDataLayer *sublayer, int set_render);

	void (*customdata_copy_data)(CustomData *source, 
               CustomData *dest, intptr_t src_index, intptr_t dst_index);
	void (*customdata_merge_data)(CustomData *source, 
               CustomData *dest, intptr_t src_index, intptr_t dst_index);
    /*These next two get specific customdata from elements.  The first one will return
      data from the currently active layer, while the second allows choosing which sublayer
      to use.*/
	void *(*customdata_get_active_data)(intptr_t data, int type);	
	void *(*customdata_get_data_at_index)(intptr_t data, int type, int sublayer);
	void (*customdata_interp)(CustomData *data, intptr_t *src_refs, float *weights,
							  int count, intptr_t dest_block);

} AbstractMeshType;

typedef struct AbstractMesh {
	AbstractMeshType *type;
	/*masks of all the custom data layers
	  currently stored in this mesh.*/
	int CD_VertDataMask;
	int CD_EdgeDataMask;
	int CD_LoopDataMask;
	int CD_FaceDataMask;

	int IM_InterfaceMask;
} AbstractMesh;

/*modeling ops flags*/
#define IM_WELD		                    (1<<0)
#define IM_EXTRUDEFACES                 (1<<1)
#define IM_EXTRUDEFACEREGION            (1<<2)
#define IM_EXTRUDEEDGES	          		(1<<3)
#define IM_EXTRUDEVERTS	          		(1<<4)
#define IM_RECALCNORMALS                (1<<5)

/*adjacency info query flags*/
#define IM_EDGES_AROUND_VERT            (1<<6)
#define IM_FACES_AROUND_EDGE            (1<<7)

/*the value denoting a null element*/
#define NULLELEMENT	-1