diff options
Diffstat (limited to 'source/blender/blenkernel')
69 files changed, 12594 insertions, 1976 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 857c88a6004..ea5b9e8367f 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -30,21 +30,49 @@ #ifndef BKE_DERIVEDMESH_H #define BKE_DERIVEDMESH_H -/** \file BKE_DerivedMesh.h - * \ingroup bke - * - * \todo - * - Make drawMapped* functions take a predicate function that - * determines whether to draw the edge (this predicate can - * also set color, etc). This will be slightly more general - * and allow some of the functions to be collapsed. - * - Once accessor functions are added then single element draw - * functions can be implemented using primitive accessors. - * - Add function to dispatch to renderer instead of using - * conversion to DLM. +/* + Basic design of the DerivedMesh system: + + DerivedMesh is a common set of interfaces for mesh systems. + + There are three main mesh data structures in Blender: Mesh, CDDM, and BMesh. + These, and a few others, all implement DerivedMesh interfaces, + which contains unified drawing interfaces, a few utility interfaces, + and a bunch of read-only interfaces intended mostly for conversion from + one format to another. + + All Mesh structures in blender make use of CustomData, which is used to store + per-element attributes and interpolate them (e.g. uvs, vcols, vgroups, etc). + + Mesh is the "serialized" structure, used for storing object-mode mesh data + and also for saving stuff to disk. It's interfaces are also what DerivedMesh + uses to communicate with. + + CDDM is a little mesh library, that uses Mesh data structures in the backend. + It's mostly used for modifiers, and has the advantages of not taking much + resources. + + BMesh is a full-on brep, used for editmode, some modifiers, etc. It's much + more capable (if memory-intensive) then CDDM. + + DerivedMesh is somewhat hackish. Many places assumes that a DerivedMesh is + a CDDM (most of the time by simply copying it and converting it to one). + CDDM is the original structure for modifiers, but has since been superseded + by BMesh, at least for the foreseeable future. +*/ + +/* + * Note: This sturcture is read-only, for all practical purposes. + * At some point in the future, we may want to consider + * creating a replacement structure that implements a proper + * abstract mesh kernel interface. Or, we can leave this + * as it is and stick with using BMesh and CDDM. */ + #include "DNA_customdata_types.h" +#include "DNA_meshdata_types.h" + #include "BKE_customdata.h" #include "BKE_bvhutils.h" @@ -55,20 +83,63 @@ struct MTFace; struct Object; struct Scene; struct Mesh; -struct EditMesh; +struct BMEditMesh; struct KeyBlock; struct ModifierData; struct MCol; struct ColorBand; struct GPUVertexAttribs; struct GPUDrawObject; +struct BMEditMesh; struct ListBase; struct PBVH; /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 #define SUB_ELEMS_EDGE 2 -#define SUB_ELEMS_FACE 4 +#define SUB_ELEMS_FACE 50 + +/* +Note: all mface interfaces now officially operate on tesselated data. + Also, the mface origindex layer indexes mpolys, not mfaces. +*/ + +/*DM Iterators. For now, first implement face iterators. + These are read-only, at least for now.*/ + +typedef struct DMLoopIter { + void (*step)(void *self); + int done; + + int index, vindex, eindex; + MVert v; /*copy of the associated vert's data*/ + + /*note: if layer is -1, then the active layer is retrieved. + loop refers to per-face-vertex data.*/ + void *(*getLoopCDData)(void *self, int type, int layer); + void *(*getVertCDData)(void *self, int type, int layer); +} DMLoopIter; + +typedef struct DMFaceIter { + void (*step)(void *self); + void (*free)(void *self); + int done; + + int index; + int len; + + /*you can set mat_nr and flags, and the backends + must detect and update the internal faces*/ + int mat_nr; + int flags; + + /*note: you may only use one + loop iterator at a time.*/ + DMLoopIter *(*getLoopsIter)(void *self); + + /*if layer is -1, returns active layer*/ + void *(*getCDData)(void *self, int type, int layer); +} DMFaceIter; typedef struct DMGridData { float co[3]; @@ -82,15 +153,15 @@ typedef struct DMGridAdjacency { typedef enum DerivedMeshType { DM_TYPE_CDDM, - DM_TYPE_EDITMESH, + DM_TYPE_EDITBMESH, DM_TYPE_CCGDM } DerivedMeshType; typedef struct DerivedMesh DerivedMesh; struct DerivedMesh { /* Private DerivedMesh data, only for internal DerivedMesh use */ - CustomData vertData, edgeData, faceData; - int numVertData, numEdgeData, numFaceData; + CustomData vertData, edgeData, faceData, loopData, polyData; + int numVertData, numEdgeData, numFaceData, numLoopData, numPolyData; int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ BVHCache bvhCache; @@ -98,22 +169,27 @@ struct DerivedMesh { DerivedMeshType type; /* Misc. Queries */ + + /*face iterator. initializes iter.*/ + DMFaceIter *(*newFaceIter)(DerivedMesh *dm); + + /*recalculates mesh tesselation*/ + void (*recalcTesselation)(DerivedMesh *dm); /* Also called in Editmode */ int (*getNumVerts)(DerivedMesh *dm); - /* Also called in Editmode */ - int (*getNumFaces)(DerivedMesh *dm); - int (*getNumEdges)(DerivedMesh *dm); + int (*getNumTessFaces)(DerivedMesh *dm); + int (*getNumFaces) (DerivedMesh *dm); - /* copy a single vert/edge/face from the derived mesh into + /* copy a single vert/edge/tesselated face from the derived mesh into * *{vert/edge/face}_r. note that the current implementation * of this function can be quite slow, iterating over all * elements (editmesh) */ void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r); void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r); - void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r); + void (*getTessFace)(DerivedMesh *dm, int index, struct MFace *face_r); /* return a pointer to the entire array of verts/edges/face from the * derived mesh. if such an array does not exist yet, it will be created, @@ -122,21 +198,21 @@ struct DerivedMesh { */ struct MVert *(*getVertArray)(DerivedMesh *dm); struct MEdge *(*getEdgeArray)(DerivedMesh *dm); - struct MFace *(*getFaceArray)(DerivedMesh *dm); + struct MFace *(*getTessFaceArray)(DerivedMesh *dm); /* copy all verts/edges/faces from the derived mesh into * *{vert/edge/face}_r (must point to a buffer large enough) */ void (*copyVertArray)(DerivedMesh *dm, struct MVert *vert_r); void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *edge_r); - void (*copyFaceArray)(DerivedMesh *dm, struct MFace *face_r); + void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *face_r); /* return a copy of all verts/edges/faces from the derived mesh * it is the caller's responsibility to free the returned pointer */ struct MVert *(*dupVertArray)(DerivedMesh *dm); struct MEdge *(*dupEdgeArray)(DerivedMesh *dm); - struct MFace *(*dupFaceArray)(DerivedMesh *dm); + struct MFace *(*dupTessFaceArray)(DerivedMesh *dm); /* return a pointer to a single element of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not @@ -144,7 +220,7 @@ struct DerivedMesh { */ void *(*getVertData)(DerivedMesh *dm, int index, int type); void *(*getEdgeData)(DerivedMesh *dm, int index, int type); - void *(*getFaceData)(DerivedMesh *dm, int index, int type); + void *(*getTessFaceData)(DerivedMesh *dm, int index, int type); /* return a pointer to the entire array of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not @@ -152,8 +228,21 @@ struct DerivedMesh { */ void *(*getVertDataArray)(DerivedMesh *dm, int type); void *(*getEdgeDataArray)(DerivedMesh *dm, int type); - void *(*getFaceDataArray)(DerivedMesh *dm, int type); - + void *(*getTessFaceDataArray)(DerivedMesh *dm, int type); + + /*retrieves the base CustomData structures for + verts/edges/tessfaces/loops/facdes*/ + CustomData *(*getVertDataLayout)(DerivedMesh *dm); + CustomData *(*getEdgeDataLayout)(DerivedMesh *dm); + CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm); + CustomData *(*getLoopDataLayout)(DerivedMesh *dm); + CustomData *(*getFaceDataLayout)(DerivedMesh *dm); + + /*copies all customdata for an element source into dst at index dest*/ + void (*copyFromVertCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + void (*copyFromEdgeCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + void (*copyFromFaceCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + /* optional grid access for subsurf */ int (*getNumGrids)(DerivedMesh *dm); int (*getGridSize)(DerivedMesh *dm); @@ -256,8 +345,8 @@ struct DerivedMesh { * o Drawing options too complicated to enumerate, look at code. */ void (*drawFacesTex)(DerivedMesh *dm, - int (*setDrawOptions)(struct MTFace *tface, - struct MCol *mcol, int matnr)); + int (*setDrawOptions)(struct MTFace *tface, + int has_vcol, int matnr)); /* Draw all faces with GLSL materials * o setMaterial is called for every different material nr @@ -339,15 +428,16 @@ void DM_init_funcs(DerivedMesh *dm); * of vertices, edges and faces (doesn't allocate memory for them, just * sets up the custom data layers) */ -void DM_init(DerivedMesh *dm, DerivedMeshType type, - int numVerts, int numEdges, int numFaces); +void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, + int numFaces, int numLoops, int numPolys); /* utility function to initialise a DerivedMesh for the desired number * of vertices, edges and faces, with a layer setup copied from source */ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, - DerivedMeshType type, - int numVerts, int numEdges, int numFaces); + DerivedMeshType type, + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys); /* utility function to release a DerivedMesh's layers * returns 1 if DerivedMesh has to be released by the backend, 0 otherwise @@ -377,6 +467,8 @@ void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); +void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype, + void *layer); void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); @@ -396,6 +488,7 @@ void *DM_get_face_data(struct DerivedMesh *dm, int index, int type); */ void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type); void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type); +void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type); void *DM_get_face_data_layer(struct DerivedMesh *dm, int type); /* custom data setting functions @@ -414,6 +507,10 @@ void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); +void DM_copy_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int source_index, int dest_index, int count); +void DM_copy_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int source_index, int dest_index, int count); void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); @@ -423,8 +520,13 @@ void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, */ void DM_free_vert_data(struct DerivedMesh *dm, int index, int count); void DM_free_edge_data(struct DerivedMesh *dm, int index, int count); +void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count); +void DM_free_loop_data(struct DerivedMesh *dm, int index, int count); void DM_free_face_data(struct DerivedMesh *dm, int index, int count); +/*sets up mpolys for a DM based on face iterators in source*/ +void DM_DupPolys(DerivedMesh *source, DerivedMesh *target); + /* interpolates vertex data from the vertices indexed by src_indices in the * source mesh using the given weights and stores the result in the vertex * indexed by dest_index in the dest mesh @@ -454,12 +556,20 @@ void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest, * vert_weights[i] multiplied by weights[i]. */ typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE]; -void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, +void DM_interp_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest, int *src_indices, float *weights, FaceVertWeight *vert_weights, int count, int dest_index); -void DM_swap_face_data(struct DerivedMesh *dm, int index, const int *corner_indices); +void DM_swap_tessface_data(struct DerivedMesh *dm, int index, const int *corner_indices); + +void DM_interp_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index); + +void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index); /* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */ void vDM_ColorBand_store(struct ColorBand *coba); @@ -480,6 +590,9 @@ DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object DerivedMesh *mesh_create_derived_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask); +DerivedMesh *getEditDerivedBMesh(struct BMEditMesh *em, struct Object *ob, + float (*vertexCos)[3]); + DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index); /* same as above but wont use render settings */ @@ -498,20 +611,20 @@ DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object * DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3], CustomDataMask dataMask); -DerivedMesh *editmesh_get_derived(struct EditMesh *em, float (*vertexCos)[3]); -DerivedMesh *editmesh_get_derived_base(struct Object *, struct EditMesh *em); -DerivedMesh *editmesh_get_derived_cage(struct Scene *scene, struct Object *, - struct EditMesh *em, CustomDataMask dataMask); -DerivedMesh *editmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *, - struct EditMesh *em, DerivedMesh **final_r, +DerivedMesh *editbmesh_get_derived(struct BMEditMesh *em, float (*vertexCos)[3]); +DerivedMesh *editbmesh_get_derived_base(struct Object *, struct BMEditMesh *em); +DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *, + struct BMEditMesh *em, CustomDataMask dataMask); +DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *, + struct BMEditMesh *em, DerivedMesh **final_r, CustomDataMask dataMask); -float (*editmesh_get_vertex_cos(struct EditMesh *em, int *numVerts_r))[3]; -int editmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm); -void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em, CustomDataMask dataMask); +float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *numVerts_r))[3]; +int editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm); +void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, CustomDataMask dataMask); /* returns an array of deform matrices for crazyspace correction, and the number of modifiers left */ -int editmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct EditMesh *em, +int editbmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]); /* returns an array of deform matrices for crazyspace correction when sculpting, diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f6bb4fbb635..44ce6060f1b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -89,6 +89,7 @@ extern int BKE_undo_valid(const char *name); extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(struct bContext *C, int nr); +void BKE_undo_save(char *fname); extern void BKE_undo_save_quit(void); extern struct Main *BKE_undo_get_main(struct Scene **scene); diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h index 5c28fa88503..e347f8fe76e 100644 --- a/source/blender/blenkernel/BKE_bmesh.h +++ b/source/blender/blenkernel/BKE_bmesh.h @@ -56,6 +56,7 @@ struct BME_Edge; struct BME_Poly; struct BME_Loop; +/*NOTE: this is the bmesh 1.0 code. it's completely outdated.*/ /*Notes on further structure Cleanup: -Remove the tflags, they belong in custom data layers diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 1edec2b69d9..c1161e7c65b 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -40,12 +40,17 @@ #include "BKE_DerivedMesh.h" struct DerivedMesh; +struct BMEditMesh; struct EditMesh; struct Mesh; struct Object; /* creates a new CDDerivedMesh */ -struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces); +struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys); + +/*tests if a given DerivedMesh is a CDDM*/ +int CDDM_Check(struct DerivedMesh *dm); /* creates a CDDerivedMesh from the given Mesh, this will reference the original data in Mesh, but it is safe to apply vertex coordinates or @@ -56,6 +61,12 @@ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob); /* creates a CDDerivedMesh from the given EditMesh */ struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh *me); +/* creates a CDDerivedMesh from the given BMEditMesh */ +DerivedMesh *CDDM_from_BMEditMesh(struct BMEditMesh *em, struct Mesh *me); + +/* merge verts */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap); + /* creates a CDDerivedMesh from the given curve object */ struct DerivedMesh *CDDM_from_curve(struct Object *ob); @@ -63,17 +74,26 @@ struct DerivedMesh *CDDM_from_curve(struct Object *ob); /* useful for OrcoDM creation for curves with constructive modifiers */ DerivedMesh *CDDM_from_curve_customDB(struct Object *ob, struct ListBase *dispbase); +struct BMEditMesh *CDDM_To_BMesh(DerivedMesh *dm, struct BMEditMesh *existing); + + /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. */ -struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); +struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm, int faces_from_tessfaces); /* creates a CDDerivedMesh with the same layer stack configuration as the * given DerivedMesh and containing the requested numbers of elements. * elements are initialised to all zeros */ struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source, - int numVerts, int numEdges, int numFaces); + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys); + +/*converts mfaces to mpolys. note things may break if there are not valid + *medges surrounding each mface. + */ +void CDDM_tessfaces_to_faces(struct DerivedMesh *dm); /* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert * layer is a referenced layer, it will be duplicate to not overwrite the @@ -88,9 +108,17 @@ void CDDM_calc_normals(struct DerivedMesh *dm); /* calculates edges for a CDDerivedMesh (from face data) * this completely replaces the current edge data in the DerivedMesh + * builds edges from the tesselated face data. */ void CDDM_calc_edges(struct DerivedMesh *dm); +/* same as CDDM_calc_edges only makes edges from ngon faces instead of tesselation + faces*/ +void CDDM_calc_edges_poly(struct DerivedMesh *dm); + +/*reconstitute face triangulation*/ +void CDDM_recalc_tesselation(struct DerivedMesh *dm); + /* lowers the number of vertices/edges/faces in a CDDerivedMesh * the layer data stays the same size */ @@ -104,7 +132,9 @@ void CDDM_lower_num_faces(struct DerivedMesh *dm, int numFaces); */ struct MVert *CDDM_get_vert(struct DerivedMesh *dm, int index); struct MEdge *CDDM_get_edge(struct DerivedMesh *dm, int index); -struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index); +struct MFace *CDDM_get_tessface(struct DerivedMesh *dm, int index); +struct MLoop *CDDM_get_loop(struct DerivedMesh *dm, int index); +struct MPoly *CDDM_get_face(struct DerivedMesh *dm, int index); /* vertex/edge/face array access functions - return the array holding the * desired data @@ -113,6 +143,18 @@ struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index); */ struct MVert *CDDM_get_verts(struct DerivedMesh *dm); struct MEdge *CDDM_get_edges(struct DerivedMesh *dm); -struct MFace *CDDM_get_faces(struct DerivedMesh *dm); +struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm); +struct MLoop *CDDM_get_loops(struct DerivedMesh *dm); +struct MPoly *CDDM_get_polys(struct DerivedMesh *dm); + +/*Assigns news m*** layers to the cddm. Note that you must handle + freeing the old ones yourself. Also you must ensure dm->num****Data + is correct.*/ +void CDDM_set_mvert(struct DerivedMesh *dm, struct MVert *mvert); +void CDDM_set_medge(struct DerivedMesh *dm, struct MEdge *medge); +void CDDM_set_mface(struct DerivedMesh *dm, struct MFace *mface); +void CDDM_set_mloop(struct DerivedMesh *dm, struct MLoop *mloop); +void CDDM_set_mpoly(struct DerivedMesh *dm, struct MPoly *mpoly); + #endif diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 7254536b555..36c442741ec 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -267,6 +267,24 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); int CTX_data_selected_pose_bones(const bContext *C, ListBase *list); int CTX_data_visible_pose_bones(const bContext *C, ListBase *list); +//stupid compiler flag isn't working +//remember to undef this later +#ifndef EVENT_RECORDER +#define EVENT_RECORDER +#endif + +#ifdef EVENT_RECORDER +#include <stdio.h> + +int CTX_rec_events(bContext *C); +FILE *CTX_rec_file(bContext *C); +int CTX_set_events_path(bContext *C, char *path); +int CTX_play_events(bContext *C, char **playpath); +int CTX_rec_events_set(bContext *C, int state); +double CTX_rec_lasttime(bContext *C, double newtime); + +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index c30100ea55a..319519cf363 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -40,11 +40,15 @@ extern "C" { #endif +struct BMesh; struct ID; struct CustomData; struct CustomDataLayer; typedef unsigned int CustomDataMask; +/*a data type large enough to hold 1 element from any customdata layer type*/ +typedef struct {unsigned char data[64];} CDBlockBytes; + extern const CustomDataMask CD_MASK_BAREMESH; extern const CustomDataMask CD_MASK_MESH; extern const CustomDataMask CD_MASK_EDITMESH; @@ -67,6 +71,25 @@ extern const CustomDataMask CD_MASK_FACECORNERS; #define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source has same number of elements */ +/* Checks if the layer at physical offset layern (in data->layers) support math + * the below operations. + */ +int CustomData_layer_has_math(struct CustomData *data, int layern); + +/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to + another, while not overwriting anything else (e.g. flags). probably only + implemented for mloopuv/mloopcol, for now.*/ +void CustomData_data_copy_value(int type, void *source, void *dest); + +/* compares if data1 is equal to data2. type is a valid CustomData type + * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare + * the data, if it exists, otherwise memcmp is used.*/ +int CustomData_data_equals(int type, void *data1, void *data2); +void CustomData_data_initminmax(int type, void *min, void *max); +void CustomData_data_dominmax(int type, void *data, void *min, void *max); +void CustomData_data_multiply(int type, void *data, float fac); +void CustomData_data_add(int type, void *data1, void *data2); + /* initialises a CustomData object with the same layer setup as source. * mask is a bitfield where (mask & (1 << (layer type))) indicates * if a layer should be copied or not. alloctype must be one of the above. */ @@ -78,6 +101,12 @@ void CustomData_copy(const struct CustomData *source, struct CustomData *dest, void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem); +/*bmesh version of CustomData_merge; merges the layouts of source and dest, + then goes through the mesh and makes sure all the customdata blocks are + consistent with the new layout.*/ +void CustomData_bmesh_merge(struct CustomData *source, struct CustomData *dest, + int mask, int alloctype, struct BMesh *bm, int type); + /* frees data associated with a CustomData object (doesn't free the object * itself, though) */ @@ -142,12 +171,13 @@ void CustomData_set_only_copy(const struct CustomData *data, void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count); +void CustomData_copy_elements(int type, void *source, void *dest, int count); void CustomData_em_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block); void CustomData_bmesh_copy_data(const struct CustomData *source, - struct CustomData *dest,void *src_block, - void **dest_block); + struct CustomData *dest, void *src_block, + void **dest_block); void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); /* frees data in a CustomData object @@ -189,11 +219,16 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic * returns NULL if there is no layer of type */ void *CustomData_get(const struct CustomData *data, int index, int type); +void *CustomData_get_n(const struct CustomData *data, int type, int index, int n); void *CustomData_em_get(const struct CustomData *data, void *block, int type); void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n); void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type); void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n); +/* gets the layer at physical index n, with no type checking. + */ +void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n); + /* gets a pointer to the active or first layer of type * returns NULL if there is no layer of type */ @@ -201,8 +236,8 @@ void *CustomData_get_layer(const struct CustomData *data, int type); void *CustomData_get_layer_n(const struct CustomData *data, int type, int n); void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name); - int CustomData_get_layer_index(const struct CustomData *data, int type); +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n); int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); @@ -229,6 +264,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type, void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, void *source); +/*sets the data of the block at physical layer n. no real type checking + *is performed. + */ +void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n, + void *source); /* set the pointer of to the first layer of type. the old data is not freed. * returns the value of ptr if the layer is found, NULL otherwise @@ -285,7 +325,8 @@ void CustomData_set_layer_unique_name(struct CustomData *data, int index); int CustomData_verify_versions(struct CustomData *data, int index); /*BMesh specific customdata stuff*/ -void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, + struct CustomData *ldata, int totloop, int totpoly); void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h index 1b2b3d2ee95..1b2b3d2ee95 100644..100755 --- a/source/blender/blenkernel/BKE_idcode.h +++ b/source/blender/blenkernel/BKE_idcode.h diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index c29320ef13c..aeaf17bec27 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -50,8 +50,10 @@ extern "C" { #endif void free_key(struct Key *sc); +void free_key_nolib(struct Key *key); struct Key *add_key(struct ID *id); struct Key *copy_key(struct Key *key); +struct Key *copy_key_nolib(struct Key *key); void make_local_key(struct Key *key); void sort_keys(struct Key *key); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 0f5780ed5b0..7dc1172d32e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -40,12 +40,15 @@ struct BoundBox; struct DispList; struct ListBase; -struct EditMesh; -struct MDeformVert; +struct BMEditMesh; +struct BMesh; struct Mesh; +struct MPoly; +struct MLoop; struct MFace; struct MEdge; struct MVert; +struct MDeformVert; struct MCol; struct Object; struct MTFace; @@ -60,12 +63,39 @@ extern "C" { struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me); void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em); +struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob); + +/* + this function recreates a tesselation. + returns number of tesselation faces. + + use_poly_origindex sets whether or not the tesselation faces' origindex + layer should point to original poly indices or real poly indices. + + use_face_origindex sets the tesselation faces' origindex layer + to point to the tesselation faces themselves, not the polys. + + if both of the above are 0, it'll use the indices of the mpolys of the MPoly + data in pdata, and ignore the origindex layer altogether. + */ +int mesh_recalcTesselation(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, struct MVert *mvert, int totface, + int totloop, int totpoly, int use_poly_origindex, int use_face_origindex); + +/*calculates a face normal.*/ +void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float *no); void unlink_mesh(struct Mesh *me); -void free_mesh(struct Mesh *me); +void free_mesh(struct Mesh *me, int unlink); struct Mesh *add_mesh(const char *name); struct Mesh *copy_mesh(struct Mesh *me); void mesh_update_customdata_pointers(struct Mesh *me); + +/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or + mloopcol and mcol) have the same relative active/render/clone/mask indices.*/ +void mesh_update_linked_customdata(struct Mesh *me); + void make_local_tface(struct Mesh *me); void make_local_mesh(struct Mesh *me); void boundbox_mesh(struct Mesh *me, float *loc, float *size); @@ -88,6 +118,12 @@ void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); void mesh_delete_material_index(struct Mesh *me, int index); void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth); +/*used for unit testing; compares two meshes, checking only + differences we care about. should be usable with leaf's + testing framework I get RNA work done, will use hackish + testing code for now.*/ +char *mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh); + struct BoundBox *mesh_get_bb(struct Object *ob); void mesh_get_texspace(struct Mesh *me, float *loc_r, float *rot_r, float *size_r); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index af625ae9d9c..5f6120509f0 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -47,6 +47,7 @@ struct ListBase; struct LinkNode; struct bArmature; struct ModifierData; +struct BMEditMesh; typedef enum { /* Should not be used, only for None modifier type */ @@ -147,13 +148,13 @@ typedef struct ModifierTypeInfo { */ void (*deformVertsEM)( struct ModifierData *md, struct Object *ob, - struct EditMesh *editData, struct DerivedMesh *derivedData, + struct BMEditMesh *editData, struct DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts); /* Set deform matrix per vertex for crazyspace correction */ void (*deformMatricesEM)( struct ModifierData *md, struct Object *ob, - struct EditMesh *editData, struct DerivedMesh *derivedData, + struct BMEditMesh *editData, struct DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); /********************* Non-deform modifier functions *********************/ @@ -191,7 +192,7 @@ typedef struct ModifierTypeInfo { */ struct DerivedMesh *(*applyModifierEM)( struct ModifierData *md, struct Object *ob, - struct EditMesh *editData, + struct BMEditMesh *editData, struct DerivedMesh *derivedData); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 238c812906d..e6caae7a954 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -90,7 +90,7 @@ typedef struct SculptSession { /* Partial redraw */ int partial_redraw; - + /* Used to cache the render of the active texture */ unsigned int texcache_side, *texcache, texcache_actual; diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index b82db853d37..3394d5b7bf6 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -47,6 +47,10 @@ struct _CCGEdge; struct _CCGFace; struct _CCGSubsurf; struct _CCGVert; +struct EdgeHash; +struct PBVH; +struct DMGridData; +struct DMGridAdjacency; /**************************** External *****************************/ @@ -75,6 +79,8 @@ typedef struct CCGDerivedMesh { short *edgeFlags; char *faceFlags; + int *reverseFaceMap; + struct PBVH *pbvh; struct ListBase *fmap; struct IndexNode *fmap_mem; @@ -96,6 +102,8 @@ typedef struct CCGDerivedMesh { void (*update)(DerivedMesh*); } multires; + + struct EdgeHash *ehash; } CCGDerivedMesh; #endif diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h new file mode 100644 index 00000000000..f2827747555 --- /dev/null +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -0,0 +1,72 @@ +#ifndef _BKE_TESSMESH_H +#define _BKE_TESSMESH_H + +#include "bmesh.h" + +struct BMesh; +struct BMLoop; +struct BMFace; +struct Mesh; +struct DerivedMesh; + +/* +ok: the EDBM module is for editmode bmesh stuff. in contrast, the + BMEdit module is for code shared with blenkernel that concerns + the BMEditMesh structure. +*/ + +/*this structure replaces EditMesh. + + through this, you get access to both the edit bmesh, + it's tesselation, and various stuff that doesn't belong in the BMesh + struct itself. + + the entire derivedmesh and modifier system works with this structure, + and not BMesh. Mesh->edit_bmesh stores a pointer to this structure.*/ +typedef struct BMEditMesh { + struct BMesh *bm; + + /*this is for undoing failed operations*/ + struct BMEditMesh *emcopy; + int emcopyusers; + + /*we store tesselations as triplets of three loops, + which each define a triangle.*/ + struct BMLoop *(*looptris)[3]; + int tottri; + + /*derivedmesh stuff*/ + struct DerivedMesh *derivedFinal, *derivedCage; + int lastDataMask; + + /*retopo data pointer*/ + struct RetopoPaintData *retopo_paint_data; + + /*index tables, to map indices to elements via + EDBM_init_index_arrays and associated functions. don't + touch this or read it directly.*/ + struct BMVert **vert_index; + struct BMEdge **edge_index; + struct BMFace **face_index; + + /*selection mode*/ + int selectmode; + + int mat_nr; + + /*Mesh structure this editmesh came from, if it came from one*/ + struct Mesh *me; + struct Object *ob; + + /*temp variables for x-mirror editing*/ + int mirror_cdlayer; + int mirr_free_arrays; +} BMEditMesh; + +void BMEdit_RecalcTesselation(BMEditMesh *tm); +BMEditMesh *BMEdit_Create(BMesh *bm); +BMEditMesh *BMEdit_Copy(BMEditMesh *tm); +void BMEdit_Free(BMEditMesh *em); +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em); + +#endif /* _BKE_TESSMESH_H */
\ No newline at end of file diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 14e622c972e..0e2817365f8 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -37,6 +37,10 @@ #ifndef BKE_UTILDEFINES_H #define BKE_UTILDEFINES_H +#ifdef __cplusplus +extern "C" { +#endif + /* these values need to be hardcoded in structs, dna does not recognize defines */ /* also defined in DNA_space_types.h */ #ifndef FILE_MAXDIR @@ -83,5 +87,16 @@ #define BROW(min, max) (((max)>=31? 0xFFFFFFFF: (1<<(max+1))-1) - ((min)? ((1<<(min))-1):0) ) #define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;} +/*little macro so inline keyword works*/ +#if defined(_MSC_VER) +#define BM_INLINE static __forceinline +#else +#define BM_INLINE static inline __attribute((always_inline)) +#endif + +#ifdef __cplusplus +} +#endif #endif // BKE_UTILDEFINES_H + diff --git a/source/blender/blenkernel/BKE_verse.h b/source/blender/blenkernel/BKE_verse.h new file mode 100644 index 00000000000..ee22081b03f --- /dev/null +++ b/source/blender/blenkernel/BKE_verse.h @@ -0,0 +1,586 @@ +/** + * $Id: BKE_verse.h 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* #define WITH_VERSE */ + +#ifndef BKE_VERSE_H +#define BKE_VERSE_H + +#include "DNA_listBase.h" +#include "BLI_dynamiclist.h" + +#include "verse.h" +#include "verse_ms.h" + +struct VNode; +struct VerseEdge; + +/* + * Verse Edge Hash (similar to edit edge hash) + */ +#define VEDHASHSIZE (512*512) +#define VEDHASH(a, b) ((a<b ? a : b) % VEDHASHSIZE) + +/* + * verse data: 4 float value + */ +typedef struct quat_real32_item { + struct quat_real32_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + real32 value[4]; +} quat_real32_item; + +/* + * verse data: 4 uint32 values + */ +typedef struct quat_uint32_item { + struct quat_uint32_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + uint32 value[4]; +} quat_uint32_item; + +/* + * verse data: 3 float values + */ +typedef struct vec_real32_item { + struct vec_real32_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + real32 value[3]; +} vec_real32_item; + +/* + * verse data: float value (weight) + */ +typedef struct real32_item { + struct real32_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + real32 value; +} real32_item; + +/* + * verse data: uint32 value + */ +typedef struct uint32_item { + struct uint32_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + uint32 value; +} uint32_item; + +/* + * verse data: uint8 value + */ +typedef struct uint8_item { + struct uint8_item *next, *prev; + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of item */ + uint8 value; +} uint8_item; + +/* + * verse data: vertex + */ +typedef struct VerseVert { + struct VerseVert *next, *prev; + /* verse data */ + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of vertex */ + real32 co[3]; /* x,y,z-coordinates of vertex */ + real32 no[3]; /* normal of vertex */ + /* blender internals */ + short flag; /* flags: VERT_DELETED, VERT_RECEIVED, etc. */ + void *vertex; /* pointer at EditVert or MVert */ + int counter; /* counter of VerseFaces using this VerseVert */ + union { + unsigned int index; /* counter need during transformation to mesh */ + struct VerseVert *vvert; + } tmp; /* pointer at new created verse vert, it is + * used during duplicating geometry node */ + float *cos; /* modified coordinates of vertex */ + float *nos; /* modified normal vector */ +} VerseVert; + +/* + * structture used for verse edge hash + */ +typedef struct HashVerseEdge { + struct VerseEdge *vedge; + struct HashVerseEdge *next; +} HashVerseEdge; + +/* + * fake verse data: edge + */ +typedef struct VerseEdge { + struct VerseEdge *next, *prev; + uint32 v0, v1; /* indexes of verse vertexes */ + int counter; /* counter of verse faces using this edge */ + struct HashVerseEdge hash; /* hash table */ + union { + unsigned int index; /* temporary index of edge */ + } tmp; +} VerseEdge; + +/* + * verse data: polygon + */ +typedef struct VerseFace { + struct VerseFace *next, *prev; + /* verse data */ + struct VLayer *vlayer; /* pointer at VerseLayer */ + uint32 id; /* id of face */ + struct VerseVert *vvert0; /* pointer at 1st VerseVert */ + struct VerseVert *vvert1; /* pointer at 2nd VerseVert */ + struct VerseVert *vvert2; /* pointer at 3th VerseVert */ + struct VerseVert *vvert3; /* pointer at 4th VerseVert */ + unsigned int v0, v1, v2, v3; /* indexes of VerseVerts ... needed during receiving */ + /* blender internals */ + char flag; /* flags: FACE_SEND_READY, FACE_SENT, FACE_RECEIVED, FACE_CHANGED*/ + short counter; /* counter of missed VerseVertexes */ + void *face; /* pointer at EditFace */ + float no[3]; /* normal vector */ + float *nos; /* modified normal vector */ +} VerseFace; + +/* + * verse data: layer + */ +typedef struct VLayer { + struct VLayer *next, *prev; + /* verse data*/ + struct VNode *vnode; /* pointer at VerseNode */ + uint16 id; /* id of layer */ + char *name; /* name of layer */ + VNGLayerType type; /* type of layer (VN_G_LAYER_VERTEX_XYZ, VN_G_LAYER_POLYGON_CORNER_UINT32) */ + uint32 def_int; /* default integer value */ + real64 def_real; /* default float value */ + /* blender internals */ + char flag; /* flags: LAYER_SENT, LAYER_RECEIVED, LAYER_DELETED, LAYER_OBSOLETE */ + short content; /* type of content (VERTEX_LAYER, POLYGON_LAYER) */ + struct DynamicList dl; /* vertexes, polygons, etc. */ + struct ListBase queue; /* queue of vertexes, polygons, etc. waiting for sending to verse server */ + struct ListBase orphans; /* list of versedata (polygons, etc.), that can be added to the DynamicList + * due to not received VerseVerts */ + unsigned int counter; /* counter of sent items */ + /* client dependent methods */ + void (*post_layer_create)(struct VLayer *vlayer); + void (*post_layer_destroy)(struct VLayer *vlayer); +} VLayer; + +/* + * verse data: link + */ +typedef struct VLink{ + struct VLink *next, *prev; + /* verse data */ + struct VerseSession *session; /* session pointer */ + struct VNode *source; /* object VerseNode "pointing" at some other VerseNode */ + struct VNode *target; /* VerseNode linked with some object node */ + unsigned int id; /* id of VerseLink */ + unsigned int target_id; /* some unknow id */ + char *label; /* name/label of VerseLink */ + /* blender internals */ + char flag; /* flags: LINK_SEND_READY */ + /* client dependent methods */ + void (*post_link_set)(struct VLink *vlink); + void (*post_link_destroy)(struct VLink *vlink); +} VLink; + +/* + * bitmap layer + */ +typedef struct VBitmapLayer { + struct VBitmapLayer *next, *prev; + /* verse data */ + struct VNode *vnode; /* pointer at Verse Node */ + VLayerID id; /* id of layer */ + char *name; /* name of layer */ + VNBLayerType type; /* type of layer (bits per channel) 1, 8, 16, 32, 64 */ + void *data; /* dynamic allocated data */ + /* blender internals */ + char flag; +} VBitmapLayer; + +/* + * data of bitmap node + */ +typedef struct VBitmapData { + struct DynamicList layers; /* dynamic list with access array of bitmap layers */ + struct ListBase queue; /* queue of layers waiting for receiving from verse server */ + uint16 width; /* width of all verse layers */ + uint16 height; /* height of all verse layers */ + uint16 depth; /* depth of bitmap 1 is 2D bitmap, >1 is 3D bitmap */ + /* blender internals */ + uint16 t_width; /* = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */ + uint16 t_height; /* = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */ + void *image; /* pointer at image */ + /* client dependent methods */ + void (*post_bitmap_dimension_set)(struct VNode *vnode); + void (*post_bitmap_layer_create)(struct VBitmapLayer *vblayer); + void (*post_bitmap_layer_destroy)(struct VBitmapLayer *vblayer); + void (*post_bitmap_tile_set)(struct VBitmapLayer *vblayer, unsigned int xs, unsigned int ys); +}VBitmapData; + +/* + * data of geometry node + */ +typedef struct VGeomData { + struct DynamicList layers; /* dynamic list with access array of Layers */ + struct VLink *vlink; /* pointer at VerseLink connecting object node and geom node */ + struct ListBase queue; /* queue of our layers waiting for receiving from verse server */ + void *mesh; /* pointer at Mesh (object node) */ + void *editmesh; /* pointer at EditMesh (edit mode) */ + struct HashVerseEdge *hash; /* verse edge hash */ + struct ListBase edges; /* list of fake verse edges */ + /* client dependent methods */ + void (*post_vertex_create)(struct VerseVert *vvert); + void (*post_vertex_set_xyz)(struct VerseVert *vvert); + void (*post_vertex_delete)(struct VerseVert *vvert); + void (*post_vertex_free_constraint)(struct VerseVert *vvert); + void (*post_polygon_create)(struct VerseFace *vface); + void (*post_polygon_set_corner)(struct VerseFace *vface); + void (*post_polygon_delete)(struct VerseFace *vface); + void (*post_polygon_free_constraint)(struct VerseFace *vface); + void (*post_geometry_free_constraint)(struct VNode *vnode); + void (*post_polygon_set_uint8)(struct VerseFace *vface); +} VGeomData; + +/* + * data of object node + */ +typedef struct VObjectData { + struct DynamicList links; /* dynamic list with access array of links between other nodes */ + struct ListBase queue; /* queue of links waiting for sending and receiving from verse server */ + float pos[3]; /* position of object VerseNode */ + float quat[4]; /* rotation of object VerseNode stored in quat */ + float scale[3]; /* scale of object VerseNode */ + void *object; /* pointer at object */ + short flag; /* flag: POS_RECEIVE_READY, ROT_RECEIVE_READY. SCALE_RECEIVE_READY */ + /* client dependent methods */ +/* void (*post_transform)(struct VNode *vnode);*/ + void (*post_transform_pos)(struct VNode *vnode); + void (*post_transform_rot)(struct VNode *vnode); + void (*post_transform_scale)(struct VNode *vnode); + void (*post_object_free_constraint)(struct VNode *vnode); +} VObjectData; + +/* + * Verse Tag + */ +typedef struct VTag { + struct VTag *next, *prev; + /* verse data*/ + struct VTagGroup *vtaggroup; /* pointer at Verse Tag Group */ + uint16 id; /* id of this tag */ + char *name; /* name of this tag*/ + VNTagType type; /* type: VN_TAG_BOOLEAN, VN_TAG_UINT32, VN_TAG_REAL64, VN_TAG_REAL64_VEC3, + VN_TAG_LINK, VN_TAG_ANIMATION, VN_TAG_BLOB */ + VNTag *tag; /* pointer at value (enum: vboolean, vuint32, vreal64, vstring, + vreal64_vec3, vlink, vanimation, vblob)*/ + /* blender internals */ + void *value; /* pointer at blender value */ +} VTag; + +/* + * Verse Tag Group (verse tags are grouped in tag groups) + */ +typedef struct VTagGroup { + struct VTagGroup *next, *prev; + /* verse data*/ + struct VNode *vnode; /* pointer at Verse Node */ + uint16 id; /* id of this tag group */ + char *name; /* name of this tag group */ + /* blender internals */ + struct DynamicList tags; /* dynamic list with access array containing tags */ + struct ListBase queue; /* list of tags waiting for receiving from verse server */ + /* client dependent methods */ + void (*post_tag_change)(struct VTag *vatg); + void (*post_taggroup_create)(struct VTagGroup *vtaggroup); +} VTagGroup; + + /* + * Verse Method Group + */ +typedef struct VMethodGroup +{ + struct VMethodGroup *next, *prev; + uint16 group_id; + char name[16]; + struct ListBase methods; +} VMethodGroup; + +/* + * Verse Method + */ +typedef struct VMethod +{ + struct VMethod *next, *prev; + uint16 id; + char name[500]; + uint8 param_count; + VNOParamType *param_type; + char **param_name; +} VMethod; + +/* + * Verse Node + */ +typedef struct VNode { + struct VNode *next, *prev; + /* verse data*/ + struct VerseSession *session; /* session pointer */ + VNodeID id; /* node id */ + VNodeID owner_id; /* owner's id of this node */ + char *name; /* name of this node */ + uint32 type; /* type of node (V_NT_OBJECT, V_NT_GEOMETRY, V_NT_BITMAP) */ + /* blender internals */ + char flag; /* flags: NODE_SENT, NODE_RECEIVED, NODE_DELTED, NODE_OBSOLETE */ + struct DynamicList taggroups; /* dynamic list with access array of taggroups */ + struct ListBase methodgroups; /* method groups */ + struct ListBase queue; /* list of taggroups waiting for receiving from verse server */ + void *data; /* generic pointer at some data (VObjectData, VGeomData, ...) */ + int counter; /* counter of verse link pointing at this vnode (vlink->target) */ + /* client dependent methods */ + void (*post_node_create)(struct VNode *vnode); + void (*post_node_destroy)(struct VNode *vnode); + void (*post_node_name_set)(struct VNode *vnode); +#ifdef VERSECHAT + /* verse chat */ + int chat_flag; /* CHAT_LOGGED, CHAT_NOTLOGGED */ +#endif +} VNode; + + +/* + * Verse Session: verse client can be connected to several verse servers + * it is neccessary to store some information about each session + */ +typedef struct VerseSession { + struct VerseSession *next, *prev; + /* verse data */ + VSession *vsession; /* pointer at VSeesion (verse.h) */ + uint32 avatar; /* id of avatar */ + char *address; /* string containg IP/domain name of verse server and number of port */ + void *connection; /* no clue */ + uint8 *host_id; /* no clue */ + /* blender internals */ + short flag; /* flag: VERSE_CONNECTING, VERSE_CONNECTED */ + DynamicList nodes; /* list of verse nodes */ + ListBase queue; /* list of nodes waiting for sending to verse server */ + unsigned int counter; /* count of events, when connection wasn't accepted */ + /* client dependent methods */ + void (*post_connect_accept)(struct VerseSession *session); + void (*post_connect_terminated)(struct VerseSession *session); + void (*post_connect_update)(struct VerseSession *session); +} VerseSession; + +typedef struct VerseServer { + struct VerseServer *next, *prev; + char *name; /* human-readable server name */ + char *ip; /* string containing IP/domain name of verse server and number of port */ + short flag; /* flag: VERSE_CONNECTING, VERSE_CONNECTED */ + struct VerseSession *session; /* pointer to related session */ +} VerseServer; +/* + * list of post callback functions + */ +typedef struct PostCallbackFunction { + void (*function)(void *arg); + void *param; +} PostCallbackFunction; + +/* VerseSession->flag */ +#define VERSE_CONNECTING 1 +#define VERSE_CONNECTED 2 +#define VERSE_AUTOSUBSCRIBE 4 + +/* max VerseSession->counter value */ +#define MAX_UNCONNECTED_EVENTS 100 + +/* VNode flags */ +#define NODE_SENT 1 +#define NODE_RECEIVED 2 +#define NODE_DELTED 4 +#define NODE_OBSOLETE 8 + +#ifdef VERSECHAT +#define CHAT_NOTLOGGED 0 +#define CHAT_LOGGED 1 +#endif + +/* VLayer flags */ +#define LAYER_SENT 1 +#define LAYER_RECEIVED 2 +#define LAYER_DELETED 4 +#define LAYER_OBSOLETE 8 + +/* VLink->flag */ +#define LINK_SEND_READY 1 + +/* VObjectData->flag */ +#define POS_RECEIVE_READY 1 +#define ROT_RECEIVE_READY 2 +#define SCALE_RECEIVE_READY 4 +#define POS_SEND_READY 8 +#define ROT_SEND_READY 16 +#define SCALE_SEND_READY 32 + +/* VLayer->content */ +#define VERTEX_LAYER 0 +#define POLYGON_LAYER 1 + +/* VerseVert->flag */ +#define VERT_DELETED 1 /* vertex delete command was received from verse server */ +#define VERT_RECEIVED 2 /* VerseVert was received from verse server (is not in sending queue) */ +#define VERT_LOCKED 4 /* VerseVert is ready to send local position to verse server */ +#define VERT_POS_OBSOLETE 8 /* position of vertex was changed during sending to verse server */ +#define VERT_OBSOLETE 16 /* vertex delete command was sent to verse server; it means, that + * no information related to this vertex shoudln't be sent to verse + * until verse vertex is completely deleted ... then this vertex id + * can be reused again for new vertex */ + +/* VerseFace->flag */ +#define FACE_SEND_READY 1 /* VerseFace is ready for sending to verse server */ +#define FACE_RECEIVED 2 /* VerseFace was received from verse server */ +#define FACE_SENT 4 /* VerseFace was sent to verse server and we expect receiving from verse server */ +#define FACE_DELETED 8 /* delete command was sent to verse server */ +#define FACE_CHANGED 16 /* VerseFace was only changed not created */ +#define FACE_OBSOLETE 32 /* VerseFace was changed during sending to verse server */ + +/* Queue type */ +#define VERSE_NODE 1 +#define VERSE_LINK 2 +#define VERSE_LAYER 3 +#define VERSE_VERT 4 +#define VERSE_FACE 5 + +#define VERSE_TAG 6 +#define VERSE_TAG_GROUP 7 + +#define VERSE_VERT_UINT32 8 +#define VERSE_VERT_REAL32 9 +#define VERSE_VERT_VEC_REAL32 10 + +#define VERSE_FACE_UINT8 11 +#define VERSE_FACE_UINT32 12 +#define VERSE_FACE_REAL32 13 +#define VERSE_FACE_QUAT_UINT32 14 +#define VERSE_FACE_QUAT_REAL32 15 + +/* Verse Bitmap Layer flags */ +#define VBLAYER_SUBSCRIBED 1 + +/* function prototypes */ + +/* functions from verse_session.c */ +void set_verse_session_callbacks(void); +struct VerseSession *versesession_from_vsession(VSession *vsession); +struct VerseSession *current_verse_session(void); +struct VerseSession *create_verse_session(const char *name, const char *pass, const char *address, uint8 *expected_key); +void free_verse_session(struct VerseSession *session); +void b_verse_update(void); +void b_verse_ms_get(void); +void b_verse_connect(char *address); +void end_verse_session(struct VerseSession *session); +void end_all_verse_sessions(void); + +/* functions from verse_node.c */ +void send_verse_tag(struct VTag *vtag); +void send_verse_taggroup(struct VTagGroup *vtaggroup); +void send_verse_node(struct VNode *vnode); +void free_verse_node_data(struct VNode *vnode); +void free_verse_node(struct VNode *vnode); +struct VNode* lookup_vnode(VerseSession *session, VNodeID node_id); +struct VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id); +void set_node_callbacks(void); + +/* functions from verse_object_node.c */ +struct VLink *find_unsent_parent_vlink(struct VerseSession *session, struct VNode *vnode); +struct VLink *find_unsent_child_vlink(struct VerseSession *session, struct VNode *vnode); +struct VLink *create_verse_link(VerseSession *session, struct VNode *source, struct VNode *target, uint16 link_id, uint32 target_id, const char *label); +void send_verse_object_position(struct VNode *vnode); +void send_verse_object_rotation(struct VNode *vnode); +void send_verse_object_scale(struct VNode *vnode); +void send_verse_link(struct VLink *vlink); + +void free_object_data(struct VNode *vnode); +void set_object_callbacks(void); +struct VObjectData *create_object_data(void); + + +/* functions from verse_method.c */ +void free_verse_methodgroup(VMethodGroup *vmg); +#ifdef VERSECHAT +void send_say(const char *chan, const char *utter); +void send_login(struct VNode *vnode); +void send_logout(struct VNode *vnode); +void send_join(struct VNode *vnode, const char *chan); +void send_leave(struct VNode *vnode, const char *chan); +#endif +void set_method_callbacks(void); + +/* functions from verse_geometry_node.c */ +struct VerseFace* create_verse_face(struct VLayer *vlayer, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3); +struct VerseVert* create_verse_vertex(struct VLayer *vlayer, uint32 vertex_id, real32 x, real32 y, real32 z); +struct VLayer *create_verse_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real); +struct VGeomData *create_geometry_data(void); + +void send_verse_layer(struct VLayer *vlayer); + +void send_verse_face_corner_quat_real32(struct quat_real32_item *item, short type); +void send_verse_face_corner_quat_uint32(struct quat_uint32_item *item, short type); +void send_verse_face_real32(struct real32_item *item, short type); +void send_verse_face_uint32(struct uint32_item *item, short type); +void send_verse_face_uint8(struct uint8_item *item, short type); + +void send_verse_vert_vec_real32(struct vec_real32_item *item, short type); +void send_verse_vert_real32(struct real32_item *item, short type); +void send_verse_vert_uint32(struct uint32_item *item, short type); + +void send_verse_vertex_delete(struct VerseVert *vvert); +void send_verse_vertex(struct VerseVert *vvert); +void send_verse_face_delete(struct VerseFace *vface); + +void destroy_geometry(struct VNode *vnode); + +struct VLayer* find_verse_layer_type(struct VGeomData *geom, short content); +void add_item_to_send_queue(struct ListBase *lb, void *item, short type); +void free_geom_data(struct VNode *vnode); +void set_geometry_callbacks(void); + +/* functions prototypes from verse_bitmap.c */ +void set_bitmap_callbacks(void); +void free_bitmap_layer_data(struct VBitmapLayer *vblayer); +struct VBitmapLayer *create_bitmap_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNBLayerType type); +void free_bitmap_node_data(struct VNode *vnode); +struct VBitmapData *create_bitmap_data(void); + +#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c8969f86778..dc485f5dc5f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC ../imbuf ../makesdna ../makesrna + ../bmesh ../modifiers ../nodes ../editors/include @@ -86,6 +87,7 @@ set(SRC intern/depsgraph.c intern/displist.c intern/effect.c + intern/editderivedbmesh.c intern/exotic.c intern/fcurve.c intern/fluidsim.c @@ -108,6 +110,7 @@ set(SRC intern/mesh.c intern/mesh_validate.c intern/modifier.c + intern/modifiers_bmesh.c intern/multires.c intern/nla.c intern/node.c diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index bef72d3bf67..33c6a170178 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -11,6 +11,7 @@ incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' +incs += ' ../bmesh' incs += ' #/intern/smoke/extern' incs += ' #/intern/mikktspace' incs += ' #/intern/audaspace/intern' diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c index d2c00d21df3..f8b432ed384 100644 --- a/source/blender/blenkernel/intern/BME_Customdata.c +++ b/source/blender/blenkernel/intern/BME_Customdata.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_customdata.c jan 2007 * @@ -82,7 +84,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc if(data->totlayer){ /*alloc memory*/ data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers"); - data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0); + data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 1); /*initialize layer data*/ for(i=0; i < BME_CD_NUMTYPES; i++){ if(init->layout[i]){ @@ -195,3 +197,4 @@ void BME_CD_set_default(BME_CustomData *data, void **block) typeInfo->set_default((char*)*block + offset, 1); } } +#endif diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index 4f1102bb828..8c399e88d67 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_mesh.c jan 2007 * @@ -262,7 +264,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); /*copy face corner data*/ - CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata); + CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0); /*initialize memory pools*/ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); @@ -457,7 +459,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); /*copy face corner data*/ - CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata); + CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata, 0, 0); /*initialize memory pools*/ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); @@ -469,10 +471,10 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) totvert = dm->getNumVerts(dm); totedge = dm->getNumEdges(dm); - totface = dm->getNumFaces(dm); + totface = dm->getNumTessFaces(dm); mvert = dm->getVertArray(dm); medge = dm->getEdgeArray(dm); - mface = dm->getFaceArray(dm); + mface = dm->getTessFaceArray(dm); vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array"); @@ -569,7 +571,8 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) } /*convert back to mesh*/ - result = CDDM_from_template(dm,totvert,totedge,totface); + /*BMESH_TODO this should add in mloops and mpolys as well*/ + result = CDDM_from_template(dm,totvert,totedge,totface, 0, 0); CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert); CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge); CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface); @@ -612,7 +615,7 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) } } if(totface){ - mface = CDDM_get_faces(result); + mface = CDDM_get_tessfaces(result); origindex = result->getFaceDataArray(result, CD_ORIGINDEX); /*make faces*/ for(i=0,f=bm->polys.first;f;f=f->next){ @@ -641,3 +644,4 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) BLI_edgehash_free(edge_hash, NULL); return result; } +#endif diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c index 9d68866bc99..6897b0c8990 100644 --- a/source/blender/blenkernel/intern/BME_eulers.c +++ b/source/blender/blenkernel/intern/BME_eulers.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_eulers.c jan 2007 * @@ -126,13 +128,13 @@ BME_Edge *BME_ME(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2){ #ifndef BME_FASTEULER /*count valance of v1*/ - if(v1->edge){ - d1 = BME_disk_getpointer(v1->edge,v1); + if(v1->e){ + d1 = BME_disk_getpointer(v1->e,v1); if(d1) valance1 = BME_cycle_length(d1); else BME_error(); } - if(v2->edge){ - d2 = BME_disk_getpointer(v2->edge,v2); + if(v2->e){ + d2 = BME_disk_getpointer(v2->e,v2); if(d2) valance2 = BME_cycle_length(d2); else BME_error(); } @@ -200,7 +202,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int elist[i]->eflag1 |= MF_CANDIDATE; /*if elist[i] has a loop, count its radial length*/ - if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->loop->radial)); + if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->l->radial)); else elist[i]->eflag2 = 0; } @@ -270,8 +272,8 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int for(i=0;i<len;i++){ curvert = vlist[i]; l = BME_create_loop(bm,curvert,NULL,f,NULL); - if(!(f->loopbase)) f->loopbase = l; - BME_cycle_append(f->loopbase, l); + if(!(f->loopbase)) f->lbase = l; + BME_cycle_append(f->lbase, l); } /*take care of edge pointers and radial cycle*/ @@ -295,7 +297,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int f->len = len; /*Validation Loop cycle*/ - edok = BME_cycle_validate(len, f->loopbase); + edok = BME_cycle_validate(len, f->lbase); if(!edok) BME_error(); for(i=0, l = f->loopbase; i<len; i++, l=l->next){ /*validate loop vert pointers*/ @@ -323,7 +325,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int */ int BME_KV(BME_Mesh *bm, BME_Vert *v){ - if(v->edge == NULL){ + if(v->e == NULL){ BLI_remlink(&(bm->verts), v); BME_free_vert(bm,v); return 1; @@ -346,7 +348,7 @@ int BME_KE(BME_Mesh *bm, BME_Edge *e){ int edok; /*Make sure that no faces!*/ - if(e->loop == NULL){ + if(e->l == NULL){ BME_disk_remove_edge(e, e->v1); BME_disk_remove_edge(e, e->v2); @@ -382,14 +384,14 @@ int BME_KF(BME_Mesh *bm, BME_Poly *bply){ /*add validation to make sure that radial cycle is cleaned up ok*/ /*deal with radial cycle first*/ - len = BME_cycle_length(bply->loopbase); + len = BME_cycle_length(bply->lbase); for(i=0, curloop=bply->loopbase; i < len; i++, curloop = curloop->next) BME_radial_remove_loop(curloop, curloop->e); /*now deallocate the editloops*/ for(i=0; i < len; i++){ - newbase = bply->loopbase->next; - oldbase = bply->loopbase; + newbase = bply->lbase->next; + oldbase = bply->lbase; BME_cycle_remove(oldbase, oldbase); BME_free_loop(bm, oldbase); bply->loopbase = newbase; @@ -449,24 +451,24 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ /*add ne to tv's disk cycle*/ BME_disk_append_edge(ne, tv); /*verify disk cycles*/ - diskbase = BME_disk_getpointer(ov->edge,ov); + diskbase = BME_disk_getpointer(ov->e,ov); edok = BME_cycle_validate(valance1, diskbase); if(!edok) BME_error(); - diskbase = BME_disk_getpointer(tv->edge,tv); + diskbase = BME_disk_getpointer(tv->e,tv); edok = BME_cycle_validate(valance2, diskbase); if(!edok) BME_error(); - diskbase = BME_disk_getpointer(nv->edge,nv); + diskbase = BME_disk_getpointer(nv->e,nv); edok = BME_cycle_validate(2, diskbase); if(!edok) BME_error(); /*Split the radial cycle if present*/ - if(e->loop){ + if(e->l){ BME_Loop *nl,*l; BME_CycleNode *radEBase=NULL, *radNEBase=NULL; - int radlen = BME_cycle_length(&(e->loop->radial)); + int radlen = BME_cycle_length(&(e->l->radial)); /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/ - while(e->loop){ - l=e->loop; + while(e->l){ + l=e->l; l->f->len++; BME_radial_remove_loop(l,e); @@ -519,17 +521,17 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ } - e->loop = radEBase->data; - ne->loop = radNEBase->data; + e->l = radEBase->data; + ne->l = radNEBase->data; /*verify length of radial cycle*/ - edok = BME_cycle_validate(radlen,&(e->loop->radial)); + edok = BME_cycle_validate(radlen,&(e->l->radial)); if(!edok) BME_error(); - edok = BME_cycle_validate(radlen,&(ne->loop->radial)); + edok = BME_cycle_validate(radlen,&(ne->l->radial)); if(!edok) BME_error(); /*verify loop->v and loop->next->v pointers for e*/ - for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){ + for(i=0,l=e->l; i < radlen; i++, l = l->radial_next){ if(!(l->e == e)) BME_error(); if(!(l->radial.data == l)) BME_error(); if(l->prev->e != ne && l->next->e != ne) BME_error(); @@ -538,11 +540,11 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ if(l->v == l->next->v) BME_error(); if(l->e == l->next->e) BME_error(); /*verify loop cycle for kloop->f*/ - edok = BME_cycle_validate(l->f->len, l->f->loopbase); + edok = BME_cycle_validate(l->f->len, l->f->lbase); if(!edok) BME_error(); } /*verify loop->v and loop->next->v pointers for ne*/ - for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){ + for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next){ if(!(l->e == ne)) BME_error(); if(!(l->radial.data == l)) BME_error(); if(l->prev->e != e && l->next->e != e) BME_error(); @@ -551,7 +553,7 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ if(l->v == l->next->v) BME_error(); if(l->e == l->next->e) BME_error(); /*verify loop cycle for kloop->f. Redundant*/ - edok = BME_cycle_validate(l->f->len, l->f->loopbase); + edok = BME_cycle_validate(l->f->len, l->f->lbase); if(!edok) BME_error(); } } @@ -596,7 +598,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo /*verify that v1 and v2 are in face.*/ - len = BME_cycle_length(f->loopbase); + len = BME_cycle_length(f->lbase); for(i = 0, curloop = f->loopbase; i < len; i++, curloop = curloop->next){ if(curloop->v == v1) v1loop = curloop; else if(curloop->v == v2) v2loop = curloop; @@ -630,7 +632,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/ /*go through all of f2's loops and make sure they point to it properly.*/ - f2len = BME_cycle_length(f2->loopbase); + f2len = BME_cycle_length(f2->lbase); for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next) curloop->f = f2; /*link up the new loops into the new edges radial*/ @@ -640,7 +642,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo f2->len = f2len; - f1len = BME_cycle_length(f->loopbase); + f1len = BME_cycle_length(f->lbase); f->len = f1len; if(rl) *rl = f2loop; @@ -688,7 +690,7 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) int len,radlen=0, halt = 0, i, valance1, valance2,edok; if(BME_vert_in_edge(ke,kv) == 0) return 0; - diskbase = BME_disk_getpointer(kv->edge, kv); + diskbase = BME_disk_getpointer(kv->e, kv); len = BME_cycle_length(diskbase); if(len == 2){ @@ -701,9 +703,9 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) else{ /*For verification later, count valance of ov and tv*/ - diskbase = BME_disk_getpointer(ov->edge, ov); + diskbase = BME_disk_getpointer(ov->e, ov); valance1 = BME_cycle_length(diskbase); - diskbase = BME_disk_getpointer(tv->edge, tv); + diskbase = BME_disk_getpointer(tv->e, tv); valance2 = BME_cycle_length(diskbase); /*remove oe from kv's disk cycle*/ @@ -718,10 +720,10 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) /*deal with radial cycle of ke*/ - if(ke->loop){ + if(ke->l){ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ - radlen = BME_cycle_length(&(ke->loop->radial)); - for(i=0,killoop = ke->loop; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){ + radlen = BME_cycle_length(&(ke->l->radial)); + for(i=0,killoop = ke->l; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){ /*relink loops and fix vertex pointer*/ killoop->next->prev = killoop->prev; killoop->prev->next = killoop->next; @@ -729,11 +731,11 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) /*fix len attribute of face*/ killoop->f->len--; - if(killoop->f->loopbase == killoop) killoop->f->loopbase = killoop->next; + if(killoop->f->loopbase == killoop) killoop->f->lbase = killoop->next; } /*second step, remove all the hanging loops attached to ke*/ - killoop = ke->loop; - radlen = BME_cycle_length(&(ke->loop->radial)); + killoop = ke->l; + radlen = BME_cycle_length(&(ke->l->radial)); /*make sure we have enough room in bm->lpar*/ if(bm->lparlen < radlen){ MEM_freeN(bm->lpar); @@ -744,7 +746,7 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) i=0; while(i<radlen){ bm->lpar[i] = killoop; - killoop = killoop->radial.next->data; + killoop = killoop->radial_next; i++; } i=0; @@ -753,22 +755,22 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) i++; } /*Validate radial cycle of oe*/ - edok = BME_cycle_validate(radlen,&(oe->loop->radial)); + edok = BME_cycle_validate(radlen,&(oe->l->radial)); } /*Validate disk cycles*/ - diskbase = BME_disk_getpointer(ov->edge,ov); + diskbase = BME_disk_getpointer(ov->e,ov); edok = BME_cycle_validate(valance1, diskbase); if(!edok) BME_error(); - diskbase = BME_disk_getpointer(tv->edge,tv); + diskbase = BME_disk_getpointer(tv->e,tv); edok = BME_cycle_validate(valance2, diskbase); if(!edok) BME_error(); /*Validate loop cycle of all faces attached to oe*/ - for(i=0,nextl = oe->loop; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){ - edok = BME_cycle_validate(nextl->f->len,nextl->f->loopbase); + for(i=0,nextl = oe->l; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){ + edok = BME_cycle_validate(nextl->f->len,nextl->f->lbase); if(!edok) BME_error(); } /*deallocate edge*/ @@ -898,8 +900,8 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) if(f1 == f2) return NULL; //can't join a face to itself /*verify that e is in both f1 and f2*/ - f1len = BME_cycle_length(f1->loopbase); - f2len = BME_cycle_length(f2->loopbase); + f1len = BME_cycle_length(f1->lbase); + f2len = BME_cycle_length(f2->lbase); for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = curloop->next){ if(curloop->e == e){ f1loop = curloop; @@ -938,19 +940,19 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) f2loop->prev->next = f1loop->next; /*if f1loop was baseloop, give f1loop->next the base.*/ - if(f1->loopbase == f1loop) f1->loopbase = f1loop->next; + if(f1->loopbase == f1loop) f1->lbase = f1loop->next; /*validate the new loop*/ - loopok = BME_cycle_validate((f1len+f2len)-2, f1->loopbase); + loopok = BME_cycle_validate((f1len+f2len)-2, f1->lbase); if(!loopok) BME_error(); /*make sure each loop points to the proper face*/ - newlen = BME_cycle_length(f1->loopbase); + newlen = BME_cycle_length(f1->lbase); for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = curloop->next) curloop->f = f1; f1->len = newlen; - edok = BME_cycle_validate(f1->len, f1->loopbase); + edok = BME_cycle_validate(f1->len, f1->lbase); if(!edok) BME_error(); /*remove edge from the disk cycle of its two vertices.*/ @@ -966,3 +968,4 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) BME_free_poly(bm, f2); return f1; } +#endif diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c index ca5d0b412ed..1097b9da2bc 100644 --- a/source/blender/blenkernel/intern/BME_mesh.c +++ b/source/blender/blenkernel/intern/BME_mesh.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_mesh.c jan 2007 * @@ -51,10 +53,10 @@ BME_Mesh *BME_make_mesh(int allocsize[4]) /*allocate the structure*/ BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh"); /*allocate the memory pools for the mesh elements*/ - bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 0); - bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 0); - bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 0); - bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 0); + bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 1, 0); + bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 1, 0); + bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 1, 0); + bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 1, 0); return bm; } /* @@ -78,7 +80,7 @@ void BME_free_mesh(BME_Mesh *bm) do{ CustomData_bmesh_free_block(&bm->ldata, &l->data); l = l->next; - }while(l!=f->loopbase); + }while(l!=f->lbase); } /*Free custom data pools, This should probably go in CustomData_free?*/ @@ -192,9 +194,9 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) if(e->v1 == e->v2) VHALT(halt); /*validate e->d1.data and e->d2.data*/ if(e->d1.data != e || e->d2.data != e) VHALT(halt); - /*validate e->loop->e*/ - if(e->loop){ - if(e->loop->e != e) VHALT(halt); + /*validate e->l->e*/ + if(e->l){ + if(e->l->e != e) VHALT(halt); } } @@ -206,17 +208,17 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) } /*Validate vertices and disk cycle*/ for(v=bm->verts.first; v; v=v->next){ - /*validate v->edge pointer*/ + /*validate v->e pointer*/ if(v->tflag1){ - if(v->edge){ - ok = BME_vert_in_edge(v->edge,v); + if(v->e){ + ok = BME_vert_in_edge(v->e,v); if(!ok) VHALT(halt); /*validate length of disk cycle*/ - diskbase = BME_disk_getpointer(v->edge, v); + diskbase = BME_disk_getpointer(v->e, v); ok = BME_cycle_validate(v->tflag1, diskbase); if(!ok) VHALT(halt); /*validate that each edge in disk cycle contains V*/ - for(i=0, e=v->edge; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){ + for(i=0, e=v->e; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){ ok = BME_vert_in_edge(e, v); if(!ok) VHALT(halt); } @@ -238,7 +240,7 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces /*Validate the loop cycle integrity.*/ for(f=bm->polys.first; f; f=f->next){ - ok = BME_cycle_length(f->loopbase); + ok = BME_cycle_length(f->lbase); if(ok > 1){ f->tflag1 = ok; } @@ -249,11 +251,11 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) if(!ok) VHALT(halt); /*verify radial node data pointer*/ if(l->radial.data != l) VHALT(halt); - /*validate l->e->loop poitner*/ - if(l->e->loop == NULL) VHALT(halt); + /*validate l->e->l poitner*/ + if(l->e->l == NULL) VHALT(halt); /*validate l->f pointer*/ if(l->f != f) VHALT(halt); - /*see if l->e->loop is actually in radial cycle*/ + /*see if l->e->l is actually in radial cycle*/ l->e->tflag2++; } @@ -261,8 +263,8 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) /*validate length of radial cycle*/ for(e=bm->edges.first; e; e=e->next){ - if(e->loop){ - ok = BME_cycle_validate(e->tflag2,&(e->loop->radial)); + if(e->l){ + ok = BME_cycle_validate(e->tflag2,&(e->l->radial)); if(!ok) VHALT(halt); } } @@ -279,3 +281,4 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt) void BME_error(void){ printf("BME modelling error!"); } +#endif diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c index 8970e7ff705..f79b8edc866 100644 --- a/source/blender/blenkernel/intern/BME_structure.c +++ b/source/blender/blenkernel/intern/BME_structure.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_structure.c jan 2007 * @@ -31,7 +33,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ - +#if 0 #include <limits.h> #include "MEM_guardedalloc.h" @@ -85,7 +87,7 @@ BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){ v->EID = bm->nextv; v->co[0] = v->co[1] = v->co[2] = 0.0f; v->no[0] = v->no[1] = v->no[2] = 0.0f; - v->edge = NULL; + v->e = NULL; v->data = NULL; v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0; v->flag = v->h = 0; @@ -113,7 +115,7 @@ BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *ex e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL; e->d1.data = e; e->d2.data = e; - e->loop = NULL; + e->l = NULL; e->data = NULL; e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0; e->flag = e->h = 0; @@ -238,7 +240,7 @@ void BME_free_loop(BME_Mesh *bm, BME_Loop *l){ * BME_disk_getpointer * * 2: The Radial Cycle - A circle of face edges (BME_Loop) around an edge - * Base: edge->loop->radial structure. + * Base: edge->l->radial structure. * * The radial cycle is similar to the radial cycle in the radial edge data structure.* * Unlike the radial edge however, the radial cycle does not require a large amount of memory @@ -254,7 +256,7 @@ void BME_free_loop(BME_Mesh *bm, BME_Loop *l){ * * * 3: The Loop Cycle - A circle of face edges around a polygon. - * Base: polygon->loopbase. + * Base: polygon->lbase. * * The loop cycle keeps track of a faces vertices and edges. It should be noted that the * direction of a loop cycle is either CW or CCW depending on the face normal, and is @@ -442,15 +444,15 @@ int BME_disk_append_edge(BME_Edge *e, BME_Vert *v) if(BME_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/ /*check for loose vert first*/ - if(v->edge == NULL){ - v->edge = e; + if(v->e == NULL){ + v->e = e; base = tail = BME_disk_getpointer(e, v); BME_cycle_append(base, tail); /*circular reference is ok!*/ return 1; } - /*insert e at the end of disk cycle and make it the new v->edge*/ - base = BME_disk_getpointer(v->edge, v); + /*insert e at the end of disk cycle and make it the new v->e*/ + base = BME_disk_getpointer(v->e, v); tail = BME_disk_getpointer(e, v); BME_cycle_append(base, tail); return 1; @@ -473,18 +475,18 @@ void BME_disk_remove_edge(BME_Edge *e, BME_Vert *v) BME_Edge *newbase; int len; - base = BME_disk_getpointer(v->edge, v); + base = BME_disk_getpointer(v->e, v); remnode = BME_disk_getpointer(e, v); - /*first deal with v->edge pointer...*/ + /*first deal with v->e pointer...*/ len = BME_cycle_length(base); if(len == 1) newbase = NULL; - else if(v->edge == e) newbase = base->next-> data; - else newbase = v->edge; + else if(v->e == e) newbase = base->next-> data; + else newbase = v->e; /*remove and rebase*/ BME_cycle_remove(base, remnode); - v->edge = newbase; + v->e = newbase; } /** @@ -537,12 +539,12 @@ int BME_disk_count_edgeflag(BME_Vert *v, int eflag, int tflag){ BME_Edge *curedge; int i, len=0, count=0; - if(v->edge){ + if(v->e){ if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/ - diskbase = BME_disk_getpointer(v->edge, v); + diskbase = BME_disk_getpointer(v->e, v); len = BME_cycle_length(diskbase); - for(i = 0, curedge=v->edge; i<len; i++){ + for(i = 0, curedge=v->e; i<len; i++){ if(tflag){ if(curedge->tflag1 == tflag) count++; } @@ -560,11 +562,11 @@ int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){ BME_Edge *curedge; int i, len=0; - if(v->edge){ - diskbase = BME_disk_getpointer(v->edge,v); + if(v->e){ + diskbase = BME_disk_getpointer(v->e,v); len = BME_cycle_length(diskbase); - for(i = 0, curedge=v->edge; i<len; i++){ + for(i = 0, curedge=v->e; i<len; i++){ if(curedge == e) return 1; else curedge=BME_disk_nextedge(curedge, v); } @@ -574,12 +576,12 @@ int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){ /*end disk cycle routines*/ BME_Loop *BME_radial_nextloop(BME_Loop *l){ - return (BME_Loop*)(l->radial.next->data); + return (BME_Loop*)(l->radial_next); } void BME_radial_append(BME_Edge *e, BME_Loop *l){ - if(e->loop == NULL) e->loop = l; - BME_cycle_append(&(e->loop->radial), &(l->radial)); + if(e->l == NULL) e->l = l; + BME_cycle_append(&(e->l->radial), &(l->radial)); } void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e) @@ -587,15 +589,15 @@ void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e) BME_Loop *newbase; int len; - /*deal with edge->loop pointer*/ - len = BME_cycle_length(&(e->loop->radial)); + /*deal with edge->l pointer*/ + len = BME_cycle_length(&(e->l->radial)); if(len == 1) newbase = NULL; - else if(e->loop == l) newbase = e->loop->radial.next->data; - else newbase = e->loop; + else if(e->l == l) newbase = e->l->radial_next; + else newbase = e->l; /*remove and rebase*/ - BME_cycle_remove(&(e->loop->radial), &(l->radial)); - e->loop = newbase; + BME_cycle_remove(&(e->l->radial), &(l->radial)); + e->l = newbase; } int BME_radial_find_face(BME_Edge *e,BME_Poly *f) @@ -604,8 +606,8 @@ int BME_radial_find_face(BME_Edge *e,BME_Poly *f) BME_Loop *curloop; int i, len; - len = BME_cycle_length(&(e->loop->radial)); - for(i = 0, curloop = e->loop; i < len; i++, curloop = curloop->radial.next->data){ + len = BME_cycle_length(&(e->l->radial)); + for(i = 0, curloop = e->l; i < len; i++, curloop = curloop->radial_next){ if(curloop->f == f) return 1; } return 0; @@ -615,9 +617,11 @@ struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v) { BME_Loop *l; int i, len; - len = BME_cycle_length(f->loopbase); + len = BME_cycle_length(f->lbase); for (i = 0, l=f->loopbase; i < len; i++, l=l->next) { if (l->v == v) return l; } return NULL; } +#endif +#endif diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c index 2b28fb705fd..9dd4669ba1f 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -1,3 +1,5 @@ +#if 0 +/** /* * BME_tools.c jan 2007 * @@ -39,7 +41,11 @@ #include "DNA_object_types.h" #include "BLI_math.h" +<<<<<<< .working +#include "BLI_cellalloc.h" +======= #include "BLI_utildefines.h" +>>>>>>> .merge-right.r35190 #include "BKE_bmesh.h" @@ -114,20 +120,20 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { BME_Loop *l; int len, count, flag; - if (v->edge == NULL) { + if (v->e == NULL) { /* loose vert */ return 1; } /* count edges while looking for non-manifold edges */ - oe = v->edge; - for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) { - if (e->loop == NULL) { + oe = v->e; + for (len=0,e=v->e; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) { + if (e->l == NULL) { /* loose edge */ return 1; } - if (BME_cycle_length(&(e->loop->radial)) > 2) { + if (BME_cycle_length(&(e->l->radial)) > 2) { /* edge shared by more than two faces */ return 1; } @@ -136,28 +142,28 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { count = 1; flag = 1; e = NULL; - oe = v->edge; - l = oe->loop; + oe = v->e; + l = oe->l; while(e != oe) { if (l->v == v) l = l->prev; else l = l->next; e = l->e; count++; /* count the edges */ - if (flag && l->radial.next->data == l) { + if (flag && l->radial_next == l) { /* we've hit the edge of an open mesh, reset once */ flag = 0; count = 1; oe = e; e = NULL; - l = oe->loop; + l = oe->l; } - else if (l->radial.next->data == l) { + else if (l->radial_next == l) { /* break the loop */ e = oe; } else { - l = l->radial.next->data; + l = l->radial_next; } } @@ -174,8 +180,8 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { static BME_Poly *BME_JFKE_safe(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) { BME_Loop *l1, *l2; - l1 = e->loop; - l2 = l1->radial.next->data; + l1 = e->l; + l2 = l1->radial_next; if (l1->v == l2->v) { BME_loop_reverse(bm, f2); } @@ -227,8 +233,8 @@ static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UN w[0] = 1.0f - fac; w[1] = fac; - if(!e1->loop) return; - l = e1->loop; + if(!e1->l) return; + l = e1->l; do{ if(l->v == v1){ v1loop = l; @@ -245,8 +251,8 @@ static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UN src[1] = v2loop->data; CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data); - l = l->radial.next->data; - }while(l!=e1->loop); + l = l->radial_next; + }while(l!=e1->l); } @@ -283,8 +289,8 @@ static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fa w[0] = 1.0f - fac; w[1] = fac; - if(ke->loop){ - l = ke->loop; + if(ke->l){ + l = ke->l; do{ if(l->v == tv && l->next->v == kv){ tvloop = l; @@ -294,8 +300,8 @@ static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fa src[1] = tvloop->data; CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data); } - l=l->radial.next->data; - }while(l!=ke->loop); + l=l->radial_next; + }while(l!=ke->l); } BME_JEKV(bm,ke,kv); } @@ -401,12 +407,12 @@ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, B * so... here we walk around edges to find the needed verts */ forward = 1; is_split_vert = 0; - if (v->edge == NULL) { + if (v->e == NULL) { //printf("We can't split a loose vert's edge!\n"); return NULL; } - e1 = v->edge; /* we just use the first two edges */ - e2 = BME_disk_nextedge(v->edge, v); + e1 = v->e; /* we just use the first two edges */ + e2 = BME_disk_nextedge(v->e, v); if (e1 == e2) { //printf("You need at least two edges to use BME_bevel_split_edge()\n"); return NULL; @@ -587,8 +593,8 @@ static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_Tran static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) { BME_Vert *ov1, *ov2, *v1, *v2; - ov1 = BME_edge_getothervert(v->edge, v); - ov2 = BME_edge_getothervert(BME_disk_nextedge(v->edge, v), v); + ov1 = BME_edge_getothervert(v->e, v); + ov2 = BME_edge_getothervert(BME_disk_nextedge(v->e, v), v); /* split the edges */ v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td); @@ -603,7 +609,7 @@ static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, /* remove the original vert */ if (res) { - BME_JEKV(bm,v->edge,v); + BME_JEKV(bm,v->e,v); } return v1; @@ -628,7 +634,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS /* first, check to see if this edge was inset previously */ if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0 && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) { - kl = l->prev->radial.next->data; + kl = l->prev->radial_next; if (kl->v == l->v) kl = kl->prev; else kl = kl->next; kv = l->v; @@ -648,14 +654,14 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS l = l->next; if (kl->v == kv) { BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); - BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); + BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e); BME_collapse_vert(bm, kl->e, kv, 1.0); //BME_JEKV(bm,kl->e,kv); } else { BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); - BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); + BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e); BME_collapse_vert(bm, kl->e, kv, 1.0); //BME_JEKV(bm,kl->e,kv); } @@ -666,7 +672,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS /* first, check to see if this edge was inset previously */ if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0 && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) { - kl = l->next->radial.next->data; + kl = l->next->radial_next; if (kl->v == l->next->v) kl = kl->prev; else kl = kl->next; kv = l->next->v; @@ -685,13 +691,13 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS if (kv) { if (kl->v == kv) { BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); - BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); + BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e); BME_collapse_vert(bm, kl->e, kv, 1.0); //BME_JEKV(bm,kl->e,kv); } else { BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); - BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); + BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e); BME_collapse_vert(bm, kl->e, kv, 1.0); //BME_JEKV(bm,kl->e,kv); } @@ -700,7 +706,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) { BME_split_face(bm,f,v2,v1,&l,e); l->e->tflag1 = BME_BEVEL_BEVEL; - l = l->radial.next->data; + l = l->radial_next; } if (l->f != f){ @@ -866,8 +872,8 @@ static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) BME_Loop *l1, *l2; float vec1[3], vec2[3], vec3[3], vec4[3]; - l1 = e->loop; - l2 = e->loop->radial.next->data; + l1 = e->l; + l2 = e->l->radial_next; if (l1->v == v) { v1 = l1->prev->v; v2 = l1->next->v; @@ -906,7 +912,7 @@ static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){ do{ if(BME_radial_find_face(l->e,f2)) count++; l = l->next; - }while(l != f1->loopbase); + }while(l != f1->lbase); return count; } @@ -951,11 +957,11 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg */ /* get disk cycle length */ - if (v->edge == NULL) { + if (v->e == NULL) { len = 0; } else { - len = BME_cycle_length(BME_disk_getpointer(v->edge,v)); + len = BME_cycle_length(BME_disk_getpointer(v->e,v)); /* we'll assign a default transform data to every vert (except the loose ones) */ vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL); } @@ -1022,13 +1028,13 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg * i.e. the vert's weight is the average of the weights of its weighted edges */ - if (e->loop == NULL) { + if (e->l == NULL) { len = 0; e->v1->tflag1 |= BME_BEVEL_NONMAN; e->v2->tflag1 |= BME_BEVEL_NONMAN; } else { - len = BME_cycle_length(&(e->loop->radial)); + len = BME_cycle_length(&(e->l->radial)); } if (len > 2) { @@ -1092,7 +1098,7 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg for (e=bm->edges.first; e; e=e->next){ if(e->tflag1 & BME_BEVEL_BEVEL){ int count = 0; - count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f); + count = BME_face_sharededges(e->l->f, ((BME_Loop*)e->l->radial_next)->f); if(count > 1){ e->tflag1 &= ~BME_BEVEL_BEVEL; } @@ -1142,26 +1148,26 @@ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){ BME_Edge *e; int done, len; - if(v->edge){ + if(v->e){ done = 0; while(!done){ done = 1; - e = v->edge; /*loop the edge looking for a edge to dissolve*/ + e = v->e; /*loop the edge looking for a edge to dissolve*/ do{ f = NULL; - len = BME_cycle_length(&(e->loop->radial)); + len = BME_cycle_length(&(e->l->radial)); if(len == 2){ - f = BME_JFKE_safe(bm,e->loop->f, ((BME_Loop*)(e->loop->radial.next->data))->f, e); + f = BME_JFKE_safe(bm,e->l->f, ((BME_Loop*)(e->l->radial_next))->f, e); } if(f){ done = 0; break; } e = BME_disk_nextedge(e,v); - }while(e != v->edge); + }while(e != v->e); } - BME_collapse_vert(bm, v->edge, v, 1.0); - //BME_JEKV(bm,v->edge,v); + BME_collapse_vert(bm, v->e, v, 1.0); + //BME_JEKV(bm,v->e,v); } } static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) { @@ -1187,7 +1193,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) { int count = 0; /* first, make sure we're not sitting on an edge to be removed */ - oe = v->edge; + oe = v->e; e = BME_disk_nextedge(oe,v); while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) { e = BME_disk_nextedge(e,v); @@ -1201,7 +1207,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) { count++; /* join the faces (we'll split them later) */ - f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e); + f = BME_JFKE_safe(bm,e->l->f,((BME_Loop*)e->l->radial_next)->f,e); if (!f){ //printf("Non-manifold geometry not getting tagged right?\n"); } @@ -1212,10 +1218,10 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, /* all original edges marked to be beveled have been removed; * now we need to link up the edges for this "corner" */ - len = BME_cycle_length(BME_disk_getpointer(v->edge, v)); - for (i=0,e=v->edge; i < len; i++,e=BME_disk_nextedge(e,v)) { - l = e->loop; - l2 = l->radial.next->data; + len = BME_cycle_length(BME_disk_getpointer(v->e, v)); + for (i=0,e=v->e; i < len; i++,e=BME_disk_nextedge(e,v)) { + l = e->l; + l2 = l->radial_next; if (l->v != v) l = l->next; if (l2->v != v) l2 = l2->next; /* look for faces that have had the original edges removed via JFKE */ @@ -1321,3 +1327,4 @@ BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_ BME_free_transdata(td); return bm; } +#endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ed636e95b96..05c06e86cd0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -42,6 +42,7 @@ #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_memarena.h" +#include "BLI_array.h" #include "BLI_pbvh.h" #include "BLI_utildefines.h" @@ -54,6 +55,9 @@ #include "BKE_paint.h" #include "BKE_texture.h" #include "BKE_multires.h" +#include "BKE_particle.h" +#include "BKE_tessmesh.h" +#include "BKE_bvhutils.h" #include "BLO_sys_types.h" // for intptr_t support @@ -105,9 +109,9 @@ static MFace *dm_getFaceArray(DerivedMesh *dm) if (!mface) { mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, - dm->getNumFaces(dm)); + dm->getNumTessFaces(dm)); CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY); - dm->copyFaceArray(dm, mface); + dm->copyTessFaceArray(dm, mface); } return mface; @@ -135,41 +139,74 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm) static MFace *dm_dupFaceArray(DerivedMesh *dm) { - MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm), + MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm), "dm_dupFaceArray tmp"); - if(tmp) dm->copyFaceArray(dm, tmp); + if(tmp) dm->copyTessFaceArray(dm, tmp); return tmp; } +CustomData *dm_getVertCData(DerivedMesh *dm) +{ + return &dm->vertData; +} + +CustomData *dm_getEdgeCData(DerivedMesh *dm) +{ + return &dm->edgeData; +} + +CustomData *dm_getFaceCData(DerivedMesh *dm) +{ + return &dm->faceData; +} + +CustomData *dm_getLoopCData(DerivedMesh *dm) +{ + return &dm->loopData; +} + +CustomData *dm_getPolyCData(DerivedMesh *dm) +{ + return &dm->polyData; +} + void DM_init_funcs(DerivedMesh *dm) { /* default function implementations */ dm->getVertArray = dm_getVertArray; dm->getEdgeArray = dm_getEdgeArray; - dm->getFaceArray = dm_getFaceArray; + dm->getTessFaceArray = dm_getFaceArray; dm->dupVertArray = dm_dupVertArray; dm->dupEdgeArray = dm_dupEdgeArray; - dm->dupFaceArray = dm_dupFaceArray; + dm->dupTessFaceArray = dm_dupFaceArray; + + dm->getVertDataLayout = dm_getVertCData; + dm->getEdgeDataLayout = dm_getEdgeCData; + dm->getTessFaceDataLayout = dm_getFaceCData; + dm->getLoopDataLayout = dm_getLoopCData; + dm->getFaceDataLayout = dm_getPolyCData; dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; + dm->getTessFaceData = DM_get_face_data; dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getFaceDataArray = DM_get_face_data_layer; + dm->getTessFaceDataArray = DM_get_tessface_data_layer; bvhcache_init(&dm->bvhCache); } -void DM_init(DerivedMesh *dm, DerivedMeshType type, - int numVerts, int numEdges, int numFaces) +void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, + int numFaces, int numLoops, int numPoly) { dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPoly; DM_init_funcs(dm); @@ -177,7 +214,8 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, } void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, - int numVerts, int numEdges, int numFaces) + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys) { CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH, CD_CALLOC, numVerts); @@ -185,11 +223,17 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type CD_CALLOC, numEdges); CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, numFaces); + CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH, + CD_CALLOC, numLoops); + CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH, + CD_CALLOC, numPolys); dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; DM_init_funcs(dm); @@ -204,6 +248,8 @@ int DM_release(DerivedMesh *dm) CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); CustomData_free(&dm->faceData, dm->numFaceData); + CustomData_free(&dm->loopData, dm->numLoopData); + CustomData_free(&dm->polyData, dm->numPolyData); return 1; } @@ -211,28 +257,139 @@ int DM_release(DerivedMesh *dm) CustomData_free_temporary(&dm->vertData, dm->numVertData); CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); CustomData_free_temporary(&dm->faceData, dm->numFaceData); + CustomData_free_temporary(&dm->loopData, dm->numLoopData); + CustomData_free_temporary(&dm->polyData, dm->numPolyData); return 0; } } +void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *dm, int totloop) +{ + DMFaceIter *iter = dm->newFaceIter(dm); + DMLoopIter *liter; + CustomData *oldata, *opdata; + MPoly *mpoly; + MLoop *mloop; + int p, l, i, j, lasttype; + + oldata = dm->getLoopDataLayout(dm); + opdata = dm->getFaceDataLayout(dm); + + CustomData_copy(oldata, ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, totloop); + CustomData_copy(opdata, pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->getNumFaces(dm)); + + mloop = MEM_callocN(sizeof(MLoop)*totloop, "MLoop from dm_add_polys_from_iter"); + CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); + mpoly = MEM_callocN(sizeof(MPoly)*dm->getNumFaces(dm), "MPoly from dm_add_polys_from_iter"); + CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, dm->getNumFaces(dm)); + + l = 0; + for (p=0; !iter->done; iter->step(iter), mpoly++, p++) { + mpoly->flag = iter->flags; + mpoly->loopstart = l; + mpoly->totloop = iter->len; + mpoly->mat_nr = iter->mat_nr; + + j = 0; + lasttype = -1; + for (i=0; i<opdata->totlayer; i++) { + void *e1, *e2; + + if (opdata->layers[i].type == lasttype) + j++; + else + j = 0; + + if (opdata->layers[i].type == CD_MPOLY) + continue; + + e1 = iter->getCDData(iter, opdata->layers[i].type, j); + e2 = (char*)CustomData_get_n(pdata, opdata->layers[i].type, p, j); + + if (!e2) + continue; + + CustomData_copy_elements(opdata->layers[i].type, e1, e2, 1); + + lasttype = opdata->layers[i].type; + } + + liter = iter->getLoopsIter(iter); + for (; !liter->done; liter->step(liter), mloop++, l++) { + mloop->v = liter->vindex; + mloop->e = liter->eindex; + + j = 0; + lasttype = -1; + for (i=0; i<oldata->totlayer; i++) { + void *e1, *e2; + + if (oldata->layers[i].type == CD_MLOOP) + continue; + + if (oldata->layers[i].type == lasttype) + j++; + else + j = 0; + + e1 = liter->getLoopCDData(liter, oldata->layers[i].type, j); + e2 = CustomData_get_n(ldata, oldata->layers[i].type, l, j); + + if (!e2) + continue; + + CustomData_copy_elements(oldata->layers[i].type, e1, e2, 1); + lasttype = oldata->layers[i].type; + } + } + } + iter->free(iter); +} + +void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) +{ + DMFaceIter *iter = source->newFaceIter(source); + DMLoopIter *liter; + int totloop = source->numLoopData; + + dm_add_polys_from_iter(&target->loopData, &target->polyData, source, totloop); + + target->numLoopData = totloop; + target->numPolyData = source->getNumFaces(source); +} + void DM_to_mesh(DerivedMesh *dm, Mesh *me) { /* dm might depend on me, so we need to do everything with a local copy */ Mesh tmp = *me; - int totvert, totedge, totface; + DMFaceIter *iter; + int totvert, totedge, totface, totloop, totpoly; memset(&tmp.vdata, 0, sizeof(tmp.vdata)); memset(&tmp.edata, 0, sizeof(tmp.edata)); memset(&tmp.fdata, 0, sizeof(tmp.fdata)); + memset(&tmp.ldata, 0, sizeof(tmp.ldata)); + memset(&tmp.pdata, 0, sizeof(tmp.pdata)); totvert = tmp.totvert = dm->getNumVerts(dm); totedge = tmp.totedge = dm->getNumEdges(dm); - totface = tmp.totface = dm->getNumFaces(dm); + totface = tmp.totface = dm->getNumTessFaces(dm); + totpoly = tmp.totpoly = dm->getNumFaces(dm); + + totloop = 0; + for (iter=dm->newFaceIter(dm); !iter->done; iter->step(iter)) { + totloop += iter->len; + } + iter->free(iter); + + tmp.totloop = totloop; CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert); CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge); CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface); + CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop); + CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly); /* not all DerivedMeshes store their verts/edges/faces in CustomData, so we set them here in case they are missing */ @@ -241,7 +398,9 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) if(!CustomData_has_layer(&tmp.edata, CD_MEDGE)) CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge); if(!CustomData_has_layer(&tmp.fdata, CD_MFACE)) - CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface); + CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupTessFaceArray(dm), totface); + if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) + dm_add_polys_from_iter(&tmp.ldata, &tmp.pdata, dm, totloop); /* object had got displacement layer, should copy this layer to save sculpted data */ /* NOTE: maybe some other layers should be copied? nazgul */ @@ -257,9 +416,14 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); - /* if the number of verts has changed, remove invalid data */ + /* BMESH_TODO/XXX: ok, this should use new CD shapekey data, + which shouuld be fed through the modifier + stack*/ if(tmp.totvert != me->totvert) { + printf("YEEK! this should be recoded! Shape key loss!!!\n"); if(tmp.key) tmp.key->id.us--; tmp.key = NULL; } @@ -304,11 +468,21 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer) CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData); } -void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer) { CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData); } +void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +{ + CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData); +} + +void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +{ + CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData); +} + void *DM_get_vert_data(DerivedMesh *dm, int index, int type) { return CustomData_get(&dm->vertData, index, type); @@ -340,14 +514,19 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type) return CustomData_get_layer(&dm->edgeData, type); } -void *DM_get_face_data_layer(DerivedMesh *dm, int type) +void *DM_get_tessface_data_layer(DerivedMesh *dm, int type) { if(type == CD_MFACE) - return dm->getFaceArray(dm); + return dm->getTessFaceArray(dm); return CustomData_get_layer(&dm->faceData, type); } +void *DM_get_face_data_layer(DerivedMesh *dm, int type) +{ + return CustomData_get_layer(&dm->polyData, type); +} + void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data) { CustomData_set(&dm->vertData, index, type, data); @@ -377,13 +556,27 @@ void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest, source_index, dest_index, count); } -void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest, +void DM_copy_tessface_data(DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count) { CustomData_copy_data(&source->faceData, &dest->faceData, source_index, dest_index, count); } +void DM_copy_loop_data(DerivedMesh *source, DerivedMesh *dest, + int source_index, int dest_index, int count) +{ + CustomData_copy_data(&source->loopData, &dest->loopData, + source_index, dest_index, count); +} + +void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest, + int source_index, int dest_index, int count) +{ + CustomData_copy_data(&source->polyData, &dest->polyData, + source_index, dest_index, count); +} + void DM_free_vert_data(struct DerivedMesh *dm, int index, int count) { CustomData_free_elem(&dm->vertData, index, count); @@ -394,11 +587,21 @@ void DM_free_edge_data(struct DerivedMesh *dm, int index, int count) CustomData_free_elem(&dm->edgeData, index, count); } -void DM_free_face_data(struct DerivedMesh *dm, int index, int count) +void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count) { CustomData_free_elem(&dm->faceData, index, count); } +void DM_free_loop_data(struct DerivedMesh *dm, int index, int count) +{ + CustomData_free_elem(&dm->loopData, index, count); +} + +void DM_free_face_data(struct DerivedMesh *dm, int index, int count) +{ + CustomData_free_elem(&dm->polyData, index, count); +} + void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest, int *src_indices, float *weights, int count, int dest_index) @@ -416,7 +619,7 @@ void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest, weights, (float*)vert_weights, count, dest_index); } -void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, +void DM_interp_tessface_data(DerivedMesh *source, DerivedMesh *dest, int *src_indices, float *weights, FaceVertWeight *vert_weights, int count, int dest_index) @@ -425,13 +628,28 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, weights, (float*)vert_weights, count, dest_index); } -void DM_swap_face_data(DerivedMesh *dm, int index, const int *corner_indices) +void DM_swap_tessface_data(DerivedMesh *dm, int index, const int *corner_indices) { CustomData_swap(&dm->faceData, index, corner_indices); } -/// +void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index) +{ + CustomData_interp(&source->loopData, &dest->loopData, src_indices, + weights, NULL, count, dest_index); +} +void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index) +{ + CustomData_interp(&source->polyData, &dest->polyData, src_indices, + weights, NULL, count, dest_index); +} + +/// DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -447,988 +665,6 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) return dm; } -/// - -typedef struct { - DerivedMesh dm; - - EditMesh *em; - float (*vertexCos)[3]; - float (*vertexNos)[3]; - float (*faceNos)[3]; -} EditMeshDerivedMesh; - -static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) { - if (emdm->vertexCos) { - func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL); - } else { - func(userData, i, eve->co, eve->no, NULL); - } - } -} -static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) - func(userData, i, emdm->vertexCos[(int) eed->v1->tmp.l], emdm->vertexCos[(int) eed->v2->tmp.l]); - } else { - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) - func(userData, i, eed->v1->co, eed->v2->co); - } -} -static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - glBegin(GL_LINES); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); - } - } - glEnd(); - } else { - glBegin(GL_LINES); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} -static void emDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges)) -{ - emDM_drawMappedEdges(dm, NULL, NULL); -} -static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); - } - } - glEnd(); - } else { - glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(eed->v1->co); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} - -static void emDM_drawUVEdges(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; - MTFace *tf; - - glBegin(GL_LINES); - for(efa= emdm->em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE); - - if(tf && !(efa->h)) { - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - - if (!efa->v4) { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[0]); - } else { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[0]); - } - } - } - glEnd(); -} - -static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3]) -{ - if (vertexCos) { - VECCOPY(cent, vertexCos[(int) efa->v1->tmp.l]); - add_v3_v3(cent, vertexCos[(int) efa->v2->tmp.l]); - add_v3_v3(cent, vertexCos[(int) efa->v3->tmp.l]); - if (efa->v4) add_v3_v3(cent, vertexCos[(int) efa->v4->tmp.l]); - } else { - VECCOPY(cent, efa->v1->co); - add_v3_v3(cent, efa->v2->co); - add_v3_v3(cent, efa->v3->co); - if (efa->v4) add_v3_v3(cent, efa->v4->co); - } - - if (efa->v4) { - mul_v3_fl(cent, 0.25f); - } else { - mul_v3_fl(cent, 0.33333333333f); - } -} -static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - EditFace *efa; - float cent[3]; - int i; - - if (emdm->vertexCos) { - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - } - - for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - emDM__calcFaceCent(efa, cent, emdm->vertexCos); - func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n); - } -} - -/* note, material function is ignored for now. */ -static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs)) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; - int i, draw; - - (void)setMaterial; /* unused */ - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if(draw) { - if (draw==2) { /* enabled with stipple */ - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(emdm->faceNos[i]); - glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]); - if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]); - } else { - glNormal3fv(emdm->vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]); - glNormal3fv(emdm->vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]); - glNormal3fv(emdm->vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]); - if(efa->v4) { - glNormal3fv(emdm->vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]); - } - } - glEnd(); - - if (draw==2) - glDisable(GL_POLYGON_STIPPLE); - } - } - } else { - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if(draw) { - if (draw==2) { /* enabled with stipple */ - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->n); - glVertex3fv(efa->v1->co); - glVertex3fv(efa->v2->co); - glVertex3fv(efa->v3->co); - if(efa->v4) glVertex3fv(efa->v4->co); - } else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - if(efa->v4) { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - glEnd(); - - if (draw==2) - glDisable(GL_POLYGON_STIPPLE); - } - } - } -} - -static void emDM_drawFacesTex_common(DerivedMesh *dm, - int (*drawParams)(MTFace *tface, MCol *mcol, int matnr), - int (*drawParamsMapped)(void *userData, int index), - void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - EditFace *efa; - int i; - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - if (vertexCos) { - EditVert *eve; - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - unsigned char *cp= NULL; - int drawSmooth= (efa->flag & ME_SMOOTH); - int flag; - - if(drawParams) - flag= drawParams(tf, mcol, efa->mat_nr); - else if(drawParamsMapped) - flag= drawParamsMapped(userData, i); - else - flag= 1; - - if(flag != 0) { /* flag 0 == the face is hidden or invisible */ - - /* we always want smooth here since otherwise vertex colors dont interpolate */ - if (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } else { - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - } - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(emdm->faceNos[i]); - - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - } else { - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - } - glEnd(); - } - } - } else { - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - unsigned char *cp= NULL; - int drawSmooth= (efa->flag & ME_SMOOTH); - int flag; - - if(drawParams) - flag= drawParams(tf, mcol, efa->mat_nr); - else if(drawParamsMapped) - flag= drawParamsMapped(userData, i); - else - flag= 1; - - if(flag != 0) { /* flag 0 == the face is hidden or invisible */ - /* we always want smooth here since otherwise vertex colors dont interpolate */ - if (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } else { - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - } - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->n); - - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(efa->v1->co); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3fv(efa->v2->co); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3fv(efa->v3->co); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3fv(efa->v4->co); - } - } else { - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - glEnd(); - } - } - } -} - -static void emDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr)) -{ - emDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); -} - -static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) -{ - emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); -} - -static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs), - int (*setDrawOptions)(void *userData, int index), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - EditVert *eve; - EditFace *efa; - DMVertexAttribs attribs; - GPUVertexAttribs gattribs; - MTFace *tf; - int transp, new_transp, orig_transp, tfoffset; - int i, b, matnr, new_matnr, dodraw, layer; - - dodraw = 0; - matnr = -1; - - transp = GPU_get_material_blend_mode(); - orig_transp = transp; - layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); - tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; - - memset(&attribs, 0, sizeof(attribs)); - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - -#define PASSATTRIB(efa, eve, vert) { \ - if(attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ - glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ - } \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[i*4 + vert]; \ - glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ - } \ -} - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth= (efa->flag & ME_SMOOTH); - - if(setDrawOptions && !setDrawOptions(userData, i)) - continue; - - new_matnr = efa->mat_nr + 1; - if(new_matnr != matnr) { - dodraw = setMaterial(matnr = new_matnr, &gattribs); - if(dodraw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - if(tfoffset != -1) { - tf = (MTFace*)((char*)efa->data)+tfoffset; - new_transp = tf->transp; - - if(new_transp != transp) { - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - - if(dodraw) { - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - if(vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); - - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - else glVertex3fv(efa->v3->co); - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - else glVertex3fv(efa->v4->co); - } - } else { - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - } - else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - } - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - } - else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - } - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - } - else { - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - } - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - else { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - } - glEnd(); - } - } -} - -static void emDM_drawFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - if (emdm->em->verts.first) { - for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) { - if (emdm->vertexCos) { - DO_MINMAX(emdm->vertexCos[i], min_r, max_r); - } else { - DO_MINMAX(eve->co, min_r, max_r); - } - } - } else { - min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; - } -} -static int emDM_getNumVerts(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->verts); -} - -static int emDM_getNumEdges(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->edges); -} - -static int emDM_getNumFaces(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->faces); -} - -static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) { - if (emdm->vertexCos) { - copy_v3_v3(cos_r[i], emdm->vertexCos[i]); - } else { - copy_v3_v3(cos_r[i], eve->co); - } - } -} - -static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) -{ - EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first; - int i; - - for(i = 0; i < index; ++i) ev = ev->next; - - VECCOPY(vert_r->co, ev->co); - - vert_r->no[0] = ev->no[0] * 32767.0; - vert_r->no[1] = ev->no[1] * 32767.0; - vert_r->no[2] = ev->no[2] * 32767.0; - - /* TODO what to do with vert_r->flag? */ - vert_r->bweight = (unsigned char) (ev->bweight*255.0f); -} - -static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditEdge *ee = em->edges.first; - EditVert *ev, *v1, *v2; - int i; - - for(i = 0; i < index; ++i) ee = ee->next; - - edge_r->crease = (unsigned char) (ee->crease*255.0f); - edge_r->bweight = (unsigned char) (ee->bweight*255.0f); - /* TODO what to do with edge_r->flag? */ - edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; - if (ee->seam) edge_r->flag |= ME_SEAM; - if (ee->sharp) edge_r->flag |= ME_SHARP; -#if 0 - /* this needs setup of f2 field */ - if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; -#endif - - /* goddamn, we have to search all verts to find indices */ - v1 = ee->v1; - v2 = ee->v2; - for(i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) { - if(ev == v1) { - edge_r->v1 = i; - v1 = NULL; - } - if(ev == v2) { - edge_r->v2 = i; - v2 = NULL; - } - } -} - -static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditFace *ef = em->faces.first; - EditVert *ev, *v1, *v2, *v3, *v4; - int i; - - for(i = 0; i < index; ++i) ef = ef->next; - - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; - - /* goddamn, we have to search all verts to find indices */ - v1 = ef->v1; - v2 = ef->v2; - v3 = ef->v3; - v4 = ef->v4; - if(!v4) face_r->v4 = 0; - - for(i = 0, ev = em->verts.first; v1 || v2 || v3 || v4; - i++, ev = ev->next) { - if(ev == v1) { - face_r->v1 = i; - v1 = NULL; - } - if(ev == v2) { - face_r->v2 = i; - v2 = NULL; - } - if(ev == v3) { - face_r->v3 = i; - v3 = NULL; - } - if(ev == v4) { - face_r->v4 = i; - v4 = NULL; - } - } - - test_index_face(face_r, NULL, 0, ef->v4?4:3); -} - -static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *ev = emdm->em->verts.first; - int i; - - for(i=0; ev; ev = ev->next, ++vert_r, ++i) { - if(emdm->vertexCos) - copy_v3_v3(vert_r->co, emdm->vertexCos[i]); - else - copy_v3_v3(vert_r->co, ev->co); - - vert_r->no[0] = ev->no[0] * 32767.0; - vert_r->no[1] = ev->no[1] * 32767.0; - vert_r->no[2] = ev->no[2] * 32767.0; - - /* TODO what to do with vert_r->flag? */ - vert_r->flag = 0; - vert_r->bweight = (unsigned char) (ev->bweight*255.0f); - } -} - -static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditEdge *ee = em->edges.first; - EditVert *ev; - int i; - - /* store vertex indices in tmp union */ - for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i) - ev->tmp.l = (intptr_t) i; - - for( ; ee; ee = ee->next, ++edge_r) { - edge_r->crease = (unsigned char) (ee->crease*255.0f); - edge_r->bweight = (unsigned char) (ee->bweight*255.0f); - /* TODO what to do with edge_r->flag? */ - edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; - if (ee->seam) edge_r->flag |= ME_SEAM; - if (ee->sharp) edge_r->flag |= ME_SHARP; -#if 0 - /* this needs setup of f2 field */ - if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; -#endif - - edge_r->v1 = (int)ee->v1->tmp.l; - edge_r->v2 = (int)ee->v2->tmp.l; - } -} - -static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditFace *ef = em->faces.first; - EditVert *ev; - int i; - - /* store vertexes indices in tmp union */ - for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i) - ev->tmp.l = (intptr_t) i; - - for( ; ef; ef = ef->next, ++face_r) { - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; - - face_r->v1 = (int)ef->v1->tmp.l; - face_r->v2 = (int)ef->v2->tmp.l; - face_r->v3 = (int)ef->v3->tmp.l; - if(ef->v4) face_r->v4 = (int)ef->v4->tmp.l; - else face_r->v4 = 0; - - test_index_face(face_r, NULL, 0, ef->v4?4:3); - } -} - -static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - EditFace *efa; - char *data, *emdata; - void *datalayer; - int index, size; - - datalayer = DM_get_face_data_layer(dm, type); - if(datalayer) - return datalayer; - - /* layers are store per face for editmesh, we convert to a temporary - * data layer array in the derivedmesh when these are requested */ - if(type == CD_MTFACE || type == CD_MCOL) { - index = CustomData_get_layer_index(&em->fdata, type); - - if(index != -1) { - /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */ - size = CustomData_sizeof(type); - - DM_add_face_layer(dm, type, CD_CALLOC, NULL); - index = CustomData_get_layer_index(&dm->faceData, type); - dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; - - data = datalayer = DM_get_face_data_layer(dm, type); - for(efa=em->faces.first; efa; efa=efa->next, data+=size) { - emdata = CustomData_em_get(&em->fdata, efa->data, type); - memcpy(data, emdata, size); - } - } - } - - return datalayer; -} - -static void emDM_release(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - if (DM_release(dm)) { - if (emdm->vertexCos) { - MEM_freeN(emdm->vertexCos); - MEM_freeN(emdm->vertexNos); - MEM_freeN(emdm->faceNos); - } - - MEM_freeN(emdm); - } -} - -DerivedMesh *editmesh_get_derived(EditMesh *em, float (*vertexCos)[3]) -{ - EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm"); - - DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts), - BLI_countlist(&em->edges), BLI_countlist(&em->faces)); - - emdm->dm.getMinMax = emDM_getMinMax; - - emdm->dm.getNumVerts = emDM_getNumVerts; - emdm->dm.getNumEdges = emDM_getNumEdges; - emdm->dm.getNumFaces = emDM_getNumFaces; - - emdm->dm.getVertCos = emDM_getVertCos; - - emdm->dm.getVert = emDM_getVert; - emdm->dm.getEdge = emDM_getEdge; - emdm->dm.getFace = emDM_getFace; - emdm->dm.copyVertArray = emDM_copyVertArray; - emdm->dm.copyEdgeArray = emDM_copyEdgeArray; - emdm->dm.copyFaceArray = emDM_copyFaceArray; - emdm->dm.getFaceDataArray = emDM_getFaceDataArray; - - emdm->dm.foreachMappedVert = emDM_foreachMappedVert; - emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; - emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; - - emdm->dm.drawEdges = emDM_drawEdges; - emdm->dm.drawMappedEdges = emDM_drawMappedEdges; - emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; - emdm->dm.drawMappedFaces = emDM_drawMappedFaces; - emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; - emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; - emdm->dm.drawFacesTex = emDM_drawFacesTex; - emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; - emdm->dm.drawUVEdges = emDM_drawUVEdges; - - emdm->dm.release = emDM_release; - - emdm->em = em; - emdm->vertexCos = vertexCos; - - if(CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { - EditVert *eve; - int i; - - DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL); - - for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i) - DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT, - CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT)); - } - - if(vertexCos) { - EditVert *eve; - EditFace *efa; - int totface = BLI_countlist(&em->faces); - int i; - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno"); - emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno"); - - for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) { - float *v1 = vertexCos[(int) efa->v1->tmp.l]; - float *v2 = vertexCos[(int) efa->v2->tmp.l]; - float *v3 = vertexCos[(int) efa->v3->tmp.l]; - float *no = emdm->faceNos[i]; - - if(efa->v4) { - float *v4 = vertexCos[(int) efa->v4->tmp.l]; - - normal_quad_v3( no,v1, v2, v3, v4); - add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no); - } - else { - normal_tri_v3( no,v1, v2, v3); - } - - add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no); - add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no); - add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no); - } - - for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) { - float *no = emdm->vertexNos[i]; - /* following Mesh convention; we use vertex coordinate itself - * for normal in this case */ - if (normalize_v3(no)==0.0) { - normalize_v3_v3(no, vertexCos[i]); - } - } - } - - return (DerivedMesh*) emdm; -} - /***/ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md) @@ -1460,30 +696,29 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier return dm; } -static float *get_editmesh_orco_verts(EditMesh *em) +static float *get_editbmesh_orco_verts(BMEditMesh *em) { - EditVert *eve; + BMIter iter; + BMVert *eve; float *orco; int a, totvert; /* these may not really be the orco's, but it's only for preview. * could be solver better once, but isn't simple */ - totvert= 0; - for(eve=em->verts.first; eve; eve=eve->next) - totvert++; + totvert= em->bm->totvert; orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco"); - for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3) + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (a=0; eve; eve=BMIter_Step(&iter), a+=3) VECCOPY(orco+a, eve->co); return orco; } /* orco custom data layer */ - -static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free) +static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free) { *free= 0; @@ -1492,7 +727,7 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free) *free= 1; if(em) - return (float(*)[3])get_editmesh_orco_verts(em); + return (float(*)[3])get_editbmesh_orco_verts(em); else return (float(*)[3])get_mesh_orco_verts(ob); } @@ -1513,13 +748,13 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free) return NULL; } -static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em, int layer) +static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int layer) { DerivedMesh *dm; float (*orco)[3]; int free; - if(em) dm= CDDM_from_editmesh(em, me); + if(em) dm= CDDM_from_BMEditMesh(em, me); else dm= CDDM_from_mesh(me, ob); orco= get_orco_coords_dm(ob, em, layer, &free); @@ -1534,7 +769,8 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em, int layer return dm; } -static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm, int layer) +static void add_orco_dm(Object *ob, BMEditMesh *em, DerivedMesh *dm, + DerivedMesh *orcodm, int layer) { float (*orco)[3], (*layerorco)[3]; int totvert, free; @@ -1638,15 +874,21 @@ void vDM_ColorBand_store(ColorBand *coba) static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm) { Mesh *me = ob->data; - MFace *mf = me->mface; + MFace *mf = dm->getTessFaceArray(dm); + DMFaceIter *dfiter; + DMLoopIter *dliter; ColorBand *coba= stored_cb; /* warning, not a local var */ unsigned char *wtcol; - int i; + unsigned char(*wlcol)[4] = NULL; + BLI_array_declare(wlcol); + int i, totface=dm->getNumTessFaces(dm), totpoly=dm->getNumFaces, totloop; + int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX); - wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap"); + wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap"); - memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4); - for (i=0; i<me->totface; i++, mf++) { + /*first add colors to the tesselation faces*/ + memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4); + for (i=0; i<totface; i++, mf++) { calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); @@ -1654,7 +896,23 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm) calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); } - CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData); + CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface); + + /*now add to loops, so the data can be passed through the modifier stack*/ + totloop = 0; + dfiter = dm->newFaceIter(dm); + for (; !dfiter->done; dfiter->step(dfiter)) { + dliter = dfiter->getLoopsIter(dfiter); + for (; !dliter->done; dliter->step(dliter), totloop++) { + BLI_array_growone(wlcol); + calc_weightpaint_vert_color(ob, coba, dliter->vindex, (unsigned +char *)&wlcol[totloop]); + } + } + + CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop); + + dfiter->free(dfiter); } /* new value for useDeform -1 (hack for the gameengine): @@ -1835,7 +1093,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* apply vertex coordinates or build a DerivedMesh as necessary */ if(dm) { if(deformedVerts) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); dm->release(dm); dm = tdm; @@ -1861,14 +1119,19 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos * data by using generic DM_copy_vert_data() functions. */ if(needMapping || (nextmask & CD_MASK_ORIGINDEX)) { + int i, *orig; + /* calc */ DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - range_vni(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); - range_vni(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0); + orig = DM_get_vert_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numVertData; i++) *orig++= i; + orig = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numEdgeData; i++) *orig++= i; + orig = DM_get_face_data_layer(dm, CD_ORIGINDEX); + for(i=0; i<dm->numPolyData; i++) *orig++= i; } } @@ -1884,7 +1147,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* add an origspace layer if needed */ if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) - DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); + DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); ndm = mti->applyModifier(md, ob, dm, useRenderParams, useCache); @@ -1953,7 +1216,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos * DerivedMesh then we need to build one. */ if(dm && deformedVerts) { - finaldm = CDDM_copy(dm); + finaldm = CDDM_copy(dm, 0); dm->release(dm); @@ -1997,21 +1260,24 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos BLI_linklist_free(datamasks, NULL); } -float (*editmesh_get_vertex_cos(EditMesh *em, int *numVerts_r))[3] +float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3] { - int i, numVerts = *numVerts_r = BLI_countlist(&em->verts); + int i, numVerts = *numVerts_r = em->bm->totvert; float (*cos)[3]; - EditVert *eve; + BMIter iter; + BMVert *eve; cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos"); - for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) { + + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { VECCOPY(cos[i], eve->co); } return cos; } -int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) +int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -2025,7 +1291,7 @@ int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm return 1; } -static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r, +static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r, DerivedMesh **final_r, CustomDataMask dataMask) { @@ -2040,7 +1306,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri modifiers_clearErrors(ob); if(cage_r && cageIndex == -1) { - *cage_r = editmesh_get_derived(em, NULL); + *cage_r = getEditDerivedBMesh(em, ob, NULL); } dm = NULL; @@ -2054,7 +1320,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri md->scene= scene; - if(!editmesh_modifier_is_enabled(scene, md, dm)) + if(!editbmesh_modifier_is_enabled(scene, md, dm)) continue; /* add an orco layer if needed by this modifier */ @@ -2082,7 +1348,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv"); dm->getVertCos(dm, deformedVerts); } else { - deformedVerts = editmesh_get_vertex_cos(em, &numVerts); + deformedVerts = editbmesh_get_vertex_cos(em, &numVerts); } } @@ -2095,7 +1361,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri /* apply vertex coordinates or build a DerivedMesh as necessary */ if(dm) { if(deformedVerts) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); if(!(cage_r && dm == *cage_r)) dm->release(dm); dm = tdm; @@ -2104,11 +1370,11 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri } else if(cage_r && dm == *cage_r) { /* dm may be changed by this modifier, so we need to copy it */ - dm = CDDM_copy(dm); + dm = CDDM_copy(dm, 0); } } else { - dm = CDDM_from_editmesh(em, ob->data); + dm = CDDM_from_BMEditMesh(em, ob->data); if(deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -2144,7 +1410,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri if(mask & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) - DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); + DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); if (mti->applyModifierEM) ndm = mti->applyModifierEM(md, ob, em, dm); @@ -2166,13 +1432,13 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri if(cage_r && i == cageIndex) { if(dm && deformedVerts) { - *cage_r = CDDM_copy(dm); + *cage_r = CDDM_copy(dm, 0); CDDM_apply_vert_coords(*cage_r, deformedVerts); } else if(dm) { *cage_r = dm; } else { *cage_r = - editmesh_get_derived(em, + getEditDerivedBMesh(em, ob, deformedVerts ? MEM_dupallocN(deformedVerts) : NULL); } } @@ -2185,7 +1451,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri * then we need to build one. */ if(dm && deformedVerts) { - *final_r = CDDM_copy(dm); + *final_r = CDDM_copy(dm, 0); if(!(cage_r && dm == *cage_r)) dm->release(dm); @@ -2196,7 +1462,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri } else if (!deformedVerts && cage_r && *cage_r) { *final_r = *cage_r; } else { - *final_r = editmesh_get_derived(em, deformedVerts); + *final_r = getEditDerivedBMesh(em, ob, deformedVerts); deformedVerts = NULL; } @@ -2263,7 +1529,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) ob->lastDataMask = dataMask; } -static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask) +static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask) { clear_mesh_caches(obedit); @@ -2280,7 +1546,7 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust em->derivedCage = NULL; } - editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask); + editbmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask); DM_set_object_boundbox (obedit, em->derivedFinal); em->lastDataMask = dataMask; @@ -2288,10 +1554,10 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust em->derivedCage->needsFree = 0; } -void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask) +void makeDerivedMesh(Scene *scene, Object *ob, BMEditMesh *em, CustomDataMask dataMask) { if (em) { - editmesh_build_data(scene, ob, em, dataMask); + editbmesh_build_data(scene, ob, em, dataMask); } else { mesh_build_data(scene, ob, dataMask); } @@ -2391,7 +1657,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, /***/ -DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r, +DerivedMesh *editbmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, BMEditMesh *em, DerivedMesh **final_r, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include @@ -2399,27 +1665,27 @@ DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, E */ if(!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) - editmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(scene, obedit, em, dataMask); *final_r = em->derivedFinal; return em->derivedCage; } -DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask) +DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ if(!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) - editmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(scene, obedit, em, dataMask); return em->derivedCage; } -DerivedMesh *editmesh_get_derived_base(Object *UNUSED(obedit), EditMesh *em) +DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em) { - return editmesh_get_derived(em, NULL); + return getEditDerivedBMesh(em, obedit, NULL); } @@ -2603,15 +1869,15 @@ void DM_add_tangent_layer(DerivedMesh *dm) if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) return; - nors = dm->getFaceDataArray(dm, CD_NORMAL); + nors = dm->getTessFaceDataArray(dm, CD_NORMAL); /* check we have all the needed layers */ totvert= dm->getNumVerts(dm); - totface= dm->getNumFaces(dm); + totface= dm->getNumTessFaces(dm); mvert= dm->getVertArray(dm); - mface= dm->getFaceArray(dm); - mtface= dm->getFaceDataArray(dm, CD_MTFACE); + mface= dm->getTessFaceArray(dm); + mtface= dm->getTessFaceDataArray(dm, CD_MTFACE); if(!mtface) { orco= dm->getVertDataArray(dm, CD_ORCO); @@ -2620,8 +1886,8 @@ void DM_add_tangent_layer(DerivedMesh *dm) } /* create tangent layer */ - DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL); - tangent= DM_get_face_data_layer(dm, CD_TANGENT); + DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL); + tangent= DM_get_tessface_data_layer(dm, CD_TANGENT); /* allocate some space */ arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena"); @@ -2747,15 +2013,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, memset(attribs, 0, sizeof(DMVertexAttribs)); vdata = &dm->vertData; - fdata = &dm->faceData; - - /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we - * can use offsets instead */ - if(dm->release == emDM_release) - tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; - else - tfdata = fdata; - + fdata = tfdata = dm->getTessFaceDataLayout(dm); + /* add a tangent layer if necessary */ for(b = 0; b < gattribs->totlayer; b++) if(gattribs->layer[b].type == CD_TANGENT) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index a8c369a9b7b..5842197da48 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -47,6 +47,8 @@ #include "DNA_key_types.h" #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_view3d_types.h" #include "DNA_vfont_types.h" #include "BKE_animsys.h" @@ -64,6 +66,7 @@ #include "BKE_particle.h" #include "BKE_scene.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "BKE_depsgraph.h" #include "BKE_anim.h" @@ -880,7 +883,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; - EditMesh *em; + BMEditMesh *em; float vec[3], no[3], pmat[4][4]; int totvert, a, oblay; unsigned int lay; @@ -890,11 +893,10 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; if(em) { - dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - BKE_mesh_end_editmesh(me, em); + dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); } else dm= mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); @@ -956,7 +958,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - if(me->edit_mesh) { + if(me->edit_btmesh) { dm->foreachMappedVert(dm, vertex_dupli__mapFunc, (void*) &vdd); } else { @@ -1005,34 +1007,31 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; - EditMesh *em; + BMEditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; copy_m4_m4(pmat, par->obmat); - - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; + if(em) { int totvert; + dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - - totface= dm->getNumFaces(dm); + totface= dm->getNumTessFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); - dm->copyFaceArray(dm, mface); + dm->copyTessFaceArray(dm, mface); totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); - - BKE_mesh_end_editmesh(me, em); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); - totface= dm->getNumFaces(dm); - mface= dm->getFaceArray(dm); + totface= dm->getNumTessFaces(dm); + mface= dm->getTessFaceArray(dm); mvert= dm->getVertArray(dm); } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 49c151947a4..b9ff4c2a30b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "DNA_anim_types.h" diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e34b4bef8d4..0556acbdece 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -448,6 +448,8 @@ static int read_undosave(bContext *C, UndoElem *uel) BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */ + strcpy(mainstr, G.main->name); /* temporal store */ + fileflags= G.fileflags; G.fileflags |= G_FILE_NO_UI; @@ -675,10 +677,18 @@ char *BKE_undo_menu_string(void) /* saves quit.blend */ void BKE_undo_save_quit(void) { + char str[FILE_MAXDIR+FILE_MAXFILE]; + + BLI_make_file_string("/", str, btempdir, "quit.blend"); + + BKE_undo_save(str); +} + +void BKE_undo_save(char *fname) +{ UndoElem *uel; MemFileChunk *chunk; int file; - char str[FILE_MAXDIR+FILE_MAXFILE]; if( (U.uiflag & USER_GLOBALUNDO)==0) return; @@ -691,9 +701,7 @@ void BKE_undo_save_quit(void) /* no undo state to save */ if(undobase.first==undobase.last) return; - BLI_make_file_string("/", str, btempdir, "quit.blend"); - - file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); + file = open(fname, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); if(file == -1) { //XXX error("Unable to save %s, check you have permissions", str); return; @@ -707,8 +715,8 @@ void BKE_undo_save_quit(void) close(file); - if(chunk) ; //XXX error("Unable to save %s, internal error", str); - else printf("Saved session recovery to %s\n", str); + if(chunk) ; //XXX error("Unable to save %s, internal error", fname); + else printf("Saved session recovery to %s\n", fname); } /* sets curscene */ diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c new file mode 100644 index 00000000000..f9df0beca7c --- /dev/null +++ b/source/blender/blenkernel/intern/booleanops.c @@ -0,0 +1,603 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * CSG operations. + */ + +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_ghash.h" + +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "CSG_BooleanOps.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + + + +/** + * Here's the vertex iterator structure used to walk through + * the blender vertex structure. + */ + +typedef struct { + DerivedMesh *dm; + Object *ob; + int pos; +} VertexIt; + +/** + * Implementations of local vertex iterator functions. + * These describe a blender mesh to the CSG module. + */ + +static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator) +{ + if (iterator->it) { + // deallocate memory for iterator + MEM_freeN(iterator->it); + iterator->it = 0; + } + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; + +} + +static int VertexIt_Done(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm)); +} + +static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert) +{ + VertexIt * iterator = (VertexIt *)it; + MVert *verts = iterator->dm->getVertArray(iterator->dm); + + float global_pos[3]; + + /* boolean happens in global space, transform both with obmat */ + mul_v3_m4v3( + global_pos, + iterator->ob->obmat, + verts[iterator->pos].co + ); + + vert->position[0] = global_pos[0]; + vert->position[1] = global_pos[1]; + vert->position[2] = global_pos[2]; +} + +static void VertexIt_Step(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + iterator->pos ++; +} + +static void VertexIt_Reset(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + iterator->pos = 0; +} + +static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob) +{ + + VertexIt *it; + if (output == 0) return; + + // allocate some memory for blender iterator + it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt")); + if (it == 0) { + return; + } + // assign blender specific variables + it->dm = dm; + it->ob = ob; // needed for obmat transformations + + it->pos = 0; + + // assign iterator function pointers. + output->Step = VertexIt_Step; + output->Fill = VertexIt_Fill; + output->Done = VertexIt_Done; + output->Reset = VertexIt_Reset; + output->num_elements = it->dm->getNumVerts(it->dm); + output->it = it; +} + +/** + * Blender Face iterator + */ + +typedef struct { + DerivedMesh *dm; + int pos; + int offset; + int flip; +} FaceIt; + +static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator) +{ + MEM_freeN(iterator->it); + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; +} + +static int FaceIt_Done(CSG_IteratorPtr it) +{ + // assume CSG_IteratorPtr is of the correct type. + FaceIt * iterator = (FaceIt *)it; + return(iterator->pos >= iterator->dm->getNumTessFaces(iterator->dm)); +} + +static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face) +{ + // assume CSG_IteratorPtr is of the correct type. + FaceIt *face_it = (FaceIt *)it; + MFace *mfaces = face_it->dm->getTessFaceArray(face_it->dm); + MFace *mface = &mfaces[face_it->pos]; + + /* reverse face vertices if necessary */ + face->vertex_index[1] = mface->v2; + if( face_it->flip == 0 ) { + face->vertex_index[0] = mface->v1; + face->vertex_index[2] = mface->v3; + } else { + face->vertex_index[2] = mface->v1; + face->vertex_index[0] = mface->v3; + } + if (mface->v4) { + face->vertex_index[3] = mface->v4; + face->vertex_number = 4; + } else { + face->vertex_number = 3; + } + + face->orig_face = face_it->offset + face_it->pos; +} + +static void FaceIt_Step(CSG_IteratorPtr it) +{ + FaceIt * face_it = (FaceIt *)it; + face_it->pos ++; +} + +static void FaceIt_Reset(CSG_IteratorPtr it) +{ + FaceIt * face_it = (FaceIt *)it; + face_it->pos = 0; +} + +static void FaceIt_Construct( + CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob) +{ + FaceIt *it; + if (output == 0) return; + + // allocate some memory for blender iterator + it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt")); + if (it == 0) { + return ; + } + // assign blender specific variables + it->dm = dm; + it->offset = offset; + it->pos = 0; + + /* determine if we will need to reverse order of face vertices */ + if (ob->size[0] < 0.0f) { + if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { + it->flip = 1; + } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { + it->flip = 1; + } else { + it->flip = 0; + } + } else { + if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { + it->flip = 0; + } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { + it->flip = 0; + } else { + it->flip = 1; + } + } + + // assign iterator function pointers. + output->Step = FaceIt_Step; + output->Fill = FaceIt_Fill; + output->Done = FaceIt_Done; + output->Reset = FaceIt_Reset; + output->num_elements = it->dm->getNumTessFaces(it->dm); + output->it = it; +} + +static Object *AddNewBlenderMesh(Scene *scene, Base *base) +{ + // This little function adds a new mesh object to the blender object list + // It uses ob to duplicate data as this seems to be easier than creating + // a new one. This new oject contains no faces nor vertices. + Mesh *old_me; + Base *basen; + Object *ob_new; + + // now create a new blender object. + // duplicating all the settings from the previous object + // to the new one. + ob_new= copy_object(base->object); + + // Ok we don't want to use the actual data from the + // last object, the above function incremented the + // number of users, so decrement it here. + old_me= ob_new->data; + old_me->id.us--; + + // Now create a new base to add into the linked list of + // vase objects. + + basen= MEM_mallocN(sizeof(Base), "duplibase"); + *basen= *base; + BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */ + basen->object= ob_new; + basen->flag &= ~SELECT; + + // Initialize the mesh data associated with this object. + ob_new->data= add_mesh("Mesh"); + + // Finally assign the object type. + ob_new->type= OB_MESH; + + return ob_new; +} + +static void InterpCSGFace( + DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr, + float mapmat[][4]) +{ + float obco[3], *co[4], *orig_co[4], w[4][4]; + MFace *mface, *orig_mface; + int j; + + mface = CDDM_get_tessface(dm, index); + orig_mface = orig_dm->getTessFaceArray(orig_dm) + orig_index; + + // get the vertex coordinates from the original mesh + orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co; + orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co; + orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co; + orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL; + + // get the vertex coordinates from the new derivedmesh + co[0] = CDDM_get_vert(dm, mface->v1)->co; + co[1] = CDDM_get_vert(dm, mface->v2)->co; + co[2] = CDDM_get_vert(dm, mface->v3)->co; + co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL; + + for (j = 0; j < nr; j++) { + // get coordinate into the space of the original mesh + if (mapmat) + mul_v3_m4v3(obco, mapmat, co[j]); + else + copy_v3_v3(obco, co[j]); + + interp_weights_face_v3( w[j],orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco); + } + + CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index); +} + +/* Iterate over the CSG Output Descriptors and create a new DerivedMesh + from them */ +static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( + CSG_FaceIteratorDescriptor *face_it, + CSG_VertexIteratorDescriptor *vertex_it, + float parinv[][4], + float mapmat[][4], + Material **mat, + int *totmat, + DerivedMesh *dm1, + Object *ob1, + DerivedMesh *dm2, + Object *ob2) +{ + DerivedMesh *result, *orig_dm; + GHash *material_hash = NULL; + Mesh *me1= (Mesh*)ob1->data; + Mesh *me2= (Mesh*)ob2->data; + int i; + + // create a new DerivedMesh + result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements, 0, 0); + CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH, + CD_DEFAULT, face_it->num_elements); + CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH, + CD_DEFAULT, face_it->num_elements); + + // step through the vertex iterators: + for (i = 0; !vertex_it->Done(vertex_it->it); i++) { + CSG_IVertex csgvert; + MVert *mvert = CDDM_get_vert(result, i); + + // retrieve a csg vertex from the boolean module + vertex_it->Fill(vertex_it->it, &csgvert); + vertex_it->Step(vertex_it->it); + + // we have to map the vertex coordinates back in the coordinate frame + // of the resulting object, since it was computed in world space + mul_v3_m4v3(mvert->co, parinv, csgvert.position); + } + + // a hash table to remap materials to indices + if (mat) { + material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "booleanops.c"); + *totmat = 0; + } + + // step through the face iterators + for(i = 0; !face_it->Done(face_it->it); i++) { + Mesh *orig_me; + Object *orig_ob; + Material *orig_mat; + CSG_IFace csgface; + MFace *mface; + int orig_index, mat_nr; + + // retrieve a csg face from the boolean module + face_it->Fill(face_it->it, &csgface); + face_it->Step(face_it->it); + + // find the original mesh and data + orig_ob = (csgface.orig_face < dm1->getNumTessFaces(dm1))? ob1: ob2; + orig_dm = (csgface.orig_face < dm1->getNumTessFaces(dm1))? dm1: dm2; + orig_me = (orig_ob == ob1)? me1: me2; + orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumTessFaces(dm1); + + // copy all face layers, including mface + CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1); + + // set mface + mface = CDDM_get_tessface(result, i); + mface->v1 = csgface.vertex_index[0]; + mface->v2 = csgface.vertex_index[1]; + mface->v3 = csgface.vertex_index[2]; + mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0; + + // set material, based on lookup in hash table + orig_mat= give_current_material(orig_ob, mface->mat_nr+1); + + if (mat && orig_mat) { + if (!BLI_ghash_haskey(material_hash, orig_mat)) { + mat[*totmat] = orig_mat; + mat_nr = mface->mat_nr = (*totmat)++; + BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); + } + else + mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); + } + else + mface->mat_nr = 0; + + InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number, + (orig_me == me2)? mapmat: NULL); + + test_index_face(mface, &result->faceData, i, csgface.vertex_number); + } + + if (material_hash) + BLI_ghash_free(material_hash, NULL, NULL); + + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + CDDM_tessfaces_to_faces(result); + + return result; +} + +static void BuildMeshDescriptors( + struct DerivedMesh *dm, + struct Object *ob, + int face_offset, + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it) +{ + VertexIt_Construct(vertex_it,dm, ob); + FaceIt_Construct(face_it,dm,face_offset,ob); +} + +static void FreeMeshDescriptors( + struct CSG_FaceIteratorDescriptor *face_it, + struct CSG_VertexIteratorDescriptor *vertex_it) +{ + VertexIt_Destruct(vertex_it); + FaceIt_Destruct(face_it); +} + +DerivedMesh *NewBooleanDerivedMesh_intern( + DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, + int int_op_type, Material **mat, int *totmat) +{ + + float inv_mat[4][4]; + float map_mat[4][4]; + + DerivedMesh *result = NULL; + + if (dm == NULL || dm_select == NULL) return 0; + if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) return 0; + + // we map the final object back into ob's local coordinate space. For this + // we need to compute the inverse transform from global to ob (inv_mat), + // and the transform from ob to ob_select for use in interpolation (map_mat) + invert_m4_m4(inv_mat, ob->obmat); + mul_m4_m4m4(map_mat, ob_select->obmat, inv_mat); + invert_m4_m4(inv_mat, ob_select->obmat); + + { + // interface with the boolean module: + // + // the idea is, we pass the boolean module verts and faces using the + // provided descriptors. once the boolean operation is performed, we + // get back output descriptors, from which we then build a DerivedMesh + + CSG_VertexIteratorDescriptor vd_1, vd_2; + CSG_FaceIteratorDescriptor fd_1, fd_2; + CSG_OperationType op_type; + CSG_BooleanOperation *bool_op; + + // work out the operation they chose and pick the appropriate + // enum from the csg module. + switch (int_op_type) { + case 1 : op_type = e_csg_intersection; break; + case 2 : op_type = e_csg_union; break; + case 3 : op_type = e_csg_difference; break; + case 4 : op_type = e_csg_classify; break; + default : op_type = e_csg_intersection; + } + + BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1); + BuildMeshDescriptors(dm, ob, dm_select->getNumTessFaces(dm_select) , &fd_2, &vd_2); + + bool_op = CSG_NewBooleanFunction(); + + // perform the operation + if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) { + CSG_VertexIteratorDescriptor vd_o; + CSG_FaceIteratorDescriptor fd_o; + + CSG_OutputFaceDescriptor(bool_op, &fd_o); + CSG_OutputVertexDescriptor(bool_op, &vd_o); + + // iterate through results of operation and insert + // into new object + result = ConvertCSGDescriptorsToDerivedMesh( + &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob); + + // free up the memory + CSG_FreeVertexDescriptor(&vd_o); + CSG_FreeFaceDescriptor(&fd_o); + } + else + printf("Unknown internal error in boolean"); + + CSG_FreeBooleanOperation(bool_op); + + FreeMeshDescriptors(&fd_1, &vd_1); + FreeMeshDescriptors(&fd_2, &vd_2); + } + + return result; +} + +int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) +{ + Mesh *me_new; + int a, maxmat, totmat= 0; + Object *ob_new, *ob, *ob_select; + Material **mat; + DerivedMesh *result; + DerivedMesh *dm_select; + DerivedMesh *dm; + + ob= base->object; + ob_select= base_select->object; + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ?? + + maxmat= ob->totcol + ob_select->totcol; + mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat"); + + /* put some checks in for nice user feedback */ + if (dm == NULL || dm_select == NULL) return 0; + if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) + { + MEM_freeN(mat); + return -1; + } + + result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat); + + if (result == NULL) { + MEM_freeN(mat); + return 0; + } + + /* create a new blender mesh object - using 'base' as a template */ + ob_new= AddNewBlenderMesh(scene, base_select); + me_new= ob_new->data; + + DM_to_mesh(result, me_new); + result->release(result); + + dm->release(dm); + dm_select->release(dm_select); + + /* add materials to object */ + for (a = 0; a < totmat; a++) + assign_material(ob_new, mat[a], a+1); + + MEM_freeN(mat); + + /* update dag */ + DAG_id_flush_update(&ob_new->id, OB_RECALC_DATA); + + return 1; +} + +DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, + int int_op_type) +{ + return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL); +} + diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 949be31354c..7a3c4bd5928 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -553,7 +553,7 @@ BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float data->mesh = mesh; data->vert = mesh->getVertDataArray(mesh, CD_MVERT); - data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE); data->sphere_radius = epsilon; } @@ -570,9 +570,9 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float if(tree == NULL) { int i; - int numFaces= mesh->getNumFaces(mesh); + int numFaces= mesh->getNumTessFaces(mesh); MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); - MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); + MFace *face = mesh->getTessFaceDataArray(mesh, CD_MFACE); if(vert != NULL && face != NULL) { @@ -636,7 +636,7 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float data->mesh = mesh; data->vert = mesh->getVertDataArray(mesh, CD_MVERT); - data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE); data->sphere_radius = epsilon; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 9a04c75db07..368e84cce30 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1,4 +1,4 @@ -/* + /* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -36,11 +36,23 @@ #include <string.h> #include "BIF_gl.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_paint.h" +#include "BKE_utildefines.h" +#include "BKE_tessmesh.h" + +#include "BLI_editVert.h" +#include "BLI_scanfill.h" +#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_pbvh.h" +#include "BLI_array.h" +#include "BLI_smallhash.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -72,6 +84,8 @@ typedef struct { MVert *mvert; MEdge *medge; MFace *mface; + MLoop *mloop; + MPoly *mpoly; /* Cached */ struct PBVH *pbvh; @@ -82,6 +96,8 @@ typedef struct { struct IndexNode *fmap_mem; } CDDerivedMesh; +DMFaceIter *cdDM_newFaceIter(DerivedMesh *source); + /**************** DerivedMesh interface functions ****************/ static int cdDM_getNumVerts(DerivedMesh *dm) { @@ -93,11 +109,16 @@ static int cdDM_getNumEdges(DerivedMesh *dm) return dm->numEdgeData; } -static int cdDM_getNumFaces(DerivedMesh *dm) +static int cdDM_getNumTessFaces(DerivedMesh *dm) { return dm->numFaceData; } +static int cdDM_getNumFaces(DerivedMesh *dm) +{ + return dm->numPolyData; +} + static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -280,7 +301,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MFace *mf = cddm->mface; - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if(mf) { @@ -451,7 +472,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); + float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; #define PASSVERT(index) { \ @@ -631,21 +652,21 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha } static void cdDM_drawFacesTex_common(DerivedMesh *dm, - int (*drawParams)(MTFace *tface, MCol *mcol, int matnr), - int (*drawParamsMapped)(void *userData, int index), - void *userData) + int (*drawParams)(MTFace *tface, int has_vcol, int matnr), + int (*drawParamsMapped)(void *userData, int index), + void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mv = cddm->mvert; - MFace *mf = DM_get_face_data_layer(dm, CD_MFACE); - MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL); - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); - int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); + MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL); + float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); int startFace = 0, lastFlag = 0xdeadbeef; - MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); + MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); cdDM_update_normals_from_pbvh(dm); @@ -657,7 +678,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, unsigned char *cp = NULL; if(drawParams) { - flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr); + flag = drawParams(tf? &tf[i]: NULL, mcol!=NULL, mf->mat_nr); } else { if(index) { @@ -737,8 +758,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } if( col != 0 ) {*/ - unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common"); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common"); + for( i=0; i < dm->getNumTessFaces(dm); i++ ) { for( j=0; j < 4; j++ ) { colors[i*12+j*3] = col[i*4+j].r; colors[i*12+j*3+1] = col[i*4+j].g; @@ -763,7 +784,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, int flag = 1; if(drawParams) { - flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr); + flag = drawParams(tf? &tf[actualFace]: NULL, mcol!=NULL, mf[actualFace].mat_nr); } else { if(index) { @@ -806,7 +827,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } } -static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr)) +static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr)) { cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); } @@ -817,14 +838,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us MVert *mv = cddm->mvert; MFace *mf = cddm->mface; MCol *mc; - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); - int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); + int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); - mc = DM_get_face_data_layer(dm, CD_ID_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL); if(!mc) - mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL); if(!mc) - mc = DM_get_face_data_layer(dm, CD_MCOL); + mc = DM_get_tessface_data_layer(dm, CD_MCOL); cdDM_update_normals_from_pbvh(dm); @@ -968,11 +989,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); + float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, b, dodraw, matnr, new_matnr; int transp, new_transp, orig_transp; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); @@ -1081,7 +1102,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo else PASSVERT(mface->v3, 2) -#undef PASSVERT } glEnd(); } @@ -1397,35 +1417,69 @@ static void cdDM_foreachMappedFaceCenter( { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; MVert *mv = cddm->mvert; - MFace *mf = cddm->mface; - int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + MPoly *mf = cddm->mpoly; + MLoop *ml = cddm->mloop; + int i, j, orig, *index; - for(i = 0; i < dm->numFaceData; i++, mf++) { + index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); + mf = cddm->mpoly; + for(i = 0; i < dm->numPolyData; i++, mf++) { float cent[3]; float no[3]; if (index) { orig = *index++; if(orig == ORIGINDEX_NONE) continue; - } - else + } else orig = i; + + ml = &cddm->mloop[mf->loopstart]; + cent[0] = cent[1] = cent[2] = 0.0f; + for (j=0; j<mf->totloop; j++, ml++) { + add_v3_v3v3(cent, cent, mv[ml->v].co); + } + mul_v3_fl(cent, 1.0f / (float)j); - VECCOPY(cent, mv[mf->v1].co); - add_v3_v3(cent, mv[mf->v2].co); - add_v3_v3(cent, mv[mf->v3].co); - - if (mf->v4) { - normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); - add_v3_v3(cent, mv[mf->v4].co); - mul_v3_fl(cent, 0.25f); + ml = &cddm->mloop[mf->loopstart]; + if (j > 3) { + normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, + mv[(ml+2)->v].co, mv[(ml+3)->v].co); } else { - normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); - mul_v3_fl(cent, 0.33333333333f); + normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, + mv[(ml+2)->v].co); } func(userData, orig, cent, no); } + +} + +static void cdDM_recalcTesselation(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, + &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, + dm->numPolyData, 1, 0); + + cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); +} + +void CDDM_recalc_tesselation(DerivedMesh *dm) +{ + cdDM_recalcTesselation(dm); +} + +/*ignores original poly origindex layer*/ +static void cdDM_recalcTesselation2(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, + &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, + dm->numPolyData, 0, 0); + + cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); } static void cdDM_free_internal(CDDerivedMesh *cddm) @@ -1444,6 +1498,11 @@ static void cdDM_release(DerivedMesh *dm) } } +int CDDM_Check(DerivedMesh *dm) +{ + return dm && dm->getMinMax == cdDM_getMinMax; +} + /**************** CDDM interface functions ****************/ static CDDerivedMesh *cdDM_create(const char *desc) { @@ -1456,21 +1515,27 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getMinMax = cdDM_getMinMax; dm->getNumVerts = cdDM_getNumVerts; - dm->getNumFaces = cdDM_getNumFaces; dm->getNumEdges = cdDM_getNumEdges; + dm->getNumTessFaces = cdDM_getNumTessFaces; + dm->getNumFaces = cdDM_getNumFaces; + + dm->newFaceIter = cdDM_newFaceIter; dm->getVert = cdDM_getVert; dm->getEdge = cdDM_getEdge; - dm->getFace = cdDM_getFace; + dm->getTessFace = cdDM_getFace; dm->copyVertArray = cdDM_copyVertArray; dm->copyEdgeArray = cdDM_copyEdgeArray; - dm->copyFaceArray = cdDM_copyFaceArray; + dm->copyTessFaceArray = cdDM_copyFaceArray; dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; + dm->getTessFaceData = DM_get_face_data; dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getFaceDataArray = DM_get_face_data_layer; + dm->getTessFaceDataArray = DM_get_tessface_data_layer; + + //doesn't work yet for all cases + //dm->recalcTesselation = cdDM_recalcTesselation; dm->getVertCos = cdDM_getVertCos; dm->getVertCo = cdDM_getVertCo; @@ -1503,24 +1568,29 @@ static CDDerivedMesh *cdDM_create(const char *desc) return cddm; } -DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces) +DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_new dm"); DerivedMesh *dm = &cddm->dm; - DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1534,7 +1604,8 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) /* this does a referenced copy, with an exception for fluidsim */ - DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface); + DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface, + mesh->totloop, mesh->totpoly); dm->deformedOnly = 1; @@ -1544,21 +1615,30 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) mesh->totvert); CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, mesh->totedge); - CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype, + CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype, mesh->totface); + CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype, + mesh->totloop); + CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype, + mesh->totpoly); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface); + return dm; } DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) { DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts), - BLI_countlist(&em->edges), - BLI_countlist(&em->faces)); + BLI_countlist(&em->edges), + BLI_countlist(&em->faces), 0, 0); CDDerivedMesh *cddm = (CDDerivedMesh*)dm; EditVert *eve; EditEdge *eed; @@ -1576,6 +1656,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) CD_CALLOC, dm->numEdgeData); */ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->numFaceData); + CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numFaceData); /* set eve->hash to vert index */ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) @@ -1631,7 +1713,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */ } - index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); for(i = 0, efa = em->faces.first; i < dm->numFaceData; i++, efa = efa->next, index++) { MFace *mf = &mface[i]; @@ -1669,10 +1751,10 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { /* Error initializing mdata. This often happens when curve is empty */ - return CDDM_new(0, 0, 0); + return CDDM_new(0, 0, 0, 0, 0); } - dm = CDDM_new(totvert, totedge, totface); + dm = CDDM_new(totvert, totedge, totface, totface*4, totface); dm->deformedOnly = 1; cddm = (CDDerivedMesh*)dm; @@ -1688,21 +1770,348 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) return dm; } -DerivedMesh *CDDM_copy(DerivedMesh *source) +static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata, + int cdindex, BMLoop *l3[3], + int numCol, int numTex) +{ + BMLoop *l; + BMFace *f = l3[0]->f; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + for (j=0; j<3; j++) { + l = l3[j]; + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i); + + for (j=0; j<3; j++) { + l = l3[j]; + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL); + + for (j=0; j<3; j++) { + l = l3[j]; + mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + +DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me) +{ + DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, + em->tottri, em->bm->totloop, em->bm->totface); + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + BMesh *bm = em->bm; + BMIter iter, liter; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + MVert *mvert = cddm->mvert; + MEdge *medge = cddm->medge; + MFace *mface = cddm->mface; + MLoop *mloop = cddm->mloop; + MPoly *mpoly = cddm->mpoly; + int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL); + int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + int i, j, *index, add_orig; + + dm->deformedOnly = 1; + + /*don't add origindex layer if one already exists*/ + add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX); + + CustomData_merge(&em->bm->vdata, &dm->vertData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numVertData); + CustomData_merge(&em->bm->edata, &dm->edgeData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numEdgeData); + CustomData_merge(&em->bm->ldata, &dm->loopData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numLoopData); + CustomData_merge(&em->bm->pdata, &dm->polyData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numPolyData); + + /*add tesselation mface layers*/ + CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri); + + /* set vert index */ + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BMINDEX_SET(eve, i); + + index = dm->getVertDataArray(dm, CD_ORIGINDEX); + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) { + MVert *mv = &mvert[i]; + + VECCOPY(mv->co, eve->co); + + BMINDEX_SET(eve, i); + + mv->no[0] = eve->no[0] * 32767.0; + mv->no[1] = eve->no[1] * 32767.0; + mv->no[2] = eve->no[2] * 32767.0; + + mv->flag = BMFlags_To_MEFlags(eve); + + if (add_orig) *index = i; + + CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i); + } + + index = dm->getEdgeDataArray(dm, CD_ORIGINDEX); + eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) { + MEdge *med = &medge[i]; + + BMINDEX_SET(eed, i); + + med->v1 = BMINDEX_GET(eed->v1); + med->v2 = BMINDEX_GET(eed->v2); + med->flag = ME_EDGEDRAW|ME_EDGERENDER; + + med->flag = BMFlags_To_MEFlags(eed); + + CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i); + if (add_orig) *index = i; + } + + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; i++, efa=BMIter_Step(&iter)) { + BMINDEX_SET(efa, i); + } + + index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + for(i = 0; i < dm->numFaceData; i++, index++) { + MFace *mf = &mface[i]; + BMLoop **l = em->looptris[i]; + efa = l[0]->f; + + mf->v1 = BMINDEX_GET(l[0]->v); + mf->v2 = BMINDEX_GET(l[1]->v); + mf->v3 = BMINDEX_GET(l[2]->v); + mf->v4 = 0; + mf->mat_nr = efa->mat_nr; + mf->flag = BMFlags_To_MEFlags(efa); + + *index = add_orig ? BMINDEX_GET(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX); + + loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex); + test_index_face(mf, &dm->faceData, i, 3); + } + + index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); + j = 0; + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) { + BMLoop *l; + MPoly *mp = &mpoly[i]; + + mp->totloop = efa->len; + mp->flag = BMFlags_To_MEFlags(efa); + mp->loopstart = j; + mp->mat_nr = efa->mat_nr; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) { + mloop->v = BMINDEX_GET(l->v); + mloop->e = BMINDEX_GET(l->e); + CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j); + + j++; + mloop++; + } + + CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i); + + if (add_orig) *index = i; + } + + return dm; +} + +typedef struct CDDM_LoopIter { + DMLoopIter head; + CDDerivedMesh *cddm; + int len, i; +} CDDM_LoopIter; + +typedef struct CDDM_FaceIter { + DMFaceIter head; + CDDerivedMesh *cddm; + CDDM_LoopIter liter; +} CDDM_FaceIter; + +void cddm_freeiter(void *self) +{ + MEM_freeN(self); +} + +void cddm_stepiter(void *self) +{ + CDDM_FaceIter *iter = self; + MPoly *mp; + + mp = iter->cddm->mpoly + iter->head.index; + mp->flag = iter->head.flags; + mp->mat_nr = iter->head.mat_nr; + + iter->head.index++; + if (iter->head.index >= iter->cddm->dm.numPolyData) { + iter->head.done = 1; + return; + } + + mp = iter->cddm->mpoly + iter->head.index; + + iter->head.flags = mp->flag; + iter->head.mat_nr = mp->mat_nr; + iter->head.len = mp->totloop; +} + +void *cddm_faceiter_getcddata(void *self, int type, int layer) +{ + CDDM_FaceIter *iter = self; + + if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData, + iter->head.index, type); + else return CustomData_get_n(&iter->cddm->dm.polyData, type, + iter->head.index, layer); +} + +void *cddm_loopiter_getcddata(void *self, int type, int layer) +{ + CDDM_LoopIter *iter = self; + + if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData, + iter->head.index, type); + else return CustomData_get_n(&iter->cddm->dm.loopData, type, + iter->head.index, layer); +} + +void *cddm_loopiter_getvertcddata(void *self, int type, int layer) +{ + CDDM_LoopIter *iter = self; + + if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData, + iter->cddm->mloop[iter->head.vindex].v, + type); + else return CustomData_get_n(&iter->cddm->dm.vertData, type, + iter->cddm->mloop[iter->head.vindex].v, layer); +} + +DMLoopIter *cddmiter_get_loopiter(void *self) +{ + CDDM_FaceIter *iter = self; + CDDM_LoopIter *liter = &iter->liter; + MPoly *mp = iter->cddm->mpoly + iter->head.index; + + liter->i = -1; + liter->len = iter->head.len; + liter->head.index = mp->loopstart-1; + liter->head.done = 0; + + liter->head.step(liter); + + return (DMLoopIter*) liter; +} + +void cddm_loopiter_step(void *self) +{ + CDDM_LoopIter *liter = self; + MLoop *ml; + + liter->i++; + liter->head.index++; + + if (liter->i == liter->len) { + liter->head.done = 1; + return; + } + + ml = liter->cddm->mloop + liter->head.index; + + liter->head.eindex = ml->e; + liter->head.v = liter->cddm->mvert[ml->v]; + liter->head.vindex = ml->v; +} + +DMFaceIter *cdDM_newFaceIter(DerivedMesh *source) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) source; + CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm"); + + iter->head.free = cddm_freeiter; + iter->head.step = cddm_stepiter; + iter->head.getCDData = cddm_faceiter_getcddata; + iter->head.getLoopsIter = cddmiter_get_loopiter; + + iter->liter.head.step = cddm_loopiter_step; + iter->liter.head.getLoopCDData = cddm_loopiter_getcddata; + iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata; + iter->liter.cddm = cddm; + + iter->cddm = cddm; + + if (source->numFaceData) { + iter->head.index = -1; + iter->head.step(iter); + } else { + iter->head.done = 1; + } + + return (DMFaceIter*) iter; +} + +DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces) { CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); DerivedMesh *dm = &cddm->dm; int numVerts = source->numVertData; int numEdges = source->numEdgeData; int numFaces = source->numFaceData; + int numLoops = source->numLoopData; + int numPolys = source->numPolyData; /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, + numLoops, numPolys); dm->deformedOnly = source->deformedOnly; CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); @@ -1712,11 +2121,19 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupFaceArray(source); + cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces); + + if (!faces_from_tessfaces) + DM_DupPolys(source, dm); + else + CDDM_tessfaces_to_faces(dm); + + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1724,7 +2141,8 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct * relationship betwen mesh data this needs to be set by the caller. */ DerivedMesh *CDDM_from_template(DerivedMesh *source, - int numVerts, int numEdges, int numFaces) + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); DerivedMesh *dm = &cddm->dm; @@ -1732,15 +2150,17 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this does a copy of all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); /* now add mvert/medge/mface layers */ CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); @@ -1752,6 +2172,8 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1784,62 +2206,355 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) VECCOPY(vert->no, vertNormals[i]); } -/* adapted from mesh_calc_normals */ void CDDM_calc_normals(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; float (*temp_nors)[3]; float (*face_nors)[3]; - int i; + float (*vert_nors)[3]; + int i, j, *origIndex; int numVerts = dm->numVertData; int numFaces = dm->numFaceData; MFace *mf; + MPoly *mp; MVert *mv; + MLoop *ml; if(numVerts == 0) return; + if (CustomData_has_layer(&dm->faceData, CD_NORMAL)) + CustomData_free_layer(&dm->faceData, CD_NORMAL, dm->numFaceData, 0); + temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors), "CDDM_calc_normals temp_nors"); - /* we don't want to overwrite any referenced layers */ - mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); - cddm->mvert = mv; + /*recalc tesselation to ensure we have valid origindex values + for mface->mpoly lookups.*/ + cdDM_recalcTesselation2(dm); - /* make a face normal layer if not present */ - face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - if(!face_nors) - face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, - NULL, dm->numFaceData); + numFaces = dm->numFaceData; - /* calculate face normals and add to vertex normals */ - mf = CDDM_get_faces(dm); - for(i = 0; i < numFaces; i++, mf++) { - float *f_no = face_nors[i]; + /*first go through and calculate normals for all the polys*/ + temp_nors = MEM_callocN(sizeof(float)*3*dm->numPolyData, "temp_nors cdderivedmesh.c"); + vert_nors = MEM_callocN(sizeof(float)*3*dm->numVertData, "vert_nors cdderivedmesh.c"); + + mp = cddm->mpoly; + for (i=0; i<dm->numPolyData; i++, mp++) { + mesh_calc_poly_normal(mp, cddm->mloop+mp->loopstart, cddm->mvert, temp_nors[i]); - if(mf->v4) - normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); - else - normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); - - add_v3_v3(temp_nors[mf->v1], f_no); - add_v3_v3(temp_nors[mf->v2], f_no); - add_v3_v3(temp_nors[mf->v3], f_no); - if(mf->v4) - add_v3_v3(temp_nors[mf->v4], f_no); + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + VECADD(vert_nors[ml->v], vert_nors[ml->v], temp_nors[i]); + } + } + + face_nors = MEM_callocN(sizeof(float)*3*dm->numFaceData, "face_nors cdderivedmesh.c"); + origIndex = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX); + + mf = cddm->mface; + for (i=0; i<dm->numFaceData; i++, mf++, origIndex++) { + VECCOPY(face_nors[i], temp_nors[*origIndex]); } - /* normalize vertex normals and assign */ - for(i = 0; i < numVerts; i++, mv++) { - float *no = temp_nors[i]; + mv = cddm->mvert; + for (i=0; i<dm->numVertData; i++, mv++) { + float *no = vert_nors[i]; - if (normalize_v3(no) == 0.0) - normalize_v3_v3(no, mv->co); + if (normalize_v3(no) == 0.0) { + VECCOPY(no, mv->co); + if (normalize_v3(no) == 0.0) { + no[0] = 0.0f; + no[1] = 0.0f; + no[2] = 1.0f; + } + } normal_float_to_short_v3(mv->no, no); } - + MEM_freeN(temp_nors); + MEM_freeN(vert_nors); + + /*this restores original poly origindex -> tessface origindex mapping, + instead of the poly index -> tessface origindex one we generated + with cdDM_recalcTesselation2*/ + cdDM_recalcTesselation(dm); + CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, + face_nors, dm->numFaceData); +} + +#if 0 +/*merge verts + + vtargetmap is a table that maps vertices to target vertices. a value of -1 + indicates a vertex is a target, and is to be kept. + + this is a really horribly written function. ger. - joeedh + + */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CDDerivedMesh *cddm2 = NULL; + MVert *mv, *mvert = NULL; + BLI_array_declare(mvert); + MEdge *me, *medge = NULL; + BLI_array_declare(medge); + MPoly *mp, *mpoly = NULL; + BLI_array_declare(mpoly); + MLoop *ml, *mloop = NULL; + BLI_array_declare(mloop); + SmallHash _hash, *hash=&_hash; + SmallHash _hash2, *hash2=&_hash2; + int *newv = NULL, *newe = NULL, *newl = NULL; + int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL; + BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp); + int i, j, c, totloop, totpoly; + + BLI_smallhash_init(hash); + BLI_smallhash_init(hash2); + +#if 0 + /*split off ngon faces with merges in them*/ + mp = cddm->mpoly; + for (i=0; i<dm->numPolyData; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + MLoop *ml2 = NULL; + int k, k1, a; + + if (ml->v == -1) + continue; + + for (k1=0; k1<mp->totloop; k1++) { + k = (j + k1) % mp->totloop; + ml2 = cddm->mloop + mp->loopstart + k; + + if (ml == ml2 || ml2->v == -1) + continue; + + if (vtargetmap[ml->v] == ml2->v || vtargetmap[ml2->v] == ml->v) { + MLoop *ml3; + MPoly *mp2; + int s, e, l, tot; + + if (k < j) + SWAP(int, k, j); + + s = j; e = k; tot = 0; + l = BLI_array_count(mloop); + ml3 = cddm->mloop + mp->loopstart + s; + for (a=s; a<e; a++, ml3++) { + if (ml3->v == -1) + continue; + + BLI_smallhash_insert(hash, dm->numLoopData + BLI_array_count(mloop), SET_INT_IN_POINTER(mp->loopstart + a - s)); + BLI_array_append(mloop, *ml3); + + ml3->v = -1; + ml3->e = -1; + tot++; + } + + if (!tot) + continue; + + BLI_smallhash_insert(hash2, dm->numPolyData + BLI_array_count(mpoly), SET_INT_IN_POINTER(i)); + + mp2 = BLI_array_append(mpoly, *mp); + mp2->loopstart = l + dm->numLoopData; + mp2->totloop = tot; + } + } + } + } + + ml = MEM_callocN(sizeof(MLoop)*(dm->numLoopData + BLI_array_count(mloop)), "merge mloop"); + mp = MEM_callocN(sizeof(MPoly)*(dm->numPolyData + BLI_array_count(mloop)), "merge mpoly"); + + memcpy(ml, cddm->mloop, sizeof(MLoop)*dm->numLoopData); + memcpy(mp, cddm->mpoly, sizeof(MPoly)*dm->numPolyData); + + cddm->mloop = ml; cddm->mpoly = mp; + + memcpy(cddm->mloop+dm->numLoopData, mloop, sizeof(MLoop)*BLI_array_count(mloop)); + memcpy(cddm->mpoly+dm->numPolyData, mpoly, sizeof(MPoly)*BLI_array_count(mpoly)); + + totloop = dm->numLoopData + BLI_array_count(mloop); + totpoly = dm->numPolyData + BLI_array_count(mpoly); + + BLI_array_empty(mloop); + BLI_array_empty(mpoly); +#else + totloop = dm->numLoopData; + totpoly = dm->numPolyData; +#endif + + newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts"); + newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts"); + newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts"); + + mv = cddm->mvert; + c = 0; + for (i=0; i<dm->numVertData; i++, mv++) { + if (vtargetmap[i] == -1) { + BLI_array_append(oldv, i); + newv[i] = c++; + BLI_array_append(mvert, *mv); + } + } + + /*find-replace merged vertices with target vertices*/ + ml = cddm->mloop; + c = 0; + for (i=0; i<totloop; i++, ml++) { + if (ml->v == -1) + continue; + + if (vtargetmap[ml->v] != -1) { + me = &cddm->medge[ml->e]; + if (me->v1 == ml->v) + me->v1 = vtargetmap[ml->v]; + else + me->v2 = vtargetmap[ml->v]; + + ml->v = vtargetmap[ml->v]; + } + } + + /*now go through and fix edges and faces*/ + me = cddm->medge; + c = 0; + for (i=0; i<dm->numEdgeData; i++, me++) { + if (me->v1 == me->v2) + continue; + + BLI_array_append(olde, i); + newe[i] = c++; + BLI_array_append(medge, *me); + } + + mp = cddm->mpoly; + for (i=0; i<totpoly; i++, mp++) { + MPoly *mp2; + + ml = cddm->mloop + mp->loopstart; + + c = 0; + for (j=0; j<mp->totloop; j++, ml++) { + if (ml->v == -1) + continue; + + me = cddm->medge + ml->e; + if (me->v1 != me->v2) { + BLI_array_append(oldl, j); + BLI_array_append(mloop, *ml); + newl[c] = BLI_array_count(mloop)-1; + c++; + } + } + + if (!c) + continue; + + mp2 = BLI_array_append(mpoly, *mp); + mp2->totloop = c; + mp2->loopstart = BLI_array_count(mloop) - c; + + BLI_array_append(oldp, i); + } + + /*create new cddm*/ + cddm2 = (CDDerivedMesh*) CDDM_new(BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly)); + + /*copy over data. CustomData_add_layer can do this, need to look it up.*/ + memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert)); + memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge)); + memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop)); + memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly)); + + BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly); + mvert = cddm2->mvert; medge = cddm2->medge; mloop = cddm2->mloop; mpoly = cddm2->mpoly; + + /*update edge indices and copy customdata*/ + me = cddm2->medge; + for (i=0; i<cddm2->dm.numEdgeData; i++, me++) { + MEdge cpy; + + me->v1 = newv[me->v1]; + me->v2 = newv[me->v2]; + + cpy = *me; + CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1); + *me = cpy; + } + + /*update loop indices and copy customdata*/ + ml = cddm2->mloop; + for (i=0; i<cddm2->dm.numLoopData; i++, ml++) { + MLoop cpy; + + ml->e = newe[ml->e]; + ml->v = newv[ml->v]; + + cpy = *ml; + + if (oldl[i] >= dm->numLoopData) + oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i])); + + CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1); + *ml = cpy; + } + + /*copy vertex customdata*/ + mv = cddm2->mvert; + for (i=0; i<cddm2->dm.numVertData; i++, mv++) { + MVert cpy = *mv; + + CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1); + *mv = cpy; + } + + /*copy poly customdata*/ + mp = cddm2->mpoly; + for (i=0; i<cddm2->dm.numPolyData; i++, mp++) { + MPoly cpy = *mp; + + if (oldl[i] >= dm->numPolyData) + oldl[i] = GET_INT_FROM_POINTER(BLI_smallhash_lookup(hash, (intptr_t)oldl[i])); + + CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1); + *mp = cpy; + } + + /*eek! not sure what to do with ORIGINDEX stuff here!!*/ + cddm2->dm.numFaceData = mesh_recalcTesselation(&cddm2->dm.faceData, &cddm2->dm.loopData, &cddm2->dm.polyData, cddm2->mvert, 0, cddm2->dm.numLoopData, cddm2->dm.numPolyData, 1, 0); + cddm2->mface = CustomData_get_layer(&cddm->dm.faceData, CD_MFACE); + + if (newv) + MEM_freeN(newv); + if (newe) + MEM_freeN(newe); + if (newl) + MEM_freeN(newl); + if (oldv) + MEM_freeN(oldv); + if (olde) + MEM_freeN(olde); + if (oldl) + MEM_freeN(oldl); + if (oldp) + MEM_freeN(oldp); + + BLI_smallhash_release(hash); + BLI_smallhash_release(hash2); + + dm->needsFree = 1; + dm->release(dm); + + return (DerivedMesh*)cddm2; } +#endif void CDDM_calc_edges(DerivedMesh *dm) { @@ -1897,6 +2612,83 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehash_free(eh, NULL); } + +void CDDM_calc_edges_poly(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CustomData edgeData; + EdgeHashIterator *ehi; + MPoly *mp = cddm->mpoly; + MLoop *ml; + MEdge *med; + EdgeHash *eh = BLI_edgehash_new(); + int v1, v2; + int *eindex; + int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData; + + eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + + med = cddm->medge; + if (med) { + for (i=0; i < numEdges; i++, med++) { + BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1)); + } + } + + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + if (!BLI_edgehash_haskey(eh, v1, v2)) { + BLI_edgehash_insert(eh, v1, v2, NULL); + } + } + } + + k = numEdges; + numEdges = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edgeData, 0, sizeof(edgeData)); + CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); + CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edgeData, CD_MEDGE); + index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + + med->flag = ME_EDGEDRAW|ME_EDGERENDER; + *index = j==0 ? ORIGINDEX_NONE : eindex[j-1]; + + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&dm->edgeData, dm->numEdgeData); + dm->edgeData = edgeData; + dm->numEdgeData = numEdges; + + cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + + mp = cddm->mpoly; + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2)); + } + } + + BLI_edgehash_free(eh, NULL); +} + void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts) { if (numVerts < dm->numVertData) @@ -1931,7 +2723,7 @@ MEdge *CDDM_get_edge(DerivedMesh *dm, int index) return &((CDDerivedMesh*)dm)->medge[index]; } -MFace *CDDM_get_face(DerivedMesh *dm, int index) +MFace *CDDM_get_tessface(DerivedMesh *dm, int index) { return &((CDDerivedMesh*)dm)->mface[index]; } @@ -1946,8 +2738,111 @@ MEdge *CDDM_get_edges(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->medge; } -MFace *CDDM_get_faces(DerivedMesh *dm) +MFace *CDDM_get_tessfaces(DerivedMesh *dm) { return ((CDDerivedMesh*)dm)->mface; } +MPoly *CDDM_get_polys(DerivedMesh *dm) +{ + return ((CDDerivedMesh*)dm)->mpoly; +} + +void CDDM_tessfaces_to_faces(DerivedMesh *dm) +{ + /*converts mfaces to mpolys/mloops*/ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + MFace *mf; + MEdge *me; + MLoop *ml; + MPoly *mp; + EdgeHash *eh = BLI_edgehash_new(); + int i, l, totloop, *index1, *index2; + + /*ensure we have all the edges we need*/ + CDDM_calc_edges(dm); + + /*build edge hash*/ + me = cddm->medge; + for (i=0; i<cddm->dm.numEdgeData; i++, me++) { + BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); + } + + mf = cddm->mface; + totloop = 0; + for (i=0; i<cddm->dm.numFaceData; i++, mf++) { + totloop += mf->v4 ? 4 : 3; + } + + CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData); + CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData); + + cddm->dm.numLoopData = totloop; + cddm->dm.numPolyData = cddm->dm.numFaceData; + + if (!totloop) return; + + cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces"); + cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces"); + + CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop); + CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData); + CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, + CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData); + + index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX); + index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX); + + mf = cddm->mface; + mp = cddm->mpoly; + ml = cddm->mloop; + l = 0; + for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) { + mp->flag = mf->flag; + mp->loopstart = l; + mp->mat_nr = mf->mat_nr; + mp->totloop = mf->v4 ? 4 : 3; + + ml->v = mf->v1; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); + ml++, l++; + + ml->v = mf->v2; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3)); + ml++, l++; + + ml->v = mf->v3; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1)); + ml++, l++; + + if (mf->v4) { + ml->v = mf->v4; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1)); + ml++, l++; + } + + } + + BLI_edgehash_free(eh, NULL); +} + +void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + cddm->mvert = mvert; +} + +void CDDM_set_medge(DerivedMesh *dm, MEdge *medge) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + cddm->medge = medge; +} + +void CDDM_set_mface(DerivedMesh *dm, MFace *mface) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + cddm->mface = mface; +} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 09f18514277..c115f6aa470 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -43,7 +43,6 @@ #include "BKE_modifier.h" #include "BKE_pointcache.h" - #ifdef _WIN32 void tstart ( void ) {} @@ -435,7 +434,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; cache= clmd->point_cache; - result = CDDM_copy(dm); + result = CDDM_copy(dm, 0); BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); @@ -929,8 +928,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int numverts = dm->getNumVerts ( dm ); - unsigned int numfaces = dm->getNumFaces ( dm ); - MFace *mface = dm->getFaceArray( dm ); + unsigned int numfaces = dm->getNumTessFaces ( dm ); + MFace *mface = dm->getTessFaceArray( dm ); unsigned int i = 0; /* Allocate our vertices. */ @@ -1042,9 +1041,9 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) unsigned int i = 0; unsigned int numverts = (unsigned int)dm->getNumVerts ( dm ); unsigned int numedges = (unsigned int)dm->getNumEdges ( dm ); - unsigned int numfaces = (unsigned int)dm->getNumFaces ( dm ); + unsigned int numfaces = (unsigned int)dm->getNumTessFaces ( dm ); MEdge *medge = dm->getEdgeArray ( dm ); - MFace *mface = dm->getFaceArray ( dm ); + MFace *mface = dm->getTessFaceArray ( dm ); int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 827dddf34d3..36d19b53ed2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -39,6 +39,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_editVert.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "DNA_armature_types.h" @@ -52,6 +53,7 @@ #include "DNA_lattice_types.h" #include "DNA_scene_types.h" #include "DNA_text_types.h" +#include "DNA_windowmanager_types.h" #include "BKE_action.h" @@ -68,8 +70,10 @@ #include "BKE_global.h" #include "BKE_library.h" #include "BKE_idprop.h" +#include "BKE_mesh.h" #include "BKE_shrinkwrap.h" #include "BKE_mesh.h" +#include "BKE_tessmesh.h" #ifdef WITH_PYTHON #include "BPY_extern.h" @@ -423,7 +427,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substr { DerivedMesh *dm = NULL; Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; float vec[3] = {0.0f, 0.0f, 0.0f}; float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; float imat[3][3], tmat[3][3]; @@ -440,7 +444,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substr /* get DerivedMesh */ if (em) { /* target is in editmode, so get a special derived mesh */ - dm = CDDM_from_editmesh(em, ob->data); + dm = CDDM_from_BMEditMesh(em, ob->data); freeDM= 1; } else { @@ -519,8 +523,6 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substr /* free temporary DerivedMesh created (in EditMode case) */ if (dm && freeDM) dm->release(dm); - if (em) - BKE_mesh_end_editmesh(me, em); } /* function that sets the given matrix based on given vertex group in lattice */ @@ -2536,9 +2538,9 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * } break; default: - { - unit_m3(totmat); - } + { + unit_m3(totmat); + } break; } /* Block to keep matrix heading */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index a80b6dfab7d..6f7188115e0 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -41,14 +41,21 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "PIL_time.h" #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" +#ifdef EVENT_RECORDER +#include "../../../../intern/ghost/GHOST_C-api.h" +#endif + +#ifndef DISABLE_PYTHON #ifdef WITH_PYTHON #include "BPY_extern.h" #endif +#endif /* struct */ @@ -81,6 +88,12 @@ struct bContext { struct { int render; } eval; + +#ifdef EVENT_RECORDER + int evtrec, evtplay; + char evtplaypath[300]; + double evtlasttime; +#endif }; /* context */ @@ -101,6 +114,62 @@ bContext *CTX_copy(const bContext *C) return newC; } +#ifdef EVENT_RECORDER +extern GHOST_SystemHandle g_system; + +int CTX_rec_events(bContext *C) +{ + return GHOST_RecordingEvents(g_system); +} + +int CTX_rec_events_set(bContext *C, int state) +{ + FILE *f = CTX_rec_file(C); + + if (GHOST_RecordingEvents(g_system) && !state) + GHOST_StopRecording(g_system); + else if (!GHOST_RecordingEvents(g_system) && state) + GHOST_RecordEvents(g_system, f); + + return 1; +} + +FILE *CTX_rec_file(bContext *C) +{ + static FILE *f = NULL; + if (!f) + f = fopen("eventlog.txt", "wb"); + return f; +} + +int CTX_set_events_path(bContext *C, char *path) +{ + if (!path) { + C->evtplaypath[0] = 0; + } else { + FILE *file = fopen(path, "rb"); + + if (!file) + return 0; + + strcpy(C->evtplaypath, path); + if (g_system) + GHOST_PlaybackEvents(g_system, file); + } + + return 1; +} + +extern int erec_playing; +int CTX_play_events(bContext *C, char **playpath) +{ + if (playpath) + *playpath = C->evtplaypath[0] ? C->evtplaypath : NULL; + + return GHOST_PlayingEvents(g_system); +} +#endif + void CTX_free(bContext *C) { MEM_freeN(C); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 5dc62f2c7af..67e988249f5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -47,6 +47,7 @@ #include "DNA_key_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "BKE_animsys.h" diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 87fe545644a..0612a57d85d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -34,6 +34,7 @@ #include <math.h> #include <string.h> + #include <assert.h> #include "MEM_guardedalloc.h" @@ -46,6 +47,7 @@ #include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_mempool.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -55,6 +57,11 @@ #include "BKE_utildefines.h" #include "BKE_multires.h" +#include "bmesh.h" + +#include <math.h> +#include <string.h> + /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 @@ -97,6 +104,14 @@ typedef struct LayerTypeInfo { default is assumed to be all zeros */ void (*set_default)(void *data, int count); + /* functions necassary for geometry collapse*/ + int (*equal)(void *data1, void *data2); + void (*multiply)(void *data, float fac); + void (*initminmax)(void *min, void *max); + void (*add)(void *data1, void *data2); + void (*dominmax)(void *data1, void *min, void *max); + void (*copyvalue)(void *source, void *dest); + /* a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); @@ -123,7 +138,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest, MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size); if(dvert->totweight) { - MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw), + MDeformWeight *dw = BLI_cellalloc_calloc(dvert->totweight * sizeof(*dw), "layerCopy_mdeformvert dw"); memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw)); @@ -142,7 +157,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) MDeformVert *dvert = (MDeformVert *)((char *)data + i * size); if(dvert->dw) { - MEM_freeN(dvert->dw); + BLI_cellalloc_free(dvert->dw); dvert->dw = NULL; dvert->totweight = 0; } @@ -151,7 +166,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) static void linklist_free_simple(void *link) { - MEM_freeN(link); + BLI_cellalloc_free(link); } static void layerInterp_mdeformvert(void **sources, float *weights, @@ -184,7 +199,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights, /* if this def_nr is not in the list, add it */ if(!node) { - MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw), + MDeformWeight *tmp_dw = BLI_cellalloc_calloc(sizeof(*tmp_dw), "layerInterp_mdeformvert tmp_dw"); tmp_dw->def_nr = dw->def_nr; tmp_dw->weight = dw->weight * interp_weight; @@ -195,10 +210,10 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } /* now we know how many unique deform weights there are, so realloc */ - if(dvert->dw) MEM_freeN(dvert->dw); + if(dvert->dw) BLI_cellalloc_free(dvert->dw); if(totweight) { - dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight, + dvert->dw = BLI_cellalloc_calloc(sizeof(*dvert->dw) * totweight, "layerInterp_mdeformvert dvert->dw"); dvert->totweight = totweight; @@ -278,6 +293,7 @@ static void layerInterp_tface(void **sources, float *weights, } *tf = *(MTFace *)sources[0]; + for(j = 0; j < 4; ++j) { tf->uv[j][0] = uv[j][0]; tf->uv[j][1] = uv[j][1]; @@ -639,12 +655,86 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count } /* --------- */ +static void layerCopyValue_mloopcol(void *source, void *dest) +{ + MLoopCol *m1 = source, *m2 = dest; + + m2->r = m1->r; + m2->g = m1->g; + m2->b = m1->b; + m2->a = m1->a; +} + +static int layerEqual_mloopcol(void *data1, void *data2) +{ + MLoopCol *m1 = data1, *m2 = data2; + float r, g, b, a; + + r = m1->r - m2->r; + g = m1->g - m2->g; + b = m1->b - m2->b; + a = m1->a - m2->a; + + return r*r + g*g + b*b + a*a < 0.001; +} + +static void layerMultiply_mloopcol(void *data, float fac) +{ + MLoopCol *m = data; + + m->r = (float)m->r * fac; + m->g = (float)m->g * fac; + m->b = (float)m->b * fac; + m->a = (float)m->a * fac; +} + +static void layerAdd_mloopcol(void *data1, void *data2) +{ + MLoopCol *m = data1, *m2 = data2; + + m->r += m2->r; + m->g += m2->g; + m->b += m2->b; + m->a += m2->a; +} + +static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax) +{ + MLoopCol *m = data; + MLoopCol *min = vmin, *max = vmax; + + if (m->r < min->r) min->r = m->r; + if (m->g < min->g) min->g = m->g; + if (m->b < min->b) min->b = m->b; + if (m->a < min->a) min->a = m->a; + + if (m->r > max->r) max->r = m->r; + if (m->g > max->g) max->g = m->g; + if (m->b > max->b) max->b = m->b; + if (m->a > max->a) max->a = m->a; +} + +static void layerInitMinMax_mloopcol(void *vmin, void *vmax) +{ + MLoopCol *min = vmin, *max = vmax; + + min->r = 255; + min->g = 255; + min->b = 255; + min->a = 255; + + max->r = 0; + max->g = 0; + max->b = 0; + max->a = 0; +} static void layerDefault_mloopcol(void *data, int count) { - static MLoopCol default_mloopcol = {255,255,255,255}; + MLoopCol default_mloopcol = {255,255,255,255}; MLoopCol *mlcol = (MLoopCol*)data; int i; + for(i = 0; i < count; i++) mlcol[i] = default_mloopcol; @@ -694,6 +784,56 @@ static void layerInterp_mloopcol(void **sources, float *weights, mc->g = (int)col.g; mc->b = (int)col.b; } + +static void layerCopyValue_mloopuv(void *source, void *dest) +{ + MLoopUV *luv1 = source, *luv2 = dest; + + luv2->uv[0] = luv1->uv[0]; + luv2->uv[1] = luv1->uv[1]; +} + +static int layerEqual_mloopuv(void *data1, void *data2) +{ + MLoopUV *luv1 = data1, *luv2 = data2; + float u, v; + + u = luv1->uv[0] - luv2->uv[0]; + v = luv1->uv[1] - luv2->uv[1]; + + return u*u + v*v < 0.00001; +} + +static void layerMultiply_mloopuv(void *data, float fac) +{ + MLoopUV *luv = data; + + luv->uv[0] *= fac; + luv->uv[1] *= fac; +} + +static void layerInitMinMax_mloopuv(void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax; + + INIT_MINMAX2(min->uv, max->uv); +} + +static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax, *luv = data; + + DO_MINMAX2(luv->uv, min->uv, max->uv); +} + +static void layerAdd_mloopuv(void *data1, void *data2) +{ + MLoopUV *l1 = data1, *l2 = data2; + + l1->uv[0] += l2->uv[0]; + l1->uv[1] += l2->uv[1]; +} + static void layerInterp_mloopuv(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -801,7 +941,45 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } +static void layerInterp_bweight(void **sources, float *weights, + float *sub_weights, int count, void *dest) +{ + float *f = dest, *src; + float **in = sources; + int i; + + if(count <= 0) return; + + *f = 0.0f; + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + *f += *src * weight; + } +} + +static void layerInterp_shapekey(void **sources, float *weights, + float *sub_weights, int count, void *dest) +{ + float *co = dest, *src; + float **in = sources; + int i, j, k; + + if(count <= 0) return; + memset(co, 0, sizeof(float)*3); + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + co[0] += src[0] * weight; + co[1] += src[1] * weight; + co[2] += src[2] * weight; + } +} static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, @@ -818,7 +996,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerSwap_mcol, layerDefault_mcol}, {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 3 floats per normal vector */ - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, @@ -827,49 +1005,71 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, - {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, + {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL, + layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, - layerFilesize_mdisps, layerValidate_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps}, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, + {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, + {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ClothOrco", NULL, NULL, layerInterp_shapekey}, + {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, + {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey}, + {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight}, + {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight}, + {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { - /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", - /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", - /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", - /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", - /* 20-23 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco" + "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", + "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", + "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly", + "CDMLoop", "CDMClothOrco", "CDMLoopCol", "CDIDCol", "CDTextureCol", + "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", "CDSubSurfCrease" }; + const CustomDataMask CD_MASK_BAREMESH = - CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; + CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT; const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP | + CD_MASK_MTEXPOLY | CD_MASK_NORMAL | CD_MASK_MDISPS; const CustomDataMask CD_MASK_EDITMESH = - CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; + CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV | + CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX | + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | + CD_MASK_MDISPS | CD_MASK_SHAPEKEY; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | - CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL; -const CustomDataMask CD_MASK_BMESH = - CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_WEIGHT_MLOOPCOL | + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | + CD_MASK_WEIGHT_MCOL | CD_MASK_NORMAL; +const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | + CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | + CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS; const CustomDataMask CD_MASK_FACECORNERS = CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - static const LayerTypeInfo *layerType_getInfo(int type) { if(type < 0 || type >= CD_NUMTYPES) return NULL; @@ -890,13 +1090,29 @@ static void customData_update_offsets(CustomData *data); static CustomDataLayer *customData_add_layer__internal(CustomData *data, int type, int alloctype, void *layerdata, int totelem, const char *name); +void customData_update_typemap(CustomData *data) +{ + int i, lasttype = -1; + + for (i=0; i<CD_NUMTYPES; i++) { + data->typemap[i] = -1; + } + + for (i=0; i<data->totlayer; i++) { + if (data->layers[i].type != lasttype) { + data->typemap[data->layers[i].type] = i; + } + lasttype = data->layers[i].type; + } +} + void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; - + for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ @@ -917,7 +1133,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, if(lastflag & CD_FLAG_NOCOPY) continue; else if(!((int)mask & (int)(1 << (int)type))) continue; - else if(number < CustomData_number_of_layers(dest, type)) continue; + else if(number+1 < CustomData_number_of_layers(dest, type)) continue; if((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE)) newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE, @@ -934,6 +1150,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY); } } + + customData_update_typemap(dest); } void CustomData_copy(const struct CustomData *source, struct CustomData *dest, @@ -1011,6 +1229,17 @@ int CustomData_get_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + n; + + return -1; +} + int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) { int i; @@ -1024,11 +1253,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha int CustomData_get_active_layer_index(const CustomData *data, int type) { - int i; + if (!data->totlayer) + return -1; - for(i=0; i < data->totlayer; ++i) - if(data->layers[i].type == type) - return i + data->layers[i].active; + if (data->typemap[type] != -1) { + return data->typemap[type] + data->layers[data->typemap[type]].active; + } return -1; } @@ -1257,6 +1487,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].type = type; data->layers[index].flag = flag; data->layers[index].data = newlayerdata; + if(name || (name=typeInfo->defaultname)) { BLI_strncpy(data->layers[index].name, name, 32); CustomData_set_layer_unique_name(data, index); @@ -1289,6 +1520,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, typeInfo->defaultname); + customData_update_typemap(data); if(layer) return layer->data; @@ -1304,6 +1536,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name); + customData_update_typemap(data); if(layer) return layer->data; @@ -1342,6 +1575,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_resize(data, -CUSTOMDATA_GROW); customData_update_offsets(data); + customData_update_typemap(data); return 1; } @@ -1451,6 +1685,16 @@ void CustomData_set_only_copy(const struct CustomData *data, data->layers[i].flag |= CD_FLAG_NOCOPY; } +void CustomData_copy_elements(int type, void *source, void *dest, int count) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->copy) + typeInfo->copy(source, dest, count); + else + memcpy(dest, source, typeInfo->size*count); +} + void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count) { @@ -1610,6 +1854,19 @@ void *CustomData_get(const CustomData *data, int index, int type) return (char *)data->layers[layer_index].data + offset; } +void *CustomData_get_n(const CustomData *data, int type, int index, int n) +{ + int layer_index; + int offset; + + /* get the layer index of the first layer of type */ + layer_index = data->typemap[type]; + if(layer_index < 0) return NULL; + + offset = layerType_getInfo(type)->size * index; + return (char *)data->layers[layer_index+n].data + offset; +} + void *CustomData_get_layer(const CustomData *data, int type) { /* get the layer index of the active layer of type */ @@ -1956,17 +2213,18 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest, /*Bmesh functions*/ /*needed to convert to/from different face reps*/ -void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata) +void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, + int totloop, int totpoly) { int i; for(i=0; i < fdata->totlayer; i++){ if(fdata->layers[i].type == CD_MTFACE){ - CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0); - CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0); + CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), totpoly); + CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), totloop); } else if(fdata->layers[i].type == CD_MCOL) - CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0); - } + CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), totloop); + } } void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){ int i; @@ -1977,12 +2235,62 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData for(i=0; i < ldata->totlayer; i++){ if(ldata->layers[i].type == CD_MLOOPCOL) CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total); + if (ldata->layers[i].type == CD_WEIGHT_MLOOPCOL) + CustomData_add_layer(fdata, CD_WEIGHT_MCOL, CD_CALLOC, &(ldata->layers[i].name), total); } } void CustomData_bmesh_init_pool(CustomData *data, int allocsize){ - if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0); + if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 1, 0); +} + +void CustomData_bmesh_merge(CustomData *source, CustomData *dest, + int mask, int alloctype, BMesh *bm, int type) +{ + BMHeader *h; + BMIter iter; + CustomData destold = *dest; + void *tmp; + int t; + + CustomData_merge(source, dest, mask, alloctype, 0); + CustomData_bmesh_init_pool(dest, 512); + + switch (type) { + case BM_VERT: + t = BM_VERTS_OF_MESH; break; + case BM_EDGE: + t = BM_EDGES_OF_MESH; break; + case BM_LOOP: + t = BM_LOOPS_OF_FACE; break; + case BM_FACE: + t = BM_FACES_OF_MESH; break; + } + + if (t != BM_LOOPS_OF_FACE) { + /*ensure all current elements follow new customdata layout*/ + BM_ITER(h, &iter, bm, t, NULL) { + CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp); + CustomData_bmesh_free_block(&destold, &h->data); + h->data = tmp; + } + } else { + BMFace *f; + BMLoop *l; + BMIter liter; + + /*ensure all current elements follow new customdata layout*/ + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + CustomData_bmesh_copy_data(&destold, dest, l->head.data, &tmp); + CustomData_bmesh_free_block(&destold, &l->head.data); + l->head.data = tmp; + } + } + } + + if (destold.pool) BLI_mempool_destroy(destold.pool); } void CustomData_bmesh_free_block(CustomData *data, void **block) @@ -2002,7 +2310,9 @@ void CustomData_bmesh_free_block(CustomData *data, void **block) } } - BLI_mempool_free(data->pool, *block); + if (data->totsize) + BLI_mempool_free(data->pool, *block); + *block = NULL; } @@ -2013,7 +2323,7 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block) CustomData_bmesh_free_block(data, block); if (data->totsize > 0) - *block = BLI_mempool_calloc(data->pool); + *block = BLI_mempool_alloc(data->pool); else *block = NULL; } @@ -2086,6 +2396,82 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return (char *)block + data->layers[layer_index+n].offset; } +/*gets from the layer at physical index n, note: doesn't check type.*/ +void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) +{ + if(n < 0 || n >= data->totlayer) return NULL; + + return (char *)block + data->layers[n].offset; +} + +int CustomData_layer_has_math(struct CustomData *data, int layern) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type); + + if (typeInfo->equal && typeInfo->add && typeInfo->multiply && + typeInfo->initminmax && typeInfo->dominmax) return 1; + + return 0; +} + +/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to + another, while not overwriting anything else (e.g. flags)*/ +void CustomData_data_copy_value(int type, void *source, void *dest) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if(!dest) return; + + if(typeInfo->copyvalue) + typeInfo->copyvalue(source, dest); + else + memcpy(dest, source, typeInfo->size); +} + +int CustomData_data_equals(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->equal) + return typeInfo->equal(data1, data2); + else return !memcmp(data1, data2, typeInfo->size); +} + +void CustomData_data_initminmax(int type, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->initminmax) + typeInfo->initminmax(min, max); +} + + +void CustomData_data_dominmax(int type, void *data, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->dominmax) + typeInfo->dominmax(data, min, max); +} + + +void CustomData_data_multiply(int type, void *data, float fac) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->multiply) + typeInfo->multiply(data, fac); +} + + +void CustomData_data_add(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->add) + typeInfo->add(data1, data2); +} + void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source) { void *dest = CustomData_bmesh_get(data, block, type); @@ -2112,6 +2498,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void memcpy(dest, source, typeInfo->size); } +void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source) +{ + void *dest = CustomData_bmesh_get_layer_n(data, block, n); + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); + + if(!dest) return; + + if(typeInfo->copy) + typeInfo->copy(source, dest, 1); + else + memcpy(dest, source, typeInfo->size); +} + void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, float *sub_weights, int count, void *dest_block) { @@ -2157,6 +2556,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block) if(typeInfo->set_default) typeInfo->set_default((char*)*block + offset, 1); + else memset((char*)*block + offset, 0, typeInfo->size); } } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 7967013c2d4..616bcb17f90 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -44,6 +44,7 @@ #include "BKE_deform.h" #include "BLI_blenlib.h" +#include "BLI_cellalloc.h" void defgroup_copy_list (ListBase *outbase, ListBase *inbase) @@ -84,10 +85,10 @@ void defvert_copy (MDeformVert *dvert_r, const MDeformVert *dvert) } else { if(dvert_r->dw) - MEM_freeN(dvert_r->dw); + BLI_cellalloc_free(dvert_r->dw); if(dvert->totweight) - dvert_r->dw= MEM_dupallocN(dvert->dw); + dvert_r->dw= BLI_cellalloc_dupalloc(dvert->dw); else dvert_r->dw= NULL; @@ -492,10 +493,10 @@ MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup) if(newdw) return newdw; - newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); + newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); if(dv->dw) { memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); - MEM_freeN(dv->dw); + BLI_cellalloc_free(dv->dw); } dv->dw=newdw; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index b59109c3f2a..59e5aa7ade6 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -510,10 +510,10 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un dm = mesh_get_derived_final(RE_GetScene(re), ob, dataMask); mvert = dm->getVertArray(dm); - mface = dm->getFaceArray(dm); - nors = dm->getFaceDataArray(dm, CD_NORMAL); + mface = dm->getTessFaceArray(dm); + nors = dm->getTessFaceDataArray(dm, CD_NORMAL); totvert = dm->getNumVerts(dm); - totface = dm->getNumFaces(dm); + totface = dm->getNumTessFaces(dm); orco= dm->getVertDataArray(dm, CD_ORCO); if (onlyForMesh) { @@ -1404,7 +1404,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (dm) { if (vertCos) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); dm->release(dm); dm = tdm; @@ -1445,7 +1445,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (vertCos) { if (dm) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); dm->release(dm); dm = tdm; diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c new file mode 100644 index 00000000000..b38521b0a23 --- /dev/null +++ b/source/blender/blenkernel/intern/editderivedbmesh.c @@ -0,0 +1,1711 @@ +/** + * $Id: editderivedbmesh.c 18571 2009-01-19 06:04:57Z joeedh $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Tbmple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "PIL_time.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_effect_types.h" +#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_object_fluidsim.h" // N_T +#include "DNA_scene_types.h" // N_T +#include "DNA_texture_types.h" +#include "DNA_view3d_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_particle_types.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_edgehash.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" +#include "BLI_scanfill.h" +#include "BLI_ghash.h" +#include "BLI_array.h" +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" +#include "BKE_key.h" +#include "BKE_material.h" +#include "BKE_modifier.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_subsurf.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" +#include "BKE_particle.h" +#include "BKE_tessmesh.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "bmesh.h" + +BMEditMesh *BMEdit_Create(BMesh *bm) +{ + BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), "tm"); + + tm->bm = bm; + + BMEdit_RecalcTesselation(tm); + + return tm; +} + +BMEditMesh *BMEdit_Copy(BMEditMesh *tm) +{ + BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), "tm2"); + *tm2 = *tm; + + tm2->derivedCage = tm2->derivedFinal = NULL; + + tm2->looptris = NULL; + tm2->bm = BM_Copy_Mesh(tm->bm); + BMEdit_RecalcTesselation(tm2); + + tm2->vert_index = NULL; + tm2->edge_index = NULL; + tm2->face_index = NULL; + + return tm2; +} + +static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm) +{ + BMesh *bm = tm->bm; + BMLoop **looptris = NULL; + BLI_array_declare(looptris); + BMIter iter, liter; + BMFace *f; + BMLoop *l; + int i = 0, j; + + if (tm->looptris) MEM_freeN(tm->looptris); + +#if 0 //simple quad/triangle code for performance testing purposes + looptris = MEM_callocN(sizeof(void*)*bm->totface*8, "looptris"); + + f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for ( ; f; f=BMIter_Step(&iter)) { + EditVert *v, *lastv=NULL, *firstv=NULL; + EditEdge *e; + EditFace *efa; + + /*don't consider two-edged faces*/ + if (f->len < 3) continue; + + //BLI_array_growone(looptris); + //BLI_array_growone(looptris); + //BLI_array_growone(looptris); + + looptris[i*3] = f->loopbase; + looptris[i*3+1] = f->loopbase->head.next; + looptris[i*3+2] = f->loopbase->head.next->next; + i++; + + if (f->len > 3) { + //BLI_array_growone(looptris); + //BLI_array_growone(looptris); + //BLI_array_growone(looptris); + + looptris[i*3] = f->loopbase; + looptris[i*3+1] = f->loopbase->head.next->next; + looptris[i*3+2] = f->loopbase->head.next->next->next; + i++; + } + + } + + tm->tottri = i; + tm->looptris = looptris; + return; +#endif + + f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for ( ; f; f=BMIter_Step(&iter)) { + EditVert *v, *lastv=NULL, *firstv=NULL; + EditEdge *e; + EditFace *efa; + + /*don't consider two-edged faces*/ + if (f->len < 3) continue; + + /*scanfill time*/ + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + for (j=0; l; l=BMIter_Step(&liter), j++) { + /*mark order*/ + l->_index = j; + + v = BLI_addfillvert(l->v->co); + v->tmp.p = l; + + if (lastv) { + e = BLI_addfilledge(lastv, v); + } + + lastv = v; + if (firstv==NULL) firstv = v; + } + + /*complete the loop*/ + BLI_addfilledge(firstv, v); + + BLI_edgefill(0); + + for (efa = fillfacebase.first; efa; efa=efa->next) { + BMLoop *l1, *l2, *l3; + + BLI_array_growone(looptris); + BLI_array_growone(looptris); + BLI_array_growone(looptris); + + looptris[i*3] = l1 = efa->v1->tmp.p; + looptris[i*3+1] = l2 = efa->v2->tmp.p; + looptris[i*3+2] = l3 = efa->v3->tmp.p; + + if (l1->_index > l2->_index) { + SWAP(BMLoop*, l1, l2); + } + if (l2->_index > l3->_index) { + SWAP(BMLoop*, l2, l3); + } + if (l1->_index > l2->_index) { + SWAP(BMLoop*, l1, l2); + } + + looptris[i*3] = l1; + looptris[i*3+1] = l2; + looptris[i*3+2] = l3; + + i += 1; + } + + BLI_end_edgefill(); + } + + tm->tottri = i; + tm->looptris = looptris; +} + +void BMEdit_RecalcTesselation(BMEditMesh *tm) +{ + BMEdit_RecalcTesselation_intern(tm); + + if (tm->derivedFinal && tm->derivedFinal == tm->derivedCage) { + if (tm->derivedFinal->recalcTesselation) + tm->derivedFinal->recalcTesselation(tm->derivedFinal); + } else if (tm->derivedFinal) { + if (tm->derivedCage->recalcTesselation) + tm->derivedCage->recalcTesselation(tm->derivedCage); + if (tm->derivedFinal->recalcTesselation) + tm->derivedFinal->recalcTesselation(tm->derivedFinal); + } +} + +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em) +{ + BMesh *bm = em->bm; + int act; + + if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) { + act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act); + } +} + +/*does not free the BMEditMesh struct itself*/ +void BMEdit_Free(BMEditMesh *em) +{ + if(em->derivedFinal) { + if (em->derivedFinal!=em->derivedCage) { + em->derivedFinal->needsFree= 1; + em->derivedFinal->release(em->derivedFinal); + } + em->derivedFinal= NULL; + } + if(em->derivedCage) { + em->derivedCage->needsFree= 1; + em->derivedCage->release(em->derivedCage); + em->derivedCage= NULL; + } + + em->retopo_paint_data= NULL; + + if (em->looptris) MEM_freeN(em->looptris); + + if (em->vert_index) MEM_freeN(em->vert_index); + if (em->edge_index) MEM_freeN(em->edge_index); + if (em->face_index) MEM_freeN(em->face_index); + + BM_Free_Mesh(em->bm); +} + + +/* +ok, basic design: + +the bmesh derivedmesh exposes the mesh as triangles. it stores pointers +to three loops per triangle. the derivedmesh stores a cache of tesselations +for each face. this cache will smartly update as needed (though at first +it'll simply be more brute force). keeping track of face/edge counts may +be a small problbm. + +this won't be the most efficient thing, considering that internal edges and +faces of tesselations are exposed. looking up an edge by index in particular +is likely to be a little slow. +*/ + +typedef struct EditDerivedBMesh { + DerivedMesh dm; + + Object *ob; + BMEditMesh *tc; + + float (*vertexCos)[3]; + float (*vertexNos)[3]; + float (*faceNos)[3]; + + /*lookup caches; these are rebuilt on dm->RecalcTesselation() + (or when the derivedmesh is created, of course)*/ + GHash *vhash, *ehash, *fhash; + BMVert **vtable; + BMEdge **etable; + BMFace **ftable; + + /*private variables, for number of verts/edges/faces + within the above hash/table members*/ + int tv, te, tf; + + /*customdata layout of the tesselated faces*/ + CustomData tessface_layout; +} EditDerivedBMesh; + +static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm) +{ + BMIter iter; + BMHeader *h; + int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + + bmdm->tv = bmdm->tc->bm->totvert; + bmdm->te = bmdm->tc->bm->totedge; + bmdm->tf = bmdm->tc->bm->totface; + + if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL); + if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL); + if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL); + + bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + + if (bmdm->vtable) MEM_freeN(bmdm->vtable); + if (bmdm->etable) MEM_freeN(bmdm->etable); + if (bmdm->ftable) MEM_freeN(bmdm->ftable); + + if (bmdm->tc->bm->totvert) + bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable"); + else bmdm->vtable = NULL; + + if (bmdm->tc->bm->totedge) + bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable"); + else bmdm->etable = NULL; + + if (bmdm->tc->bm->totface) + bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable"); + else bmdm->ftable = NULL; + + for (a=0; a<3; a++) { + h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL); + for (i=0; h; h=BMIter_Step(&iter), i++) { + switch (a) { + case 0: + bmdm->vtable[i] = (BMVert*) h; + BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i)); + break; + case 1: + bmdm->etable[i] = (BMEdge*) h; + BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i)); + break; + case 2: + bmdm->ftable[i] = (BMFace*) h; + BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i)); + break; + + } + } + } +} + +static void bmDM_recalcTesselation(DerivedMesh *dm) +{ + //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + //bmdm_recalc_lookups(bmdm); +} + +static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; + int i; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; i++, eve=BMIter_Step(&iter)) { + if (bmdm->vertexCos) { + func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL); + } else { + func(userData, i, eve->co, eve->no, NULL); + } + } +} +static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + BMIter viter; + + eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&viter), i++) { + BMINDEX_SET(eve, i); + } + + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) + func(userData, i, + bmdm->vertexCos[BMINDEX_GET(eve)], + bmdm->vertexCos[BMINDEX_GET(eve)]); + } else { + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) + func(userData, i, eed->v1->co, eed->v2->co); + } + +} + +static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + BMIter viter; + + eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&viter), i++) { + BMINDEX_SET(eve, i); + } + + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v1)]); + glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v2)]); + } + } + glEnd(); + + } else { + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + glVertex3fv(eed->v1->co); + glVertex3fv(eed->v2->co); + } + } + glEnd(); + } +} + +static void bmDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) +{ + bmDM_drawMappedEdges(dm, NULL, NULL); +} + +static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BMINDEX_SET(eve, i); + + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + setDrawInterpOptions(userData, i, 0.0); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v1)]); + setDrawInterpOptions(userData, i, 1.0); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v2)]); + } + } + glEnd(); + } else { + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + setDrawInterpOptions(userData, i, 0.0); + glVertex3fv(eed->v1->co); + setDrawInterpOptions(userData, i, 1.0); + glVertex3fv(eed->v2->co); + } + } + glEnd(); + } +} + +static void bmDM_drawUVEdges(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; + BMFace *efa; + BMIter iter; + + glBegin(GL_LINES); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BMIter liter; + BMLoop *l; + MLoopUV *lastluv = NULL, *firstluv = NULL; + + if (BM_TestHFlag(efa, BM_HIDDEN)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv) { + if (lastluv) + glVertex2fv(luv->uv); + glVertex2fv(luv->uv); + + lastluv = luv; + if (!firstluv) + firstluv = luv; + } + } + + if (lastluv) { + glVertex2fv(lastluv->uv); + glVertex2fv(firstluv->uv); + } + } + glEnd(); +} + +static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], + float (*vertexCos)[3]) +{ + BMIter iter; + BMLoop *l; + int tot = 0; + + cent[0] = cent[1] = cent[2] = 0.0f; + + /*simple (and stupid) median (average) based method :/ */ + + if (vertexCos) { + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + VECADD(cent, cent, vertexCos[BMINDEX_GET(l->v)]); + tot++; + } + } else { + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + VECADD(cent, cent, l->v->co); + tot++; + } + } + + if (tot==0) return; + mul_v3_fl(cent, 1.0f/(float)tot); +} + +static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMFace *efa; + BMIter iter; + float cent[3]; + int i; + + if (bmdm->vertexCos) { + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BMINDEX_SET(eve, i); + } + + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) { + bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos); + func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no); + } +} + +static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMFace *efa; + BMIter iter; + int i, draw; + + if (bmdm->vertexCos) { + BMVert *eve; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BMINDEX_SET(eve, i); + + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) + BMINDEX_SET(efa, i); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->looptris[i]; + int drawSmooth; + + efa = l[0]->f; + drawSmooth = (efa->head.flag & BM_SMOOTH); + + draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth); + if(draw) { + if (draw==2) { /* enabled with stipple */ + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); + } + + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + + glBegin(GL_TRIANGLES); + + if (!drawSmooth) { + glNormal3fv(bmdm->faceNos[i]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]); + } else { + glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[0]->v)]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]); + glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[1]->v)]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]); + glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[2]->v)]); + glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]); + } + glEnd(); + + if (draw==2) + glDisable(GL_POLYGON_STIPPLE); + } + } + } else { + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) + BMINDEX_SET(efa, i); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->looptris[i]; + int drawSmooth; + + efa = l[0]->f; + drawSmooth = (efa->head.flag & BM_SMOOTH); + + draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth); + if(draw) { + if (draw==2) { /* enabled with stipple */ + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); + } + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + + glBegin(GL_TRIANGLES); + if (!drawSmooth) { + glNormal3fv(efa->no); + glVertex3fv(l[0]->v->co); + glVertex3fv(l[1]->v->co); + glVertex3fv(l[2]->v->co); + } else { + glNormal3fv(l[0]->v->no); + glVertex3fv(l[0]->v->co); + glNormal3fv(l[1]->v->no); + glVertex3fv(l[1]->v->co); + glNormal3fv(l[2]->v->no); + glVertex3fv(l[2]->v->co); + } + glEnd(); + + if (draw==2) + glDisable(GL_POLYGON_STIPPLE); + } + } + } +} + +static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3], + int has_uv, int has_col) +{ + if (has_uv) { + luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV); + luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV); + luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV); + } + + if (has_col) { + lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL); + lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL); + lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL); + } + + +} + +static void bmDM_drawFacesTex_common(DerivedMesh *dm, + int (*drawParams)(MTFace *tface, int has_vcol, int matnr), + int (*drawParamsMapped)(void *userData, int index), + void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; + BMesh *bm= bmdm->tc->bm; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMFace *efa; + BMVert *eve; + BMIter iter; + MLoopUV *luv[3], dummyluv = {0}; + MLoopCol *lcol[3], dummylcol = {0}; + int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL); + int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY); + + luv[0] = luv[1] = luv[2] = &dummyluv; + lcol[0] = lcol[1] = lcol[2] = &dummylcol; + + dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255; + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + i = 0; + BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) + BMINDEX_SET(efa, i++); + + if (vertexCos) { + i = 0; + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) + BMINDEX_SET(eve, i++); + + glBegin(GL_TRIANGLES); + for (i=0; i<em->tottri; i++) { + BMLoop **ls = em->looptris[i]; + MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY); + MTFace mtf = {0}; + unsigned char *cp= NULL; + int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH); + int flag; + + efa = ls[0]->f; + + if (has_uv) { + mtf.flag = tp->flag; + mtf.tpage = tp->tpage; + mtf.transp = tp->transp; + mtf.mode = tp->mode; + mtf.tile = tp->tile; + mtf.unwrap = tp->unwrap; + } + + if(drawParams) + flag= drawParams(&mtf, has_vcol, efa->mat_nr); + else if(drawParamsMapped) + flag= drawParamsMapped(userData, BMINDEX_GET(efa)); + else + flag= 1; + + if(flag != 0) { /* flag 0 == the face is hidden or invisible */ + + /* we always want smooth here since otherwise vertex colors dont interpolate */ + if (!has_vcol) { + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + } + + if (!drawSmooth) { + glNormal3fv(bmdm->faceNos[i]); + + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + glTexCoord2fv(luv[0]->uv); + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]); + + glTexCoord2fv(luv[1]->uv); + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]); + + glTexCoord2fv(luv[2]->uv); + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]); + } else { + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + glTexCoord2fv(luv[0]->uv); + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + glNormal3fv(vertexNos[BMINDEX_GET(ls[0]->v)]); + glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]); + + glTexCoord2fv(luv[1]->uv); + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + glNormal3fv(vertexNos[BMINDEX_GET(ls[1]->v)]); + glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]); + + glTexCoord2fv(luv[2]->uv); + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + glNormal3fv(vertexNos[BMINDEX_GET(ls[2]->v)]); + glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]); + } + } + } + glEnd(); + } else { + i = 0; + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) + BMINDEX_SET(eve, i++); + + for (i=0; i<em->tottri; i++) { + BMLoop **ls = em->looptris[i]; + MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY); + MTFace mtf = {0}; + unsigned char *cp= NULL; + int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH); + int flag; + + efa = ls[0]->f; + + if (has_uv) { + mtf.flag = tp->flag; + mtf.tpage = tp->tpage; + mtf.transp = tp->transp; + mtf.mode = tp->mode; + mtf.tile = tp->tile; + mtf.unwrap = tp->unwrap; + } + + if(drawParams) + flag= drawParams(&mtf, has_vcol, efa->mat_nr); + else if(drawParamsMapped) + flag= drawParamsMapped(userData, BMINDEX_GET(efa)); + else + flag= 1; + + if(flag != 0) { /* flag 0 == the face is hidden or invisible */ + + /* we always want smooth here since otherwise vertex colors dont interpolate */ + if (!has_vcol) { + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + } + + glBegin(GL_TRIANGLES); + if (!drawSmooth) { + glNormal3fv(efa->no); + + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + if (luv[0]) + glTexCoord2fv(luv[0]->uv); + if (lcol[0]) + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[0]->v->co); + + if (luv[1]) + glTexCoord2fv(luv[1]->uv); + if (lcol[1]) + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[1]->v->co); + + if (luv[2]) + glTexCoord2fv(luv[2]->uv); + if (lcol[2]) + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[2]->v->co); + } else { + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + if (luv[0]) + glTexCoord2fv(luv[0]->uv); + if (lcol[0]) + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[0]->v->no); + glVertex3fv(ls[0]->v->co); + + if (luv[1]) + glTexCoord2fv(luv[1]->uv); + if (lcol[1]) + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[1]->v->no); + glVertex3fv(ls[1]->v->co); + + if (luv[2]) + glTexCoord2fv(luv[2]->uv); + if (lcol[2]) + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[2]->v->no); + glVertex3fv(ls[2]->v->co); + } + glEnd(); + } + } + } +} + +static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr)) +{ + bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); +} + +static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +{ + bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); +} + +static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs), + int (*setDrawOptions)(void *userData, int index), void *userData) +{ +#if 0 + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMVert *eve; + BMFace *efa; + DMVertexAttribs attribs; + GPUVertexAttribs gattribs; + MTFace *tf; + int transp, new_transp, orig_transp, tfoffset; + int i, b, matnr, new_matnr, dodraw, layer; + + dodraw = 0; + matnr = -1; + + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + layer = CustomData_get_layer_index(&bm->pdata, CD_MTFACE); + tfoffset = (layer == -1)? -1: bm->pdata.layers[layer].offset; + + memset(&attribs, 0, sizeof(attribs)); + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + for (i=0,eve=bm->verts.first; eve; eve= eve->next) + BMINDEX_SET(eve, i++); + +#define PASSATTRIB(efa, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[BMINDEX_GET(eve)]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].bmOffset); \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].bmOffset); \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[i*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) { + int drawSmooth= (efa->flag & ME_SMOOTH); + + if(setDrawOptions && !setDrawOptions(userData, i)) + continue; + + new_matnr = efa->mat_nr + 1; + if(new_matnr != matnr) { + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(tfoffset != -1) { + tf = (MTFace*)((char*)efa->data)+tfoffset; + new_transp = tf->transp; + + if(new_transp != transp) { + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + } + } + + if(dodraw) { + glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(bmdm->faceNos[i]); + else glNormal3fv(efa->n); + + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + else glVertex3fv(efa->v1->co); + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + else glVertex3fv(efa->v2->co); + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + else glVertex3fv(efa->v3->co); + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + else glVertex3fv(efa->v4->co); + } + } else { + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + } + else { + glNormal3fv(efa->v1->no); + glVertex3fv(efa->v1->co); + } + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + } + else { + glNormal3fv(efa->v2->no); + glVertex3fv(efa->v2->co); + } + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + } + else { + glNormal3fv(efa->v3->no); + glVertex3fv(efa->v3->co); + } + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + } + else { + glNormal3fv(efa->v4->no); + glVertex3fv(efa->v4->co); + } + } + } + glEnd(); + } + } +#endif +} + +static void bmDM_drawFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + +static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; + int i; + + if (bmdm->tc->bm->totvert) { + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + if (bmdm->vertexCos) { + DO_MINMAX(bmdm->vertexCos[i], min_r, max_r); + } else { + DO_MINMAX(eve->co, min_r, max_r); + } + } + } else { + min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; + } +} +static int bmDM_getNumVerts(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totvert; +} + +static int bmDM_getNumEdges(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totedge; +} + +static int bmDM_getNumTessFaces(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->tottri; +} + +static int bmDM_getNumFaces(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totface; +} + +static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r) +{ + VECCOPY(vert_r->co, ev->co); + + vert_r->no[0] = (short)(ev->no[0] * 32767.0f); + vert_r->no[1] = (short)(ev->no[1] * 32767.0f); + vert_r->no[2] = (short)(ev->no[2] * 32767.0f); + + vert_r->flag = BMFlags_To_MEFlags(ev); + + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f); + } + + return 1; +} + +static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) +{ + BMVert *ev; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) { + printf("error in bmDM_getVert.\n"); + return; + } + + ev = ((EditDerivedBMesh *)dm)->vtable[index]; + bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r); +} + +static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *e; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) { + printf("error in bmDM_getEdge.\n"); + return; + } + + e = bmdm->etable[index]; + + if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f); + } + + if (CustomData_has_layer(&bm->edata, CD_CREASE)) { + edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f); + } + + edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; + edge_r->flag |= BMFlags_To_MEFlags(e); +#if 0 + /* this needs setup of f2 field */ + if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; +#endif + + edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1)); + edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2)); +} + +static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMFace *ef; + BMLoop **l; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) { + printf("error in bmDM_getTessFace.\n"); + return; + } + + l = ((EditDerivedBMesh *)dm)->tc->looptris[index]; + + ef = l[0]->f; + + face_r->mat_nr = (unsigned char) ef->mat_nr; + face_r->flag = BMFlags_To_MEFlags(ef); + + face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v)); + face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v)); + face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v)); + face_r->v4 = 0; + + test_index_face(face_r, NULL, 0, 3); +} + +static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) +{ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMVert *ev; + BMIter iter; + + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for( ; ev; ev = BMIter_Step(&iter), ++vert_r) { + VECCOPY(vert_r->co, ev->co); + + vert_r->no[0] = (short) (ev->no[0] * 32767.0); + vert_r->no[1] = (short) (ev->no[1] * 32767.0); + vert_r->no[2] = (short) (ev->no[2] * 32767.0); + + vert_r->flag = BMFlags_To_MEFlags(ev); + + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f); + } + } +} + +static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) +{ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *ee; + BMIter iter; + BMVert *ev; + int i; + + /* store vertex indices in tmp union */ + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; ev; ev=BMIter_Step(&iter), i++) + BMINDEX_SET(ev, i); + + ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for( ; ee; ee=BMIter_Step(&iter)) { + if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f); + } + + if (CustomData_has_layer(&bm->edata, CD_CREASE)) { + edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f); + } + + edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; + if (ee->head.flag & BM_SEAM) edge_r->flag |= ME_SEAM; + if (ee->head.flag & BM_SHARP) edge_r->flag |= ME_SHARP; +#if 0 + /* this needs setup of f2 field */ + if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; +#endif + + edge_r->v1 = (int)BMINDEX_GET(ee->v1); + edge_r->v2 = (int)BMINDEX_GET(ee->v2); + } +} + +static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMFace *ef; + BMVert *ev; + BMIter iter; + BMLoop **l; + int i; + + /* store vertexes indices in tmp union */ + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; ev; ev=BMIter_Step(&iter), i++) + BMINDEX_SET(ev, i); + + for (i=0; i<bmdm->tc->tottri; i++) { + l = bmdm->tc->looptris[i]; + ef = l[0]->f; + + face_r->mat_nr = (unsigned char) ef->mat_nr; + + /*HACK/TODO: need to convert this*/ + face_r->flag = ef->head.flag; + + face_r->v1 = BMINDEX_GET(l[0]->v); + face_r->v2 = BMINDEX_GET(l[1]->v); + face_r->v3 = BMINDEX_GET(l[2]->v); + face_r->v4 = 0; + + test_index_face(face_r, NULL, 0, 3); + } +} + +static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMFace *efa; + char *data, *bmdata; + void *datalayer; + int index, offset, size, i; + + datalayer = DM_get_tessface_data_layer(dm, type); + if(datalayer) + return datalayer; + + /* layers are store per face for editmesh, we convert to a tbmporary + * data layer array in the derivedmesh when these are requested */ + if(type == CD_MTFACE || type == CD_MCOL) { + index = CustomData_get_layer_index(&bm->pdata, type); + + if(index != -1) { + offset = bm->pdata.layers[index].offset; + size = CustomData_sizeof(type); + + DM_add_tessface_layer(dm, type, CD_CALLOC, NULL); + index = CustomData_get_layer_index(&dm->faceData, type); + dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; + + data = datalayer = DM_get_tessface_data_layer(dm, type); + for (i=0; i<bmdm->tc->tottri; i++, data+=size) { + efa = bmdm->tc->looptris[i][0]->f; + /*BMESH_TODO: need to still add tface data, + derived from the loops.*/ + bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type); + memcpy(data, bmdata, size); + } + } + } + + return datalayer; +} + +typedef struct bmDM_loopIter { + DMLoopIter head; + + BMFace *f; + BMLoop *l, *nextl; + BMIter iter; + BMesh *bm; +} bmDM_loopIter; + +typedef struct bmDM_faceIter { + DMFaceIter head; + + BMFace *f, *nextf; + BMIter iter; + BMesh *bm; + + bmDM_loopIter loopiter; +} bmDM_faceIter; + +void bmDM_faceIterStep(void *self) +{ + bmDM_faceIter *iter = self; + + if (iter->f) { + iter->f->mat_nr = iter->head.mat_nr; + iter->f->head.flag = MEFlags_To_BMFlags(iter->head.flags, BM_FACE); + } + + iter->f = iter->nextf; + + iter->head.mat_nr = iter->f->mat_nr; + iter->head.flags = BMFlags_To_MEFlags(iter->f); + iter->head.index++; + + iter->head.len = iter->f->len; + + iter->nextf = BMIter_Step(&iter->iter); + + if (!iter->nextf) iter->head.done = 1; +} + +void *bmDM_getFaceCDData(void *self, int type, int layer) +{ + bmDM_faceIter *iter = self; + + if (layer == -1) + return CustomData_bmesh_get(&iter->bm->pdata, iter->f->head.data, type); + else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->head.data, type, layer); +} + +void bmDM_loopIterStep(void *self) +{ + bmDM_loopIter *iter = self; + + iter->l = BMIter_Step(&iter->iter); + if (!iter->l) { + iter->head.done = 1; + return; + } + + bmvert_to_mvert(iter->bm, iter->l->v, &iter->head.v); + iter->head.index++; + iter->head.vindex = BMINDEX_GET(iter->l->v); + iter->head.eindex = BMINDEX_GET(iter->l->e); +} + +void *bmDM_getLoopCDData(void *self, int type, int layer) +{ + bmDM_loopIter *iter = self; + + if (layer == -1) + return CustomData_bmesh_get(&iter->bm->ldata, iter->l->head.data, type); + else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->head.data, type, layer); +} + +void *bmDM_getVertCDData(void *self, int type, int layer) +{ + bmDM_loopIter *iter = self; + + if (layer == -1) + return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->head.data, type); + else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->head.data, type, layer); +} + +void bmDM_iterFree(void *self) +{ + MEM_freeN(self); +} + +void bmDM_nulliterFree(void *self) +{ +} + +DMLoopIter *bmDM_newLoopsIter(void *faceiter) +{ + bmDM_faceIter *fiter = faceiter; + bmDM_loopIter *iter = &fiter->loopiter; + + memset(&fiter->loopiter, 0, sizeof(bmDM_loopIter)); + + iter->bm = fiter->bm; + iter->f = fiter->f; + iter->l = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f); + + iter->head.step = bmDM_loopIterStep; + iter->head.getLoopCDData = bmDM_getLoopCDData; + iter->head.getVertCDData = bmDM_getVertCDData; + + bmvert_to_mvert(iter->bm, iter->l->v, &iter->head.v); + iter->head.vindex = BMINDEX_GET(iter->l->v); + iter->head.eindex = BMINDEX_GET(iter->l->e); + + return (DMLoopIter*) iter; +} + +static DMFaceIter *bmDM_getFaceIter(void *dm) +{ + EditDerivedBMesh *bmdm= dm; + bmDM_faceIter *iter = MEM_callocN(sizeof(bmDM_faceIter), "bmDM_faceIter"); + BMIter biter; + BMVert *v; + BMEdge *e; + int i; + + iter->bm = bmdm->tc->bm; + iter->f = iter->nextf = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL); + + iter->head.step = bmDM_faceIterStep; + iter->head.free = bmDM_iterFree; + iter->head.getCDData = bmDM_getFaceCDData; + iter->head.getLoopsIter = bmDM_newLoopsIter; + + iter->head.mat_nr = iter->f->mat_nr; + iter->head.flags = BMFlags_To_MEFlags(iter->f); + + /*set up vert/edge indices*/ + i = 0; + BM_ITER(v, &biter, iter->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(v, i); + i++; + } + + i = 0; + BM_ITER(e, &biter, iter->bm, BM_EDGES_OF_MESH, NULL) { + BMINDEX_SET(e, i); + i++; + } + + return (DMFaceIter*) iter; +} + +static void bmDM_release(void *dm) +{ + EditDerivedBMesh *bmdm= dm; + + if (DM_release(dm)) { + if (bmdm->vertexCos) { + MEM_freeN(bmdm->vertexCos); + MEM_freeN(bmdm->vertexNos); + MEM_freeN(bmdm->faceNos); + } + + if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL); + if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL); + if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL); + + if (bmdm->vtable) MEM_freeN(bmdm->vtable); + if (bmdm->etable) MEM_freeN(bmdm->etable); + if (bmdm->ftable) MEM_freeN(bmdm->ftable); + + MEM_freeN(bmdm); + } +} + +CustomData *bmDm_getVertDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->vdata; +} + +CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->edata; +} + +CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tessface_layout; +} + +CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->ldata; +} + +CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->pdata; +} + + +DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob, + float (*vertexCos)[3]) +{ + EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm"); + BMesh *bm = em->bm; + int i; + + bmdm->tc = em; + + DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert, + em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface); + + for (i=0; i<bm->ldata.totlayer; i++) { + if (bm->ldata.layers[i].type == CD_MLOOPCOL) { + CustomData_add_layer(&bmdm->tessface_layout, CD_MCOL, CD_ASSIGN, NULL, 0); + } else if (bm->ldata.layers[i].type == CD_MLOOPUV) { + CustomData_add_layer(&bmdm->tessface_layout, CD_MTFACE, CD_ASSIGN, NULL, 0); + } + } + + bmdm->dm.numVertData = bm->totvert; + bmdm->dm.numEdgeData = bm->totedge; + bmdm->dm.numFaceData = em->tottri; + bmdm->dm.numLoopData = bm->totloop; + bmdm->dm.numPolyData = bm->totface; + + bmdm->dm.getMinMax = bmDM_getMinMax; + + bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout; + bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout; + bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout; + bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout; + bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout; + + bmdm->dm.getNumVerts = bmDM_getNumVerts; + bmdm->dm.getNumEdges = bmDM_getNumEdges; + bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces; + bmdm->dm.getNumFaces = bmDM_getNumFaces; + + bmdm->dm.getVert = bmDM_getVert; + bmdm->dm.getEdge = bmDM_getEdge; + bmdm->dm.getTessFace = bmDM_getTessFace; + bmdm->dm.copyVertArray = bmDM_copyVertArray; + bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray; + bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray; + bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray; + + bmdm->dm.newFaceIter = bmDM_getFaceIter; + bmdm->dm.recalcTesselation = bmDM_recalcTesselation; + + bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert; + bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge; + bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter; + + bmdm->dm.drawEdges = bmDM_drawEdges; + bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges; + bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp; + bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces; + bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex; + bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL; + bmdm->dm.drawFacesTex = bmDM_drawFacesTex; + bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL; + bmdm->dm.drawUVEdges = bmDM_drawUVEdges; + + bmdm->dm.release = bmDM_release; + + bmdm->vertexCos = vertexCos; + + if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) { + BMIter iter; + BMVert *eve; + int i; + + DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL); + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT, + CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT)); + } + + if(vertexCos) { + BMVert *eve; + BMIter iter; + int totface = bmdm->tc->tottri; + int i; + + eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BMINDEX_SET(eve, i); + + bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno"); + bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno"); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->looptris[i]; + float *v1 = vertexCos[(int) BMINDEX_GET(l[0]->v)]; + float *v2 = vertexCos[(int) BMINDEX_GET(l[1]->v)]; + float *v3 = vertexCos[(int) BMINDEX_GET(l[2]->v)]; + float *no = bmdm->faceNos[i]; + + normal_tri_v3( no,v1, v2, v3); + add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[0]->v)], bmdm->vertexNos[BMINDEX_GET(l[0]->v)], no); + add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[1]->v)], bmdm->vertexNos[BMINDEX_GET(l[1]->v)], no); + add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[2]->v)], bmdm->vertexNos[BMINDEX_GET(l[2]->v)], no); + } + + eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + float *no = bmdm->vertexNos[i]; + /* following Mesh convention; we use vertex coordinate itself + * for normal in this case */ + if (normalize_v3(no)==0.0) { + VECCOPY(no, vertexCos[i]); + normalize_v3(no); + } + } + } + + //bmdm_recalc_lookups(bmdm); + + return (DerivedMesh*) bmdm; +} diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index ddfc58b7491..5d8401d7a43 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -576,7 +576,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surfa } if(surface_vel) { - MFace *mface = CDDM_get_face(surmd->dm, nearest.index); + MFace *mface = CDDM_get_tessface(surmd->dm, nearest.index); VECCOPY(surface_vel, surmd->v[mface->v1].co); add_v3_v3(surface_vel, surmd->v[mface->v2].co); diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 4a6638ff3a0..4afce1e56c4 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -534,8 +534,8 @@ static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL) static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm) { MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getFaceArray(dm); - int i, numfacets = 0, totface = dm->getNumFaces(dm); + MFace *mface = dm->getTessFaceArray(dm); + int i, numfacets = 0, totface = dm->getNumTessFaces(dm); float zero[3] = {0.0f, 0.0f, 0.0f}; for (i=0; i<totface; i++, mface++) { diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index bb56a5b176a..810c56dbe5d 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -62,7 +62,6 @@ /* ************************* fluidsim bobj file handling **************************** */ - //------------------------------------------------------------------------------- // file handling //------------------------------------------------------------------------------- @@ -83,9 +82,9 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob, //dm = mesh_create_derived_no_deform(ob,NULL); mvert = dm->getVertArray(dm); - mface = dm->getFaceArray(dm); + mface = dm->getTessFaceArray(dm); totvert = dm->getNumVerts(dm); - totface = dm->getNumFaces(dm); + totface = dm->getNumTessFaces(dm); *numVertices = totvert; verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices"); diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index f979973f55d..804c26295bd 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1,5 +1,5 @@ /* - * $Id$ + * $Id: fmodifier.c 21537 2009-07-11 22:22:53Z gsrb3d $ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index bf0427e4fee..05988605b4c 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -261,7 +261,7 @@ static PackedFile *get_builtin_packedfile(void) void free_ttfont(void) { struct TmpFont *tf; - + for(tf= ttfdata.first; tf; tf= tf->next) { if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */ tf->pf= NULL; diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 6c8b5329711..6c8b5329711 100644..100755 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 3681dc910cd..5c10c14c4e2 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -56,11 +56,13 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_tessmesh.h" #include "BKE_main.h" #include "BKE_object.h" #include "RNA_access.h" +#include "BLI_cellalloc.h" #define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */ #define KEY_MODE_BPOINT 1 @@ -90,6 +92,20 @@ void free_key(Key *key) } +void free_key_nolib(Key *key) +{ + KeyBlock *kb; + + while( (kb= key->block.first) ) { + + if(kb->data) MEM_freeN(kb->data); + + BLI_remlink(&key->block, kb); + MEM_freeN(kb); + } + +} + /* GS reads the memory pointed at in a specific ordering. There are, * however two definitions for it. I have jotted them down here, both, * but I think the first one is actually used. The thing is that @@ -112,6 +128,8 @@ Key *add_key(ID *id) /* common function */ key->type= KEY_NORMAL; key->from= id; + + key->uidgen = 1; // XXX the code here uses some defines which will soon be depreceated... if( GS(id->name)==ID_ME) { @@ -170,6 +188,32 @@ Key *copy_key(Key *key) return keyn; } + +Key *copy_key_nolib(Key *key) +{ + Key *keyn; + KeyBlock *kbn, *kb; + + if(key==0) return 0; + + keyn= MEM_dupallocN(key); + + BLI_duplicatelist(&keyn->block, &key->block); + + kb= key->block.first; + kbn= keyn->block.first; + while(kbn) { + + if(kbn->data) kbn->data= MEM_dupallocN(kbn->data); + if(kb==key->refkey) keyn->refkey= kbn; + + kbn= kbn->next; + kb= kb->next; + } + + return keyn; +} + void make_local_key(Key *key) { @@ -493,18 +537,21 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char ** edit mode with shape keys blending applied */ if(GS(key->from->name) == ID_ME) { Mesh *me; - EditVert *eve; + BMVert *eve; + BMIter iter; float (*co)[3]; int a; me= (Mesh*)key->from; - if(me->edit_mesh && me->edit_mesh->totvert == kb->totelem) { + if(me->edit_btmesh && me->edit_btmesh->bm->totvert == kb->totelem) { a= 0; - co= MEM_callocN(sizeof(float)*3*me->edit_mesh->totvert, "key_block_get_data"); + co= MEM_callocN(sizeof(float)*3*me->edit_btmesh->bm->totvert, "key_block_get_data"); - for(eve=me->edit_mesh->verts.first; eve; eve=eve->next, a++) + BM_ITER(eve, &iter, me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL) { VECCOPY(co[a], eve->co); + a++; + } *freedata= (char*)co; return (char*)co; @@ -998,8 +1045,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key static float *get_weights_array(Object *ob, char *vgroup) { MDeformVert *dvert= NULL; - EditMesh *em= NULL; - EditVert *eve; + BMEditMesh *em= NULL; + BMIter iter; + BMVert *eve; int totvert= 0, index= 0; /* no vgroup string set? */ @@ -1011,8 +1059,8 @@ static float *get_weights_array(Object *ob, char *vgroup) dvert= me->dvert; totvert= me->totvert; - if(me->edit_mesh && me->edit_mesh->totvert == totvert) - em= me->edit_mesh; + if(me->edit_btmesh && me->edit_btmesh->bm->totvert == totvert) + em= me->edit_btmesh; } else if(ob->type==OB_LATTICE) { Lattice *lt= ob->data; @@ -1031,8 +1079,9 @@ static float *get_weights_array(Object *ob, char *vgroup) weights= MEM_callocN(totvert*sizeof(float), "weights"); if(em) { - for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) { - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); if(dvert) { for(j=0; j<dvert->totweight; j++) { @@ -1459,7 +1508,8 @@ KeyBlock *add_keyblock(Key *key, const char *name) // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey) kb->adrcode= tot-1; - + kb->uid = key->uidgen++; + key->totkey++; if(key->totkey==1) key->refkey= kb; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index b0f90ef8042..70eba3903d0 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "DNA_mesh_types.h" diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 05d1e5841dc..cb96f549829 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -728,7 +728,7 @@ void free_libblock(ListBase *lb, void *idv) free_object((Object *)id); break; case ID_ME: - free_mesh((Mesh *)id); + free_mesh((Mesh *)id, 1); break; case ID_CU: free_curve((Curve *)id); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 3c56cb4663b..f6679315606 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -42,15 +42,18 @@ #include "DNA_key_types.h" #include "DNA_meshdata_types.h" #include "DNA_ipo_types.h" +#include "DNA_customdata_types.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_edgehash.h" #include "BLI_utildefines.h" +#include "BLI_scanfill.h" #include "BKE_animsys.h" #include "BKE_main.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" @@ -64,20 +67,316 @@ #include "BKE_curve.h" /* -- */ #include "BKE_object.h" +#include "BKE_tessmesh.h" +#include "BLI_edgehash.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_math.h" +#include "BLI_cellalloc.h" +#include "BLI_array.h" +#include "BLI_edgehash.h" + +#include "bmesh.h" + +enum { + MESHCMP_DVERT_WEIGHTMISMATCH = 1, + MESHCMP_DVERT_GROUPMISMATCH, + MESHCMP_DVERT_TOTGROUPMISMATCH, + MESHCMP_LOOPCOLMISMATCH, + MESHCMP_LOOPUVMISMATCH, + MESHCMP_LOOPMISMATCH, + MESHCMP_POLYVERTMISMATCH, + MESHCMP_POLYMISMATCH, + MESHCMP_EDGEUNKNOWN, + MESHCMP_VERTCOMISMATCH, + MESHCMP_CDLAYERS_MISMATCH, +}; + +static char *cmpcode_to_str(int code) +{ + switch (code) { + case MESHCMP_DVERT_WEIGHTMISMATCH: + return "Vertex Weight Mismatch"; + case MESHCMP_DVERT_GROUPMISMATCH: + return "Vertex Group Mismatch"; + case MESHCMP_DVERT_TOTGROUPMISMATCH: + return "Vertex Doesn't Belong To Same Number Of Groups"; + case MESHCMP_LOOPCOLMISMATCH: + return "Vertex Color Mismatch"; + case MESHCMP_LOOPUVMISMATCH: + return "UV Mismatch"; + case MESHCMP_LOOPMISMATCH: + return "Loop Mismatch"; + case MESHCMP_POLYVERTMISMATCH: + return "Loop Vert Mismatch In Poly Test"; + case MESHCMP_POLYMISMATCH: + return "Loop Vert Mismatch"; + case MESHCMP_EDGEUNKNOWN: + return "Edge Mismatch"; + case MESHCMP_VERTCOMISMATCH: + return "Vertex Coordinate Mismatch"; + case MESHCMP_CDLAYERS_MISMATCH: + "CustomData Layer Count Mismatch"; + default: + return "Mesh Comparison Code Unknown"; + } +} + +/*thresh is threshold for comparing vertices, uvs, vertex colors, + weights, etc.*/ +int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, float thresh) +{ + CustomDataLayer *l1, *l2; + int i, i1=0, i2=0, tot, j; + + for (i=0; i<c1->totlayer; i++) { + if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + i1++; + } + + for (i=0; i<c2->totlayer; i++) { + if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + i2++; + } + + if (i1 != i2) + return MESHCMP_CDLAYERS_MISMATCH; + + l1 = c1->layers; l2 = c2->layers; + tot = i1; + i1 = 0; i2 = 0; + for (i=0; i < tot; i++) { + while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + i1++, l1++; + + while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + i2++, l2++; + + if (l1->type == CD_MVERT) { + MVert *v1 = l1->data; + MVert *v2 = l2->data; + int vtot = m1->totvert; + + for (j=0; j<vtot; j++, v1++, v2++) { + if (len_v3v3(v1->co, v2->co) > thresh) + return MESHCMP_VERTCOMISMATCH; + /*I don't care about normals, let's just do coodinates*/ + } + } + + /*we're order-agnostic for edges here*/ + if (l1->type == CD_MEDGE) { + MEdge *e1 = l1->data; + MEdge *e2 = l2->data; + EdgeHash *eh = BLI_edgehash_new(); + int etot = m1->totedge; + + for (j=0; j<etot; j++, e1++) { + BLI_edgehash_insert(eh, e1->v1, e1->v2, e1); + } + + for (j=0; j<etot; j++, e2++) { + if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) + return MESHCMP_EDGEUNKNOWN; + } + BLI_edgehash_free(eh, NULL); + } + + if (l1->type == CD_MPOLY) { + MPoly *p1 = l1->data; + MPoly *p2 = l2->data; + int ptot = m1->totpoly; + + for (j=0; j<ptot; j++, p1++, p2++) { + MLoop *lp1, *lp2; + int k; + + if (p1->totloop != p2->totloop) + return MESHCMP_POLYMISMATCH; + + lp1 = m1->mloop + p1->loopstart; + lp2 = m2->mloop + p2->loopstart; + + for (k=0; k<p1->totloop; k++, lp1++, lp2++) { + if (lp1->v != lp2->v) + return MESHCMP_POLYVERTMISMATCH; + } + } + } + if (l1->type == CD_MLOOP) { + MLoop *lp1 = l1->data; + MLoop *lp2 = l2->data; + int ltot = m1->totloop; + + for (j=0; j<ltot; j++, lp1++, lp2++) { + if (lp1->v != lp2->v) + return MESHCMP_LOOPMISMATCH; + } + } + if (l1->type == CD_MLOOPUV) { + MLoopUV *lp1 = l1->data; + MLoopUV *lp2 = l2->data; + int ltot = m1->totloop; + + for (j=0; j<ltot; j++, lp1++, lp2++) { + if (len_v2v2(lp1->uv, lp2->uv) > thresh) + return MESHCMP_LOOPUVMISMATCH; + } + } + + if (l1->type == CD_MLOOPCOL) { + MLoopCol *lp1 = l1->data; + MLoopCol *lp2 = l2->data; + int ltot = m1->totloop; + + for (j=0; j<ltot; j++, lp1++, lp2++) { + if (ABS(lp1->r - lp2->r) > thresh || + ABS(lp1->g - lp2->g) > thresh || + ABS(lp1->b - lp2->b) > thresh || + ABS(lp1->a - lp2->a) > thresh) + { + return MESHCMP_LOOPCOLMISMATCH; + } + } + } + if (l1->type == CD_MDEFORMVERT) { + MDeformVert *dv1 = l1->data; + MDeformVert *dv2 = l2->data; + int dvtot = m1->totvert; + + for (j=0; j<dvtot; j++, dv1++, dv2++) { + int k; + MDeformWeight *dw1 = dv1->dw, *dw2=dv2->dw; + + if (dv1->totweight != dv2->totweight) + return MESHCMP_DVERT_TOTGROUPMISMATCH; + + for (k=0; k<dv1->totweight; k++, dw1++, dw2++) { + if (dw1->def_nr != dw2->def_nr) + return MESHCMP_DVERT_GROUPMISMATCH; + if (ABS(dw1->weight - dw2->weight) > thresh) + return MESHCMP_DVERT_WEIGHTMISMATCH; + } + } + } + } + + return 0; +} -EditMesh *BKE_mesh_get_editmesh(Mesh *me) +/*used for testing. returns an error string the two meshes don't match*/ +char *mesh_cmp(Mesh *me1, Mesh *me2, float thresh) { - return me->edit_mesh; + int c; + + if (!me1 || !me2) + return "Requires two input meshes"; + + if (me1->totvert != me2->totvert) + return "Number of verts don't match"; + + if (me1->totedge != me2->totedge) + return "Number of edges don't match"; + + if (me1->totpoly != me2->totpoly) + return "Number of faces don't match"; + + if (me1->totloop !=me2->totloop) + return "Number of loops don't match"; + + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) + return cmpcode_to_str(c); + + if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) + return cmpcode_to_str(c); + + if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) + return cmpcode_to_str(c); + + if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) + return cmpcode_to_str(c); + + return NULL; } -void BKE_mesh_end_editmesh(Mesh *UNUSED(me), EditMesh *UNUSED(em)) +static void mesh_ensure_tesselation_customdata(Mesh *me) { + int tottex, totcol; + + tottex = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + totcol = CustomData_number_of_layers(&me->fdata, CD_MCOL); + + if (tottex != CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY) || + totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL)) + { + CustomData_free(&me->fdata, me->totface); + + me->mface = NULL; + me->mtface = NULL; + me->mcol = NULL; + me->totface = 0; + + memset(&me->fdata, 0, sizeof(&me->fdata)); + + CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface); + printf("Warning! Tesselation uvs or vcol data got out of sync, had to reset!\n"); + } } +/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or + mloopcol and mcol) have the same relative active/render/clone/mask indices.*/ +void mesh_update_linked_customdata(Mesh *me) +{ + int act; + + if (me->edit_btmesh) + BMEdit_UpdateLinkedCustomData(me->edit_btmesh); + + mesh_ensure_tesselation_customdata(me); + + if (CustomData_has_layer(&me->pdata, CD_MTEXPOLY)) { + act = CustomData_get_active_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_active(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_render_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_render(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_render(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_clone_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_clone(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_clone(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_stencil_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_stencil(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_stencil(&me->fdata, CD_MTFACE, act); + } + + if (CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) { + act = CustomData_get_active_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_active(&me->fdata, CD_MCOL, act); + + act = CustomData_get_render_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_render(&me->fdata, CD_MCOL, act); + + act = CustomData_get_clone_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_clone(&me->fdata, CD_MCOL, act); + + act = CustomData_get_stencil_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_stencil(&me->fdata, CD_MCOL, act); + } +} void mesh_update_customdata_pointers(Mesh *me) { + mesh_update_linked_customdata(me); + me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY); @@ -87,6 +386,13 @@ void mesh_update_customdata_pointers(Mesh *me) me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); + + me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); + me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); + + me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY); + me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); + me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); } /* Note: unlinking is called when me->id.us is 0, question remains how @@ -117,9 +423,10 @@ void unlink_mesh(Mesh *me) /* do not free mesh itself */ -void free_mesh(Mesh *me) +void free_mesh(Mesh *me, int unlink) { - unlink_mesh(me); + if (unlink) + unlink_mesh(me); if(me->pv) { if(me->pv->vert_map) MEM_freeN(me->pv->vert_map); @@ -135,7 +442,9 @@ void free_mesh(Mesh *me) CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); - + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + if(me->adt) { BKE_free_animdata(&me->id); me->adt= NULL; @@ -145,7 +454,7 @@ void free_mesh(Mesh *me) if(me->bb) MEM_freeN(me->bb); if(me->mselect) MEM_freeN(me->mselect); - if(me->edit_mesh) MEM_freeN(me->edit_mesh); + if(me->edit_btmesh) MEM_freeN(me->edit_btmesh); } void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) @@ -160,7 +469,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) for (i=0; i<copycount; i++){ if (src[i].dw){ - dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); + dst[i].dw = BLI_cellalloc_calloc (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight); } } @@ -179,7 +488,7 @@ void free_dverts(MDeformVert *dvert, int totvert) /* Free any special data from the verts */ for (i=0; i<totvert; i++){ - if (dvert[i].dw) MEM_freeN (dvert[i].dw); + if (dvert[i].dw) BLI_cellalloc_free (dvert[i].dw); } MEM_freeN (dvert); } @@ -204,6 +513,7 @@ Mesh *copy_mesh(Mesh *me) { Mesh *men; MTFace *tface; + MTexPoly *txface; int a, i; men= copy_libblock(me); @@ -217,6 +527,8 @@ Mesh *copy_mesh(Mesh *me) CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert); CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge); CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface); + CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop); + CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly); mesh_update_customdata_pointers(men); /* ensure indirect linked data becomes lib-extern */ @@ -229,7 +541,17 @@ Mesh *copy_mesh(Mesh *me) id_lib_extern((ID*)tface->tpage); } } - + + for(i=0; i<me->pdata.totlayer; i++) { + if(me->pdata.layers[i].type == CD_MTEXPOLY) { + txface= (MTexPoly*)me->pdata.layers[i].data; + + for(a=0; a<me->totpoly; a++, txface++) + if(txface->tpage) + id_lib_extern((ID*)txface->tpage); + } + } + men->mselect= NULL; men->bb= MEM_dupallocN(men->bb); @@ -240,12 +562,43 @@ Mesh *copy_mesh(Mesh *me) return men; } +BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob) +{ + BMesh *bm; + int allocsize[4] = {512,512,2048,512}; + + bm = BM_Make_Mesh(allocsize); + + BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p", me, ob); + + return bm; +} + void make_local_tface(Mesh *me) { MTFace *tface; + MTexPoly *txface; Image *ima; int a, i; + for(i=0; i<me->pdata.totlayer; i++) { + if(me->pdata.layers[i].type == CD_MTEXPOLY) { + txface= (MTexPoly*)me->fdata.layers[i].data; + + for(a=0; a<me->totpoly; a++, txface++) { + /* special case: ima always local immediately */ + if(txface->tpage) { + ima= txface->tpage; + if(ima->id.lib) { + ima->id.lib= 0; + ima->id.flag= LIB_LOCAL; + new_id(0, (ID *)ima, 0); + } + } + } + } + } + for(i=0; i<me->fdata.totlayer; i++) { if(me->fdata.layers[i].type == CD_MTFACE) { tface= (MTFace*)me->fdata.layers[i].data; @@ -263,6 +616,7 @@ void make_local_tface(Mesh *me) } } } + } void make_local_mesh(Mesh *me) @@ -1076,10 +1430,10 @@ void mesh_to_curve(Scene *scene, Object *ob) MVert *mverts= dm->getVertArray(dm); MEdge *med, *medge= dm->getEdgeArray(dm); - MFace *mf, *mface= dm->getFaceArray(dm); + MFace *mf, *mface= dm->getTessFaceArray(dm); int totedge = dm->getNumEdges(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumTessFaces(dm); int totedges = 0; int i, needsFree = 0; @@ -1536,6 +1890,285 @@ void mesh_pmv_off(Mesh *me) } } +static void mesh_loops_to_corners(CustomData *fdata, CustomData *ldata, + CustomData *pdata, int lindex[4], int findex, + int polyindex, int numTex, int numCol, int tot) +{ + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + for (j=0; j<tot; j++) { + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); + + for (j=0; j<tot; j++) { + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL); + + for (j=0; j<tot; j++) { + mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + +/* + this function recreates a tesselation. + returns number of tesselation faces. + + use_poly_origindex sets whether or not the tesselation faces' origindex + layer should point to original poly indices or real poly indices. + + use_face_origindex sets the tesselation faces' origindex layer + to point to the tesselation faces themselves, not the polys. + + if both of the above are 0, it'll use the indices of the mpolys of the MPoly + data in pdata, and ignore the origindex layer altogether. + */ +int mesh_recalcTesselation(CustomData *fdata, + CustomData *ldata, CustomData *pdata, + MVert *mvert, int totface, int totloop, + int totpoly, int use_poly_origindex, + int use_face_origindex) +{ + MPoly *mp, *mpoly; + MLoop *ml, *mloop; + MFace *mf = NULL, *mface; + BLI_array_declare(mf); + EditVert *v, *lastv, *firstv; + EditFace *f; + BLI_array_declare(origIndex); + int i, j, k, lindex[4], *origIndex = NULL, *polyorigIndex; + int numTex, numCol; + + mpoly = CustomData_get_layer(pdata, CD_MPOLY); + mloop = CustomData_get_layer(ldata, CD_MLOOP); + + numTex = CustomData_number_of_layers(ldata, CD_MLOOPUV); + numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + + k = 0; + mp = mpoly; + polyorigIndex = use_poly_origindex? CustomData_get_layer(pdata, CD_ORIGINDEX) : NULL; + for (i=0; i<totpoly; i++, mp++) { + if (mp->totloop > 2) { + ml = mloop + mp->loopstart; + + firstv = NULL; + lastv = NULL; + for (j=0; j<mp->totloop; j++, ml++) { + v = BLI_addfillvert(mvert[ml->v].co); + if (polyorigIndex && use_poly_origindex) + v->tmp.l = polyorigIndex[i]; + else + v->tmp.l = i; + + v->keyindex = mp->loopstart + j; + + if (lastv) + BLI_addfilledge(lastv, v); + + if (!firstv) + firstv = v; + lastv = v; + } + BLI_addfilledge(lastv, firstv); + + BLI_edgefill(0); + for (f=fillfacebase.first; f; f=f->next) { + BLI_array_growone(mf); + BLI_array_growone(origIndex); + + /*these are loop indices, they'll be transformed + into vert indices later.*/ + mf[k].v1 = f->v1->keyindex; + mf[k].v2 = f->v2->keyindex; + mf[k].v3 = f->v3->keyindex; + + /*put poly index in mf->v4*/ + mf[k].v4 = f->v1->tmp.l; + + mf[k].mat_nr = mp->mat_nr; + mf[k].flag = mp->flag; + origIndex[k] = use_face_origindex ? k : f->v1->tmp.l; + + k++; + } + + BLI_end_edgefill(); + } + } + + CustomData_free(fdata, totface); + memset(fdata, 0, sizeof(CustomData)); + totface = k; + + CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mf, totface); + CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, origIndex, totface); + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + mface = mf; + for (i=0; i<totface; i++, mf++) { + /*sort loop indices to ensure winding is correct*/ + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + + mesh_loops_to_corners(fdata, ldata, pdata, + lindex, i, mf->v4, numTex, numCol, 3); + + mf->v4 = 0; + } + + return totface; +} + +/* + * COMPUTE POLY NORMAL + * + * Computes the normal of a planar + * polygon See Graphics Gems for + * computing newell normal. + * +*/ +static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvert, float *normal) +{ + + MVert *v1, *v2, *v3; + double u[3], v[3], w[3]; + double n[3] = {0.0, 0.0, 0.0}, l; + int i, s=0; + + for(i = 0; i < mpoly->totloop; i++){ + v1 = mvert + loopstart[i].v; + v2 = mvert + loopstart[(i+1)%mpoly->totloop].v; + v3 = mvert + loopstart[(i+2)%mpoly->totloop].v; + + VECCOPY(u, v1->co); + VECCOPY(v, v2->co); + VECCOPY(w, v3->co); + + /*this fixes some weird numerical error*/ + if (i==0) { + u[0] += 0.0001f; + u[1] += 0.0001f; + u[2] += 0.0001f; + } + + /* newell's method + + so thats?: + (a[1] - b[1]) * (a[2] + b[2]); + a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2] + + odd. half of that is the cross product. . .what's the + other half? + + also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2]) + */ + + n[0] += (u[1] - v[1]) * (u[2] + v[2]); + n[1] += (u[2] - v[2]) * (u[0] + v[0]); + n[2] += (u[0] - v[0]) * (u[1] + v[1]); + } + + l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; + l = sqrt(l); + + if (l == 0.0) { + normal[0] = 0.0f; + normal[1] = 0.0f; + normal[2] = 1.0f; + + return; + } else l = 1.0f / l; + + n[0] *= l; + n[1] *= l; + n[2] *= l; + + normal[0] = (float) n[0]; + normal[1] = (float) n[1]; + normal[2] = (float) n[2]; + +} + +void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float *no) +{ + if(mpoly->totloop > 4) { + mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no); + } + else if(mpoly->totloop == 3){ + MVert *v1, *v2, *v3; + + v1 = mvarray + (loopstart++)->v; + v2 = mvarray + (loopstart++)->v; + v3 = mvarray + loopstart->v; + normal_tri_v3( no,v1->co, v2->co, v3->co); + } + else if(mpoly->totloop == 4){ + MVert *v1, *v2, *v3, *v4; + + v1 = mvarray + (loopstart++)->v; + v2 = mvarray + (loopstart++)->v; + v3 = mvarray + (loopstart++)->v; + v4 = mvarray + loopstart->v; + normal_quad_v3( no,v1->co, v2->co, v3->co, v4->co); + } + else{ /*horrible, two sided face!*/ + no[0] = 0.0; + no[1] = 0.0; + no[2] = 1.0; + } +} + /* basic vertex data functions */ int minmax_mesh(Mesh *me, float min[3], float max[3]) { diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 8b0b7a041dc..0821b4188fe 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -308,7 +308,7 @@ int BKE_mesh_validate(Mesh *me, int do_verbose) int BKE_mesh_validate_dm(DerivedMesh *dm) { - return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); + return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), TRUE, FALSE); } void BKE_mesh_calc_edges(Mesh *mesh, int update) diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c new file mode 100644 index 00000000000..8b437635b2a --- /dev/null +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -0,0 +1,226 @@ +/* +* $Id: modifier_bmesh.c 20831 2009-06-12 14:02:37Z joeedh $ +* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) 2005 by the Blender Foundation. +* All rights reserved. +* +* Contributor(s): Joseph Eagar +* +* ***** END GPL LICENSE BLOCK ***** +* +* Modifier stack implementation. +* +* BKE_modifier.h contains the function prototypes for this file. +* +*/ + +#include "string.h" +#include "stdarg.h" +#include "math.h" +#include "float.h" +#include "ctype.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_kdopbvh.h" +#include "BLI_kdtree.h" +#include "BLI_linklist.h" +#include "BLI_rand.h" +#include "BLI_edgehash.h" +#include "BLI_ghash.h" +#include "BLI_memarena.h" +#include "BLI_cellalloc.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_cloth_types.h" +#include "DNA_curve_types.h" +#include "DNA_effect_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" + +#include "BLI_editVert.h" +#include "BLI_array.h" + +#include "BKE_main.h" +#include "BKE_anim.h" +#include "BKE_bmesh.h" +// XXX #include "BKE_booleanops.h" +#include "BKE_cloth.h" +#include "BKE_collision.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_curve.h" +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_displist.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" +#include "BKE_multires.h" +#include "BKE_lattice.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" +#include "BKE_softbody.h" +#include "BKE_subsurf.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" +#include "BKE_tessmesh.h" + +#include "depsgraph_private.h" +#include "BKE_deform.h" +#include "BKE_shrinkwrap.h" + +#include "CCGSubSurf.h" +#include "RE_shader_ext.h" +#include "LOD_decimation.h" + +/*converts a cddm to a BMEditMesh. if existing is non-NULL, the + new geometry will be put in there.*/ +BMEditMesh *CDDM_To_BMesh(DerivedMesh *dm, BMEditMesh *existing) +{ + int allocsize[4] = {512, 512, 2048, 512}; + BMesh *bm, bmold; /*bmold is for storing old customdata layout*/ + BMEditMesh *em = existing; + MVert *mv, *mvert; + MEdge *me, *medge; + DMFaceIter *dfiter; + DMLoopIter *dliter; + BMVert *v, **vtable, **verts=NULL; + BMEdge *e, **etable, **edges=NULL; + BMFace *f; + BMIter liter; + BLI_array_declare(verts); + BLI_array_declare(edges); + int numTex, numCol; + int i, j, k, totvert, totedge, totface; + + if (em) bm = em->bm; + else bm = BM_Make_Mesh(allocsize); + + bmold = *bm; + + /*merge custom data layout*/ + CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT); + CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE); + CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP); + CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE); + + /*needed later*/ + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); + + totvert = dm->getNumVerts(dm); + totedge = dm->getNumEdges(dm); + totface = dm->getNumFaces(dm); + + vtable = MEM_callocN(sizeof(void**)*totvert, "vert table in BMDM_Copy"); + etable = MEM_callocN(sizeof(void**)*totedge, "edge table in BMDM_Copy"); + + /*do verts*/ + mv = mvert = dm->dupVertArray(dm); + for (i=0; i<totvert; i++, mv++) { + v = BM_Make_Vert(bm, mv->co, NULL); + + VECCOPY(v->no, mv->no); + v->head.flag = MEFlags_To_BMFlags(mv->flag, BM_VERT); + + CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data); + vtable[i] = v; + } + MEM_freeN(mvert); + + /*do edges*/ + me = medge = dm->dupEdgeArray(dm); + for (i=0; i<totedge; i++, me++) { + e = BM_Make_Edge(bm, vtable[me->v1], vtable[me->v2], NULL, 0); + + e->head.flag = MEFlags_To_BMFlags(me->flag, BM_EDGE); + + CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data); + etable[i] = e; + } + MEM_freeN(medge); + + /*do faces*/ + k = 0; + dfiter = dm->newFaceIter(dm); + for (; !dfiter->done; dfiter->step(dfiter)) { + BMLoop *l; + + BLI_array_empty(verts); + BLI_array_empty(edges); + + dliter = dfiter->getLoopsIter(dfiter); + for (j=0; !dliter->done; dliter->step(dliter), j++) { + BLI_array_growone(verts); + BLI_array_growone(edges); + + verts[j] = vtable[dliter->vindex]; + edges[j] = etable[dliter->eindex]; + } + + if (j < 2) + break; + + f = BM_Make_Ngon(bm, verts[0], verts[1], edges, dfiter->len, 0); + + if (!f) + continue; + + f->head.flag = MEFlags_To_BMFlags(dfiter->flags, BM_FACE); + f->mat_nr = dfiter->mat_nr; + + dliter = dfiter->getLoopsIter(dfiter); + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + for (j=0; l; l=BMIter_Step(&liter)) { + CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data); + k += 1; + } + + CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, + dfiter->index, &f->head.data); + } + dfiter->free(dfiter); + + MEM_freeN(vtable); + MEM_freeN(etable); + + BLI_array_free(verts); + BLI_array_free(edges); + + if (!em) em = BMEdit_Create(bm); + else BMEdit_RecalcTesselation(em); + + return em; +} + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 29726ccbc99..f2c5a9cbf37 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -47,6 +47,7 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" +#include "BKE_tessmesh.h" #include "BKE_object.h" @@ -72,7 +73,7 @@ DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob dm = mti->applyModifier(md, ob, tdm, 0, 1); if (dm == tdm) { - dm = CDDM_copy(tdm); + dm = CDDM_copy(tdm, 0); } return dm; @@ -231,7 +232,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm dm->getVertCos(dm, deformedVerts); mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0, 0); - ndm= CDDM_copy(dm); + ndm= CDDM_copy(dm, 0); CDDM_apply_vert_coords(ndm, deformedVerts); MEM_freeN(deformedVerts); @@ -250,26 +251,31 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm static int get_levels_from_disps(Object *ob) { Mesh *me = ob->data; - MDisps *mdisp; - int i, totlvl= 0; + MDisps *mdisp, *md; + int i, j, totlvl= 0; mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS); - for(i = 0; i < me->totface; ++i, ++mdisp) { - int S = me->mface[i].v4 ? 4 : 3; - - if(mdisp->totdisp == 0) continue; - - while(1) { - int side = (1 << (totlvl-1)) + 1; - int lvl_totdisp = side*side*S; - if(mdisp->totdisp == lvl_totdisp) - break; - else if(mdisp->totdisp < lvl_totdisp) - --totlvl; - else - ++totlvl; - + for(i = 0; i < me->totpoly; ++i) { + int S = me->mpoly[i].totloop; + + md = mdisp + me->mpoly[i].loopstart; + for (j=0; j<me->mpoly[i].totloop; j++, md++) { + if(md->totdisp == 0) continue; + + while(1) { + int side = (1 << (totlvl-1)) + 1; + int lvl_totdisp = side*side*S; + if(md->totdisp == lvl_totdisp) + break; + else if(md->totdisp < lvl_totdisp) + --totlvl; + else + ++totlvl; + + } + + break; } } @@ -282,10 +288,10 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o Mesh *me = ob->data; MDisps *mdisp; - if(me->edit_mesh) - mdisp = CustomData_get_layer(&me->edit_mesh->fdata, CD_MDISPS); + if(me->edit_btmesh) + mdisp = CustomData_get_layer(&me->edit_btmesh->bm->ldata, CD_MDISPS); else - mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS); + mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS); if(mdisp) { mmd->totlvl = get_levels_from_disps(ob); @@ -297,15 +303,12 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o static void multires_set_tot_mdisps(Mesh *me, int lvl) { - MDisps *mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); + MDisps *mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS); int i; if(mdisps) { - for(i = 0; i < me->totface; i++) { - if(mdisps[i].totdisp == 0) { - int nvert = (me->mface[i].v4)? 4: 3; - mdisps[i].totdisp = multires_grid_tot[lvl]*nvert; - } + for(i = 0; i < me->totloop; i++, mdisps++) { + mdisps->totdisp = multires_grid_tot[lvl]; } } } @@ -315,9 +318,8 @@ static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl) int i; /* reallocate displacements to be filled in */ - for(i = 0; i < me->totface; ++i) { - int nvert = (me->mface[i].v4)? 4: 3; - int totdisp = multires_grid_tot[lvl]*nvert; + for(i = 0; i < me->totloop; ++i) { + int totdisp = multires_grid_tot[lvl]; float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); if(mdisps[i].disps) @@ -382,44 +384,43 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) MDisps *mdisps; multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); - mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS); multires_force_update(ob); if(mdisps && levels > 0) { if(lvl > 0) { + MLoop *ml = me->mloop; int nsize = multires_side_tot[lvl]; int hsize = multires_side_tot[mmd->totlvl]; - int i; + int i, j, k=0; - for(i = 0; i < me->totface; ++i) { - MDisps *mdisp= &mdisps[i]; - float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; - int nvert = (me->mface[i].v4)? 4: 3; - int totdisp = multires_grid_tot[lvl]*nvert; - int S; + for(i = 0; i < me->totpoly; ++i) { + for (j=0; j<me->mpoly[i].totloop; j++, k++) { + MDisps *mdisp= &mdisps[k]; + float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; + int totdisp = multires_grid_tot[lvl]; - disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); - ndisps = disps; - hdisps = mdisp->disps; + ndisps = disps; + hdisps = mdisp->disps; - for(S = 0; S < nvert; S++) { multires_copy_grid(ndisps, hdisps, nsize, hsize); ndisps += nsize*nsize; hdisps += hsize*hsize; - } - MEM_freeN(mdisp->disps); - mdisp->disps = disps; - mdisp->totdisp = totdisp; + MEM_freeN(mdisp->disps); + mdisp->disps = disps; + mdisp->totdisp = totdisp; + } } } else { - CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface); - CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); + CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop); + CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop); } } @@ -607,9 +608,9 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl multires_force_update(ob); - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if(!mdisps) - mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_DEFAULT, NULL, me->totloop); if(mdisps->disps && !updateblock && totlvl > 1) { /* upsample */ @@ -706,14 +707,14 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; DMGridData **gridData, **subGridData; - MFace *mface = me->mface; - MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + MPoly *mpoly = me->mpoly; + MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); int *gridOffset; - int i, /*numGrids,*/ gridSize, dGridSize, dSkip; + int i, k, /*numGrids,*/ gridSize, dGridSize, dSkip; if(!mdisps) { if(invert) - mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_DEFAULT, NULL, me->totloop); else return; } @@ -727,23 +728,28 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int dGridSize = multires_side_tot[totlvl]; dSkip = (dGridSize-1)/(gridSize-1); - #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT) - for(i = 0; i < me->totface; ++i) { - const int numVerts = mface[i].v4 ? 4 : 3; - MDisps *mdisp = &mdisps[i]; - int S, x, y, gIndex = gridOffset[i]; + k = 0; /*current loop/mdisp index within the mloop array*/ - /* when adding new faces in edit mode, need to allocate disps */ - if(!mdisp->disps) - #pragma omp critical - { - multires_reallocate_mdisps(me, mdisps, totlvl); - } + #pragma omp parallel for private(i) if(me->totloop*gridSize*gridSize >= CCG_OMP_LIMIT) - for(S = 0; S < numVerts; ++S, ++gIndex) { + for(i = 0; i < me->totpoly; ++i) { + const int numVerts = mpoly[i].totloop; + int S, x, y, gIndex = gridOffset[i]; + + for(S = 0; S < numVerts; ++S, ++gIndex, ++k) { + MDisps *mdisp = &mdisps[k]; DMGridData *grid = gridData[gIndex]; DMGridData *subgrid = subGridData[gIndex]; - float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize]; + float (*dispgrid)[3] = NULL; + + /* when adding new faces in edit mode, need to allocate disps */ + if(!mdisp->disps) + #pragma omp critical + { + multires_reallocate_mdisps(me, mdisps, totlvl); + } + + dispgrid = mdisp->disps; for(y = 0; y < gridSize; y++) { for(x = 0; x < gridSize; x++) { @@ -805,9 +811,10 @@ static void multiresModifier_update(DerivedMesh *dm) ob = ccgdm->multires.ob; me = ccgdm->multires.ob->data; mmd = ccgdm->multires.mmd; + multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if(mdisps) { int lvl = ccgdm->multires.lvl; @@ -821,7 +828,7 @@ static void multiresModifier_update(DerivedMesh *dm) int i, j, numGrids, highGridSize, lowGridSize; /* create subsurf DM from original mesh at high level */ - if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); + if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform, 0); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); @@ -875,7 +882,7 @@ static void multiresModifier_update(DerivedMesh *dm) else { DerivedMesh *cddm, *subdm; - if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); + if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform, 0); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); @@ -948,7 +955,9 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca } multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + + /*run displacement*/ multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); for(i = 0; i < numGrids; i++) @@ -1049,15 +1058,33 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) void multires_load_old_250(Mesh *me) { - MDisps *mdisps; - int a; + MDisps *mdisps, *mdisps2; + MFace *mf; + int i, j, k; mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); if(mdisps) { - for(a=0; a<me->totface; a++) - if(mdisps[a].totdisp) - old_mdisps_convert(&me->mface[a], &mdisps[a]); + for(i=0; i<me->totface; i++) + if(mdisps[i].totdisp) + old_mdisps_convert(&me->mface[i], &mdisps[i]); + + CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); + mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS); + + k = 0; + mf = me->mface; + for (i=0; i<me->totface; i++, mf++) { + int nvert = mf->v4 ? 4 : 3; + int totdisp = mdisps[i].totdisp / nvert; + + for (j=0; j < mf->v4 ? 4 : 3; j++, k++) { + mdisps2[k].disps = MEM_callocN(sizeof(float)*3*totdisp, "multires disp in conversion"); + mdisps2[k].totdisp = totdisp; + memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp*j, totdisp); + } + + } } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 15ad3a7809a..53bac9171ae 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3586,5 +3586,4 @@ void clear_scene_in_nodes(Main *bmain, Scene *sce) } } } -} - +}
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 21a53d5365a..9910392e2d0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -81,6 +81,7 @@ #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_mesh.h" +#include "BKE_tessmesh.h" #include "BKE_mball.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -947,7 +948,7 @@ void free_lamp(Lamp *la) BKE_free_animdata((ID *)la); - curvemapping_free(la->curfalloff); + curvemapping_free(la->curfalloff); BKE_previewimg_free(&la->preview); BKE_icon_delete(&la->id); @@ -1897,7 +1898,7 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) static void give_parvert(Object *par, int nr, float *vec) { - EditMesh *em; + BMEditMesh *em; int a, count; vec[0]=vec[1]=vec[2]= 0.0f; @@ -1906,7 +1907,22 @@ static void give_parvert(Object *par, int nr, float *vec) Mesh *me= par->data; DerivedMesh *dm; - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; + + if(em) { + BMVert *eve; + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + int *keyindex = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX); + + if(keyindex && *keyindex==nr) { + memcpy(vec, eve->co, sizeof(float)*3); + break; + } + } + } + dm = (em)? em->derivedFinal: par->derivedFinal; if(dm) { @@ -1933,9 +1949,6 @@ static void give_parvert(Object *par, int nr, float *vec) dm->getVertCo(dm, 0, vec); } } - - if(em) - BKE_mesh_end_editmesh(me, em); } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { Nurb *nu; @@ -2568,11 +2581,14 @@ void object_handle_update(Scene *scene, Object *ob) if (G.f & G_DEBUG) printf("recalcdata %s\n", ob->id.name+2); + if(adt) { /* evaluate drivers */ // XXX: for mesh types, should we push this to derivedmesh instead? BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); + + } /* includes all keys and modifiers */ @@ -2580,19 +2596,17 @@ void object_handle_update(Scene *scene, Object *ob) case OB_MESH: { #if 0 // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask' - EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL; + BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH); if(em) { makeDerivedMesh(scene, ob, em, scene->customdata_mask); /* was CD_MASK_BAREMESH */ - BKE_mesh_end_editmesh(ob->data, em); } else makeDerivedMesh(scene, ob, NULL, scene->customdata_mask); #else /* ensure CD_MASK_BAREMESH for now */ - EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL; + BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; if(em) { makeDerivedMesh(scene, ob, em, scene->customdata_mask | CD_MASK_BAREMESH); /* was CD_MASK_BAREMESH */ - BKE_mesh_end_editmesh(ob->data, em); } else makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH); #endif diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4609e64c271..4b3b30e6cd2 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -51,6 +51,8 @@ #include "BLI_kdtree.h" #include "BLI_rand.h" #include "BLI_threads.h" +#include "BLI_cellalloc.h" +#include "BLI_math.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -696,7 +698,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float data->totchildcache= psys->totchildcache; if(psmd->dm) - data->dm= CDDM_copy(psmd->dm); + data->dm= CDDM_copy(psmd->dm, 0); data->totdmvert= psmd->totdmvert; data->totdmedge= psmd->totdmedge; data->totdmface= psmd->totdmface; @@ -799,9 +801,9 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) return tot; mvert= dm->getVertArray(dm); - mface= dm->getFaceArray(dm); - origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX); - totface= dm->getNumFaces(dm); + mface= dm->getTessFaceArray(dm); + origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + totface= dm->getNumTessFaces(dm); totorigface= me->totface; if(totface == 0 || totorigface == 0) @@ -1540,7 +1542,7 @@ static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int case PART_FROM_FACE: case PART_FROM_VOLUME: { - MFace *mf=dm->getFaceData(dm,index,CD_MFACE); + MFace *mf=dm->getTessFaceData(dm,index,CD_MFACE); return interpolate_particle_value(values[mf->v1],values[mf->v2],values[mf->v3],values[mf->v4],fw,mf->v4); } @@ -1588,11 +1590,11 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float * int quad, findex, totface; float uv[2], (*faceuv)[2]; - mface = dm->getFaceDataArray(dm, CD_MFACE); - origindex = dm->getFaceDataArray(dm, CD_ORIGINDEX); - osface = dm->getFaceDataArray(dm, CD_ORIGSPACE); + mface = dm->getTessFaceDataArray(dm, CD_MFACE); + origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE); - totface = dm->getNumFaces(dm); + totface = dm->getNumTessFaces(dm); if(osface==NULL || origindex==NULL) { /* Assume we dont need osface data */ @@ -1661,7 +1663,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_ *mapindex = index; } else { /* FROM_FACE/FROM_VOLUME */ - if(index >= dm->getNumFaces(dm)) + if(index >= dm->getNumTessFaces(dm)) return 0; *mapindex = index; @@ -1685,15 +1687,15 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_ i = index_dmcache; - if(i== DMCACHE_NOTFOUND || i >= dm->getNumFaces(dm)) + if(i== DMCACHE_NOTFOUND || i >= dm->getNumTessFaces(dm)) return 0; *mapindex = i; /* modify the original weights to become * weights for the derived mesh face */ - osface= dm->getFaceDataArray(dm, CD_ORIGSPACE); - mface= dm->getFaceData(dm, i, CD_MFACE); + osface= dm->getTessFaceDataArray(dm, CD_ORIGSPACE); + mface= dm->getTessFaceData(dm, i, CD_MFACE); if(osface == NULL) mapfw[0]= mapfw[1]= mapfw[2]= mapfw[3]= 0.0f; @@ -1751,7 +1753,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache MTFace *mtface; MVert *mvert; - mface=dm->getFaceData(dm,mapindex,CD_MFACE); + mface=dm->getTessFaceData(dm,mapindex,CD_MFACE); mvert=dm->getVertDataArray(dm,CD_MVERT); mtface=CustomData_get_layer(&dm->faceData,CD_MTFACE); @@ -3330,10 +3332,10 @@ static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float m int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache; - if (i==-1 || i >= dm->getNumFaces(dm)) { unit_m4(mat); return; } + if (i==-1 || i >= dm->getNumTessFaces(dm)) { unit_m4(mat); return; } - mface=dm->getFaceData(dm,i,CD_MFACE); - osface=dm->getFaceData(dm,i,CD_ORIGSPACE); + mface=dm->getTessFaceData(dm,i,CD_MFACE); + osface=dm->getTessFaceData(dm,i,CD_ORIGSPACE); if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) { VECCOPY(v[0], orcodata[mface->v1]); @@ -3667,7 +3669,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl if(pa) { i= (pa->num_dmcache==DMCACHE_NOTFOUND)? pa->num: pa->num_dmcache; - if(i >= dm->getNumFaces(dm)) + if(i >= dm->getNumTessFaces(dm)) i = -1; } else @@ -3679,7 +3681,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl texco[2]= 0.0f; } else { - mf= dm->getFaceData(dm, i, CD_MFACE); + mf= dm->getTessFaceData(dm, i, CD_MFACE); psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco); @@ -4318,7 +4320,7 @@ void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, Particle if(part->childtype == PART_CHILD_FACES) { mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE); if(mtface) { - mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE); + mface= psmd->dm->getTessFaceData(psmd->dm, cpa->num, CD_MFACE); mtface += cpa->num; psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); } @@ -4340,14 +4342,14 @@ void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, Particle if(num == DMCACHE_NOTFOUND) num= pa->num; - if (num >= psmd->dm->getNumFaces(psmd->dm)) { + if (num >= psmd->dm->getNumTessFaces(psmd->dm)) { /* happens when simplify is enabled * gives invalid coords but would crash otherwise */ num= DMCACHE_NOTFOUND; } if(mtface && num != DMCACHE_NOTFOUND) { - mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE); + mface= psmd->dm->getTessFaceData(psmd->dm, num, CD_MFACE); mtface += num; psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv); } @@ -4505,7 +4507,6 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] VECADDFAC(center, center, yvec, bb->offset[1]); } - void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSimulationData sim= {0}; sim.scene= scene; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index fd792168c6b..b4900553814 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -347,9 +347,9 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) origindex= dm->getVertDataArray(dm, CD_ORIGINDEX); } else { /* FROM_FACE/FROM_VOLUME */ - totdmelem= dm->getNumFaces(dm); + totdmelem= dm->getNumTessFaces(dm); totelem= me->totface; - origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX); + origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); } nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); @@ -489,8 +489,8 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) int a, a1, a2, a0mul, a1mul, a2mul, totface; int amax= from==PART_FROM_FACE ? 3 : 1; - totface=dm->getNumFaces(dm); - mface_array= dm->getFaceDataArray(dm,CD_MFACE); + totface=dm->getNumTessFaces(dm); + mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE); for(a=0; a<amax; a++){ if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; } @@ -751,7 +751,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData MFace *mface; pa->num = i = ctx->index[p]; - mface = dm->getFaceData(dm,i,CD_MFACE); + mface = dm->getTessFaceData(dm,i,CD_MFACE); switch(distr){ case PART_DISTR_JIT: @@ -773,7 +773,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData if(from==PART_FROM_VOLUME){ MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - tot=dm->getNumFaces(dm); + tot=dm->getNumTessFaces(dm); psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0); @@ -785,7 +785,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData min_d=2.0; intersect=0; - for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){ + for(i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){ if(i==pa->num) continue; v1=mvert[mface->v1].co; @@ -842,7 +842,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData return; } - mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); + mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE); randu= rng_getFloat(thread->rng); randv= rng_getFloat(thread->rng); @@ -1001,7 +1001,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, if(totpart==0) return 0; - if (!finaldm->deformedOnly && !finaldm->getFaceDataArray(finaldm, CD_ORIGINDEX)) { + if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) { printf("Can't create particles with the current modifier stack, disable destructive modifiers\n"); // XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); return 0; @@ -1102,7 +1102,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, break; case PART_FROM_VOLUME: case PART_FROM_FACE: - tot = dm->getNumFaces(dm); + tot = dm->getNumTessFaces(dm); break; case PART_FROM_PARTICLE: if(psys->target_ob) @@ -1162,7 +1162,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, orcodata= dm->getVertDataArray(dm, CD_ORCO); for(i=0; i<tot; i++){ - MFace *mf=dm->getFaceData(dm,i,CD_MFACE); + MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE); if(orcodata) { VECCOPY(co1, orcodata[mf->v1]); @@ -1231,7 +1231,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, } else { /* PART_FROM_FACE / PART_FROM_VOLUME */ for(i=0;i<tot; i++){ - MFace *mf=dm->getFaceData(dm,i,CD_MFACE); + MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE); tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3]; if(mf->v4) { @@ -1307,7 +1307,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, } else { if(dm->numFaceData) - COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); + COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); } if(COMPARE_ORIG_INDEX) { @@ -1550,7 +1550,7 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time; } - + pa->hair_index = 0; /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ /* usage other than straight after distribute has to handle this index by itself - jahka*/ @@ -1622,7 +1622,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float q_phase[4]; int p = pa - psys->particles; part=psys->part; - + #if 0 /* deprecated code */ if(part->from==PART_FROM_PARTICLE){ float speed; @@ -1885,7 +1885,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, } } - if(part->type == PART_HAIR){ pa->lifetime = 100.0f; } @@ -2712,8 +2711,8 @@ int psys_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos VECCOPY(p_max,pa_minmax+3); } - totface=dm->getNumFaces(dm); - mface=dm->getFaceDataArray(dm,CD_MFACE); + totface=dm->getNumTessFaces(dm); + mface=dm->getTessFaceDataArray(dm,CD_MFACE); mvert=dm->getVertDataArray(dm,CD_MVERT); /* lets intersect the faces */ @@ -3228,7 +3227,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) } if(!dm) { - dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0); + dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0); DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL); } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index c004e254572..c8a855c8156 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -589,6 +589,15 @@ void set_sca_new_poins_ob(Object *ob) bPropertyActuator *pa= act->data; ID_NEW(pa->ob); } + else if(act->type==ACT_ARMATURE) { + bArmatureActuator *aa = act->data; + ID_NEW(aa->target); + ID_NEW(aa->subtarget); + } + else if(act->type==ACT_PROPERTY) { + bPropertyActuator *pa= act->data; + ID_NEW(pa->ob); + } } act= act->next; } diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index df81bcd1593..000d08e4df2 100644..100755 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -145,8 +145,8 @@ void seq_stripelem_cache_init(void) hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash"); limitor = new_MEM_CacheLimiter( IMB_seq_cache_destructor ); - entrypool = BLI_mempool_create(sizeof(seqCacheEntry), 64, 64, 0); - keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0); + entrypool = BLI_mempool_create(sizeof(seqCacheEntry), 64, 64, 0, 0); + keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0, 0); } void seq_stripelem_cache_destruct(void) diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 53fefa685b9..5311f3a9c38 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -39,6 +39,7 @@ #include "DNA_meshdata_types.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_editVert.h" #include "BLI_math.h" @@ -51,6 +52,8 @@ #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_subsurf.h" +#include "BKE_mesh.h" +#include "BKE_tessmesh.h" /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) @@ -86,11 +89,11 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c DerivedMesh *object_get_derived_final(Object *ob) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; - if(em) { + if (em) + { DerivedMesh *dm = em->derivedFinal; - BKE_mesh_end_editmesh(me, em); return dm; } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index b2d3ddf2e52..b2f8831cced 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -295,7 +295,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, if(!smd->coll->bvhtree) { - smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 ); + smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 ); } return 1; } @@ -306,7 +306,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) { MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getFaceArray(dm); + MFace *mface = dm->getTessFaceArray(dm); int i = 0, divs = 0; int *tridivs = NULL; float cell_len = 1.0 / 50.0; // for res = 50 @@ -314,16 +314,16 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) int quads = 0, facecounter = 0; // count quads - for(i = 0; i < dm->getNumFaces(dm); i++) + for(i = 0; i < dm->getNumTessFaces(dm); i++) { if(mface[i].v4) quads++; } - calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len); + calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len); // count triangle divisions - for(i = 0; i < dm->getNumFaces(dm) + quads; i++) + for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++) { divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1); } @@ -340,7 +340,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) VECCOPY(&scs->points[i * 3], tmpvec); } - for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++) + for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++) { int again = 0; do @@ -1321,7 +1321,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); - smd->coll->dm = CDDM_copy(dm); + smd->coll->dm = CDDM_copy(dm, 1); // rigid movement support copy_m4_m4(smd->coll->mat_old, smd->coll->mat); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index ca8df76311d..d197541c620 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -66,6 +66,7 @@ variables on the UI for now #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_threads.h" +#include "BLI_cellalloc.h" #include "BKE_curve.h" #include "BKE_effect.h" @@ -294,11 +295,11 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm) /* first some paranoia checks */ if (!dm) return NULL; - if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return NULL; + if (!dm->getNumVerts(dm) || !dm->getNumTessFaces(dm)) return NULL; pccd_M = MEM_mallocN(sizeof(ccd_Mesh),"ccd_Mesh"); pccd_M->totvert = dm->getNumVerts(dm); - pccd_M->totface = dm->getNumFaces(dm); + pccd_M->totface = dm->getNumTessFaces(dm); pccd_M->savety = CCD_SAVETY; pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f; pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f; @@ -327,7 +328,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm) } /* alloc and copy faces*/ - pccd_M->mface = dm->dupFaceArray(dm); + pccd_M->mface = dm->dupTessFaceArray(dm); /* OBBs for idea1 */ pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface,"ccd_Mesh_Faces_mima"); @@ -390,10 +391,10 @@ static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M, DerivedMesh *dm) /* first some paranoia checks */ if (!dm) return ; - if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return ; + if (!dm->getNumVerts(dm) || !dm->getNumTessFaces(dm)) return ; if ((pccd_M->totvert != dm->getNumVerts(dm)) || - (pccd_M->totface != dm->getNumFaces(dm))) return; + (pccd_M->totface != dm->getNumTessFaces(dm))) return; pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f; pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f; @@ -2123,9 +2124,9 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float UN forcefactor = iks/bs->len; else forcefactor = iks; - kw = (bp1->springweight+bp2->springweight)/2.0f; - kw = kw * kw; - kw = kw * kw; + kw = (bp1->springweight+bp2->springweight)/2.0f; + kw = kw * kw; + kw = kw * kw; switch (bs->springtype){ case SB_EDGE: case SB_HANDLE: @@ -3467,7 +3468,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object * if (dostiff) { - if(w){ + if(w){ if( v && u ) { bs->v1 = bpc; bs->v2 = bpc-dw-dv-1; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 9c157f57d49..88ca0c33624 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -445,8 +445,8 @@ void sound_seek_scene(struct bContext *C) AUD_resume(scene->sound_scene_handle); if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID) AUD_seek(scene->sound_scrub_handle, 0); - else - scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS); + //XXX merge EEK! else + //scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS); } else { diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 5697c29db5d..86e901345c4 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -55,7 +55,11 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" +#include "BKE_tessmesh.h" +#include "BKE_utildefines.h" +#include "PIL_time.h" +#include "BLI_array.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -66,9 +70,10 @@ #include "CCGSubSurf.h" -static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v); -static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e); -static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f); +static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, + int drawInteriorEdges, + int useSubsurfUv, + DerivedMesh *dm); /// @@ -155,7 +160,8 @@ static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) { return edgeBase + x-1; } } -static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) { + +BM_INLINE int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) { int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f)); int numVerts = ccgSubSurf_getFaceNumVerts(f); @@ -210,10 +216,11 @@ static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGV } static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) { - MFace *mface = dm->getFaceArray(dm); +#if 0 + MFace *mface = dm->getTessFaceArray(dm); MVert *mvert = dm->getVertArray(dm); int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumTessFaces(dm); int i, j, seam; UvMapVert *v; UvVertMap *vmap; @@ -303,6 +310,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, free_uv_vert_map(vmap); ccgSubSurf_processSync(ss); +#endif return 1; } @@ -375,7 +383,6 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, MEM_freeN(faceMap); } -/* face weighting */ static void calc_ss_weights(int gridFaces, FaceVertWeight **qweight, FaceVertWeight **tweight) { @@ -419,22 +426,496 @@ static void calc_ss_weights(int gridFaces, } } +/* face weighting */ +typedef struct FaceVertWeightEntry { + FaceVertWeight *weight; + float *w; + int valid; +} FaceVertWeightEntry; + +typedef struct WeightTable { + FaceVertWeightEntry *weight_table; + int len; +} WeightTable; + +static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen) +{ + int x, y, i, j; + float *w, w1, w2, w4, fac, fac2, fx, fy; + + if (wtable->len <= faceLen) { + void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2"); + + if (wtable->len) { + memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry)*wtable->len); + MEM_freeN(wtable->weight_table); + } + + wtable->weight_table = tmp; + wtable->len = faceLen+1; + } + + if (!wtable->weight_table[faceLen].valid) { + wtable->weight_table[faceLen].valid = 1; + wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float)*faceLen*faceLen*(gridCuts+2)*(gridCuts+2), "weight table alloc"); + fac = 1.0 / (float)faceLen; + + for (i=0; i<faceLen; i++) { + for (x=0; x<gridCuts+2; x++) { + for (y=0; y<gridCuts+2; y++) { + fx = 0.5f - (float)x / (float)(gridCuts+1) / 2.0f; + fy = 0.5f - (float)y / (float)(gridCuts+1) / 2.0f; + + fac2 = faceLen - 4; + w1 = (1.0f - fx) * (1.0f - fy) + (-fac2*fx*fy*fac); + w2 = (1.0f - fx + fac2*fx*-fac) * (fy); + w4 = (fx) * (1.0 - fy + -fac2*fy*fac); + + fac2 = 1.0 - (w1+w2+w4); + fac2 = fac2 / (float)(faceLen-3); + for (j=0; j<faceLen; j++) + w[j] = fac2; + + w[i] = w1; + w[(i-1+faceLen)%faceLen] = w2; + w[(i+1)%faceLen] = w4; + + w += faceLen; + } + } + } + } + + return wtable->weight_table[faceLen].w; +} + +void free_ss_weights(WeightTable *wtable) +{ + int i; + + for (i=0; i<wtable->len; i++) { + if (wtable->weight_table[i].valid) + MEM_freeN(wtable->weight_table[i].w); + } +} + +static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, + int drawInteriorEdges, int useSubsurfUv, + DerivedMesh *dm, struct MultiresSubsurf *ms) +{ + DerivedMesh *cgdm, *result; + double curt = PIL_check_seconds_timer(); + + cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); + result = CDDM_copy(cgdm, 1); + + printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt); + + cgdm->needsFree = 1; + cgdm->release(cgdm); + + CDDM_calc_normals(result); + + return result; +#if 0 + DerivedMesh *result; + int edgeSize = ccgSubSurf_getEdgeSize(ss); + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + int edgeBase, faceBase; + int i, j, k, S, x, y, index; + int *vertIdx = NULL; + BLI_array_declare(vertIdx); + CCGVertIterator *vi; + CCGEdgeIterator *ei; + CCGFaceIterator *fi; + CCGFace **faceMap2; + CCGEdge **edgeMap2; + CCGVert **vertMap2; + int totvert, totedge, totface; + MVert *mvert; + MEdge *med; + float *w = NULL; + WeightTable wtable; + BLI_array_declare(w); + MFace *mf; + int *origIndex; + + memset(&wtable, 0, sizeof(wtable)); + + /* vert map */ + totvert = ccgSubSurf_getNumVerts(ss); + vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap"); + vi = ccgSubSurf_getVertIterator(ss); + for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { + CCGVert *v = ccgVertIterator_getCurrent(vi); + + vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v; + } + ccgVertIterator_free(vi); + + totedge = ccgSubSurf_getNumEdges(ss); + edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap"); + ei = ccgSubSurf_getEdgeIterator(ss); + for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + + edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e; + } + + totface = ccgSubSurf_getNumFaces(ss); + faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap"); + fi = ccgSubSurf_getFaceIterator(ss); + for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(fi); + + faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f; + } + ccgFaceIterator_free(fi); + + if(ms) { + result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss), 0, 0); + } + else { + if(dm) { + result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss), 0, 0); + } else { + result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss), 0, 0); + } + } + + // load verts + faceBase = i = 0; + mvert = CDDM_get_verts(result); + origIndex = result->getVertData(result, 0, CD_ORIGINDEX); + + for(index = 0; index < totface; index++) { + CCGFace *f = faceMap2[index]; + int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); + FaceVertWeight *weight = 0;//get_ss_weights(&wtable, gridFaces-1, numVerts); + + BLI_array_empty(vertIdx); + + for(S = 0; S < numVerts; S++) { + CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S); + BLI_array_growone(vertIdx); + + vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + } + +#if 0 + DM_interp_vert_data(dm, result, vertIdx, weight[0][0], numVerts, i); +#endif + copy_v3_v3(mvert->co, ccgSubSurf_getFaceCenterData(f)); + *origIndex = ORIGINDEX_NONE; + ++mvert; + ++origIndex; + i++; + + BLI_array_empty(w); + for (x=0; x<numVerts; x++) { + BLI_array_growone(w); + } + + for(S = 0; S < numVerts; S++) { + int prevS = (S - 1 + numVerts) % numVerts; + int nextS = (S + 1) % numVerts; + int otherS = (numVerts >= 4) ? (S + 2) % numVerts : 3; + + for(x = 1; x < gridFaces; x++) { +#if 0 + w[prevS] = weight[x][0][0]; + w[S] = weight[x][0][1]; + w[nextS] = weight[x][0][2]; + w[otherS] = weight[x][0][3]; + + DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); +#endif + copy_v3_v3(mvert->co, + ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); + + *origIndex = ORIGINDEX_NONE; + ++mvert; + ++origIndex; + i++; + } + } + + BLI_array_empty(w); + for (x=0; x<numVerts; x++) { + BLI_array_growone(w); + } + + for(S = 0; S < numVerts; S++) { + int prevS = (S - 1 + numVerts) % numVerts; + int nextS = (S + 1) % numVerts; + int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + + for(y = 1; y < gridFaces; y++) { + for(x = 1; x < gridFaces; x++) { +#if 0 + w[prevS] = weight[y * gridFaces + x][0][0]; + w[S] = weight[y * gridFaces + x][0][1]; + w[nextS] = weight[y * gridFaces + x][0][2]; + w[otherS] = weight[y * gridFaces + x][0][3]; + DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); +#endif + + copy_v3_v3(mvert->co, + ccgSubSurf_getFaceGridData(ss, f, S, x, y)); + *origIndex = ORIGINDEX_NONE; + ++mvert; + ++origIndex; + i++; + } + } + } + *((int*)ccgSubSurf_getFaceUserData(ss, f)) = faceBase; + faceBase += 1 + numVerts * ((gridSize-2) + (gridSize-2) * (gridSize-2)); + } + + edgeBase = i; + for(index = 0; index < totedge; index++) { + CCGEdge *e = edgeMap2[index]; + int x; + int vertIdx[2]; + + CCGVert *v; + v = ccgSubSurf_getEdgeVert0(e); + vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + v = ccgSubSurf_getEdgeVert1(e); + vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + + for(x = 1; x < edgeSize - 1; x++) { + float w2[2]; + + w2[1] = (float) x / (edgeSize - 1); + w2[0] = 1 - w2[1]; + DM_interp_vert_data(dm, result, vertIdx, w2, 2, i); + + copy_v3_v3(mvert->co, ccgSubSurf_getEdgeData(ss, e, x)); + *origIndex = ORIGINDEX_NONE; + ++mvert; + ++origIndex; + i++; + } + + *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase; + edgeBase += edgeSize-2; + } + + for(index = 0; index < totvert; index++) { + CCGVert *v = vertMap2[index]; + int vertIdx; + + vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + + DM_copy_vert_data(dm, result, vertIdx, i, 1); + copy_v3_v3(mvert->co, ccgSubSurf_getVertData(ss, v)); + + *((int*)ccgSubSurf_getVertUserData(ss, v)) = i; + *origIndex = ccgDM_getVertMapIndex(ss, v); + ++mvert; + ++origIndex; + i++; + } + + // load edges + i = 0; + med = CDDM_get_edges(result); + origIndex = result->getEdgeData(result, 0, CD_ORIGINDEX); + + for(index = 0; index < totface; index++) { + CCGFace *f = faceMap2[index]; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + + for(k = 0; k < numVerts; k++) { + for(x = 0; x < gridFaces; x++) { + if(drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER; + med->v1 = getFaceIndex(ss, f, k, x, 0, edgeSize, gridSize); + med->v2 = getFaceIndex(ss, f, k, x+1, 0, edgeSize, gridSize); + *origIndex = ORIGINDEX_NONE; + ++med; + ++origIndex; + i++; + } + + for(x = 1; x < gridFaces; x++) { + for(y = 0; y < gridFaces; y++) { + if(drawInteriorEdges) + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + med->v1 = getFaceIndex(ss, f, k, x, y, edgeSize, gridSize); + med->v2 = getFaceIndex(ss, f, k, x, y + 1, + edgeSize, gridSize); + *origIndex = ORIGINDEX_NONE; + ++med; + ++origIndex; + i++; + + if(drawInteriorEdges) + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + med->v1 = getFaceIndex(ss, f, k, y, x, edgeSize, gridSize); + med->v2 = getFaceIndex(ss, f, k, y + 1, x, + edgeSize, gridSize); + *origIndex = ORIGINDEX_NONE; + ++med; + ++origIndex; + i++; + } + } + } + } + + for(index = 0; index < totedge; index++) { + CCGEdge *e = edgeMap2[index]; + unsigned int flags = 0; + char bweight = 0; + int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); + + if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE; + + + if(edgeIdx != -1 && dm) { + MEdge origMed; + dm->getEdge(dm, edgeIdx, &origMed); + + flags |= origMed.flag; + bweight = origMed.bweight; + } + + for(x = 0; x < edgeSize - 1; x++) { + med->v1 = getEdgeIndex(ss, e, x, edgeSize); + med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); + med->flag = flags; + med->bweight = bweight; + *origIndex = ccgDM_getEdgeMapIndex(ss, e); + ++med; + ++origIndex; + i++; + } + } + + // load faces + i = 0; + mf = CDDM_get_tessfaces(result); + origIndex = result->getTessFaceData(result, 0, CD_ORIGINDEX); + + for(index = 0; index < totface; index++) { + CCGFace *f = faceMap2[index]; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + int mat_nr; + int flag; + int mapIndex = ccgDM_getFaceMapIndex(ss, f); + int faceIdx = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); + + if(!ssFromEditmesh) { + MFace origMFace; + dm->getTessFace(dm, faceIdx, &origMFace); + + mat_nr = origMFace.mat_nr; + flag = origMFace.flag; + } else { + BMFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f); + mat_nr = ef->mat_nr; + flag = BMFlags_To_MEFlags(ef); + } + + for(S = 0; S < numVerts; S++) { + FaceVertWeight *weight = 0;//get_ss_weights(&wtable, gridFaces-1, numVerts); + + for(y = 0; y < gridFaces; y++) { + for(x = 0; x < gridFaces; x++) { + mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0, + edgeSize, gridSize); + mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1, + edgeSize, gridSize); + mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1, + edgeSize, gridSize); + mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, + edgeSize, gridSize); + mf->mat_nr = mat_nr; + mf->flag = flag; +#if 0 //BMESH_TODO + if(dm) { + int prevS = (S - 1 + numVerts) % numVerts; + int nextS = (S + 1) % numVerts; + int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + FaceVertWeight w; + + for(j = 0; j < 4; ++j) { + w[j][prevS] = (*weight)[j][0]; + w[j][S] = (*weight)[j][1]; + w[j][nextS] = (*weight)[j][2]; + w[j][otherS] = (*weight)[j][3]; + } + + DM_interp_tessface_data(dm, result, &faceIdx, NULL, + &w, 1, i); + weight++; + } +#endif + + *origIndex = mapIndex; + ++mf; + ++origIndex; + i++; + } + } + } + } + + MEM_freeN(faceMap2); + MEM_freeN(edgeMap2); + MEM_freeN(vertMap2); + + free_ss_weights(&wtable); + + BLI_array_free(vertIdx); + + if(useSubsurfUv) { + CustomData *fdata = &result->faceData; + CustomData *dmfdata = &dm->faceData; + int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE); + int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE); + + for (i=0; i<numlayer && i<dmnumlayer; i++) + set_subsurf_uv(ss, dm, result, i); + } + + CDDM_calc_normals(result); + CDDM_tessfaces_to_faces(result); + + BLI_array_free(w); + return result; +#endif +} + static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float (*vertexCos)[3], int useFlatSubdiv) { float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss); - CCGVertHDL fVerts[4]; + CCGVertHDL *fVerts = NULL; + BLI_array_declare(fVerts); int totvert = dm->getNumVerts(dm); int totedge = dm->getNumEdges(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumTessFaces(dm); + int totpoly = dm->getNumFaces(dm); int i; int *index; MVert *mvert = dm->getVertArray(dm); MEdge *medge = dm->getEdgeArray(dm); - MFace *mface = dm->getFaceArray(dm); + MFace *mface = dm->getTessFaceArray(dm); MVert *mv; MEdge *me; MFace *mf; + DMFaceIter *fiter; + DMLoopIter *liter; ccgSubSurf_initFullSync(ss); @@ -466,28 +947,31 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i; } - - mf = mface; - index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < totface; i++, mf++) { + + fiter = dm->newFaceIter(dm); + for (i=0; !fiter->done; fiter->step(fiter), i++) { CCGFace *f; + BLI_array_empty(fVerts); - fVerts[0] = SET_INT_IN_POINTER(mf->v1); - fVerts[1] = SET_INT_IN_POINTER(mf->v2); - fVerts[2] = SET_INT_IN_POINTER(mf->v3); - fVerts[3] = SET_INT_IN_POINTER(mf->v4); + index = (int*) fiter->getCDData(fiter, CD_ORIGINDEX, -1); + liter = fiter->getLoopsIter(fiter); + + for (; !liter->done; liter->step(liter)) { + BLI_array_growone(fVerts); + fVerts[BLI_array_count(fVerts)-1] = SET_INT_IN_POINTER(liter->vindex); + } - // this is very bad, means mesh is internally consistent. - // it is not really possible to continue without modifying - // other parts of code significantly to handle missing faces. - // since this really shouldn't even be possible we just bail. - if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3, + /* this is very bad, means mesh is internally inconsistent. + * it is not really possible to continue without modifying + * other parts of code significantly to handle missing faces. + * since this really shouldn't even be possible we just bail.*/ + if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fiter->len, fVerts, &f) == eCCGError_InvalidValue) { static int hasGivenError = 0; if(!hasGivenError) { - //XXX error("Unrecoverable error in SubSurf calculation," - // " mesh is inconsistent."); + printf("Unrecoverable error in SubSurf calculation," + " mesh is inconsistent.\n"); hasGivenError = 1; } @@ -497,27 +981,30 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i; } + fiter->free(fiter); ccgSubSurf_processSync(ss); + + BLI_array_free(fVerts); } /***/ -static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) { +int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) { return ((int*) ccgSubSurf_getVertUserData(ss, v))[1]; } -static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) { +int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) { return ((int*) ccgSubSurf_getEdgeUserData(ss, e))[1]; } -static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) { +int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) { return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1]; } -static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss); CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -559,32 +1046,32 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { ccgEdgeIterator_free(ei); ccgVertIterator_free(vi); } -static int ccgDM_getNumVerts(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumVerts(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalVerts(ccgdm->ss); + return ccgSubSurf_getNumFinalVerts(cgdm->ss); } -static int ccgDM_getNumEdges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumEdges(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalEdges(ccgdm->ss); + return ccgSubSurf_getNumFinalEdges(cgdm->ss); } -static int ccgDM_getNumFaces(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumTessFaces(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalFaces(ccgdm->ss); + return ccgSubSurf_getNumFinalFaces(cgdm->ss); } static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; DMGridData *vd; int i; memset(mv, 0, sizeof(*mv)); - if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { + if((vertNum < cgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -597,10 +1084,10 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) int gridInternalEnd; i = 0; - while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert) + while(i < lastface && vertNum >= cgdm->faceMap[i + 1].startVert) ++i; - f = ccgdm->faceMap[i].face; + f = cgdm->faceMap[i].face; numVerts = ccgSubSurf_getFaceNumVerts(f); gridSideVerts = gridSize - 2; @@ -609,7 +1096,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) gridSideEnd = 1 + numVerts * gridSideVerts; gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts; - offset = vertNum - ccgdm->faceMap[i].startVert; + offset = vertNum - cgdm->faceMap[i].startVert; if(offset < 1) { vd = ccgSubSurf_getFaceCenterData(f); copy_v3_v3(mv->co, vd->co); @@ -631,28 +1118,28 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) copy_v3_v3(mv->co, vd->co); normal_float_to_short_v3(mv->no, vd->no); } - } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { + } else if((vertNum < cgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { /* this vert comes from edge data */ CCGEdge *e; int lastedge = ccgSubSurf_getNumEdges(ss) - 1; int x; i = 0; - while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert) + while(i < lastedge && vertNum >= cgdm->edgeMap[i + 1].startVert) ++i; - e = ccgdm->edgeMap[i].edge; + e = cgdm->edgeMap[i].edge; - x = vertNum - ccgdm->edgeMap[i].startVert + 1; + x = vertNum - cgdm->edgeMap[i].startVert + 1; vd = ccgSubSurf_getEdgeData(ss, e, x); copy_v3_v3(mv->co, vd->co); normal_float_to_short_v3(mv->no, vd->no); } else { /* this vert comes from vert data */ CCGVert *v; - i = vertNum - ccgdm->vertMap[0].startVert; + i = vertNum - cgdm->vertMap[0].startVert; - v = ccgdm->vertMap[i].vert; + v = cgdm->vertMap[i].vert; vd = ccgSubSurf_getVertData(ss, v); copy_v3_v3(mv->co, vd->co); normal_float_to_short_v3(mv->no, vd->no); @@ -677,13 +1164,13 @@ static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float no_r[3]) static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int i; memset(med, 0, sizeof(*med)); - if(edgeNum < ccgdm->edgeMap[0].startEdge) { + if(edgeNum < cgdm->edgeMap[0].startEdge) { /* this edge comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -695,16 +1182,16 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) int gridInternalEdges; i = 0; - while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge) + while(i < lastface && edgeNum >= cgdm->faceMap[i + 1].startEdge) ++i; - f = ccgdm->faceMap[i].face; + f = cgdm->faceMap[i].face; /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/ gridSideEdges = gridSize - 1; gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; - offset = edgeNum - ccgdm->faceMap[i].startEdge; + offset = edgeNum - cgdm->faceMap[i].startEdge; grid = offset / (gridSideEdges + gridInternalEdges); offset %= (gridSideEdges + gridInternalEdges); @@ -732,18 +1219,18 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) short *edgeFlag; unsigned int flags = 0; - i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1); + i = (edgeNum - cgdm->edgeMap[0].startEdge) / (edgeSize - 1); - e = ccgdm->edgeMap[i].edge; + e = cgdm->edgeMap[i].edge; if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE; - x = edgeNum - ccgdm->edgeMap[i].startEdge; + x = edgeNum - cgdm->edgeMap[i].startEdge; med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x+1, edgeSize); - edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL; + edgeFlag = (cgdm->edgeFlags)? &cgdm->edgeFlags[i]: NULL; if(edgeFlag) flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER; @@ -756,8 +1243,8 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSideEdges = gridSize - 1; @@ -769,18 +1256,18 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) int grid; int x, y; int lastface = ccgSubSurf_getNumFaces(ss) - 1; - char *faceFlags = ccgdm->faceFlags; + char *faceFlags = cgdm->faceFlags; memset(mf, 0, sizeof(*mf)); + if (faceNum >= cgdm->dm.numFaceData) + return; - i = 0; - while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace) - ++i; + i = cgdm->reverseFaceMap[faceNum]; - f = ccgdm->faceMap[i].face; + f = cgdm->faceMap[i].face; /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/ - offset = faceNum - ccgdm->faceMap[i].startFace; + offset = faceNum - cgdm->faceMap[i].startFace; grid = offset / gridFaces; offset %= gridFaces; y = offset / gridSideEdges; @@ -800,8 +1287,8 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; DMGridData *vd; int index; int totvert, totedge, totface; @@ -811,7 +1298,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) totface = ccgSubSurf_getNumFaces(ss); for(index = 0; index < totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); vd= ccgSubSurf_getFaceCenterData(f); @@ -840,7 +1327,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) totedge = ccgSubSurf_getNumEdges(ss); for(index = 0; index < totedge; index++) { - CCGEdge *e = ccgdm->edgeMap[index].edge; + CCGEdge *e = cgdm->edgeMap[index].edge; int x; for(x = 1; x < edgeSize - 1; x++, i++) { @@ -853,7 +1340,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) totvert = ccgSubSurf_getNumVerts(ss); for(index = 0; index < totvert; index++) { - CCGVert *v = ccgdm->vertMap[index].vert; + CCGVert *v = cgdm->vertMap[index].vert; vd= ccgSubSurf_getVertData(ss, v); copy_v3_v3(mvert[i].co, vd->co); @@ -864,25 +1351,25 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int index; int totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); int i = 0; - short *edgeFlags = ccgdm->edgeFlags; + short *edgeFlags = cgdm->edgeFlags; totface = ccgSubSurf_getNumFaces(ss); for(index = 0; index < totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); for(S = 0; S < numVerts; S++) { for(x = 0; x < gridSize - 1; x++) { MEdge *med = &medge[i]; - if(ccgdm->drawInteriorEdges) + if(cgdm->drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize); med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize); @@ -894,7 +1381,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) MEdge *med; med = &medge[i]; - if(ccgdm->drawInteriorEdges) + if(cgdm->drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize); @@ -903,7 +1390,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) i++; med = &medge[i]; - if(ccgdm->drawInteriorEdges) + if(cgdm->drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, y, x, edgeSize, gridSize); @@ -917,7 +1404,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) totedge = ccgSubSurf_getNumEdges(ss); for(index = 0; index < totedge; index++) { - CCGEdge *e = ccgdm->edgeMap[index].edge; + CCGEdge *e = cgdm->edgeMap[index].edge; unsigned int flags = 0; int x; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); @@ -943,20 +1430,177 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) } } +struct cgdm_faceIter; + +typedef struct cgdm_loopIter { + DMLoopIter head; + int curloop; + int lindex; //loop index within the mesh, not the face + CCGDerivedMesh *cgdm; + struct cgdm_faceIter *fiter; +} cgdm_loopIter; + +typedef struct cgdm_faceIter { + DMFaceIter head; + CCGDerivedMesh *cgdm; + MFace *mface, *mf; + + cgdm_loopIter liter; + EdgeHash *ehash; /*edge map for populating loopiter->eindex*/ +} cgdm_faceIter; + +void cgdm_faceIterStep(void *self) +{ + cgdm_faceIter *fiter = self; + + if (!fiter->cgdm || !fiter->cgdm->ss) { + fiter->head.done = 1; + return; + } + + if (fiter->head.index+1 >= ccgSubSurf_getNumFinalFaces(fiter->cgdm->ss)) { + fiter->head.done = 1; + return; + }; + + fiter->head.index++; + + fiter->mf++; + + fiter->head.flags = fiter->mface->flag; + fiter->head.mat_nr = fiter->mface->mat_nr; + fiter->head.len = 4; +} + +void *cgdm_faceIterCData(void *self, int type, int layer) +{ + cgdm_faceIter *fiter = self; + + if (layer == -1) + return CustomData_get(&fiter->cgdm->dm.polyData, fiter->head.index, type); + else + return CustomData_get_n(&fiter->cgdm->dm.polyData, type, fiter->head.index, layer); +} + +void cgdm_loopIterStep(void *self) +{ + cgdm_loopIter *liter = self; + MFace *mf = liter->fiter->mface; + int i, v1, v2; + + liter->head.index++; + i = liter->head.index; + + if (liter->head.index >= 4) { + liter->head.done = 1; + return; + } + + switch (i) { + case 0: + v1 = liter->fiter->mf->v1; + v2 = liter->fiter->mf->v2; + break; + case 1: + v1 = liter->fiter->mf->v2; + v2 = liter->fiter->mf->v3; + break; + case 2: + v1 = liter->fiter->mf->v3; + v2 = liter->fiter->mf->v4; + break; + case 3: + v1 = liter->fiter->mf->v4; + v2 = liter->fiter->mf->v1; + break; + } + + liter->head.vindex = v1; + liter->head.eindex = GET_INT_FROM_POINTER(BLI_edgehash_lookup(liter->fiter->cgdm->ehash, v1, v2)); + liter->lindex += 1; + + ccgDM_getFinalVert((DerivedMesh*)liter->cgdm, v1, &liter->head.v); +} + +void *cgdm_loopIterGetVCData(void *self, int type, int layer) +{ + cgdm_loopIter *liter = self; + + if (layer == -1) + return CustomData_get(&liter->cgdm->dm.vertData, liter->head.vindex, type); + else return CustomData_get_n(&liter->cgdm->dm.vertData, type, liter->head.vindex, layer); +} + +void *cgdm_loopIterGetCData(void *self, int type, int layer) +{ + cgdm_loopIter *liter = self; + + if (layer == -1) + return CustomData_get(&liter->cgdm->dm.loopData, liter->lindex, type); + else return CustomData_get_n(&liter->cgdm->dm.loopData, type, liter->lindex, layer); +} + +DMLoopIter *cgdm_faceIterGetLIter(void *self) +{ + cgdm_faceIter *fiter = self; + + fiter->liter.head.index = -1; + fiter->liter.head.done = 0; + fiter->liter.head.step(&fiter->liter); + + return (DMLoopIter*) &fiter->liter; +} + +void cgdm_faceIterFree(void *vfiter) +{ + cgdm_faceIter *fiter = vfiter; + + MEM_freeN(fiter->mface); + MEM_freeN(fiter); +} + +DMFaceIter *cgdm_newFaceIter(DerivedMesh *dm) +{ + cgdm_faceIter *fiter = MEM_callocN(sizeof(cgdm_faceIter), "cgdm_faceIter"); + MEdge medge; + int i, totedge = cgdm_getNumEdges(dm); + + fiter->cgdm = dm; + fiter->liter.cgdm = dm; + fiter->mface = fiter->mf = dm->dupTessFaceArray(dm); + fiter->mf--; + + fiter->head.free = cgdm_faceIterFree; + fiter->head.step = cgdm_faceIterStep; + fiter->head.index = -1; + fiter->head.getCDData = cgdm_faceIterCData; + fiter->head.getLoopsIter = cgdm_faceIterGetLIter; + + fiter->liter.fiter = fiter; + fiter->liter.head.getLoopCDData = cgdm_loopIterGetCData; + fiter->liter.head.getVertCDData = cgdm_loopIterGetVCData; + fiter->liter.head.step = cgdm_loopIterStep; + fiter->liter.lindex = -1; + + fiter->head.step(fiter); + + return fiter; +} + static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int index; int totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); int i = 0; - char *faceFlags = ccgdm->faceFlags; + char *faceFlags = cgdm->faceFlags; totface = ccgSubSurf_getNumFaces(ss); for(index = 0; index < totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; @@ -973,6 +1617,11 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) edgeSize, gridSize); mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize); + if (faceFlags) { + mat_nr = faceFlags[index*2+1]; + mf->flag = faceFlags[index*2]; + } else mf->flag = flag; + mf->mat_nr = mat_nr; mf->flag = flag; @@ -983,9 +1632,9 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) } } -static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); int i; @@ -1066,14 +1715,14 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) { MEM_freeN(edgeMap2); MEM_freeN(faceMap2); } -static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss); +static void cgdm_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGVertIterator *vi = ccgSubSurf_getVertIterator(cgdm->ss); for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { CCGVert *v = ccgVertIterator_getCurrent(vi); - DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v); - int index = ccgDM_getVertMapIndex(ccgdm->ss, v); + DMGridData *vd = ccgSubSurf_getVertData(cgdm->ss, v); + int index = ccgDM_getVertMapIndex(cgdm->ss, v); if (index!=-1) func(userData, index, vd->co, vd->no, NULL); @@ -1081,9 +1730,9 @@ static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData ccgVertIterator_free(vi); } -static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1102,8 +1751,8 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData } static void ccgDM_drawVerts(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); CCGVertIterator *vi; @@ -1230,8 +1879,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(draw ccgEdgeIterator_free(ei); } static void ccgDM_drawLooseEdges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1252,7 +1901,7 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm) { ccgEdgeIterator_free(ei); } -static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) +void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) { float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2]; float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2]; @@ -1276,7 +1925,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) int step = (fast)? gridSize-1: 1; ccgdm_pbvh_update(ccgdm); - if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) { if(dm->numFaceData) { /* should be per face */ @@ -1291,6 +1939,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) return; } + gridSize = ccgSubSurf_getGridSize(ss); + fi = ccgSubSurf_getFaceIterator(ss); for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { CCGFace *f = ccgFaceIterator_getCurrent(fi); @@ -1354,21 +2004,21 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) } /* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); GPUVertexAttribs gattribs; DMVertexAttribs attribs= {{{0}}}; - MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); + MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); int gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; int edgeSize = ccgSubSurf_getEdgeSize(ss); int transp, orig_transp, new_transp; - char *faceFlags = ccgdm->faceFlags; + char *faceFlags = cgdm->faceFlags; int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); doDraw = 0; matnr = -1; @@ -1398,7 +2048,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v totface = ccgSubSurf_getNumFaces(ss); for(a = 0, i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; + CCGFace *f = cgdm->faceMap[i].face; int S, x, y, drawSmooth; int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); int origIndex = ccgDM_getFaceMapIndex(ss, f); @@ -1509,19 +2159,19 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v ccgFaceIterator_free(fi); } -static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { +static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } -static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); int gridSize = ccgSubSurf_getGridSize(ss); unsigned char *cp1, *cp2; int useTwoSide=1; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); cp1= col1; if(col2) { @@ -1580,27 +2230,27 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), uns ccgFaceIterator_free(fi); } -static void ccgDM_drawFacesTex_common(DerivedMesh *dm, - int (*drawParams)(MTFace *tface, MCol *mcol, int matnr), +static void cgdm_drawFacesTex_common(DerivedMesh *dm, + int (*drawParams)(MTFace *tface, int has_vcol, int matnr), int (*drawParamsMapped)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; - MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); - char *faceFlags = ccgdm->faceFlags; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; + MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + char *faceFlags = cgdm->faceFlags; int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); totface = ccgSubSurf_getNumFaces(ss); for(i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; + CCGFace *f = cgdm->faceMap[i].face; int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f); int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); @@ -1617,7 +2267,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, } if(drawParams) - flag = drawParams(tf, mcol, mat_nr); + flag = drawParams(tf, mcol!=NULL, mat_nr); else if (index != ORIGINDEX_NONE) flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1; else @@ -1720,21 +2370,21 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, } } -static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr)) +static void cgdm_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr)) { - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); + cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); } -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); + cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } -static void ccgDM_drawUVEdges(DerivedMesh *dm) +static void cgdm_drawUVEdges(DerivedMesh *dm) { - MFace *mf = dm->getFaceArray(dm); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); + MFace *mf = dm->getTessFaceArray(dm); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if (tf) { @@ -1764,22 +2414,22 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm) } static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs)) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; MCol *mcol= NULL; int i, gridSize = ccgSubSurf_getGridSize(ss); - char *faceFlags = ccgdm->faceFlags; + char *faceFlags = cgdm->faceFlags; int gridFaces = gridSize - 1, totface; if(useColors) { - mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); } totface = ccgSubSurf_getNumFaces(ss); for(i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; + CCGFace *f = cgdm->faceMap[i].face; int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f); int origIndex; @@ -1879,9 +2529,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u } } } -static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1909,9 +2559,9 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *u ccgEdgeIterator_free(ei); } -static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1940,9 +2590,9 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v ccgEdgeIterator_free(ei); } -static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { @@ -1960,7 +2610,7 @@ static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *us ccgFaceIterator_free(fi); } -static void ccgDM_release(DerivedMesh *dm) { +static void cgdm_release(DerivedMesh *dm) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; if (DM_release(dm)) { @@ -1973,6 +2623,10 @@ static void ccgDM_release(DerivedMesh *dm) { ccgdm->multires.update(dm); } + if (ccgdm->ehash) + BLI_edgehash_free(ccgdm->ehash, NULL); + + if(ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap); if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces); if(ccgdm->gridData) MEM_freeN(ccgdm->gridData); if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency); @@ -1989,12 +2643,66 @@ static void ccgDM_release(DerivedMesh *dm) { } } +void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata, + CustomData *pdata, int loopstart, int findex, + int polyindex, int numTex, int numCol) +{ + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); + for (j=0; j<4; j++, mloopuv++) { + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i); + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); + + for (j=0; j<4; j++, mloopcol++) { + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mloopcol = CustomData_get(ldata, loopstart, CD_WEIGHT_MLOOPCOL); + mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL); + + for (j=0; j<4; j++, mloopcol++) { + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type) { if(type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; int *origindex; int a, index, totnone, totorig; @@ -2009,8 +2717,8 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type) origindex[a]= ORIGINDEX_NONE; for(index=0; index<totorig; index++, a++) { - CCGVert *v = ccgdm->vertMap[index].vert; - origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v); + CCGVert *v = cgdm->vertMap[index].vert; + origindex[a] = ccgDM_getVertMapIndex(cgdm->ss, v); } return origindex; @@ -2023,8 +2731,8 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type) { if(type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; int *origindex; int a, i, index, totnone, totorig, totedge; int edgeSize= ccgSubSurf_getEdgeSize(ss); @@ -2041,7 +2749,7 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type) origindex[a]= ORIGINDEX_NONE; for(index=0; index<totedge; index++) { - CCGEdge *e= ccgdm->edgeMap[index].edge; + CCGEdge *e= cgdm->edgeMap[index].edge; int mapIndex= ccgDM_getEdgeMapIndex(ss, e); for(i = 0; i < edgeSize - 1; i++, a++) @@ -2058,19 +2766,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) { if(type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; int *origindex; int a, i, index, totface; int gridFaces = ccgSubSurf_getGridSize(ss) - 1; DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX); + origindex= DM_get_tessface_data_layer(dm, CD_ORIGINDEX); totface= ccgSubSurf_getNumFaces(ss); for(a=0, index=0; index<totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); int mapIndex = ccgDM_getFaceMapIndex(ss, f); @@ -2081,19 +2789,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) return origindex; } - return DM_get_face_data_layer(dm, type); + return DM_get_tessface_data_layer(dm, type); } static int ccgDM_getNumGrids(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; int index, numFaces, numGrids; - numFaces= ccgSubSurf_getNumFaces(ccgdm->ss); + numFaces= ccgSubSurf_getNumFaces(cgdm->ss); numGrids= 0; for(index=0; index<numFaces; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; numGrids += ccgSubSurf_getFaceNumVerts(f); } @@ -2102,11 +2810,11 @@ static int ccgDM_getNumGrids(DerivedMesh *dm) static int ccgDM_getGridSize(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - return ccgSubSurf_getGridSize(ccgdm->ss); + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + return ccgSubSurf_getGridSize(cgdm->ss); } -static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset) +static int cgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset) { CCGFace *adjf; CCGEdge *e; @@ -2139,15 +2847,15 @@ static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int static void ccgdm_create_grids(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; DMGridData **gridData; DMGridAdjacency *gridAdjacency, *adj; CCGFace **gridFaces; int *gridOffset; int index, numFaces, numGrids, S, gIndex /*, gridSize*/; - if(ccgdm->gridData) + if(cgdm->gridData) return; numGrids = ccgDM_getNumGrids(dm); @@ -2155,10 +2863,10 @@ static void ccgdm_create_grids(DerivedMesh *dm) /*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/ /* compute offset into grid array for each face */ - gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset"); + gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset"); for(gIndex = 0, index = 0; index < numFaces; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); gridOffset[index] = gIndex; @@ -2166,12 +2874,12 @@ static void ccgdm_create_grids(DerivedMesh *dm) } /* compute grid data */ - gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData"); - gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency"); - gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces"); + gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "cgdm.gridData"); + gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "cgdm.gridAdjacency"); + gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "cgdm.gridFaces"); for(gIndex = 0, index = 0; index < numFaces; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); for(S = 0; S < numVerts; S++, gIndex++) { @@ -2185,43 +2893,43 @@ static void ccgdm_create_grids(DerivedMesh *dm) adj->index[0] = gIndex - S + nextS; adj->rotation[0] = 3; - adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0); + adj->index[1] = cgdm_adjacent_grid(ss, gridOffset, f, prevS, 0); adj->rotation[1] = 1; - adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1); + adj->index[2] = cgdm_adjacent_grid(ss, gridOffset, f, S, 1); adj->rotation[2] = 3; adj->index[3] = gIndex - S + prevS; adj->rotation[3] = 1; } } - ccgdm->gridData = gridData; - ccgdm->gridFaces = gridFaces; - ccgdm->gridAdjacency = gridAdjacency; - ccgdm->gridOffset = gridOffset; + cgdm->gridData = gridData; + cgdm->gridFaces = gridFaces; + cgdm->gridAdjacency = gridAdjacency; + cgdm->gridOffset = gridOffset; } static DMGridData **ccgDM_getGridData(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; ccgdm_create_grids(dm); - return ccgdm->gridData; + return cgdm->gridData; } static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; ccgdm_create_grids(dm); - return ccgdm->gridAdjacency; + return cgdm->gridAdjacency; } static int *ccgDM_getGridOffset(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; ccgdm_create_grids(dm); - return ccgdm->gridOffset; + return cgdm->gridOffset; } static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm) @@ -2285,50 +2993,73 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int useSubsurfUv, DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm"); + CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "cgdm"); CCGVertIterator *vi; CCGEdgeIterator *ei; CCGFaceIterator *fi; int index, totvert, totedge, totface; int i; int vertNum, edgeNum, faceNum; + int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex; /* *edgeOrigIndex - as yet, unused */ short *edgeFlags; char *faceFlags; - int edgeSize; + int *loopidx = NULL, *vertidx = NULL; + BLI_array_declare(loopidx); + BLI_array_declare(vertidx); + int loopindex, loopindex2; + int edgeSize, has_edge_origindex; int gridSize; - int gridFaces; + int gridFaces, gridCuts; /*int gridSideVerts;*/ int gridSideEdges; + int numTex, numCol; int gridInternalEdges; - MEdge *medge = NULL; + float *w = NULL; + WeightTable wtable = {0}; + MCol *mcol; + MEdge *medge = NULL, medge2; MFace *mface = NULL; - int *orig_indices; - FaceVertWeight *qweight, *tweight; + MPoly *mpoly = NULL; DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM, ccgSubSurf_getNumFinalVerts(ss), ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss), + ccgSubSurf_getNumFinalFaces(ss)*4, ccgSubSurf_getNumFinalFaces(ss)); + + numTex = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPUV); + numCol = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPCOL); + + if (numTex && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MTFACE) != numTex) + CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss)); + else if (numCol && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MCOL) != numCol) + CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss)); + + ccgdm->dm.getMinMax = cgdm_getMinMax; + ccgdm->dm.getNumVerts = cgdm_getNumVerts; + ccgdm->dm.getNumEdges = cgdm_getNumEdges; + ccgdm->dm.getNumTessFaces = cgdm_getNumTessFaces; + ccgdm->dm.getNumFaces = cgdm_getNumTessFaces; - ccgdm->dm.getMinMax = ccgDM_getMinMax; - ccgdm->dm.getNumVerts = ccgDM_getNumVerts; - ccgdm->dm.getNumFaces = ccgDM_getNumFaces; + ccgdm->dm.getNumGrids = ccgDM_getNumGrids; + ccgdm->dm.getPBVH = ccgDM_getPBVH; - ccgdm->dm.getNumEdges = ccgDM_getNumEdges; + ccgdm->dm.newFaceIter = cgdm_newFaceIter; ccgdm->dm.getVert = ccgDM_getFinalVert; ccgdm->dm.getEdge = ccgDM_getFinalEdge; - ccgdm->dm.getFace = ccgDM_getFinalFace; + ccgdm->dm.getTessFace = ccgDM_getFinalFace; ccgdm->dm.getVertCo = ccgDM_getFinalVertCo; ccgdm->dm.getVertNo = ccgDM_getFinalVertNo; ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; - ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray; + ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; ccgdm->dm.getVertData = DM_get_vert_data; ccgdm->dm.getEdgeData = DM_get_edge_data; - ccgdm->dm.getFaceData = DM_get_face_data; + ccgdm->dm.getTessFaceData = DM_get_face_data; ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; - ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer; + ccgdm->dm.getTessFaceDataArray = ccgDM_get_face_data_layer; ccgdm->dm.getNumGrids = ccgDM_getNumGrids; ccgdm->dm.getGridSize = ccgDM_getGridSize; ccgdm->dm.getGridData = ccgDM_getGridData; @@ -2337,27 +3068,38 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getFaceMap = ccgDM_getFaceMap; ccgdm->dm.getPBVH = ccgDM_getPBVH; - ccgdm->dm.getVertCos = ccgdm_getVertCos; - ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert; - ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge; - ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter; + ccgdm->dm.getTessFace = ccgDM_getFinalFace; + ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; + ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; + ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; + ccgdm->dm.getVertData = DM_get_vert_data; + ccgdm->dm.getEdgeData = DM_get_edge_data; + ccgdm->dm.getTessFaceData = DM_get_face_data; + ccgdm->dm.getVertDataArray = DM_get_vert_data_layer; + ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer; + ccgdm->dm.getTessFaceDataArray = DM_get_tessface_data_layer; + + ccgdm->dm.getVertCos = cgdm_getVertCos; + ccgdm->dm.foreachMappedVert = cgdm_foreachMappedVert; + ccgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge; + ccgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter; ccgdm->dm.drawVerts = ccgDM_drawVerts; ccgdm->dm.drawEdges = ccgDM_drawEdges; ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges; ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; - ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored; - ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; - ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL; + ccgdm->dm.drawFacesColored = cgdm_drawFacesColored; + ccgdm->dm.drawFacesTex = cgdm_drawFacesTex; + ccgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; - ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; - ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; - ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; + ccgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex; + ccgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL; + ccgdm->dm.drawUVEdges = cgdm_drawUVEdges; - ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; - ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges; + ccgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp; + ccgdm->dm.drawMappedEdges = cgdm_drawMappedEdges; - ccgdm->dm.release = ccgDM_release; + ccgdm->dm.release = cgdm_release; ccgdm->ss = ss; ccgdm->drawInteriorEdges = drawInteriorEdges; @@ -2392,139 +3134,186 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, } ccgFaceIterator_free(fi); + ccgdm->reverseFaceMap = MEM_callocN(sizeof(int)*ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap"); + edgeSize = ccgSubSurf_getEdgeSize(ss); gridSize = ccgSubSurf_getGridSize(ss); gridFaces = gridSize - 1; - /*gridSideVerts = gridSize - 2;*/ /*UNUSED*/ - /*gridInternalVerts = gridSideVerts * gridSideVerts; */ /*UNUSED*/ + gridCuts = gridSize - 2; + /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */ gridSideEdges = gridSize - 1; gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; - calc_ss_weights(gridFaces, &qweight, &tweight); - vertNum = 0; edgeNum = 0; faceNum = 0; /* mvert = dm->getVertArray(dm); - as yet unused */ medge = dm->getEdgeArray(dm); - mface = dm->getFaceArray(dm); + mface = dm->getTessFaceArray(dm); + mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + /*CDDM hack*/ + edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "faceFlags"); faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags"); - orig_indices = (int*)ccgdm->dm.getFaceDataArray(&ccgdm->dm, CD_ORIGINDEX); - for(index = 0; index < totface; ++index) { + vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX); + /*edgeOrigIndex = DM_get_edge_data_layer(&cgdm->dm, CD_ORIGINDEX);*/ + faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX); + + polyOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX); + + if (!CustomData_has_layer(&ccgdm->dm.faceData, CD_MCOL)) + DM_add_tessface_layer(&ccgdm->dm, CD_MCOL, CD_CALLOC, NULL); + + mcol = DM_get_tessface_data_layer(&ccgdm->dm, CD_MCOL); + has_edge_origindex = CustomData_has_layer(&ccgdm->dm.edgeData, CD_ORIGINDEX); + + faceNum = 0; + loopindex = loopindex2 = 0; //current loop index + for (index = 0; index < totface; index++) { CCGFace *f = ccgdm->faceMap[index].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges); int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); - FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight; - int S, x, y; - int vertIdx[4]; + int g2_wid = gridCuts+2; + float *w2; + int s, x, y; + + w = get_ss_weights(&wtable, gridCuts, numVerts); ccgdm->faceMap[index].startVert = vertNum; ccgdm->faceMap[index].startEdge = edgeNum; ccgdm->faceMap[index].startFace = faceNum; - - if(orig_indices) - orig_indices[faceNum] = origIndex; + + faceFlags[0] = mpoly[origIndex].flag; + faceFlags[1] = mpoly[origIndex].mat_nr; + faceFlags += 2; /* set the face base vert */ *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum; - for(S = 0; S < numVerts; S++) { - CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S); + BLI_array_empty(loopidx); + for (s=0; s<numVerts; s++) { + BLI_array_growone(loopidx); + loopidx[s] = loopindex++; + } + + BLI_array_empty(vertidx); + for(s = 0; s < numVerts; s++) { + CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s); + + BLI_array_growone(vertidx); + vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + } + - vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + /*I think this is for interpolating the center vert?*/ + w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1); + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; } - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0], - numVerts, vertNum); ++vertNum; - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + /*interpolate per-vert data*/ + for(s = 0; s < numVerts; s++) { for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[x][0][0]; - w[S] = weight[x][0][1]; - w[nextS] = weight[x][0][2]; - w[otherS] = weight[x][0][3]; - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, - numVerts, vertNum); + w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts; + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; + } + ++vertNum; } } - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + /*interpolate per-vert data*/ + for(s = 0; s < numVerts; s++) { for(y = 1; y < gridFaces; y++) { for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[y * gridFaces + x][0][0]; - w[S] = weight[y * gridFaces + x][0][1]; - w[nextS] = weight[y * gridFaces + x][0][2]; - w[otherS] = weight[y * gridFaces + x][0][3]; - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, - numVerts, vertNum); + w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts; + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; + } + ++vertNum; } } } - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; - - weight = (numVerts == 4) ? qweight : tweight; - - for(y = 0; y < gridFaces; y++) { - for(x = 0; x < gridFaces; x++) { - FaceVertWeight w; - int j; - - for(j = 0; j < 4; ++j) { - w[j][prevS] = (*weight)[j][0]; - w[j][S] = (*weight)[j][1]; - w[j][nextS] = (*weight)[j][2]; - w[j][otherS] = (*weight)[j][3]; + if (has_edge_origindex) { + for(i = 0; i < numFinalEdges; ++i) + *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i, + CD_ORIGINDEX) = ORIGINDEX_NONE; + } + + for (s=0; s<numVerts; s++) { + /*interpolate per-face data*/ + for (y=0; y<gridFaces; y++) { + for (x=0; x<gridFaces; x++) { + w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + /*copy over poly data, e.g. mtexpoly*/ + CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1); + + /*generate tesselated face data used for drawing*/ + ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData, + &ccgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol); + + /*set original index data*/ + if (faceOrigIndex) { + *faceOrigIndex = origIndex; + faceOrigIndex++; + } + if (polyOrigIndex) { + *polyOrigIndex = origIndex; + polyOrigIndex++; } - DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL, - &w, 1, faceNum); - weight++; + ccgdm->reverseFaceMap[faceNum] = index; - ++faceNum; + faceNum++; } } } - faceFlags[index*2] = mface[origIndex].flag; - faceFlags[index*2 + 1] = mface[origIndex].mat_nr; - edgeNum += numFinalEdges; } - if(useSubsurfUv) { - CustomData *fdata = &ccgdm->dm.faceData; - CustomData *dmfdata = &dm->faceData; - int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE); - int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE); - - for (i=0; i<numlayer && i<dmnumlayer; i++) - set_subsurf_uv(ss, dm, &ccgdm->dm, i); - } - - edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags"); - for(index = 0; index < totedge; ++index) { CCGEdge *e = ccgdm->edgeMap[index].edge; int numFinalEdges = edgeSize - 1; + int mapIndex = ccgDM_getEdgeMapIndex(ss, e); int x; int vertIdx[2]; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); @@ -2538,6 +3327,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->edgeMap[index].startVert = vertNum; ccgdm->edgeMap[index].startEdge = edgeNum; + if(edgeIdx >= 0 && edgeFlags) + edgeFlags[edgeIdx] = medge[edgeIdx].flag; + /* set the edge base vert */ *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum; @@ -2546,32 +3338,59 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, w[1] = (float) x / (edgeSize - 1); w[0] = 1 - w[1]; DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum); + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; + } ++vertNum; } - edgeFlags[index]= medge[edgeIdx].flag; + for(i = 0; i < numFinalEdges; ++i) { + if (has_edge_origindex) { + *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i, + CD_ORIGINDEX) = mapIndex; + } + } edgeNum += numFinalEdges; } for(index = 0; index < totvert; ++index) { CCGVert *v = ccgdm->vertMap[index].vert; - int vertIdx; + int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v); + int vidx; - vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + vidx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); ccgdm->vertMap[index].startVert = vertNum; /* set the vert base vert */ *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum; - DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1); + DM_copy_vert_data(dm, &ccgdm->dm, vidx, vertNum, 1); + if (vertOrigIndex) { + *vertOrigIndex = mapIndex; + ++vertOrigIndex; + } ++vertNum; } - MEM_freeN(qweight); - MEM_freeN(tweight); + ccgdm->dm.numVertData = vertNum; + ccgdm->dm.numEdgeData = edgeNum; + ccgdm->dm.numFaceData = faceNum; + ccgdm->dm.numLoopData = loopindex2; + ccgdm->dm.numPolyData = faceNum; + + BLI_array_free(vertidx); + BLI_array_free(loopidx); + free_ss_weights(&wtable); + + ccgdm->ehash = BLI_edgehash_new(); + for (i=0; i<ccgdm->dm.numEdgeData; i++) { + ccgDM_getFinalEdge((DerivedMesh*)ccgdm, i, &medge2); + BLI_edgehash_insert(ccgdm->ehash, medge2.v1, medge2.v2, SET_INT_IN_POINTER(i)); + } return ccgdm; } @@ -2588,7 +3407,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); - CCGDerivedMesh *result; + CCGDerivedMesh *result = NULL; if(editMode) { int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; @@ -2617,7 +3436,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( result->freeSS = 1; } else { - int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); + int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental); int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; CCGSubSurf *ss; @@ -2661,8 +3480,8 @@ struct DerivedMesh *subsurf_make_derived_from_derived( result->freeSS = 1; } } - - return (DerivedMesh*)result; + + return result; } void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) diff --git a/source/blender/blenkernel/intern/verse_bitmap_node.c b/source/blender/blenkernel/intern/verse_bitmap_node.c new file mode 100644 index 00000000000..d27f7a13f02 --- /dev/null +++ b/source/blender/blenkernel/intern/verse_bitmap_node.c @@ -0,0 +1,451 @@ +/** + * $Id: verse_bitmap_node.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" + +#include "BIF_verse.h" + +#include "BKE_verse.h" + +#include "verse.h" + +/* function prototypes of static functions */ +static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth); +static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type); +static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id); +static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile); + +static void change_layer_dimension( + VBitmapLayer *vblayer, + unsigned int old_width, + unsigned int old_height, + unsigned int t_old_width, + unsigned int t_old_height); +static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer); + +/* + * resize/crop verse bitmap layer + */ +static void change_layer_dimension( + VBitmapLayer *vblayer, + unsigned int old_width, + unsigned int old_height, + unsigned int t_old_width, + unsigned int t_old_height) +{ + struct VNode *vnode = vblayer->vnode; + unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width; + unsigned int width = ((VBitmapData*)(vnode->data))->width; + unsigned int height = ((VBitmapData*)(vnode->data))->height; + unsigned int x, y, i, j; + + i = j = 0; + + /* "copy" old data to new data */ + if(vblayer->type==VN_B_LAYER_UINT8) { + unsigned char *data = (unsigned char*)vblayer->data; + /* allocate new verse bitmap layer data */ + unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer); + for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) { + for(x=0; x<old_width && y<width; x++, i++, j++) { + new_data[i] = data[j]; + } + } + MEM_freeN(vblayer->data); + vblayer->data = new_data; + } +} + +/* + * free data stored in verse bitmap layer + */ +void free_bitmap_layer_data(VBitmapLayer *vblayer) +{ + struct VerseSession *session = vblayer->vnode->session; + + /* free name of bitmap layer */ + MEM_freeN(vblayer->name); + + /* unsubscribe from verse bitmap layer */ + if(session->flag & VERSE_CONNECTED) + verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id); + + /* free image data of bitmap layer */ + if(vblayer->data) MEM_freeN(vblayer->data); +} + +/* + * allocate data of verse bitmap layer + */ +static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer) +{ + struct VNode *vnode = vblayer->vnode; + unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width; + unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height; + unsigned int size; + void *data; + + size = t_width*t_height; + + /* allocation of own data stored in verse bitmap layer */ + switch (vblayer->type) { + case VN_B_LAYER_UINT1: + data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1"); + break; + case VN_B_LAYER_UINT8: + data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8"); + break; + case VN_B_LAYER_UINT16: + data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16"); + break; + case VN_B_LAYER_REAL32: + data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16"); + break; + case VN_B_LAYER_REAL64: + data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32"); + break; + default: + data = NULL; + break; + } + + return data; +} + +/* + * create verse bitmap layer + */ +VBitmapLayer *create_bitmap_layer( + VNode *vnode, + VLayerID layer_id, + const char *name, + VNBLayerType type) +{ + struct VBitmapLayer *vblayer; + unsigned int width = ((VBitmapData*)(vnode->data))->width; + unsigned int height = ((VBitmapData*)(vnode->data))->height; + + /* allocate memory for own verse bitmap layer */ + vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer"); + + /* verse bitmap layer will include pointer at parent verse node and own id */ + vblayer->vnode = vnode; + vblayer->id = layer_id; + + /* name of verse layer */ + vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name"); + vblayer->name[0] = '\0'; + strcpy(vblayer->name, name); + + /* type of data stored in verse bitmap layer */ + vblayer->type = type; + + /* we can allocate memory for layer data, when we know dimmension of layers; when + * we don't know it, then we will allocate this data when we will receive dimmension */ + if(width==0 || height==0) + vblayer->data = NULL; + else + vblayer->data = alloc_verse_bitmap_layer_data(vblayer); + + vblayer->flag = 0; + + return vblayer; +} + +/* + * free data of bitmap node + */ +void free_bitmap_node_data(VNode *vnode) +{ + if(vnode->data) { + struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first; + + /* free all VerseLayer data */ + while(vblayer) { + free_bitmap_layer_data(vblayer); + vblayer = vblayer->next; + } + + /* free all VerseLayers */ + BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers)); + } +} + +/* + * create data of bitmap node + */ +VBitmapData *create_bitmap_data() +{ + struct VBitmapData *vbitmap; + + vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data"); + + BLI_dlist_init(&(vbitmap->layers)); + vbitmap->queue.first = vbitmap->queue.last = NULL; + + vbitmap->width = 0; + vbitmap->height = 0; + vbitmap->depth = 0; + + vbitmap->image = NULL; + + vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set; + vbitmap->post_bitmap_layer_create = post_bitmap_layer_create; + vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy; + vbitmap->post_bitmap_tile_set = post_bitmap_tile_set; + + return vbitmap; +} + +/* + * callback function, dimension of image was changed, it is neccessary to + * crop all layers + */ +static void cb_b_dimension_set( + void *user_data, + VNodeID node_id, + uint16 width, + uint16 height, + uint16 depth) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VBitmapLayer *vblayer; + unsigned int old_width, old_height, t_old_width, t_old_height; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + +#ifdef VERSE_DEBUG_PRINT + printf("\t cb_b_dimension_set()\n"); +#endif + + /* backup old width and height */ + old_width = ((VBitmapData*)(vnode->data))->width; + old_height = ((VBitmapData*)(vnode->data))->height; + t_old_width = ((VBitmapData*)(vnode->data))->t_width; + t_old_height = ((VBitmapData*)(vnode->data))->t_height; + + /* set up new dimension of layers */ + ((VBitmapData*)(vnode->data))->width = width; + ((VBitmapData*)(vnode->data))->height = height; + ((VBitmapData*)(vnode->data))->depth = depth; + + /* we cache t_width because tiles aren't one pixel width */ + if((width % VN_B_TILE_SIZE)!=0) + ((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE; + else + ((VBitmapData*)(vnode->data))->t_width = width; + + /* we cache t_height because tiles aren't one pixel height */ + if((height % VN_B_TILE_SIZE)!=0) + ((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE; + else + ((VBitmapData*)(vnode->data))->t_height = height; + + /* crop resize all layers */ + vblayer = ((VBitmapData*)vnode->data)->layers.lb.first; + + while(vblayer) { + /* when this callback function received after cb_b_layer_create, + * then we have to allocate memory for verse bitmap layer data */ + if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer); + /* crop/resize all verse bitmap layers */ + else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height); + + vblayer = vblayer->next; + } + + /* post callback function */ + ((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode); +} + +/* + * callback function, new layer channel of image was created + */ +static void cb_b_layer_create( + void *user_data, + VNodeID node_id, + VLayerID layer_id, + const char *name, + VNBLayerType type) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VBitmapLayer *vblayer; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + +#ifdef VERSE_DEBUG_PRINT + printf("\t cb_b_layer_create()\n"); +#endif + + /* when no layer exists, then new layer will be created */ + vblayer = create_bitmap_layer(vnode, layer_id, name, type); + + /* add verse bitmap layer to list of layers */ + BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id); + + /* post callback function */ + ((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer); + +} + +/* + * callback function, existing layer of image was destroyed + */ +static void cb_b_layer_destroy( + void *user_data, + VNodeID node_id, + VLayerID layer_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VBitmapLayer *vblayer; + + if(!session) return; + + /* find node of this layer*/ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id); + if(!vblayer) return; + +#ifdef VERSE_DEBUG_PRINT + printf("\t cb_b_layer_destroy()\n"); +#endif + + /* remove verse bitmap layer from list of layers */ + BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id); + + /* post callback function */ + ((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer); + + /* free data of verse bitmap layer */ + free_bitmap_layer_data(vblayer); + + /* free verse bitmap layer */ + MEM_freeN(vblayer); +} + +/* + * callback function, small part (8x8 pixels) was changed + */ +static void cb_b_tile_set( + void *user_data, + VNodeID node_id, + VLayerID layer_id, + uint16 tile_x, + uint16 tile_y, + uint16 z, + VNBLayerType type, + const VNBTile *tile) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VBitmapLayer *vblayer; + unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j; + + if(!session) return; + + /* try to find verse node in dynamic list nodes */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find verse bitmap layer in list of layers */ + vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id); + if(!vblayer) return; + + /* we have to have allocated memory for bitmap layer */ + if(!vblayer->data) return; + + width = ((VBitmapData*)vnode->data)->width; + height = ((VBitmapData*)vnode->data)->height; + + /* width of verse image including all tiles */ + t_height = ((VBitmapData*)vnode->data)->t_height; + /* height of verse image including all tiles */ + t_width = ((VBitmapData*)vnode->data)->t_width; + +#ifdef VERSE_DEBUG_PRINT + printf("\t cb_b_tile_set()\n"); +#endif + + xs = tile_x*VN_B_TILE_SIZE; + ys = tile_y*VN_B_TILE_SIZE; + + /* initial position in one dimension vblayer->data (y_start*width + x_start) */ + i = ys*t_width + xs; + /* intial position in one dimension tile array */ + j = 0; + + if(type==VN_B_LAYER_UINT8) { + unsigned char *data = (unsigned char*)vblayer->data; + for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs) + for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++) + data[i] = (unsigned char)tile->vuint8[j]; + } + + /* post callback function */ + ((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys); +} + +/* + * set up all callbacks functions for image nodes + */ +void set_bitmap_callbacks(void) +{ + /* dimension (size) of bitmap was set up or changes (image will be croped) */ + verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL); + + /* new layer (chanell) of image was added or created */ + verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL); + + /* existing layer was destroyed */ + verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL); + + /* some tile (small part 8x8 pixels of image was changed) */ + verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL); +} + +#endif + diff --git a/source/blender/blenkernel/intern/verse_geometry_node.c b/source/blender/blenkernel/intern/verse_geometry_node.c new file mode 100644 index 00000000000..0b3f26007a6 --- /dev/null +++ b/source/blender/blenkernel/intern/verse_geometry_node.c @@ -0,0 +1,2101 @@ +/** + * $Id: verse_geometry_node.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_verse.h" +#include "BKE_utildefines.h" + +#include "BIF_verse.h" + +#include "verse.h" + +/* function prototypes of static functions */ + +/* test functions for callback functions */ +static char test_polygon_set_corner_uint32(uint32 v0, uint32 v1, uint32 v2, uint32 v3); + +/* callback functions */ +static void cb_g_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real); +static void cb_g_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id); +static void cb_g_vertex_set_xyz_real32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 vertex_id, real32 x, real32 y, real32 z); +static void cb_g_polygon_set_corner_uint32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3); +static void cb_g_vertex_delete_real32(void *user_data, VNodeID node_id, uint32 vertex_id); +static void cb_g_polygon_delete(void *user_data, VNodeID node_id, uint32 polygon_id); +static void cb_g_crease_set_edge(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease); +static void cb_g_crease_set_vertex(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease); + +/* other static functions */ + +static void free_unneeded_verseverts_of_verseface(struct VNode *vnode, struct VerseFace *vface); +static void free_verse_vertex(struct VLayer *vlayer, struct VerseVert *vvert); +static void free_verse_face(struct VLayer *vlayer, struct VerseFace *vface); +static void free_verse_layer_data(struct VNode *vnode, struct VLayer *vlayer); + +static void send_verse_face(struct VerseFace *vface); + +static VerseVert* find_verse_vert_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 vertex_id, real32 x, real32 y, real32 z); +static VerseFace* find_verse_face_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3); + +static unsigned short test_incoming_verseface(struct VGeomData *geom, struct VerseFace *vface); +static void find_unsent_faces(struct VNode *vnode, struct VerseVert *vvert); +static void find_vlayer_orphans(struct VNode *vnode, struct VerseVert *vvert); +static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer, struct VerseFace *vface); +static void increase_verse_verts_references(struct VerseFace *vface); +static void recalculate_verseface_normals(struct VNode *vnode); + +/* verse edge functions */ +static VerseEdge* find_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); +static void insert_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge); +static void remove_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge); +static void remove_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); +static void add_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); +static void update_edgehash_of_deleted_verseface(struct VNode *vnode, struct VerseFace *vface); +static void update_edgehash_of_changed_verseface(struct VNode *vnode, struct VerseFace *vface, uint32 v0, uint32 v1, uint32 v2, uint32 v3); +static void update_edgehash_of_new_verseface(struct VNode *vnode, uint32 v0, uint32 v1, uint32 v2, uint32 v3); + +/* + * recalcute normals of all VerseFaces + */ +static void recalculate_verseface_normals(VNode *vnode) +{ + struct VLayer *vert_layer, *face_layer; + struct VerseFace *vface; + struct VerseVert *vvert; + + if(vnode->type != V_NT_GEOMETRY) return; + + vert_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); + face_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); + + vvert = vert_layer->dl.lb.first; + while(vvert) { + vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0; + vvert = vvert->next; + } + + vface = face_layer->dl.lb.first; + while(vface) { + /* calculate face normals */ + if(vface->vvert3) { + CalcNormFloat4(vface->vvert0->co, vface->vvert1->co, + vface->vvert2->co, vface->vvert3->co, vface->no); + add_v3_v3v3(vface->vvert3->no, vface->vvert3->no, vface->no); + } + else + CalcNormFloat(vface->vvert0->co, vface->vvert1->co, + vface->vvert2->co, vface->no); + + /* calculate vertex normals ... it is averadge of all face normals using the vertex */ + add_v3_v3v3(vface->vvert0->no, vface->vvert0->no, vface->no); + add_v3_v3v3(vface->vvert1->no, vface->vvert1->no, vface->no); + add_v3_v3v3(vface->vvert2->no, vface->vvert2->no, vface->no); + + vface = vface->next; + } + + /* we have to normalize all vertex normals */ + vvert = vert_layer->dl.lb.first; + while(vvert) { + normalize_v3(vvert->no); + vvert = vvert->next; + } +} + +/* + * add created item to the queue and send it if possible + */ +void add_item_to_send_queue(ListBase *lb, void *item, short type) +{ + struct VNode *vnode; + struct VLayer *vlayer; + struct VerseVert *vvert; + struct VerseFace *vface; + + /* this prevent from adding duplicated faces */ + if(type==VERSE_FACE) { + struct Link *link = (Link*)lb->first; + while(link) { + if(link==item) { + if(((VerseFace*)item)->flag & FACE_SENT) { +/* printf("\tverse face %d marked as OBSOLETE\n", ((VerseFace*)item)->id);*/ + ((VerseFace*)item)->flag |= FACE_OBSOLETE; + } + return; + } + link = link->next; + } + } + + /* add item to sending queue (two way dynamic list) */ + BLI_addtail(lb, item); + + /* send item, when it is possible */ + switch (type) { + case VERSE_NODE: /* only first node in queue can be sent */ + if(lb->first==lb->last) + send_verse_node((VNode*)item); + break; + case VERSE_LINK: /* both object between have to exist */ + if(((VLink*)item)->flag & LINK_SEND_READY) + send_verse_link((VLink*)item); + break; + case VERSE_LAYER: + if(((VLayer*)item)->vnode->flag & NODE_RECEIVED) + send_verse_layer((VLayer*)item); + break; + case VERSE_VERT: + if(((VerseVert*)item)->vlayer->flag & LAYER_RECEIVED) + send_verse_vertex((VerseVert*)item); + break; + case VERSE_FACE: /* all vertexes of face have to be received */ + if(((VerseFace*)item)->flag & FACE_SEND_READY) + send_verse_face((VerseFace*)item); + break; + case VERSE_TAG: + send_verse_tag((VTag*)item); + break; + case VERSE_TAG_GROUP: + send_verse_taggroup((VTagGroup*)item); + break; + case VERSE_VERT_UINT32: /* parent item has to exist */ + vnode = (((uint32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); + vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id ); + if(vvert != NULL) + send_verse_vert_uint32((uint32_item*)item, type); + break; + case VERSE_VERT_REAL32: /* parent item has to exist */ + vnode = (((real32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); + vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id ); + if( vvert != NULL) + send_verse_vert_real32((real32_item*)item, type); + break; + case VERSE_VERT_VEC_REAL32: /* parent item has to exist */ + vnode = (((vec_real32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); + vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((vec_real32_item*)item)->id ); + if(vvert != NULL) + send_verse_vert_vec_real32((vec_real32_item*)item, type); + break; + case VERSE_FACE_UINT8: /* parent item has to exist */ + vnode = (((uint8_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint8_item*)item)->id ); + if(vface != NULL) + send_verse_face_uint8((uint8_item*)item, type); + break; + case VERSE_FACE_UINT32: /* parent item has to exist */ + vnode = (((uint32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id ); + if(vface != NULL) + send_verse_face_uint32((uint32_item*)item, type); + break; + case VERSE_FACE_REAL32: /* parent item has to exist */ + vnode = (((real32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id ); + if(vface != NULL) + send_verse_face_real32((real32_item*)item, type); + break; + case VERSE_FACE_QUAT_UINT32: /* parent item has to exist */ + vnode = (((quat_uint32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_uint32_item*)item)->id ); + if(vface != NULL) + send_verse_face_corner_quat_uint32((quat_uint32_item*)item, type); + break; + case VERSE_FACE_QUAT_REAL32: /* parent item has to exist */ + vnode = (((quat_real32_item*)item)->vlayer)->vnode; + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_real32_item*)item)->id ); + if(vface != NULL) + send_verse_face_corner_quat_real32((quat_real32_item*)item, type); + break; + } +} + +/* + * return VerseLayer with certain content (vertexes, polygons, in the + * future: weight, red color, etc.) + */ +VLayer* find_verse_layer_type(VGeomData *geom, short content) +{ + struct VLayer *vlayer = NULL; + + switch(content) { + case VERTEX_LAYER: + /* VERTEX_LAYER equals 0 and vertex layer is + * always in 1st layer */ + vlayer = geom->layers.da.items[VERTEX_LAYER]; + break; + case POLYGON_LAYER: + /* POLYGON_LAYER equals 1 and vertex layer is + * always in 2nd layer */ + vlayer = geom->layers.da.items[POLYGON_LAYER]; + break; + } + + return vlayer; +} + +/* + * increase references of VerseVerts of new VerseFace + */ +static void increase_verse_verts_references(VerseFace *vface) +{ + if(vface->vvert0) vface->vvert0->counter++; + if(vface->vvert1) vface->vvert1->counter++; + if(vface->vvert2) vface->vvert2->counter++; + if(vface->vvert3) vface->vvert3->counter++; +} + +/* + * move VerseFace from list of orphans to dlist of VerseFaces (if VerseFace was only changed + * then this VerseFace is only removed from list of orphans) + */ +static void move_face_orphan_to_dlist(VNode *vnode, VLayer *vlayer, VerseFace *vface) +{ + /* remove vface from list of orphans */ + BLI_remlink(&(vlayer->orphans), vface); + /* increase references of all vertexes beying part of this face*/ + increase_verse_verts_references(vface); + + if(vface->flag & FACE_RECEIVED) { + /* set up vface flag */ + vface->flag &= ~FACE_RECEIVED; + /* move vface to dynamic list of faces */ + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id); + /* recalculate all vertex and faces normals */ + recalculate_verseface_normals(vnode); + /* post create action (change local data) */ + ((VGeomData*)vnode->data)->post_polygon_create(vface); + } + else if(vface->flag & FACE_CHANGED) { + /* set up vface flag */ + vface->flag &= ~FACE_CHANGED; + /* move vface to dynamic list of faces */ + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id); + /* recalculate all vertex and faces normals */ + recalculate_verseface_normals(vnode); + /* post create action (change local data) */ + ((VGeomData*)vnode->data)->post_polygon_set_corner(vface); + } +} + +/* + * find all VerseFaces waiting in queue, which needs id of new VerseVert + */ +static void find_unsent_faces(VNode *vnode, VerseVert *vvert) +{ + VLayer *vlayer; + VerseFace *vface, *next_vface; + + vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); + + if(vlayer) { + vface = vlayer->queue.first; + while(vface) { + next_vface = vface->next; + if(vface->vvert0==vvert) { + vface->v0 = vvert->id; + vface->counter--; + } + else if(vface->vvert1==vvert) { + vface->v1 = vvert->id; + vface->counter--; + } + else if(vface->vvert2==vvert) { + vface->v2 = vvert->id; + vface->counter--; + } + else if(vface->vvert3==vvert){ + vface->v3 = vvert->id; + vface->counter--; + } + + if(vface->counter<1 && !(vface->flag & FACE_SENT)) + send_verse_face(vface); + + vface = next_vface; + } + } +} + +/* + * find all VerseFace orphans, which needs incoming VerseVert + */ +static void find_vlayer_orphans(VNode *vnode, VerseVert *vvert) +{ + VLayer *vlayer; + VerseFace *vface, *next_vface; + unsigned int vertex_id = vvert->id; + + vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); + + if(vlayer) { + vface = vlayer->orphans.first; + while(vface){ + next_vface = vface->next; + if(vface->v0 == vertex_id) { + vface->vvert0 = vvert; + vface->counter--; + } + else if(vface->v1 == vertex_id) { + vface->vvert1 = vvert; + vface->counter--; + } + else if(vface->v2 == vertex_id) { + vface->vvert2 = vvert; + vface->counter--; + } + else if(vface->v3 == vertex_id) { + vface->vvert3 = vvert; + vface->counter--; + } + if(vface->counter<1) { + /* moving VerseFace orphan to dlist */ + move_face_orphan_to_dlist(vnode, vlayer, vface); + } + vface = next_vface; + } + } +} + +/* + * return number of VerseVerts missing to incoming VerseFace, set up pointers + * at VerseVerts + */ +static unsigned short test_incoming_verseface(VGeomData *geom, VerseFace *vface) +{ + struct VLayer *vert_layer; + struct VerseVert *vvert; + int counter=0; + + vert_layer = find_verse_layer_type(geom, VERTEX_LAYER); + + if(vface->v0 != -1){ + vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v0); + if(vvert==NULL) counter++; + else vface->vvert0 = vvert; + } + if(vface->v1 != -1){ + vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v1); + if(vvert==NULL) counter++; + else vface->vvert1 = vvert; + } + if(vface->v2 != -1){ + vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v2); + if(vvert==NULL) counter++; + else vface->vvert2 = vvert; + } + if(vface->v3 != -1){ + vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v3); + if(vvert==NULL) counter++; + else vface->vvert3 = vvert; + } + + return counter; +} + +/* + * try to find changed VerseFace in sending queue + */ +static VerseFace* find_changed_verse_face_in_queue(VLayer *vlayer, uint32 polygon_id) +{ + struct VerseFace *vface = vlayer->queue.first; + + while(vface){ + if(vface->id == polygon_id && vface->flag & FACE_CHANGED) { + return vface; + } + vface = vface->next; + } + return NULL; +} + +/* + * try to find VerseFace in queue + */ +static VerseFace* find_verse_face_in_queue( + VLayer *vlayer, + VNodeID node_id, + uint32 polygon_id, + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + struct VerseFace *vface = vlayer->queue.first; + + while(vface){ + if((vface->v0==v0) && (vface->v1==v1) && (vface->v2==v2) && (vface->v3==v3)){ + vface->id = polygon_id; + vface->vlayer = vlayer; + return vface; + } + vface = vface->next; + } + return NULL; +} + +/* + * try to find VerseVert in queue + */ +static VerseVert* find_verse_vert_in_queue( + VLayer *vlayer, + VNodeID node_id, + uint32 vertex_id, + real32 x, + real32 y, + real32 z) +{ + struct VerseVert *vvert = vlayer->queue.first; + + while(vvert){ + if((vvert->vlayer->vnode->id == node_id) && (vvert->co[0] == x) && (vvert->co[1] == y) && (vvert->co[2] == z)) + { + vvert->id = vertex_id; + vvert->vlayer = vlayer; + + return vvert; + } + vvert = vvert->next; + } + + return NULL; +} + + +/* + * send quat of float values to verse server (4x32 bits) + */ +void send_verse_face_corner_quat_real32(quat_real32_item *item, short type) +{ + verse_send_g_polygon_set_corner_real32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value[0], + item->value[1], + item->value[2], + item->value[3]); +} + +/* + * send quat of unsigned int values to verse server (4x32 bits) + */ +void send_verse_face_corner_quat_uint32(quat_uint32_item *item, short type) +{ + verse_send_g_polygon_set_corner_uint32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value[0], + item->value[1], + item->value[2], + item->value[3]); +} + +/* + * send float value (32 bits) to verse server + */ +void send_verse_face_real32(real32_item *item, short type) +{ + verse_send_g_polygon_set_face_real32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value); +} + +/* + * send unsigned integer (32 bits) to verse server + */ +void send_verse_face_uint32(uint32_item *item, short type) +{ + verse_send_g_polygon_set_face_uint32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value); +} + +/* + * send unsigned char (8 bits) to verse server + */ +void send_verse_face_uint8(uint8_item *item, short type) +{ + verse_send_g_polygon_set_face_uint8( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value); +} + +/* + * send vector of float values to verse server (3x32 bits) + */ +void send_verse_vert_vec_real32(vec_real32_item *item, short type) +{ + verse_send_g_vertex_set_xyz_real32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value[0], + item->value[1], + item->value[2]); +} + +/* + * send float value (32 bits) to verse server + */ +void send_verse_vert_real32(real32_item *item, short type) +{ + verse_send_g_vertex_set_real32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value); +} + +/* + * send unsigned integer (32 bits) to verse server + */ +void send_verse_vert_uint32(uint32_item *item, short type) +{ + verse_send_g_vertex_set_uint32( + item->vlayer->vnode->id, + item->vlayer->id, + item->id, + item->value); +} + +/* + * send delete command to verse server + */ +void send_verse_vertex_delete(VerseVert *vvert) +{ + verse_session_set(vvert->vlayer->vnode->session->vsession); + + vvert->flag |= VERT_OBSOLETE; + + verse_send_g_vertex_delete_real32(vvert->vlayer->vnode->id, vvert->id); +} + +/* + * send VerseLayer to verse server + */ +void send_verse_layer(VLayer *vlayer) +{ + verse_session_set(vlayer->vnode->session->vsession); + + verse_send_g_layer_create( + vlayer->vnode->id, + vlayer->id, + vlayer->name, + vlayer->type, + vlayer->def_int, + vlayer->def_real); +} + +/* + * send VerseVert to verse server + */ +void send_verse_vertex(VerseVert *vvert) +{ + /* new vertex position will not be sent, when vertex was deleted */ + if(vvert->flag & VERT_OBSOLETE) return; + + verse_session_set(vvert->vlayer->vnode->session->vsession); + + verse_send_g_vertex_set_xyz_real32( + vvert->vlayer->vnode->id, + vvert->vlayer->id, + vvert->id, + vvert->co[0], + vvert->co[2], + -vvert->co[1]); +} + +/* + * send delete command to verse server + */ +void send_verse_face_delete(VerseFace *vface) +{ + verse_session_set(vface->vlayer->vnode->session->vsession); + + vface->flag |= FACE_DELETED; + + verse_send_g_polygon_delete(vface->vlayer->vnode->id, vface->id); +} + +/* + * send VerseFace to verse server + */ +static void send_verse_face(VerseFace *vface) +{ + verse_session_set(vface->vlayer->vnode->session->vsession); + + vface->flag |= FACE_SENT; + + if(vface->v3 != -1) { + verse_send_g_polygon_set_corner_uint32( + vface->vlayer->vnode->id, + vface->vlayer->id, + vface->id, + vface->v0, + vface->v3, /* verse use clock-wise winding */ + vface->v2, + vface->v1); /* verse use clock-wise winding */ + } + else { + verse_send_g_polygon_set_corner_uint32( + vface->vlayer->vnode->id, + vface->vlayer->id, + vface->id, + vface->v0, + vface->v2, /* verse use clock-wise winding */ + vface->v1, /* verse use clock-wise winding */ + vface->v3); + } +} + +/* + * free VerseVert + */ +static void free_verse_vertex(VLayer *vlayer, VerseVert *vvert) +{ + /* free VerseVert */ + BLI_freelinkN(&(vlayer->orphans), vvert); +} + +/* + * free VerseFace (and blender face) + */ +static void free_verse_face(VLayer *vlayer, VerseFace *vface) +{ + /* free VerseFace */ + BLI_dlist_free_item(&(vlayer->dl), (unsigned int)vface->id); +} + +/* + * free VerseLayer data + */ +static void free_verse_layer_data(VNode *vnode, VLayer *vlayer) +{ + struct VerseFace *vface; + struct VerseVert *vvert; + + /* set up EditVert->vvert and EditFace->vface pointers to NULL */ + switch(vlayer->content) { + case VERTEX_LAYER: + vvert = (VerseVert*)vlayer->dl.lb.first; + while(vvert) { + ((VGeomData*)vnode->data)->post_vertex_free_constraint(vvert); + vvert = vvert->next; + } + break; + case POLYGON_LAYER: + vface = (VerseFace*)vlayer->dl.lb.first; + while(vface) { + ((VGeomData*)vnode->data)->post_polygon_free_constraint(vface); + vface = vface->next; + } + break; + default: + break; + } + /* free Verse Layer name */ + MEM_freeN(vlayer->name); + /* destroy VerseLayer data (vertexes, polygons, etc.) */ + BLI_dlist_destroy(&(vlayer->dl)); + /* free unsent data */ + BLI_freelistN(&(vlayer->queue)); + /* free orphans */ + BLI_freelistN(&(vlayer->orphans)); +} + +/* + * free all unneeded VerseVerts waiting for deleting + */ +static void free_unneeded_verseverts_of_verseface(VNode *vnode, VerseFace *vface) +{ + struct VLayer *vert_vlayer; + + /* find layer containing vertexes */ + vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); + + /* free all "deleted" VerseVert waiting for deleting this VerseFace */ + + if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0); + free_verse_vertex(vert_vlayer, vface->vvert0); + vface->vvert0 = NULL; + } + if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1); + free_verse_vertex(vert_vlayer, vface->vvert1); + vface->vvert1 = NULL; + } + if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2); + free_verse_vertex(vert_vlayer, vface->vvert2); + vface->vvert2 = NULL; + } + if((vface->vvert3) && (vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3); + free_verse_vertex(vert_vlayer, vface->vvert3); + vface->vvert3 = NULL; + } +} + +/* + * This function create VerseVert and returns pointer on this vertex + */ +VerseVert* create_verse_vertex( + VLayer *vlayer, + uint32 vertex_id, + real32 x, + real32 y, + real32 z) +{ + struct VerseVert *vvert; + + vvert = (VerseVert*)MEM_mallocN(sizeof(VerseVert), "VerseVert"); + + /* set up pointer on parent node */ + vvert->vlayer = vlayer; + vvert->id = vertex_id; + /* position */ + vvert->co[0] = x; + vvert->co[1] = y; + vvert->co[2] = z; + /* normal */ + vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0; + /* blender internals */ + vvert->flag = 0; + vvert->counter = 0; + vvert->vertex = NULL; + + /* increase layer counter of vertexes */ + vlayer->counter++; + + return vvert; +} + +/* + * this function creates fake VerseEdge and returns pointer at this edge + */ +VerseEdge *create_verse_edge(uint32 v0, uint32 v1) +{ + struct VerseEdge *vedge; + + vedge = (VerseEdge*)MEM_mallocN(sizeof(VerseEdge), "VerseEdge"); + + vedge->v0 = v0; + vedge->v1 = v1; + vedge->counter = 0; + + return vedge; +} + +/* + * this function will create new VerseFace and will return pointer on such Face + */ +VerseFace* create_verse_face( + VLayer *vlayer, + uint32 polygon_id, + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + struct VerseFace *vface; + + vface = (VerseFace*)MEM_mallocN(sizeof(VerseFace), "VerseFace"); + + /* verse data */ + vface->vlayer = vlayer; + vface->id = polygon_id; + + vface->vvert0 = NULL; + vface->vvert1 = NULL; + vface->vvert2 = NULL; + vface->vvert3 = NULL; + + vface->v0 = v0; + vface->v1 = v1; + vface->v2 = v2; + vface->v3 = v3; + + /* blender data */ + vface->face = NULL; + vface->flag = 0; + vface->counter = 4; + + /* increase layer counter of faces */ + vlayer->counter++; + + return vface; +} + +/* + * create and return VerseLayer + */ +VLayer *create_verse_layer( + VNode *vnode, + VLayerID layer_id, + const char *name, + VNGLayerType type, + uint32 def_integer, + real64 def_real) +{ + struct VLayer *vlayer; + + /* add layer to the DynamicList */ + vlayer = (VLayer*)MEM_mallocN(sizeof(VLayer), "VerseLayer"); + + /* store all relevant info to the vlayer and set up vlayer */ + vlayer->vnode = vnode; + vlayer->id = layer_id; + vlayer->name = (char*)MEM_mallocN(sizeof(char)*(sizeof(name)+1),"Verse Layer name"); + strcpy(vlayer->name, name); + vlayer->type = type; + vlayer->def_int = def_integer; + vlayer->def_real = def_real; + + if((type == VN_G_LAYER_VERTEX_XYZ) && (layer_id == 0)) + vlayer->content = VERTEX_LAYER; + else if((type == VN_G_LAYER_POLYGON_CORNER_UINT32) && (layer_id == 1)) + vlayer->content = POLYGON_LAYER; + else + vlayer->content = -1; + + /* initialize DynamicList in the vlayer (vertexes, polygons, etc.)*/ + BLI_dlist_init(&(vlayer->dl)); + /* initialization of queue of layer */ + vlayer->queue.first = vlayer->queue.last = NULL; + /* initialization of list of orphans */ + vlayer->orphans.first = vlayer->orphans.last = NULL; + /* initialize number of sent items (vertexes, faces, etc) */ + vlayer->counter = 0; + /* initialize flag */ + vlayer->flag = 0; + + /* set up methods */ + vlayer->post_layer_create = post_layer_create; + vlayer->post_layer_destroy = post_layer_destroy; + + return vlayer; +} + +/* + * create geometry data + */ +VGeomData *create_geometry_data(void) +{ + struct VGeomData *geom; + + geom = (VGeomData*)MEM_mallocN(sizeof(VGeomData), "VerseGeometryData"); + BLI_dlist_init(&(geom->layers)); + geom->vlink = NULL; + geom->queue.first = geom->queue.last = NULL; + geom->mesh = NULL; + geom->editmesh = NULL; + + /* initialize list of fake verse edges and initialize verse edge hash */ + geom->edges.first = geom->edges.last = NULL; + geom->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); + + /* set up methods */ + geom->post_vertex_create = post_vertex_create; + geom->post_vertex_set_xyz = post_vertex_set_xyz; + geom->post_vertex_delete = post_vertex_delete; + geom->post_vertex_free_constraint = post_vertex_free_constraint; + geom->post_polygon_create = post_polygon_create; + geom->post_polygon_set_corner = post_polygon_set_corner; + geom->post_polygon_delete = post_polygon_delete; + geom->post_polygon_free_constraint = post_polygon_free_constraint; + geom->post_geometry_free_constraint = post_geometry_free_constraint; + geom->post_polygon_set_uint8 = post_polygon_set_uint8; + + return geom; +} + +/* Create item containing 4 floats */ +static quat_real32_item *create_quat_real32_item( + VLayer *vlayer, + uint32 item_id, + real32 v0, + real32 v1, + real32 v2, + real32 v3) +{ + struct quat_real32_item *item; + + item = (quat_real32_item*)MEM_mallocN(sizeof(quat_real32_item), "quat_real32_item"); + + item->vlayer = vlayer; + item->id = item_id; + item->value[0] = v0; + item->value[1] = v1; + item->value[2] = v2; + item->value[3] = v3; + + return item; +} + +/* Create item containing 1 float */ +static real32_item *create_real32_item(VLayer *vlayer, uint32 item_id, real32 value) +{ + struct real32_item *item; + + item = (real32_item*)MEM_mallocN(sizeof(real32_item), "real32_item"); + + item->vlayer = vlayer; + item->id = item_id; + item->value = value; + + return item; +} + +/* Create item containing 1 integer */ +static uint32_item *create_uint32_item(VLayer *vlayer, uint32 item_id, uint32 value) +{ + struct uint32_item *item; + + item = (uint32_item*)MEM_mallocN(sizeof(uint32_item), "uint32_item"); + + item->vlayer = vlayer; + item->id = item_id; + item->value = value; + + return item; +} + +/* Create item containing 1 byte */ +static uint8_item *create_uint8_item(VLayer *vlayer, uint32 item_id, uint8 value) +{ + struct uint8_item *item; + + item = (uint8_item*)MEM_mallocN(sizeof(uint8_item), "uint8_item"); + + item->vlayer = vlayer; + item->id = item_id; + item->value = value; + + return item; +} + +/* + * callback function: vertex crease was set + */ +static void cb_g_crease_set_vertex( + void *user_data, + VNodeID node_id, + const char *layer, + uint32 def_crease) +{ +} + +/* + * we have to test corretness of incoming data from verse server + * no two vertexes can have the same index + */ +static char test_polygon_set_corner_uint32( + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + if((v0==v1) || (v0==v2) || (v0==v3) || (v1==v2) || (v1==v3) || (v2==v3)) + return 0; + else + return 1; +} + +/* + * try to find verse layer in sending queue of verse geometry node + */ +static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id) +{ + struct VLayer *vlayer; + + /* try to find verse layyer in sending queue */ + vlayer = ((VGeomData*)vnode->data)->queue.first; + while(vlayer) { + if(vlayer->id==layer_id) return vlayer; + vlayer = vlayer->next; + } + + return NULL; +} + +/* + * this function will find edge in hash table, hash function isn't too optimal (it needs + * lot of memory for every verse node), but it works without any bug + */ +static VerseEdge* find_verse_edge(VNode *vnode, uint32 v0, uint32 v1) +{ + struct HashVerseEdge *hve; + + if(((VGeomData*)vnode->data)->hash==NULL) + ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); + + hve = ((VGeomData*)vnode->data)->hash + VEDHASH(v0, v1);; + while(hve) { + /* edge v0---v1 is the same edge as v1---v0 */ + if(hve->vedge && ((hve->vedge->v0==v0 && hve->vedge->v1==v1) || (hve->vedge->v0==v1 && hve->vedge->v1==v0))) return hve->vedge; + hve = hve->next; + } + + return NULL; +} + +/* + * insert hash of verse edge to hash table + */ +static void insert_verse_edgehash(VNode *vnode, VerseEdge *vedge) +{ + struct HashVerseEdge *first, *hve; + + if(((VGeomData*)vnode->data)->hash==NULL) + ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); + + first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1); + + if(first->vedge==NULL) { + first->vedge = vedge; + } + else { + hve = &(vedge->hash); + hve->vedge = vedge; + hve->next = first->next; + first->next = hve; + } +} + +/* + * remove hash of verse edge from hash table + */ +static void remove_verse_edgehash(VNode *vnode, VerseEdge *vedge) +{ + struct HashVerseEdge *first, *hve, *prev; + + hve = first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1); + + while(hve) { + if(hve->vedge == vedge) { + if(hve==first) { + if(first->next) { + hve = first->next; + first->vedge = hve->vedge; + first->next = hve->next; + } + else { + hve->vedge = NULL; + } + } + else { + prev->next = hve->next; + } + return; + } + prev = hve; + hve = hve->next; + } +} + +/* + * this function will try to remove existing fake verse edge, when this verse + * edge is still used by some faces, then counter will be only decremented + */ +static void remove_verse_edge(VNode *vnode, uint32 v0, uint32 v1) +{ + struct VerseEdge *vedge; + + vedge = find_verse_edge(vnode, v0, v1); + if(vedge) { + vedge->counter--; + if(vedge->counter==0) { + remove_verse_edgehash(vnode, vedge); + BLI_freelinkN(&(((VGeomData*)vnode->data)->edges), vedge); + } + } + else { + printf("error: remove_verse_edge %d, %d\n", v0, v1); + } +} + +/* + * this function will try to add new fake verse edge, when no such edge exist, + * when such edge exist, then only counter of edge will be incremented + */ +static void add_verse_edge(VNode *vnode, uint32 v0, uint32 v1) +{ + struct VerseEdge *vedge; + + vedge = find_verse_edge(vnode, v0, v1); + if(!vedge) { + if(v0!=v1) { + vedge = create_verse_edge(v0, v1); + BLI_addtail(&(((VGeomData*)vnode->data)->edges), vedge); + insert_verse_edgehash(vnode, vedge); + } + else { + printf("error:add_verse_edge: %d, %d\n", v0, v1); + return; + } + } + vedge->counter++; +} + +/* + * verse face was deleted ... update edge hash + */ +static void update_edgehash_of_deleted_verseface(VNode *vnode, VerseFace *vface) +{ + uint32 v0, v1, v2, v3; /* verse vertex indexes of deleted verse face */ + + v0 = vface->vvert0->id; + v1 = vface->vvert1->id; + v2 = vface->vvert2->id; + v3 = vface->vvert3 ? vface->vvert3->id : -1; + + remove_verse_edge(vnode, v0, v1); + remove_verse_edge(vnode, v1, v2); + if(v3!=-1) { + remove_verse_edge(vnode, v2, v3); + remove_verse_edge(vnode, v3, v0); + } + else { + remove_verse_edge(vnode, v2, v0); + } +} + +/* + * existing verse face was changed ... update edge hash + */ +static void update_edgehash_of_changed_verseface( + VNode *vnode, + VerseFace *vface, + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + uint32 ov0, ov1, ov2, ov3; /* old indexes at verse vertexes*/ + + ov0 = vface->vvert0->id; + ov1 = vface->vvert1->id; + ov2 = vface->vvert2->id; + ov3 = vface->vvert3 ? vface->vvert3->id : -1; + + /* 1st edge */ + if(v0!=ov0 || v1!=ov1) { + remove_verse_edge(vnode, ov0, ov1); + add_verse_edge(vnode, v0, v1); + } + + /* 2nd edge */ + if(v1!=ov1 || v2!=ov2) { + remove_verse_edge(vnode, ov1, ov2); + add_verse_edge(vnode, v1, v2); + } + + /* 3rd edge */ + if(v2!=ov2 || v3!=ov3 || v0!=ov0) { + if(ov3!=-1) { + remove_verse_edge(vnode, ov2, ov3); + if(v3!=-1) { + add_verse_edge(vnode, v2, v3); /* new 3rd edge (quat->quat) */ + } + else { + remove_verse_edge(vnode, ov3, ov0); /* old edge v3,v0 of quat have to be removed */ + add_verse_edge(vnode, v2, v0); /* new 3rd edge (quat->triangle) */ + } + } + else { + remove_verse_edge(vnode, ov2, ov0); + if(v3!=-1) { + add_verse_edge(vnode, v2, v3); /* new 3rd edge (triangle->quat) */ + } + else { + add_verse_edge(vnode, v2, v0); /* new 3rd edge (triangle->triangle) */ + } + } + } + + /* 4th edge */ + if(v3!=-1 && (v3!=ov3 || v0!=ov0)) { + remove_verse_edge(vnode, ov3, ov0); + add_verse_edge(vnode, v3, v0); + } +} + +/* + * new verse face was created ... update list of edges and edge has + */ +static void update_edgehash_of_new_verseface( + VNode *vnode, + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + /* when edge already exists, then only its counter is incremented, + * look at commentary of add_verse_edge() function */ + add_verse_edge(vnode, v0, v1); + add_verse_edge(vnode, v1, v2); + if(v3!=-1) { + add_verse_edge(vnode, v2, v3); + add_verse_edge(vnode, v3, v0); + } + else { + add_verse_edge(vnode, v2, v0); + } +} + +/* + * callback function: edge crease was set + */ +static void cb_g_crease_set_edge( + void *user_data, + VNodeID node_id, + const char *layer, + uint32 def_crease) +{ +} + +/* + * callback function: float value for polygon was set up + */ +static void cb_g_polygon_set_face_real32( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 polygon_id, + real32 value) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct real32_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); + + if(item) { + item->value = value; + } + else { + item = create_real32_item(vlayer, polygon_id, value); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: int values for polygon was set up + */ +static void cb_g_polygon_set_face_uint32( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 polygon_id, + uint32 value) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct uint32_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); + + if(item) { + item->value = value; + } + else { + item = create_uint32_item(vlayer, polygon_id, value); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: uint8 value for polygon was set up + */ +static void cb_g_polygon_set_face_uint8( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 polygon_id, + uint8 value) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct uint8_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); + + if(item) { + item->value = value; + } + else { + item = create_uint8_item(vlayer, polygon_id, value); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: float value for polygon corner was set up + */ +static void cb_g_polygon_set_corner_real32( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 polygon_id, + real32 v0, + real32 v1, + real32 v2, + real32 v3) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct quat_real32_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); + + if(item) { + item->value[0] = v0; + item->value[1] = v1; + item->value[2] = v2; + item->value[3] = v3; + } + else { + item = create_quat_real32_item(vlayer, polygon_id, v0, v1, v2, v3); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: polygon is deleted + */ +static void cb_g_polygon_delete( + void *user_data, + VNodeID node_id, + uint32 polygon_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + VNode *vnode; + VLayer *vlayer; + VerseFace *vface; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + + /* find layer containing faces */ + vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); + + /* find wanted VerseFace */ + vface = BLI_dlist_find_link(&(vlayer->dl), polygon_id); + + if(!vface) return; + + /* update edge hash */ + update_edgehash_of_deleted_verseface(vnode, vface); + + ((VGeomData*)vnode->data)->post_polygon_delete(vface); + + /* decrease references at coresponding VerseVertexes */ + vface->vvert0->counter--; + vface->vvert1->counter--; + vface->vvert2->counter--; + if(vface->vvert3) vface->vvert3->counter--; + + /* delete unneeded VerseVertexes */ + free_unneeded_verseverts_of_verseface(vnode, vface); + + free_verse_face(vlayer, vface); +} + +/* + * callback function: new polygon (face) created or existing polygon was changed + */ +static void cb_g_polygon_set_corner_uint32( + void *user_data, + VNodeID node_id, + VLayerID layer_id, + uint32 polygon_id, + uint32 v0, + uint32 v1, + uint32 v2, + uint32 v3) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct VerseFace *vface=NULL; + + if(!session) return; + + /* try to find VerseNode */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find VerseLayer */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + if(!vlayer) return; + + /* we have to test coretness of incoming data */ + if(!test_polygon_set_corner_uint32(v0, v1, v2, v3)) return; + + /* Blender uses different order of vertexes */ + if(v3!=-1) { /* quat swap */ + unsigned int v; v = v1; v1 = v3; v3 = v; + } + else { /* triangle swap */ + unsigned int v; v = v1; v1 = v2; v2 = v; + } + + /* try to find VerseFace */ + vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)polygon_id); + + /* try to find modified VerseFace */ + if(!vface) { + vface = find_changed_verse_face_in_queue(vlayer, polygon_id); + if(vface) { + BLI_remlink(&(vlayer->queue), (void*)vface); + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id); + } + } + + if(!vface) { + /* try to find VerseFace in list of VerseVaces created by me and set up polygon and + * layer ids */ + vface = find_verse_face_in_queue(vlayer, node_id, polygon_id, v0, v1, v2, v3); + + /* update edge hash */ + update_edgehash_of_new_verseface(vnode, v0, v1, v2, v3); + + if(vface){ + /* I creeated this face ... remove VerseFace from queue */ + BLI_remlink(&(vlayer->queue), (void*)vface); + } + else { + /* some other client created this face*/ + vface = create_verse_face(vlayer, polygon_id, v0, v1, v2, v3); + } + + vface->flag &= ~FACE_SENT; + + /* return number of missing verse vertexes */ + vface->counter = test_incoming_verseface((VGeomData*)vnode->data, vface); + + if(vface->counter < 1) { + /* when VerseFace received all needed VerseFaces, then it is moved + * to list of VerseFaces */ + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id); + increase_verse_verts_references(vface); + recalculate_verseface_normals(vnode); + ((VGeomData*)vnode->data)->post_polygon_create(vface); + } + else { + /* when all needed VerseVertexes weren't received, then VerseFace is moved to + * the list of orphans waiting on needed vertexes */ + vface->flag |= FACE_RECEIVED; + BLI_addtail(&(vlayer->orphans), (void*)vface); + } + } + else { + VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); + /* VerseVertexes of existing VerseFace were changed (VerseFace will use some different + * VerseVertexes or it will use them in different order) */ + + /* update fake verse edges */ + update_edgehash_of_changed_verseface(vnode, vface, v0, v1, v2, v3); + + /* initialize count of unreceived vertexes needed for this face */ + vface->counter = 4; + + /* 1st corner */ + if(vface->vvert0->id != v0) { + /* decrease references of obsolete vertexes*/ + vface->vvert0->counter--; + /* delete this vertex, when it isn't used by any face and it was marked as deleted */ + if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0); + free_verse_vertex(vert_vlayer, vface->vvert0); + } + /* try to set up new pointer at verse vertex */ + vface->v0 = v0; + vface->vvert0 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v0); + if(vface->vvert0) { + /* increase references at new vertex */ + vface->vvert0->counter++; + /* decrease count of needed vertex to receive */ + vface->counter--; + } + + } + else + /* this corner wasn't changed */ + vface->counter--; + + /* 2nd corner */ + if(vface->vvert1->id != v1) { + vface->vvert1->counter--; + if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1); + free_verse_vertex(vert_vlayer, vface->vvert1); + } + vface->v1 = v1; + vface->vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v1); + if(vface->vvert1) { + vface->vvert1->counter++; + vface->counter--; + } + } + else + vface->counter--; + + /* 3rd corner */ + if(vface->vvert2->id != v2) { + vface->vvert2->counter--; + if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2); + free_verse_vertex(vert_vlayer, vface->vvert2); + } + vface->v2 = v2; + vface->vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v2); + if(vface->vvert2) { + vface->vvert2->counter++; + vface->counter--; + } + } + else + vface->counter--; + + /* 4th corner */ + if(vface->vvert3) { + if(vface->vvert3->id != v3) { + vface->vvert3->counter--; + if((vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) { + ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3); + free_verse_vertex(vert_vlayer, vface->vvert3); + } + vface->v3 = v3; + if(v3 != -1) { + vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3); + if(vface->vvert3) { + vface->vvert3->counter++; + vface->counter--; + } + } + else { + /* this is some special case, this face hase now only 3 corners + * quat -> triangle */ + vface->vvert3 = NULL; + vface->counter--; + } + } + } + else if(v3 != -1) + /* this is some special case, 4th corner of this polygon was created + * triangle -> quat */ + vface->v3 = v3; + vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3); + if(vface->vvert3) { + vface->vvert3->counter++; + vface->counter--; + } + else { + vface->v3 = -1; + vface->counter--; + } + + vface->flag &= ~FACE_SENT; + vface->flag |= FACE_CHANGED; + + if(vface->counter<1) { + vface->flag &= ~FACE_CHANGED; + recalculate_verseface_normals(vnode); + ((VGeomData*)vnode->data)->post_polygon_set_corner(vface); + } + else { + /* when all needed VerseVertexes weren't received, then VerseFace is added to + * the list of orphans waiting on needed vertexes */ + BLI_dlist_rem_item(&(vlayer->dl), vface->id); + BLI_addtail(&(vlayer->orphans), (void*)vface); + } + } +} + +/* + * callback function: float value was set up for VerseVert with vertex_id + */ +static void cb_g_vertex_set_real32( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 vertex_id, + real32 value) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct real32_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), vertex_id); + + if(item) { + item->value = value; + } + else { + item = create_real32_item(vlayer, vertex_id, value); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: int value was set up for VerseVert with vertex_id + */ +static void cb_g_vertex_set_uint32( + void *user_def, + VNodeID node_id, + VLayerID layer_id, + uint32 vertex_id, + uint32 value) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + struct uint32_item *item; + + if(!session) return; + + /* find needed node (we can be sure, that it is geometry node) */ + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + /* find layer containing uint_8 data */ + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + + /* try to find item*/ + item = BLI_dlist_find_link(&(vlayer->dl), vertex_id); + + if(item) { + item->value = value; + } + else { + item = create_uint32_item(vlayer, vertex_id, value); + BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); + } +} + +/* + * callback function: polygon was deleted + */ +static void cb_g_vertex_delete_real32( + void *user_data, + VNodeID node_id, + uint32 vertex_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + VNode *vnode=NULL; + VLayer *vert_vlayer=NULL; + VerseVert *vvert=NULL; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); + + vvert = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vertex_id); + + if(!vvert) return; + + if(vvert->counter < 1) { + ((VGeomData*)vnode->data)->post_vertex_delete(vvert); + BLI_dlist_free_item(&(vert_vlayer->dl), (unsigned int)vertex_id); + } + else { + /* some VerseFace(s) still need VerseVert, remove verse vert from + * list verse vertexes and put it to list of orphans */ + vvert->flag |= VERT_DELETED; + BLI_dlist_rem_item(&(vert_vlayer->dl), (unsigned int)vertex_id); + BLI_addtail(&(vert_vlayer->orphans), vvert); + } +} + +/* + * callback function: position of one vertex was changed or new vertex was created + */ +static void cb_g_vertex_set_xyz_real32( + void *user_data, + VNodeID node_id, + VLayerID layer_id, + uint32 vertex_id, + real32 x, + real32 y, + real32 z) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode = NULL; + struct VLayer *vlayer = NULL; + struct VerseVert *vvert = NULL; + real32 tmp; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode)return; + + vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); + if(!vlayer) return; + + /* switch axis orientation */ + tmp = y; + y = -z; + z = tmp; + + if(vlayer->id == 0) { + /* try to pick up verse vert from DynamicList */ + vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)vertex_id); + + if(vvert) { + if(vvert->flag & VERT_OBSOLETE) return; + + if (vvert->flag & VERT_LOCKED) { + /* this application changed position of this vertex */ + if((vvert->co[0]==x) && (vvert->co[1]==y) && (vvert->co[2]==z)) { + /* unlock vertex position */ + vvert->flag &= ~VERT_LOCKED; + /* call post_vertex_set_xyz only, when position of vertex is + * obsolete ... the new vertex position will be sent to + * verse server */ + if (vvert->flag & VERT_POS_OBSOLETE) { + ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert); + } + } + } + else { + /* somebody else changed position of this vertex*/ + if((vvert->co[0]!=x) || (vvert->co[1]!=y) || (vvert->co[2]!=z)) { + vvert->co[0] = x; + vvert->co[1] = y; + vvert->co[2] = z; + recalculate_verseface_normals(vnode); + ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert); + } + } + } + else { + /* create new verse vert */ + + /* test if we are authors of this vertex :-) */ + vvert = find_verse_vert_in_queue(vlayer, node_id, vertex_id, x, y, z); + + if(vvert) { + /* remove vert from queue */ + BLI_remlink(&(vlayer->queue), (void*)vvert); + /* add vvert to the dynamic list */ + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id); + /* set VerseVert flags */ + vvert->flag |= VERT_RECEIVED; + if(!(vvert->flag & VERT_POS_OBSOLETE)) + vvert->flag &= ~VERT_LOCKED; + /* find VerseFaces orphans */ + find_vlayer_orphans(vnode, vvert); + /* find unsent VerseFaces */ + find_unsent_faces(vnode, vvert); + } + else { + /* create new VerseVert */ + vvert = create_verse_vertex(vlayer, vertex_id, x, y, z); + /* add VerseVert to list of VerseVerts */ + BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id); + /* set VerseVert flags */ + vvert->flag |= VERT_RECEIVED; + /* find VerseFaces orphans */ + find_vlayer_orphans(vnode, vvert); + } + + ((VGeomData*)vnode->data)->post_vertex_create(vvert); + } + } +} + +/* + * callback function for destroyng of verse layer + */ +static void cb_g_layer_destroy( + void *user_data, + VNodeID node_id, + VLayerID layer_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLayer *vlayer; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), node_id); + if(!vnode) return; + + vlayer = (VLayer*) BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), layer_id); + + if(vlayer){ + /* free VerseLayer data */ + free_verse_layer_data(vnode, vlayer); + /* remove VerseLayer from list of verse layers */ + BLI_dlist_rem_item(&(((VGeomData*)vnode->data)->layers), layer_id); + /* do client dependent actions */ + vlayer->post_layer_destroy(vlayer); + /* free vlayer itself */ + MEM_freeN(vlayer); + } + +} + +/* + * callback function: new layer was created + */ +static void cb_g_layer_create( + void *user_data, + VNodeID node_id, + VLayerID layer_id, + const char *name, + VNGLayerType type, + uint32 def_integer, + real64 def_real) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode=NULL; + struct VLayer *vlayer=NULL; + + if(!session) return; + + /* find node of this layer*/ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + if(!vnode) return; + + /* when we created this layer, then subscribe to this layer */ + if(vnode->owner_id == VN_OWNER_MINE || session->flag & VERSE_AUTOSUBSCRIBE) + verse_send_g_layer_subscribe(node_id, layer_id, 0); + + /* try to find */ + if(vnode->owner_id == VN_OWNER_MINE) + vlayer = find_vlayer_in_sending_queue(vnode, layer_id); + + if(vlayer) { + /* remove vlayer form sending queue add verse layer to list of verse layers */ + BLI_remlink(&((VGeomData*)vnode->data)->queue, vlayer); + BLI_dlist_add_item_index(&((VGeomData*)vnode->data)->layers, (void*)vlayer, (unsigned int)vlayer->id); + /* send all not sent vertexes to verse server + * other items waiting in sending queue will be automaticaly sent to verse server, + * when verse vertexes will be received from verse server */ + if((vlayer->type == VN_G_LAYER_VERTEX_XYZ) && (layer_id==0)) { + struct VerseVert *vvert = (VerseVert*)vlayer->queue.first; + while(vvert) { + send_verse_vertex(vvert); + vvert = vvert->next; + } + } + } + else { + /* create new VerseLayer */ + vlayer = create_verse_layer(vnode, layer_id, name, type, def_integer, def_real); + /* add layer to the list of VerseLayers */ + BLI_dlist_add_item_index(&(((VGeomData*)vnode->data)->layers), (void*)vlayer, (unsigned int)layer_id); + } + + vlayer->flag |= LAYER_RECEIVED; + + /* post callback function */ + vlayer->post_layer_create(vlayer); +} + +/* + * this function will send destroy commands for all VerseVertexes and + * VerseFaces to verse server, but it will not send destroy commands + * for VerseLayers or geometry node, it can be used in other functions + * (undo, destroy geom node, some edit mesh commands, ... ), parameter of + * this function has to be geometry verse node + */ +void destroy_geometry(VNode *vnode) +{ + struct VLayer *vert_vlayer, *face_vlayer; + struct VerseFace *vface; + struct VerseVert *vvert; + + if(vnode->type != V_NT_GEOMETRY) return; + + face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); + vface = face_vlayer->dl.lb.first; + + while(vface) { + send_verse_face_delete(vface); + vface = vface->next; + } + + vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); + vvert = vert_vlayer->dl.lb.first; + + while(vvert) { + send_verse_vertex_delete(vvert); + vvert = vvert->next; + } + + /* own destruction of local verse date will be executed, when client will + * receive apropriate callback commands from verse server */ +} + +/* + * free VGeomData + */ +void free_geom_data(VNode *vnode) +{ + struct VerseSession *session = vnode->session; + struct VLayer *vlayer; + + if(vnode->data){ + vlayer = (VLayer*)((VGeomData*)vnode->data)->layers.lb.first; + while(vlayer){ + /* unsubscribe from layer */ + if(session->flag & VERSE_CONNECTED) + verse_send_g_layer_unsubscribe(vnode->id, vlayer->id); + /* free VerseLayer data */ + free_verse_layer_data(vnode, vlayer); + /* next layer */ + vlayer = vlayer->next; + } + /* free constraint between vnode and mesh */ + ((VGeomData*)vnode->data)->post_geometry_free_constraint(vnode); + /* free all VerseLayers */ + BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers)); + /* free fake verse edges */ + BLI_freelistN(&((VGeomData*)vnode->data)->edges); + /* free edge hash */ + MEM_freeN(((VGeomData*)vnode->data)->hash); + } +} + +void set_geometry_callbacks(void) +{ + /* new layer created */ + verse_callback_set(verse_send_g_layer_create, cb_g_layer_create, NULL); + /* layer was destroyed */ + verse_callback_set(verse_send_g_layer_destroy, cb_g_layer_destroy, NULL); + + /* position of vertex was changed */ + verse_callback_set(verse_send_g_vertex_set_xyz_real32, cb_g_vertex_set_xyz_real32, NULL); + /* vertex was deleted */ + verse_callback_set(verse_send_g_vertex_delete_real32, cb_g_vertex_delete_real32, NULL); + + /* callback functions for values being associated with vertexes */ + verse_callback_set(verse_send_g_vertex_set_uint32, cb_g_vertex_set_uint32, NULL); + verse_callback_set(verse_send_g_vertex_set_real32, cb_g_vertex_set_real32, NULL); + + /* new polygon was created / vertex(es) of polygon was set */ + verse_callback_set(verse_send_g_polygon_set_corner_uint32, cb_g_polygon_set_corner_uint32, NULL); + /* polygon was deleted */ + verse_callback_set(verse_send_g_polygon_delete, cb_g_polygon_delete, NULL); + + /* callback functions for values being associated with polygon corners */ + verse_callback_set(verse_send_g_polygon_set_corner_real32, cb_g_polygon_set_corner_real32, NULL); + /* callback functions for values being associated with faces */ + verse_callback_set(verse_send_g_polygon_set_face_uint8, cb_g_polygon_set_face_uint8, NULL); + verse_callback_set(verse_send_g_polygon_set_face_uint32, cb_g_polygon_set_face_uint32, NULL); + verse_callback_set(verse_send_g_polygon_set_face_real32, cb_g_polygon_set_face_real32, NULL); + + /* crease of vertex was set */ + verse_callback_set(verse_send_g_crease_set_vertex, cb_g_crease_set_vertex, NULL); + /* crease of edge was set */ + verse_callback_set(verse_send_g_crease_set_edge, cb_g_crease_set_edge, NULL); +} + +#endif diff --git a/source/blender/blenkernel/intern/verse_method.c b/source/blender/blenkernel/intern/verse_method.c new file mode 100644 index 00000000000..20f7e2c9f9d --- /dev/null +++ b/source/blender/blenkernel/intern/verse_method.c @@ -0,0 +1,523 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Nathan Letwory. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_userdef_types.h" +#include "DNA_text_types.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BIF_verse.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_library.h" +#include "BKE_text.h" +#include "BKE_verse.h" +#include "BKE_global.h" +#include "BKE_main.h" + +#include "verse.h" + +/* helper struct for creating method descriptions */ +typedef struct VMethodInfo { + const char *name; + uint8 param_count; + const VNOParamType param_type[4]; + const char *param_name[4]; + uint16 id; +} VMethodInfo; + +#ifdef VERSECHAT +/* array with methods for verse chat */ +static VMethodInfo vmethod_info[] = { + { "join", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}}, + { "leave", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}}, + { "hear", 3, { VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING }, { "channel", "from", "msg"}} +}; +#endif + +/* lookup a method group based on its name */ +struct VMethodGroup *lookup_vmethodgroup_name(ListBase *lb, const char *name) { + struct VMethodGroup *vmg; + + for(vmg= lb->first; vmg; vmg= vmg->next) + if(strcmp(vmg->name,name)==0) break; + + return vmg; +} + +/* lookup a method group based on its group_id */ +struct VMethodGroup *lookup_vmethodgroup(ListBase *lb, uint16 group_id) { + struct VMethodGroup *vmg; + + for(vmg= lb->first; vmg; vmg= vmg->next) + if(vmg->group_id==group_id) break; + + return vmg; +} + +/* lookup a method based on its name */ +struct VMethod *lookup_vmethod_name(ListBase *lb, const char *name) { + struct VMethod *vm; + for(vm= lb->first; vm; vm= vm->next) + if(strcmp(vm->name,name)==0) break; + + return vm; +} + +/* lookup a method based on its method_id */ +struct VMethod *lookup_vmethod(ListBase *lb, uint8 method_id) { + struct VMethod *vm; + for(vm= lb->first; vm; vm= vm->next) + if(vm->id==method_id) break; + + return vm; +} + +#ifdef VERSECHAT +/* + * send say command + */ +void send_say(const char *chan, const char *utter) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + struct VMethod *vm; + VNOPackedParams *utterpack; + VNOParam args[2]; + + vnode= (VNode *)(session->nodes.lb.first); + + for( ; vnode; vnode= vnode->next) { + if(strcmp(vnode->name, "tawksrv")==0) { + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); + if(!vmg) break; + vm= lookup_vmethod_name(&(vmg->methods), "say"); + if(!vm) break; + args[0].vstring= (char *)chan; + args[1].vstring= (char *)utter; + if((utterpack= verse_method_call_pack(vm->param_count, vm->param_type, args))!=NULL) { + verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, utterpack); + } + break; + } + + } +} + +/* + * send logout command + */ +void send_logout(VNode *vnode) +{ + struct VMethodGroup *vmg; + struct VMethod *vm; + VNOPackedParams *pack; + + vnode->chat_flag = CHAT_LOGGED; + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); + if(!vmg) return; + vm= lookup_vmethod_name(&(vmg->methods), "logout"); + if(!vm) return; + + if((pack= verse_method_call_pack(vm->param_count, vm->param_type, NULL))!=NULL) { + verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, pack); + } + vnode->chat_flag = CHAT_NOTLOGGED; +} + +/* + * send join command + */ +void send_join(VNode *vnode, const char *chan) +{ + struct VMethodGroup *vmg; + struct VMethod *vm; + VNOPackedParams *join; + VNOParam channel[1]; + + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); + if(!vmg) return; + vm= lookup_vmethod_name(&(vmg->methods), "join"); + if(!vm) return; + + channel[0].vstring= (char *)chan; + if((join= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) { + verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, join); + } +} + +/* + * send leave command + */ +void send_leave(VNode *vnode, const char *chan) +{ + struct VMethodGroup *vmg; + struct VMethod *vm; + VNOPackedParams *leave; + VNOParam channel[1]; + + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); + if(!vmg) return; + vm= lookup_vmethod_name(&(vmg->methods), "leave"); + if(!vm) return; + + channel[0].vstring= (char *)chan; + if((leave= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) { + verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, leave); + } +} + +/* + * send login command + */ +void send_login(VNode *vnode) +{ + struct VMethodGroup *vmg; + struct VMethod *vm; + VNOPackedParams *login; + VNOParam param[1]; + + vnode->chat_flag = CHAT_LOGGED; + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); + if(!vmg) return; + vm= lookup_vmethod_name(&(vmg->methods), "login"); + if(!vm) return; + + param[0].vstring= U.verseuser; + + if((login= verse_method_call_pack(vm->param_count, vm->param_type, param))!=NULL) { + verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, login); + } + vnode->chat_flag = CHAT_LOGGED; + + vnode= lookup_vnode(vnode->session, vnode->session->avatar); + vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk-client"); + if(!vmg) + verse_send_o_method_group_create(vnode->session->avatar, ~0, "tawk-client"); +} +#endif + +/* + * Free a VMethod + */ +void free_verse_method(VMethod *vm) { + if(!vm) return; + + MEM_freeN(vm->param_type); +} + +/* + * Free methods for VMethodGroup + */ +void free_verse_methodgroup(VMethodGroup *vmg) +{ + struct VMethod *vm, *tmpvm; + + if(!vmg) return; + + vm= vmg->methods.first; + while(vm) { + tmpvm=vm->next; + free_verse_method(vm); + vm= tmpvm; + } + BLI_freelistN(&(vmg->methods)); +} + +/* callback for method group creation */ +static void cb_o_method_group_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + vmg = lookup_vmethodgroup(&(vnode->methodgroups), group_id); + + /* create method group holder in node node_id */ + if(!vmg) { + vmg= MEM_mallocN(sizeof(VMethodGroup), "VMethodGroup"); + vmg->group_id = group_id; + vmg->methods.first = vmg->methods.last = NULL; + BLI_addtail(&(vnode->methodgroups), vmg); + printf("new method group with name %s (group_id %d) for node %u created\n", name, group_id, node_id); + } + + /* this ensures name of an existing group gets updated, in case it is changed */ + BLI_strncpy(vmg->name, (char *)name, 16); + + /* subscribe to method group */ + verse_send_o_method_group_subscribe(node_id, group_id); + +#ifdef VERSECHAT + /* if this is our own method group, register our methods */ + if(node_id==session->avatar) { + verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[0].name, + vmethod_info[0].param_count, + (VNOParamType *)vmethod_info[0].param_type, + (const char **)vmethod_info[0].param_name); + b_verse_update(); + verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[1].name, + vmethod_info[1].param_count, + (VNOParamType *)vmethod_info[1].param_type, + (const char **)vmethod_info[1].param_name); + b_verse_update(); + verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[2].name, + vmethod_info[2].param_count, + (VNOParamType *)vmethod_info[2].param_type, + (const char **)vmethod_info[2].param_name); + b_verse_update(); + } +#endif +} + +/* callback for method group destruction */ +static void cb_o_method_group_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + struct VMethod *vm; + + printf("method group %d destroyed\n", group_id); + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next) + if(vmg->group_id==group_id) break; + + if(!vmg) return; /* method group doesn't exist? */ + + vmg->group_id = 0; + vmg->name[0] = '\0'; + vm= vmg->methods.first; + while(vm) { + /* free vm */ + + } + + /* TODO: unsubscribe from method group */ + BLI_remlink(&(vnode->methodgroups),vmg); + MEM_freeN(vmg); +} + +/* callback for method creation */ +static void cb_o_method_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 method_id, + const char *name, + uint8 param_count, + const VNOParamType *param_type, + const char *param_name[]) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + struct VMethod *vm; + unsigned int size; + unsigned int i; + char *put; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + vmg= lookup_vmethodgroup((&vnode->methodgroups), group_id); + + if(!vmg) return; + + vm= lookup_vmethod((&vmg->methods), method_id); + + if(!vm) { + vm= MEM_mallocN(sizeof(VMethod), "VMethod"); + vm->id= method_id; + vm->param_count= param_count; + size= param_count* (sizeof(*vm->param_type) + sizeof(*vm->param_name)); + for(i= 0; i <param_count; i++) { + size+=strlen(param_name[i])+1; + } + vm->param_type= MEM_mallocN(size, "param_type and param_name"); + memcpy(vm->param_type, param_type, sizeof(VNOParamType)*param_count); + vm->param_name= (char **)(vm->param_type + param_count); + put= (char *)(vm->param_name + param_count); + for(i= 0; i < param_count; i++) { + vm->param_name[i]= put; + strcpy(put, param_name[i]); + put += strlen(param_name[i]) + 1; + } + + BLI_addtail(&(vmg->methods), vm); +#ifdef VERSECHAT + if(strcmp(vmethod_info[0].name, name)==0) { + vmethod_info[0].id = method_id; + } +#endif + printf("method %s in group %d of node %u created\n", name, group_id, node_id); + } + + BLI_strncpy(vm->name, (char *)name, 500); +} + +/* callback for method destruction */ +static void cb_o_method_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 method_id, + const char *name, + uint8 param_count, + const VNOParamType *param_type, + const char *param_name[]) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + struct VMethod *vm; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next) + if(vmg->group_id==group_id) break; + + if(!vmg) return; /* method group doesn't exist? */ + + for(vm= vmg->methods.first; vm; vm= vm->next) + if(vm->id==method_id) break; + + if(!vm) return; + + BLI_remlink(&(vmg->methods), vm); + MEM_freeN(vm->param_type); + MEM_freeN(vm); +} + +/* callback for method calls */ +static void cb_o_method_call(void *user_data, VNodeID node_id, uint8 group_id, uint8 method_id, VNodeID sender, VNOPackedParams *params) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VMethodGroup *vmg; + struct VMethod *vm; + Text *text; + int method_idx= -1; + + VNOParam arg[3]; + + if(!session) return; + + if(session->avatar!=node_id) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + vmg= lookup_vmethodgroup(&(vnode->methodgroups), group_id); + if(!vmg) return; + + vm= lookup_vmethod(&(vmg->methods), method_id); + if(!vm) return; +#ifdef VERSECHAT + if(strcmp(vm->name, "join")==0) method_idx=0; + if(strcmp(vm->name, "leave")==0) method_idx=1; + if(strcmp(vm->name, "hear")==0) method_idx=2; + if(method_idx>-1) + verse_method_call_unpack(params, vmethod_info[method_idx].param_count, vmethod_info[method_idx].param_type, arg); + + switch(method_idx) { + case 0: + printf("Joining channel %s\n",arg[0].vstring); + text=add_empty_text(); + text->flags |= TXT_ISCHAT; + rename_id(&(text->id), arg[0].vstring); + break; + case 1: + printf("Leaving channel %s\n",arg[0].vstring); + break; + case 2: + { + ListBase lb = G.main->text; + ID *id= (ID *)lb.first; + char showstr[1024]; + showstr[0]='\0'; + text = NULL; + sprintf(showstr, "%s: %s\n", arg[1].vstring, arg[2].vstring); + for(; id; id= id->next) { + if(strcmp(id->name+2, arg[0].vstring)==0 && strcmp(arg[0].vstring, "#server")!=0) { + text = (Text *)id; + break; + } + } + if(text) { + txt_insert_buf(text, showstr); + txt_move_eof(text, 0); + allqueue(REDRAWCHAT, 0); + } else { + printf("%s> %s: %s\n",arg[0].vstring, arg[1].vstring, arg[2].vstring); + } + } + break; + } +#endif +} + +void set_method_callbacks(void) +{ + /* create and destroy method groups */ + verse_callback_set(verse_send_o_method_group_create, cb_o_method_group_create, NULL); + verse_callback_set(verse_send_o_method_group_destroy, cb_o_method_group_destroy, NULL); + + /* create and destroy methods */ + verse_callback_set(verse_send_o_method_create, cb_o_method_create, NULL); + verse_callback_set(verse_send_o_method_destroy, cb_o_method_destroy, NULL); + + /* call methods */ + verse_callback_set(verse_send_o_method_call, cb_o_method_call, NULL); +} + +#endif diff --git a/source/blender/blenkernel/intern/verse_node.c b/source/blender/blenkernel/intern/verse_node.c new file mode 100644 index 00000000000..682ae773da5 --- /dev/null +++ b/source/blender/blenkernel/intern/verse_node.c @@ -0,0 +1,750 @@ +/** + * $Id: verse_node.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_userdef_types.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" + +#include "BIF_verse.h" + +#include "BKE_verse.h" + +#include "verse.h" + +/* function prototypes of static functions */ + /* for tags */ +static void free_verse_tag_data(struct VTag *vtag); +static struct VTag *find_tag_in_queue(struct VTagGroup *vtaggroup, const char *name); +static struct VTag *create_verse_tag(struct VTagGroup *vtaggroup, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); + /* for verse tag groups */ +static void free_verse_taggroup_data(struct VTagGroup *taggroup); +static struct VTagGroup *find_taggroup_in_queue(struct VNode *vnode, const char *name); +static struct VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name); + /* for verse nodes */ +static void move_verse_node_to_dlist(struct VerseSession *session, VNodeID vnode_id); + /* function prototypes of node callback functions */ +static void cb_tag_destroy(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id); +static void cb_tag_create(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); +static void cb_tag_group_destroy(void *user_data, VNodeID node_id, uint16 group_id); +static void cb_tag_group_create(void *user_data, VNodeID node_id, uint16 group_id, const char *name); +static void cb_node_name_set(void *user_data, VNodeID node_id, const char *name); +static void cb_node_destroy(void *user_data, VNodeID node_id); +static void cb_node_create(void *user_data, VNodeID node_id, uint8 type, VNodeID owner_id); + +/* + * send new tag to verse server + */ +void send_verse_tag(VTag *vtag) +{ + verse_send_tag_create(vtag->vtaggroup->vnode->id, + vtag->vtaggroup->id, + vtag->id, + vtag->name, + vtag->type, + vtag->tag); +} + +/* + * free tag data + */ +static void free_verse_tag_data(VTag *vtag) +{ + /* free name of verse tag */ + MEM_freeN(vtag->name); + /* free value of tag */ + MEM_freeN(vtag->tag); +} + +/* + * try to find tag in sending queue ... if tag will be found, then + * this function will removed tag from queue and will return pointer + * at this tag + */ +static VTag *find_tag_in_queue(VTagGroup *vtaggroup, const char *name) +{ + struct VTag *vtag; + + vtag = vtaggroup->queue.first; + + while(vtag) { + if(strcmp(vtag->name, name)==0) { + BLI_remlink(&(vtaggroup->queue), vtag); + break; + } + vtag = vtag->next; + } + + return vtag; +} + +/* + * create new verse tag + */ +static VTag *create_verse_tag( + VTagGroup *vtaggroup, + uint16 tag_id, + const char *name, + VNTagType type, + const VNTag *tag) +{ + struct VTag *vtag; + + vtag = (VTag*)MEM_mallocN(sizeof(VTag), "VTag"); + + vtag->vtaggroup = vtaggroup; + vtag->id = tag_id; + vtag->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTag name"); + strcpy(vtag->name, name); + vtag->type = type; + + vtag->tag = (VNTag*)MEM_mallocN(sizeof(VNTag), "VNTag"); + *vtag->tag = *tag; + + vtag->value = NULL; + + return vtag; +} + +/* + * send taggroup to verse server + */ +void send_verse_taggroup(VTagGroup *vtaggroup) +{ + verse_send_tag_group_create( + vtaggroup->vnode->id, + vtaggroup->id, + vtaggroup->name); +} + +/* + * free taggroup data + */ +static void free_verse_taggroup_data(VTagGroup *taggroup) +{ + struct VerseSession *session = taggroup->vnode->session; + struct VTag *vtag; + + vtag = taggroup->tags.lb.first; + + while(vtag) { + free_verse_tag_data(vtag); + vtag = vtag->next; + } + + /* unsubscribe from taggroup */ + if(session->flag & VERSE_CONNECTED) + verse_send_tag_group_unsubscribe(taggroup->vnode->id, taggroup->id); + + BLI_dlist_destroy(&(taggroup->tags)); + MEM_freeN(taggroup->name); +} + +/* + * move taggroup from queue to dynamic list with access array, + * set up taggroup id and return pointer at this taggroup + */ +static VTagGroup *find_taggroup_in_queue(VNode *vnode, const char *name) +{ + struct VTagGroup *vtaggroup; + + vtaggroup = vnode->queue.first; + + while(vtaggroup) { + if(strcmp(vtaggroup->name, name)==0) { + BLI_remlink(&(vnode->queue), vtaggroup); + break; + } + vtaggroup = vtaggroup->next; + } + + return vtaggroup; +} + +/* + * create new verse group of tags + */ +static VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name) +{ + struct VTagGroup *taggroup; + + taggroup = (VTagGroup*)MEM_mallocN(sizeof(VTagGroup), "VTagGroup"); + + taggroup->vnode = vnode; + taggroup->id = group_id; + taggroup->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTagGroup name"); + strcpy(taggroup->name, name); + + BLI_dlist_init(&(taggroup->tags)); + taggroup->queue.first = taggroup->queue.last = NULL; + + taggroup->post_tag_change = post_tag_change; + taggroup->post_taggroup_create = post_taggroup_create; + + return taggroup; +} + +/* + * move first VerseNode waiting in sending queue to dynamic list of VerseNodes + * (it usually happens, when "our" VerseNode was received from verse server) + */ +static void move_verse_node_to_dlist(VerseSession *session, VNodeID vnode_id) +{ + VNode *vnode; + + vnode = session->queue.first; + + if(vnode) { + BLI_remlink(&(session->queue), vnode); + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, vnode_id); + } +} + +/* + * send VerseNode to verse server + */ +void send_verse_node(VNode *vnode) +{ + verse_send_node_create( + vnode->id, + vnode->type, + vnode->session->avatar); +} + +/* + * free Verse Node data + */ +void free_verse_node_data(VNode *vnode) +{ + struct VerseSession *session = vnode->session; + struct VTagGroup *vtaggroup; + + /* free node data (object, geometry, etc.) */ + switch(vnode->type){ + case V_NT_OBJECT: + free_object_data(vnode); + break; + case V_NT_GEOMETRY: + free_geom_data(vnode); + break; + case V_NT_BITMAP: + free_bitmap_node_data(vnode); + break; + default: + break; + } + + /* free all tag groups in dynamic list with access array */ + vtaggroup = vnode->taggroups.lb.first; + while(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + vtaggroup = vtaggroup->next; + } + BLI_dlist_destroy(&(vnode->taggroups)); + + /* free all tag groups still waiting in queue */ + vtaggroup = vnode->queue.first; + while(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + vtaggroup = vtaggroup->next; + } + BLI_freelistN(&(vnode->queue)); + + /* unsubscribe from node */ + if(session->flag & VERSE_CONNECTED) + verse_send_node_unsubscribe(vnode->id); + + /* free node name */ + MEM_freeN(vnode->name); + vnode->name = NULL; + + /* free node data */ + MEM_freeN(vnode->data); + vnode->data = NULL; + +} + +/* + * free VerseNode + */ +void free_verse_node(VNode *vnode) +{ + free_verse_node_data(vnode); + + BLI_dlist_free_item(&(vnode->session->nodes), vnode->id); +} + +/* + * Find a Verse Node from session + */ +VNode* lookup_vnode(VerseSession *session, VNodeID node_id) +{ + struct VNode *vnode; + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + return vnode; +} + +/* + * create new Verse Node + */ +VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id) +{ + struct VNode *vnode; + + vnode = (VNode*)MEM_mallocN(sizeof(VNode), "VerseNode"); + + vnode->session = session; + vnode->id = node_id; + vnode->owner_id = owner_id; + vnode->name = NULL; + vnode->type = type; + + BLI_dlist_init(&(vnode->taggroups)); + vnode->queue.first = vnode->queue.last = NULL; + vnode->methodgroups.first = vnode->methodgroups.last = NULL; + + vnode->data = NULL; + + vnode->counter = 0; + + vnode->flag = 0; +#ifdef VERSECHAT + vnode->chat_flag = CHAT_NOTLOGGED; +#endif + + vnode->post_node_create = post_node_create; + vnode->post_node_destroy = post_node_destroy; + vnode->post_node_name_set = post_node_name_set; + + return vnode; +} + +/* + * callback function: tag was destroyed + */ +static void cb_tag_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 tag_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + struct VTag *vtag; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) return; + + /* try to find verse tag in dynamic list of tags in tag group */ + vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); + + if(vtag) { + free_verse_tag_data(vtag); + BLI_dlist_free_item(&(vtaggroup->tags), vtag->id); + } +} + +/* + * callback function: new tag was created + */ +static void cb_tag_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 tag_id, + const char *name, + VNTagType type, + const VNTag *tag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + struct VTag *vtag; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) return; + + /* try to find verse tag in dynamic list of tags in tag group */ + vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); + + if(!vtag) { + /* we will try to find vtag in sending queue */ + vtag = find_tag_in_queue(vtaggroup, name); + + /* when we didn't create this tag, then we will have to create one */ + if(!vtag) vtag = create_verse_tag(vtaggroup, tag_id, name, type, tag); + else vtag->id = tag_id; + + /* add tag to the list of tags in tag group */ + BLI_dlist_add_item_index(&(vtaggroup->tags), vtag, tag_id); + + /* post change/create method */ + vtaggroup->post_tag_change(vtag); + } + else { + /* this tag exists, then we will propably change value of this tag */ + if((vtag->type != type) || (strcmp(vtag->name, name)!=0)) { + /* changes of type or name are not allowed and such + * stupid changes will be returned back */ + send_verse_tag(vtag); + } + else { + /* post change/create method */ + vtaggroup->post_tag_change(vtag); + } + } +} + +/* + * callback function: tag group was destroyed + */ +static void cb_tag_group_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + BLI_dlist_free_item(&(vnode->taggroups), vtaggroup->id); + } +} + +/* + * callback function: new tag group was created + */ +static void cb_tag_group_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* name of taggroup has to begin with string "blender:" */ + if(strncmp("blender:", name, 8)) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) { + /* subscribe to tag group (when new tag will be created, then blender will + * receive command about it) */ + verse_send_tag_group_subscribe(vnode->id, group_id); + verse_callback_update(0); + + /* try to find taggroup in waiting queue */ + vtaggroup = find_taggroup_in_queue(vnode, name); + + /* if no taggroup exist, then new has to be created */ + if(!vtaggroup) vtaggroup = create_verse_taggroup(vnode, group_id, name); + else vtaggroup->id = group_id; + + /* add tag group to dynamic list with access array */ + BLI_dlist_add_item_index(&(vnode->taggroups), (void*)vtaggroup, (unsigned int)group_id); + + /* post create method */ + vtaggroup->post_taggroup_create(vtaggroup); + } + else { + /* this taggroup exist and somebody try to change its name */ + if(strcmp(vtaggroup->name, name)!=0) { + /* blender doesn't allow such stupid and dangerous things */ + send_verse_taggroup(vtaggroup); + } + } +} + +/* + * callback function: change name of node + */ +static void cb_node_name_set( + void *user_data, + VNodeID node_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(vnode && name) { + if(!vnode->name) { + vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); + } + else if(strlen(name) > strlen(vnode->name)) { + MEM_freeN(vnode->name); + vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); + } + strcpy(vnode->name, name); + + vnode->post_node_name_set(vnode); + } +} + +/* + * callback function for deleting node + */ +static void cb_node_destroy( + void *user_data, + VNodeID node_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + if(vnode) { + /* remove VerseNode from dynamic list */ + BLI_dlist_rem_item(&(session->nodes), (unsigned int)node_id); + /* do post destroy operations */ + vnode->post_node_destroy(vnode); + /* free verse data */ + free_verse_node_data(vnode); + /* free VerseNode */ + MEM_freeN(vnode); + }; +} + + +/* + * callback function for new created node + */ +static void cb_node_create( + void *user_data, + VNodeID node_id, + uint8 type, + VNodeID owner_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode = NULL; + + if(!session) return; + + /* subscribe to node */ + if((type==V_NT_OBJECT) || (type==V_NT_GEOMETRY) || (type==V_NT_BITMAP)) + verse_send_node_subscribe(node_id); + else + return; + + switch(type){ + case V_NT_OBJECT : + if(owner_id==VN_OWNER_MINE) { + struct VLink *vlink; + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* find unsent link pointing at this VerseNode */ + vlink = find_unsent_child_vlink(session, vnode); + /* send VerseLink */ + if(vlink) send_verse_link(vlink); + /* send name of object node */ + verse_send_node_name_set(node_id, vnode->name); + /* subscribe to changes of object node transformations */ + verse_send_o_transform_subscribe(node_id, 0); + /* send object transformation matrix */ + send_verse_object_position(vnode); + send_verse_object_rotation(vnode); + send_verse_object_scale(vnode); + } + else { + /* create new VerseNode */ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to list of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create object data */ + vnode->data = create_object_data(); + /* set up avatar's name */ + if(node_id == session->avatar) { + verse_send_node_name_set(node_id, U.verseuser); + } + else if(session->flag & VERSE_AUTOSUBSCRIBE) { + /* subscribe to changes of object node transformations */ + verse_send_o_transform_subscribe(node_id, 0); + } + } + break; + case V_NT_GEOMETRY : + if(owner_id==VN_OWNER_MINE){ + struct VLink *vlink; + struct VLayer *vlayer; + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* find unsent link pointing at this VerseNode */ + vlink = find_unsent_parent_vlink(session, vnode); + /* send VerseLink */ + if(vlink) send_verse_link(vlink); + /* send name of geometry node */ + verse_send_node_name_set(node_id, vnode->name); + /* send all not sent layer to verse server */ + vlayer = (VLayer*)((VGeomData*)vnode->data)->queue.first; + if(vlayer) { + while(vlayer) { + send_verse_layer(vlayer); + vlayer = vlayer->next; + } + } + else { + /* send two verse layers to verse server */ +/* verse_send_g_layer_create(node_id, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0); + verse_send_g_layer_create(node_id, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);*/ + } + } + else { + /* create new VerseNode*/ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to dlist of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create geometry data */ + vnode->data = (void*)create_geometry_data(); + } + break; + case V_NT_BITMAP : + if(owner_id==VN_OWNER_MINE) { + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* send name of object node */ + verse_send_node_name_set(node_id, vnode->name); + /* send dimension of image to verse server */ + verse_send_b_dimensions_set(node_id, + ((VBitmapData*)vnode->data)->width, + ((VBitmapData*)vnode->data)->height, + ((VBitmapData*)vnode->data)->depth); + } + else { + /* create new VerseNode*/ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to dlist of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create bitmap data */ + vnode->data = (void*)create_bitmap_data(); + } + break; + default: + vnode = NULL; + break; + } + + if(vnode) vnode->post_node_create(vnode); +} + +/* + * set up all callbacks for verse nodes + */ +void set_node_callbacks(void) +{ + /* new node created */ + verse_callback_set(verse_send_node_create, cb_node_create, NULL); + /* node was deleted */ + verse_callback_set(verse_send_node_destroy, cb_node_destroy, NULL); + /* name of node was set */ + verse_callback_set(verse_send_node_name_set, cb_node_name_set, NULL); + + /* new tag group was created */ + verse_callback_set(verse_send_tag_group_create, cb_tag_group_create, NULL); + /* tag group was destroy */ + verse_callback_set(verse_send_tag_group_destroy, cb_tag_group_destroy, NULL); + + /* new tag was created */ + verse_callback_set(verse_send_tag_create, cb_tag_create, NULL); + /* tag was destroy */ + verse_callback_set(verse_send_tag_destroy, cb_tag_destroy, NULL); +} + +#endif diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c new file mode 100644 index 00000000000..fc5a27cd5d9 --- /dev/null +++ b/source/blender/blenkernel/intern/verse_object_node.c @@ -0,0 +1,620 @@ +/** + * $Id: verse_object_node.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_userdef_types.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BIF_verse.h" + +#include "BKE_verse.h" +#include "BKE_utildefines.h" + +#include "verse.h" + +/* function prototypes of static functions */ + +/* callback functions */ +static void cb_o_transform_pos_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const real32 *pos, const real32 *speed, const real32 *accelerate, const real32 *drag_normal, real32 drag); +static void cb_o_transform_rot_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const VNQuat32 *temp, const VNQuat32 *speed, const VNQuat32 *accelerate, const VNQuat32 *drag_normal, real32 drag); +static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z); +static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id); +static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id); + +/* other functions */ +static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink); +static void free_verse_link_data(struct VLink *vlink); + +/* + * find noy sent VerseLink in queue + */ +VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode) +{ + struct VLink *vlink; + + if(vnode->type!=V_NT_OBJECT) return NULL; + + vlink = ((VObjectData*)vnode->data)->queue.first; + while(vlink) { + if(vlink->target->id != -1) { + printf("\t vlink found, vnode target id %d\n", vlink->target->id); + return vlink; + } + vlink = vlink->next; + } + return NULL; +} + +/* + * find unsent VerseLink "pointing at this VerseNode" + */ +VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode) +{ + struct VNode *tmp; + struct VLink *vlink; + + tmp = session->nodes.lb.first; + + while(tmp) { + if(tmp->type==V_NT_OBJECT) { + vlink = ((VObjectData*)tmp->data)->queue.first; + while(vlink) { + if(vlink->target == vnode) + return vlink; + vlink = vlink->next; + } + } + tmp = tmp->next; + } + return NULL; +} + +/* + * send object position to verse server + */ +void send_verse_object_position(VNode *vnode) +{ + float tmp; + + ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY; + + /* we have to do rotation around x axis (+pi/2) to be + compatible with other verse applications */ + tmp = -((VObjectData*)vnode->data)->pos[1]; + ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2]; + ((VObjectData*)vnode->data)->pos[2] = tmp; + + verse_send_o_transform_pos_real32( + vnode->id, /* node id */ + 0, /* time_s ... no interpolation */ + 0, /* time_f ... no interpolation */ + ((VObjectData*)vnode->data)->pos, + NULL, /* speed ... no interpolation */ + NULL, /* accelerate ... no interpolation */ + NULL, /* drag normal ... no interpolation */ + 0.0); /* drag ... no interpolation */ +} + +/* + * send object rotation to verse server + */ +void send_verse_object_rotation(VNode *vnode) +{ + VNQuat32 quat; + float q[4] = {cos(-M_PI/4), -sin(-M_PI/4), 0, 0}, v[4], tmp[4]; + + /* inverse transformation to transformation in function cb_o_transform_rot_real32 */ + mul_qt_qtqt(v, ((VObjectData*)vnode->data)->quat, q); + q[1]= sin(-M_PI/4); + mul_qt_qtqt(tmp, q, v); + + quat.x = tmp[1]; + quat.y = tmp[2]; + quat.z = tmp[3]; + quat.w = tmp[0]; + + ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY; + + verse_send_o_transform_rot_real32( + vnode->id, /* node id */ + 0, /* time_s ... no interpolation */ + 0, /* time_f ... no interpolation */ + &quat, + NULL, /* speed ... no interpolation */ + NULL, /* accelerate ... no interpolation */ + NULL, /* drag normal ... no interpolation */ + 0.0); /* drag ... no interpolation */ +} + +/* + * send object rotation to verse server + */ +void send_verse_object_scale(VNode *vnode) +{ + float tmp; + + ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY; + + /* we have to do rotation around x axis (+pi/2) to be + compatible with other verse applications */ + tmp = ((VObjectData*)vnode->data)->scale[1]; + ((VObjectData*)vnode->data)->scale[1] = ((VObjectData*)vnode->data)->scale[2]; + ((VObjectData*)vnode->data)->scale[2] = tmp; + + verse_send_o_transform_scale_real32( + vnode->id, + ((VObjectData*)vnode->data)->scale[0], + ((VObjectData*)vnode->data)->scale[1], + ((VObjectData*)vnode->data)->scale[2]); +} + +/* + * send VerseLink to verse server + */ +void send_verse_link(VLink *vlink) +{ + verse_session_set(vlink->session->vsession); + + verse_send_o_link_set( + vlink->source->id, + vlink->id, + vlink->target->id, + vlink->label, + vlink->target_id); +} + +/* + * set up pointer at VerseLink of target node (geometry node, material node, etc.) + */ +static void set_target_node_link_pointer(VNode *vnode, VLink *vlink) +{ + switch (vnode->type) { + case V_NT_GEOMETRY: + ((VGeomData*)vnode->data)->vlink = vlink; + break; + default: + break; + } +} + +/* + * free VerseLink and it's label + */ +static void free_verse_link_data(VLink *vlink) +{ + MEM_freeN(vlink->label); +} + +/* + * create new VerseLink + */ +VLink *create_verse_link( + VerseSession *session, + VNode *source, + VNode *target, + uint16 link_id, + uint32 target_id, + const char *label) +{ + struct VLink *vlink; + + vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink"); + vlink->session = session; + vlink->source = source; + vlink->target = target; + vlink->id = link_id; + vlink->target_id = target_id; + + set_target_node_link_pointer(target, vlink); + + vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label"); + vlink->label[0] = '\0'; + strcat(vlink->label, label); + + vlink->flag = 0; + + vlink->post_link_set = post_link_set; + vlink->post_link_destroy = post_link_destroy; + + return vlink; +} + +/* + * free ObjectData (links, links in queue and lables of links) + */ +void free_object_data(VNode *vnode) +{ + struct VerseSession *session = vnode->session; + struct VObjectData *obj = (VObjectData*)vnode->data; + struct VLink *vlink; + struct VMethodGroup *vmg; + + if(!obj) return; + + /* free all labels of links in dlist */ + vlink = obj->links.lb.first; + while(vlink){ + free_verse_link_data(vlink); + vlink = vlink->next; + } + + /* free all labels of links waiting in queue */ + vlink = obj->queue.first; + while(vlink){ + free_verse_link_data(vlink); + vlink = vlink->next; + } + /* free dynamic list and sendig queue of links */ + BLI_dlist_destroy(&(obj->links)); + BLI_freelistN(&(obj->queue)); + + /* free method groups and their methods */ + for(vmg = vnode->methodgroups.first; vmg; vmg= vmg->next) { + free_verse_methodgroup(vmg); + } + BLI_freelistN(&(vnode->methodgroups)); + + /* free constraint between VerseNode and Object */ + obj->post_object_free_constraint(vnode); + + /* unsubscribe from receiving changes of transformation matrix */ + if(session->flag & VERSE_CONNECTED) + verse_send_o_transform_unsubscribe(vnode->id, 0); +} + +/* + * create new object data + */ +VObjectData *create_object_data(void) +{ + VObjectData *obj; + + obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData"); + obj->object = NULL; + BLI_dlist_init(&(obj->links)); + obj->queue.first = obj->queue.last = NULL; + obj->flag = 0; + + /* transformation matrix */ + obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0; + obj->quat[0] = obj->quat[1] = obj->quat[2] = 0.0; obj->quat[3] = 1; + obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0; + + /* transformation flags */ + obj->flag |= POS_SEND_READY; + obj->flag |= ROT_SEND_READY; + obj->flag |= SCALE_SEND_READY; + + /* set up pointers at post callback functions */ +/* obj->post_transform = post_transform;*/ + obj->post_transform_pos = post_transform_pos; + obj->post_transform_rot = post_transform_rot; + obj->post_transform_scale = post_transform_scale; + obj->post_object_free_constraint = post_object_free_constraint; + + return obj; +} + +/* + * callback function: + */ +static void cb_o_transform_pos_real32( + void *user_data, + VNodeID node_id, + uint32 time_s, + uint32 time_f, + const real32 *pos, + const real32 *speed, + const real32 *accelerate, + const real32 *drag_normal, + real32 drag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + float vec[3], dt, tmp; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= POS_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY; + return; + } + + dt = time_s + time_f/(0xffff); + + if(pos) { + vec[0] = pos[0]; + vec[1] = pos[1]; + vec[2] = pos[2]; + } + else { + vec[0] = 0.0f; + vec[1] = 0.0f; + vec[2] = 0.0f; + } + + if(speed) { + vec[0] += speed[0]*dt; + vec[1] += speed[1]*dt; + vec[2] += speed[2]*dt; + } + + if(accelerate) { + vec[0] += accelerate[0]*dt*dt/2; + vec[1] += accelerate[1]*dt*dt/2; + vec[2] += accelerate[2]*dt*dt/2; + } + + /* we have to do rotation around x axis (+pi/2) to be + compatible with other verse applications */ + tmp = vec[1]; + vec[1] = -vec[2]; + vec[2] = tmp; + + if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) || + (((VObjectData*)vnode->data)->pos[1] != vec[1]) || + (((VObjectData*)vnode->data)->pos[2] != vec[2])) + { + ((VObjectData*)vnode->data)->pos[0] = vec[0]; + ((VObjectData*)vnode->data)->pos[1] = vec[1]; + ((VObjectData*)vnode->data)->pos[2] = vec[2]; + + ((VObjectData*)vnode->data)->post_transform_pos(vnode); + } +} + +/* + * callback function: + */ +static void cb_o_transform_rot_real32( + void *user_data, + VNodeID node_id, + uint32 time_s, + uint32 time_f, + const VNQuat32 *quat, + const VNQuat32 *speed, + const VNQuat32 *accelerate, + const VNQuat32 *drag_normal, + real32 drag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + float temp[4]={0, 0, 0, 0}, v[4], dt; /* temporary quaternions */ + float q[4]={cos(M_PI/4), -sin(M_PI/4), 0, 0}; /* conjugate quaternion (represents rotation + around x-axis +90 degrees) */ + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY; + return; + } + + dt = time_s + time_f/(0xffff); + + if(quat) { + temp[1] = quat->x; + temp[2] = quat->y; + temp[3] = quat->z; + temp[0] = quat->w; + } + + if(speed) { + temp[1] += speed->x*dt; + temp[2] += speed->y*dt; + temp[3] += speed->z*dt; + temp[0] += speed->w*dt; + } + + if(accelerate) { + temp[1] += accelerate->x*dt*dt/2; + temp[2] += accelerate->y*dt*dt/2; + temp[3] += accelerate->z*dt*dt/2; + temp[0] += accelerate->w*dt*dt/2; + } + + /* following matematical operation transform rotation: + * + * v' = quaternion * v * conjugate_quaternion + * + *, where v is original representation of rotation */ + + mul_qt_qtqt(v, temp, q); + q[1]= sin(M_PI/4); /* normal quaternion */ + mul_qt_qtqt(temp, q, v); + + if( (((VObjectData*)vnode->data)->quat[0] != temp[0]) || + (((VObjectData*)vnode->data)->quat[1] != temp[1]) || + (((VObjectData*)vnode->data)->quat[2] != temp[2]) || + (((VObjectData*)vnode->data)->quat[3] != temp[3])) + { + QUATCOPY(((VObjectData*)vnode->data)->quat, temp); + + ((VObjectData*)vnode->data)->post_transform_rot(vnode); + } +} + +/* + * callback function: + */ +static void cb_o_transform_scale_real32( + void *user_data, + VNodeID node_id, + real32 scale_x, + real32 scale_y, + real32 scale_z) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + real32 tmp; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY; + return; + } + + /* flip axis (verse spec) */ + tmp = scale_y; + scale_y = scale_z; + scale_z = tmp; + + /* z and y axis are flipped here too */ + if( (((VObjectData*)vnode->data)->scale[0] != scale_x) || + (((VObjectData*)vnode->data)->scale[1] != scale_y) || + (((VObjectData*)vnode->data)->scale[2] != scale_z)) + { + ((VObjectData*)vnode->data)->scale[0] = scale_x; + ((VObjectData*)vnode->data)->scale[1] = scale_y; + ((VObjectData*)vnode->data)->scale[2] = scale_z; + + ((VObjectData*)vnode->data)->post_transform_scale(vnode); + } +} + +/* + * callback function: link between object node and some other node was created + */ +static void cb_o_link_set( + void *user_data, + VNodeID node_id, + uint16 link_id, + VNodeID link, + const char *label, + uint32 target_id) +{ + struct VLink *vlink; + struct VNode *source; + struct VNode *target; + + struct VerseSession *session = (VerseSession*)current_verse_session(); + + if(!session) return; + + source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link); + + if(!(source && target)) return; + + vlink = ((VObjectData*)source->data)->queue.first; + + if(vlink && (vlink->source==source) && (vlink->target==target)) { + /* remove VerseLink from sending queue */ + BLI_remlink(&(((VObjectData*)source->data)->queue), vlink); + /* add VerseLink to dynamic list of VerseLinks */ + BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); + /* send next link from sending queue */ + if(((VObjectData*)source->data)->queue.first) + send_verse_link(((VObjectData*)source->data)->queue.first); + /* set up VerseLink variables */ + vlink->flag = 0; + vlink->id = link_id; + vlink->target_id = target_id; + } + else { + /* create new VerseLink */ + vlink = create_verse_link(session, source, target, link_id, target_id, label); + /* add VerseLink to dynamic list of VerseLinks */ + BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); + } + + target->counter++; + + vlink->post_link_set(vlink); +} + +/* + * callback function: destroy link between two VerseNodes + */ +static void cb_o_link_destroy( + void *user_data, + VNodeID node_id, + uint16 link_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLink *vlink; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id); + + if(vlink) { + vlink->target->counter--; + free_verse_link_data(vlink); + BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id); + } + + vlink->post_link_destroy(vlink); +} + +void set_object_callbacks(void) +{ + /* position of object was changed */ + verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL); + /* rotation of object was changed */ + verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL); + /* size of object was changed */ + verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL); + /* new link between nodes was created */ + verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL); + /* link between nodes was destroyed */ + verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL); +} + +#endif diff --git a/source/blender/blenkernel/intern/verse_session.c b/source/blender/blenkernel/intern/verse_session.c new file mode 100644 index 00000000000..64d6b9885fe --- /dev/null +++ b/source/blender/blenkernel/intern/verse_session.c @@ -0,0 +1,480 @@ +/** + * $Id: verse_session.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" /* temp */ +#include "DNA_listBase.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" + +#include "BIF_screen.h" +#include "BIF_verse.h" + +#include "BKE_global.h" +#include "BKE_verse.h" + +struct ListBase session_list={NULL, NULL}; +struct ListBase server_list={NULL, NULL}; + +static int cb_ping_registered = 0; + +/* list of static function prototypes */ +static void cb_connect_terminate(const char *address, const char *bye); +static void cb_connect_accept(void *user_data, uint32 avatar, void *address, void *connection, const uint8 *host_id); +static void set_all_callbacks(void); +static void free_verse_session_data(struct VerseSession *session); +static void add_verse_server(VMSServer *server); +static void check_connection_state(struct VerseServer *server); + +static void check_connection_state(struct VerseServer *server) +{ + struct VerseSession *session; + session = session_list.first; + while(session) { + if(strcmp(server->ip,session->address)==0) { + server->flag = session->flag; + return; + } + session = session->next; + } +} +/* + * add verse server to server_list. Prevents duplicate + * entries + */ +static void add_verse_server(VMSServer *server) +{ + struct VerseServer *iter, *niter; + VerseServer *newserver; + const char *name = verse_ms_field_value(server, "DE"); + iter = server_list.first; + + while(iter) { + niter = iter->next; + if(strcmp(iter->ip, server->ip)==0) { + return; + } + iter = niter; + } + + newserver = (VerseServer *)MEM_mallocN(sizeof(VerseServer), "VerseServer"); + newserver->ip = (char *)MEM_mallocN(sizeof(char)*(strlen(server->ip)+1), "VerseServer ip"); + strcpy(newserver->ip, server->ip); + + if(name) { + newserver->name = (char *)MEM_mallocN(sizeof(char)*(strlen(name)+strlen(newserver->ip)+4), "VerseServer name"); + strcpy(newserver->name, name); + strcat(newserver->name, " ("); + strcat(newserver->name, newserver->ip); + strcat(newserver->name, ")"); + } + + newserver->flag = 0; + check_connection_state(newserver); + + printf("Adding new verse server: %s at %s\n", newserver->name, newserver->ip); + + BLI_addtail(&server_list, newserver); + post_server_add(); +} + +/* + * callback function for ping + */ +static void cb_ping(void *user, const char *address, const char *message) +{ + VMSServer **servers = verse_ms_list_parse(message); + if(servers != NULL) + { + int i; + + for(i = 0; servers[i] != NULL; i++) + add_verse_server(servers[i]); + + free(servers); + } +} + +/* + * callback function for connection terminated + */ +static void cb_connect_terminate(const char *address, const char *bye) +{ + VerseSession *session = (VerseSession*)current_verse_session(); + + if(!session) return; + + /* remove session from list of session */ + BLI_remlink(&session_list, session); + /* do post connect operations */ + session->post_connect_terminated(session); + /* free session data */ + free_verse_session_data(session); + /* free session */ + MEM_freeN(session); +} + +/* + * callback function for accepted connection to verse server + */ +static void cb_connect_accept( + void *user_data, + uint32 avatar, + void *address, + void *connection, + const uint8 *host_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VerseServer *server = server_list.first; + uint32 i, mask=0; + + if(!session) return; + + session->flag |= VERSE_CONNECTED; + session->flag &= ~VERSE_CONNECTING; + + while(server) { + if(strcmp(session->address, server->ip)==0) { + server->flag |= VERSE_CONNECTED; + server->flag &= ~VERSE_CONNECTING; + server->session = session; + break; + } + server = server->next; + } + + printf("\tBlender is connected to verse server: %s\n", (char*)address); + printf("\tVerseSession->counter: %d\n", session->counter); + + session->avatar = avatar; + + session->post_connect_accept(session); + + for(i = 0; i < V_NT_NUM_TYPES; i++) + mask = mask | (1 << i); + verse_send_node_index_subscribe(mask); + verse_send_node_subscribe(session->avatar); /* subscribe to avatar node, as well */ + + /* create our own method group and method */ + /*verse_send_o_method_group_create(session->avatar, ~0, "tawk-client");*/ +} + +/* + * set up all callbacks for sessions + */ +void set_verse_session_callbacks(void) +{ + /* connection */ + verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL); + /* connection was terminated */ + verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL); + +} + +/* + * set all callbacks used in Blender + */ +static void set_all_callbacks(void) +{ + /* set up all callbacks for sessions */ + set_verse_session_callbacks(); + + /* set up callbacks for nodes */ + set_node_callbacks(); + + /* set up all callbacks for object nodes */ + set_object_callbacks(); + + /* set up all callbacks for geometry nodes */ + set_geometry_callbacks(); + + /* set up all callbacks for bitmap nodes */ + set_bitmap_callbacks(); + + /* set up all callbacks for method groups and methods */ + set_method_callbacks(); +} + +/* + * this function sends and receive all packets for all sessions + */ +void b_verse_update(void) +{ + VerseSession *session, *next_session; + + session = session_list.first; + while(session){ + next_session = session->next; + verse_session_set(session->vsession); + if((session->flag & VERSE_CONNECTED) || (session->flag & VERSE_CONNECTING)) { + verse_callback_update(10); + session->post_connect_update(session); + } + session = next_session; + } + if(cb_ping_registered>0) { + verse_callback_update(10); + } +} + +/* + * returns VerseSession coresponding to vsession pointer + */ +VerseSession *versesession_from_vsession(VSession *vsession) +{ + struct VerseSession *session; + + session = session_list.first; + + while(session) { + if(session->vsession==vsession) return session; + session = session->next; + } + + return session; +} + +/* + * returns pointer at current VerseSession + */ +VerseSession *current_verse_session(void) +{ + struct VerseSession *session; + VSession vsession = verse_session_get(); + + session = session_list.first; + + while(session){ + if(session->vsession == vsession) + return session; + session = session->next; + } + + printf("error: non-existing SESSION occured!\n"); + return NULL; +} + +/* + * free VerseSession + */ +static void free_verse_session_data(VerseSession *session) +{ + struct VNode *vnode; + + /* free data of all nodes */ + vnode = session->nodes.lb.first; + while(vnode){ + free_verse_node_data(vnode); + vnode = vnode->next; + } + + /* free data of nodes waiting in queue */ + vnode = session->queue.first; + while(vnode){ + free_verse_node_data(vnode); + vnode = vnode->next; + } + + /* free all VerseNodes */ + BLI_dlist_destroy(&(session->nodes)); + /* free all VerseNodes waiting in queque */ + BLI_freelistN(&(session->queue)); + + /* free name of verse host for this session */ + MEM_freeN(session->address); +} + +/* + * free VerseSession + */ +void free_verse_session(VerseSession *session) +{ + /* remove session from session list*/ + BLI_remlink(&session_list, session); + /* do post terminated operations */ + session->post_connect_terminated(session); + /* free session data (nodes, layers) */ + free_verse_session_data(session); + /* free session */ + MEM_freeN(session); +} + +/* + * create new verse session and return coresponding data structure + */ +VerseSession *create_verse_session( + const char *name, + const char *pass, + const char *address, + uint8 *expected_key) +{ + struct VerseSession *session; + VSession *vsession; + + vsession = verse_send_connect(name, pass, address, expected_key); + + if(!vsession) return NULL; + + session = (VerseSession*)MEM_mallocN(sizeof(VerseSession), "VerseSession"); + + session->flag = VERSE_CONNECTING; + + session->vsession = vsession; + session->avatar = -1; + + session->address = (char*)MEM_mallocN(sizeof(char)*(strlen(address)+1),"session adress name"); + strcpy(session->address, address); + + session->connection = NULL; + session->host_id = NULL; + session->counter = 0; + + /* initialize dynamic list of nodes and node queue */ + BLI_dlist_init(&(session->nodes)); + session->queue.first = session->queue.last = NULL; + + /* set up all client dependent functions */ + session->post_connect_accept = post_connect_accept; + session->post_connect_terminated = post_connect_terminated; + session->post_connect_update = post_connect_update; + + post_server_add(); + + return session; +} + +/* + * end verse session and free all session data + */ +void end_verse_session(VerseSession *session) +{ + /* send terminate command to verse server */ + verse_send_connect_terminate(session->address, "blender: bye bye"); + /* update callbacks */ + verse_callback_update(1000); + /* send destroy session command to verse server */ + verse_session_destroy(session->vsession); + /* set up flag of verse session */ + session->flag &= ~VERSE_CONNECTED; + /* do post connect operations */ + session->post_connect_terminated(session); + /* free structure of verse session */ + free_verse_session(session); +} + +void free_all_servers(void) +{ + VerseServer *server, *nextserver; + + server = server_list.first; + + while(server) { + nextserver = server->next; + BLI_remlink(&server_list, server); + MEM_freeN(server->name); + MEM_freeN(server->ip); + MEM_freeN(server); + server = nextserver; + } + + BLI_freelistN(&server_list); +} + +/* + * end connection to all verse hosts (servers) ... free all VerseSessions + * free all VerseServers + */ +void end_all_verse_sessions(void) +{ + VerseSession *session,*nextsession; + + session = session_list.first; + + while(session) { + nextsession= session->next; + end_verse_session(session); + /* end next session */ + session = nextsession; + } + + BLI_freelistN(&session_list); + + free_all_servers(); +} + +/* + * do a get from ms + */ +void b_verse_ms_get(void) +{ + if(cb_ping_registered==0) { + /* handle ping messages (for master server) */ + verse_callback_set(verse_send_ping, cb_ping, NULL); + add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1); + cb_ping_registered++; + } + free_all_servers(); + + verse_ms_get_send(U.versemaster, VERSE_MS_FIELD_DESCRIPTION, NULL); + verse_callback_update(10); +} + +/* + * connect to verse host, set up all callbacks, create session + */ +void b_verse_connect(char *address) +{ + VerseSession *session = NULL; + + /* if no session was created before, then set up all callbacks */ + if((session_list.first==NULL) && (session_list.last==NULL)) + set_all_callbacks(); + + /* create new session */ + if(address) + session = create_verse_session("Blender", "pass", address, NULL); + + if(session) { + /* add new session to the list of sessions */ + BLI_addtail(&session_list, session); + + /* add verse handler if this is first session */ + if(session_list.first == session_list.last) + add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1); + + } +} + +#endif diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index dae9c4f6e41..bd760646053 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -1,5 +1,5 @@ /* - * $Id$ + * $Id: nla_private.h 21537 2009-07-11 22:22:53Z gsrb3d $ * * ***** BEGIN GPL LICENSE BLOCK ***** * |