diff options
Diffstat (limited to 'source/blender/blenkernel')
49 files changed, 6611 insertions, 1997 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index a887412bbf4..69abfe3c34d 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -28,21 +28,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" @@ -53,20 +81,26 @@ 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. +*/ typedef struct DMGridData { float co[3]; @@ -80,15 +114,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, numTessFaceData, 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; @@ -96,23 +130,29 @@ struct DerivedMesh { DerivedMeshType type; float auto_bump_scale; + /* calculate vert and face normals */ + void (*calcNormals)(DerivedMesh *dm); + + /* recalculates mesh tesselation */ + void (*recalcTesselation)(DerivedMesh *dm); + /* Misc. Queries */ /* 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 (*getNumLoops)(DerivedMesh *dm); + int (*getNumPolys)(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, @@ -121,21 +161,27 @@ struct DerivedMesh { */ struct MVert *(*getVertArray)(DerivedMesh *dm); struct MEdge *(*getEdgeArray)(DerivedMesh *dm); - struct MFace *(*getFaceArray)(DerivedMesh *dm); + struct MFace *(*getTessFaceArray)(DerivedMesh *dm); + struct MLoop *(*getLoopArray)(DerivedMesh *dm); + struct MPoly *(*getPolyArray)(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); + void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *loop_r); + void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *poly_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); + struct MLoop *(*dupLoopArray)(DerivedMesh *dm); + struct MPoly *(*dupPolyArray)(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 @@ -143,7 +189,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 @@ -151,8 +197,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 *(*getPolyDataLayout)(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); @@ -255,8 +314,8 @@ struct DerivedMesh { * o Drawing options too complicated to enumerate, look at code. */ void (*drawFacesTex)(DerivedMesh *dm, - int (*setDrawOptions)(struct MTFace *tface, - int has_mcol, int matnr), + int (*setDrawOptions)(struct MTFace *tface, + int has_vcol, int matnr), int (*compareDrawOptions)(void *userData, int cur_index, int next_index), @@ -357,15 +416,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 @@ -374,7 +434,7 @@ int DM_release(DerivedMesh *dm); /* utility function to convert a DerivedMesh to a Mesh */ -void DM_to_mesh(DerivedMesh *dm, struct Mesh *me); +void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob); /* utility function to convert a DerivedMesh to a shape key block */ @@ -392,11 +452,15 @@ void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask); * freed, see BKE_customdata.h for the different options */ void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype, - void *layer); + void *layer); void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype, - void *layer); -void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype, - void *layer); + void *layer); +void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype, + void *layer); +void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, + void *layer); +void DM_add_poly_layer(struct DerivedMesh *dm, int type, int alloctype, + void *layer); /* custom data access functions * return pointer to data from first layer which matches type @@ -405,7 +469,7 @@ void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype, */ void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type); void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type); -void *DM_get_face_data(struct DerivedMesh *dm, int index, int type); +void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type); /* custom data layer access functions * return pointer to first data layer which matches type (a flat array) @@ -414,7 +478,8 @@ 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_face_data_layer(struct DerivedMesh *dm, int type); +void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type); +void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type); /* custom data setting functions * copy supplied data into first layer of type using layer's copy function @@ -422,7 +487,7 @@ void *DM_get_face_data_layer(struct DerivedMesh *dm, int type); */ void DM_set_vert_data(struct DerivedMesh *dm, int index, int type, void *data); void DM_set_edge_data(struct DerivedMesh *dm, int index, int type, void *data); -void DM_set_face_data(struct DerivedMesh *dm, int index, int type, void *data); +void DM_set_tessface_data(struct DerivedMesh *dm, int index, int type, void *data); /* custom data copy functions * copy count elements from source_index in source to dest_index in dest @@ -432,7 +497,11 @@ 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_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, +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_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); /* custom data free functions @@ -441,7 +510,14 @@ 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_face_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_poly_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); + +void DM_ensure_tessface(DerivedMesh *dm); /* 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 @@ -472,12 +548,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_poly_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); @@ -493,11 +577,15 @@ DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob, DerivedMesh *mesh_get_derived_deform(struct Scene *scene, struct Object *ob, CustomDataMask dataMask); -DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob, struct ModifierData *md); +DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob, + struct ModifierData *md, int build_shapekey_layers); 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 */ @@ -516,20 +604,21 @@ 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, int build_shapekey_layers); /* 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, @@ -574,16 +663,6 @@ typedef struct DMVertexAttribs { int tottface, totmcol, tottang, totorco; } DMVertexAttribs; -/* should be local, bmesh replaces this */ -typedef struct { - DerivedMesh dm; - - struct EditMesh *em; - float (*vertexCos)[3]; - float (*vertexNos)[3]; - float (*faceNos)[3]; -} EditMeshDerivedMesh; - void DM_vertex_attributes_from_gpu(DerivedMesh *dm, struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 50fef032b75..48f1df2bd73 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -90,6 +90,7 @@ extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(struct bContext *C, int nr); extern const char *BKE_undo_get_name(int nr, int *active); +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 c8df6c4f455..85ecaf0bb27 100644 --- a/source/blender/blenkernel/BKE_bmesh.h +++ b/source/blender/blenkernel/BKE_bmesh.h @@ -51,6 +51,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 @@ -208,6 +209,10 @@ int BME_loop_reverse(struct BME_Mesh *bm, struct BME_Poly *f); #define BME_BEVEL_RUNNING (1<<9) #define BME_BEVEL_RES (1<<10) +#define BME_BEVEL_EVEN (1<<11) /* this is a new setting not related to old (trunk bmesh bevel code) but adding + * here because they are mixed - campbell */ +#define BME_BEVEL_DIST (1<<12) /* same as above */ + typedef struct BME_TransData { BME_Mesh *bm; /* the bmesh the vert belongs to */ BME_Vert *v; /* pointer to the vert this tdata applies to */ diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index c71c86e110d..db9f8e0527f 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -38,12 +38,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 @@ -51,8 +56,11 @@ struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces); data to not overwrite the original */ 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, int use_mdisps, int use_tessface); + +/* merge verts */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap); /* creates a CDDerivedMesh from the given curve object */ struct DerivedMesh *CDDM_from_curve(struct Object *ob); @@ -61,17 +69,27 @@ 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(struct Object *ob, struct DerivedMesh *dm, + struct BMEditMesh *existing, int do_tesselate); + + /* 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 @@ -82,19 +100,31 @@ void CDDM_apply_vert_normals(struct DerivedMesh *cddm, short (*vertNormals)[3]); /* recalculates vertex and face normals for a CDDerivedMesh */ +void CDDM_calc_normals_mapping(struct DerivedMesh *dm); void CDDM_calc_normals(struct DerivedMesh *dm); +void CDDM_calc_normals_tessface(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_tessface(struct DerivedMesh *dm); + +/* same as CDDM_calc_edges_tessface only makes edges from ngon faces instead of tesselation + faces*/ void CDDM_calc_edges(struct DerivedMesh *dm); +/* reconstitute face triangulation */ +void CDDM_recalc_tesselation(struct DerivedMesh *dm); +void CDDM_recalc_tesselation_ex(struct DerivedMesh *dm, const int do_face_nor_cpy); + /* lowers the number of vertices/edges/faces in a CDDerivedMesh * the layer data stays the same size */ void CDDM_lower_num_verts(struct DerivedMesh *dm, int numVerts); void CDDM_lower_num_edges(struct DerivedMesh *dm, int numEdges); -void CDDM_lower_num_faces(struct DerivedMesh *dm, int numFaces); +void CDDM_lower_num_polys(struct DerivedMesh *dm, int numPolys); +void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces); /* vertex/edge/face access functions * should always succeed if index is within bounds @@ -102,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 @@ -111,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_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 7ad25ac7e79..b69ad4d1b8b 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -40,11 +40,15 @@ extern "C" { #include "../blenloader/BLO_sys_types.h" /* XXX, should have a more generic include for this */ +struct BMesh; struct ID; struct CustomData; struct CustomDataLayer; typedef uint64_t 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; @@ -69,6 +73,25 @@ extern const CustomDataMask CD_MASK_FACECORNERS; #define CD_TYPE_AS_MASK(_type) (CustomDataMask)((CustomDataMask)1 << (CustomDataMask)(_type)) +/* 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. */ @@ -83,6 +106,12 @@ void CustomData_update_typemap(struct CustomData *data); 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) */ @@ -308,8 +337,9 @@ 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); + 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_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); /* External file storage */ diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index c055bb2004b..529d0680cf9 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -48,8 +48,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 30a4b154e31..b1cb62d4d5a 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -36,7 +36,8 @@ struct BoundBox; struct DispList; struct ListBase; -struct EditMesh; +struct BMEditMesh; +struct BMesh; struct Mesh; struct MPoly; struct MLoop; @@ -60,19 +61,50 @@ struct UvElement; extern "C" { #endif -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, + const int do_face_normals); /* for forwards compat only quad->tri polys to mface, skip ngons. */ int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, int totface, int totloop, int totpoly); +/*calculates a face normal.*/ +void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float no[3]); + +void mesh_calc_poly_normal_coords(struct MPoly *mpoly, struct MLoop *loopstart, + const float (*vertex_coords)[3], float no[3]); + +void mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float cent[3]); + +float mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float polynormal[3]); + 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); +void mesh_update_customdata_pointers(struct Mesh *me, const short do_ensure_tess_cd); + void make_local_mesh(struct Mesh *me); void boundbox_mesh(struct Mesh *me, float *loc, float *size); void tex_space_mesh(struct Mesh *me); @@ -82,17 +114,26 @@ int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, struct Mesh *get_mesh(struct Object *ob); void set_mesh(struct Object *ob, struct Mesh *me); void mball_to_mesh(struct ListBase *lb, struct Mesh *me); -int nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *_totvert, - struct MEdge **alledge, int *_totedge, struct MFace **allface, int *_totface); -int nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase, - struct MVert **allvert, int *_totvert, struct MEdge **alledge, int *_totedge, - struct MFace **allface, int *_totface); +int nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *totvert, + struct MEdge **alledge, int *totedge, struct MFace **allface, struct MLoop **allloop, struct MPoly **allpoly, + int *totface, int *totloop, int *totpoly); +int nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert, + struct MEdge **alledge, int *_totedge, struct MFace **allface, struct MLoop **allloop, struct MPoly **allpoly, + int *_totface, int *_totloop, int *_totpoly); void nurbs_to_mesh(struct Object *ob); void mesh_to_curve(struct Scene *scene, struct Object *ob); void free_dverts(struct MDeformVert *dvert, int totvert); void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */ void mesh_delete_material_index(struct Mesh *me, short index); void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth); +void convert_mfaces_to_mpolys(struct Mesh *mesh); +void mesh_calc_normals_tessface(struct MVert *mverts, int numVerts,struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]); + +/*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.*/ +const 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); @@ -106,7 +147,21 @@ void mesh_strip_loose_edges(struct Mesh *me); /* Calculate vertex and face normals, face normals are returned in *faceNors_r if non-NULL * and vertex normals are stored in actual mverts. */ -void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]); +void mesh_calc_normals_mapping( + struct MVert *mverts, int numVerts, + struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3], + struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]); + /* extended version of 'mesh_calc_normals' with option not to calc vertex normals */ +void mesh_calc_normals_mapping_ex( + struct MVert *mverts, int numVerts, + struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3], + struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3], + const short only_face_normals); + +void mesh_calc_normals( + struct MVert *mverts, int numVerts, + struct MLoop *mloop, struct MPoly *mpolys, + int numLoops, int numPolys, float (*polyNors_r)[3]); /* Return a newly MEM_malloc'd array of all the mesh vertex locations * (_numVerts_r_ may be NULL) */ @@ -146,7 +201,7 @@ typedef struct UvElement { /* Next UvElement corresponding to same vertex */ struct UvElement *next; /* Face the element belongs to */ - struct EditFace *face; + struct BMFace *face; /* Index in the editFace of the uv */ unsigned char tfindex; /* Whether this element is the first of coincident elements */ @@ -161,8 +216,7 @@ typedef struct UvElement { * to make that many islands, he can bite me :p */ #define INVALID_ISLAND 0xFFFF - -UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit); +UvVertMap *make_uv_vert_map(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, int selected, float *limit); UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v); void free_uv_vert_map(UvVertMap *vmap); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index f72bc5b93ec..947e630273e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -45,6 +45,7 @@ struct ListBase; struct LinkNode; struct bArmature; struct ModifierData; +struct BMEditMesh; typedef enum { /* Should not be used, only for None modifier type */ @@ -154,13 +155,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 *********************/ @@ -198,7 +199,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_multires.h b/source/blender/blenkernel/BKE_multires.h index 4f1262cd523..ce6e12345e8 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -71,6 +71,14 @@ int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresMo void multires_stitch_grids(struct Object *); +/*switch mdisp data in dm between tangent and object space*/ +enum { + MULTIRES_SPACE_TANGENT, + MULTIRES_SPACE_OBJECT, + MULTIRES_SPACE_ABSOLUTE, +}; +void multires_set_space(struct DerivedMesh *dm, struct Object *ob, int from, int to); + /* Related to the old multires */ void multires_free(struct Multires *mr); void multires_load_old(struct Object *ob, struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index dcbd045f62d..5c878102bc2 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -46,6 +46,10 @@ struct _CCGEdge; struct _CCGFace; struct _CCGSubsurf; struct _CCGVert; +struct EdgeHash; +struct PBVH; +struct DMGridData; +struct DMGridAdjacency; /**************************** External *****************************/ @@ -74,6 +78,8 @@ typedef struct CCGDerivedMesh { short *edgeFlags; char *faceFlags; + int *reverseFaceMap; + struct PBVH *pbvh; struct ListBase *fmap; struct IndexNode *fmap_mem; @@ -95,6 +101,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..67afb86fde1 --- /dev/null +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -0,0 +1,75 @@ +#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*/ + short selectmode; + short 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; /* -1 is invalid */ + int mirr_free_arrays; +} BMEditMesh; + +/* undo triggers editmesh tessface update, this is odd but works OK. + * BMESH_TODO, look into having the update elsewhere. */ +#define BMESH_EM_UNDO_RECALC_TESSFACE_WORKAROUND + +void BMEdit_RecalcTesselation(BMEditMesh *tm); +BMEditMesh *BMEdit_Create(BMesh *bm, int do_tesselate); +BMEditMesh *BMEdit_Copy(BMEditMesh *tm); +void BMEdit_Free(BMEditMesh *em); +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em); + +#endif /* _BKE_TESSMESH_H */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 42e6f1d8fb2..dc93885c05c 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 ../render/extern/include @@ -114,6 +115,7 @@ set(SRC intern/mesh.c intern/mesh_validate.c intern/modifier.c + intern/modifiers_bmesh.c intern/movieclip.c intern/multires.c intern/nla.c @@ -227,6 +229,7 @@ set(SRC BKE_speaker.h BKE_subsurf.h BKE_suggestions.h + BKE_tessmesh.h BKE_text.h BKE_texture.h BKE_tracking.h diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 62a8aa8362f..d949f0c73db 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -12,6 +12,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 bb909dcbbdd..af0e5c93aba 100644 --- a/source/blender/blenkernel/intern/BME_Customdata.c +++ b/source/blender/blenkernel/intern/BME_Customdata.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_customdata.c jan 2007 * * Custom Data functions for Bmesh @@ -83,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, FALSE, FALSE); + data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, TRUE); /*initialize layer data*/ for(i=0; i < BME_CD_NUMTYPES; i++){ if(init->layout[i]){ @@ -196,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 ce1da6132cd..65a8ee8e0bb 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_mesh.c jan 2007 * * BMesh mesh level functions. @@ -267,7 +268,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]); @@ -462,7 +463,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]); @@ -474,10 +475,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"); @@ -574,7 +575,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); @@ -617,7 +619,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){ @@ -646,3 +648,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 25970dd8d91..215493fb6cf 100644 --- a/source/blender/blenkernel/intern/BME_eulers.c +++ b/source/blender/blenkernel/intern/BME_eulers.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_eulers.c jan 2007 * * BMesh Euler construction API. @@ -131,13 +132,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(); } @@ -205,7 +206,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; } @@ -275,8 +276,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*/ @@ -300,7 +301,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*/ @@ -328,7 +329,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; @@ -351,7 +352,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); @@ -387,14 +388,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; @@ -454,24 +455,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); @@ -524,17 +525,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(); @@ -543,11 +544,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(); @@ -556,7 +557,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(); } } @@ -601,7 +602,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; @@ -635,7 +636,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*/ @@ -645,7 +646,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; @@ -693,7 +694,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){ @@ -706,9 +707,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*/ @@ -723,10 +724,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; @@ -734,11 +735,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); @@ -749,7 +750,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; @@ -758,22 +759,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*/ @@ -903,8 +904,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; @@ -943,19 +944,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.*/ @@ -971,3 +972,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 cda66de6f22..dcca2da5414 100644 --- a/source/blender/blenkernel/intern/BME_mesh.c +++ b/source/blender/blenkernel/intern/BME_mesh.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_mesh.c jan 2007 * * BMesh mesh level functions. @@ -55,10 +56,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], FALSE, FALSE); - bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], FALSE, FALSE); - bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], FALSE, FALSE); - bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], FALSE, FALSE); + bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], TRUE, FALSE); + bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], TRUE, FALSE); + bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], TRUE, FALSE); + bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], TRUE, FALSE); return bm; } /* @@ -82,7 +83,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?*/ @@ -196,9 +197,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); } } @@ -210,17 +211,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); } @@ -242,7 +243,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; } @@ -253,11 +254,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++; } @@ -265,8 +266,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); } } @@ -283,3 +284,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 6d8a8339e46..789812a99c8 100644 --- a/source/blender/blenkernel/intern/BME_structure.c +++ b/source/blender/blenkernel/intern/BME_structure.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_structure.c jan 2007 * * Low level routines for manipulating the BMesh structure. @@ -30,7 +31,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ - +#if 0 /** \file blender/blenkernel/intern/BME_structure.c * \ingroup bke */ @@ -90,7 +91,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; @@ -118,7 +119,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; @@ -243,7 +244,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 @@ -259,7 +260,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 @@ -447,15 +448,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; @@ -478,18 +479,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; } /** @@ -542,12 +543,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++; } @@ -565,11 +566,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); } @@ -579,12 +580,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) @@ -592,15 +593,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) @@ -609,8 +610,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; @@ -620,9 +621,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 44258f92024..32e608623d5 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -1,4 +1,5 @@ -/* +#if 0 +/** * BME_tools.c jan 2007 * * Functions for changing the topology of a mesh. @@ -130,20 +131,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; } @@ -152,28 +153,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; } } @@ -190,8 +191,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); } @@ -243,8 +244,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; @@ -261,8 +262,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); } @@ -299,8 +300,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; @@ -310,8 +311,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); } @@ -419,12 +420,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; */ /* UNUSED */ - 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; @@ -605,8 +606,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); @@ -621,7 +622,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; @@ -646,7 +647,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; @@ -666,14 +667,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); } @@ -684,7 +685,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; @@ -703,13 +704,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); } @@ -718,7 +719,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){ @@ -885,8 +886,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; @@ -925,7 +926,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; } @@ -970,11 +971,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 = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL); } @@ -1041,13 +1042,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) { @@ -1111,7 +1112,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; } @@ -1162,26 +1163,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) { @@ -1207,7 +1208,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); @@ -1221,7 +1222,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"); } @@ -1232,10 +1233,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 */ @@ -1341,3 +1342,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 27aeeb95903..686d6a4018c 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -31,7 +31,7 @@ #include <string.h> - +#include "limits.h" #include "MEM_guardedalloc.h" @@ -46,6 +46,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" #include "BLI_linklist.h" @@ -60,6 +61,9 @@ #include "BKE_texture.h" #include "BKE_multires.h" #include "BKE_armature.h" +#include "BKE_particle.h" +#include "BKE_tessmesh.h" +#include "BKE_bvhutils.h" #include "BKE_deform.h" #ifdef WITH_GAMEENGINE @@ -78,6 +82,9 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ +static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob); +static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid); + /////////////////////////////////// /////////////////////////////////// @@ -109,20 +116,48 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm) return medge; } -static MFace *dm_getFaceArray(DerivedMesh *dm) +static MFace *dm_getTessFaceArray(DerivedMesh *dm) { MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE); 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; } +static MLoop *dm_getLoopArray(DerivedMesh *dm) +{ + MLoop *mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + + if (!mloop) { + mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, + dm->getNumLoops(dm)); + CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY); + dm->copyLoopArray(dm, mloop); + } + + return mloop; +} + +static MPoly *dm_getPolyArray(DerivedMesh *dm) +{ + MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + + if (!mpoly) { + mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, + dm->getNumPolys(dm)); + CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY); + dm->copyPolyArray(dm, mpoly); + } + + return mpoly; +} + static MVert *dm_dupVertArray(DerivedMesh *dm) { MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm), @@ -145,41 +180,98 @@ 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; +} + +static MLoop *dm_dupLoopArray(DerivedMesh *dm) +{ + MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm), + "dm_dupLoopArray tmp"); + + if(tmp) dm->copyLoopArray(dm, tmp); + + return tmp; +} + +static MPoly *dm_dupPolyArray(DerivedMesh *dm) +{ + MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm), + "dm_dupPolyArray tmp"); + + if(tmp) dm->copyPolyArray(dm, tmp); return tmp; } +static CustomData *dm_getVertCData(DerivedMesh *dm) +{ + return &dm->vertData; +} + +static CustomData *dm_getEdgeCData(DerivedMesh *dm) +{ + return &dm->edgeData; +} + +static CustomData *dm_getTessFaceCData(DerivedMesh *dm) +{ + return &dm->faceData; +} + +static CustomData *dm_getLoopCData(DerivedMesh *dm) +{ + return &dm->loopData; +} + +static 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_getTessFaceArray; + dm->getLoopArray = dm_getLoopArray; + dm->getPolyArray = dm_getPolyArray; dm->dupVertArray = dm_dupVertArray; dm->dupEdgeArray = dm_dupEdgeArray; - dm->dupFaceArray = dm_dupFaceArray; + dm->dupTessFaceArray = dm_dupFaceArray; + dm->dupLoopArray = dm_dupLoopArray; + dm->dupPolyArray = dm_dupPolyArray; + + dm->getVertDataLayout = dm_getVertCData; + dm->getEdgeDataLayout = dm_getEdgeCData; + dm->getTessFaceDataLayout = dm_getTessFaceCData; + dm->getLoopDataLayout = dm_getLoopCData; + dm->getPolyDataLayout = dm_getPolyCData; dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; + dm->getTessFaceData = DM_get_tessface_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 numTessFaces, int numLoops, int numPolys) { dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; - dm->numFaceData = numFaces; + dm->numTessFaceData = numTessFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; DM_init_funcs(dm); @@ -188,19 +280,26 @@ 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 numTessFaces, + int numLoops, int numPolys) { CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH, CD_CALLOC, numVerts); CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH, CD_CALLOC, numEdges); CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH, - CD_CALLOC, numFaces); + CD_CALLOC, numTessFaces); + 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->numTessFaceData = numTessFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; DM_init_funcs(dm); @@ -214,63 +313,160 @@ int DM_release(DerivedMesh *dm) GPU_drawobject_free( dm ); CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); - CustomData_free(&dm->faceData, dm->numFaceData); + CustomData_free(&dm->faceData, dm->numTessFaceData); + CustomData_free(&dm->loopData, dm->numLoopData); + CustomData_free(&dm->polyData, dm->numPolyData); return 1; } else { 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->faceData, dm->numTessFaceData); + CustomData_free_temporary(&dm->loopData, dm->numLoopData); + CustomData_free_temporary(&dm->polyData, dm->numPolyData); return 0; } } -void DM_to_mesh(DerivedMesh *dm, Mesh *me) +void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) +{ + CustomData_free(&target->loopData, source->numLoopData); + CustomData_free(&target->polyData, source->numPolyData); + + CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numLoopData); + CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numPolyData); + + target->numLoopData = source->numLoopData; + target->numPolyData = source->numPolyData; + + if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { + MPoly *mpoly; + MLoop *mloop; + + mloop = source->dupLoopArray(source); + mpoly = source->dupPolyArray(source); + CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData); + CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData); + } +} + +/* note: until all modifiers can take MPoly's as input, + * use this at the start of modifiers */ +void DM_ensure_tessface(DerivedMesh *dm) +{ + const int numTessFaces = dm->getNumTessFaces(dm); + const int numPolys = dm->getNumPolys(dm); + + if ( (numTessFaces == 0) && (numPolys != 0)) { + dm->recalcTesselation(dm); + + if (dm->getNumTessFaces(dm) != 0) { + /* printf("info %s: polys -> ngons calculated\n", __func__); */ + } + else { + printf("warning %s: could not create tessfaces from %d polygons, dm->type=%d\n", + __func__, numPolys, dm->type); + } + } +} + +void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob) { /* dm might depend on me, so we need to do everything with a local copy */ Mesh tmp = *me; - int totvert, totedge, totface; - + int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; + int did_shapekeys=0; + 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); + totloop = tmp.totloop = dm->getNumLoops(dm); + totpoly = tmp.totpoly = dm->getNumPolys(dm); 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); + if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { + KeyBlock *kb; + int i=0; + + if (ob) { + for (kb=me->key->block.first; kb; kb=kb->next, i++) { + if (i == ob->shapenr-1) { + i = kb->uid; + break; + } + } + + if (!kb) { + printf("%s: error - could not find active shapekey %d!\n", + __func__, ob->shapenr-1); + + i = INT_MAX; + } + } else { + /*if no object, set to INT_MAX so we don't mess up any shapekey layers*/ + i = INT_MAX; + } + + shapekey_layers_to_keyblocks(dm, me, i); + did_shapekeys = 1; + } + /* not all DerivedMeshes store their verts/edges/faces in CustomData, so we set them here in case they are missing */ if(!CustomData_has_layer(&tmp.vdata, CD_MVERT)) CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert); 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); + if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { + tmp.mloop = dm->dupLoopArray(dm); + tmp.mpoly = dm->dupPolyArray(dm); + + CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); + CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); + } /* object had got displacement layer, should copy this layer to save sculpted data */ /* NOTE: maybe some other layers should be copied? nazgul */ - if(CustomData_has_layer(&me->fdata, CD_MDISPS)) { - if (totface == me->totface) { - MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface); + if(CustomData_has_layer(&me->ldata, CD_MDISPS)) { + if (totloop == me->totloop) { + MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); + CustomData_add_layer(&tmp.ldata, CD_MDISPS, CD_DUPLICATE, mdisps, totloop); } } - mesh_update_customdata_pointers(&tmp); + /* yes, must be before _and_ after tesselate */ + mesh_update_customdata_pointers(&tmp, TRUE); + + tmp.totface = mesh_recalcTesselation(&tmp.fdata, &tmp.ldata, &tmp.pdata, + tmp.mvert, + tmp.totface, tmp.totloop, tmp.totpoly, + TRUE); + + mesh_update_customdata_pointers(&tmp, TRUE); + CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); - - /* if the number of verts has changed, remove invalid data */ - if(tmp.totvert != me->totvert) { + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + + /* ok, this should now use new CD shapekey data, + which shouuld be fed through the modifier + stack*/ + if(tmp.totvert != me->totvert && !did_shapekeys && me->key) { + printf("YEEK! this should be recoded! Shape key loss!!!\n"); if(tmp.key) tmp.key->id.us--; tmp.key = NULL; } @@ -315,9 +511,19 @@ 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->numTessFaceData); +} + +void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer) { - CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData); + CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData); +} + +void DM_add_poly_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) @@ -330,7 +536,7 @@ void *DM_get_edge_data(DerivedMesh *dm, int index, int type) return CustomData_get(&dm->edgeData, index, type); } -void *DM_get_face_data(DerivedMesh *dm, int index, int type) +void *DM_get_tessface_data(DerivedMesh *dm, int index, int type) { return CustomData_get(&dm->faceData, index, type); } @@ -351,14 +557,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); + if (type == CD_MFACE) + return dm->getTessFaceArray(dm); return CustomData_get_layer(&dm->faceData, type); } +void *DM_get_poly_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); @@ -369,7 +580,7 @@ void DM_set_edge_data(DerivedMesh *dm, int index, int type, void *data) CustomData_set(&dm->edgeData, index, type, data); } -void DM_set_face_data(DerivedMesh *dm, int index, int type, void *data) +void DM_set_tessface_data(DerivedMesh *dm, int index, int type, void *data) { CustomData_set(&dm->faceData, index, type, data); } @@ -388,13 +599,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_poly_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); @@ -405,11 +630,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_poly_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) @@ -427,7 +662,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) @@ -436,13 +671,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_poly_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); @@ -458,7 +708,10 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) return dm; } -DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md) +/***/ + +DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, + ModifierData *md, int build_shapekey_layers) { Mesh *me = ob->data; ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -468,7 +721,11 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier if (!(md->mode&eModifierMode_Realtime)) return NULL; if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; - + + if (build_shapekey_layers && me->key && ob->shapenr <= BLI_countlist(&me->key->block)) { + key_to_mesh(BLI_findlink(&me->key->block, ob->shapenr-1), me); + } + if (mti->type==eModifierTypeType_OnlyDeform) { int numVerts; float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts); @@ -476,9 +733,16 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0); dm = mesh_create_derived(me, ob, deformedVerts); + if (build_shapekey_layers) + add_shapekey_layers(dm, me, ob); + MEM_freeN(deformedVerts); } else { DerivedMesh *tdm = mesh_create_derived(me, ob, NULL); + + if (build_shapekey_layers) + add_shapekey_layers(tdm, me, ob); + dm = mti->applyModifier(md, ob, tdm, 0, 0); if(tdm != dm) tdm->release(tdm); @@ -487,22 +751,22 @@ 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) { copy_v3_v3(orco+a, eve->co); } @@ -510,8 +774,7 @@ static float *get_editmesh_orco_verts(EditMesh *em) } /* 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; @@ -520,7 +783,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); } @@ -541,13 +804,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, FALSE, FALSE); else dm= CDDM_from_mesh(me, ob); orco= get_orco_coords_dm(ob, em, layer, &free); @@ -562,7 +825,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; @@ -775,19 +1039,35 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, { ColorBand *coba= stored_cb; /* warning, not a local var */ - MFace *mf = dm->getFaceArray(dm); - int numFaces = dm->getNumFaces(dm); - int numVerts = dm->getNumVerts(dm); unsigned char *wtcol_v; - unsigned char *wtcol_f = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); - int i; +#if 0 /* See coment below. */ + unsigned char *wtcol_f = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); +#endif + unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_WEIGHT_MLOOPCOL); +#if 0 /* See coment below. */ + MFace *mf = dm->getTessFaceArray(dm); +#endif + MLoop *mloop = dm->getLoopArray(dm), *ml; + MPoly *mp = dm->getPolyArray(dm); + int numFaces = dm->getNumTessFaces(dm); + int numVerts = dm->getNumVerts(dm); + int totloop; + int i, j; +#if 0 /* See comment below */ /* If no CD_WEIGHT_MCOL existed yet, add a new one! */ if (!wtcol_f) wtcol_f = CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces); if (wtcol_f) { unsigned char *wtcol_f_step = wtcol_f; +# else + /* XXX We have to create a CD_WEIGHT_MCOL, else it might sigsev (after a SubSurf mod, eg)... */ + if(!dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL)) + CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces); + + { +#endif /* Weights are given by caller. */ if (weights) { @@ -813,7 +1093,13 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); /* Now copy colors in all face verts. */ + /*first add colors to the tesselation faces*/ + /* XXX Why update that layer? We have to update WEIGHT_MLOOPCOL anyway, + * and tesselation recreates mface layers from mloop/mpoly ones, so no + * need to fill WEIGHT_MCOL here. */ +#if 0 for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) { + /*origindex being NULL means we're operating on original mesh data*/ #if 0 unsigned int fidx= mf->v4 ? 3:2; @@ -830,13 +1116,127 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, do { copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], - (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); + (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); } while (fidx--); } +#endif + /*now add to loops, so the data can be passed through the modifier stack*/ + /* If no CD_WEIGHT_MLOOPCOL existed yet, we have to add a new one! */ + if (!wtcol_l) { + BLI_array_declare(wtcol_l); + totloop = 0; + for (i=0; i<dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + BLI_array_growitems(wtcol_l, mp->totloop); + for (j = 0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); + } + else { + totloop = 0; + for (i=0; i < dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + for (j=0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + } MEM_freeN(wtcol_v); } } + +static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid) +{ + KeyBlock *kb; + int i, j, tot; + + if (!me->key) + return; + + tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY); + for (i=0; i<tot; i++) { + CustomDataLayer *layer = &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)]; + float (*cos)[3], (*kbcos)[3]; + + for (kb=me->key->block.first; kb; kb=kb->next) { + if (kb->uid == layer->uid) + break; + } + + if (!kb) { + kb = add_keyblock(me->key, layer->name); + kb->uid = layer->uid; + } + + if (kb->data) + MEM_freeN(kb->data); + + cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i); + kb->totelem = dm->numVertData; + + kb->data = kbcos = MEM_mallocN(sizeof(float)*3*kb->totelem, "kbcos DerivedMesh.c"); + if (kb->uid == actshape_uid) { + MVert *mvert = dm->getVertArray(dm); + + for (j=0; j<dm->numVertData; j++, kbcos++, mvert++) { + copy_v3_v3(*kbcos, mvert->co); + } + } else { + for (j=0; j<kb->totelem; j++, cos++, kbcos++) { + copy_v3_v3(*kbcos, *cos); + } + } + } + + for (kb=me->key->block.first; kb; kb=kb->next) { + if (kb->totelem != dm->numVertData) { + if (kb->data) + MEM_freeN(kb->data); + + kb->totelem = dm->numVertData; + kb->data = MEM_callocN(sizeof(float)*3*kb->totelem, "kb->data derivedmesh.c"); + fprintf(stderr, "%s: lost a shapekey layer! (bmesh internal error)\n", __func__); + } + } +} + +static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob)) +{ + KeyBlock *kb; + Key *key = me->key; + int a, b; + + if (!me->key) + return; + + if (dm->numVertData != me->totvert) { + printf("error in add_shapekey_layers: dm isn't the same size as me\n"); + return; + } + + for (a=0, kb=key->block.first; kb; kb=kb->next, a++) { + float (*cos)[3] = CustomData_add_layer_named(&dm->vertData, CD_SHAPEKEY, CD_CALLOC, NULL, dm->numVertData, kb->name); + int ci = CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, a); + + dm->vertData.layers[ci].uid = kb->uid; + if (kb->totelem != dm->numVertData) { + printf("error in add_shapekey_layers: totelem and totvert don't match"); + continue; + } + + for (b=0; b<kb->totelem; b++, cos++) { + copy_v3_v3((float *)cos, ((float*)kb->data)+b*3); + } + } +} + /* new value for useDeform -1 (hack for the gameengine): * - apply only the modifier stack of the object, skipping the virtual modifiers, * - don't apply the key @@ -845,14 +1245,15 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, - int needMapping, CustomDataMask dataMask, int index, int useCache) + int needMapping, CustomDataMask dataMask, + int index, int useCache, int build_shapekey_layers) { Mesh *me = ob->data; ModifierData *firstmd, *md, *previewmd = NULL; LinkNode *datamasks, *curr; CustomDataMask mask, nextmask, append_mask = 0; float (*deformedVerts)[3] = NULL; - DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm; + DerivedMesh *dm=NULL, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; int required_mode; int isPrevDeform= FALSE; @@ -940,7 +1341,10 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos */ if (deform_r) { *deform_r = CDDM_from_mesh(me, ob); - + + if (build_shapekey_layers) + add_shapekey_layers(dm, me, ob); + if(deformedVerts) { CDDM_apply_vert_coords(*deform_r, deformedVerts); CDDM_calc_normals(*deform_r); @@ -1044,7 +1448,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; @@ -1054,6 +1458,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } else { dm = CDDM_from_mesh(me, ob); + if (build_shapekey_layers) + add_shapekey_layers(dm, me, ob); + if(deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); CDDM_calc_normals(dm); @@ -1073,11 +1480,11 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* 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); + DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vn_i(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0); + range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } } @@ -1096,7 +1503,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); @@ -1175,7 +1582,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); @@ -1196,10 +1603,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); #endif } else { - finaldm = CDDM_from_mesh(me, ob); + int recalc_normals= 0; + finaldm = CDDM_from_mesh(me, ob); + + if(build_shapekey_layers) { + add_shapekey_layers(finaldm, me, ob); + recalc_normals= 1; + } + if(deformedVerts) { CDDM_apply_vert_coords(finaldm, deformedVerts); + recalc_normals= 1; + } + + if(recalc_normals) { CDDM_calc_normals(finaldm); } @@ -1228,6 +1646,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } #endif /* WITH_GAMEENGINE */ + /* --------------------------------------------------------------------- */ + /* First calculate the polygon and vertex normals, re-tesselation + * copies these into the tessface's normal layer */ + finaldm->calcNormals(finaldm); + /* Re-tesselation is necessary to push render data (uvs, textures, colors) + * from loops and polys onto the tessfaces. This may be currently be + * redundantin cases where the render mode doesn't use these inputs, but + * ideally eventually tesselation would happen on-demand, and this is one + * of the primary places it would be needed. */ + finaldm->recalcTesselation(finaldm); + /* Need to watch this, it can cause issues, see bug [#29338] */ + /* take care with this block, we really need testing frameworks */ + /* --------------------------------------------------------------------- */ + + *final_r = finaldm; if(orcodm) @@ -1241,21 +1674,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) { + cos = MEM_mallocN(sizeof(float)*3*numVerts, "vertexcos"); + + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { copy_v3_v3(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; @@ -1269,7 +1705,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) { @@ -1284,7 +1720,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; @@ -1298,7 +1734,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 */ @@ -1326,7 +1762,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); } } @@ -1339,7 +1775,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; @@ -1348,11 +1784,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, FALSE, FALSE); if(deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -1388,7 +1824,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); @@ -1410,13 +1846,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); } } @@ -1429,21 +1865,31 @@ 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); CDDM_apply_vert_coords(*final_r, deformedVerts); - CDDM_calc_normals(*final_r); + CDDM_calc_normals(*final_r); /* was CDDM_calc_normals_mapping - campbell */ } else if (dm) { *final_r = dm; + (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */ } else if (!deformedVerts && cage_r && *cage_r) { *final_r = *cage_r; + (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */ } else { - *final_r = editmesh_get_derived(em, deformedVerts); + *final_r = getEditDerivedBMesh(em, ob, deformedVerts); deformedVerts = NULL; + (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */ } + /* --- */ + /* BMESH_ONLY, ensure tessface's used for drawing, + * but dont recalculate if the last modifier in the stack gives us tessfaces */ + DM_ensure_tessface(*final_r); + if (cage_r && (*cage_r != *final_r)) DM_ensure_tessface(*cage_r); + /* --- */ + /* add an orco layer if needed */ if(dataMask & CD_MASK_ORCO) add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO); @@ -1487,18 +1933,19 @@ static void clear_mesh_caches(Object *ob) } } -static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) +static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, + int build_shapekey_layers) { Object *obact = scene->basact?scene->basact->object:NULL; - int editing = paint_facesel_test(ob) || paint_vertsel_test(ob);/* paint_vertsel_test */ + int editing = paint_facesel_test(ob); /* weight paint and face select need original indices because of selection buffer drawing */ - int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT))); + int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT))); clear_mesh_caches(ob); mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1, - needMapping, dataMask, -1, 1); + needMapping, dataMask, -1, 1, build_shapekey_layers); DM_set_object_boundbox (ob, ob->derivedFinal); @@ -1507,7 +1954,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); @@ -1524,7 +1971,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; @@ -1532,12 +1979,13 @@ 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, int build_shapekey_layers) { if (em) { - editmesh_build_data(scene, ob, em, dataMask); + editbmesh_build_data(scene, ob, em, dataMask); } else { - mesh_build_data(scene, ob, dataMask); + mesh_build_data(scene, ob, dataMask, build_shapekey_layers); } } @@ -1549,7 +1997,7 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat * the data we need, rebuild the derived mesh */ if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask) - mesh_build_data(scene, ob, dataMask); + mesh_build_data(scene, ob, dataMask, 0); return ob->derivedFinal; } @@ -1560,7 +2008,7 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da * the data we need, rebuild the derived mesh */ if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask) - mesh_build_data(scene, ob, dataMask); + mesh_build_data(scene, ob, dataMask, 0); return ob->derivedDeform; } @@ -1569,7 +2017,7 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0, 0); return final; } @@ -1578,7 +2026,7 @@ DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDa { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0); + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0, 0); return final; } @@ -1587,7 +2035,7 @@ DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask d { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0, 0); return final; } @@ -1597,7 +2045,7 @@ DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*ver { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0, 0); return final; } @@ -1607,7 +2055,7 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0, 0); return final; } @@ -1617,7 +2065,7 @@ DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertC { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0, 0); return final; } @@ -1628,14 +2076,14 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, { DerivedMesh *final; - mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0, 0); return final; } /***/ -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 @@ -1643,27 +2091,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); } @@ -1703,7 +2151,7 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) if(ob->type!=OB_MESH || me->totvert==0) return NULL; - dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH|CD_MASK_ORIGINDEX); vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map"); if(dm->foreachMappedVert) { @@ -1733,7 +2181,7 @@ typedef struct MVert * mvert; // vertices & normals float (*orco)[3]; float (*tangent)[4]; // destination - int numFaces; + int numTessFaces; } SGLSLMeshToTangent; @@ -1743,7 +2191,7 @@ typedef struct static int GetNumFaces(const SMikkTSpaceContext * pContext) { SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - return pMesh->numFaces; + return pMesh->numTessFaces; } static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num) @@ -1832,15 +2280,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); @@ -1849,8 +2297,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"); @@ -1870,7 +2318,7 @@ void DM_add_tangent_layer(DerivedMesh *dm) mesh2tangent.mvert = mvert; mesh2tangent.orco = orco; mesh2tangent.tangent = tangent; - mesh2tangent.numFaces = totface; + mesh2tangent.numTessFaces = totface; sContext.m_pUserData = &mesh2tangent; sContext.m_pInterface = &sInterface; @@ -1963,11 +2411,11 @@ void DM_add_tangent_layer(DerivedMesh *dm) void DM_calc_auto_bump_scale(DerivedMesh *dm) { /* int totvert= dm->getNumVerts(dm); */ /* UNUSED */ - int totface= dm->getNumFaces(dm); + int totface= dm->getNumTessFaces(dm); MVert * mvert = dm->getVertArray(dm); - MFace * mface = dm->getFaceArray(dm); - MTFace * mtface = dm->getFaceDataArray(dm, CD_MTFACE); + MFace * mface = dm->getTessFaceArray(dm); + MTFace * mtface = dm->getTessFaceDataArray(dm, CD_MTFACE); if(mtface) { @@ -2124,15 +2572,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->type == DM_TYPE_EDITMESH) - tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; - else - tfdata = fdata; - + fdata = tfdata = dm->getTessFaceDataLayout(dm); + /* calc auto bump scale if necessary */ if(dm->auto_bump_scale<=0.0f) DM_calc_auto_bump_scale(dm); @@ -2158,8 +2599,30 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, attribs->tface[a].array = tfdata->layers[layer].data; attribs->tface[a].emOffset = tfdata->layers[layer].offset; attribs->tface[a].glIndex = gattribs->layer[b].glindex; - attribs->tface[a].glTexco = gattribs->layer[b].gltexco; + /* attribs->tface[a].glTexco = gattribs->layer[b].gltexco; */ /* BMESH_TODO, trunk has this but not bmesh, need to investigate whats going on here - campbell */ } + /* BMESH ONLY, may need to get this working?, otherwise remove */ + /* else { + int player; + CustomData *pdata = dm->getPolyDataLayout(dm); + + if(gattribs->layer[b].name[0]) + player = CustomData_get_named_layer_index(pdata, CD_MTEXPOLY, + gattribs->layer[b].name); + else + player = CustomData_get_active_layer_index(pdata, CD_MTEXPOLY); + + if (player != -1) { + a = attribs->tottface++; + + attribs->tface[a].array = NULL; + attribs->tface[a].emOffset = pdata->layers[layer].offset; + attribs->tface[a].glIndex = gattribs->layer[b].glindex; + attribs->tface[a].glTexco = gattribs->layer[b].gltexco; + + } + } + */ } else if(gattribs->layer[b].type == CD_MCOL) { /* vertex colors */ @@ -2262,7 +2725,7 @@ static void navmesh_drawColored(DerivedMesh *dm) DEBUG_VBO( "Using legacy code. drawNavMeshColored\n" ); //glShadeModel(GL_SMOOTH); glBegin(glmode = GL_QUADS); - for(a = 0; a < dm->numFaceData; a++, mface++) { + for(a = 0; a < dm->numTessFaceData; a++, mface++) { int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES; int pi = polygonIdx[a]; if (pi <= 0) { @@ -2315,7 +2778,7 @@ static void navmesh_DM_drawFacesSolid(DerivedMesh *dm, static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) { DerivedMesh *result; - int maxFaces = dm->getNumFaces(dm); + int maxFaces = dm->getNumPolys(dm); int *recastData; int vertsPerPoly=0, nverts=0, ndtris=0, npolys=0; float* verts=NULL; @@ -2323,7 +2786,7 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL; int res; - result = CDDM_copy(dm); + result = CDDM_copy(dm, 0); if (!CustomData_has_layer(&result->faceData, CD_RECAST)) { int *sourceRecastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST); if (sourceRecastData) { @@ -2429,14 +2892,15 @@ char *DM_debug_info(DerivedMesh *dm) BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm); switch (dm->type) { case DM_TYPE_CDDM: tstr = "DM_TYPE_CDDM"; break; - case DM_TYPE_EDITMESH: tstr = "DM_TYPE_EDITMESH"; break; + case DM_TYPE_EDITBMESH: tstr = "DM_TYPE_EDITMESH"; break; case DM_TYPE_CCGDM: tstr = "DM_TYPE_CCGDM"; break; default: tstr = "UNKNOWN"; break; } BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr); BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData); BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData); - BLI_dynstr_appendf(dynstr, " 'numFaceData': %d,\n", dm->numFaceData); + BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData); + BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData); BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly); BLI_dynstr_appendf(dynstr, " 'vertexLayers': (\n"); @@ -2447,8 +2911,12 @@ char *DM_debug_info(DerivedMesh *dm) dm_debug_info_layers(dynstr, dm, dm->getEdgeDataArray); BLI_dynstr_appendf(dynstr, " ),\n"); - BLI_dynstr_appendf(dynstr, " 'faceLayers': (\n"); - dm_debug_info_layers(dynstr, dm, dm->getFaceDataArray); + BLI_dynstr_appendf(dynstr, " 'tessFaceLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getTessFaceDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'PolyLayers': (\n"); + dm_debug_info_layers(dynstr, dm, DM_get_poly_data_layer); BLI_dynstr_appendf(dynstr, " ),\n"); BLI_dynstr_appendf(dynstr, "}\n"); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 89bad72044e..82c9b0c4691 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -65,6 +65,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" #include "BKE_report.h" @@ -895,7 +896,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; @@ -905,11 +906,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); @@ -971,7 +971,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 { @@ -1012,44 +1012,45 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa DupliObject *dob; DerivedMesh *dm; Mesh *me= par->data; - MTFace *mtface; - MFace *mface; + MLoopUV *mloopuv; + MPoly *mpoly, *mp; + MLoop *mloop; MVert *mvert; float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; int lay, oblay, totface, a; 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) { - 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); } - totface= dm->getNumFaces(dm); - mface= dm->getFaceArray(dm); + totface= dm->getNumPolys(dm); + mpoly= dm->getPolyArray(dm); + mloop= dm->getLoopArray(dm); mvert= dm->getVertArray(dm); if(G.rendering) { orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, orco, me->totvert, 0); - mtface= me->mtface; + mloopuv= me->mloopuv; } else { orco= NULL; - mtface= NULL; + mloopuv= NULL; } /* having to loop on scene OR group objects is NOT FUN */ @@ -1093,22 +1094,36 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - for(a=0; a<totface; a++) { - int mv1 = mface[a].v1; - int mv2 = mface[a].v2; - int mv3 = mface[a].v3; - int mv4 = mface[a].v4; - float *v1= mvert[mv1].co; - float *v2= mvert[mv2].co; - float *v3= mvert[mv3].co; - float *v4= (mv4)? mvert[mv4].co: NULL; + for(a=0, mp= mpoly; a<totface; a++, mp++) { + int mv1; + int mv2; + int mv3; + /* int mv4; */ /* UNUSED */ + float *v1; + float *v2; + float *v3; + /* float *v4; */ /* UNUSED */ float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; + MLoop *loopstart= mloop + mp->loopstart; + + if (mp->totloop < 3) { + /* highly unlikely but to be safe */ + continue; + } + else { + v1= mvert[(mv1= loopstart[0].v)].co; + v2= mvert[(mv2= loopstart[1].v)].co; + v3= mvert[(mv3= loopstart[2].v)].co; + /* + if (mp->totloop > 3) { + v4= mvert[(mv4= loopstart[3].v)].co; + } + */ + } /* translation */ - if(v4) - cent_quad_v3(cent, v1, v2, v3, v4); - else - cent_tri_v3(cent, v1, v2, v3); + mesh_calc_poly_center(mp, loopstart, mvert, cent); + mul_m4_v3(pmat, cent); sub_v3_v3v3(cent, cent, pmat[3]); @@ -1124,7 +1139,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa /* scale */ if(par->transflag & OB_DUPLIFACES_SCALE) { - float size= v4? area_quad_v3(v1, v2, v3, v4): area_tri_v3(v1, v2, v3); + float size= mesh_calc_poly_area(mp, loopstart, mvert, NULL); size= sqrtf(size) * par->dupfacesca; mul_m3_fl(mat, size); } @@ -1137,23 +1152,19 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dob= new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIFACES, animated); if(G.rendering) { - w= (mv4)? 0.25f: 1.0f/3.0f; + w= 1.0f / (float)mp->totloop; if(orco) { - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv1], w); - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv2], w); - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv3], w); - if (mv4) { - madd_v3_v3v3fl(dob->orco, dob->orco, orco[mv4], w); + int j; + for (j = 0; j < mpoly->totloop; j++) { + madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); } } - if(mtface) { - madd_v2_v2v2fl(dob->uv, dob->uv, mtface[a].uv[0], w); - madd_v2_v2v2fl(dob->uv, dob->uv, mtface[a].uv[1], w); - madd_v2_v2v2fl(dob->uv, dob->uv, mtface[a].uv[2], w); - if (mv4) { - madd_v2_v2v2fl(dob->uv, dob->uv, mtface[a].uv[3], w); + if(mloopuv) { + int j; + for (j = 0; j < mpoly->totloop; j++) { + madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w); } } } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 64ea862477f..3ef36918f98 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -945,7 +945,6 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, else dvert = NULL; } else dvert = NULL; - if(armature_def_nr >= 0 && dvert) { armature_weight= defvert_find_weight(dvert, armature_def_nr); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index a8644618945..9534dfd9d0b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -57,6 +57,7 @@ #include "BLI_blenlib.h" #include "BLI_bpath.h" #include "BLI_dynstr.h" +#include "BLI_path_util.h" #include "BLI_utildefines.h" #include "BLI_callbacks.h" @@ -699,10 +700,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, BLI_temporary_dir(), "quit.blend"); + + BKE_undo_save(str); +} + +void BKE_undo_save(char *fname) +{ UndoElem *uel; MemFileChunk *chunk; int file; - char str[FILE_MAX]; if( (U.uiflag & USER_GLOBALUNDO)==0) return; @@ -715,9 +724,7 @@ void BKE_undo_save_quit(void) /* no undo state to save */ if(undobase.first==undobase.last) return; - BLI_make_file_string("/", str, BLI_temporary_dir(), "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; @@ -731,8 +738,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/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 1aad0a242f9..c9ab126d7ab 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -41,7 +41,7 @@ #include "BLI_linklist.h" #include "BKE_DerivedMesh.h" - +#include "BKE_tessmesh.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" @@ -555,7 +555,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; } @@ -572,22 +572,87 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float if(tree == NULL) { int i; - int numFaces= mesh->getNumFaces(mesh); - MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); - MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); + int numFaces= mesh->getNumTessFaces(mesh); - if(vert != NULL && face != NULL) + /* BMESH spesific check that we have tessfaces, + * we _could_ tesselate here but rather not - campbell + * + * this assert checks we have tessfaces, + * if not caller should use DM_ensure_tessface() */ + BLI_assert(!(numFaces == 0 && mesh->getNumPolys(mesh) != 0)); + + if(numFaces != 0) { /* Create a bvh-tree of the given target */ tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); if(tree != NULL) { - /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */ - EditMesh *em= data->em_evil; + BMEditMesh *em= data->em_evil; if(em) { - EditFace *efa= em->faces.first; - for(i = 0; i < numFaces; i++, efa= efa->next) { - if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) { + /*data->em_evil is only set for snapping, and only for the mesh of the object + which is currently open in edit mode. When set, the bvhtree should not contain + faces that will interfere with snapping (e.g. faces that are hidden/selected + or faces that have selected verts).*/ + + /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */ + + /*Insert BMesh-tesselation triangles into the bvh tree, unless they are hidden + and/or selected. Even if the faces themselves are not selected for the snapped + transform, having a vertex selected means the face (and thus it's tesselated + triangles) will be moving and will not be a good snap targets.*/ + for (i = 0; i < em->tottri; i++) { + BMLoop **tri = em->looptris[i]; + BMFace *f; + BMVert *v; + BMIter iter; + int insert; + + /*Each loop of the triangle points back to the BMFace it was tesselated from. + All three should point to the same face, so just use the face from the first + loop.*/ + f = tri[0]->f; + + /*If the looptris is ordered such that all triangles tesselated from a single + faces are consecutive elements in the array, then we could speed up the tests + below by using the insert value from the previous iteration.*/ + + /*Start with the assumption the triangle should be included for snapping.*/ + insert = 1; + + if (BM_TestHFlag(f, BM_SELECT) || BM_TestHFlag(f, BM_HIDDEN)) { + /*Don't insert triangles tesselated from faces that are hidden + or selected*/ + insert = 0; + } + else { + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_FACE, f) { + if (BM_TestHFlag(v, BM_SELECT)) { + /*Don't insert triangles tesselated from faces that have + any selected verts.*/ + insert = 0; + } + } + } + + if (insert) + { + /*No reason found to block hit-testing the triangle for snap, + so insert it now.*/ + float co[4][3]; + copy_v3_v3(co[0], tri[0]->v->co); + copy_v3_v3(co[1], tri[1]->v->co); + copy_v3_v3(co[2], tri[2]->v->co); + + BLI_bvhtree_insert(tree, i, co[0], 3); + } + } + } + else { + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MFace *face = mesh->getTessFaceDataArray(mesh, CD_MFACE); + + if (vert != NULL && face != NULL) { + for(i = 0; i < numFaces; i++) { float co[4][3]; copy_v3_v3(co[0], vert[ face[i].v1 ].co); copy_v3_v3(co[1], vert[ face[i].v2 ].co); @@ -599,18 +664,6 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } } } - else { - for(i = 0; i < numFaces; i++) { - float co[4][3]; - copy_v3_v3(co[0], vert[ face[i].v1 ].co); - copy_v3_v3(co[1], vert[ face[i].v2 ].co); - copy_v3_v3(co[2], vert[ face[i].v3 ].co); - if(face[i].v4) - copy_v3_v3(co[3], vert[ face[i].v4 ].co); - - BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); - } - } BLI_bvhtree_balance(tree); //Save on cache for later use @@ -638,7 +691,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 5af3dc15704..5133bb0a22b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1,4 +1,4 @@ -/* + /* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -36,11 +36,23 @@ #include "GL/glew.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; @@ -93,9 +107,19 @@ static int cdDM_getNumEdges(DerivedMesh *dm) return dm->numEdgeData; } -static int cdDM_getNumFaces(DerivedMesh *dm) +static int cdDM_getNumTessFaces(DerivedMesh *dm) +{ + return dm->numTessFaceData; +} + +static int cdDM_getNumLoops(DerivedMesh *dm) { - return dm->numFaceData; + return dm->numLoopData; +} + +static int cdDM_getNumPolys(DerivedMesh *dm) +{ + return dm->numPolyData; } static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) @@ -110,7 +134,7 @@ static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) *edge_r = cddm->medge[index]; } -static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r) +static void cdDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; *face_r = cddm->mface[index]; @@ -128,10 +152,22 @@ static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData); } -static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) +static void cdDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numTessFaceData); +} + +static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData); + memcpy(loop_r, cddm->mloop, sizeof(*loop_r) * dm->numLoopData); +} + +static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + memcpy(poly_r, cddm->mpoly, sizeof(*poly_r) * dm->numPolyData); } static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) @@ -203,7 +239,7 @@ static int can_pbvh_draw(Object *ob, DerivedMesh *dm) if(deformed) return 0; - return (cddm->mvert == me->mvert) || ob->sculpt->kb; + return cddm->mvert == me->mvert || ob->sculpt->kb; } static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) @@ -256,7 +292,7 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) CDDerivedMesh *cddm = (CDDerivedMesh*) dm; float (*face_nors)[3]; - if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData) + if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numTessFaceData) return; face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); @@ -292,13 +328,13 @@ 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) { if( GPU_buffer_legacy(dm) ) { glBegin(GL_LINES); - for(i = 0; i < dm->numFaceData; i++, mf++, tf++) { + for(i = 0; i < dm->numTessFaceData; i++, mf++, tf++) { if(!(mf->flag&ME_HIDE)) { glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); @@ -328,7 +364,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) GPU_uvedge_setup(dm); if( !GPU_buffer_legacy(dm) ) { - for(i = 0; i < dm->numFaceData; i++, mf++) { + for(i = 0; i < dm->numTessFaceData; i++, mf++) { if(!(mf->flag&ME_HIDE)) { draw = 1; } @@ -463,7 +499,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) { \ @@ -475,7 +511,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, } if(cddm->pbvh && cddm->pbvh_draw) { - if(dm->numFaceData) { + if(dm->numTessFaceData) { float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); /* should be per face */ @@ -493,7 +529,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, if( GPU_buffer_legacy(dm) ) { DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" ); glBegin(glmode = GL_QUADS); - for(a = 0; a < dm->numFaceData; a++, mface++) { + for(a = 0; a < dm->numTessFaceData; a++, mface++) { int new_glmode, new_matnr, new_shademodel; new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES; @@ -586,7 +622,7 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" ); glShadeModel(GL_SMOOTH); glBegin(glmode = GL_QUADS); - for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) { + for(a = 0; a < dm->numTessFaceData; a++, mface++, cp1 += 16) { int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES; if(new_glmode != glmode) { @@ -652,21 +688,21 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, { 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 */ /* UNUSED */; - 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); if( GPU_buffer_legacy(dm) ) { DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" ); - for(i = 0; i < dm->numFaceData; i++, mf++) { + for(i = 0; i < dm->numTessFaceData; i++, mf++) { MVert *mvert; int flag; unsigned char *cp = NULL; @@ -752,8 +788,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++ ) { /* bgr -> rgb is intentional (and stupid), but how its stored internally */ colors[i*12+j*3] = col[i*4+j].b; @@ -850,14 +886,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, 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_get_tessface_data_layer(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); @@ -865,7 +901,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, * color array temporarily overwritten for drawing, then reset. */ if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) { DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" ); - for(i = 0; i < dm->numFaceData; i++, mf++) { + for(i = 0; i < dm->numTessFaceData; i++, mf++) { int drawSmooth = (mf->flag & ME_SMOOTH); int draw= 1; @@ -1067,10 +1103,10 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ + float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, b, dodraw, matnr, new_matnr; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); @@ -1085,7 +1121,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glBegin(GL_QUADS); - for(a = 0; a < dm->numFaceData; a++, mface++) { + for(a = 0; a < dm->numTessFaceData; a++, mface++) { const int smoothnormal = (mface->flag & ME_SMOOTH); new_matnr = mface->mat_nr + 1; @@ -1361,9 +1397,9 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mf = cddm->mface; - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, matnr, new_matnr; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); @@ -1375,7 +1411,7 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, glBegin(GL_QUADS); - for(a = 0; a < dm->numFaceData; a++, mf++) { + for(a = 0; a < dm->numTessFaceData; a++, mf++) { const int smoothnormal = (mf->flag & ME_SMOOTH); /* material */ @@ -1505,10 +1541,13 @@ 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]; @@ -1518,22 +1557,51 @@ static void cdDM_foreachMappedFaceCenter( } 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); - copy_v3_v3(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); } + +} + +void CDDM_recalc_tesselation_ex(DerivedMesh *dm, const int do_face_nor_cpy) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + dm->numTessFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, &dm->polyData, + cddm->mvert, + dm->numTessFaceData, dm->numLoopData, dm->numPolyData, + do_face_nor_cpy); + + if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) { + int *polyIndex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyIndex, dm->numTessFaceData); + } + + cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + + /* Tesselation recreated faceData, and the active layer indices need to get re-propagated + from loops and polys to faces */ + CustomData_bmesh_update_active_layers(&dm->faceData, &dm->polyData, &dm->loopData); +} + +void CDDM_recalc_tesselation(DerivedMesh *dm) +{ + CDDM_recalc_tesselation_ex(dm, TRUE); } static void cdDM_free_internal(CDDerivedMesh *cddm) @@ -1552,6 +1620,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) { @@ -1564,21 +1637,30 @@ 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->getNumLoops = cdDM_getNumLoops; + dm->getNumPolys = cdDM_getNumPolys; dm->getVert = cdDM_getVert; dm->getEdge = cdDM_getEdge; - dm->getFace = cdDM_getFace; + dm->getTessFace = cdDM_getTessFace; + dm->copyVertArray = cdDM_copyVertArray; dm->copyEdgeArray = cdDM_copyEdgeArray; - dm->copyFaceArray = cdDM_copyFaceArray; + dm->copyTessFaceArray = cdDM_copyTessFaceArray; + dm->copyLoopArray = cdDM_copyLoopArray; + dm->copyPolyArray = cdDM_copyPolyArray; + dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; + dm->getTessFaceData = DM_get_tessface_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; + + dm->calcNormals = CDDM_calc_normals; + dm->recalcTesselation = CDDM_recalc_tesselation; dm->getVertCos = cdDM_getVertCos; dm->getVertCo = cdDM_getVertCo; @@ -1612,24 +1694,30 @@ 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 numTessFaces, 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, numTessFaces, 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->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces); + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numTessFaces); + 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->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces); + 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; } @@ -1640,10 +1728,12 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) DerivedMesh *dm = &cddm->dm; CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); int alloctype; + int *polyindex = NULL; /* 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; @@ -1653,21 +1743,38 @@ 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_POLYINDEX, 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); + /* commented since even when CD_POLYINDEX was first added this line fails + * on the default cube, (after editmode toggle too) - campbell */ +#if 0 + BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_POLYINDEX)); +#endif + + polyindex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); + if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)) { + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyindex, mesh->totface); + } + return dm; } -DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) +static DerivedMesh *UNUSED_FUNCTION(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; @@ -1684,7 +1791,9 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->numEdgeData); */ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, - CD_CALLOC, dm->numFaceData); + CD_CALLOC, dm->numTessFaceData); + CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numTessFaceData); /* set eve->hash to vert index */ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) @@ -1738,8 +1847,8 @@ 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); - for(i = 0, efa = em->faces.first; i < dm->numFaceData; + index = dm->getTessFaceDataArray(dm, CD_POLYINDEX); + for(i = 0, efa = em->faces.first; i < dm->numTessFaceData; i++, efa = efa->next, index++) { MFace *mf = &mface[i]; @@ -1771,15 +1880,17 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) MVert *allvert; MEdge *alledge; MFace *allface; - int totvert, totedge, totface; + MLoop *allloop; + MPoly *allpoly; + int totvert, totedge, totface, totloop, totpoly; if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge, - &totedge, &allface, &totface) != 0) { + &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 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, totloop, totpoly); dm->deformedOnly = 1; cddm = (CDDerivedMesh*)dm; @@ -1787,43 +1898,279 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) memcpy(cddm->mvert, allvert, totvert*sizeof(MVert)); memcpy(cddm->medge, alledge, totedge*sizeof(MEdge)); memcpy(cddm->mface, allface, totface*sizeof(MFace)); + memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop)); + memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly)); MEM_freeN(allvert); MEM_freeN(alledge); MEM_freeN(allface); + MEM_freeN(allloop); + MEM_freeN(allpoly); 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 *UNUSED(me), int use_mdisps, int use_tessface) +{ + 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(&bm->ldata, CD_MLOOPCOL); + int numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + int *index, add_orig; + int has_crease, has_edge_bweight, has_vert_bweight; + CustomDataMask mask; + unsigned int i, j; + + has_edge_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT); + has_vert_bweight = CustomData_has_layer(&bm->vdata, CD_BWEIGHT); + has_crease = CustomData_has_layer(&bm->edata, CD_CREASE); + + dm->deformedOnly = 1; + + /*don't add origindex layer if one already exists*/ + add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); + + mask = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH; + + /*don't process shapekeys, we only feed them through the modifier stack as needed, + e.g. for applying modifiers or the like*/ + mask &= ~CD_MASK_SHAPEKEY; + CustomData_merge(&bm->vdata, &dm->vertData, mask, + CD_CALLOC, dm->numVertData); + CustomData_merge(&bm->edata, &dm->edgeData, mask, + CD_CALLOC, dm->numEdgeData); + CustomData_merge(&bm->ldata, &dm->loopData, mask, + CD_CALLOC, dm->numLoopData); + CustomData_merge(&bm->pdata, &dm->polyData, mask, + CD_CALLOC, dm->numPolyData); + + /*add tesselation mface layers*/ + if (use_tessface) { + CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri); + } + + 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]; + + copy_v3_v3(mv->co, eve->co); + + BM_SetIndex(eve, i); /* set_inline */ + + normal_float_to_short_v3(mv->no, eve->no); + + mv->flag = BM_Vert_Flag_To_MEFlag(eve); + + if (has_vert_bweight) + mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f); + + if (add_orig) *index = i; + + CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i); + } + bm->elem_index_dirty &= ~BM_VERT; + + 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]; + + BM_SetIndex(eed, i); /* set_inline */ + + med->v1 = BM_GetIndex(eed->v1); + med->v2 = BM_GetIndex(eed->v2); + + if (has_crease) + med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f); + if (has_edge_bweight) + med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f); + + med->flag = BM_Edge_Flag_To_MEFlag(eed); + + CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i); + if (add_orig) *index = i; + } + bm->elem_index_dirty &= ~BM_EDGE; + + /* avoid this where possiblem, takes extra memory */ + if (use_tessface) { + int *polyindex; + + BM_ElemIndex_Ensure(bm, BM_FACE); + + polyindex = dm->getTessFaceDataArray(dm, CD_POLYINDEX); + index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + for(i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) { + MFace *mf = &mface[i]; + BMLoop **l = em->looptris[i]; + efa = l[0]->f; + + mf->v1 = BM_GetIndex(l[0]->v); + mf->v2 = BM_GetIndex(l[1]->v); + mf->v3 = BM_GetIndex(l[2]->v); + mf->v4 = 0; + mf->mat_nr = efa->mat_nr; + mf->flag = BM_Face_Flag_To_MEFlag(efa); + + *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX); + *polyindex = BM_GetIndex(efa); + + 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]; + + BM_SetIndex(efa, i); /* set_inline */ + + mp->totloop = efa->len; + mp->flag = BM_Face_Flag_To_MEFlag(efa); + mp->loopstart = j; + mp->mat_nr = efa->mat_nr; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) { + mloop->v = BM_GetIndex(l->v); + mloop->e = BM_GetIndex(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; + } + bm->elem_index_dirty &= ~BM_FACE; + + return dm; +} + +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 numTessFaces = source->numTessFaceData; + 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, numTessFaces, + numLoops, numPolys); dm->deformedOnly = source->deformedOnly; CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); - CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces); + CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); /* 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); + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); + + 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); + + /* any callers that need tessface data can calculate it - campbell */ +#if 0 + /* BMESH_TODO: Find out why this is necessary (or else find a way to remove + it). If it is necessary, add a comment explaining why. */ + CDDM_recalc_tesselation((DerivedMesh *)cddm); +#endif return dm; } @@ -1831,7 +2178,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 numTessFaces, + int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); DerivedMesh *dm = &cddm->dm; @@ -1839,26 +2187,32 @@ 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, numTessFaces, 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->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces); + 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); if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces); + if(!CustomData_get_layer(&dm->faceData, CD_POLYINDEX)) + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numTessFaces); 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; } @@ -1891,9 +2245,79 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) copy_v3_v3_short(vert->no, vertNormals[i]); } +void CDDM_calc_normals_mapping(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + float (*face_nors)[3] = NULL; + + /* use this to skip calculating normals on original vert's, this may need to be changed */ + const short only_face_normals = CustomData_is_referenced_layer(&dm->vertData, CD_MVERT); + + if(dm->numVertData == 0) return; + + /* now we skip calculating vertex normals for referenced layer, + * no need to duplicate verts. + * WATCH THIS, bmesh only change!, + * need to take care of the side effects here - campbell */ +#if 0 + /* we don't want to overwrite any referenced layers */ + cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); +#endif + + + if (dm->numTessFaceData == 0) { + /* No tesselation on this mesh yet, need to calculate one. + * + * Important not to update face normals from polys since it + * interfears with assigning the new normal layer in the following code. + */ + CDDM_recalc_tesselation_ex(dm, FALSE); + } + else { + /* A tesselation already exists, it should always have a CD_POLYINDEX */ + BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); + CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData); + } + + + face_nors = MEM_mallocN(sizeof(float)*3*dm->numTessFaceData, "face_nors"); + + /* calculate face normals */ + mesh_calc_normals_mapping_ex(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numTessFaceData, + CustomData_get_layer(&dm->faceData, CD_POLYINDEX), face_nors, + only_face_normals); + + CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, + face_nors, dm->numTessFaceData); + + +} + +/* bmesh note: this matches what we have in trunk */ void CDDM_calc_normals(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + float (*poly_nors)[3]; + + if(dm->numVertData == 0) return; + + /* we don't want to overwrite any referenced layers */ + cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); + + /* fill in if it exists */ + poly_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL); + if (!poly_nors) { + poly_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, dm->numPolyData); + } + + mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + dm->numLoopData, dm->numPolyData, poly_nors); +} + +void CDDM_calc_normals_tessface(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; float (*face_nors)[3]; if(dm->numVertData == 0) return; @@ -1901,17 +2325,204 @@ void CDDM_calc_normals(DerivedMesh *dm) /* we don't want to overwrite any referenced layers */ cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - /* make a face normal layer if not present */ + /* fill in if it exists */ 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); + if (!face_nors) { + face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numTessFaceData); + } - /* calculate face normals */ - mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors); + mesh_calc_normals_tessface(cddm->mvert, dm->numVertData, + cddm->mface, dm->numTessFaceData, face_nors); } -void CDDM_calc_edges(DerivedMesh *dm) +#if 1 +/* 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 frees dm, and returns a new one. + * + * this is a really horribly written function. ger. - joeedh + * + * note, CDDM_recalc_tesselation has to run on the returned DM if you want to access tessfaces. + */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CDDerivedMesh *cddm2 = NULL; + MVert *mv, *mvert = NULL; + BLI_array_declare(mvert); + MEdge *med, *medge = NULL; + BLI_array_declare(medge); + MPoly *mp, *mpoly = NULL; + BLI_array_declare(mpoly); + MLoop *ml, *mloop = NULL; + BLI_array_declare(mloop); + EdgeHash *ehash = BLI_edgehash_new(); + 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; + + totloop = dm->numLoopData; + totpoly = dm->numPolyData; + + 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"); + + /*fill newl with destination vertex indices*/ + 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); + } + } + + /*now link target vertices to destination indices*/ + for (i=0; i<dm->numVertData; i++) { + if (vtargetmap[i] != -1) { + newv[i] = newv[vtargetmap[i]]; + } + } + + /*find-replace merged vertices with target vertices*/ + ml = cddm->mloop; + c = 0; + for (i=0; i<totloop; i++, ml++) { + if (vtargetmap[ml->v] != -1) { + ml->v = vtargetmap[ml->v]; + } + } + + /*now go through and fix edges and faces*/ + med = cddm->medge; + c = 0; + for (i=0; i<dm->numEdgeData; i++, med++) { + + if (LIKELY(med->v1 != med->v2)) { + const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + void **eh_p= BLI_edgehash_lookup_p(ehash, v1, v2); + + if (eh_p) { + newe[i] = GET_INT_FROM_POINTER(*eh_p); + } + else { + BLI_array_append(olde, i); + newe[i] = c; + BLI_array_append(medge, *med); + BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c)); + c++; + } + } + else { + newe[i] = -1; + } + } + + 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++) { + med = cddm->medge + ml->e; + if (LIKELY(med->v1 != med->v2)) { + newl[j+mp->loopstart] = BLI_array_count(mloop); + BLI_array_append(oldl, j+mp->loopstart); + BLI_array_append(mloop, *ml); + c++; + } + } + + if (UNLIKELY(c == 0)) { + continue; + } + + mp2 = BLI_array_append_r(mpoly, *mp); + mp2->totloop = c; + mp2->loopstart = BLI_array_count(mloop) - c; + + BLI_array_append(oldp, i); + } + + /*create new cddm*/ + cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly)); + + /*update edge indices and copy customdata*/ + med = medge; + for (i=0; i<cddm2->dm.numEdgeData; i++, med++) { + if (newv[med->v1] != -1) + med->v1 = newv[med->v1]; + if (newv[med->v2] != -1) + med->v2 = newv[med->v2]; + + CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1); + } + + /*update loop indices and copy customdata*/ + ml = mloop; + for (i=0; i<cddm2->dm.numLoopData; i++, ml++) { + if (newe[ml->e] != -1) + ml->e = newe[ml->e]; + if (newv[ml->v] != -1) + ml->v = newv[ml->v]; + + CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1); + } + + /*copy vertex customdata*/ + mv = mvert; + for (i=0; i<cddm2->dm.numVertData; i++, mv++) { + CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1); + } + + /*copy poly customdata*/ + mp = mpoly; + for (i=0; i<cddm2->dm.numPolyData; i++, mp++) { + CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1); + } + + /*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); + + 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); + if (ehash) + BLI_edgehash_free(ehash, NULL); + + /*free old derivedmesh*/ + dm->needsFree = 1; + dm->release(dm); + + return (DerivedMesh*)cddm2; +} +#endif + +void CDDM_calc_edges_tessface(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; CustomData edgeData; @@ -1919,7 +2530,7 @@ void CDDM_calc_edges(DerivedMesh *dm) MFace *mf = cddm->mface; MEdge *med; EdgeHash *eh = BLI_edgehash_new(); - int i, *index, numEdges, maxFaces = dm->numFaceData; + int i, *index, numEdges, maxFaces = dm->numTessFaceData; for (i = 0; i < maxFaces; i++, mf++) { if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) @@ -1967,6 +2578,82 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehash_free(eh, NULL); } +/* warning, this uses existing edges but CDDM_calc_edges_tessface() doesn't */ +void CDDM_calc_edges(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, *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 = ME_POLY_LOOP_NEXT(cddm->mloop, mp, j)->v; + if (!BLI_edgehash_haskey(eh, v1, v2)) { + BLI_edgehash_insert(eh, v1, v2, NULL); + } + } + } + + 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, &med->v1, &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 = ME_POLY_LOOP_NEXT(cddm->mloop, mp, j)->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) @@ -1983,12 +2670,20 @@ void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges) dm->numEdgeData = numEdges; } -void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces) +void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces) { - if (numFaces < dm->numFaceData) - CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces); + if (numTessFaces < dm->numTessFaceData) + CustomData_free_elem(&dm->faceData, numTessFaces, dm->numTessFaceData-numTessFaces); - dm->numFaceData = numFaces; + dm->numTessFaceData = numTessFaces; +} + +void CDDM_lower_num_polys(DerivedMesh *dm, int numPolys) +{ + if (numPolys < dm->numPolyData) + CustomData_free_elem(&dm->polyData, numPolys, dm->numPolyData-numPolys); + + dm->numPolyData = numPolys; } MVert *CDDM_get_vert(DerivedMesh *dm, int index) @@ -2001,7 +2696,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]; } @@ -2016,8 +2711,127 @@ 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; } +MLoop *CDDM_get_loops(DerivedMesh *dm) +{ + return ((CDDerivedMesh*)dm)->mloop; +} + +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; + EdgeHash *eh = BLI_edgehash_new(); + int i, totloop; + + /*ensure we have all the edges we need*/ + CDDM_calc_edges_tessface(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.numTessFaceData; 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.numTessFaceData; + + if (totloop) { + MLoop *ml; + MPoly *mp; + int l, *polyindex; + + cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces"); + cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numTessFaceData, "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.numTessFaceData); + + polyindex = CustomData_get_layer(&cddm->dm.faceData, CD_POLYINDEX); + + mf = cddm->mface; + mp = cddm->mpoly; + ml = cddm->mloop; + l = 0; + for (i=0; i<cddm->dm.numTessFaceData; 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++; + } + + *polyindex = i; + } + } + + BLI_edgehash_free(eh, NULL); +} + +void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) + CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData); + + cddm->mvert = mvert; +} + +void CDDM_set_medge(DerivedMesh *dm, MEdge *medge) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) + CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData); + + cddm->medge = medge; +} + +void CDDM_set_mface(DerivedMesh *dm, MFace *mface) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + if (!CustomData_has_layer(&dm->faceData, CD_MFACE)) + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numTessFaceData); + + cddm->mface = mface; +} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d86fc5c9aef..ca0898a7085 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -35,6 +35,7 @@ #include "DNA_object_types.h" #include "DNA_meshdata_types.h" +#include "BLI_utildefines.h" #include "BLI_math.h" #include "BLI_edgehash.h" #include "BLI_utildefines.h" @@ -930,8 +931,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. */ @@ -1043,9 +1044,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/collision.c b/source/blender/blenkernel/intern/collision.c index 456c0c9fe3b..10a955760f0 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -42,6 +42,7 @@ #include "DNA_scene_types.h" #include "DNA_meshdata_types.h" +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_edgehash.h" diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8118cf64429..e207334bd45 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -77,8 +77,12 @@ #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" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" @@ -434,7 +438,7 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat { 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]; @@ -450,7 +454,7 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat /* 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, FALSE, FALSE); freeDM= 1; } else { @@ -520,8 +524,6 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat /* 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 */ diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f840774222a..4dbb143a73e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -44,6 +44,7 @@ #include "DNA_meshdata_types.h" #include "DNA_ID.h" +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_math.h" @@ -54,9 +55,13 @@ #include "BKE_customdata_file.h" #include "BKE_global.h" #include "BKE_main.h" -#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 @@ -440,6 +445,23 @@ static void layerSwap_mdisps(void *data, const int *ci) } } +#if 1 /* BMESH_TODO: place holder function, dont actually interp */ +static void layerInterp_mdisps(void **sources, float *UNUSED(weights), + float *UNUSED(sub_weights), int UNUSED(count), void *dest) +{ + MDisps *d = dest; + + /* happens when flipping normals of newly created mesh */ + if(!d->totdisp) { + d->totdisp = ((MDisps*)sources[0])->totdisp; + } + + if (!d->disps && d->totdisp) + d->disps = MEM_callocN(sizeof(float)*3*d->totdisp, "blank mdisps in layerInterp_mdisps"); +} + +#else // BMESH_TODO + static void layerInterp_mdisps(void **sources, float *UNUSED(weights), float *sub_weights, int count, void *dest) { @@ -552,6 +574,7 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), MEM_freeN(d->disps); d->disps = disps; } +#endif // BMESH_TODO static void layerCopy_mdisps(const void *source, void *dest, int count) { @@ -574,6 +597,10 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) static void layerValidate_mdisps(void *data, int sub_elements) { +#if 1 /*BMESH_TODO*/ + (void)data; + (void)sub_elements; +#else MDisps *disps = data; if(disps->disps) { int corners = multires_mdisp_corners(disps); @@ -584,6 +611,7 @@ static void layerValidate_mdisps(void *data, int sub_elements) disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); } } +#endif } static void layerFree_mdisps(void *data, int count, int UNUSED(size)) @@ -992,7 +1020,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 8: CD_NORMAL */ /* 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}, /* 9: CD_POLYINDEX */ {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 10: CD_PROP_FLT */ @@ -1037,9 +1065,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 24: CD_RECAST */ {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} -#ifdef USE_BMESH_FORWARD_COMPAT - , /* BMESH ONLY */ + , /* 25: CD_MPOLY */ {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, /* 26: CD_MLOOP */ @@ -1058,10 +1085,11 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, /* END BMESH ONLY */ -#endif /* USE_BMESH_FORWARD_COMPAT */ }; +/* note, numbers are from trunk and need updating for bmesh */ + static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", @@ -1069,29 +1097,38 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast" -#ifdef USE_BMESH_FORWARD_COMPAT +/* BMESH ONLY */ , /* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", /* 30-31 */ "CDSubSurfCrease", "CDWeightLoopCol" +/* END BMESH ONLY */ -#endif /* USE_BMESH_FORWARD_COMPAT */ }; + 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_RECAST; + 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 | CD_MASK_RECAST; 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_RECAST; + 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 | CD_MASK_RECAST; 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 | CD_MASK_RECAST; -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_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | + 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 | CD_MASK_SHAPEKEY | CD_MASK_RECAST | + CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX; +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; @@ -1140,6 +1177,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, { /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; + void *data; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; for(i = 0; i < source->totlayer; ++i) { @@ -1164,14 +1202,27 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, else if(!(mask & CD_TYPE_AS_MASK(type))) continue; else if(number < CustomData_number_of_layers(dest, type)) continue; + switch (alloctype) { + case CD_ASSIGN: + case CD_REFERENCE: + case CD_DUPLICATE: + data = layer->data; + break; + default: + data = NULL; + break; + } + if((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE)) newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE, - layer->data, totelem, layer->name); + data, totelem, layer->name); else newlayer = customData_add_layer__internal(dest, type, alloctype, - layer->data, totelem, layer->name); + data, totelem, layer->name); if(newlayer) { + newlayer->uid = layer->uid; + newlayer->active = lastactive; newlayer->active_rnd = lastrender; newlayer->active_clone = lastclone; @@ -1473,7 +1524,14 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, { const LayerTypeInfo *typeInfo= layerType_getInfo(type); int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; - void *newlayerdata; + void *newlayerdata = NULL; + + /* Passing a layerdata to copy from with an alloctype that won't copy is + most likely a bug */ + BLI_assert(!layerdata || + (alloctype == CD_ASSIGN) || + (alloctype == CD_DUPLICATE) || + (alloctype == CD_REFERENCE)); if (!typeInfo->defaultname && CustomData_has_layer(data, type)) return &data->layers[CustomData_get_layer_index(data, type)]; @@ -1481,13 +1539,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { newlayerdata = layerdata; } - else { + else if (size > 0) { newlayerdata = MEM_callocN(size, layerType_getName(type)); if(!newlayerdata) return NULL; } - if (alloctype == CD_DUPLICATE) { + if (alloctype == CD_DUPLICATE && layerdata) { if(typeInfo->copy) typeInfo->copy(layerdata, newlayerdata, totelem); else @@ -2304,35 +2362,139 @@ 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); + for(i=0; i < fdata->totlayer; i++) { + if(fdata->layers[i].type == CD_MTFACE) { + CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC, NULL, totpoly, fdata->layers[i].name); + CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC, NULL, totloop, fdata->layers[i].name); } - else if(fdata->layers[i].type == CD_MCOL) - CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0); - } + else if (fdata->layers[i].type == CD_MCOL) { + CustomData_add_layer_named(ldata, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, fdata->layers[i].name); + } + else if (fdata->layers[i].type == CD_MDISPS) { + CustomData_add_layer_named(ldata, CD_MDISPS, CD_CALLOC, NULL, totloop, fdata->layers[i].name); + } + } } + void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total) { int i; - for(i=0; i < pdata->totlayer; i++){ - if(pdata->layers[i].type == CD_MTEXPOLY) - CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total); + for(i=0; i < pdata->totlayer; i++) { + if (pdata->layers[i].type == CD_MTEXPOLY) { + CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name); + } } - 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); + for(i=0; i < ldata->totlayer; i++) { + if (ldata->layers[i].type == CD_MLOOPCOL) { + CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); + } + else if (ldata->layers[i].type == CD_WEIGHT_MLOOPCOL) { + CustomData_add_layer_named(fdata, CD_WEIGHT_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); + } } } +void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata) +{ + int act; + + if (CustomData_has_layer(pdata, CD_MTEXPOLY)) { + act = CustomData_get_active_layer(pdata, CD_MTEXPOLY); + CustomData_set_layer_active(ldata, CD_MLOOPUV, act); + CustomData_set_layer_active(fdata, CD_MTFACE, act); + + act = CustomData_get_render_layer(pdata, CD_MTEXPOLY); + CustomData_set_layer_render(ldata, CD_MLOOPUV, act); + CustomData_set_layer_render(fdata, CD_MTFACE, act); + + act = CustomData_get_clone_layer(pdata, CD_MTEXPOLY); + CustomData_set_layer_clone(ldata, CD_MLOOPUV, act); + CustomData_set_layer_clone(fdata, CD_MTFACE, act); + + act = CustomData_get_stencil_layer(pdata, CD_MTEXPOLY); + CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act); + CustomData_set_layer_stencil(fdata, CD_MTFACE, act); + } + + if (CustomData_has_layer(ldata, CD_MLOOPCOL)) { + act = CustomData_get_active_layer(ldata, CD_MLOOPCOL); + CustomData_set_layer_active(fdata, CD_MCOL, act); + + act = CustomData_get_render_layer(ldata, CD_MLOOPCOL); + CustomData_set_layer_render(fdata, CD_MCOL, act); + + act = CustomData_get_clone_layer(ldata, CD_MLOOPCOL); + CustomData_set_layer_clone(fdata, CD_MCOL, act); + + act = CustomData_get_stencil_layer(ldata, CD_MLOOPCOL); + CustomData_set_layer_stencil(fdata, CD_MCOL, act); + } +} void CustomData_bmesh_init_pool(CustomData *data, int allocsize) { - if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, FALSE, FALSE); + /* Dispose old pools before calling here to avoid leaks */ + BLI_assert(data->pool == NULL); + + /* If there are no layers, no pool is needed just yet */ + if (data->totlayer) { + data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, TRUE, FALSE); + } +} + +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; + default: /* should never happen */ + BLI_assert(!"invalid type given"); + t = BM_VERTS_OF_MESH; + } + + 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) @@ -2352,7 +2514,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; } @@ -2363,7 +2527,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; } @@ -2444,6 +2608,73 @@ void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) 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) { diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 3f3e3b80042..a95cd8d00d8 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -650,11 +650,11 @@ void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw) dvert->dw[i]= dvert->dw[dvert->totweight]; } memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight); - MEM_freeN(dvert->dw); #else memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*i); memcpy(dw_new+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); #endif + MEM_freeN(dvert->dw); } dvert->dw = dw_new; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e0f76917368..d944d12b0c0 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -432,6 +432,8 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) totvert= 0; nextcol= 0; + BLI_begin_edgefill(); + dl= dispbase->first; while(dl) { @@ -885,12 +887,12 @@ 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; CDDM_apply_vert_coords(dm, vertCos); - CDDM_calc_normals(dm); + CDDM_calc_normals_mapping(dm); } } else { if (vertCos) { @@ -903,7 +905,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba dm= CDDM_from_curve_customDB(ob, dispbase); - CDDM_calc_normals(dm); + CDDM_calc_normals_mapping(dm); } if (vertCos) { @@ -926,12 +928,12 @@ 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; CDDM_apply_vert_coords(dm, vertCos); - CDDM_calc_normals(dm); + CDDM_calc_normals_mapping(dm); MEM_freeN(vertCos); } else { displist_apply_allverts(dispbase, vertCos); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index cdfd5d3562b..f4e69624839 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1227,6 +1227,7 @@ static int surface_usesAdjData(DynamicPaintSurface *surface) static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init) { PaintSurfaceData *sData = surface->data; + DerivedMesh *dm = surface->canvas->dm; PaintAdjData *ad; int *temp_data; int neigh_points = 0; @@ -1235,7 +1236,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { /* For vertex format, neighbours are connected by edges */ - neigh_points = 2*surface->canvas->dm->getNumEdges(surface->canvas->dm); + neigh_points = 2*dm->getNumEdges(dm); } else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) neigh_points = sData->total_points*8; @@ -1265,10 +1266,11 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for int n_pos; /* For vertex format, count every vertex that is connected by an edge */ - int numOfEdges = surface->canvas->dm->getNumEdges(surface->canvas->dm); - int numOfFaces = surface->canvas->dm->getNumFaces(surface->canvas->dm); - struct MEdge *edge = surface->canvas->dm->getEdgeArray(surface->canvas->dm); - struct MFace *face = surface->canvas->dm->getFaceArray(surface->canvas->dm); + int numOfEdges = dm->getNumEdges(dm); + int numOfPolys = dm->getNumPolys(dm); + struct MEdge *edge = dm->getEdgeArray(dm); + struct MPoly *mpoly = dm->getPolyArray(dm); + struct MLoop *mloop = dm->getLoopArray(dm); /* count number of edges per vertex */ for (i=0; i<numOfEdges; i++) { @@ -1281,12 +1283,11 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for /* also add number of vertices to temp_data * to locate points on "mesh edge" */ - for (i=0; i<numOfFaces; i++) { - temp_data[face[i].v1]++; - temp_data[face[i].v2]++; - temp_data[face[i].v3]++; - if (face[i].v4) - temp_data[face[i].v4]++; + for (i=0; i<numOfPolys; i++) { + int j=0; + for (; j<mpoly[i].totloop; j++) { + temp_data[mloop[mpoly[i].loopstart + j].v]++; + } } /* now check if total number of edges+faces for @@ -1355,8 +1356,8 @@ void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { Tex *tex = surface->init_texture; MTFace *tface; - MFace *mface = dm->getFaceArray(dm); - int numOfFaces = dm->getNumFaces(dm); + MFace *mface = dm->getTessFaceArray(dm); + int numOfFaces = dm->getNumTessFaces(dm); char uvname[MAX_CUSTOMDATA_LAYER_NAME]; if (!tex) return; @@ -1425,31 +1426,27 @@ void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) } /* vertex color layer */ else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) { - MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername); - if (!col) return; /* for vertex surface, just copy colors from mcol */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - MFace *mface = dm->getFaceArray(dm); - int numOfFaces = dm->getNumFaces(dm); + MLoop *mloop = dm->getLoopArray(dm); + int numOfLoops = dm->getNumLoops(dm); + MCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername); + if (!col) return; #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - int numOfVert = (mface[i].v4) ? 4 : 3; - int j; - for (j=0; j<numOfVert; j++) { - unsigned int *vert = ((&mface[i].v1)+j); - - pPoint[*vert].color[0] = 1.0f/255.f*(float)col[i*4+j].b; - pPoint[*vert].color[1] = 1.0f/255.f*(float)col[i*4+j].g; - pPoint[*vert].color[2] = 1.0f/255.f*(float)col[i*4+j].r; - pPoint[*vert].alpha = 1.0f/255.f*(float)col[i*4+j].a; - } + for (i=0; i<numOfLoops; i++) { + pPoint[mloop[i].v].color[0] = 1.0f/255.f*(float)col[i].b; + pPoint[mloop[i].v].color[1] = 1.0f/255.f*(float)col[i].g; + pPoint[mloop[i].v].color[2] = 1.0f/255.f*(float)col[i].r; + pPoint[mloop[i].v].alpha = 1.0f/255.f*(float)col[i].a; } } else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data; int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; + MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername); + if (!col) return; #pragma omp parallel for schedule(static) for (i=0; i<sData->total_points; i++) { @@ -1575,7 +1572,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData Object *ob, DerivedMesh *dm) { - DerivedMesh *result = CDDM_copy(dm); + DerivedMesh *result = CDDM_copy(dm, 0); if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) { @@ -1595,11 +1592,11 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData /* vertex color paint */ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { - MFace *mface = result->getFaceArray(result); - int numOfFaces = result->getNumFaces(result); int i; PaintPoint* pPoint = (PaintPoint*)sData->type_data; - MCol *col; + MLoopCol *col = NULL; + MLoop *mloop = CDDM_get_loops(result); + int totloop = result->numLoopData; /* paint is stored on dry and wet layers, so mix final color first */ float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color"); @@ -1612,26 +1609,37 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData /* viewport preview */ if (surface->flags & MOD_DPAINT_PREVIEW) { - /* Save preview results to weight layer, to be + MPoly *mp = CDDM_get_polys(result); + int totpoly = result->numPolyData; + + /* XXX We have to create a CD_WEIGHT_MCOL, else it might sigsev + * (after a SubSurf mod, eg)... */ + if(!result->getTessFaceDataArray(result, CD_WEIGHT_MCOL)) { + int numFaces = result->getNumTessFaces(result); + CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces); + } + + /* Save preview results to weight layer to be * able to share same drawing methods */ - col = result->getFaceDataArray(result, CD_WEIGHT_MCOL); - if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces); + col = CustomData_get_layer(&result->loopData, CD_WEIGHT_MLOOPCOL); + if (!col) col = CustomData_add_layer(&result->loopData, CD_WEIGHT_MLOOPCOL, CD_CALLOC, NULL, totloop); if (col) { #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - int j = (mface[i].v4) ? 4 : 3; - Material *material = give_current_material(ob, mface[i].mat_nr+1); + for (i=0; i<totpoly; i++) { + int j=0; + Material *material = give_current_material(ob, mp[i].mat_nr+1); - while (j--) { - int index = *((&mface[i].v1)+j); + for (; j<mp[i].totloop; j++) { + int l_index = mp[i].loopstart + j; + int v_index = mloop[l_index].v; if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) { float c[3]; - index *= 4; + v_index *= 4; /* Apply material color as base vertex color for preview */ - col[i*4+j].a = 255; + col[l_index].a = 255; if (material) { c[0] = material->r; c[1] = material->g; @@ -1643,17 +1651,17 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData c[2] = 0.65f; } /* mix surface color */ - interp_v3_v3v3(c, c, &fcolor[index], fcolor[index+3]); + interp_v3_v3v3(c, c, &fcolor[v_index], fcolor[v_index+3]); - col[i*4+j].r = FTOCHAR(c[2]); - col[i*4+j].g = FTOCHAR(c[1]); - col[i*4+j].b = FTOCHAR(c[0]); + col[l_index].r = FTOCHAR(c[2]); + col[l_index].g = FTOCHAR(c[1]); + col[l_index].b = FTOCHAR(c[0]); } else { - col[i*4+j].a = 255; - col[i*4+j].r = - col[i*4+j].g = - col[i*4+j].b = FTOCHAR(pPoint[index].wetness); + col[l_index].a = 255; + col[l_index].r = + col[l_index].g = + col[l_index].b = FTOCHAR(pPoint[v_index].wetness); } } } @@ -1664,46 +1672,38 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData /* save layer data to output layer */ /* paint layer */ - col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name); + col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name); /* if output layer is lost from a constructive modifier, re-add it */ if (!col && dynamicPaint_outputLayerExists(surface, ob, 0)) - col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name); + col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name); /* apply color */ if (col) { #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - int j = (mface[i].v4) ? 4 : 3; - while (j--) { - int index = *((&mface[i].v1)+j); - index *= 4; - - col[i*4+j].a = FTOCHAR(fcolor[index+3]); - col[i*4+j].r = FTOCHAR(fcolor[index+2]); - col[i*4+j].g = FTOCHAR(fcolor[index+1]); - col[i*4+j].b = FTOCHAR(fcolor[index]); - } + for (i=0; i<totloop; i++) { + int index = mloop[i].v*4; + col[i].a = FTOCHAR(fcolor[index+3]); + col[i].r = FTOCHAR(fcolor[index+2]); + col[i].g = FTOCHAR(fcolor[index+1]); + col[i].b = FTOCHAR(fcolor[index]); } } MEM_freeN(fcolor); /* wet layer */ - col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name2); + col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name2); /* if output layer is lost from a constructive modifier, re-add it */ if (!col && dynamicPaint_outputLayerExists(surface, ob, 1)) - col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name2); + col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name2); /* apply color */ if (col) { #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - int j = (mface[i].v4) ? 4 : 3; - while (j--) { - int index = *((&mface[i].v1)+j); - col[i*4+j].a = 255; - col[i*4+j].r = - col[i*4+j].g = - col[i*4+j].b = FTOCHAR(pPoint[index].wetness); - } + for (i=0; i<totloop; i++) { + int index = mloop[i].v; + col[i].a = 255; + col[i].r = + col[i].g = + col[i].b = FTOCHAR(pPoint[index].wetness); } } } @@ -1712,9 +1712,10 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData int defgrp_index = defgroup_name_index(ob, surface->output_name); MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT); float *weight = (float*)sData->type_data; + /* viewport preview */ if (surface->flags & MOD_DPAINT_PREVIEW) { - /* Save preview results to weight layer, to be + /* Save preview results to weight layer to be * able to share same drawing methods */ DM_update_weight_mcol(ob, result, 0, weight, 0, NULL); } @@ -1773,7 +1774,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData /* make a copy of dm to use as brush data */ if (pmd->brush) { if (pmd->brush->dm) pmd->brush->dm->release(pmd->brush->dm); - pmd->brush->dm = CDDM_copy(result); + pmd->brush->dm = CDDM_copy(result, 0); } return result; @@ -1791,7 +1792,7 @@ void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface) void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) { if (canvas->dm) canvas->dm->release(canvas->dm); - canvas->dm = CDDM_copy(dm); + canvas->dm = CDDM_copy(dm, 0); } /* @@ -1873,6 +1874,10 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene /* Modifier call. Processes dynamic paint modifier step. */ struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm) { + /* For now generate tessfaces in every case + * XXX - move/remove when most of dpaint functions are converted to use bmesh types */ + DM_ensure_tessface(dm); + /* Update canvas data for a new frame */ dynamicPaint_frameUpdate(pmd, scene, ob, dm); @@ -1945,8 +1950,8 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh * TODO: Implement something more accurate / optimized? */ { - int numOfFaces = dm->getNumFaces(dm); - MFace *mface = dm->getFaceArray(dm); + int numOfFaces = dm->getNumTessFaces(dm); + MFace *mface = dm->getTessFaceArray(dm); MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* Get closest edge to that subpixel on UV map */ @@ -2112,8 +2117,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) if (!dm) return setError(canvas, "Canvas mesh not updated."); if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) return setError(canvas, "Can't bake non-\"image sequence\" formats."); - numOfFaces = dm->getNumFaces(dm); - mface = dm->getFaceArray(dm); + numOfFaces = dm->getNumTessFaces(dm); + mface = dm->getTessFaceArray(dm); /* get uv map */ CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname); @@ -2708,7 +2713,7 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) { Material *mat = bMats->mat; - MFace *mface = orcoDm->getFaceArray(orcoDm); + MFace *mface = orcoDm->getTessFaceArray(orcoDm); /* If no material defined, use the one assigned to the mesh face */ if (mat == NULL) { @@ -3040,7 +3045,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, Dy scene->r.subframe = prev_sfra; subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene)); - dm_p = CDDM_copy(brush->dm); + dm_p = CDDM_copy(brush->dm, 0); numOfVerts_p = dm_p->getNumVerts(dm_p); mvert_p = dm_p->getVertArray(dm_p); copy_m4_m4(prev_obmat, ob->obmat); @@ -3145,9 +3150,9 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, Bounds3D mesh_bb = {0}; VolumeGrid *grid = bData->grid; - dm = CDDM_copy(brush->dm); + dm = CDDM_copy(brush->dm, 0); mvert = dm->getVertArray(dm); - mface = dm->getFaceArray(dm); + mface = dm->getTessFaceArray(dm); numOfVerts = dm->getNumVerts(dm); /* Transform collider vertices to global space diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index bb1d20f0187..5ab97549618 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -29,6 +29,10 @@ * \ingroup bke */ +#include <string.h> +#include <limits.h> +#include <math.h> + #include "GL/glew.h" #include "BLI_utildefines.h" @@ -55,24 +59,369 @@ #include "GPU_extensions.h" #include "GPU_material.h" -#include <string.h> -#include <limits.h> -#include <math.h> +/* bmesh */ +#include "BKE_tessmesh.h" +#include "BLI_array.h" +#include "BLI_scanfill.h" + +#include "bmesh.h" +/* end bmesh */ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ + +BMEditMesh *BMEdit_Create(BMesh *bm, int do_tesselate) +{ + BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__); + + tm->bm = bm; + if (do_tesselate) { + BMEdit_RecalcTesselation(tm); + } + + return tm; +} + +BMEditMesh *BMEdit_Copy(BMEditMesh *tm) +{ + BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__); + *tm2 = *tm; + + tm2->derivedCage = tm2->derivedFinal = NULL; + + tm2->bm = BM_Copy_Mesh(tm->bm); + + /*The tesselation is NOT calculated on the copy here, + because currently all the callers of this function use + it to make a backup copy of the BMEditMesh to restore + it in the case of errors in an operation. For perf + reasons, in that case it makes more sense to do the + tesselation only when/if that copy ends up getting + used.*/ + tm2->looptris = NULL; + + tm2->vert_index = NULL; + tm2->edge_index = NULL; + tm2->face_index = NULL; + + return tm2; +} + +static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm) +{ + /* use this to avoid locking pthread for _every_ polygon + * and calling the fill function */ +#define USE_TESSFACE_SPEEDUP + + BMesh *bm = tm->bm; + BMLoop *(*looptris)[3]= NULL; + BLI_array_declare(looptris); + BMIter iter, liter; + BMFace *f; + BMLoop *l; + int i = 0, j; + +#if 0 + /* note, we could be clever and re-use this array but would need to ensure + * its realloced at some point, for now just free it */ + if (tm->looptris) MEM_freeN(tm->looptris); + + /* Use tm->tottri when set, this means no reallocs while transforming, + * (unless scanfill fails), otherwise... */ + /* allocate the length of totfaces, avoid many small reallocs, + * if all faces are tri's it will be correct, quads == 2x allocs */ + BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface); +#else + + /* this means no reallocs for quad dominant models, for */ + if ( (tm->looptris != NULL) && + (tm->tottri != 0) && + /* (totrti <= bm->totface * 2) would be fine for all quads, + * but incase there are some ngons, still re-use the array */ + (tm->tottri <= bm->totface * 3)) + { + looptris = tm->looptris; + } + else { + if (tm->looptris) MEM_freeN(tm->looptris); + BLI_array_reserve(looptris, bm->totface); + } + +#endif + + f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for ( ; f; f=BMIter_Step(&iter)) { + /*don't consider two-edged faces*/ + if (f->len < 3) { + /* do nothing */ + } + +#ifdef USE_TESSFACE_SPEEDUP + + /* no need to ensure the loop order, we know its ok */ + + else if (f->len == 3) { + BLI_array_growone(looptris); + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + for (j=0; l; l=BMIter_Step(&liter), j++) { + looptris[i][j] = l; + } + i += 1; + } + else if (f->len == 4) { + BMLoop *ltmp[4]; + BLI_array_growitems(looptris, 2); + + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + for (j=0; l; l=BMIter_Step(&liter), j++) { + ltmp[j] = l; + } + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[1]; + looptris[i][2] = ltmp[2]; + i += 1; + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[2]; + looptris[i][2] = ltmp[3]; + i += 1; + } + +#endif /* USE_TESSFACE_SPEEDUP */ + + else { + EditVert *v, *lastv=NULL, *firstv=NULL; + EditEdge *e; + EditFace *efa; + int totfilltri; + + BLI_begin_edgefill(); + /*scanfill time*/ + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + for (j=0; l; l=BMIter_Step(&liter), j++) { + /*mark order*/ + BM_SetIndex(l, j); /* set_loop */ + + 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); + + totfilltri = BLI_edgefill(2); + BLI_array_growitems(looptris, totfilltri); + + for (efa = fillfacebase.first; efa; efa=efa->next) { + BMLoop *l1= efa->v1->tmp.p; + BMLoop *l2= efa->v2->tmp.p; + BMLoop *l3= efa->v3->tmp.p; + + if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); } + if (BM_GetIndex(l2) > BM_GetIndex(l3)) { SWAP(BMLoop*, l2, l3); } + if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); } + + looptris[i][0] = l1; + looptris[i][1] = l2; + looptris[i][2] = l3; + i += 1; + } + + BLI_end_edgefill(); + } + } + + tm->tottri = i; + tm->looptris = looptris; + +#undef USE_TESSFACE_SPEEDUP + +} + +void BMEdit_RecalcTesselation(BMEditMesh *em) +{ + BMEdit_RecalcTesselation_intern(em); + + /* commented because editbmesh_build_data() ensures we get tessfaces */ +#if 0 + if (em->derivedFinal && em->derivedFinal == em->derivedCage) { + if (em->derivedFinal->recalcTesselation) + em->derivedFinal->recalcTesselation(em->derivedFinal); + } + else if (em->derivedFinal) { + if (em->derivedCage->recalcTesselation) + em->derivedCage->recalcTesselation(em->derivedCage); + if (em->derivedFinal->recalcTesselation) + em->derivedFinal->recalcTesselation(em->derivedFinal); + } +#endif +} + +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; + } + + 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); + + if (em->bm) + 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 (*polyNos)[3]; + + /*lookup caches; these are rebuilt on dm->RecalcTesselation() + (or when the derivedmesh is created, of course)*/ + BMVert **vtable; + BMEdge **etable; + BMFace **ftable; + + /*private variables, for number of verts/edges/faces + within the above hash/table members*/ + int tv, te, tf; +} EditDerivedBMesh; + +/* BMESH_TODO, since this is not called get functions fail! */ +static void UNUSED_FUNCTION(bmdm_recalc_lookups)(EditDerivedBMesh *bmdm) +{ + BMIter iter; + int a, i; + + int iters[3] = {BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH}; + + BMHeader **iters_table[3] = { + (BMHeader **)bmdm->vtable, + (BMHeader **)bmdm->etable, + (BMHeader **)bmdm->ftable}; + + bmdm->tv = bmdm->tc->bm->totvert; + bmdm->te = bmdm->tc->bm->totedge; + bmdm->tf = bmdm->tc->bm->totface; + + 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++) { + BMHeader **table = iters_table[a]; + BMHeader *ele; + + ele = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL); + for (i=0; ele; ele=BMIter_Step(&iter), i++) { + table[i] = ele; + BM_SetIndex(ele, i); /* set_ok */ + } + } + bmdm->tc->bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE); + +} + +static void emDM_calcNormals(DerivedMesh *UNUSED(dm)) +{ + /* Nothing to do: normals are already calculated and stored on the + BMVerts and BMFaces */ +} + +static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm)) +{ + //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + //bmdm_recalc_lookups(bmdm); +} + 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; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; 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); + 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); @@ -84,20 +433,24 @@ static void emDM_foreachMappedEdge( void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; int i; - if (emdm->vertexCos) { - EditVert *eve; + if (bmdm->vertexCos) { + + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT); - 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]); + 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[BM_GetIndex(eed->v1)], + bmdm->vertexCos[BM_GetIndex(eed->v2)]); } else { - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) + 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); } } @@ -107,28 +460,29 @@ static void emDM_drawMappedEdges( int (*setDrawOptions)(void *userData, int index), void *userData) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; int i; - if (emdm->vertexCos) { - EditVert *eve; + if (bmdm->vertexCos) { - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT); glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { + 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(emdm->vertexCos[(int) eed->v1->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]); + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]); } } glEnd(); } else { glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { + 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); @@ -151,30 +505,31 @@ static void emDM_drawMappedEdgesInterp( void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; int i; - if (emdm->vertexCos) { - EditVert *eve; + if (bmdm->vertexCos) { - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT); glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { + 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(emdm->vertexCos[(int) eed->v1->tmp.l]); + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]); setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]); } } glEnd(); } else { glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { + 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); @@ -188,57 +543,69 @@ static void emDM_drawMappedEdgesInterp( static void emDM_drawUVEdges(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; - MTFace *tf; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; + BMFace *efa; + BMIter iter; glBegin(GL_LINES); - for (efa= emdm->em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BMIter liter; + BMLoop *l; + MLoopUV *lastluv = NULL, *firstluv = NULL; - if (tf && !(efa->h)) { - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); + if (BM_TestHFlag(efa, BM_HIDDEN)) + continue; - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); + 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 (!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]); + 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 emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3]) +static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3]) { + BMIter iter; + BMLoop *l; + int tot = 0; + + zero_v3(cent); + + /*simple (and stupid) median (average) based method :/ */ + if (vertexCos) { - copy_v3_v3(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]); + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]); + tot++; + } } else { - copy_v3_v3(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); + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + add_v3_v3(cent, l->v->co); + tot++; + } } - if (efa->v4) { - mul_v3_fl(cent, 0.25f); - } - else { - mul_v3_fl(cent, 0.33333333333f); - } + if (tot==0) return; + mul_v3_fl(cent, 1.0f/(float)tot); } static void emDM_foreachMappedFaceCenter( @@ -246,24 +613,28 @@ static void emDM_foreachMappedFaceCenter( void (*func)(void *userData, int index, float *co, float *no), void *userData) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - EditFace *efa; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + float (*polyNos)[3] = NULL; + BMFace *efa; + BMIter iter; 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++; + /* ensure for face center calculation */ + if (bmdm->vertexCos) { + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT); + polyNos = bmdm->polyNos; + + BLI_assert(polyNos != NULL); } - 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); + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) { + emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos); + func(userData, i, cent, polyNos ? polyNos[i] : efa->no); } } -/* note, material function is ignored for now. */ static void emDM_drawMappedFaces( DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), @@ -271,8 +642,11 @@ static void emDM_drawMappedFaces( int (*compareDrawOptions)(void *userData, int cur_index, int next_index), void *userData, int UNUSED(useColors)) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMFace *efa; + struct BMLoop *(*looptris)[3]= bmdm->tc->looptris; + const int tottri= bmdm->tc->tottri; + const int lasttri= tottri - 1; /* compare agasint this a lot */ int i, draw, flush; const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */ @@ -285,21 +659,25 @@ static void emDM_drawMappedFaces( /* currently unused -- each original face is handled separately */ (void)compareDrawOptions; - if (emdm->vertexCos) { + if (bmdm->vertexCos) { /* add direct access */ - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - float (*faceNos)[3]= emdm->faceNos; - EditVert *eve; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + float (*polyNos)[3]= bmdm->polyNos; + // int *triPolyMap= bmdm->triPolyMap; + + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT | BM_FACE); - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; + for (i=0; i < tottri; i++) { + BMLoop **l = looptris[i]; + int drawSmooth; - 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); + efa = l[0]->f; + drawSmooth= BM_TestHFlag(efa, BM_SMOOTH); + + draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth); if (draw) { - const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES; + const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ if (draw==2) { /* enabled with stipple */ if (poly_prev != GL_ZERO) glEnd(); @@ -312,49 +690,43 @@ static void emDM_drawMappedFaces( if (skip_normals) { if (poly_type != poly_prev) { if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]); } else { const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT; if (shade_type != shade_prev) { if (poly_prev != GL_ZERO) glEnd(); glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */ - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - else if (poly_type != poly_prev) { + if (poly_type != poly_prev) { if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } if (!drawSmooth) { - glNormal3fv(faceNos[i]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + glNormal3fv(polyNos[BM_GetIndex(efa)]); + glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]); } else { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - if (poly_type == GL_QUADS) { - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } + glNormal3fv(vertexNos[BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]); + glNormal3fv(vertexNos[BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]); + glNormal3fv(vertexNos[BM_GetIndex(l[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]); } } flush= (draw==2); - if (!skip_normals && !flush && efa->next) - flush|= efa->mat_nr != efa->next->mat_nr; + if (!skip_normals && !flush && (i != lasttri)) + flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */ if (flush) { glEnd(); @@ -366,11 +738,18 @@ static void emDM_drawMappedFaces( } } 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); + BM_ElemIndex_Ensure(bmdm->tc->bm, BM_FACE); + + for (i=0; i < tottri; i++) { + BMLoop **l = looptris[i]; + int drawSmooth; + + efa = l[0]->f; + drawSmooth= BM_TestHFlag(efa, BM_SMOOTH); + + draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth); if (draw) { - const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES; + const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ if (draw==2) { /* enabled with stipple */ if (poly_prev != GL_ZERO) glEnd(); @@ -383,49 +762,44 @@ static void emDM_drawMappedFaces( if (skip_normals) { if (poly_type != poly_prev) { if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - glVertex3fv(efa->v1->co); - glVertex3fv(efa->v2->co); - glVertex3fv(efa->v3->co); - if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co); + glVertex3fv(l[0]->v->co); + glVertex3fv(l[1]->v->co); + glVertex3fv(l[2]->v->co); } else { const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT; if (shade_type != shade_prev) { if (poly_prev != GL_ZERO) glEnd(); glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */ - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - else if (poly_type != poly_prev) { + if (poly_type != poly_prev) { if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ } if (!drawSmooth) { - glNormal3fv(efa->n); - glVertex3fv(efa->v1->co); - glVertex3fv(efa->v2->co); - glVertex3fv(efa->v3->co); - if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co); + glNormal3fv(efa->no); + glVertex3fv(l[0]->v->co); + glVertex3fv(l[1]->v->co); + glVertex3fv(l[2]->v->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 (poly_type == GL_QUADS) { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } + 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); } } flush= (draw==2); - if (!skip_normals && !flush && efa->next) - flush|= efa->mat_nr != efa->next->mat_nr; + if (!skip_normals && !flush && (i != lasttri)) { + flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */ + } if (flush) { glEnd(); @@ -441,177 +815,219 @@ static void emDM_drawMappedFaces( if (poly_prev != GL_ZERO) glEnd(); } +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 emDM_drawFacesTex_common( DerivedMesh *dm, - int (*drawParams)(MTFace *tface, int has_mcol, int matnr), + int (*drawParams)(MTFace *tface, int has_vcol, int matnr), int (*drawParamsMapped)(void *userData, int index), int (*compareDrawOptions)(void *userData, int cur_index, int next_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; + 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; + 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); (void) compareDrawOptions; + 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); + BM_ElemIndex_Ensure(bm, BM_FACE); + if (vertexCos) { - EditVert *eve; + BM_ElemIndex_Ensure(bm, BM_VERT); + + 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;*/ /*UNUSED*/ + int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH); + int flag; - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; + efa = ls[0]->f; - 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 (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(tf, (mcol != NULL), efa->mat_nr); + flag= drawParams(&mtf, has_vcol, efa->mat_nr); else if (drawParamsMapped) - flag= drawParamsMapped(userData, i); + flag= drawParamsMapped(userData, BM_GetIndex(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 (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } - else { + if (!has_vcol) { glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); } - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); if (!drawSmooth) { - glNormal3fv(emdm->faceNos[i]); + glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]); - if (tf) glTexCoord2fv(tf->uv[0]); - if (cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); - if (tf) glTexCoord2fv(tf->uv[1]); - if (cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + glTexCoord2fv(luv[0]->uv); + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]); - if (tf) glTexCoord2fv(tf->uv[2]); - if (cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + glTexCoord2fv(luv[1]->uv); + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]); - 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]); - } + glTexCoord2fv(luv[2]->uv); + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]); } 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]); - } + 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[BM_GetIndex(ls[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]); + + glTexCoord2fv(luv[1]->uv); + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]); + + glTexCoord2fv(luv[2]->uv); + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]); } - glEnd(); } } + 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); + BM_ElemIndex_Ensure(bm, BM_VERT); + + 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;*/ /*UNUSED*/ + 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(tf, (mcol != NULL), efa->mat_nr); + flag= drawParams(&mtf, has_vcol, efa->mat_nr); else if (drawParamsMapped) - flag= drawParamsMapped(userData, i); + flag= drawParamsMapped(userData, BM_GetIndex(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 (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } - else { + if (!has_vcol) { glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); } - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + glBegin(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); - } + 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 { - 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); - } + 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(); } @@ -621,7 +1037,7 @@ static void emDM_drawFacesTex_common( static void emDM_drawFacesTex( DerivedMesh *dm, - int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr), + int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr), int (*compareDrawOptions)(void *userData, int cur_index, int next_index), void *userData) { @@ -643,54 +1059,56 @@ static void emDM_drawMappedFacesGLSL( 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= {{{0}}}; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMEditMesh *em = bmdm->tc; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMFace *efa; + BMLoop **ltri; + DMVertexAttribs attribs; GPUVertexAttribs gattribs; - /* int tfoffset; */ /* UNUSED */ - int i, b, matnr, new_matnr, dodraw /* , layer */ /* UNUSED */; + + int i, b, matnr, new_matnr, dodraw; dodraw = 0; matnr = -1; - /* layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); */ /* UNUSED */ - /* tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; */ /* UNUSED */ + memset(&attribs, 0, sizeof(attribs)); /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ glShadeModel(GL_SMOOTH); + BM_ElemIndex_Ensure(bm, BM_VERT | BM_FACE); - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - -#define PASSATTRIB(efa, eve, vert) { \ +#define PASSATTRIB(loop, eve, vert) { \ if (attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ + float *orco = attribs.orco.array[BM_GetIndex(eve)]; \ 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]); \ + MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \ } \ 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); \ + MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\ + 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); \ + glVertexAttrib3fvARB(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)) + for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) { + int drawSmooth; + + efa = ltri[0]->f; + drawSmooth= BM_TestHFlag(efa, BM_SMOOTH); + + if (setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa))) continue; new_matnr = efa->mat_nr + 1; @@ -701,70 +1119,52 @@ static void emDM_drawMappedFacesGLSL( } if (dodraw) { - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + glBegin(GL_TRIANGLES); if (!drawSmooth) { - if (vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); + if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]); + else glNormal3fv(efa->no); - PASSATTRIB(efa, efa->v1, 0); - if (vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); + PASSATTRIB(ltri[0], ltri[0]->v, 0); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + else glVertex3fv(ltri[0]->v->co); - PASSATTRIB(efa, efa->v2, 1); - if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + else glVertex3fv(ltri[1]->v->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); - } + PASSATTRIB(ltri[2], ltri[2]->v, 2); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); + else glVertex3fv(ltri[2]->v->co); } else { - PASSATTRIB(efa, efa->v1, 0); + PASSATTRIB(ltri[0], ltri[0]->v, 0); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); } else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); + glNormal3fv(ltri[0]->v->no); + glVertex3fv(ltri[0]->v->co); } - PASSATTRIB(efa, efa->v2, 1); + PASSATTRIB(ltri[1], ltri[1]->v, 1); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); } else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); + glNormal3fv(ltri[1]->v->no); + glVertex3fv(ltri[1]->v->co); } - PASSATTRIB(efa, efa->v3, 2); + PASSATTRIB(ltri[2], ltri[2]->v, 2); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); } 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); - } + glNormal3fv(ltri[2]->v->no); + glVertex3fv(ltri[2]->v->co); } } glEnd(); @@ -785,12 +1185,13 @@ static void emDM_drawMappedFacesMat( void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(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; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMEditMesh *em = bmdm->tc; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMFace *efa; + BMLoop **ltri; DMVertexAttribs attribs= {{{0}}}; GPUVertexAttribs gattribs; int i, b, matnr, new_matnr; @@ -800,29 +1201,22 @@ static void emDM_drawMappedFacesMat( /* 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++; + BM_ElemIndex_Ensure(bm, BM_VERT); -#define PASSATTRIB(efa, eve, vert) { \ +#define PASSATTRIB(loop, eve, vert) { \ if (attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ - if (attribs.orco.glTexco) \ - glTexCoord3fv(orco); \ - else \ - glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + float *orco = attribs.orco.array[BM_GetIndex(eve)]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ } \ for (b = 0; b < attribs.tottface; b++) { \ - MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ - if (attribs.tface[b].glTexco) \ - glTexCoord2fv(_tf->uv[vert]); \ - else \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \ + MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \ } \ 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); \ + MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\ + 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]; \ @@ -830,11 +1224,14 @@ static void emDM_drawMappedFacesMat( } \ } - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth= (efa->flag & ME_SMOOTH); + for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) { + int drawSmooth; + + efa = ltri[0]->f; + drawSmooth = BM_TestHFlag(efa, BM_SMOOTH); /* face hiding */ - if (setFace && !setFace(userData, i)) + if (setFace && !setFace(userData, BM_GetIndex(efa))) continue; /* material */ @@ -845,70 +1242,53 @@ static void emDM_drawMappedFacesMat( } /* face */ - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + glBegin(GL_TRIANGLES); if (!drawSmooth) { - if (vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); + if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]); + else glNormal3fv(efa->no); - PASSATTRIB(efa, efa->v1, 0); - if (vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); + PASSATTRIB(ltri[0], ltri[0]->v, 0); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + else glVertex3fv(ltri[0]->v->co); - PASSATTRIB(efa, efa->v2, 1); - if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + else glVertex3fv(ltri[1]->v->co); - PASSATTRIB(efa, efa->v3, 2); - if (vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - else glVertex3fv(efa->v3->co); + PASSATTRIB(ltri[2], ltri[2]->v, 2); + if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); + else glVertex3fv(ltri[2]->v->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); + PASSATTRIB(ltri[0], ltri[0]->v, 0); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); } else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); + glNormal3fv(ltri[0]->v->no); + glVertex3fv(ltri[0]->v->co); } - PASSATTRIB(efa, efa->v2, 1); + PASSATTRIB(ltri[1], ltri[1]->v, 1); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); } else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); + glNormal3fv(ltri[1]->v->no); + glVertex3fv(ltri[1]->v->co); } - PASSATTRIB(efa, efa->v3, 2); + PASSATTRIB(ltri[2], ltri[2]->v, 2); if (vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); } 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); - } + glNormal3fv(ltri[2]->v->no); + glVertex3fv(ltri[2]->v->co); } } glEnd(); @@ -918,14 +1298,16 @@ static void emDM_drawMappedFacesMat( static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; 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); + 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); @@ -938,236 +1320,267 @@ static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) } static int emDM_getNumVerts(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; - return BLI_countlist(&emdm->em->verts); + return bmdm->tc->bm->totvert; } static int emDM_getNumEdges(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; - return BLI_countlist(&emdm->em->edges); + return bmdm->tc->bm->totedge; } -static int emDM_getNumFaces(DerivedMesh *dm) +static int emDM_getNumTessFaces(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; - return BLI_countlist(&emdm->em->faces); + return bmdm->tc->tottri; } -static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) +static int emDM_getNumLoops(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; - 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); - } - } + return bmdm->tc->bm->totloop; } -static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) +static int emDM_getNumPolys(DerivedMesh *dm) { - EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first; - int i; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; - for (i = 0; i < index; ++i) ev = ev->next; + return bmdm->tc->bm->totface; +} +static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r) +{ copy_v3_v3(vert_r->co, ev->co); normal_float_to_short_v3(vert_r->no, ev->no); - /* TODO what to do with vert_r->flag? */ - vert_r->bweight = (unsigned char) (ev->bweight*255.0f); + vert_r->flag = BM_Vert_Flag_To_MEFlag(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 emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) +{ + BMVert *ev; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) { + printf("error in emDM_getVert.\n"); + return; + } + + ev = ((EditDerivedBMesh *)dm)->vtable[index]; + bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r); } 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; + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *e; - for (i = 0; i < index; ++i) ee = ee->next; + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) { + printf("error in emDM_getEdge.\n"); + return; + } - 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 + e = bmdm->etable[index]; - /* 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; - } + 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 = BM_Edge_Flag_To_MEFlag(e); + + edge_r->v1 = BM_GetIndex(e->v1); + edge_r->v2 = BM_GetIndex(e->v2); } -static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r) +static void emDM_getTessFace(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; + /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ + BMFace *ef; + BMLoop **l; - for (i = 0; i < index; ++i) ef = ef->next; + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) { + printf("error in emDM_getTessFace.\n"); + return; + } - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; + l = ((EditDerivedBMesh *)dm)->tc->looptris[index]; - /* 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; + ef = l[0]->f; - 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; - } - } + face_r->mat_nr = (unsigned char) ef->mat_nr; + face_r->flag = BM_Face_Flag_To_MEFlag(ef); - test_index_face(face_r, NULL, 0, ef->v4?4:3); + face_r->v1 = BM_GetIndex(l[0]->v); + face_r->v2 = BM_GetIndex(l[1]->v); + face_r->v3 = BM_GetIndex(l[2]->v); + face_r->v4 = 0; + + test_index_face(face_r, NULL, 0, 3); } static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *ev = emdm->em->verts.first; - int i; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMVert *ev; + BMIter iter; - 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); + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for ( ; ev; ev = BMIter_Step(&iter), ++vert_r) { + copy_v3_v3(vert_r->co, ev->co); normal_float_to_short_v3(vert_r->no, ev->no); - /* TODO what to do with vert_r->flag? */ - vert_r->flag = 0; - vert_r->bweight = (unsigned char) (ev->bweight*255.0f); + vert_r->flag = BM_Vert_Flag_To_MEFlag(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 emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) { - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditEdge *ee = em->edges.first; - EditVert *ev; - int i; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *ee; + BMIter iter; + int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT); + int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE); + + BM_ElemIndex_Ensure(bm, BM_VERT); + + ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); + for ( ; ee; ee=BMIter_Step(&iter), edge_r++) { + if (has_bweight) { + edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f); + } - /* 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 + if (has_crease) { + edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f); + } - edge_r->v1 = (int)ee->v1->tmp.l; - edge_r->v2 = (int)ee->v2->tmp.l; + edge_r->flag = BM_Edge_Flag_To_MEFlag(ee); + + edge_r->v1 = BM_GetIndex(ee->v1); + edge_r->v2 = BM_GetIndex(ee->v2); } } -static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) +static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r) { - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditFace *ef = em->faces.first; - EditVert *ev; + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMFace *ef; + BMLoop **l; 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; + BM_ElemIndex_Ensure(bm, BM_VERT); + + for (i=0; i<bmdm->tc->tottri; i++, face_r++) { + l = bmdm->tc->looptris[i]; + ef = l[0]->f; + + face_r->mat_nr = (unsigned char) ef->mat_nr; + + face_r->flag = BM_Face_Flag_To_MEFlag(ef); + + face_r->v1 = BM_GetIndex(l[0]->v); + face_r->v2 = BM_GetIndex(l[1]->v); + face_r->v3 = BM_GetIndex(l[2]->v); + face_r->v4 = 0; + + test_index_face(face_r, NULL, 0, 3); + } +} + - for ( ; ef; ef = ef->next, ++face_r) { - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; +static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r) +{ + /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMIter iter, liter; + BMFace *f; + BMLoop *l; + + BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE); + + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + loop_r->v = BM_GetIndex(l->v); + loop_r->e = BM_GetIndex(l->e); + loop_r++; + } + } +} - 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; +static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r) +{ + /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMIter iter; + BMFace *f; + int i; + + i = 0; + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + poly_r->flag = BM_Face_Flag_To_MEFlag(f); + poly_r->loopstart = i; + poly_r->totloop = f->len; + poly_r->mat_nr = f->mat_nr; - test_index_face(face_r, NULL, 0, ef->v4?4:3); + poly_r++; + i += f->len; } } -static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) +static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - EditFace *efa; - char *data, *emdata; + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMFace *efa; + char *data, *bmdata; void *datalayer; - int index, size; + int index /*, offset*/ /*UNUSED */, size, i; - datalayer = DM_get_face_data_layer(dm, type); + datalayer = DM_get_tessface_data_layer(dm, type); if (datalayer) return datalayer; - /* layers are store per face for editmesh, we convert to a temporary + /* 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(&em->fdata, type); + index = CustomData_get_layer_index(&bm->pdata, type); if (index != -1) { - /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */ + /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */ size = CustomData_sizeof(type); - DM_add_face_layer(dm, type, CD_CALLOC, NULL); + 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_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); + 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); } } } @@ -1175,120 +1588,194 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) return datalayer; } +static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) +{ + EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; + int i; + + i= 0; + BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) { + if (emdm->vertexCos) { + copy_v3_v3(cos_r[i], emdm->vertexCos[i]); + } + else { + copy_v3_v3(cos_r[i], eve->co); + } + + i++; + } +} + static void emDM_release(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm; if (DM_release(dm)) { - if (emdm->vertexCos) { - MEM_freeN(emdm->vertexCos); - MEM_freeN(emdm->vertexNos); - MEM_freeN(emdm->faceNos); + if (bmdm->vertexCos) { + MEM_freeN(bmdm->vertexCos); + MEM_freeN(bmdm->vertexNos); + MEM_freeN(bmdm->polyNos); } - MEM_freeN(emdm); + if (bmdm->vtable) MEM_freeN(bmdm->vtable); + if (bmdm->etable) MEM_freeN(bmdm->etable); + if (bmdm->ftable) MEM_freeN(bmdm->ftable); + + MEM_freeN(bmdm); } } -DerivedMesh *editmesh_get_derived( - EditMesh *em, - float (*vertexCos)[3]) +static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm) { - EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm"); + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; - DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts), - BLI_countlist(&em->edges), BLI_countlist(&em->faces)); + return &bmdm->tc->bm->vdata; +} - emdm->dm.getMinMax = emDM_getMinMax; +static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; - emdm->dm.getNumVerts = emDM_getNumVerts; - emdm->dm.getNumEdges = emDM_getNumEdges; - emdm->dm.getNumFaces = emDM_getNumFaces; + return &bmdm->tc->bm->edata; +} - emdm->dm.getVertCos = emDM_getVertCos; +static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; - 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; + return &bmdm->dm.faceData; +} - emdm->dm.foreachMappedVert = emDM_foreachMappedVert; - emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; - emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; +static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; - 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.drawMappedFacesMat = emDM_drawMappedFacesMat; - emdm->dm.drawUVEdges = emDM_drawUVEdges; + return &bmdm->tc->bm->ldata; +} - emdm->dm.release = emDM_release; +static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->pdata; +} - emdm->em = em; - emdm->vertexCos = vertexCos; - if (CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { - EditVert *eve; +DerivedMesh *getEditDerivedBMesh( + BMEditMesh *em, + Object *UNUSED(ob), + float (*vertexCos)[3]) +{ + EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__); + BMesh *bm = em->bm; + + bmdm->tc = em; + + DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert, + em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface); + + CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0); + + bmdm->dm.getVertCos = emDM_getVertCos; + bmdm->dm.getMinMax = emDM_getMinMax; + + bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout; + bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout; + bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout; + bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout; + bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout; + + bmdm->dm.getNumVerts = emDM_getNumVerts; + bmdm->dm.getNumEdges = emDM_getNumEdges; + bmdm->dm.getNumTessFaces = emDM_getNumTessFaces; + bmdm->dm.getNumLoops = emDM_getNumLoops; + bmdm->dm.getNumPolys = emDM_getNumPolys; + + bmdm->dm.getVert = emDM_getVert; + bmdm->dm.getEdge = emDM_getEdge; + bmdm->dm.getTessFace = emDM_getTessFace; + bmdm->dm.copyVertArray = emDM_copyVertArray; + bmdm->dm.copyEdgeArray = emDM_copyEdgeArray; + bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray; + bmdm->dm.copyLoopArray = emDM_copyLoopArray; + bmdm->dm.copyPolyArray = emDM_copyPolyArray; + + bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray; + + bmdm->dm.calcNormals = emDM_calcNormals; + bmdm->dm.recalcTesselation = emDM_recalcTesselation; + + bmdm->dm.foreachMappedVert = emDM_foreachMappedVert; + bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; + bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; + + bmdm->dm.drawEdges = emDM_drawEdges; + bmdm->dm.drawMappedEdges = emDM_drawMappedEdges; + bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; + bmdm->dm.drawMappedFaces = emDM_drawMappedFaces; + bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; + bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; + bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat; + bmdm->dm.drawFacesTex = emDM_drawFacesTex; + bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; + bmdm->dm.drawUVEdges = emDM_drawUVEdges; + + bmdm->dm.release = emDM_release; + + bmdm->vertexCos = vertexCos; + + if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) { + BMIter iter; + BMVert *eve; int i; - DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL); + DM_add_vert_layer(&bmdm->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)); + 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) { - EditVert *eve; - EditFace *efa; - int totface = BLI_countlist(&em->faces); + BMFace *efa; + BMVert *eve; + BMIter fiter; + BMIter viter; int i; - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; + BM_ElemIndex_Ensure(bm, BM_VERT); - emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno"); - emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno"); + bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno"); + bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno"); - 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]; + i = 0; + BM_ITER(efa, &fiter, bm, BM_FACES_OF_MESH, NULL) { + BM_SetIndex(efa, i); /* set_inline */ + BM_Face_UpdateNormal_VertexCos(bm, efa, bmdm->polyNos[i], vertexCos); + i++; + } + bm->elem_index_dirty &= ~BM_FACE; - 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); + eve=BMIter_New(&viter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&viter), i++) { + float *no = bmdm->vertexNos[i]; + BM_ITER(efa, &fiter, bm, BM_FACES_OF_VERT, eve) { + add_v3_v3(no, bmdm->polyNos[BM_GetIndex(efa)]); } - 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.0f) { - normalize_v3_v3(no, vertexCos[i]); + if (normalize_v3(no)==0.0) { + copy_v3_v3(no, vertexCos[i]); + normalize_v3(no); } } } - return (DerivedMesh*) emdm; -} + //bmdm_recalc_lookups(bmdm); + return (DerivedMesh*) bmdm; +} diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index dcb8533d7a1..69d860bfb08 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -553,7 +553,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa } if(surface_vel) { - MFace *mface = CDDM_get_face(surmd->dm, nearest.index); + MFace *mface = CDDM_get_tessface(surmd->dm, nearest.index); copy_v3_v3(surface_vel, surmd->v[mface->v1].co); add_v3_v3(surface_vel, surmd->v[mface->v2].co); diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index cdb2b194b43..587fe75031f 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -85,9 +85,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/key.c b/source/blender/blenkernel/intern/key.c index b2385a5cdb8..2f05d14bdd5 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -56,6 +56,7 @@ #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 "BKE_deform.h" @@ -92,6 +93,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 @@ -114,6 +129,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) { @@ -172,6 +189,34 @@ 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); + + keyn->adt = NULL; + + 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) { @@ -495,18 +540,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) { copy_v3_v3(co[a], eve->co); + a++; + } *freedata= (char*)co; return (char*)co; @@ -1000,8 +1048,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, defgrp_index= 0; /* no vgroup string set? */ @@ -1013,8 +1062,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; @@ -1033,8 +1082,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) { weights[i]= defvert_find_weight(dvert, defgrp_index); @@ -1451,7 +1501,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/library.c b/source/blender/blenkernel/intern/library.c index 795cf75820f..8a615b379e8 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -808,7 +808,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 cba92e7a14c..772851cef7e 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -41,6 +41,7 @@ #include "DNA_key_types.h" #include "DNA_meshdata_types.h" #include "DNA_ipo_types.h" +#include "DNA_customdata_types.h" #include "BLI_utildefines.h" #include "BLI_blenlib.h" @@ -48,9 +49,11 @@ #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_edgehash.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,24 +67,297 @@ #include "BKE_curve.h" /* -- */ #include "BKE_object.h" +#include "BKE_tessmesh.h" +#include "BLI_edgehash.h" -#ifdef USE_BMESH_FORWARD_COMPAT +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_math.h" #include "BLI_array.h" -#endif +#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 const 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: + return "CustomData Layer Count Mismatch"; + default: + return "Mesh Comparison Code Unknown"; + } +} + +/*thresh is threshold for comparing vertices, uvs, vertex colors, + weights, etc.*/ +static 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*/ +const 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) { + const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + + const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + const int totcol_tessface = CustomData_number_of_layers(&me->fdata, CD_MCOL); + + if (tottex_tessface != tottex_original || + totcol_tessface != totcol_original ) + { + 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); + + /* note: this warning may be un-called for if we are inirializing the mesh for the + * first time from bmesh, rather then giving a warning about this we could be smarter + * and check if there was any data to begin with, for now just print the warning with + * some info to help troubleshoot whats going on - campbell */ + printf("%s: warning! Tesselation uvs or vcol data got out of sync, " + "had to reset!\n CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", + __func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original); + } } +/* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or + * mloopcol and mcol) have the same relative active/render/clone/mask indices. + * + * note that for undo mesh data we want to skip 'ensure_tess_cd' call since + * we dont want to store memory for tessface when its only used for older + * versions of the mesh. - campbell*/ +static void mesh_update_linked_customdata(Mesh *me, const short do_ensure_tess_cd) +{ + if (me->edit_btmesh) + BMEdit_UpdateLinkedCustomData(me->edit_btmesh); + + if (do_ensure_tess_cd) { + mesh_ensure_tesselation_customdata(me); + } -void mesh_update_customdata_pointers(Mesh *me) + CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata); +} + +void mesh_update_customdata_pointers(Mesh *me, const short do_ensure_tess_cd) { + mesh_update_linked_customdata(me, do_ensure_tess_cd); + 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); @@ -91,6 +367,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 @@ -118,14 +401,17 @@ 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); 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; @@ -135,7 +421,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) @@ -194,6 +480,7 @@ Mesh *copy_mesh(Mesh *me) { Mesh *men; MTFace *tface; + MTexPoly *txface; int a, i; men= copy_libblock(&me->id); @@ -207,7 +494,9 @@ 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); - mesh_update_customdata_pointers(men); + 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, TRUE); /* ensure indirect linked data becomes lib-extern */ for(i=0; i<me->fdata.totlayer; i++) { @@ -220,8 +509,18 @@ Mesh *copy_mesh(Mesh *me) } } + 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->edit_mesh= NULL; + men->edit_btmesh= NULL; men->bb= MEM_dupallocN(men->bb); @@ -231,21 +530,50 @@ 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(ob, allocsize); + + BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p set_shapekey=%i", me, ob, 1); + + return bm; +} + static void expand_local_mesh(Mesh *me) { id_lib_extern((ID *)me->texcomesh); if(me->mtface) { - MTFace *tface; int a, i; + for(i=0; i<me->pdata.totlayer; i++) { + if(me->pdata.layers[i].type == CD_MTEXPOLY) { + 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) { + if(txface->tpage) { + id_lib_extern((ID *)txface->tpage); + } + } + } + } + } + for(i=0; i<me->fdata.totlayer; i++) { if(me->fdata.layers[i].type == CD_MTFACE) { - tface= (MTFace*)me->fdata.layers[i].data; + MTFace *tface= (MTFace*)me->fdata.layers[i].data; for(a=0; a<me->totface; a++, tface++) { + /* special case: ima always local immediately */ if(tface->tpage) { - id_lib_extern((ID *)tface->tpage); + if(tface->tpage) { + id_lib_extern((ID *)tface->tpage); + } } } } @@ -572,13 +900,17 @@ static void mfaces_strip_loose(MFace *mface, int *totface) } /* Create edges based on known verts and faces */ -static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface, +static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *allloop, + MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly, int old, MEdge **alledge, int *_totedge) { + MPoly *mpoly; + MLoop *mloop; MFace *mface; MEdge *medge; + EdgeHash *hash = BLI_edgehash_new(); struct edgesort *edsort, *ed; - int a, totedge=0, final=0; + int a, b, totedge=0, final=0; /* we put all edges in array, sort them, and detect doubles that way */ @@ -650,6 +982,26 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED( medge->flag |= ME_EDGERENDER; MEM_freeN(edsort); + + /*set edge members of mloops*/ + medge= *alledge; + for (a=0; a<*_totedge; a++, medge++) { + BLI_edgehash_insert(hash, medge->v1, medge->v2, SET_INT_IN_POINTER(a)); + } + + mpoly = allpoly; + for (a=0; a<totpoly; a++, mpoly++) { + mloop = allloop + mpoly->loopstart; + for (b=0; b<mpoly->totloop; b++) { + int v1, v2; + + v1 = mloop[b].v; + v2 = ME_POLY_LOOP_NEXT(mloop, mpoly, b)->v; + mloop[b].e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(hash, v1, v2)); + } + } + + BLI_edgehash_free(hash, NULL); } void make_edges(Mesh *me, int old) @@ -657,7 +1009,7 @@ void make_edges(Mesh *me, int old) MEdge *medge; int totedge=0; - make_edges_mdata(me->mvert, me->mface, me->totvert, me->totface, old, &medge, &totedge); + make_edges_mdata(me->mvert, me->mface, me->mloop, me->mpoly, me->totvert, me->totface, me->totloop, me->totpoly, old, &medge, &totedge); if(totedge==0) { /* flag that mesh has edges */ me->medge = medge; @@ -753,31 +1105,42 @@ void mball_to_mesh(ListBase *lb, Mesh *me) } make_edges(me, 0); // all edges - } + + + /* BMESH_TODO - low priority, should make polygons instead */ + convert_mfaces_to_mpolys(me); + + mesh_update_customdata_pointers(me, TRUE); + } } /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* return non-zero on error */ int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert, - MEdge **alledge, int *totedge, MFace **allface, int *totface) + MEdge **alledge, int *totedge, MFace **allface, MLoop **allloop, MPoly **allpoly, + int *totface, int *totloop, int *totpoly) { return nurbs_to_mdata_customdb(ob, &ob->disp, - allvert, totvert, alledge, totedge, allface, totface); + allvert, totvert, alledge, totedge, allface, allloop, allpoly, totface, totloop, totpoly); } /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* use specified dispbase */ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *_totvert, - MEdge **alledge, int *_totedge, MFace **allface, int *_totface) + MEdge **alledge, int *_totedge, MFace **allface, MLoop **allloop, MPoly **allpoly, + int *_totface, int *_totloop, int *_totpoly) { DispList *dl; Curve *cu; MVert *mvert; MFace *mface; + MPoly *mpoly; + MLoop *mloop; float *data; int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0; int p1, p2, p3, p4, *index; int conv_polys= 0; + int i, j; cu= ob->data; @@ -816,7 +1179,9 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert"); *allface= mface= MEM_callocN(sizeof (MFace) * totvlak, "nurbs_init mface"); - + *allloop = mloop = MEM_callocN(sizeof(MLoop) * totvlak * 4, "nurbs_init mloop"); + *allpoly = mpoly = MEM_callocN(sizeof(MPoly) * totvlak * 4, "nurbs_init mloop"); + /* verts and faces */ vertcount= 0; @@ -954,11 +1319,35 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int dl= dl->next; } - + + mface= *allface; + j = 0; + for (i=0; i<totvert; i++, mpoly++, mface++) { + int k; + + if (!mface->v3) { + mpoly--; + i--; + continue; + } + + if (mface >= *allface + totvlak) + break; + + mpoly->flag |= mface->flag & ME_SMOOTH; + mpoly->loopstart= j; + mpoly->totloop= mface->v4 ? 4 : 3; + for (k=0; k<mpoly->totloop; k++, mloop++, j++) { + mloop->v = (&mface->v1)[k]; + } + } + + *_totpoly= i; + *_totloop= j; *_totvert= totvert; *_totface= totvlak; - make_edges_mdata(*allvert, *allface, totvert, totvlak, 0, alledge, _totedge); + make_edges_mdata(*allvert, *allface, *allloop, *allpoly, totvert, totvlak, *_totloop, *_totpoly, 0, alledge, _totedge); mfaces_strip_loose(*allface, _totface); return 0; @@ -975,12 +1364,14 @@ void nurbs_to_mesh(Object *ob) MVert *allvert= NULL; MEdge *alledge= NULL; MFace *allface= NULL; - int totvert, totedge, totface; + MLoop *allloop = NULL; + MPoly *allpoly = NULL; + int totvert, totedge, totface, totloop, totpoly; cu= ob->data; if (dm == NULL) { - if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { + if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) { /* Error initializing */ return; } @@ -990,15 +1381,19 @@ void nurbs_to_mesh(Object *ob) me->totvert= totvert; me->totface= totface; me->totedge= totedge; + me->totloop = totloop; + me->totpoly = totpoly; me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface); + me->mloop= CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop); + me->mpoly= CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly); - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + mesh_calc_normals_mapping(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL); } else { me= add_mesh("Mesh"); - DM_to_mesh(dm, me); + DM_to_mesh(dm, me, ob); } me->totcol= cu->totcol; @@ -1059,10 +1454,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; @@ -1225,10 +1620,16 @@ void mesh_to_curve(Scene *scene, Object *ob) void mesh_delete_material_index(Mesh *me, short index) { - MFace *mf; int i; - for (i=0, mf=me->mface; i<me->totface; i++, mf++) { + for (i=0; i<me->totpoly; i++) { + MPoly *mp = &((MPoly*) me->mpoly)[i]; + if (mp->mat_nr && mp->mat_nr>=index) + mp->mat_nr--; + } + + for (i=0; i<me->totface; i++) { + MFace *mf = &((MFace*) me->mface)[i]; if (mf->mat_nr && mf->mat_nr>=index) mf->mat_nr--; } @@ -1239,6 +1640,16 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) Mesh *me = meshOb->data; int i; + for (i=0; i<me->totpoly; i++) { + MPoly *mp = &((MPoly*) me->mpoly)[i]; + + if (enableSmooth) { + mp->flag |= ME_SMOOTH; + } else { + mp->flag &= ~ME_SMOOTH; + } + } + for (i=0; i<me->totface; i++) { MFace *mf = &((MFace*) me->mface)[i]; @@ -1250,7 +1661,136 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) } } -void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3]) +void mesh_calc_normals_mapping(MVert *mverts, int numVerts, + MLoop *mloop, MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3], + MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]) +{ + mesh_calc_normals_mapping_ex(mverts, numVerts, mloop, mpolys, + numLoops, numPolys, polyNors_r, mfaces, numFaces, + origIndexFace, faceNors_r, TRUE); +} + +void mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts, + MLoop *mloop, MPoly *mpolys, + int numLoops, int numPolys, float (*polyNors_r)[3], + MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3], + const short only_face_normals) +{ + float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r; + int i; + MFace *mf; + MPoly *mp; + + if (numPolys == 0) { + return; + } + + /* if we are not calculating verts and no verts were passes thene we have nothign to do */ + if ((only_face_normals == TRUE) && (polyNors_r == NULL) && (faceNors_r == NULL)) { + printf("%s: called with nothing to do\n", __func__); + return; + } + + if (!pnors) pnors = MEM_callocN(sizeof(float) * 3 * numPolys, "poly_nors mesh.c"); + /* if (!fnors) fnors = MEM_callocN(sizeof(float) * 3 * numFaces, "face nors mesh.c"); */ /* NO NEED TO ALLOC YET */ + + + if (only_face_normals == FALSE) { + /* vertex normals are optional, they require some extra calculations, + * so make them optional */ + mesh_calc_normals(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors); + } + else { + /* only calc poly normals */ + mp = mpolys; + for (i=0; i<numPolys; i++, mp++) { + mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]); + } + } + + if ( origIndexFace && + /* fnors==faceNors_r */ /* NO NEED TO ALLOC YET */ + fnors != NULL && + numFaces) + { + mf = mfaces; + for (i=0; i<numFaces; i++, mf++, origIndexFace++) { + if (*origIndexFace < numPolys) { + copy_v3_v3(fnors[i], pnors[*origIndexFace]); + } else { + /*eek, we're not corrusponding to polys*/ + printf("error in mesh_calc_normals; tesselation face indices are incorrect. normals may look bad.\n"); + } + } + } + + if (pnors != polyNors_r) MEM_freeN(pnors); + /* if (fnors != faceNors_r) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */ + + fnors = pnors = NULL; + +} + +void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys, + int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3]) +{ + float (*pnors)[3] = polyNors_r; + + float (*tnorms)[3], (*edgevecbuf)[3]= NULL; + float **vertcos = NULL, **vertnos = NULL; + BLI_array_declare(vertcos); + BLI_array_declare(vertnos); + BLI_array_declare(edgevecbuf); + + int i, j; + MPoly *mp; + MLoop *ml; + + if (!pnors) pnors = MEM_callocN(sizeof(float) * 3 * numPolys, "poly_nors mesh.c"); + + /*first go through and calculate normals for all the polys*/ + tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c"); + + mp = mpolys; + for (i=0; i<numPolys; i++, mp++) { + mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]); + ml = mloop + mp->loopstart; + + BLI_array_empty(vertcos); + BLI_array_empty(vertnos); + for (j=0; j<mp->totloop; j++) { + int vindex = ml[j].v; + BLI_array_append(vertcos, mverts[vindex].co); + BLI_array_append(vertnos, tnorms[vindex]); + } + + BLI_array_empty(edgevecbuf); + BLI_array_growitems(edgevecbuf, mp->totloop); + + accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop); + } + + BLI_array_free(vertcos); + BLI_array_free(vertnos); + BLI_array_free(edgevecbuf); + + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ + for(i=0; i<numVerts; i++) { + MVert *mv= &mverts[i]; + float *no= tnorms[i]; + + if(normalize_v3(no) == 0.0f) + normalize_v3_v3(no, mv->co); + + normal_float_to_short_v3(mv->no, no); + } + + MEM_freeN(tnorms); + + if (pnors != polyNors_r) MEM_freeN(pnors); +} + +void mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3]) { float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms"); float (*fnors)[3]= (faceNors_r)? faceNors_r: MEM_callocN(sizeof(*fnors)*numFaces, "meshnormals"); @@ -1288,6 +1828,159 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, MEM_freeN(fnors); } + +static void bmesh_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol) +{ + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + MFace *mf; + int i; + + mf = me->mface + findex; + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i); + + texpoly->tpage = texface->tpage; + texpoly->flag = texface->flag; + texpoly->transp = texface->transp; + texpoly->mode = texface->mode; + texpoly->tile = texface->tile; + texpoly->unwrap = texface->unwrap; + + mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i); + mloopuv->uv[0] = texface->uv[0][0]; mloopuv->uv[1] = texface->uv[0][1]; mloopuv++; + mloopuv->uv[0] = texface->uv[1][0]; mloopuv->uv[1] = texface->uv[1][1]; mloopuv++; + mloopuv->uv[0] = texface->uv[2][0]; mloopuv->uv[1] = texface->uv[2][1]; mloopuv++; + + if (mf->v4) { + mloopuv->uv[0] = texface->uv[3][0]; mloopuv->uv[1] = texface->uv[3][1]; mloopuv++; + } + } + + for(i=0; i < numCol; i++){ + mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i); + mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i); + + mloopcol->r = mcol[0].r; mloopcol->g = mcol[0].g; mloopcol->b = mcol[0].b; mloopcol->a = mcol[0].a; mloopcol++; + mloopcol->r = mcol[1].r; mloopcol->g = mcol[1].g; mloopcol->b = mcol[1].b; mloopcol->a = mcol[1].a; mloopcol++; + mloopcol->r = mcol[2].r; mloopcol->g = mcol[2].g; mloopcol->b = mcol[2].b; mloopcol->a = mcol[2].a; mloopcol++; + if (mf->v4) { + mloopcol->r = mcol[3].r; mloopcol->g = mcol[3].g; mloopcol->b = mcol[3].b; mloopcol->a = mcol[3].a; mloopcol++; + } + } + + if (CustomData_has_layer(&me->fdata, CD_MDISPS)) { + MDisps *ld = CustomData_get(&me->ldata, loopstart, CD_MDISPS); + MDisps *fd = CustomData_get(&me->fdata, findex, CD_MDISPS); + float (*disps)[3] = fd->disps; + int i, tot = mf->v4 ? 4 : 3; + int side, corners; + + corners = multires_mdisp_corners(fd); + + if (corners == 0) { + /* Empty MDisp layers appear in at least one of the sintel.blend files. + Not sure why this happens, but it seems fine to just ignore them here. + If corners==0 for a non-empty layer though, something went wrong. */ + BLI_assert(fd->totdisp == 0); + } + else { + side = sqrt(fd->totdisp / corners); + + for (i=0; i<tot; i++, disps += side*side, ld++) { + ld->totdisp = side*side; + + if (ld->disps) + MEM_freeN(ld->disps); + + ld->disps = MEM_callocN(sizeof(float)*3*side*side, "converted loop mdisps"); + if (fd->disps) { + memcpy(ld->disps, disps, sizeof(float)*3*side*side); + } + } + } + } +} + +void convert_mfaces_to_mpolys(Mesh *mesh) +{ + MFace *mf; + MLoop *ml; + MPoly *mp; + MEdge *me; + EdgeHash *eh; + int numTex, numCol; + int i, j, totloop; + + mesh->totpoly = mesh->totface; + mesh->mpoly = MEM_callocN(sizeof(MPoly)*mesh->totpoly, "mpoly converted"); + CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly); + + numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE); + numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL); + + totloop = 0; + mf = mesh->mface; + for (i=0; i<mesh->totface; i++, mf++) { + totloop += mf->v4 ? 4 : 3; + } + + mesh->totloop = totloop; + mesh->mloop = MEM_callocN(sizeof(MLoop)*mesh->totloop, "mloop converted"); + + CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop); + CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata, + mesh->totloop, mesh->totpoly); + + eh = BLI_edgehash_new(); + + /*build edge hash*/ + me = mesh->medge; + for (i=0; i<mesh->totedge; i++, me++) { + BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); + } + + j = 0; /*current loop index*/ + ml = mesh->mloop; + mf = mesh->mface; + mp = mesh->mpoly; + for (i=0; i<mesh->totface; i++, mf++, mp++) { + mp->loopstart = j; + + mp->totloop = mf->v4 ? 4 : 3; + + mp->mat_nr = mf->mat_nr; + mp->flag = mf->flag; + + #define ML(v1, v2) {ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++;} + + ML(v1, v2); + ML(v2, v3); + if (mf->v4) { + ML(v3, v4); + ML(v4, v1); + } else { + ML(v3, v1); + } + + #undef ML + + bmesh_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol); + } + + /* note, we dont convert FGons at all, these are not even real ngons, + * they have their own UV's, colors etc - its more an editing feature. */ + + mesh_update_customdata_pointers(mesh, TRUE); + + BLI_edgehash_free(eh, NULL); +} + float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] { int i, numVerts = me->totvert; @@ -1300,22 +1993,27 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] return cos; } -UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit) + +/* ngon version wip, based on EDBM_make_uv_vert_map */ +/* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could + * but for now this replaces it because its unused. */ + +UvVertMap *make_uv_vert_map(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, int selected, float *limit) { UvVertMap *vmap; UvMapVert *buf; - MFace *mf; + MPoly *mp; unsigned int a; int i, totuv, nverts; totuv = 0; /* generate UvMapVert array */ - mf= mface; - for(a=0; a<totface; a++, mf++) - if(!selected || (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))) - totuv += (mf->v4)? 4: 3; - + mp= mpoly; + for(a=0; a<totpoly; a++, mp++) + if(!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) + totuv += mp->totloop; + if(totuv==0) return NULL; @@ -1331,17 +2029,17 @@ UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned return NULL; } - mf= mface; - for(a=0; a<totface; a++, mf++) { - if(!selected || (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))) { - nverts= (mf->v4)? 4: 3; + mp= mpoly; + for(a=0; a<totpoly; a++, mp++) { + if(!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { + nverts= mp->totloop; for(i=0; i<nverts; i++) { buf->tfindex= i; buf->f= a; buf->separate = 0; - buf->next= vmap->vert[*(&mf->v1 + i)]; - vmap->vert[*(&mf->v1 + i)]= buf; + buf->next= vmap->vert[mloop[mp->loopstart + i].v]; + vmap->vert[mloop[mp->loopstart + i].v]= buf; buf++; } } @@ -1359,14 +2057,14 @@ UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned v->next= newvlist; newvlist= v; - uv= tface[v->f].uv[v->tfindex]; + uv= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv; lastv= NULL; iterv= vlist; while(iterv) { next= iterv->next; - uv2= tface[iterv->f].uv[iterv->tfindex]; + uv2= mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv; sub_v2_v2v2(uvdiff, uv2, uv); @@ -1447,8 +2145,6 @@ void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, c } } -#ifdef USE_BMESH_FORWARD_COMPAT - void mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata, CustomData *pdata, int lindex[4], int findex, const int polyindex, @@ -1510,6 +2206,286 @@ void mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata, } } +/* + this function recreates a tesselation. + returns number of tesselation faces. + */ +int mesh_recalcTesselation(CustomData *fdata, + CustomData *ldata, CustomData *pdata, + MVert *mvert, int totface, int UNUSED(totloop), + int totpoly, + /* when teseelating to recalcilate normals after + * we can skip copying here */ + const int do_face_nor_cpy) +{ + + /* use this to avoid locking pthread for _every_ polygon + * and calling the fill function */ + +#define USE_TESSFACE_SPEEDUP +#define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING + +#define TESSFACE_SCANFILL (1<<0) +#define TESSFACE_IS_QUAD (1<<1) + + MPoly *mp, *mpoly; + MLoop *ml, *mloop; + MFace *mface = NULL, *mf; + BLI_array_declare(mface); + EditVert *v, *lastv, *firstv; + EditFace *f; + int *mface_orig_index = NULL; + BLI_array_declare(mface_orig_index); + int *mface_to_poly_map = NULL; + BLI_array_declare(mface_to_poly_map); + int lindex[4]; /* only ever use 3 in this case */ + int *poly_orig_index; + int poly_index, j, mface_index; + + const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + const int hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL); + + mpoly = CustomData_get_layer(pdata, CD_MPOLY); + mloop = CustomData_get_layer(ldata, CD_MLOOP); + + /* allocate the length of totfaces, avoid many small reallocs, + * if all faces are tri's it will be correct, quads == 2x allocs */ + BLI_array_reserve(mface_to_poly_map, totpoly); + BLI_array_reserve(mface, totpoly); + + mface_index = 0; + mp = mpoly; + poly_orig_index = CustomData_get_layer(pdata, CD_ORIGINDEX); + for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) { + if (mp->totloop < 3) { + /* do nothing */ + } + +#ifdef USE_TESSFACE_SPEEDUP + +#define ML_TO_MF(i1, i2, i3) \ + BLI_array_growone(mface_to_poly_map); \ + BLI_array_growone(mface); \ + mface_to_poly_map[mface_index] = poly_index; \ + mf= &mface[mface_index]; \ + /* set loop indices, transformed to vert indices later */ \ + mf->v1 = mp->loopstart + i1; \ + mf->v2 = mp->loopstart + i2; \ + mf->v3 = mp->loopstart + i3; \ + mf->v4 = 0; \ + mf->mat_nr = mp->mat_nr; \ + mf->flag = mp->flag; \ + if (poly_orig_index) { \ + BLI_array_append(mface_orig_index, \ + poly_orig_index[poly_index]); \ + } \ + +/* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */ +#define ML_TO_MF_QUAD() \ + BLI_array_growone(mface_to_poly_map); \ + BLI_array_growone(mface); \ + mface_to_poly_map[mface_index] = poly_index; \ + mf= &mface[mface_index]; \ + /* set loop indices, transformed to vert indices later */ \ + mf->v1 = mp->loopstart + 0; /* EXCEPTION */ \ + mf->v2 = mp->loopstart + 1; /* EXCEPTION */ \ + mf->v3 = mp->loopstart + 2; /* EXCEPTION */ \ + mf->v4 = mp->loopstart + 3; /* EXCEPTION */ \ + mf->mat_nr = mp->mat_nr; \ + mf->flag = mp->flag; \ + if (poly_orig_index) { \ + BLI_array_append(mface_orig_index, \ + poly_orig_index[poly_index]); \ + } \ + mf->edcode |= TESSFACE_IS_QUAD; /* EXCEPTION */ \ + + + else if (mp->totloop == 3) { + ml = mloop + mp->loopstart; + ML_TO_MF(0, 1, 2) + mface_index++; + } + else if (mp->totloop == 4) { +#ifdef USE_TESSFACE_QUADS + ml = mloop + mp->loopstart; + ML_TO_MF_QUAD() + mface_index++; +#else + ml = mloop + mp->loopstart; + ML_TO_MF(0, 1, 2) + mface_index++; + ML_TO_MF(0, 2, 3) + mface_index++; +#endif + } +#endif /* USE_TESSFACE_SPEEDUP */ + else { + int totfilltri; + + ml = mloop + mp->loopstart; + + BLI_begin_edgefill(); + firstv = NULL; + lastv = NULL; + for (j=0; j<mp->totloop; j++, ml++) { + v = BLI_addfillvert(mvert[ml->v].co); + + v->keyindex = mp->loopstart + j; + + if (lastv) + BLI_addfilledge(lastv, v); + + if (!firstv) + firstv = v; + lastv = v; + } + BLI_addfilledge(lastv, firstv); + + totfilltri = BLI_edgefill(2); + if (totfilltri) { + BLI_array_growitems(mface_to_poly_map, totfilltri); + BLI_array_growitems(mface, totfilltri); + if (poly_orig_index) { + BLI_array_growitems(mface_orig_index, totfilltri); + } + + for (f = fillfacebase.first; f; f = f->next, mf++) { + mface_to_poly_map[mface_index] = poly_index; + mf= &mface[mface_index]; + + /* set loop indices, transformed to vert indices later */ + mf->v1 = f->v1->keyindex; + mf->v2 = f->v2->keyindex; + mf->v3 = f->v3->keyindex; + mf->v4 = 0; + + mf->mat_nr = mp->mat_nr; + mf->flag = mp->flag; + +#ifdef USE_TESSFACE_SPEEDUP + mf->edcode |= TESSFACE_SCANFILL; /* tag for sorting loop indicies */ +#endif + + if (poly_orig_index) { + mface_orig_index[mface_index] = poly_orig_index[poly_index]; + } + + mface_index++; + } + } + + BLI_end_edgefill(); + } + } + + CustomData_free(fdata, totface); + memset(fdata, 0, sizeof(CustomData)); + totface = mface_index; + + + /* note essential but without this we store over-alloc'd memory in the CustomData layers */ + if (LIKELY((MEM_allocN_len(mface) / sizeof(*mface)) != totface)) { + mface = MEM_reallocN(mface, sizeof(*mface) * totface); + mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface); + if (mface_orig_index) { + mface_orig_index = MEM_reallocN(mface_orig_index, sizeof(*mface_orig_index) * totface); + } + } + + CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); + + /* CD_POLYINDEX will contain an array of indices from tessfaces to the polygons + * they are directly tesselated from */ + CustomData_add_layer(fdata, CD_POLYINDEX, CD_ASSIGN, mface_to_poly_map, totface); + if (mface_orig_index) { + /* If polys had a CD_ORIGINDEX layer, then the tesselated faces will get this + * layer as well, pointing to polys from the original mesh (not the polys + * that just got tesselated) */ + CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_orig_index, totface); + } + + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + if (do_face_nor_cpy) { + /* If polys have a normals layer, copying that to faces can help + * avoid the need to recalculate normals later */ + if (CustomData_has_layer(pdata, CD_NORMAL)) { + float (*pnors)[3] = CustomData_get_layer(pdata, CD_NORMAL); + float (*fnors)[3] = CustomData_add_layer(fdata, CD_NORMAL, CD_CALLOC, NULL, totface); + for (mface_index = 0; mface_index < totface; mface_index++) { + copy_v3_v3(fnors[mface_index], pnors[mface_to_poly_map[mface_index]]); + } + } + } + + mf = mface; + for (mface_index=0; mface_index < totface; mface_index++, mf++) { + +#ifdef USE_TESSFACE_QUADS + const int mf_len = mf->edcode & TESSFACE_IS_QUAD ? 4 : 3; +#endif + +#ifdef USE_TESSFACE_SPEEDUP + /* skip sorting when not using ngons */ + if (UNLIKELY(mf->edcode & TESSFACE_SCANFILL)) +#endif + { + /* 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); + } + + /* end abusing the edcode */ +#if defined(USE_TESSFACE_QUADS) || defined(USE_TESSFACE_SPEEDUP) + mf->edcode = 0; +#endif + + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; +#ifdef USE_TESSFACE_QUADS + if (mf_len == 4) lindex[3] = mf->v4; +#endif + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; +#ifdef USE_TESSFACE_QUADS + if (mf_len == 4) mf->v4 = mloop[mf->v4].v; +#endif + + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, mface_index, mface_to_poly_map[mface_index], +#ifdef USE_TESSFACE_QUADS + mf_len, +#else + 3, +#endif + numTex, numCol, hasWCol); + + +#ifdef USE_TESSFACE_QUADS + test_index_face(mf, fdata, mface_index, mf_len); +#endif + + } + + return totface; + +#undef USE_TESSFACE_SPEEDUP + +} + + +#ifdef USE_BMESH_SAVE_AS_COMPAT /* * this function recreates a tesselation. @@ -1620,10 +2596,261 @@ int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, return k; } +#endif /* USE_BMESH_SAVE_AS_COMPAT */ + +/* + * 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[3]) +{ + + MVert *v1, *v2, *v3; + double u[3], v[3], w[3]; + double n[3] = {0.0, 0.0, 0.0}, l; + int i; + + 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] -#endif /* USE_BMESH_FORWARD_COMPAT */ + 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[3]) +{ + if (mpoly->totloop > 4) { + mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no); + } + else if (mpoly->totloop == 3){ + normal_tri_v3(no, + mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co + ); + } + else if (mpoly->totloop == 4) { + normal_quad_v3(no, + mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co, + mvarray[loopstart[3].v].co + ); + } + else { /* horrible, two sided face! */ + no[0] = 0.0; + no[1] = 0.0; + no[2] = 1.0; + } +} +/* duplicate of function above _but_ takes coords rather then mverts */ +static void mesh_calc_ngon_normal_coords(MPoly *mpoly, MLoop *loopstart, + const float (*vertex_coords)[3], float normal[3]) +{ + + const float *v1, *v2, *v3; + double u[3], v[3], w[3]; + double n[3] = {0.0, 0.0, 0.0}, l; + int i; + + for(i = 0; i < mpoly->totloop; i++){ + v1 = (const float *)(vertex_coords + loopstart[i].v); + v2 = (const float *)(vertex_coords + loopstart[(i+1)%mpoly->totloop].v); + v3 = (const float *)(vertex_coords + loopstart[(i+2)%mpoly->totloop].v); + + VECCOPY(u, v1); + VECCOPY(v, v2); + VECCOPY(w, v3); + + /*this fixes some weird numerical error*/ + if (i==0) { + u[0] += 0.0001f; + u[1] += 0.0001f; + u[2] += 0.0001f; + } + + 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_coords(MPoly *mpoly, MLoop *loopstart, + const float (*vertex_coords)[3], float no[3]) +{ + if (mpoly->totloop > 4) { + mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, no); + } + else if (mpoly->totloop == 3){ + normal_tri_v3(no, + vertex_coords[loopstart[0].v], + vertex_coords[loopstart[1].v], + vertex_coords[loopstart[2].v] + ); + } + else if (mpoly->totloop == 4) { + normal_quad_v3(no, + vertex_coords[loopstart[0].v], + vertex_coords[loopstart[1].v], + vertex_coords[loopstart[2].v], + vertex_coords[loopstart[3].v] + ); + } + else { /* horrible, two sided face! */ + no[0] = 0.0; + no[1] = 0.0; + no[2] = 1.0; + } +} + +static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart, + MVert *mvert, float cent[3]) +{ + const float w= 1.0f / (float)mpoly->totloop; + int i; + + zero_v3(cent); + + for (i = 0; i < mpoly->totloop; i++) { + madd_v3_v3fl(cent, mvert[(loopstart++)->v].co, w); + } +} + +void mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float cent[3]) +{ + if (mpoly->totloop == 3) { + cent_tri_v3(cent, + mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co + ); + } + else if (mpoly->totloop == 4) { + cent_quad_v3(cent, + mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co, + mvarray[loopstart[3].v].co + ); + } + else { + mesh_calc_ngon_center(mpoly, loopstart, mvarray, cent); + } +} + +/* note, passing polynormal is only a speedup so we can skip calculating it */ +float mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float polynormal[3]) +{ + if (mpoly->totloop == 3) { + return area_tri_v3(mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co + ); + } + else if (mpoly->totloop == 4) { + return area_quad_v3(mvarray[loopstart[0].v].co, + mvarray[loopstart[1].v].co, + mvarray[loopstart[2].v].co, + mvarray[loopstart[3].v].co + ); + } + else { + int i; + float area, polynorm_local[3], (*vertexcos)[3]; + float *no= polynormal ? polynormal : polynorm_local; + BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); + + /* pack vertex cos into an array for area_poly_v3 */ + for (i = 0; i < mpoly->totloop; i++) { + copy_v3_v3(vertexcos[i], mvarray[(loopstart++)->v].co); + } + + /* need normal for area_poly_v3 as well */ + if (polynormal == NULL) { + mesh_calc_poly_normal(mpoly, loopstart, mvarray, no); + } + + /* finally calculate the area */ + area = area_poly_v3(mpoly->totloop, vertexcos, no); + + BLI_array_fixedstack_free(vertexcos); + + return area; + } +} /* 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 ed9b63fe98d..92f7f959f8a 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -451,11 +451,11 @@ 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), - dm->getVertDataArray(dm, CD_MDEFORMVERT), - TRUE, FALSE); + dm->getVertArray(dm), dm->getNumVerts(dm), + dm->getEdgeArray(dm), dm->getNumEdges(dm), + dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), + dm->getVertDataArray(dm, CD_MDEFORMVERT), + TRUE, FALSE); } void BKE_mesh_calc_edges(Mesh *mesh, int update) @@ -466,6 +466,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) MEdge *med, *med_orig; EdgeHash *eh = BLI_edgehash_new(); int i, totedge, totface = mesh->totface; + int med_index; if(mesh->totedge==0) update= 0; @@ -478,20 +479,37 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) BLI_edgehash_insert(eh, med->v1, med->v2, med); } - for (i = 0; i < totface; i++, mf++) { - if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) - BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); - if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) - BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); - - if (mf->v4) { - if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) - BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); - if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) - BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); - } else { - if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) - BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + if(mesh->totpoly) { + /* mesh loops (bmesh only) */ + MPoly *mp= mesh->mpoly; + for(i=0; i < mesh->totpoly; i++, mp++) { + MLoop *l= &mesh->mloop[mp->loopstart]; + int j, l_prev= (l + (mp->totloop-1))->v; + for (j=0; j < mp->totloop; j++, l++) { + if (!BLI_edgehash_haskey(eh, l_prev, l->v)) { + BLI_edgehash_insert(eh, l_prev, l->v, NULL); + } + l_prev= l->v; + } + } + } + else { + /* regular faces (note, we could remove this for bmesh - campbell) */ + for (i = 0; i < totface; i++, mf++) { + if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) + BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); + if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) + BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); + + if (mf->v4) { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) + BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); + if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) + BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); + } else { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) + BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + } } } @@ -512,9 +530,29 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ } + + /* store the new edge index in the hash value */ + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } BLI_edgehashIterator_free(ehi); + if (mesh->totpoly) { + /* second pass, iterate through all loops again and assign + the newly created edges to them. */ + MPoly *mp= mesh->mpoly; + for(i=0; i < mesh->totpoly; i++, mp++) { + MLoop *l= &mesh->mloop[mp->loopstart]; + MLoop *l_prev= (l + (mp->totloop-1)); + int j; + for (j=0; j < mp->totloop; j++, l++) { + /* lookup hashed edge index */ + med_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v)); + l_prev->e = med_index; + l_prev= l; + } + } + } + /* free old CustomData and assign new one */ CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c new file mode 100644 index 00000000000..c54a622be7e --- /dev/null +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -0,0 +1,220 @@ +/* + * ***** 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_utildefines.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 "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_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(Object *ob, DerivedMesh *dm, BMEditMesh *existing, int do_tesselate) +{ + 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; + MPoly *mpoly, *mp; + MLoop *mloop, *ml; + BMVert *v, **vtable, **verts=NULL; + BMEdge *e, **etable, **edges=NULL; + BMFace *f; + BMIter liter; + BLI_array_declare(verts); + BLI_array_declare(edges); + int i, j, k, totvert, totedge, totface; + + if (em) bm = em->bm; + else bm = BM_Make_Mesh(ob, 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); + + totvert = dm->getNumVerts(dm); + totedge = dm->getNumEdges(dm); + totface = dm->getNumPolys(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); + normal_short_to_float_v3(v->no, mv->no); + v->head.hflag = BM_Vert_Flag_From_MEFlag(mv->flag); + + 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.hflag = BM_Edge_Flag_From_MEFlag(me->flag); + + CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data); + etable[i] = e; + } + MEM_freeN(medge); + + /*do faces*/ + mpoly = mp = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); + for (i=0; i<dm->numPolyData; i++, mp++) { + BMLoop *l; + + BLI_array_empty(verts); + BLI_array_empty(edges); + + BLI_array_growitems(verts, mp->totloop); + BLI_array_growitems(edges, mp->totloop); + + ml = mloop + mp->loopstart; + for (j = 0; j < mp->totloop; j++, ml++) { + + verts[j] = vtable[ml->v]; + edges[j] = etable[ml->e]; + } + + f = BM_Make_Ngon(bm, verts[0], verts[1], edges, mp->totloop, 0); + + if (!f) + continue; + + f->head.hflag = BM_Face_Flag_From_MEFlag(mp->flag); + f->mat_nr = mp->mat_nr; + + l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f); + k = mp->loopstart; + + for (j=0; l; l=BMIter_Step(&liter), k++) { + CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data); + } + + CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, + i, &f->head.data); + } + + MEM_freeN(vtable); + MEM_freeN(etable); + + BLI_array_free(verts); + BLI_array_free(edges); + + if (!em) { + em = BMEdit_Create(bm, do_tesselate); + } + else { + if (do_tesselate) { + BMEdit_RecalcTesselation(em); + } + } + + return em; +} + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 3fb49d508cd..cba4780e282 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -53,6 +53,7 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" +#include "BKE_tessmesh.h" #include "BKE_object.h" @@ -67,7 +68,7 @@ static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641, static const int multires_side_tot[] = {0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert); -static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, int invert, int add, DMGridData **oldGridData, int totlvl); DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob) { @@ -78,7 +79,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; @@ -180,7 +181,7 @@ void multires_force_external_reload(Object *ob) { Mesh *me = get_mesh(ob); - CustomData_external_reload(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + CustomData_external_reload(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); multires_force_update(ob); } @@ -237,7 +238,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); @@ -256,26 +257,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; - - 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; + MDisps *mdisp, *md; + int i, j, totlvl= 0; - 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; + mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS); + 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; } } @@ -288,10 +294,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); @@ -303,27 +309,23 @@ 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]; } } } -static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl) +static void multires_reallocate_mdisps(int totloop, 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 < totloop; ++i) { + int totdisp = multires_grid_tot[lvl]; float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); if(mdisps[i].disps) @@ -388,44 +390,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; */ /*UNUSED*/ int nsize = multires_side_tot[lvl]; int hsize = multires_side_tot[mmd->totlvl]; - int i; + int i, j; - 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++) { + MDisps *mdisp= &mdisps[me->mpoly[i].loopstart+j]; + 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); } } @@ -441,8 +442,8 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire 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); @@ -597,7 +598,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) cddm->release(cddm); /* calc disps */ - multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl); + multiresModifier_disp_run(dispdm, me, NULL, 1, 0, origdm->getGridData(origdm), totlvl); origdm->release(origdm); dispdm->release(dispdm); @@ -614,9 +615,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 */ @@ -661,10 +662,10 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl ccgSubSurf_updateLevels(ss, lvl, NULL, 0); /* reallocate displacements */ - multires_reallocate_mdisps(me, mdisps, totlvl); + multires_reallocate_mdisps(me->totloop, mdisps, totlvl); /* compute displacements */ - multiresModifier_disp_run(highdm, me, 1, 0, subGridData, totlvl); + multiresModifier_disp_run(highdm, me, NULL, 1, 0, subGridData, totlvl); /* free */ highdm->release(highdm); @@ -674,7 +675,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl } else { /* only reallocate, nothing to upsample */ - multires_reallocate_mdisps(me, mdisps, totlvl); + multires_reallocate_mdisps(me->totloop, mdisps, totlvl); } multires_set_tot_level(ob, mmd, totlvl); @@ -685,7 +686,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple); } -static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) +void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) { if(axis == 0) { if(x == gridSize - 1) { @@ -709,18 +710,30 @@ static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGrid } } -static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl) +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, int invert, int add, DMGridData **oldGridData, int totlvl) { 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; + int totloop, totpoly; + + /*this happens in the dm made by bmesh_set_mdisps_space*/ + if (dm2 && CustomData_has_layer(&dm2->loopData, CD_MDISPS)) { + mpoly = CustomData_get_layer(&dm2->polyData, CD_MPOLY); + mdisps = CustomData_get_layer(&dm2->loopData, CD_MDISPS); + totloop = dm2->numLoopData; + totpoly = dm2->numPolyData; + } else { + totloop = me->totloop; + totpoly = me->totpoly; + } + 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; } @@ -734,23 +747,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(totloop*gridSize*gridSize >= CCG_OMP_LIMIT) + + for(i = 0; i < totpoly; ++i) { + const int numVerts = mpoly[i].totloop; + int S, x, y, gIndex = gridOffset[i]; - for(S = 0; S < numVerts; ++S, ++gIndex) { + for(S = 0; S < numVerts; ++S, ++gIndex, ++k) { + MDisps *mdisp = &mdisps[mpoly[i].loopstart+S]; 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(totloop, mdisps, totlvl); + } + + dispgrid = mdisp->disps; for(y = 0; y < gridSize; y++) { for(x = 0; x < gridSize; x++) { @@ -813,8 +831,8 @@ static void multiresModifier_update(DerivedMesh *dm) 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; @@ -828,7 +846,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); @@ -871,7 +889,7 @@ static void multiresModifier_update(DerivedMesh *dm) ccgSubSurf_updateLevels(ss, lvl, NULL, 0); /* add to displacements */ - multiresModifier_disp_run(highdm, me, 1, 1, subGridData, mmd->totlvl); + multiresModifier_disp_run(highdm, me, NULL, 1, 1, subGridData, mmd->totlvl); /* free */ highdm->release(highdm); @@ -882,20 +900,143 @@ 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); subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); cddm->release(cddm); - multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); + multiresModifier_disp_run(dm, me, NULL, 1, 0, subdm->getGridData(subdm), mmd->totlvl); subdm->release(subdm); } } } + +void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) +{ + DerivedMesh *ccgdm = NULL, *subsurf = NULL; + DMGridData **gridData, **subGridData=NULL; + MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + MDisps *mdisps; + MultiresModifierData *mmd = get_multires_modifier(NULL, ob, 1); + int *gridOffset, totlvl; + int i, k, numGrids, gridSize, dGridSize, dSkip; + + if (!mmd) + return; + + mdisps = CustomData_get_layer(&dm->loopData, CD_MDISPS); + + if(!mdisps) { + goto cleanup; + } + + totlvl = mmd->totlvl; + ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple); + + subsurf = subsurf_dm_create_local(ob, dm, totlvl, + mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv); + + numGrids = subsurf->getNumGrids(subsurf); + gridSize = subsurf->getGridSize(subsurf); + gridData = subsurf->getGridData(subsurf); + + subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); + + for(i = 0; i < numGrids; i++) { + subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData"); + memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); + } + + /*numGrids = ccgdm->dm->getNumGrids((DerivedMesh*)ccgdm);*/ /*UNUSED*/ + gridSize = ccgdm->getGridSize((DerivedMesh*)ccgdm); + gridData = ccgdm->getGridData((DerivedMesh*)ccgdm); + gridOffset = ccgdm->getGridOffset((DerivedMesh*)ccgdm); + + dGridSize = multires_side_tot[totlvl]; + dSkip = (dGridSize-1)/(gridSize-1); + + k = 0; /*current loop/mdisp index within the mloop array*/ + + //#pragma omp parallel for private(i) if(dm->numLoopData*gridSize*gridSize >= CCG_OMP_LIMIT) + + for(i = 0; i < dm->numPolyData; ++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[mpoly[i].loopstart+S]; + /* DMGridData *grid = gridData[gIndex]; */ /* UNUSED */ + DMGridData *subgrid = subGridData[gIndex]; + float (*dispgrid)[3] = NULL; + + /* when adding new faces in edit mode, need to allocate disps */ + if(!mdisp->disps) { + mdisp->totdisp = gridSize*gridSize; + mdisp->disps = MEM_callocN(sizeof(float)*3*mdisp->totdisp, "disp in multires_set_space"); + } + + dispgrid = mdisp->disps; + + for(y = 0; y < gridSize; y++) { + for(x = 0; x < gridSize; x++) { + float *data = dispgrid[dGridSize*y*dSkip + x*dSkip]; + float *no = subgrid[x + y*gridSize].no; + float *co = subgrid[x + y*gridSize].co; + float mat[3][3], tx[3], ty[3], dco[3]; + + /* construct tangent space matrix */ + grid_tangent(gridSize, gIndex, x, y, 0, subGridData, tx); + normalize_v3(tx); + + grid_tangent(gridSize, gIndex, x, y, 1, subGridData, ty); + normalize_v3(ty); + column_vectors_to_mat3(mat, tx, ty, no); + + /* convert to absolute coordinates in space */ + if (from == MULTIRES_SPACE_TANGENT) { + mul_v3_m3v3(dco, mat, data); + add_v3_v3(dco, co); + } else if (from == MULTIRES_SPACE_OBJECT) { + add_v3_v3v3(dco, co, data); + } else if (from == MULTIRES_SPACE_ABSOLUTE) { + copy_v3_v3(dco, data); + } + + column_vectors_to_mat3(mat, tx, ty, no); + + /*now, convert to desired displacement type*/ + if (to == MULTIRES_SPACE_TANGENT) { + invert_m3(mat); + + sub_v3_v3(dco, co); + mul_v3_m3v3(data, mat, dco); + } else if (to == MULTIRES_SPACE_OBJECT) { + sub_v3_v3(dco, co); + mul_v3_m3v3(data, mat, dco); + } else if (to == MULTIRES_SPACE_ABSOLUTE) { + copy_v3_v3(data, dco); + } + } + } + } + } + +cleanup: + if (subsurf) { + subsurf->needsFree = 1; + subsurf->release(subsurf); + } + + if (ccgdm) { + ccgdm->needsFree = 1; + ccgdm->release(ccgdm); + } +} + void multires_stitch_grids(Object *ob) { /* utility for smooth brush */ @@ -956,8 +1097,10 @@ 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); - multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); + CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + + /*run displacement*/ + multiresModifier_disp_run(result, ob->data, dm, 0, 0, subGridData, mmd->totlvl); for(i = 0; i < numGrids; i++) MEM_freeN(subGridData[i]); @@ -976,7 +1119,10 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, const int st_max = st - 1; float urat, vrat, uopp; float d[4][3], d2[2][3]; - + + if (!disps || isnan(u) || isnan(v)) + return; + if(u < 0) u = 0; else if(u >= st) @@ -1057,15 +1203,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); + } + + } } } @@ -1590,8 +1754,8 @@ static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob) Mesh *me= (Mesh*)ob->data; - 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); } if(!mmd || !to_mmd) return; @@ -1605,7 +1769,8 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL; DMGridData **gridData, **subGridData; Mesh *me= (Mesh*)ob->data; - MFace *mface= me->mface; + MPoly *mpoly= me->mpoly; + /* MLoop *mloop = me->mloop; */ /* UNUSED */ MDisps *mdisps; int *gridOffset; int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert; @@ -1613,8 +1778,8 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); MultiresModifierData high_mmd; - 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 || !mmd || !mmd->totlvl) return; @@ -1650,15 +1815,15 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) 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]; + for(i = 0; i < me->totpoly; ++i) { + const int numVerts= mpoly[i].totloop; + MDisps *mdisp= &mdisps[mpoly[i].loopstart]; int S, x, y, gIndex = gridOffset[i]; - for(S = 0; S < numVerts; ++S, ++gIndex) { + for(S = 0; S < numVerts; ++S, ++gIndex, mdisp++) { DMGridData *grid= gridData[gIndex]; DMGridData *subgrid= subGridData[gIndex]; - float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize]; + float (*dispgrid)[3]= mdisp->disps; for(y = 0; y < gridSize; y++) { for(x = 0; x < gridSize; x++) { @@ -1731,6 +1896,7 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) } /* update multires data after topology changing */ +#if 0 // BMESH_TODO void multires_topology_changed(Scene *scene, Object *ob) { Mesh *me= (Mesh*)ob->data; @@ -1781,6 +1947,7 @@ void multires_topology_changed(Scene *scene, Object *ob) } } } +#endif // BMESH_TODO /* makes displacement along grid boundary symmetrical */ void multires_mdisp_smooth_bounds(MDisps *disps) diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index e3b5b83964e..72523ae54e0 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -134,8 +134,8 @@ int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, } //calculate number of tris - nfaces = dm->getNumFaces(dm); - faces = dm->getFaceArray(dm); + nfaces = dm->getNumTessFaces(dm); + faces = dm->getTessFaceArray(dm); ntris = nfaces; for (fi=0; fi<nfaces; fi++) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d2b81a345a7..3d8729bc788 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -86,6 +86,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_node.h" @@ -1712,7 +1713,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; @@ -1721,7 +1722,24 @@ 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 0 /* this was bmesh only, better, evaluate why this was needed - campbell*/ + 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) { + copy_v3_v3(vec, eve->co); + break; + } + } + } +#endif + dm = (em)? em->derivedFinal: par->derivedFinal; if(dm) { @@ -1750,9 +1768,6 @@ static void give_parvert(Object *par, int nr, float *vec) } } else fprintf(stderr, "%s: DerivedMesh is needed to solve parenting, object position can be wrong now\n", __func__); - - if(em) - BKE_mesh_end_editmesh(me, em); } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { Nurb *nu; @@ -2512,22 +2527,24 @@ 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); + makeDerivedMesh(scene, ob, em, scene->customdata_mask, 0); /* was CD_MASK_BAREMESH */ + } + else { + makeDerivedMesh(scene, ob, NULL, scene->customdata_mask, 0); + } #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; uint64_t data_mask= scene->customdata_mask | ob->customdata_mask | CD_MASK_BAREMESH; if(em) { - makeDerivedMesh(scene, ob, em, data_mask); /* was CD_MASK_BAREMESH */ - BKE_mesh_end_editmesh(ob->data, em); - } else - makeDerivedMesh(scene, ob, NULL, data_mask); + makeDerivedMesh(scene, ob, em, data_mask, 0); /* was CD_MASK_BAREMESH */ + } + else { + makeDerivedMesh(scene, ob, NULL, data_mask, 0); + } #endif } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 3a4ae5797a0..132b721006e 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -55,6 +55,7 @@ #include "BLI_threads.h" #include "BLI_linklist.h" #include "BLI_bpath.h" +#include "BLI_math.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -698,7 +699,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; @@ -801,9 +802,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) @@ -1545,7 +1546,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); } @@ -1593,11 +1594,11 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f 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 */ @@ -1666,7 +1667,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; @@ -1690,15 +1691,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; @@ -1756,7 +1757,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); @@ -3322,10 +3323,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))) { copy_v3_v3(v[0], orcodata[mface->v1]); @@ -3640,7 +3641,6 @@ void make_local_particlesettings(ParticleSettings *part) } else if(is_local && is_lib) { ParticleSettings *part_new= psys_copy_settings(part); - part_new->id.us= 0; /* Remap paths of new ID using old library as base. */ @@ -3680,7 +3680,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co 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 @@ -3692,7 +3692,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co 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); @@ -4338,7 +4338,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, Partic 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); } @@ -4358,14 +4358,14 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, Partic 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); } @@ -4524,7 +4524,6 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] madd_v3_v3fl(center, yvec, bb->offset[1]); } - void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSimulationData sim= {0}; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5a64da7354e..f259ddbf577 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -61,7 +61,6 @@ #include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed! #include "DNA_listBase.h" -#include "BLI_edgehash.h" #include "BLI_rand.h" #include "BLI_jitter.h" #include "BLI_math.h" @@ -71,6 +70,7 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLI_linklist.h" +#include "BLI_edgehash.h" #include "BKE_main.h" #include "BKE_animsys.h" @@ -352,9 +352,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"); @@ -523,8 +523,8 @@ static void distribute_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; } @@ -783,7 +783,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch 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: @@ -813,7 +813,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch 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); @@ -825,7 +825,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch 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; @@ -873,7 +873,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch 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); @@ -1040,7 +1040,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D 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; @@ -1071,6 +1071,10 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D distr=PART_DISTR_RAND; BLI_srandom(31415926 + psys->seed + psys->child_seed); dm= finaldm; + + /* BMESH ONLY */ + DM_ensure_tessface(dm); + children=1; tree=BLI_kdtree_new(totpart); @@ -1092,6 +1096,11 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D dm= CDDM_from_mesh((Mesh*)ob->data, ob); + /* BMESH ONLY, for verts we dont care about tessfaces */ + if (from != PART_FROM_VERT) { + DM_ensure_tessface(dm); + } + /* we need orco for consistent distributions */ DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); @@ -1117,7 +1126,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D } /* Get total number of emission elements and allocate needed arrays */ - totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm); + totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm); if(totelem == 0){ distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0); @@ -1146,7 +1155,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D orcodata= dm->getVertDataArray(dm, CD_ORCO); for(i=0; i<totelem; i++){ - MFace *mf=dm->getFaceData(dm,i,CD_MFACE); + MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE); if(orcodata) { copy_v3_v3(co1, orcodata[mf->v1]); @@ -1204,7 +1213,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D } else { /* PART_FROM_FACE / PART_FROM_VOLUME */ for(i=0;i<totelem; 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) { @@ -1278,8 +1287,8 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX); } else { - if(dm->numFaceData) - COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); + if(dm->numTessFaceData) + COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); } if(COMPARE_ORIG_INDEX) { @@ -3502,7 +3511,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); } @@ -3537,7 +3546,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if(dvert) { if(!dvert->totweight) { - dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight"); dvert->totweight = 1; } @@ -3558,7 +3567,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if(dvert) { if(!dvert->totweight) { - dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight"); dvert->totweight = 1; } /* roots should be 1.0, the rest can be anything from 0.0 to 1.0 */ @@ -3575,7 +3584,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; deformedVerts = MEM_callocN(sizeof(*deformedVerts)*dm->getNumVerts(dm), "do_hair_dynamics vertexCos"); - psys->hair_out_dm = CDDM_copy(dm); + psys->hair_out_dm = CDDM_copy(dm, 0); psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts); clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, deformedVerts); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 6fd89db10e7..c5f948bb27f 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2302,7 +2302,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra if(timescale) { time= BKE_curframe(scene); - nexttime= BKE_frame_to_ctime(scene, CFRA+1); + nexttime= BKE_frame_to_ctime(scene, CFRA + 1.0f); *timescale= MAX2(nexttime - time, 0.0f); } diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index aed246690bd..820d474253f 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -54,6 +54,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")) @@ -89,11 +91,10 @@ 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) { DerivedMesh *dm = em->derivedFinal; - BKE_mesh_end_editmesh(me, em); return dm; } @@ -587,7 +588,9 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM } //free memory - if(ss_mesh) + if(ss_mesh) { + ss_mesh->needsFree = 1; ss_mesh->release(ss_mesh); + } } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 424f97f57ed..cd2d4c0c1f8 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -41,6 +41,7 @@ #include <stdio.h> #include <string.h> /* memset */ +#include "BLI_utildefines.h" #include "BLI_linklist.h" #include "BLI_rand.h" #include "BLI_jitter.h" @@ -49,7 +50,6 @@ #include "BLI_edgehash.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" -#include "BLI_utildefines.h" #include "BKE_bvhutils.h" #include "BKE_cdderivedmesh.h" @@ -317,7 +317,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; } @@ -328,7 +328,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 @@ -336,16 +336,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); } @@ -362,7 +362,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) copy_v3_v3(&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 @@ -1354,7 +1354,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); #endif // rigid movement support diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index ffcbd0bdc56..f8fec9911fb 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -44,12 +44,12 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_pbvh.h" -#include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_global.h" @@ -58,6 +58,10 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" +#include "BKE_tessmesh.h" + +#include "PIL_time.h" +#include "BLI_array.h" #include "GL/glew.h" @@ -69,9 +73,10 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ -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); static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm); /// @@ -206,13 +211,12 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg } } -static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) { - unsigned int *fv = &mf->v1; +static void get_face_uv_map_vert(UvVertMap *vmap, struct MPoly *mp, struct MLoop *ml, int fi, CCGVertHDL *fverts) { UvMapVert *v, *nv; - int j, nverts= mf->v4? 4: 3; + int j, nverts= mp->totloop; - for (j=0; j<nverts; j++, fv++) { - for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) { + for (j=0; j<nverts; j++) { + for (nv=v=get_uv_map_vert(vmap, ml[j].v); v; v=v->next) { if (v->separate) nv= v; if (v->f == fi) @@ -223,22 +227,24 @@ 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); +static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MLoopUV *mloopuv) { + MPoly *mpoly = dm->getPolyArray(dm); + MLoop *mloop = dm->getLoopArray(dm); MVert *mvert = dm->getVertArray(dm); int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); + int totface = dm->getNumPolys(dm); int i, j, seam; UvMapVert *v; UvVertMap *vmap; float limit[2]; - CCGVertHDL fverts[4]; + CCGVertHDL *fverts= NULL; + BLI_array_declare(fverts); EdgeHash *ehash; float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss); float uv[3]= {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0]= limit[1]= STD_UV_CONNECT_LIMIT; - vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit); + vmap= make_uv_vert_map(mpoly, mloop, mloopuv, totface, totvert, 0, limit); if (!vmap) return 0; @@ -260,7 +266,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, CCGVert *ssv; CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex); - copy_v2_v2(uv, (tface+v->f)->uv[v->tfindex]); + copy_v2_v2(uv, mloopuv[mpoly[v->f].loopstart + v->tfindex].uv); ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv); } @@ -271,18 +277,22 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, ehash = BLI_edgehash_new(); for (i=0; i<totface; i++) { - MFace *mf = &((MFace*) mface)[i]; - int nverts= mf->v4? 4: 3; + MPoly *mp = &((MPoly*) mpoly)[i]; + int nverts= mp->totloop; CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i)); - unsigned int *fv = &mf->v1; + /* unsigned int *fv = &mp->v1; */ + MLoop *ml= mloop + mp->loopstart; + + BLI_array_empty(fverts); + BLI_array_growitems(fverts, nverts); - get_face_uv_map_vert(vmap, mf, i, fverts); + get_face_uv_map_vert(vmap, mp, ml, i, fverts); for (j=0; j<nverts; j++) { int v0 = GET_INT_FROM_POINTER(fverts[j]); int v1 = GET_INT_FROM_POINTER(fverts[(j+1)%nverts]); - MVert *mv0 = mvert + *(fv+j); - MVert *mv1 = mvert + *(fv+((j+1)%nverts)); + MVert *mv0 = mvert + (ml[ j ]. v); + MVert *mv1 = mvert + (ml[ ((j+1)%nverts) ].v); if (!BLI_edgehash_haskey(ehash, v0, v1)) { CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j); @@ -304,14 +314,20 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, /* create faces */ for (i=0; i<totface; i++) { - MFace *mf = &((MFace*) mface)[i]; - int nverts= mf->v4? 4: 3; + MPoly *mp = &mpoly[i]; + MLoop *ml= &mloop[mp->loopstart]; + int nverts= mp->totloop; CCGFace *f; - get_face_uv_map_vert(vmap, mf, i, fverts); + BLI_array_empty(fverts); + BLI_array_growitems(fverts, nverts); + + get_face_uv_map_vert(vmap, mp, ml, i, fverts); ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f); } + BLI_array_free(fverts); + free_uv_vert_map(vmap); ccgSubSurf_processSync(ss); @@ -323,18 +339,22 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, CCGSubSurf *uvss; CCGFace **faceMap; MTFace *tf; + MLoopUV *mluv; CCGFaceIterator *fi; int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S; - MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n); + MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n); + /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with + * just tface except applying the modifier then looses subsurf UV */ MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n); + MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n); - if(!dmtface || !tface) + if(!dmloopuv || (!tface && !mloopuv)) return; /* create a CCGSubSurf from uv's */ uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), CCG_USE_ARENA); - if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) { + if(!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) { ccgSubSurf_free(uvss); return; } @@ -357,6 +377,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, /* load coordinates from uvss into tface */ tf= tface; + mluv= mloopuv; for(index = 0; index < totface; index++) { CCGFace *f = faceMap[index]; @@ -367,12 +388,27 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, for(y = 0; y < gridFaces; y++) { for(x = 0; x < gridFaces; x++) { - copy_v2_v2(tf->uv[0], faceGridData[(y + 0)*gridSize + x + 0]); - copy_v2_v2(tf->uv[1], faceGridData[(y + 1)*gridSize + x + 0]); - copy_v2_v2(tf->uv[2], faceGridData[(y + 1)*gridSize + x + 1]); - copy_v2_v2(tf->uv[3], faceGridData[(y + 0)*gridSize + x + 1]); + float *a = faceGridData[(y + 0)*gridSize + x + 0]; + float *b = faceGridData[(y + 0)*gridSize + x + 1]; + float *c = faceGridData[(y + 1)*gridSize + x + 1]; + float *d = faceGridData[(y + 1)*gridSize + x + 0]; + + if (tface) { + tf->uv[0][0] = a[0]; tf->uv[0][1] = a[1]; + tf->uv[1][0] = d[0]; tf->uv[1][1] = d[1]; + tf->uv[2][0] = c[0]; tf->uv[2][1] = c[1]; + tf->uv[3][0] = b[0]; tf->uv[3][1] = b[1]; + } + + if (mloopuv) { + mluv[0].uv[0] = a[0]; mluv[0].uv[1] = a[1]; + mluv[1].uv[0] = d[0]; mluv[1].uv[1] = d[1]; + mluv[2].uv[0] = c[0]; mluv[2].uv[1] = c[1]; + mluv[3].uv[0] = b[0]; mluv[3].uv[1] = b[1]; + } tf++; + mluv+=4; } } } @@ -383,65 +419,101 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, } /* face weighting */ -static void calc_ss_weights(int gridFaces, - FaceVertWeight **qweight, FaceVertWeight **tweight) +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) { - FaceVertWeight *qw, *tw; - int x, y, j; - int numWeights = gridFaces * gridFaces; - - *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight"); - *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight"); - - qw = *qweight; - tw = *tweight; - - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - for (j = 0; j < 4; j++) { - int fx = x + (j == 2 || j == 3); - int fy = y + (j == 1 || j == 2); - float x_v = (float) fx / gridFaces; - float y_v = (float) fy / gridFaces; - float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v); - float center = (1.0f / 3.0f) * tx_v * ty_v; - - (*tw)[j][0] = center + 0.5f * tx_v * y_v; - (*tw)[j][2] = center + 0.5f * x_v * ty_v; - (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2]; - (*tw)[j][3] = 0.0f; - - tx_v *= 0.5f; - ty_v *= 0.5f; - - (*qw)[j][3] = tx_v * ty_v; - (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v; - (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v; - (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3]; + 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.0f / (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.0f - fy + -fac2*fy*fac); + + fac2 = 1.0f - (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; + } } - tw++; - qw++; } } + + return wtable->weight_table[faceLen].w; } -static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, +static 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); + } + + if (wtable->weight_table) + MEM_freeN(wtable->weight_table); +} + +static int ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float (*vertexCos)[3], int useFlatSubdiv) { float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss); - CCGVertHDL fVerts[4]; - int totvert = dm->getNumVerts(dm); - int totedge = dm->getNumEdges(dm); - int totface = dm->getNumFaces(dm); - int i; - int *index; + CCGVertHDL *fVerts = NULL; + BLI_array_declare(fVerts); MVert *mvert = dm->getVertArray(dm); MEdge *medge = dm->getEdgeArray(dm); - MFace *mface = dm->getFaceArray(dm); + /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */ MVert *mv; MEdge *me; - MFace *mf; + MLoop *mloop = dm->getLoopArray(dm), *ml; + MPoly *mpoly = dm->getPolyArray(dm), *mp; + /*MFace *mf;*/ /*UNUSED*/ + int totvert = dm->getNumVerts(dm); + int totedge = dm->getNumEdges(dm); + /*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/ + /*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/ + int i, j; + int *index; ccgSubSurf_initFullSync(ss); @@ -474,38 +546,43 @@ 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++) { - CCGFace *f; + mp = mpoly; + index = DM_get_poly_data_layer(dm, CD_ORIGINDEX); + for (i=0; i<dm->numPolyData; i++, mp++) { + CCGFace *f=NULL; + + 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); + ml = mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + BLI_array_append(fVerts, SET_INT_IN_POINTER(ml->v)); + } /* 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), fVerts[3] ? 4 : 3, + if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), mp->totloop, 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; } - return; + return 0; } - ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i; + ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = index ? *index++: i; } ccgSubSurf_processSync(ss); + + BLI_array_free(fVerts); + return 1; } /***/ @@ -522,9 +599,9 @@ static 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); @@ -566,32 +643,38 @@ 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(cgdm->ss); +} +static int cgdm_getNumLoops(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalFaces(ccgdm->ss); + /* All subsurf faces are quads */ + return 4 * 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; @@ -604,10 +687,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; @@ -616,7 +699,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); @@ -638,28 +721,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); @@ -684,13 +767,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; @@ -701,17 +784,52 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) int gridSideEdges; int gridInternalEdges; + /* code added in bmesh but works correctly without, commenting - campbell */ +#if 0 + int lasti, previ; + i = lastface; + lasti = 0; + while (1) { + previ = i; + if (cgdm->faceMap[i].startEdge >= edgeNum) { + i -= fabsf(i-lasti)/2.0f; + } else if (cgdm->faceMap[i].startEdge < edgeNum) { + i += fabsf(i-lasti)/2.0f; + } else { + break; + } + + if (i < 0) { + i = 0; + break; + } + + if (i > lastface) { + i = lastface; + break; + + } + + if (i == lasti) + break; + + lasti = previ; + } + + i = i > 0 ? i - 1 : i; +#endif + 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); @@ -739,18 +857,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; @@ -763,8 +881,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; @@ -775,19 +893,19 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) int offset; int grid; int x, y; - int lastface = ccgSubSurf_getNumFaces(ss) - 1; - char *faceFlags = ccgdm->faceFlags; + /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/ + char *faceFlags = cgdm->faceFlags; memset(mf, 0, sizeof(*mf)); + if (faceNum >= cgdm->dm.numTessFaceData) + 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; @@ -807,8 +925,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; @@ -818,7 +936,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); @@ -847,7 +965,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++) { @@ -864,7 +982,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); @@ -875,25 +993,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); @@ -905,7 +1023,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); @@ -914,7 +1032,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); @@ -928,7 +1046,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)); @@ -956,18 +1074,18 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) 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); /* keep types in sync with MFace, avoid many conversions */ char flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; @@ -985,6 +1103,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; @@ -995,9 +1118,118 @@ 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 ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) +{ + 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; + MLoop *mv; + /* char *faceFlags = cgdm->faceFlags; */ /* UNUSED */ + + if (!cgdm->ehash) { + MEdge *medge; + + cgdm->ehash = BLI_edgehash_new(); + medge = cgdm->dm.getEdgeArray((DerivedMesh*)cgdm); + + for (i=0; i<cgdm->dm.numEdgeData; i++) { + BLI_edgehash_insert(cgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i)); + } + } + + totface = ccgSubSurf_getNumFaces(ss); + mv = mloop; + for(index = 0; index < totface; index++) { + CCGFace *f = cgdm->faceMap[index].face; + int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); + /* int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; */ /* UNUSED */ + /* int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; */ /* UNUSED */ + + for(S = 0; S < numVerts; S++) { + for(y = 0; y < gridSize - 1; y++) { + for(x = 0; x < gridSize - 1; x++) { + int v1, v2, v3, v4; + + v1 = getFaceIndex(ss, f, S, x + 0, y + 0, + edgeSize, gridSize); + + v2 = getFaceIndex(ss, f, S, x + 0, y + 1, + edgeSize, gridSize); + v3 = getFaceIndex(ss, f, S, x + 1, y + 1, + edgeSize, gridSize); + v4 = getFaceIndex(ss, f, S, x + 1, y + 0, + edgeSize, gridSize); + + mv->v = v1; + mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v1, v2)); + mv++, i++; + + mv->v = v2; + mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v2, v3)); + mv++, i++; + + mv->v = v3; + mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v3, v4)); + mv++, i++; + + mv->v = v4; + mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v4, v1)); + mv++, i++; + } + } + } + } +} + + +static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mface) +{ + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; + int index; + int totface; + int gridSize = ccgSubSurf_getGridSize(ss); + /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */ + int i = 0, k = 0; + char *faceFlags = cgdm->faceFlags; + + totface = ccgSubSurf_getNumFaces(ss); + for(index = 0; index < totface; index++) { + 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; + + for(S = 0; S < numVerts; S++) { + for(y = 0; y < gridSize - 1; y++) { + for(x = 0; x < gridSize - 1; x++) { + MPoly *mf = &mface[i]; + + 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; + mf->loopstart = k; + mf->totloop = 4; + + k += 4; + i++; + } + } + } + } +} + +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; @@ -1078,14 +1310,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); @@ -1093,9 +1325,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); @@ -1114,8 +1346,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; @@ -1243,13 +1475,13 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(draw } } static void ccgDM_drawLooseEdges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int totedge = ccgSubSurf_getNumEdges(ss); int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss); for (j=0; j< totedge; j++) { - CCGEdge *e = ccgdm->edgeMap[j].edge; + CCGEdge *e = cgdm->edgeMap[j].edge; DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); if (!ccgSubSurf_getEdgeNumFaces(e)) { @@ -1290,7 +1522,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) ccgdm_pbvh_update(ccgdm); if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) { - if(dm->numFaceData) { + if(dm->numTessFaceData) { /* should be per face */ if(!setMaterial(faceFlags[1]+1, NULL)) return; @@ -1371,23 +1603,23 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) } /* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, +static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; GPUVertexAttribs gattribs; DMVertexAttribs attribs= {{{NULL}}}; - /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ + /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ int gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; int edgeSize = ccgSubSurf_getEdgeSize(ss); - 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; @@ -1415,7 +1647,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, 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); @@ -1512,12 +1744,12 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, #undef PASSATTRIB } -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); } /* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) { +static void cgdm_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; GPUVertexAttribs gattribs; @@ -1662,14 +1894,14 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void * } -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 UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; int gridSize = ccgSubSurf_getGridSize(ss); unsigned char *cp1, *cp2; int useTwoSide=1, i, totface; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); cp1= col1; if(col2) { @@ -1688,7 +1920,7 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), uns glBegin(GL_QUADS); 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); for (S=0; S<numVerts; S++) { @@ -1729,33 +1961,33 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), uns glEnd(); } -static void ccgDM_drawFacesTex_common(DerivedMesh *dm, +static void cgdm_drawFacesTex_common(DerivedMesh *dm, int (*drawParams)(MTFace *tface, int has_mcol, int matnr), int (*drawParamsMapped)(void *userData, int index), int (*compareDrawOptions)(void *userData, int cur_index, int next_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; (void) compareDrawOptions; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_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)); @@ -1875,32 +2107,32 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, } } -static void ccgDM_drawFacesTex(DerivedMesh *dm, - int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr), +static void cgdm_drawFacesTex(DerivedMesh *dm, + int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr), int (*compareDrawOptions)(void *userData, int cur_index, int next_index), void *userData) { - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); + cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); } -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, - int (*setDrawOptions)(void *userData, int index), - int (*compareDrawOptions)(void *userData, int cur_index, int next_index), - void *userData) +static void cgdm_drawMappedFacesTex(DerivedMesh *dm, + int (*setDrawOptions)(void *userData, int index), + int (*compareDrawOptions)(void *userData, int cur_index, int next_index), + void *userData) { - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); + cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, 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) { glBegin(GL_LINES); - for(i = 0; i < dm->numFaceData; i++, mf++, tf++) { + for(i = 0; i < dm->numTessFaceData; i++, mf++, tf++) { if(!(mf->flag&ME_HIDE)) { glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); @@ -1930,25 +2162,25 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*compareDrawOptions)(void *userData, int cur_index, int next_index), void *userData, int useColors) { - 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; /* currently unused -- each original face is handled separately */ (void)compareDrawOptions; 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; @@ -2050,9 +2282,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, } } } -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); @@ -2080,9 +2312,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); @@ -2111,9 +2343,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)) { @@ -2131,7 +2363,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)) { @@ -2144,6 +2376,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); @@ -2160,15 +2396,75 @@ static void ccgDM_release(DerivedMesh *dm) { } } +static 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; + /* Avoid re-creation if the layer exists already */ + origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX); + if (origindex) { + return origindex; + } + DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX); @@ -2180,8 +2476,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; @@ -2194,12 +2490,18 @@ 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); + /* Avoid re-creation if the layer exists already */ + origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + if (origindex) { + return origindex; + } + DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); origindex= DM_get_edge_data_layer(dm, CD_ORIGINDEX); @@ -2212,7 +2514,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++) @@ -2225,23 +2527,29 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type) return DM_get_edge_data_layer(dm, type); } -static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) +static void *ccgDM_get_tessface_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); + /* Avoid re-creation if the layer exists already */ + origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); + if (origindex) { + return origindex; + } + + DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + 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); @@ -2252,19 +2560,49 @@ 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 void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type) +{ + if (type == CD_ORIGINDEX) { + /* ensure creation of CD_ORIGINDEX layer */ + ccgDM_get_vert_data_layer(dm, type); + } + + return DM_get_vert_data(dm, index, type); +} + +static void *ccgDM_get_edge_data(DerivedMesh *dm, int index, int type) +{ + if (type == CD_ORIGINDEX) { + /* ensure creation of CD_ORIGINDEX layer */ + ccgDM_get_edge_data_layer(dm, type); + } + + return DM_get_edge_data(dm, index, type); +} + +static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type) +{ + if (type == CD_ORIGINDEX) { + /* ensure creation of CD_ORIGINDEX layer */ + ccgDM_get_tessface_data_layer(dm, type); + } + + return DM_get_tessface_data(dm, index, 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); } @@ -2273,11 +2611,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; @@ -2313,15 +2651,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); @@ -2329,10 +2667,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; @@ -2340,12 +2678,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++) { @@ -2359,43 +2697,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) @@ -2477,55 +2815,92 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) return ccgdm->pbvh; } +static void ccgDM_recalcTesselection(DerivedMesh *UNUSED(dm)) +{ + /* Nothing to do: CCG handles creating its own tessfaces */ +} + +static void ccgDM_calcNormals(DerivedMesh *UNUSED(dm)) +{ + /* Nothing to do: CCG calculates normals during drawing */ +} + static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int drawInteriorEdges, 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, *base_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; + float *w = NULL; + WeightTable wtable = {0}; + /* MCol *mcol; */ /* UNUSED */ MEdge *medge = NULL; - MFace *mface = NULL; - int *orig_indices; - FaceVertWeight *qweight, *tweight; + /* MFace *mface = NULL; */ + 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.getNumLoops = cgdm_getNumLoops; + /* reuse of cgdm_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */ + ccgdm->dm.getNumPolys = 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.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.getVertData = DM_get_vert_data; - ccgdm->dm.getEdgeData = DM_get_edge_data; - ccgdm->dm.getFaceData = DM_get_face_data; + ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; + ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray; + ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray; + + ccgdm->dm.getVertData = ccgDM_get_vert_data; + ccgdm->dm.getEdgeData = ccgDM_get_edge_data; + ccgdm->dm.getTessFaceData = ccgDM_get_tessface_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_tessface_data_layer; ccgdm->dm.getNumGrids = ccgDM_getNumGrids; ccgdm->dm.getGridSize = ccgDM_getGridSize; ccgdm->dm.getGridData = ccgDM_getGridData; @@ -2534,35 +2909,43 @@ 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.calcNormals = ccgDM_calcNormals; + ccgdm->dm.recalcTesselation = ccgDM_recalcTesselection; + + 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.drawMappedFacesMat = ccgDM_drawMappedFacesMat; - ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; + ccgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex; + ccgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL; + ccgdm->dm.drawMappedFacesMat = cgdm_drawMappedFacesMat; + ccgdm->dm.drawUVEdges = cgdm_drawUVEdges; - ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; - ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges; - - ccgdm->dm.release = ccgDM_release; + ccgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp; + ccgdm->dm.drawMappedEdges = cgdm_drawMappedEdges; + + ccgdm->dm.release = cgdm_release; ccgdm->ss = ss; ccgdm->drawInteriorEdges = drawInteriorEdges; ccgdm->useSubsurfUv = useSubsurfUv; totvert = ccgSubSurf_getNumVerts(ss); - ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap"); + ccgdm->vertMap = MEM_callocN(totvert * sizeof(*ccgdm->vertMap), "vertMap"); vi = ccgSubSurf_getVertIterator(ss); for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { CCGVert *v = ccgVertIterator_getCurrent(vi); @@ -2572,7 +2955,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgVertIterator_free(vi); totedge = ccgSubSurf_getNumEdges(ss); - ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap"); + ccgdm->edgeMap = MEM_callocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap"); ei = ccgSubSurf_getEdgeIterator(ss); for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); @@ -2581,7 +2964,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, } totface = ccgSubSurf_getNumFaces(ss); - ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap"); + ccgdm->faceMap = MEM_callocN(totface * sizeof(*ccgdm->faceMap), "faceMap"); fi = ccgSubSurf_getFaceIterator(ss); for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { CCGFace *f = ccgFaceIterator_getCurrent(fi); @@ -2590,139 +2973,193 @@ 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 */ + /* mvert = dm->getVertArray(dm); */ /* UNUSED */ medge = dm->getEdgeArray(dm); - mface = dm->getFaceArray(dm); + /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */ + mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); + + /*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_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX); + +#if 0 + /* this is not in trunk, can gives problems because colors initialize + * as black, just dont do it!, it works fine - campbell */ + 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); +#endif + + 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; + + origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex; + + 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 ? mpoly[origIndex].flag : 0; + faceFlags[1] = mpoly ? mpoly[origIndex].mat_nr : 0; + 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); + BLI_array_growitems(loopidx, numVerts); + for (s = 0; s < numVerts; s++) { + loopidx[s] = loopindex++; + } + + BLI_array_empty(vertidx); + BLI_array_growitems(vertidx, numVerts); + for (s = 0; s < numVerts; s++) { + CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s); + 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)); @@ -2736,6 +3173,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; @@ -2744,16 +3184,36 @@ 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; } + if(useSubsurfUv) { + CustomData *ldata = &ccgdm->dm.loopData; + CustomData *dmldata = &dm->loopData; + int numlayer = CustomData_number_of_layers(ldata, CD_MLOOPUV); + int dmnumlayer = CustomData_number_of_layers(dmldata, CD_MLOOPUV); + + for (i=0; i<numlayer && i<dmnumlayer; i++) + set_subsurf_uv(ss, dm, &ccgdm->dm, i); + } + for(index = 0; index < totvert; ++index) { CCGVert *v = ccgdm->vertMap[index].vert; + int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v); int vertIdx; vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); @@ -2765,11 +3225,22 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1); + if (vertOrigIndex) { + *vertOrigIndex = mapIndex; + ++vertOrigIndex; + } ++vertNum; } - MEM_freeN(qweight); - MEM_freeN(tweight); + ccgdm->dm.numVertData = vertNum; + ccgdm->dm.numEdgeData = edgeNum; + ccgdm->dm.numTessFaceData = faceNum; + ccgdm->dm.numLoopData = loopindex2; + ccgdm->dm.numPolyData = faceNum; + + BLI_array_free(vertidx); + BLI_array_free(loopidx); + free_ss_weights(&wtable); return ccgdm; } @@ -2786,7 +3257,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); - CCGDerivedMesh *result; + CCGDerivedMesh *result = NULL; if(forEditMode) { int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; @@ -2814,7 +3285,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 levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; CCGSubSurf *ss; @@ -2837,7 +3308,13 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if(useIncremental && isFinalCalc) { smd->mCache = ss = _getSubSurf(smd->mCache, levels, useAging|CCG_CALC_NORMALS); - ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + if (!ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple)) { + //ccgSubSurf_free(smd->mCache); + smd->mCache = ss = _getSubSurf(NULL, levels, useAging); + + ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + + } result = getCCGDerivedMesh(smd->mCache, drawInteriorEdges, |