diff options
Diffstat (limited to 'source/blender/blenkernel')
50 files changed, 6902 insertions, 2441 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 15fdc2fe307..284e916e9ee 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,38 +114,43 @@ typedef struct DMGridAdjacency { typedef enum DerivedMeshType { DM_TYPE_CDDM, - DM_TYPE_EDITMESH, + DM_TYPE_EDITBMESH, DM_TYPE_CCGDM } DerivedMeshType; typedef struct DerivedMesh DerivedMesh; struct DerivedMesh { /* Private DerivedMesh data, only for internal DerivedMesh use */ - CustomData vertData, edgeData, faceData; - int numVertData, numEdgeData, numFaceData; + CustomData vertData, edgeData, faceData, loopData, polyData; + int numVertData, numEdgeData, numFaceData, numLoopData, numPolyData; int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ BVHCache bvhCache; struct GPUDrawObject *drawObject; DerivedMeshType type; + /* 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 (*getNumFaces) (DerivedMesh *dm); - /* copy a single vert/edge/face from the derived mesh into + /* copy a single vert/edge/tesselated face from the derived mesh into * *{vert/edge/face}_r. note that the current implementation * of this function can be quite slow, iterating over all * elements (editmesh) */ void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r); void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r); - void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r); + void (*getTessFace)(DerivedMesh *dm, int index, struct MFace *face_r); /* return a pointer to the entire array of verts/edges/face from the * derived mesh. if such an array does not exist yet, it will be created, @@ -120,21 +159,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 @@ -142,7 +187,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 @@ -150,8 +195,21 @@ struct DerivedMesh { */ void *(*getVertDataArray)(DerivedMesh *dm, int type); void *(*getEdgeDataArray)(DerivedMesh *dm, int type); - void *(*getFaceDataArray)(DerivedMesh *dm, int type); - + void *(*getTessFaceDataArray)(DerivedMesh *dm, int type); + + /*retrieves the base CustomData structures for + verts/edges/tessfaces/loops/facdes*/ + CustomData *(*getVertDataLayout)(DerivedMesh *dm); + CustomData *(*getEdgeDataLayout)(DerivedMesh *dm); + CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm); + CustomData *(*getLoopDataLayout)(DerivedMesh *dm); + CustomData *(*getFaceDataLayout)(DerivedMesh *dm); + + /*copies all customdata for an element source into dst at index dest*/ + void (*copyFromVertCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + void (*copyFromEdgeCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + void (*copyFromFaceCData)(DerivedMesh *dm, int source, CustomData *dst, int dest); + /* optional grid access for subsurf */ int (*getNumGrids)(DerivedMesh *dm); int (*getGridSize)(DerivedMesh *dm); @@ -254,8 +312,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)); /* Draw all faces with GLSL materials * o setMaterial is called for every different material nr @@ -346,15 +404,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 @@ -363,7 +422,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 */ @@ -384,6 +443,8 @@ void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); +void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype, + void *layer); void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype, void *layer); @@ -403,6 +464,7 @@ void *DM_get_face_data(struct DerivedMesh *dm, int index, int type); */ void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type); void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type); +void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type); void *DM_get_face_data_layer(struct DerivedMesh *dm, int type); /* custom data setting functions @@ -421,6 +483,10 @@ void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); +void DM_copy_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int source_index, int dest_index, int count); +void DM_copy_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int source_index, int dest_index, int count); void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); @@ -430,8 +496,13 @@ void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, */ void DM_free_vert_data(struct DerivedMesh *dm, int index, int count); void DM_free_edge_data(struct DerivedMesh *dm, int index, int count); +void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count); +void DM_free_loop_data(struct DerivedMesh *dm, int index, int count); void DM_free_face_data(struct DerivedMesh *dm, int index, int count); +/*sets up mpolys for a DM based on face iterators in source*/ +void DM_DupPolys(DerivedMesh *source, DerivedMesh *target); + /* interpolates vertex data from the vertices indexed by src_indices in the * source mesh using the given weights and stores the result in the vertex * indexed by dest_index in the dest mesh @@ -461,12 +532,20 @@ void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest, * vert_weights[i] multiplied by weights[i]. */ typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE]; -void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, +void DM_interp_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest, int *src_indices, float *weights, FaceVertWeight *vert_weights, int count, int dest_index); -void DM_swap_face_data(struct DerivedMesh *dm, int index, const int *corner_indices); +void DM_swap_tessface_data(struct DerivedMesh *dm, int index, const int *corner_indices); + +void DM_interp_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index); + +void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index); /* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */ void vDM_ColorBand_store(struct ColorBand *coba); @@ -482,11 +561,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 */ @@ -505,20 +588,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, diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 34b674fcb4a..73f2fdc2a51 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 9739a5eacf2..cddc42315b7 100644 --- a/source/blender/blenkernel/BKE_bmesh.h +++ b/source/blender/blenkernel/BKE_bmesh.h @@ -54,6 +54,7 @@ struct BME_Edge; struct BME_Poly; struct BME_Loop; +/*NOTE: this is the bmesh 1.0 code. it's completely outdated.*/ /*Notes on further structure Cleanup: -Remove the tflags, they belong in custom data layers diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index c71c86e110d..c24db5dd1f8 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); + +/* merge verts */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap); /* creates a CDDerivedMesh from the given curve object */ struct DerivedMesh *CDDM_from_curve(struct Object *ob); @@ -61,17 +69,26 @@ struct DerivedMesh *CDDM_from_curve(struct Object *ob); /* useful for OrcoDM creation for curves with constructive modifiers */ DerivedMesh *CDDM_from_curve_customDB(struct Object *ob, struct ListBase *dispbase); +struct BMEditMesh *CDDM_To_BMesh(struct Object *ob, struct DerivedMesh *dm, struct BMEditMesh *existing); + + /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. */ -struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); +struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm, int faces_from_tessfaces); /* creates a CDDerivedMesh with the same layer stack configuration as the * given DerivedMesh and containing the requested numbers of elements. * elements are initialised to all zeros */ struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source, - int numVerts, int numEdges, int numFaces); + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys); + +/*converts mfaces to mpolys. note things may break if there are not valid + *medges surrounding each mface. + */ +void CDDM_tessfaces_to_faces(struct DerivedMesh *dm); /* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert * layer is a referenced layer, it will be duplicate to not overwrite the @@ -86,9 +103,17 @@ void CDDM_calc_normals(struct DerivedMesh *dm); /* calculates edges for a CDDerivedMesh (from face data) * this completely replaces the current edge data in the DerivedMesh + * builds edges from the tesselated face data. */ void CDDM_calc_edges(struct DerivedMesh *dm); +/* same as CDDM_calc_edges only makes edges from ngon faces instead of tesselation + faces*/ +void CDDM_calc_edges_poly(struct DerivedMesh *dm); + +/* reconstitute face triangulation */ +void CDDM_recalc_tesselation(struct DerivedMesh *dm); + /* lowers the number of vertices/edges/faces in a CDDerivedMesh * the layer data stays the same size */ @@ -102,7 +127,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 +138,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 5497866b9df..6dc3baa2746 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -38,11 +38,15 @@ extern "C" { #endif +struct BMesh; struct ID; struct CustomData; struct CustomDataLayer; typedef unsigned int CustomDataMask; +/*a data type large enough to hold 1 element from any customdata layer type*/ +typedef struct {unsigned char data[64];} CDBlockBytes; + extern const CustomDataMask CD_MASK_BAREMESH; extern const CustomDataMask CD_MASK_MESH; extern const CustomDataMask CD_MASK_EDITMESH; @@ -65,17 +69,45 @@ extern const CustomDataMask CD_MASK_FACECORNERS; #define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source has same number of elements */ +/* Checks if the layer at physical offset layern (in data->layers) support math + * the below operations. + */ +int CustomData_layer_has_math(struct CustomData *data, int layern); + +/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to + another, while not overwriting anything else (e.g. flags). probably only + implemented for mloopuv/mloopcol, for now.*/ +void CustomData_data_copy_value(int type, void *source, void *dest); + +/* compares if data1 is equal to data2. type is a valid CustomData type + * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare + * the data, if it exists, otherwise memcmp is used.*/ +int CustomData_data_equals(int type, void *data1, void *data2); +void CustomData_data_initminmax(int type, void *min, void *max); +void CustomData_data_dominmax(int type, void *data, void *min, void *max); +void CustomData_data_multiply(int type, void *data, float fac); +void CustomData_data_add(int type, void *data1, void *data2); + /* initialises a CustomData object with the same layer setup as source. * mask is a bitfield where (mask & (1 << (layer type))) indicates * if a layer should be copied or not. alloctype must be one of the above. */ void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem); +/* BMESH_TODO, not really a public function but readfile.c needs it */ +void CustomData_update_typemap(struct CustomData *data); + /* same as the above, except that this will preserve existing layers, and only * add the layers that were not there yet */ 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) */ @@ -140,12 +172,13 @@ void CustomData_set_only_copy(const struct CustomData *data, void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count); +void CustomData_copy_elements(int type, void *source, void *dest, int count); void CustomData_em_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block); void CustomData_bmesh_copy_data(const struct CustomData *source, - struct CustomData *dest,void *src_block, - void **dest_block); + struct CustomData *dest, void *src_block, + void **dest_block); void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); /* frees data in a CustomData object @@ -187,11 +220,18 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic * returns NULL if there is no layer of type */ void *CustomData_get(const struct CustomData *data, int index, int type); +void *CustomData_get_n(const struct CustomData *data, int type, int index, int n); void *CustomData_em_get(const struct CustomData *data, void *block, int type); void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n); void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type); void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n); +/* gets the layer at physical index n, with no type checking. + */ +void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n); + +int CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name); + /* gets a pointer to the active or first layer of type * returns NULL if there is no layer of type */ @@ -199,8 +239,8 @@ void *CustomData_get_layer(const struct CustomData *data, int type); void *CustomData_get_layer_n(const struct CustomData *data, int type, int n); void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name); - int CustomData_get_layer_index(const struct CustomData *data, int type); +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n); int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); @@ -227,6 +267,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type, void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, void *source); +/*sets the data of the block at physical layer n. no real type checking + *is performed. + */ +void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n, + void *source); /* set the pointer of to the first layer of type. the old data is not freed. * returns the value of ptr if the layer is found, NULL otherwise @@ -285,7 +330,8 @@ void CustomData_validate_layer_name(const struct CustomData *data, int type, cha int CustomData_verify_versions(struct CustomData *data, int index); /*BMesh specific customdata stuff*/ -void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, + struct CustomData *ldata, int totloop, int totpoly); void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); diff --git a/source/blender/blenkernel/BKE_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 900835940c7..054ce35b31c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -36,12 +36,15 @@ struct BoundBox; struct DispList; struct ListBase; -struct EditMesh; -struct MDeformVert; +struct BMEditMesh; +struct BMesh; struct Mesh; +struct MPoly; +struct MLoop; struct MFace; struct MEdge; struct MVert; +struct MDeformVert; struct MCol; struct Object; struct MTFace; @@ -49,19 +52,41 @@ struct VecNor; struct CustomData; struct DerivedMesh; struct Scene; +struct MLoopUV; #ifdef __cplusplus 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); + +/*calculates a face normal.*/ +void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float *no); void unlink_mesh(struct Mesh *me); -void free_mesh(struct Mesh *me); +void free_mesh(struct Mesh *me, int unlink); struct Mesh *add_mesh(const char *name); struct Mesh *copy_mesh(struct Mesh *me); void mesh_update_customdata_pointers(struct Mesh *me); + void make_local_mesh(struct Mesh *me); void boundbox_mesh(struct Mesh *me, float *loc, float *size); void tex_space_mesh(struct Mesh *me); @@ -71,17 +96,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_tessface_normals(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); @@ -95,7 +129,9 @@ 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(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]); /* Return a newly MEM_malloc'd array of all the mesh vertex locations * (_numVerts_r_ may be NULL) */ @@ -118,7 +154,7 @@ typedef struct UvMapVert { unsigned char tfindex, separate, flag; } UvMapVert; -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); @@ -159,6 +195,11 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, int update); void BKE_mesh_ensure_navmesh(struct Mesh *me); +/*convert a triangle of loop facedata to mface facedata*/ +void mesh_loops_to_tri_corners(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int lindex[3], int findex, + int polyindex); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index a47cefe6f65..db57f2e30fa 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 */ @@ -146,13 +147,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 *********************/ @@ -190,7 +191,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_paint.h b/source/blender/blenkernel/BKE_paint.h index 081b79b44d6..fd80006d71d 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -86,7 +86,7 @@ typedef struct SculptSession { /* Partial redraw */ int partial_redraw; - + /* Used to cache the render of the active texture */ unsigned int texcache_side, *texcache, texcache_actual; diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 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..48549f5660d --- /dev/null +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -0,0 +1,71 @@ +#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; + +void BMEdit_RecalcTesselation(BMEditMesh *tm); +BMEditMesh *BMEdit_Create(BMesh *bm); +BMEditMesh *BMEdit_Copy(BMEditMesh *tm); +void BMEdit_Free(BMEditMesh *em); +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em); + +#endif /* _BKE_TESSMESH_H */ diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 3222167c56e..b5b3c7e67eb 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -36,6 +36,10 @@ #ifndef BKE_UTILDEFINES_H #define BKE_UTILDEFINES_H +#ifdef __cplusplus +extern "C" { +#endif + /* these values need to be hardcoded in structs, dna does not recognize defines */ /* also defined in DNA_space_types.h */ #ifndef FILE_MAXDIR @@ -81,6 +85,8 @@ /* bit-row */ #define BROW(min, max) (((max)>=31? 0xFFFFFFFF: (1<<(max+1))-1) - ((min)? ((1<<(min))-1):0) ) -#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;} +#ifdef __cplusplus +} +#endif #endif // BKE_UTILDEFINES_H diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b4745669ff0..61375be1dc7 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 @@ -91,6 +92,7 @@ set(SRC intern/displist.c intern/dynamicpaint.c intern/effect.c + intern/editderivedbmesh.c intern/fcurve.c intern/fluidsim.c intern/fmodifier.c @@ -113,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 +230,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 8a6426eb3d5..94307968933 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 @@ -86,7 +87,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc if(data->totlayer){ /*alloc memory*/ data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers"); - data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0); + data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 1); /*initialize layer data*/ for(i=0; i < BME_CD_NUMTYPES; i++){ if(init->layout[i]){ @@ -199,3 +200,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 1b5761fb94e..89f9a6bc945 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], 0); - bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 0); - bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 0); - bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 0); + bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 1, 0); + bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 1, 0); + bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 1, 0); + bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 1, 0); return bm; } /* @@ -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 d1c258cbc93..203a07e0cfc 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. @@ -118,20 +119,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; } @@ -140,28 +141,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; } } @@ -178,8 +179,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); } @@ -231,8 +232,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; @@ -249,8 +250,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); } @@ -287,8 +288,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; @@ -298,8 +299,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); } @@ -340,14 +341,14 @@ static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransDa if (compare_v3v3(vtd1->org,vtd2->org,0.000001f)) { VECSUB(vec,v2->co,v1->co); if (len_v3(vec) < 0.000001f) { - mul_v3_fl(vec,0); + zero_v3(vec); } return 0; } else { VECSUB(vec,vtd2->org,vtd1->org); if (len_v3(vec) < 0.000001f) { - mul_v3_fl(vec,0); + zero_v3(vec); } return 1; } @@ -405,12 +406,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; @@ -591,8 +592,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); @@ -607,7 +608,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; @@ -632,7 +633,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; @@ -652,14 +653,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); } @@ -670,7 +671,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; @@ -689,13 +690,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); } @@ -704,7 +705,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){ @@ -870,8 +871,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; @@ -910,7 +911,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; } @@ -955,11 +956,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); } @@ -1026,13 +1027,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) { @@ -1096,7 +1097,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; } @@ -1146,26 +1147,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) { @@ -1191,7 +1192,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); @@ -1205,7 +1206,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"); } @@ -1216,10 +1217,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 */ @@ -1325,3 +1326,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 4400c895b78..68aa5f883f4 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" #ifdef WITH_GAMEENGINE #include "BKE_navmesh_conversion.h" @@ -77,6 +81,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); + /////////////////////////////////// /////////////////////////////////// @@ -114,14 +121,42 @@ static MFace *dm_getFaceArray(DerivedMesh *dm) if (!mface) { mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, - dm->getNumFaces(dm)); + dm->getNumTessFaces(dm)); CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY); - dm->copyFaceArray(dm, mface); + dm->copyTessFaceArray(dm, mface); } return mface; } +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->numLoopData); + 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->getNumFaces(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), @@ -144,41 +179,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->numLoopData, + "dm_dupLoopArray tmp"); + + if(tmp) dm->copyLoopArray(dm, tmp); + + return tmp; +} + +static MPoly *dm_dupPolyArray(DerivedMesh *dm) +{ + MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->numFaceData, + "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_getFaceCData(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_getFaceArray; + 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_getFaceCData; + dm->getLoopDataLayout = dm_getLoopCData; + dm->getFaceDataLayout = dm_getPolyCData; dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; - dm->getFaceData = DM_get_face_data; + dm->getTessFaceData = DM_get_face_data; dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getFaceDataArray = DM_get_face_data_layer; + dm->getTessFaceDataArray = DM_get_tessface_data_layer; bvhcache_init(&dm->bvhCache); } -void DM_init(DerivedMesh *dm, DerivedMeshType type, - int numVerts, int numEdges, int numFaces) +void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, + int numFaces, int numLoops, int numPoly) { dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPoly; DM_init_funcs(dm); @@ -186,7 +278,8 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, } void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, - int numVerts, int numEdges, int numFaces) + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys) { CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH, CD_CALLOC, numVerts); @@ -194,11 +287,17 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type CD_CALLOC, numEdges); CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, numFaces); + CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH, + CD_CALLOC, numLoops); + CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH, + CD_CALLOC, numPolys); dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; DM_init_funcs(dm); @@ -213,6 +312,8 @@ int DM_release(DerivedMesh *dm) CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); CustomData_free(&dm->faceData, dm->numFaceData); + CustomData_free(&dm->loopData, dm->numLoopData); + CustomData_free(&dm->polyData, dm->numPolyData); return 1; } @@ -220,55 +321,120 @@ int DM_release(DerivedMesh *dm) CustomData_free_temporary(&dm->vertData, dm->numVertData); CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); CustomData_free_temporary(&dm->faceData, dm->numFaceData); + CustomData_free_temporary(&dm->loopData, dm->numLoopData); + CustomData_free_temporary(&dm->polyData, dm->numPolyData); return 0; } } -void DM_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); + } +} + +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, 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); + totpoly = tmp.totpoly = dm->getNumFaces(dm); + totloop = tmp.totloop = dm->numLoopData; 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("error in DM_to_mesh: could not find active shapekey! eek!!\n"); + 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); } } + tmp.totface = mesh_recalcTesselation(&tmp.fdata, &tmp.ldata, &tmp.pdata, tmp.mvert, tmp.totface, tmp.totloop, tmp.totpoly); mesh_update_customdata_pointers(&tmp); 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; } @@ -313,11 +479,21 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer) CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData); } -void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer) { CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData); } +static void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +{ + CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData); +} + +void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer) +{ + CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData); +} + void *DM_get_vert_data(DerivedMesh *dm, int index, int type) { return CustomData_get(&dm->vertData, index, type); @@ -349,14 +525,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_face_data_layer(DerivedMesh *dm, int type) +{ + return CustomData_get_layer(&dm->polyData, type); +} + void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data) { CustomData_set(&dm->vertData, index, type, data); @@ -386,13 +567,27 @@ void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest, source_index, dest_index, count); } -void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest, +void DM_copy_tessface_data(DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count) { CustomData_copy_data(&source->faceData, &dest->faceData, source_index, dest_index, count); } +void DM_copy_loop_data(DerivedMesh *source, DerivedMesh *dest, + int source_index, int dest_index, int count) +{ + CustomData_copy_data(&source->loopData, &dest->loopData, + source_index, dest_index, count); +} + +void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest, + int source_index, int dest_index, int count) +{ + CustomData_copy_data(&source->polyData, &dest->polyData, + source_index, dest_index, count); +} + void DM_free_vert_data(struct DerivedMesh *dm, int index, int count) { CustomData_free_elem(&dm->vertData, index, count); @@ -403,11 +598,21 @@ void DM_free_edge_data(struct DerivedMesh *dm, int index, int count) CustomData_free_elem(&dm->edgeData, index, count); } -void DM_free_face_data(struct DerivedMesh *dm, int index, int count) +void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count) { CustomData_free_elem(&dm->faceData, index, count); } +void DM_free_loop_data(struct DerivedMesh *dm, int index, int count) +{ + CustomData_free_elem(&dm->loopData, index, count); +} + +void DM_free_face_data(struct DerivedMesh *dm, int index, int count) +{ + CustomData_free_elem(&dm->polyData, index, count); +} + void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest, int *src_indices, float *weights, int count, int dest_index) @@ -425,7 +630,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) @@ -434,13 +639,28 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, weights, (float*)vert_weights, count, dest_index); } -void DM_swap_face_data(DerivedMesh *dm, int index, const int *corner_indices) +void DM_swap_tessface_data(DerivedMesh *dm, int index, const int *corner_indices) { CustomData_swap(&dm->faceData, index, corner_indices); } -/// +void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index) +{ + CustomData_interp(&source->loopData, &dest->loopData, src_indices, + weights, NULL, count, dest_index); +} + +void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, + int *src_indices, + float *weights, int count, int dest_index) +{ + CustomData_interp(&source->polyData, &dest->polyData, src_indices, + weights, NULL, count, dest_index); +} +/// DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -456,1181 +676,10 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) return dm; } -/// - -typedef struct { - DerivedMesh dm; - - EditMesh *em; - float (*vertexCos)[3]; - float (*vertexNos)[3]; - float (*faceNos)[3]; -} EditMeshDerivedMesh; - -static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) { - if (emdm->vertexCos) { - func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL); - } else { - func(userData, i, eve->co, eve->no, NULL); - } - } -} -static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) - func(userData, i, emdm->vertexCos[(int) eed->v1->tmp.l], emdm->vertexCos[(int) eed->v2->tmp.l]); - } else { - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) - func(userData, i, eed->v1->co, eed->v2->co); - } -} -static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - glBegin(GL_LINES); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); - } - } - glEnd(); - } else { - glBegin(GL_LINES); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} -static void emDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges)) -{ - emDM_drawMappedEdges(dm, NULL, NULL); -} -static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditEdge *eed; - int i; - - if (emdm->vertexCos) { - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]); - } - } - glEnd(); - } else { - glBegin(GL_LINES); - for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(eed->v1->co); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} - -static void emDM_drawUVEdges(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; - MTFace *tf; - - glBegin(GL_LINES); - for(efa= emdm->em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE); - - if(tf && !(efa->h)) { - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - - if (!efa->v4) { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[0]); - } else { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[0]); - } - } - } - glEnd(); -} - -static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3]) -{ - if (vertexCos) { - 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]); - } 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); - } - - if (efa->v4) { - mul_v3_fl(cent, 0.25f); - } else { - mul_v3_fl(cent, 0.33333333333f); - } -} -static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - EditFace *efa; - float cent[3]; - int i; - - if (emdm->vertexCos) { - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - } - - for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - emDM__calcFaceCent(efa, cent, emdm->vertexCos); - func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n); - } -} - -/* note, material function is ignored for now. */ -static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs), - int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditFace *efa; - int i, draw; - const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */ - - /* GL_ZERO is used to detect if drawing has started or not */ - GLenum poly_prev= GL_ZERO; - GLenum shade_prev= GL_ZERO; - - (void)setMaterial; /* unused */ - - /* currently unused -- each original face is handled separately */ - (void)compareDrawOptions; - - if (emdm->vertexCos) { - /* add direct access */ - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - float (*faceNos)[3]= emdm->faceNos; - EditVert *eve; - - for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if(draw) { - const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES; - if (draw==2) { /* enabled with stipple */ - - if(poly_prev != GL_ZERO) glEnd(); - poly_prev= GL_ZERO; /* force glBegin */ - - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - - if(skip_normals) { - if(poly_type != poly_prev) { - if(poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); - } - 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]); - } - 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)); - } - else if(poly_type != poly_prev) { - if(poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); - } - - 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]); - } 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]); - } - } - } - - - if (draw==2) { - glEnd(); - poly_prev= GL_ZERO; /* force glBegin */ - - glDisable(GL_POLYGON_STIPPLE); - } - } - } - } - else { - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if(draw) { - const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES; - if (draw==2) { /* enabled with stipple */ - - if(poly_prev != GL_ZERO) glEnd(); - poly_prev= GL_ZERO; /* force glBegin */ - - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - - if(skip_normals) { - if(poly_type != poly_prev) { - if(poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); - } - glVertex3fv(efa->v1->co); - glVertex3fv(efa->v2->co); - glVertex3fv(efa->v3->co); - if(poly_type == GL_QUADS) glVertex3fv(efa->v4->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)); - } - else if(poly_type != poly_prev) { - if(poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev= poly_type)); - } - - 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); - } 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); - } - } - } - - - if (draw==2) { - glEnd(); - poly_prev= GL_ZERO; - - glDisable(GL_POLYGON_STIPPLE); - } - } - } - } - - /* if non zero we know a face was rendered */ - if(poly_prev != GL_ZERO) glEnd(); -} - -static void emDM_drawFacesTex_common(DerivedMesh *dm, - int (*drawParams)(MTFace *tface, int has_mcol, int matnr), - int (*drawParamsMapped)(void *userData, int index), - void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - EditFace *efa; - int i; - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - if (vertexCos) { - EditVert *eve; - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - unsigned char *cp= NULL; - int drawSmooth= (efa->flag & ME_SMOOTH); - int flag; - - if(drawParams) - flag= drawParams(tf, (mcol != NULL), efa->mat_nr); - else if(drawParamsMapped) - flag= drawParamsMapped(userData, i); - else - flag= 1; - - if(flag != 0) { /* flag 0 == the face is hidden or invisible */ - - /* we always want smooth here since otherwise vertex colors dont interpolate */ - if (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } else { - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - } - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(emdm->faceNos[i]); - - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - } else { - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - } - glEnd(); - } - } - } else { - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - unsigned char *cp= NULL; - int drawSmooth= (efa->flag & ME_SMOOTH); - int flag; - - if(drawParams) - flag= drawParams(tf, (mcol != NULL), efa->mat_nr); - else if(drawParamsMapped) - flag= drawParamsMapped(userData, i); - else - flag= 1; - - if(flag != 0) { /* flag 0 == the face is hidden or invisible */ - /* we always want smooth here since otherwise vertex colors dont interpolate */ - if (mcol) { - if (flag==1) { - cp= (unsigned char*)mcol; - } - } else { - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - } - - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->n); - - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(efa->v1->co); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3fv(efa->v2->co); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3fv(efa->v3->co); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3fv(efa->v4->co); - } - } else { - if(tf) glTexCoord2fv(tf->uv[0]); - if(cp) glColor3ub(cp[3], cp[2], cp[1]); - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - - if(tf) glTexCoord2fv(tf->uv[1]); - if(cp) glColor3ub(cp[7], cp[6], cp[5]); - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - - if(tf) glTexCoord2fv(tf->uv[2]); - if(cp) glColor3ub(cp[11], cp[10], cp[9]); - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - - if(efa->v4) { - if(tf) glTexCoord2fv(tf->uv[3]); - if(cp) glColor3ub(cp[15], cp[14], cp[13]); - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - glEnd(); - } - } - } -} - -static void emDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr)) -{ - emDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); -} - -static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) -{ - emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); -} - -static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs), - int (*setDrawOptions)(void *userData, int index), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - EditVert *eve; - EditFace *efa; - DMVertexAttribs attribs= {{{0}}}; - GPUVertexAttribs gattribs; - /* int tfoffset; */ /* UNUSED */ - int i, b, matnr, new_matnr, dodraw /* , layer */ /* UNUSED */; - - dodraw = 0; - matnr = -1; - - /* layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); */ /* UNUSED */ - /* tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; */ /* UNUSED */ - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - -#define PASSATTRIB(efa, eve, vert) { \ - if(attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ - glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ - } \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[i*4 + vert]; \ - glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ - } \ -} - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth= (efa->flag & ME_SMOOTH); - - if(setDrawOptions && !setDrawOptions(userData, i)) - continue; - - new_matnr = efa->mat_nr + 1; - if(new_matnr != matnr) { - dodraw = setMaterial(matnr = new_matnr, &gattribs); - if(dodraw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - if(dodraw) { - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - if(vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); - - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - else glVertex3fv(efa->v3->co); - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - else glVertex3fv(efa->v4->co); - } - } else { - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - } - else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - } - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - } - else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - } - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - } - else { - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - } - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - else { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - } - glEnd(); - } - } -#undef PASSATTRIB -} - -static void emDM_drawFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -static void emDM_drawMappedFacesMat(DerivedMesh *dm, - 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; - DMVertexAttribs attribs= {{{0}}}; - GPUVertexAttribs gattribs; - int i, b, matnr, new_matnr; - - matnr = -1; - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - -#define PASSATTRIB(efa, eve, vert) { \ - if(attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ - if(attribs.orco.glTexco) \ - glTexCoord3fv(orco); \ - else \ - 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]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[i*4 + vert]; \ - glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \ - } \ -} - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth= (efa->flag & ME_SMOOTH); - - /* face hiding */ - if(setFace && !setFace(userData, i)) - continue; - - /* material */ - new_matnr = efa->mat_nr + 1; - if(new_matnr != matnr) { - setMaterial(userData, matnr = new_matnr, &gattribs); - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - /* face */ - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - if(vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); - - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - else glVertex3fv(efa->v3->co); - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - else glVertex3fv(efa->v4->co); - } - } else { - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - } - else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - } - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - } - else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - } - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - } - else { - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - } - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - else { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - } - glEnd(); - } -#undef PASSATTRIB -} - -static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - if (emdm->em->verts.first) { - for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) { - if (emdm->vertexCos) { - DO_MINMAX(emdm->vertexCos[i], min_r, max_r); - } else { - DO_MINMAX(eve->co, min_r, max_r); - } - } - } else { - min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; - } -} -static int emDM_getNumVerts(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->verts); -} - -static int emDM_getNumEdges(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->edges); -} - -static int emDM_getNumFaces(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - return BLI_countlist(&emdm->em->faces); -} - -static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - - for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) { - if (emdm->vertexCos) { - copy_v3_v3(cos_r[i], emdm->vertexCos[i]); - } else { - copy_v3_v3(cos_r[i], eve->co); - } - } -} - -static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) -{ - EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first; - int i; - - for(i = 0; i < index; ++i) ev = ev->next; - - 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); -} - -static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditEdge *ee = em->edges.first; - EditVert *ev, *v1, *v2; - int i; - - for(i = 0; i < index; ++i) ee = ee->next; - - edge_r->crease = (unsigned char) (ee->crease*255.0f); - edge_r->bweight = (unsigned char) (ee->bweight*255.0f); - /* TODO what to do with edge_r->flag? */ - edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; - if (ee->seam) edge_r->flag |= ME_SEAM; - if (ee->sharp) edge_r->flag |= ME_SHARP; -#if 0 - /* this needs setup of f2 field */ - if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; -#endif - - /* goddamn, we have to search all verts to find indices */ - v1 = ee->v1; - v2 = ee->v2; - for(i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) { - if(ev == v1) { - edge_r->v1 = i; - v1 = NULL; - } - if(ev == v2) { - edge_r->v2 = i; - v2 = NULL; - } - } -} - -static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditFace *ef = em->faces.first; - EditVert *ev, *v1, *v2, *v3, *v4; - int i; - - for(i = 0; i < index; ++i) ef = ef->next; - - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; - - /* goddamn, we have to search all verts to find indices */ - v1 = ef->v1; - v2 = ef->v2; - v3 = ef->v3; - v4 = ef->v4; - if(!v4) face_r->v4 = 0; - - for(i = 0, ev = em->verts.first; v1 || v2 || v3 || v4; - i++, ev = ev->next) { - if(ev == v1) { - face_r->v1 = i; - v1 = NULL; - } - if(ev == v2) { - face_r->v2 = i; - v2 = NULL; - } - if(ev == v3) { - face_r->v3 = i; - v3 = NULL; - } - if(ev == v4) { - face_r->v4 = i; - v4 = NULL; - } - } - - test_index_face(face_r, NULL, 0, ef->v4?4:3); -} - -static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *ev = emdm->em->verts.first; - int i; - - for(i=0; ev; ev = ev->next, ++vert_r, ++i) { - if(emdm->vertexCos) - copy_v3_v3(vert_r->co, emdm->vertexCos[i]); - else - copy_v3_v3(vert_r->co, ev->co); - - 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); - } -} - -static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditEdge *ee = em->edges.first; - EditVert *ev; - int i; - - /* store vertex indices in tmp union */ - for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i) - ev->tmp.l = (intptr_t) i; - - for( ; ee; ee = ee->next, ++edge_r) { - edge_r->crease = (unsigned char) (ee->crease*255.0f); - edge_r->bweight = (unsigned char) (ee->bweight*255.0f); - /* TODO what to do with edge_r->flag? */ - edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; - if (ee->seam) edge_r->flag |= ME_SEAM; - if (ee->sharp) edge_r->flag |= ME_SHARP; -#if 0 - /* this needs setup of f2 field */ - if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; -#endif - - edge_r->v1 = (int)ee->v1->tmp.l; - edge_r->v2 = (int)ee->v2->tmp.l; - } -} - -static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) -{ - EditMesh *em = ((EditMeshDerivedMesh *)dm)->em; - EditFace *ef = em->faces.first; - EditVert *ev; - int i; - - /* store vertexes indices in tmp union */ - for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i) - ev->tmp.l = (intptr_t) i; - - for( ; ef; ef = ef->next, ++face_r) { - face_r->mat_nr = ef->mat_nr; - face_r->flag = ef->flag; - - face_r->v1 = (int)ef->v1->tmp.l; - face_r->v2 = (int)ef->v2->tmp.l; - face_r->v3 = (int)ef->v3->tmp.l; - if(ef->v4) face_r->v4 = (int)ef->v4->tmp.l; - else face_r->v4 = 0; - - test_index_face(face_r, NULL, 0, ef->v4?4:3); - } -} - -static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - EditFace *efa; - char *data, *emdata; - void *datalayer; - int index, size; - - datalayer = DM_get_face_data_layer(dm, type); - if(datalayer) - return datalayer; - - /* layers are store per face for editmesh, we convert to a temporary - * data layer array in the derivedmesh when these are requested */ - if(type == CD_MTFACE || type == CD_MCOL) { - index = CustomData_get_layer_index(&em->fdata, type); - - if(index != -1) { - /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */ - size = CustomData_sizeof(type); - - DM_add_face_layer(dm, type, CD_CALLOC, NULL); - index = CustomData_get_layer_index(&dm->faceData, type); - dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; - - data = datalayer = DM_get_face_data_layer(dm, type); - for(efa=em->faces.first; efa; efa=efa->next, data+=size) { - emdata = CustomData_em_get(&em->fdata, efa->data, type); - memcpy(data, emdata, size); - } - } - } - - return datalayer; -} - -static void emDM_release(DerivedMesh *dm) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - - if (DM_release(dm)) { - if (emdm->vertexCos) { - MEM_freeN(emdm->vertexCos); - MEM_freeN(emdm->vertexNos); - MEM_freeN(emdm->faceNos); - } - - MEM_freeN(emdm); - } -} - -DerivedMesh *editmesh_get_derived(EditMesh *em, float (*vertexCos)[3]) -{ - EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm"); - - DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts), - BLI_countlist(&em->edges), BLI_countlist(&em->faces)); - - emdm->dm.getMinMax = emDM_getMinMax; - - emdm->dm.getNumVerts = emDM_getNumVerts; - emdm->dm.getNumEdges = emDM_getNumEdges; - emdm->dm.getNumFaces = emDM_getNumFaces; - - emdm->dm.getVertCos = emDM_getVertCos; - - emdm->dm.getVert = emDM_getVert; - emdm->dm.getEdge = emDM_getEdge; - emdm->dm.getFace = emDM_getFace; - emdm->dm.copyVertArray = emDM_copyVertArray; - emdm->dm.copyEdgeArray = emDM_copyEdgeArray; - emdm->dm.copyFaceArray = emDM_copyFaceArray; - emdm->dm.getFaceDataArray = emDM_getFaceDataArray; - - emdm->dm.foreachMappedVert = emDM_foreachMappedVert; - emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; - emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; - - emdm->dm.drawEdges = emDM_drawEdges; - emdm->dm.drawMappedEdges = emDM_drawMappedEdges; - emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; - emdm->dm.drawMappedFaces = emDM_drawMappedFaces; - emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; - emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; - emdm->dm.drawFacesTex = emDM_drawFacesTex; - emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; - emdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat; - emdm->dm.drawUVEdges = emDM_drawUVEdges; - - emdm->dm.release = emDM_release; - - emdm->em = em; - emdm->vertexCos = vertexCos; - - if(CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { - EditVert *eve; - int i; - - DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL); - - for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i) - DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT, - CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT)); - } - - if(vertexCos) { - EditVert *eve; - EditFace *efa; - int totface = BLI_countlist(&em->faces); - int i; - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (intptr_t) i++; - - emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno"); - emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno"); - - for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) { - float *v1 = vertexCos[(int) efa->v1->tmp.l]; - float *v2 = vertexCos[(int) efa->v2->tmp.l]; - float *v3 = vertexCos[(int) efa->v3->tmp.l]; - float *no = emdm->faceNos[i]; - - if(efa->v4) { - float *v4 = vertexCos[(int) efa->v4->tmp.l]; - - normal_quad_v3( no,v1, v2, v3, v4); - add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no); - } - else { - normal_tri_v3( no,v1, v2, v3); - } - - add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no); - add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no); - add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no); - } - - for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) { - float *no = emdm->vertexNos[i]; - /* following Mesh convention; we use vertex coordinate itself - * for normal in this case */ - if (normalize_v3(no) == 0.0f) { - normalize_v3_v3(no, vertexCos[i]); - } - } - } - - return (DerivedMesh*) emdm; -} - /***/ -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); @@ -1640,7 +689,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); @@ -1648,9 +701,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); @@ -1659,22 +719,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); } @@ -1682,8 +742,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; @@ -1692,7 +751,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); } @@ -1701,10 +760,12 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free) by a more flexible customdata system, but not simple */ if(!em) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest); - - if(kb->data) - return kb->data; + if (clmd) { + KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest); + + if(kb->data) + return kb->data; + } } return NULL; @@ -1713,13 +774,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, 0); else dm= CDDM_from_mesh(me, ob); orco= get_orco_coords_dm(ob, em, layer, &free); @@ -1734,7 +795,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; @@ -1881,21 +943,28 @@ void vDM_ColorBand_store(ColorBand *coba) static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) { - Mesh *me = ob->data; - MFace *mf = me->mface; + // Mesh *me = ob->data; // UNUSED + MFace *mf = dm->getTessFaceArray(dm); + MLoop *mloop = dm->getLoopArray(dm), *ml; + MPoly *mp = dm->getPolyArray(dm); ColorBand *coba= stored_cb; /* warning, not a local var */ unsigned char *wtcol; - int i; - + unsigned char(*wlcol)[4] = NULL; + BLI_array_declare(wlcol); + int i, j, totface=dm->getNumTessFaces(dm), totloop; + int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX); + int defbase_len = BLI_countlist(&ob->defbase); char *defbase_sel = MEM_mallocN(defbase_len * sizeof(char), __func__); int selected = get_selected_defgroups(ob, defbase_sel, defbase_len); int unselected = defbase_len - selected; - wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap"); + wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap"); - memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4); - for (i=0; i<me->totface; i++, mf++) { + /*first add colors to the tesselation faces*/ + memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4); + for (i=0; i<totface; i++, mf++) { + /*origindex being NULL means we're operating on original mesh data*/ calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag); calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag); calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag); @@ -1903,9 +972,110 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag); } + CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface); + + /*now add to loops, so the data can be passed through the modifier stack*/ + totloop = 0; + for (i=0; i<dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + for (j=0; j<mp->totloop; j++, ml++, totloop++) { + BLI_array_growone(wlcol); + + calc_weightpaint_vert_color(ob, coba, origIndex ? origIndex[ml->v] : ml->v, + (unsigned char *)&wlcol[totloop], defbase_sel, selected, unselected, draw_flag); + } + } + MEM_freeN(defbase_sel); - CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData); + CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop); +} + + +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): @@ -1916,14 +1086,15 @@ static void add_weight_mcol_dm(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; 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; @@ -1994,7 +1165,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); @@ -2077,7 +1251,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* if this is not the last modifier in the stack then recalculate the normals * to avoid giving bogus normals to the next modifier see: [#23673] */ - if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + if(dm && isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { /* XXX, this covers bug #23673, but we may need normal calc for other types */ if(dm && dm->type == DM_TYPE_CDDM) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -2098,7 +1272,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; @@ -2108,14 +1282,14 @@ 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); } - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, dm, draw_flag); - /* Constructive modifiers need to have an origindex * otherwise they wont have anywhere to copy the data from. * @@ -2131,8 +1305,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos range_vni(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); range_vni(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0); + range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } + + if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) + add_weight_mcol_dm(ob, dm, draw_flag); + } @@ -2150,7 +1328,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); @@ -2223,7 +1401,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); @@ -2235,13 +1413,23 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } else if(dm) { finaldm = dm; } 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); - CDDM_calc_normals(finaldm); + recalc_normals= 1; } + if(recalc_normals) + CDDM_calc_normals(finaldm); + if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) add_weight_mcol_dm(ob, finaldm, draw_flag); } @@ -2266,6 +1454,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } #endif /* WITH_GAMEENGINE */ + finaldm->calcNormals(finaldm); + *final_r = finaldm; if(orcodm) @@ -2279,21 +1469,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(float)*3*numVerts, "vertexcos"); - cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos"); - for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) { + eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { 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; @@ -2307,14 +1500,14 @@ 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) { ModifierData *md; float (*deformedVerts)[3] = NULL; CustomDataMask mask; - DerivedMesh *dm, *orcodm = NULL; + DerivedMesh *dm = NULL, *orcodm = NULL, *finaldm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); LinkNode *datamasks, *curr; int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -2322,10 +1515,9 @@ 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; md = modifiers_getVirtualModifierList(ob); datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); @@ -2336,7 +1528,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 */ @@ -2364,7 +1556,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); } } @@ -2377,7 +1569,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; @@ -2386,11 +1578,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, 0); if(deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -2426,7 +1618,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); @@ -2448,13 +1640,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); } } @@ -2467,21 +1659,24 @@ 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); + finaldm = 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); } else if (dm) { - *final_r = dm; + finaldm = dm; } else if (!deformedVerts && cage_r && *cage_r) { - *final_r = *cage_r; + finaldm = *cage_r; } else { - *final_r = editmesh_get_derived(em, deformedVerts); + finaldm = getEditDerivedBMesh(em, ob, deformedVerts); deformedVerts = NULL; } + finaldm->calcNormals(finaldm); + + *final_r = finaldm; + /* add an orco layer if needed */ if(dataMask & CD_MASK_ORCO) add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO); @@ -2525,18 +1720,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); @@ -2545,7 +1741,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); @@ -2562,7 +1758,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; @@ -2570,12 +1766,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); } } @@ -2587,7 +1784,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; } @@ -2598,7 +1795,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; } @@ -2607,7 +1804,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; } @@ -2616,7 +1813,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; } @@ -2625,7 +1822,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; } @@ -2635,7 +1832,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; } @@ -2645,7 +1842,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; } @@ -2655,7 +1852,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; } @@ -2666,14 +1863,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 @@ -2681,27 +1878,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); } @@ -2741,7 +1938,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) { @@ -2870,15 +2067,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); @@ -2887,8 +2084,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"); @@ -3009,15 +2206,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, memset(attribs, 0, sizeof(DMVertexAttribs)); vdata = &dm->vertData; - fdata = &dm->faceData; - - /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we - * can use offsets instead */ - if(dm->release == emDM_release) - tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; - else - tfdata = fdata; - + fdata = tfdata = dm->getTessFaceDataLayout(dm); + /* add a tangent layer if necessary */ for(b = 0; b < gattribs->totlayer; b++) if(gattribs->layer[b].type == CD_TANGENT) @@ -3039,8 +2229,26 @@ 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; - } + } /*else { + int player; + CustomData *pdata = dm->getFaceDataLayout(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 */ @@ -3199,7 +2407,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) { diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 36df1101a24..33df6132c13 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 { @@ -1020,34 +1020,31 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; - EditMesh *em; + BMEditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; copy_m4_m4(pmat, par->obmat); - - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; + if(em) { int totvert; + dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - - totface= dm->getNumFaces(dm); + totface= dm->getNumTessFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); - dm->copyFaceArray(dm, mface); + dm->copyTessFaceArray(dm, mface); totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); - - BKE_mesh_end_editmesh(me, em); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); - totface= dm->getNumFaces(dm); - mface= dm->getFaceArray(dm); + totface= dm->getNumTessFaces(dm); + mface= dm->getTessFaceArray(dm); mvert= dm->getVertArray(dm); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 0e8d598da3d..af31da7af1e 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_MAXDIR+FILE_MAXFILE]; 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 1100c1c0ef5..19838a634f8 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,45 +572,91 @@ 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) + 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); 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); } } } - 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 +684,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 0f9033ca461..3a132aa326d 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,11 +107,16 @@ static int cdDM_getNumEdges(DerivedMesh *dm) return dm->numEdgeData; } -static int cdDM_getNumFaces(DerivedMesh *dm) +static int cdDM_getNumTessFaces(DerivedMesh *dm) { return dm->numFaceData; } +static int cdDM_getNumFaces(DerivedMesh *dm) +{ + return dm->numPolyData; +} + static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -134,6 +153,18 @@ static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData); } +static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + 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]) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -203,7 +234,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) @@ -292,7 +323,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MFace *mf = cddm->mface; - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if(mf) { @@ -463,7 +494,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) { \ @@ -651,15 +682,15 @@ 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; - 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); @@ -751,8 +782,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; @@ -846,14 +877,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us MVert *mv = cddm->mvert; MFace *mf = cddm->mface; MCol *mc; - float *nors= dm->getFaceDataArray(dm, CD_NORMAL); - int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + float *nors= DM_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); @@ -862,15 +893,17 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us 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++) { - int drawSmooth = (mf->flag & ME_SMOOTH); - int draw= 1; + int drawSmooth = (mf->flag & ME_SMOOTH) != 0; + int draw = (mf->flag & ME_HIDE) == 0; orig= (index==NULL) ? i : *index++; - - if(orig == ORIGINDEX_NONE) - draw= setMaterial(mf->mat_nr + 1, NULL); - else if (setDrawOptions != NULL) - draw= setDrawOptions(userData, orig, &drawSmooth); + + if (orig == ORIGINDEX_NONE) { + draw = draw && setMaterial(mf->mat_nr + 1, NULL); + } + else if (setDrawOptions != NULL) { + draw = draw && setDrawOptions(userData, orig, &drawSmooth); + } if(draw) { unsigned char *cp = NULL; @@ -925,7 +958,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us } glEnd(); - } + } /*else { + printf("eek in cddm draw mapped faces!\n"); + }*/ if (nors) nors += 3; } @@ -956,7 +991,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us int actualFace = next_actualFace; MFace *mface= mf + actualFace; int drawSmooth= (mface->flag & ME_SMOOTH); - int draw = 1; + int draw = (mf->flag & ME_HIDE) == 0; int flush = 0; if(i != tottri-1) @@ -964,10 +999,12 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us orig= (index==NULL) ? actualFace : index[actualFace]; - if(orig == ORIGINDEX_NONE) - draw= setMaterial(mface->mat_nr + 1, NULL); - else if (setDrawOptions != NULL) - draw= setDrawOptions(userData, orig, &drawSmooth); + if (orig == ORIGINDEX_NONE) { + draw = draw && setMaterial(mface->mat_nr + 1, NULL); + } + else if (setDrawOptions != NULL) { + draw = draw && setDrawOptions(userData, orig, &drawSmooth); + } /* Goal is to draw as long of a contiguous triangle array as possible, so draw when we hit either an @@ -1065,10 +1102,10 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; - /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* 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); @@ -1362,9 +1399,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); @@ -1506,10 +1543,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]; @@ -1519,22 +1559,36 @@ 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(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + + dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, + &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, + dm->numPolyData); + + cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); } static void cdDM_free_internal(CDDerivedMesh *cddm) @@ -1553,6 +1607,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) { @@ -1565,21 +1624,28 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getMinMax = cdDM_getMinMax; dm->getNumVerts = cdDM_getNumVerts; - dm->getNumFaces = cdDM_getNumFaces; dm->getNumEdges = cdDM_getNumEdges; + dm->getNumTessFaces = cdDM_getNumTessFaces; + dm->getNumFaces = cdDM_getNumFaces; dm->getVert = cdDM_getVert; dm->getEdge = cdDM_getEdge; - dm->getFace = cdDM_getFace; + dm->getTessFace = cdDM_getFace; dm->copyVertArray = cdDM_copyVertArray; dm->copyEdgeArray = cdDM_copyEdgeArray; - dm->copyFaceArray = cdDM_copyFaceArray; + dm->copyTessFaceArray = cdDM_copyFaceArray; + dm->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_face_data; dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getFaceDataArray = DM_get_face_data_layer; + dm->getTessFaceDataArray = DM_get_tessface_data_layer; + + dm->calcNormals = CDDM_calc_normals; + //doesn't work yet for all cases + //dm->recalcTesselation = CDDM_recalc_tesselation; dm->getVertCos = cdDM_getVertCos; dm->getVertCo = cdDM_getVertCo; @@ -1613,24 +1679,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 numFaces, int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_new dm"); DerivedMesh *dm = &cddm->dm; - DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); return dm; } @@ -1641,10 +1713,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; @@ -1654,21 +1728,34 @@ 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); + BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_POLYINDEX)); + + 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 *disabled__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; @@ -1686,6 +1773,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) CD_CALLOC, dm->numEdgeData); */ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->numFaceData); + CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, + CD_CALLOC, dm->numFaceData); /* set eve->hash to vert index */ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) @@ -1739,7 +1828,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */ } - index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + index = dm->getTessFaceDataArray(dm, CD_POLYINDEX); for(i = 0, efa = em->faces.first; i < dm->numFaceData; i++, efa = efa->next, index++) { MFace *mf = &mface[i]; @@ -1772,15 +1861,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; @@ -1788,29 +1879,245 @@ 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) +{ + DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, + em->tottri, em->bm->totloop, em->bm->totface); + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + BMesh *bm = em->bm; + BMIter iter, liter; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + MVert *mvert = cddm->mvert; + MEdge *medge = cddm->medge; + MFace *mface = cddm->mface; + MLoop *mloop = cddm->mloop; + MPoly *mpoly = cddm->mpoly; + int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL); + int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + int i, j, *index, *polyindex, add_orig; + int has_crease, has_edge_bweight, has_vert_bweight; + int flag; + + has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT); + has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT); + has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE); + + dm->deformedOnly = 1; + + /*don't add origindex layer if one already exists*/ + add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX); + + flag = 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*/ + flag &= ~CD_SHAPEKEY; + CustomData_merge(&em->bm->vdata, &dm->vertData, flag, + CD_CALLOC, dm->numVertData); + CustomData_merge(&em->bm->edata, &dm->edgeData, flag, + CD_CALLOC, dm->numEdgeData); + CustomData_merge(&em->bm->ldata, &dm->loopData, flag, + CD_CALLOC, dm->numLoopData); + CustomData_merge(&em->bm->pdata, &dm->polyData, flag, + CD_CALLOC, dm->numPolyData); + + /*add tesselation mface layers*/ + CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri); + + /* set vert index */ + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BM_SetIndex(eve, i); + + index = dm->getVertDataArray(dm, CD_ORIGINDEX); + + eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) { + MVert *mv = &mvert[i]; + + copy_v3_v3(mv->co, eve->co); + + BM_SetIndex(eve, i); + + normal_float_to_short_v3(mv->no, eve->no); + + mv->flag = BMFlags_To_MEFlags(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); + } + + 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); + + 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 = BMFlags_To_MEFlags(eed); + + CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i); + if (add_orig) *index = i; + } + + efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; i++, efa=BMIter_Step(&iter)) { + BM_SetIndex(efa, i); + } + + polyindex = dm->getTessFaceDataArray(dm, CD_POLYINDEX); + index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + for(i = 0; i < dm->numFaceData; i++, index++) { + MFace *mf = &mface[i]; + BMLoop **l = em->looptris[i]; + efa = l[0]->f; + + mf->v1 = 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 = BMFlags_To_MEFlags(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]; + + mp->totloop = efa->len; + mp->flag = BMFlags_To_MEFlags(efa); + mp->loopstart = j; + mp->mat_nr = efa->mat_nr; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) { + mloop->v = 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; + } + + 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 numLoops = source->numLoopData; + int numPolys = source->numPolyData; /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, + numLoops, numPolys); dm->deformedOnly = source->deformedOnly; CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); @@ -1820,19 +2127,32 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupFaceArray(source); + cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces); + + if (!faces_from_tessfaces) + DM_DupPolys(source, dm); + else + CDDM_tessfaces_to_faces(dm); + cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); + cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); + + /* 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); + return dm; } /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct * relationship betwen mesh data this needs to be set by the caller. */ DerivedMesh *CDDM_from_template(DerivedMesh *source, - int numVerts, int numEdges, int numFaces) + int numVerts, int numEdges, int numFaces, + int numLoops, int numPolys) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); DerivedMesh *dm = &cddm->dm; @@ -1840,15 +2160,17 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getFaceDataArray(source, CD_ORIGINDEX); + source->getTessFaceDataArray(source, CD_ORIGINDEX); /* this does a copy of all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys); /* now add mvert/medge/mface layers */ CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); + CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); @@ -1856,10 +2178,14 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, 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); + if(!CustomData_get_layer(&dm->faceData, CD_POLYINDEX)) + CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numFaces); 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; } @@ -1895,23 +2221,232 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) void CDDM_calc_normals(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; - float (*face_nors)[3]; - + float (*face_nors)[3] = NULL; + if(dm->numVertData == 0) return; /* we don't want to overwrite any referenced layers */ cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); - /* make a face normal layer if not present */ - face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - if(!face_nors) - face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, - NULL, dm->numFaceData); + if (dm->numFaceData == 0) { + /* No tesselation on this mesh yet, need to calculate one */ + CDDM_recalc_tesselation(dm); + } + 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->numFaceData); + } + face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors"); + /* calculate face normals */ - mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors); + mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), + dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData, + CustomData_get_layer(&dm->faceData, CD_POLYINDEX), face_nors); + + CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, + face_nors, dm->numFaceData); } +#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 + + */ +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CDDerivedMesh *cddm2 = NULL; + MVert *mv, *mvert = NULL; + BLI_array_declare(mvert); + MEdge *me, *medge = NULL; + BLI_array_declare(medge); + MPoly *mp, *mpoly = NULL; + BLI_array_declare(mpoly); + MLoop *ml, *mloop = NULL; + BLI_array_declare(mloop); + 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 (ml->v == -1) + continue; + + if (vtargetmap[ml->v] != -1) + ml->v = vtargetmap[ml->v]; + } + + /*now go through and fix edges and faces*/ + me = cddm->medge; + c = 0; + for (i=0; i<dm->numEdgeData; i++, me++) { + int v1, v2; + + if (me->v1 == me->v2) { + newe[i] = -1; + continue; + } + + if (vtargetmap[me->v1] != -1) + v1 = vtargetmap[me->v1]; + else + v1 = me->v1; + + if (vtargetmap[me->v2] != -1) + v2 = vtargetmap[me->v2]; + else + v2 = me->v2; + + if (BLI_edgehash_haskey(ehash, v1, v2)) { + newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2)); + } else { + BLI_array_append(olde, i); + newe[i] = c; + BLI_array_append(medge, *me); + BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c)); + c++; + } + } + + mp = cddm->mpoly; + for (i=0; i<totpoly; i++, mp++) { + MPoly *mp2; + + ml = cddm->mloop + mp->loopstart; + + c = 0; + for (j=0; j<mp->totloop; j++, ml++) { + if (ml->v == -1) + continue; + + me = cddm->medge + ml->e; + if (me->v1 != me->v2) { + BLI_array_append(oldl, j+mp->loopstart); + BLI_array_append(mloop, *ml); + newl[j+mp->loopstart] = BLI_array_count(mloop)-1; + c++; + } + } + + if (!c) + continue; + + mp2 = BLI_array_append(mpoly, *mp); + mp2->totloop = c; + mp2->loopstart = BLI_array_count(mloop) - c; + + BLI_array_append(oldp, i); + } + + /*create new cddm*/ + cddm2 = (CDDerivedMesh*) CDDM_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*/ + me = medge; + for (i=0; i<cddm2->dm.numEdgeData; i++, me++) { + if (newv[me->v1] != -1) + me->v1 = newv[me->v1]; + if (newv[me->v2] != -1) + me->v2 = newv[me->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); + + CDDM_recalc_tesselation((DerivedMesh*)cddm2); + + 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(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; @@ -1968,6 +2503,83 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehash_free(eh, NULL); } + +void CDDM_calc_edges_poly(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*)dm; + CustomData edgeData; + EdgeHashIterator *ehi; + MPoly *mp = cddm->mpoly; + MLoop *ml; + MEdge *med; + EdgeHash *eh = BLI_edgehash_new(); + int v1, v2; + int *eindex; + int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData; + + eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX); + + med = cddm->medge; + if (med) { + for (i=0; i < numEdges; i++, med++) { + BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1)); + } + } + + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + if (!BLI_edgehash_haskey(eh, v1, v2)) { + BLI_edgehash_insert(eh, v1, v2, NULL); + } + } + } + + k = numEdges; + numEdges = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edgeData, 0, sizeof(edgeData)); + CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); + CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edgeData, CD_MEDGE); + index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + + med->flag = ME_EDGEDRAW|ME_EDGERENDER; + *index = j==0 ? ORIGINDEX_NONE : eindex[j-1]; + + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&dm->edgeData, dm->numEdgeData); + dm->edgeData = edgeData; + dm->numEdgeData = numEdges; + + cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + + mp = cddm->mpoly; + for (i=0; i < maxFaces; i++, mp++) { + ml = cddm->mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + v1 = ml->v; + v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2)); + } + } + + BLI_edgehash_free(eh, NULL); +} + void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts) { if (numVerts < dm->numVertData) @@ -2002,7 +2614,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]; } @@ -2017,8 +2629,125 @@ 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; + MLoop *ml; + MPoly *mp; + EdgeHash *eh = BLI_edgehash_new(); + int i, l, totloop, *polyindex; + + /*ensure we have all the edges we need*/ + CDDM_calc_edges(dm); + + /*build edge hash*/ + me = cddm->medge; + for (i=0; i<cddm->dm.numEdgeData; i++, me++) { + BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); + } + + mf = cddm->mface; + totloop = 0; + for (i=0; i<cddm->dm.numFaceData; i++, mf++) { + totloop += mf->v4 ? 4 : 3; + } + + CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData); + CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData); + + cddm->dm.numLoopData = totloop; + cddm->dm.numPolyData = cddm->dm.numFaceData; + + if (!totloop) return; + + cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces"); + cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces"); + + CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop); + CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData); + CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, + CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData); + + 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.numFaceData; i++, mf++, mp++) { + mp->flag = mf->flag; + mp->loopstart = l; + mp->mat_nr = mf->mat_nr; + mp->totloop = mf->v4 ? 4 : 3; + + ml->v = mf->v1; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); + ml++, l++; + + ml->v = mf->v2; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3)); + ml++, l++; + + ml->v = mf->v3; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1)); + ml++, l++; + + if (mf->v4) { + ml->v = mf->v4; + ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1)); + ml++, l++; + } + + *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->numFaceData); + + cddm->mface = mface; +} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4d5dce14b27..bd11625bf6e 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" @@ -439,7 +440,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; cache= clmd->point_cache; - result = CDDM_copy(dm); + result = CDDM_copy(dm, 0); BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); @@ -933,8 +934,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. */ @@ -1046,9 +1047,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 adc3f17f187..92304278b3f 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -75,8 +75,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" @@ -432,7 +436,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]; @@ -449,7 +453,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, 0); freeDM= 1; } else { @@ -522,8 +526,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/curve.c b/source/blender/blenkernel/intern/curve.c index 8a6e8faf29a..5f1a5f73973 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -49,6 +49,7 @@ #include "DNA_key_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "BKE_animsys.h" diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d7cc5376e21..f0b93212766 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -44,19 +44,25 @@ #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" #include "BLI_mempool.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "BKE_customdata.h" #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 @@ -99,6 +105,14 @@ typedef struct LayerTypeInfo { default is assumed to be all zeros */ void (*set_default)(void *data, int count); + /* functions necassary for geometry collapse*/ + int (*equal)(void *data1, void *data2); + void (*multiply)(void *data, float fac); + void (*initminmax)(void *min, void *max); + void (*add)(void *data1, void *data2); + void (*dominmax)(void *data1, void *min, void *max); + void (*copyvalue)(void *source, void *dest); + /* a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); @@ -125,7 +139,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest, MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size); if(dvert->totweight) { - MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw), + MDeformWeight *dw = BLI_cellalloc_calloc(dvert->totweight * sizeof(*dw), "layerCopy_mdeformvert dw"); memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw)); @@ -144,7 +158,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) MDeformVert *dvert = (MDeformVert *)((char *)data + i * size); if(dvert->dw) { - MEM_freeN(dvert->dw); + BLI_cellalloc_free(dvert->dw); dvert->dw = NULL; dvert->totweight = 0; } @@ -153,7 +167,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) static void linklist_free_simple(void *link) { - MEM_freeN(link); + BLI_cellalloc_free(link); } static void layerInterp_mdeformvert(void **sources, float *weights, @@ -186,7 +200,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights, /* if this def_nr is not in the list, add it */ if(!node) { - MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw), + MDeformWeight *tmp_dw = BLI_cellalloc_calloc(sizeof(*tmp_dw), "layerInterp_mdeformvert tmp_dw"); tmp_dw->def_nr = dw->def_nr; tmp_dw->weight = dw->weight * interp_weight; @@ -197,10 +211,10 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } /* now we know how many unique deform weights there are, so realloc */ - if(dvert->dw) MEM_freeN(dvert->dw); + if(dvert->dw) BLI_cellalloc_free(dvert->dw); if(totweight) { - dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight, + dvert->dw = BLI_cellalloc_calloc(sizeof(*dvert->dw) * totweight, "layerInterp_mdeformvert dvert->dw"); dvert->totweight = totweight; @@ -331,6 +345,24 @@ static void layerDefault_tface(void *data, int count) tf[i] = default_tf; } +static void layerCopy_propFloat(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MFloatProperty)*count); +} + +static void layerCopy_propInt(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MIntProperty)*count); +} + +static void layerCopy_propString(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MStringProperty)*count); +} + static void layerCopy_origspace_face(const void *source, void *dest, int count) { const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source; @@ -419,22 +451,39 @@ static void layerSwap_mdisps(void *data, const int *ci) /* happens when face changed vertex count in edit mode if it happened, just forgot displacement */ - MEM_freeN(s->disps); + BLI_cellalloc_free(s->disps); s->totdisp= (s->totdisp/corners)*nverts; - s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap"); + s->disps= BLI_cellalloc_calloc(s->totdisp*sizeof(float)*3, "mdisp swap"); return; } - d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + d= BLI_cellalloc_calloc(sizeof(float) * 3 * s->totdisp, "mdisps swap"); for(S = 0; S < corners; S++) memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); - MEM_freeN(s->disps); + BLI_cellalloc_free(s->disps); s->disps= d; } } +#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 = BLI_cellalloc_calloc(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) { @@ -547,6 +596,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) { @@ -556,7 +606,7 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) for(i = 0; i < count; ++i) { if(s[i].disps) { - d[i].disps = MEM_dupallocN(s[i].disps); + d[i].disps = BLI_cellalloc_dupalloc(s[i].disps); d[i].totdisp = s[i].totdisp; } else { @@ -569,6 +619,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); @@ -576,9 +630,10 @@ static void layerValidate_mdisps(void *data, int sub_elements) if(corners != sub_elements) { MEM_freeN(disps->disps); disps->totdisp = disps->totdisp / corners * sub_elements; - disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); + disps->disps = BLI_cellalloc_calloc(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); } } +#endif } static void layerFree_mdisps(void *data, int count, int UNUSED(size)) @@ -588,7 +643,7 @@ static void layerFree_mdisps(void *data, int count, int UNUSED(size)) for(i = 0; i < count; ++i) { if(d[i].disps) - MEM_freeN(d[i].disps); + BLI_cellalloc_free(d[i].disps); d[i].disps = NULL; d[i].totdisp = 0; } @@ -601,7 +656,7 @@ static int layerRead_mdisps(CDataFile *cdf, void *data, int count) for(i = 0; i < count; ++i) { if(!d[i].disps) - d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read"); + d[i].disps = BLI_cellalloc_calloc(sizeof(float)*3*d[i].totdisp, "mdisps read"); if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) { printf("failed to read multires displacement %d/%d %d\n", i, count, d[i].totdisp); @@ -640,10 +695,83 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count } /* --------- */ +static void layerCopyValue_mloopcol(void *source, void *dest) +{ + MLoopCol *m1 = source, *m2 = dest; + + m2->r = m1->r; + m2->g = m1->g; + m2->b = m1->b; + m2->a = m1->a; +} + +static int layerEqual_mloopcol(void *data1, void *data2) +{ + MLoopCol *m1 = data1, *m2 = data2; + float r, g, b, a; + + r = m1->r - m2->r; + g = m1->g - m2->g; + b = m1->b - m2->b; + a = m1->a - m2->a; + + return r*r + g*g + b*b + a*a < 0.001; +} + +static void layerMultiply_mloopcol(void *data, float fac) +{ + MLoopCol *m = data; + + m->r = (float)m->r * fac; + m->g = (float)m->g * fac; + m->b = (float)m->b * fac; + m->a = (float)m->a * fac; +} + +static void layerAdd_mloopcol(void *data1, void *data2) +{ + MLoopCol *m = data1, *m2 = data2; + + m->r += m2->r; + m->g += m2->g; + m->b += m2->b; + m->a += m2->a; +} + +static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax) +{ + MLoopCol *m = data; + MLoopCol *min = vmin, *max = vmax; + + if (m->r < min->r) min->r = m->r; + if (m->g < min->g) min->g = m->g; + if (m->b < min->b) min->b = m->b; + if (m->a < min->a) min->a = m->a; + + if (m->r > max->r) max->r = m->r; + if (m->g > max->g) max->g = m->g; + if (m->b > max->b) max->b = m->b; + if (m->a > max->a) max->a = m->a; +} + +static void layerInitMinMax_mloopcol(void *vmin, void *vmax) +{ + MLoopCol *min = vmin, *max = vmax; + + min->r = 255; + min->g = 255; + min->b = 255; + min->a = 255; + + max->r = 0; + max->g = 0; + max->b = 0; + max->a = 0; +} static void layerDefault_mloopcol(void *data, int count) { - static MLoopCol default_mloopcol = {255,255,255,255}; + MLoopCol default_mloopcol = {255,255,255,255}; MLoopCol *mlcol = (MLoopCol*)data; int i; for(i = 0; i < count; i++) @@ -695,6 +823,56 @@ static void layerInterp_mloopcol(void **sources, float *weights, mc->g = (int)col.g; mc->b = (int)col.b; } + +static void layerCopyValue_mloopuv(void *source, void *dest) +{ + MLoopUV *luv1 = source, *luv2 = dest; + + luv2->uv[0] = luv1->uv[0]; + luv2->uv[1] = luv1->uv[1]; +} + +static int layerEqual_mloopuv(void *data1, void *data2) +{ + MLoopUV *luv1 = data1, *luv2 = data2; + float u, v; + + u = luv1->uv[0] - luv2->uv[0]; + v = luv1->uv[1] - luv2->uv[1]; + + return u*u + v*v < 0.00001; +} + +static void layerMultiply_mloopuv(void *data, float fac) +{ + MLoopUV *luv = data; + + luv->uv[0] *= fac; + luv->uv[1] *= fac; +} + +static void layerInitMinMax_mloopuv(void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax; + + INIT_MINMAX2(min->uv, max->uv); +} + +static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax, *luv = data; + + DO_MINMAX2(luv->uv, min->uv, max->uv); +} + +static void layerAdd_mloopuv(void *data1, void *data2) +{ + MLoopUV *l1 = data1, *l2 = data2; + + l1->uv[0] += l2->uv[0]; + l1->uv[1] += l2->uv[1]; +} + static void layerInterp_mloopuv(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -802,7 +980,48 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } +static void layerInterp_bweight(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *f = dest, *src; + float **in = (float **)sources; + int i; + + if(count <= 0) return; + + *f = 0.0f; + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + *f += *src * weight; + } +} + +static void layerInterp_shapekey(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *co = dest, *src; + float **in = (float **)sources; + int i; + if(count <= 0) return; + + memset(co, 0, sizeof(float)*3); + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + co[0] += src[0] * weight; + co[1] += src[1] * weight; + co[2] += src[2] * weight; + } +} + +/* note, these numbered comments below are copied from trunk, + * while _most_ match, some at the end need adding and are out of sync */ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ @@ -828,15 +1047,15 @@ 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}, - /* 9: CD_FLAGS */ - {sizeof(int), "", 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 */ - {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, + {sizeof(MFloatProperty), "MFloatProperty",1,"Float", layerCopy_propFloat,NULL,NULL,NULL}, /* 11: CD_PROP_INT */ - {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, + {sizeof(MIntProperty), "MIntProperty",1,"Int",layerCopy_propInt,NULL,NULL,NULL}, /* 12: CD_PROP_STR */ - {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL}, + {sizeof(MStringProperty), "MStringProperty",1,"String",layerCopy_propString,NULL,NULL,NULL}, /* 13: CD_ORIGSPACE */ {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL, layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, @@ -845,58 +1064,80 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 15: CD_MTEXPOLY */ {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, /* 16: CD_MLOOPUV */ - {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, + {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL, + layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, /* 17: CD_MLOOPCOL */ - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, - /* 18: CD_TANGENT */ + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 19: CD_MDISPS */ {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, - layerFilesize_mdisps, layerValidate_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps}, /* 20: CD_WEIGHT_MCOL */ {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, + {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, + {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ClothOrco", NULL, NULL, layerInterp_shapekey}, /* 21: CD_ID_MCOL */ {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - /* 22: CD_TEXTURE_MCOL */ - {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, + {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - /* 23: CD_CLOTH_ORCO */ - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey}, + {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight}, + {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight}, + {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, /* 24: CD_RECAST */ {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} }; +/* 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", - /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", - /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", - /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast" + /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", + /* 5-9 */ "CDMCol", "CDOrigIndex", "CDNormal", "CDPolyIndex","CDMFloatProperty", + /* 10-14 */ "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", + /* 15-19 */ "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly", + /* 20-24 */ "CDMLoop", "CDMClothOrco", "CDMLoopCol", "CDIDCol", "CDTextureCol", + /* ?-? */ "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", "CDSubSurfCrease", "CDMRecast" }; + 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; - static const LayerTypeInfo *layerType_getInfo(int type) { if(type < 0 || type >= CD_NUMTYPES) return NULL; @@ -917,11 +1158,28 @@ static void customData_update_offsets(CustomData *data); static CustomDataLayer *customData_add_layer__internal(CustomData *data, int type, int alloctype, void *layerdata, int totelem, const char *name); +void CustomData_update_typemap(CustomData *data) +{ + int i, lasttype = -1; + + for (i=0; i<CD_NUMTYPES; i++) { + data->typemap[i] = -1; + } + + for (i=0; i<data->totlayer; i++) { + if (data->layers[i].type != lasttype) { + data->typemap[data->layers[i].type] = i; + } + lasttype = data->layers[i].type; + } +} + void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; + 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) { @@ -946,14 +1204,27 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, else if(!((int)mask & (int)(1 << (int)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; @@ -961,6 +1232,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY); } } + + CustomData_update_typemap(dest); } void CustomData_copy(const struct CustomData *source, struct CustomData *dest, @@ -1025,6 +1298,7 @@ static void customData_update_offsets(CustomData *data) } data->totsize = offset; + CustomData_update_typemap(data); } int CustomData_get_layer_index(const CustomData *data, int type) @@ -1038,6 +1312,17 @@ int CustomData_get_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + n; + + return -1; +} + int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) { int i; @@ -1051,11 +1336,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha int CustomData_get_active_layer_index(const CustomData *data, int type) { - int i; + if (!data->totlayer) + return -1; - for(i=0; i < data->totlayer; ++i) - if(data->layers[i].type == type) - return i + data->layers[i].active; + if (data->typemap[type] != -1) { + return data->typemap[type] + data->layers[data->typemap[type]].active; + } return -1; } @@ -1242,6 +1528,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; void *newlayerdata; + /* 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)]; @@ -1254,7 +1547,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, return NULL; } - if (alloctype == CD_DUPLICATE) { + if (alloctype == CD_DUPLICATE && layerdata) { if(typeInfo->copy) typeInfo->copy(layerdata, newlayerdata, totelem); else @@ -1284,6 +1577,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].type = type; data->layers[index].flag = flag; data->layers[index].data = newlayerdata; + if(name || (name=typeInfo->defaultname)) { BLI_strncpy(data->layers[index].name, name, 32); CustomData_set_layer_unique_name(data, index); @@ -1316,6 +1610,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, typeInfo->defaultname); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1331,6 +1626,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1369,6 +1665,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_resize(data, -CUSTOMDATA_GROW); customData_update_offsets(data); + CustomData_update_typemap(data); return 1; } @@ -1469,7 +1766,7 @@ void CustomData_free_temporary(CustomData *data, int totelem) } void CustomData_set_only_copy(const struct CustomData *data, - CustomDataMask mask) + CustomDataMask mask) { int i; @@ -1478,6 +1775,16 @@ void CustomData_set_only_copy(const struct CustomData *data, data->layers[i].flag |= CD_FLAG_NOCOPY; } +void CustomData_copy_elements(int type, void *source, void *dest, int count) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->copy) + typeInfo->copy(source, dest, count); + else + memcpy(dest, source, typeInfo->size*count); +} + void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count) { @@ -1509,7 +1816,12 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest, src_offset = source_index * typeInfo->size; dest_offset = dest_index * typeInfo->size; - + + if (!src_data || !dest_data) { + printf("eek! null data in CustomData_copy_data!\n"); + continue; + } + if(typeInfo->copy) typeInfo->copy(src_data + src_offset, dest_data + dest_offset, @@ -1637,6 +1949,19 @@ void *CustomData_get(const CustomData *data, int index, int type) return (char *)data->layers[layer_index].data + offset; } +void *CustomData_get_n(const CustomData *data, int type, int index, int n) +{ + int layer_index; + int offset; + + /* get the layer index of the first layer of type */ + layer_index = data->typemap[type]; + if(layer_index < 0) return NULL; + + offset = layerType_getInfo(type)->size * index; + return (char *)data->layers[layer_index+n].data + offset; +} + void *CustomData_get_layer(const CustomData *data, int type) { /* get the layer index of the active layer of type */ @@ -1664,6 +1989,20 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type, return data->layers[layer_index].data; } + +int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name) +{ + /* get the layer index of the first layer of type */ + int layer_index = CustomData_get_layer_index_n(data, type, n); + + if(layer_index < 0) return 0; + if (!name) return 0; + + strcpy(data->layers[layer_index].name, name); + + return 1; +} + void *CustomData_set_layer(const CustomData *data, int type, void *ptr) { /* get the layer index of the first layer of type */ @@ -1983,33 +2322,97 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest, /*Bmesh functions*/ /*needed to convert to/from different face reps*/ -void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata) +void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, + int totloop, int totpoly) { int i; for(i=0; i < fdata->totlayer; i++){ if(fdata->layers[i].type == CD_MTFACE){ - CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0); - CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0); + CustomData_add_layer_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); - } + 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){ +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); + 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); + CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); + 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_init_pool(CustomData *data, int allocsize){ - if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0); +void CustomData_bmesh_init_pool(CustomData *data, int allocsize) +{ + /* 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, 1, 0); + } +} + +void CustomData_bmesh_merge(CustomData *source, CustomData *dest, + int mask, int alloctype, BMesh *bm, int type) +{ + BMHeader *h; + BMIter iter; + CustomData destold = *dest; + void *tmp; + int t; + + CustomData_merge(source, dest, mask, alloctype, 0); + CustomData_bmesh_init_pool(dest, 512); + + switch (type) { + case BM_VERT: + t = BM_VERTS_OF_MESH; break; + case BM_EDGE: + t = BM_EDGES_OF_MESH; break; + case BM_LOOP: + t = BM_LOOPS_OF_FACE; break; + case BM_FACE: + t = BM_FACES_OF_MESH; break; + 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) @@ -2029,7 +2432,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; } @@ -2040,7 +2445,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; } @@ -2113,6 +2518,82 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return (char *)block + data->layers[layer_index+n].offset; } +/*gets from the layer at physical index n, note: doesn't check type.*/ +void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) +{ + if(n < 0 || n >= data->totlayer) return NULL; + + return (char *)block + data->layers[n].offset; +} + +int CustomData_layer_has_math(struct CustomData *data, int layern) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type); + + if (typeInfo->equal && typeInfo->add && typeInfo->multiply && + typeInfo->initminmax && typeInfo->dominmax) return 1; + + return 0; +} + +/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to + another, while not overwriting anything else (e.g. flags)*/ +void CustomData_data_copy_value(int type, void *source, void *dest) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if(!dest) return; + + if(typeInfo->copyvalue) + typeInfo->copyvalue(source, dest); + else + memcpy(dest, source, typeInfo->size); +} + +int CustomData_data_equals(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->equal) + return typeInfo->equal(data1, data2); + else return !memcmp(data1, data2, typeInfo->size); +} + +void CustomData_data_initminmax(int type, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->initminmax) + typeInfo->initminmax(min, max); +} + + +void CustomData_data_dominmax(int type, void *data, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->dominmax) + typeInfo->dominmax(data, min, max); +} + + +void CustomData_data_multiply(int type, void *data, float fac) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->multiply) + typeInfo->multiply(data, fac); +} + + +void CustomData_data_add(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->add) + typeInfo->add(data1, data2); +} + void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source) { void *dest = CustomData_bmesh_get(data, block, type); @@ -2139,6 +2620,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void memcpy(dest, source, typeInfo->size); } +void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source) +{ + void *dest = CustomData_bmesh_get_layer_n(data, block, n); + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); + + if(!dest) return; + + if(typeInfo->copy) + typeInfo->copy(source, dest, 1); + else + memcpy(dest, source, typeInfo->size); +} + void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, float *sub_weights, int count, void *dest_block) { @@ -2184,6 +2678,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block) if(typeInfo->set_default) typeInfo->set_default((char*)*block + offset, 1); + else memset((char*)*block + offset, 0, typeInfo->size); } } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 0c3c78f6eef..9539e6a4bfa 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -45,6 +45,9 @@ #include "BLI_utildefines.h" +#include "BLI_cellalloc.h" + + void defgroup_copy_list (ListBase *outbase, ListBase *inbase) { bDeformGroup *defgroup, *defgroupn; @@ -83,10 +86,10 @@ void defvert_copy (MDeformVert *dvert_r, const MDeformVert *dvert) } else { if(dvert_r->dw) - MEM_freeN(dvert_r->dw); + BLI_cellalloc_free(dvert_r->dw); if(dvert->totweight) - dvert_r->dw= MEM_dupallocN(dvert->dw); + dvert_r->dw= BLI_cellalloc_dupalloc(dvert->dw); else dvert_r->dw= NULL; @@ -530,10 +533,10 @@ MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup) if(newdw) return newdw; - newdw= MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); - if (dv->dw) { + newdw= BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); + if(dv->dw) { memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); - MEM_freeN(dv->dw); + BLI_cellalloc_free(dv->dw); } dv->dw= newdw; newdw += dv->totweight; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index a5be056bc16..8810dae9d70 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) { @@ -884,7 +886,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (dm) { if (vertCos) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); dm->release(dm); dm = tdm; @@ -925,7 +927,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (vertCos) { if (dm) { - DerivedMesh *tdm = CDDM_copy(dm); + DerivedMesh *tdm = CDDM_copy(dm, 0); dm->release(dm); dm = tdm; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 532e6f797dd..16102f466da 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1210,9 +1210,9 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for /* 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); + int numOfFaces = surface->canvas->dm->getNumTessFaces(surface->canvas->dm); struct MEdge *edge = surface->canvas->dm->getEdgeArray(surface->canvas->dm); - struct MFace *face = surface->canvas->dm->getFaceArray(surface->canvas->dm); + struct MFace *face = surface->canvas->dm->getTessFaceArray(surface->canvas->dm); /* count number of edges per vertex */ for (i=0; i<numOfEdges; i++) { @@ -1298,8 +1298,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[40]; if (!tex) return; @@ -1373,8 +1373,8 @@ void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) /* 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); + MFace *mface = dm->getTessFaceArray(dm); + int numOfFaces = dm->getNumTessFaces(dm); #pragma omp parallel for schedule(static) for (i=0; i<numOfFaces; i++) { @@ -1520,7 +1520,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData Object *ob, DerivedMesh *dm) { - DerivedMesh *result = CDDM_copy(dm); + DerivedMesh *result = CDDM_copy(dm, 0); /* BMESH_TODO second argument untested, may be incorrect - campbell */ if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) { @@ -1540,8 +1540,8 @@ 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); + MFace *mface = result->getTessFaceArray(result); + int numOfFaces = result->getNumTessFaces(result); int i; PaintPoint* pPoint = (PaintPoint*)sData->type_data; MCol *col; @@ -1559,7 +1559,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (surface->flags & MOD_DPAINT_PREVIEW) { /* Save preview results to weight layer, to be * able to share same drawing methods */ - col = result->getFaceDataArray(result, CD_WEIGHT_MCOL); + col = result->getTessFaceDataArray(result, CD_WEIGHT_MCOL); if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces); if (col) { @@ -1655,10 +1655,10 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (surface->flags & MOD_DPAINT_PREVIEW) { /* Save preview results to weight layer, to be * able to share same drawing methods */ - MFace *mface = result->getFaceArray(result); + MFace *mface = result->getTessFaceArray(result); int numOfFaces = result->getNumFaces(result); int i; - MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL); + MCol *col = result->getTessFaceDataArray(result, CD_WEIGHT_MCOL); if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces); if (col) { @@ -1741,7 +1741,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); /* BMESH_TODO untested second argument - campbell */ } return result; @@ -1759,7 +1759,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); /* BMESH_TODO second argument untested, may be incorrect - campbell */ } /* @@ -1912,9 +1912,9 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh * TODO: Implement something more accurate / optimized? */ { - int numOfFaces = dm->getNumFaces(dm); - MFace *mface = dm->getFaceArray(dm); - MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); + int numOfFaces = dm->getNumTessFaces(dm); + MFace *mface = dm->getTessFaceArray(dm); + MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* BMESH_TODO, is this data valid?, possibly need loop uv's */ /* Get closest edge to that subpixel on UV map */ { @@ -2082,7 +2082,7 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) numOfFaces = dm->getNumFaces(dm); /* mvert = dm->getVertArray(dm); */ /* UNUSED */ - mface = dm->getFaceArray(dm); + mface = dm->getTessFaceArray(dm); /* get uv layer */ CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname); @@ -2683,7 +2683,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) { @@ -3000,7 +3000,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); /* BMESH_TODO second argument untested, may be incorrect - campbell */ numOfVerts_p = dm_p->getNumVerts(dm_p); mvert_p = dm_p->getVertArray(dm_p); copy_m4_m4(prev_obmat, ob->obmat); @@ -3104,9 +3104,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); /* BMESH_TODO second argument untested, may be incorrect - campbell */ 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/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c new file mode 100644 index 00000000000..d0db7c82ce6 --- /dev/null +++ b/source/blender/blenkernel/intern/editderivedbmesh.c @@ -0,0 +1,1753 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Tbmple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "PIL_time.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_effect_types.h" +#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_object_fluidsim.h" // N_T +#include "DNA_scene_types.h" // N_T +#include "DNA_texture_types.h" +#include "DNA_view3d_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_particle_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_edgehash.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" +#include "BLI_scanfill.h" +#include "BLI_ghash.h" +#include "BLI_array.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" +#include "BKE_key.h" +#include "BKE_material.h" +#include "BKE_modifier.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_subsurf.h" +#include "BKE_texture.h" +#include "BKE_particle.h" +#include "BKE_tessmesh.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "GL/glew.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "bmesh.h" + +extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ + + +BMEditMesh *BMEdit_Create(BMesh *bm) +{ + BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__); + + tm->bm = bm; + + 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) +{ + BMesh *bm = tm->bm; + BMLoop **looptris = NULL; + BLI_array_declare(looptris); + BMIter iter, liter; + BMFace *f; + BMLoop *l; + int i = 0, j; + + if (tm->looptris) MEM_freeN(tm->looptris); + + f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); + for ( ; f; f=BMIter_Step(&iter)) { + EditVert *v, *lastv=NULL, *firstv=NULL; + EditEdge *e; + EditFace *efa; + + /*don't consider two-edged faces*/ + if (f->len < 3) continue; + + BLI_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*/ + l->_index = j; + + v = BLI_addfillvert(l->v->co); + v->tmp.p = l; + + if (lastv) { + e = BLI_addfilledge(lastv, v); + } + + lastv = v; + if (firstv==NULL) firstv = v; + } + + /*complete the loop*/ + BLI_addfilledge(firstv, v); + + BLI_edgefill(2); + + for (efa = fillfacebase.first; efa; efa=efa->next) { + BMLoop *l1, *l2, *l3; + + BLI_array_growone(looptris); + BLI_array_growone(looptris); + BLI_array_growone(looptris); + + looptris[i*3] = l1 = efa->v1->tmp.p; + looptris[i*3+1] = l2 = efa->v2->tmp.p; + looptris[i*3+2] = l3 = efa->v3->tmp.p; + + if (l1->_index > l2->_index) { + SWAP(BMLoop*, l1, l2); + } + if (l2->_index > l3->_index) { + SWAP(BMLoop*, l2, l3); + } + if (l1->_index > l2->_index) { + SWAP(BMLoop*, l1, l2); + } + + looptris[i*3] = l1; + looptris[i*3+1] = l2; + looptris[i*3+2] = l3; + + i += 1; + } + + BLI_end_edgefill(); + } + + tm->tottri = i; + tm->looptris = (BMLoop *(*)[3])looptris; +} + +void BMEdit_RecalcTesselation(BMEditMesh *em) +{ + BMEdit_RecalcTesselation_intern(em); + + 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); + } +} + +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em) +{ + BMesh *bm = em->bm; + int act; + + if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) { + act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act); + + act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY); + CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act); + } +} + +/*does not free the BMEditMesh struct itself*/ +void BMEdit_Free(BMEditMesh *em) +{ + if(em->derivedFinal) { + if (em->derivedFinal!=em->derivedCage) { + em->derivedFinal->needsFree= 1; + em->derivedFinal->release(em->derivedFinal); + } + em->derivedFinal= NULL; + } + if(em->derivedCage) { + em->derivedCage->needsFree= 1; + em->derivedCage->release(em->derivedCage); + em->derivedCage= NULL; + } + + em->retopo_paint_data= NULL; + + if (em->looptris) MEM_freeN(em->looptris); + + if (em->vert_index) MEM_freeN(em->vert_index); + if (em->edge_index) MEM_freeN(em->edge_index); + if (em->face_index) MEM_freeN(em->face_index); + + 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 (*faceNos)[3]; + + /*lookup caches; these are rebuilt on dm->RecalcTesselation() + (or when the derivedmesh is created, of course)*/ + GHash *vhash, *ehash, *fhash; + BMVert **vtable; + BMEdge **etable; + BMFace **ftable; + + /*private variables, for number of verts/edges/faces + within the above hash/table members*/ + int tv, te, tf; +} EditDerivedBMesh; + +static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm) +{ + BMIter iter; + BMHeader *h; + int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + + bmdm->tv = bmdm->tc->bm->totvert; + bmdm->te = bmdm->tc->bm->totedge; + bmdm->tf = bmdm->tc->bm->totface; + + if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL); + if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL); + if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL); + + bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived"); + + if (bmdm->vtable) MEM_freeN(bmdm->vtable); + if (bmdm->etable) MEM_freeN(bmdm->etable); + if (bmdm->ftable) MEM_freeN(bmdm->ftable); + + if (bmdm->tc->bm->totvert) + bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable"); + else bmdm->vtable = NULL; + + if (bmdm->tc->bm->totedge) + bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable"); + else bmdm->etable = NULL; + + if (bmdm->tc->bm->totface) + bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable"); + else bmdm->ftable = NULL; + + for (a=0; a<3; a++) { + h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL); + for (i=0; h; h=BMIter_Step(&iter), i++) { + switch (a) { + case 0: + bmdm->vtable[i] = (BMVert*) h; + BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i)); + break; + case 1: + bmdm->etable[i] = (BMEdge*) h; + BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i)); + break; + case 2: + bmdm->ftable[i] = (BMFace*) h; + BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i)); + break; + + } + } + } +} + +static void bmDM_calcNormals(DerivedMesh *UNUSED(dm)) +{ + /* Nothing to do: normals are already calculated and stored on the + BMVerts and BMFaces */ +} + +static void bmDM_recalcTesselation(DerivedMesh *UNUSED(dm)) +{ + //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + //bmdm_recalc_lookups(bmdm); +} + +static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; + int i; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; i++, eve=BMIter_Step(&iter)) { + if (bmdm->vertexCos) { + func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL); + } else { + func(userData, i, eve->co, eve->no, NULL); + } + } +} +static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + BMIter viter; + + eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&viter), i++) { + BM_SetIndex(eve, i); + } + + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) + func(userData, i, + bmdm->vertexCos[BM_GetIndex(eed->v1)], + bmdm->vertexCos[BM_GetIndex(eed->v2)]); + } else { + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) + func(userData, i, eed->v1->co, eed->v2->co); + } + +} + +static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + BMIter viter; + + eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&viter), i++) { + BM_SetIndex(eve, i); + } + + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]); + glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]); + } + } + glEnd(); + + } else { + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + glVertex3fv(eed->v1->co); + glVertex3fv(eed->v2->co); + } + } + glEnd(); + } +} + +static void bmDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges)) +{ + bmDM_drawMappedEdges(dm, NULL, NULL); +} + +static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEdge *eed; + BMIter iter; + int i; + + if (bmdm->vertexCos) { + BMVert *eve; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BM_SetIndex(eve, i); + + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + setDrawInterpOptions(userData, i, 0.0); + glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v1)]); + setDrawInterpOptions(userData, i, 1.0); + glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v2)]); + } + } + glEnd(); + } else { + glBegin(GL_LINES); + eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL); + for(i=0; eed; i++,eed=BMIter_Step(&iter)) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + setDrawInterpOptions(userData, i, 0.0); + glVertex3fv(eed->v1->co); + setDrawInterpOptions(userData, i, 1.0); + glVertex3fv(eed->v2->co); + } + } + glEnd(); + } +} + +static void bmDM_drawUVEdges(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; + BMFace *efa; + BMIter iter; + + glBegin(GL_LINES); + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BMIter liter; + BMLoop *l; + MLoopUV *lastluv = NULL, *firstluv = NULL; + + if (BM_TestHFlag(efa, BM_HIDDEN)) + continue; + + BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (luv) { + if (lastluv) + glVertex2fv(luv->uv); + glVertex2fv(luv->uv); + + lastluv = luv; + if (!firstluv) + firstluv = luv; + } + } + + if (lastluv) { + glVertex2fv(lastluv->uv); + glVertex2fv(firstluv->uv); + } + } + glEnd(); +} + +static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], + float (*vertexCos)[3]) +{ + BMIter iter; + BMLoop *l; + int tot = 0; + + zero_v3(cent); + + /*simple (and stupid) median (average) based method :/ */ + + if (vertexCos) { + l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa); + for (; l; l=BMIter_Step(&iter)) { + add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]); + tot++; + } + } else { + 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 (tot==0) return; + mul_v3_fl(cent, 1.0f/(float)tot); +} + +static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMFace *efa; + BMIter iter; + float cent[3]; + int i; + + if (bmdm->vertexCos) { + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BM_SetIndex(eve, i); + } + + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) { + bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos); + func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no); + } +} + +static void bmDM_drawMappedFaces(DerivedMesh *dm, + int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), + void *userData, int UNUSED(useColors), + int (*setMaterial)(int, void *attribs), + int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMFace *efa; + BMIter iter; + int i, draw; + + const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */ + + /* GL_ZERO is used to detect if drawing has started or not */ + GLenum poly_prev= GL_ZERO; + GLenum shade_prev= GL_ZERO; + + (void)setMaterial; /* UNUSED */ + + /* currently unused -- each original face is handled separately */ + (void)compareDrawOptions; + + if (bmdm->vertexCos) { + /* add direct access */ + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + float (*faceNos)[3]= bmdm->faceNos; + BMVert *eve; + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BM_SetIndex(eve, i); + + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) + BM_SetIndex(efa, i); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->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= 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(); + poly_prev= GL_ZERO; /* force glBegin */ + + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); + } + + if(skip_normals) { + if(poly_type != poly_prev) { + if(poly_prev != GL_ZERO) glEnd(); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ + } + glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[(int) 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)); /* BMesh: will always be GL_TRIANGLES */ + } + if(poly_type != poly_prev) { + if(poly_prev != GL_ZERO) glEnd(); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ + } + + if (!drawSmooth) { + glNormal3fv(faceNos[i]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]); + } else { + glNormal3fv(vertexNos[(int) BM_GetIndex(l[0]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]); + glNormal3fv(vertexNos[(int) BM_GetIndex(l[1]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]); + glNormal3fv(vertexNos[(int) BM_GetIndex(l[2]->v)]); + glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]); + } + } + + if (draw==2) { + glEnd(); + poly_prev= GL_ZERO; /* force glBegin */ + + glDisable(GL_POLYGON_STIPPLE); + } + } + } + } else { + efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL); + for (i=0; efa; efa=BMIter_Step(&iter), i++) + BM_SetIndex(efa, i); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->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= 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(); + poly_prev= GL_ZERO; /* force glBegin */ + + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); + } + + if(skip_normals) { + if(poly_type != poly_prev) { + if(poly_prev != GL_ZERO) glEnd(); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ + } + 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)); /* BMesh: will always be GL_TRIANGLES */ + } + if(poly_type != poly_prev) { + if(poly_prev != GL_ZERO) glEnd(); + glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */ + } + + if (!drawSmooth) { + glNormal3fv(efa->no); + glVertex3fv(l[0]->v->co); + glVertex3fv(l[1]->v->co); + glVertex3fv(l[2]->v->co); + } else { + glNormal3fv(l[0]->v->no); + glVertex3fv(l[0]->v->co); + glNormal3fv(l[1]->v->no); + glVertex3fv(l[1]->v->co); + glNormal3fv(l[2]->v->no); + glVertex3fv(l[2]->v->co); + } + } + if (draw==2) { + glEnd(); + poly_prev= GL_ZERO; /* force glBegin */ + + glDisable(GL_POLYGON_STIPPLE); + } + } + } + } + + /* if non zero we know a face was rendered */ + 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 bmDM_drawFacesTex_common(DerivedMesh *dm, + int (*drawParams)(MTFace *tface, int has_vcol, int matnr), + int (*drawParamsMapped)(void *userData, int index), + void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMEditMesh *em = bmdm->tc; + BMesh *bm= bmdm->tc->bm; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMFace *efa; + BMVert *eve; + BMIter iter; + MLoopUV *luv[3], dummyluv = {{0}}; + MLoopCol *lcol[3], dummylcol = {0}; + int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL); + int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY); + + luv[0] = luv[1] = luv[2] = &dummyluv; + lcol[0] = lcol[1] = lcol[2] = &dummylcol; + + dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255; + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + i = 0; + BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) + BM_SetIndex(efa, i++); + + if (vertexCos) { + i = 0; + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) + BM_SetIndex(eve, i++); + + glBegin(GL_TRIANGLES); + for (i=0; i<em->tottri; i++) { + BMLoop **ls = em->looptris[i]; + MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY); + MTFace mtf = {{{0}}}; + /*unsigned char *cp= NULL;*/ /*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(&mtf, has_vcol, efa->mat_nr); + else if(drawParamsMapped) + 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 (!has_vcol) { + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + } + + if (!drawSmooth) { + glNormal3fv(bmdm->faceNos[i]); + + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + glTexCoord2fv(luv[0]->uv); + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]); + + glTexCoord2fv(luv[1]->uv); + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]); + + glTexCoord2fv(luv[2]->uv); + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]); + } else { + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + glTexCoord2fv(luv[0]->uv); + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + glNormal3fv(vertexNos[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(); + } else { + i = 0; + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) + BM_SetIndex(eve, i++); + + for (i=0; i<em->tottri; i++) { + BMLoop **ls = em->looptris[i]; + MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY); + MTFace mtf = {{{0}}}; + /*unsigned char *cp= NULL;*/ /*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(&mtf, has_vcol, efa->mat_nr); + else if(drawParamsMapped) + 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 (!has_vcol) { + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + } + + glBegin(GL_TRIANGLES); + if (!drawSmooth) { + glNormal3fv(efa->no); + + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + if (luv[0]) + glTexCoord2fv(luv[0]->uv); + if (lcol[0]) + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[0]->v->co); + + if (luv[1]) + glTexCoord2fv(luv[1]->uv); + if (lcol[1]) + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[1]->v->co); + + if (luv[2]) + glTexCoord2fv(luv[2]->uv); + if (lcol[2]) + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + else glColor3ub(0, 0, 0); + glVertex3fv(ls[2]->v->co); + } else { + bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol); + + if (luv[0]) + glTexCoord2fv(luv[0]->uv); + if (lcol[0]) + glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[0]->v->no); + glVertex3fv(ls[0]->v->co); + + if (luv[1]) + glTexCoord2fv(luv[1]->uv); + if (lcol[1]) + glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[1]->v->no); + glVertex3fv(ls[1]->v->co); + + if (luv[2]) + glTexCoord2fv(luv[2]->uv); + if (lcol[2]) + glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r); + else glColor3ub(0, 0, 0); + glNormal3fv(ls[2]->v->no); + glVertex3fv(ls[2]->v->co); + } + glEnd(); + } + } + } +} + +static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr)) +{ + bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); +} + +static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +{ + bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); +} + +static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs), + int (*setDrawOptions)(void *userData, int index), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMEditMesh *em = bmdm->tc; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMVert *eve; + BMFace *efa; + BMIter iter; + BMLoop **ltri; + DMVertexAttribs attribs; + GPUVertexAttribs gattribs; + + int i, b, matnr, new_matnr, dodraw; + + dodraw = 0; + matnr = -1; + + memset(&attribs, 0, sizeof(attribs)); + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + BM_ITER_INDEX(eve, &iter, bm, BM_VERTS_OF_MESH, NULL, i) { + BM_SetIndex(eve, i); + } + +#define PASSATTRIB(loop, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[BM_GetIndex(eve)]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + 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++) { \ + 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]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ + } + + BM_ITER_INDEX(efa, &iter, bm, BM_FACES_OF_MESH, NULL, i) { + BM_SetIndex(efa, 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; + if(new_matnr != matnr) { + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(dodraw) { + glBegin(GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(bmdm->faceNos[i]); + else glNormal3fv(efa->no); + + PASSATTRIB(ltri[0], ltri[0]->v, 0); + if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + else glVertex3fv(ltri[0]->v->co); + + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + else glVertex3fv(ltri[1]->v->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(ltri[0], ltri[0]->v, 0); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + } + else { + glNormal3fv(ltri[0]->v->no); + glVertex3fv(ltri[0]->v->co); + } + + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + } + else { + glNormal3fv(ltri[1]->v->no); + glVertex3fv(ltri[1]->v->co); + } + + PASSATTRIB(ltri[2], ltri[2]->v, 2); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); + } + else { + glNormal3fv(ltri[2]->v->no); + glVertex3fv(ltri[2]->v->co); + } + } + glEnd(); + } + } +#undef PASSATTRIB +} + +static void bmDM_drawFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + + +static void bmDM_drawMappedFacesMat(DerivedMesh *dm, + void (*setMaterial)(void *userData, int, void *attribs), + int (*setFace)(void *userData, int index), void *userData) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMEditMesh *em = bmdm->tc; + float (*vertexCos)[3]= bmdm->vertexCos; + float (*vertexNos)[3]= bmdm->vertexNos; + BMVert *eve; + BMFace *efa; + BMIter iter; + BMLoop **ltri; + DMVertexAttribs attribs= {{{0}}}; + GPUVertexAttribs gattribs; + int i, b, matnr, new_matnr, dodraw; + + matnr = -1; + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + BM_ITER_INDEX(eve, &iter, bm, BM_VERTS_OF_MESH, NULL, i) { + BM_SetIndex(eve, i); + } + +#define PASSATTRIB(loop, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[BM_GetIndex(eve)]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + 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++) { \ + 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); \ + } \ +} + + for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) { + int drawSmooth= BM_TestHFlag(efa, BM_SMOOTH); + + efa = ltri[0]->f; + + /* face hiding */ + if(setFace && !setFace(userData, BM_GetIndex(efa))) + continue; + + /* material */ + new_matnr = efa->mat_nr + 1; + if(new_matnr != matnr) { + setMaterial(userData, matnr = new_matnr, &gattribs); + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + /* face */ + glBegin(GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(bmdm->faceNos[i]); + else glNormal3fv(efa->no); + + PASSATTRIB(ltri[0], ltri[0]->v, 0); + if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + else glVertex3fv(ltri[0]->v->co); + + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + else glVertex3fv(ltri[1]->v->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(ltri[0], ltri[0]->v, 0); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]); + } + else { + glNormal3fv(ltri[0]->v->no); + glVertex3fv(ltri[0]->v->co); + } + + PASSATTRIB(ltri[1], ltri[1]->v, 1); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]); + } + else { + glNormal3fv(ltri[1]->v->no); + glVertex3fv(ltri[1]->v->co); + } + + PASSATTRIB(ltri[2], ltri[2]->v, 2); + if(vertexCos) { + glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]); + glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]); + } + else { + glNormal3fv(ltri[2]->v->no); + glVertex3fv(ltri[2]->v->co); + } + } + glEnd(); + } +#undef PASSATTRIB +} + +static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMVert *eve; + BMIter iter; + int i; + + if (bmdm->tc->bm->totvert) { + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + if (bmdm->vertexCos) { + DO_MINMAX(bmdm->vertexCos[i], min_r, max_r); + } else { + DO_MINMAX(eve->co, min_r, max_r); + } + } + } else { + min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; + } +} +static int bmDM_getNumVerts(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totvert; +} + +static int bmDM_getNumEdges(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totedge; +} + +static int bmDM_getNumTessFaces(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->tottri; +} + +static int bmDM_getNumFaces(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + + return bmdm->tc->bm->totface; +} + +static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r) +{ + copy_v3_v3(vert_r->co, ev->co); + + vert_r->no[0] = (short)(ev->no[0] * 32767.0f); + vert_r->no[1] = (short)(ev->no[1] * 32767.0f); + vert_r->no[2] = (short)(ev->no[2] * 32767.0f); + + vert_r->flag = BMFlags_To_MEFlags(ev); + + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f); + } + + return 1; +} + +static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) +{ + BMVert *ev; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) { + printf("error in bmDM_getVert.\n"); + return; + } + + ev = ((EditDerivedBMesh *)dm)->vtable[index]; + bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r); +} + +static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *e; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) { + printf("error in bmDM_getEdge.\n"); + return; + } + + e = bmdm->etable[index]; + + if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f); + } + + if (CustomData_has_layer(&bm->edata, CD_CREASE)) { + edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f); + } + + edge_r->flag = BMFlags_To_MEFlags(e); + + edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1)); + edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2)); +} + +static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMFace *ef; + BMLoop **l; + + if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) { + printf("error in bmDM_getTessFace.\n"); + return; + } + + l = ((EditDerivedBMesh *)dm)->tc->looptris[index]; + + ef = l[0]->f; + + face_r->mat_nr = (unsigned char) ef->mat_nr; + face_r->flag = BMFlags_To_MEFlags(ef); + + face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v)); + face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v)); + face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v)); + face_r->v4 = 0; + + test_index_face(face_r, NULL, 0, 3); +} + +static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) +{ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMVert *ev; + BMIter iter; + + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for( ; ev; ev = BMIter_Step(&iter), ++vert_r) { + copy_v3_v3(vert_r->co, ev->co); + + vert_r->no[0] = (short) (ev->no[0] * 32767.0); + vert_r->no[1] = (short) (ev->no[1] * 32767.0); + vert_r->no[2] = (short) (ev->no[2] * 32767.0); + + vert_r->flag = BMFlags_To_MEFlags(ev); + + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f); + } + } +} + +static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) +{ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMEdge *ee; + BMIter iter; + BMVert *ev; + int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT); + int i, has_crease = CustomData_has_layer(&bm->edata, CD_CREASE); + + /* store vertex indices in tmp union */ + ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; ev; ev=BMIter_Step(&iter), i++) + BM_SetIndex(ev, i); + + 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); + } + + if (has_crease) { + edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f); + } + + edge_r->flag = BMFlags_To_MEFlags(ee); + + edge_r->v1 = (int)BM_GetIndex(ee->v1); + edge_r->v2 = (int)BM_GetIndex(ee->v2); + } +} + +static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMFace *ef; + BMVert *ev; + BMIter iter; + BMLoop **l; + int i; + + /* store vertexes indices in tmp union */ + i = 0; + BM_ITER(ev, &iter, bm, BM_VERTS_OF_MESH, NULL) + BM_SetIndex(ev, i++); + + 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 = BMFlags_To_MEFlags(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); + } +} + + +static void bmDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r) +{ + /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */ + BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm; + BMIter iter, liter; + BMVert *v; + BMFace *f; + BMLoop *l; + BMEdge *e; + int i; + + i = 0; + BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) { + BM_SetIndex(v, i++); + } + + i = 0; + BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) { + BM_SetIndex(e, i++); + } + + 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++; + } + } +} + +static void bmDM_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 = BMFlags_To_MEFlags(f); + poly_r->loopstart = i; + poly_r->totloop = f->len; + poly_r->mat_nr = f->mat_nr; + + poly_r++; + i += f->len; + } +} + +static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm; + BMesh *bm= bmdm->tc->bm; + BMFace *efa; + char *data, *bmdata; + void *datalayer; + int index /*, offset*/ /*UNUSED */, size, i; + + datalayer = DM_get_tessface_data_layer(dm, type); + if(datalayer) + return datalayer; + + /* layers are store per face for editmesh, we convert to a tbmporary + * data layer array in the derivedmesh when these are requested */ + if(type == CD_MTFACE || type == CD_MCOL) { + index = CustomData_get_layer_index(&bm->pdata, type); + + if(index != -1) { + /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */ + size = CustomData_sizeof(type); + + DM_add_tessface_layer(dm, type, CD_CALLOC, NULL); + index = CustomData_get_layer_index(&dm->faceData, type); + dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; + + data = datalayer = DM_get_tessface_data_layer(dm, type); + for (i=0; i<bmdm->tc->tottri; i++, data+=size) { + efa = bmdm->tc->looptris[i][0]->f; + /*BMESH_TODO: need to still add tface data, + derived from the loops.*/ + bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type); + memcpy(data, bmdata, size); + } + } + } + + return datalayer; +} + +static void bmDM_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 bmDM_release(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm; + + if (DM_release(dm)) { + if (bmdm->vertexCos) { + MEM_freeN(bmdm->vertexCos); + MEM_freeN(bmdm->vertexNos); + MEM_freeN(bmdm->faceNos); + } + + if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL); + if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL); + if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL); + + if (bmdm->vtable) MEM_freeN(bmdm->vtable); + if (bmdm->etable) MEM_freeN(bmdm->etable); + if (bmdm->ftable) MEM_freeN(bmdm->ftable); + + MEM_freeN(bmdm); + } +} + +static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->vdata; +} + +static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->edata; +} + +static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->dm.faceData; +} + +static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->ldata; +} + +static CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm; + + return &bmdm->tc->bm->pdata; +} + + +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.numVertData = bm->totvert; + bmdm->dm.numEdgeData = bm->totedge; + bmdm->dm.numFaceData = em->tottri; + bmdm->dm.numLoopData = bm->totloop; + bmdm->dm.numPolyData = bm->totface; + + bmdm->dm.getVertCos = bmDM_getVertCos; + bmdm->dm.getMinMax = bmDM_getMinMax; + + bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout; + bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout; + bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout; + bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout; + bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout; + + bmdm->dm.getNumVerts = bmDM_getNumVerts; + bmdm->dm.getNumEdges = bmDM_getNumEdges; + bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces; + bmdm->dm.getNumFaces = bmDM_getNumFaces; + + bmdm->dm.getVert = bmDM_getVert; + bmdm->dm.getEdge = bmDM_getEdge; + bmdm->dm.getTessFace = bmDM_getTessFace; + bmdm->dm.copyVertArray = bmDM_copyVertArray; + bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray; + bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray; + bmdm->dm.copyLoopArray = bmDM_copyLoopArray; + bmdm->dm.copyPolyArray = bmDM_copyPolyArray; + + bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray; + + bmdm->dm.calcNormals = bmDM_calcNormals; + bmdm->dm.recalcTesselation = bmDM_recalcTesselation; + + bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert; + bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge; + bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter; + + bmdm->dm.drawEdges = bmDM_drawEdges; + bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges; + bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp; + bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces; + bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex; + bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL; + bmdm->dm.drawMappedFacesMat = bmDM_drawMappedFacesMat; + bmdm->dm.drawFacesTex = bmDM_drawFacesTex; + bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL; + bmdm->dm.drawUVEdges = bmDM_drawUVEdges; + + bmdm->dm.release = bmDM_release; + + bmdm->vertexCos = vertexCos; + + if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) { + BMIter iter; + BMVert *eve; + int i; + + DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL); + + eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT, + CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT)); + } + + if(vertexCos) { + BMVert *eve; + BMIter iter; + int totface = bmdm->tc->tottri; + int i; + + eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) + BM_SetIndex(eve, i); + + bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno"); + bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno"); + + for (i=0; i<bmdm->tc->tottri; i++) { + BMLoop **l = bmdm->tc->looptris[i]; + float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)]; + float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)]; + float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)]; + float *no = bmdm->faceNos[i]; + + normal_tri_v3( no,v1, v2, v3); + add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no); + add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no); + add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no); + } + + eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); + for (i=0; eve; eve=BMIter_Step(&iter), i++) { + float *no = bmdm->vertexNos[i]; + /* following Mesh convention; we use vertex coordinate itself + * for normal in this case */ + if (normalize_v3(no)==0.0) { + copy_v3_v3(no, vertexCos[i]); + normalize_v3(no); + } + } + } + + //bmdm_recalc_lookups(bmdm); + + return (DerivedMesh*) bmdm; +} diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 7b58c0bc00b..99a609f7ce2 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -590,7 +590,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 eb7d07a6f7d..94868ffee87 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,32 @@ Key *copy_key(Key *key) return keyn; } + +Key *copy_key_nolib(Key *key) +{ + Key *keyn; + KeyBlock *kbn, *kb; + + if(key==0) return 0; + + keyn= MEM_dupallocN(key); + + BLI_duplicatelist(&keyn->block, &key->block); + + kb= key->block.first; + kbn= keyn->block.first; + while(kbn) { + + if(kbn->data) kbn->data= MEM_dupallocN(kbn->data); + if(kb==key->refkey) keyn->refkey= kbn; + + kbn= kbn->next; + kb= kb->next; + } + + return keyn; +} + void make_local_key(Key *key) { @@ -495,18 +538,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 +1046,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 +1060,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 +1080,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 +1499,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 7332b89f629..4155551763e 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 ec9d4873057..e106ebae63d 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -41,16 +41,19 @@ #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" #include "BLI_bpath.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_edgehash.h" -#include "BLI_utildefines.h" +#include "BLI_scanfill.h" #include "BKE_animsys.h" #include "BKE_main.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" @@ -64,20 +67,316 @@ #include "BKE_curve.h" /* -- */ #include "BKE_object.h" +#include "BKE_tessmesh.h" +#include "BLI_edgehash.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_math.h" +#include "BLI_cellalloc.h" +#include "BLI_array.h" +#include "BLI_edgehash.h" +#include "bmesh.h" + +enum { + MESHCMP_DVERT_WEIGHTMISMATCH = 1, + MESHCMP_DVERT_GROUPMISMATCH, + MESHCMP_DVERT_TOTGROUPMISMATCH, + MESHCMP_LOOPCOLMISMATCH, + MESHCMP_LOOPUVMISMATCH, + MESHCMP_LOOPMISMATCH, + MESHCMP_POLYVERTMISMATCH, + MESHCMP_POLYMISMATCH, + MESHCMP_EDGEUNKNOWN, + MESHCMP_VERTCOMISMATCH, + MESHCMP_CDLAYERS_MISMATCH, +}; -EditMesh *BKE_mesh_get_editmesh(Mesh *me) +static const char *cmpcode_to_str(int code) { - return me->edit_mesh; + switch (code) { + case MESHCMP_DVERT_WEIGHTMISMATCH: + return "Vertex Weight Mismatch"; + case MESHCMP_DVERT_GROUPMISMATCH: + return "Vertex Group Mismatch"; + case MESHCMP_DVERT_TOTGROUPMISMATCH: + return "Vertex Doesn't Belong To Same Number Of Groups"; + case MESHCMP_LOOPCOLMISMATCH: + return "Vertex Color Mismatch"; + case MESHCMP_LOOPUVMISMATCH: + return "UV Mismatch"; + case MESHCMP_LOOPMISMATCH: + return "Loop Mismatch"; + case MESHCMP_POLYVERTMISMATCH: + return "Loop Vert Mismatch In Poly Test"; + case MESHCMP_POLYMISMATCH: + return "Loop Vert Mismatch"; + case MESHCMP_EDGEUNKNOWN: + return "Edge Mismatch"; + case MESHCMP_VERTCOMISMATCH: + return "Vertex Coordinate Mismatch"; + case MESHCMP_CDLAYERS_MISMATCH: + "CustomData Layer Count Mismatch"; + default: + return "Mesh Comparison Code Unknown"; + } } -void BKE_mesh_end_editmesh(Mesh *UNUSED(me), EditMesh *UNUSED(em)) +/*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; +} + +/*used for testing. returns an error string the two meshes don't match*/ +const char *mesh_cmp(Mesh *me1, Mesh *me2, float thresh) +{ + 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; } +static void mesh_ensure_tesselation_customdata(Mesh *me) +{ + int tottex, totcol; + + tottex = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + totcol = CustomData_number_of_layers(&me->fdata, CD_MCOL); + + if (tottex != CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY) || + totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL)) + { + CustomData_free(&me->fdata, me->totface); + + me->mface = NULL; + me->mtface = NULL; + me->mcol = NULL; + me->totface = 0; + + memset(&me->fdata, 0, sizeof(&me->fdata)); + + CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface); + printf("Warning! Tesselation uvs or vcol data got out of sync, had to reset!\n"); + } +} + +/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or + mloopcol and mcol) have the same relative active/render/clone/mask indices.*/ +static void mesh_update_linked_customdata(Mesh *me) +{ + int act; + + if (me->edit_btmesh) + BMEdit_UpdateLinkedCustomData(me->edit_btmesh); + + mesh_ensure_tesselation_customdata(me); + + if (CustomData_has_layer(&me->pdata, CD_MTEXPOLY)) { + act = CustomData_get_active_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_active(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_render_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_render(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_render(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_clone_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_clone(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_clone(&me->fdata, CD_MTFACE, act); + + act = CustomData_get_stencil_layer(&me->pdata, CD_MTEXPOLY); + CustomData_set_layer_stencil(&me->ldata, CD_MLOOPUV, act); + CustomData_set_layer_stencil(&me->fdata, CD_MTFACE, act); + } + + if (CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) { + act = CustomData_get_active_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_active(&me->fdata, CD_MCOL, act); + + act = CustomData_get_render_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_render(&me->fdata, CD_MCOL, act); + + act = CustomData_get_clone_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_clone(&me->fdata, CD_MCOL, act); + + act = CustomData_get_stencil_layer(&me->ldata, CD_MLOOPCOL); + CustomData_set_layer_stencil(&me->fdata, CD_MCOL, act); + } +} void mesh_update_customdata_pointers(Mesh *me) { + mesh_update_linked_customdata(me); + me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY); @@ -87,6 +386,13 @@ void mesh_update_customdata_pointers(Mesh *me) me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); + + me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); + me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); + + me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY); + me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); + me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); } /* Note: unlinking is called when me->id.us is 0, question remains how @@ -117,9 +423,10 @@ void unlink_mesh(Mesh *me) /* do not free mesh itself */ -void free_mesh(Mesh *me) +void free_mesh(Mesh *me, int unlink) { - unlink_mesh(me); + if (unlink) + unlink_mesh(me); if(me->pv) { if(me->pv->vert_map) MEM_freeN(me->pv->vert_map); @@ -135,7 +442,9 @@ void free_mesh(Mesh *me) CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); - + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + if(me->adt) { BKE_free_animdata(&me->id); me->adt= NULL; @@ -145,7 +454,7 @@ void free_mesh(Mesh *me) if(me->bb) MEM_freeN(me->bb); if(me->mselect) MEM_freeN(me->mselect); - if(me->edit_mesh) MEM_freeN(me->edit_mesh); + if(me->edit_btmesh) MEM_freeN(me->edit_btmesh); } void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) @@ -160,7 +469,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) for (i=0; i<copycount; i++){ if (src[i].dw){ - dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); + dst[i].dw = BLI_cellalloc_calloc (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight); } } @@ -179,7 +488,7 @@ void free_dverts(MDeformVert *dvert, int totvert) /* Free any special data from the verts */ for (i=0; i<totvert; i++){ - if (dvert[i].dw) MEM_freeN (dvert[i].dw); + if (dvert[i].dw) BLI_cellalloc_free (dvert[i].dw); } MEM_freeN (dvert); } @@ -204,6 +513,7 @@ Mesh *copy_mesh(Mesh *me) { Mesh *men; MTFace *tface; + MTexPoly *txface; int a, i; men= copy_libblock(&me->id); @@ -217,6 +527,8 @@ Mesh *copy_mesh(Mesh *me) CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert); CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge); CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface); + CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop); + CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly); mesh_update_customdata_pointers(men); /* ensure indirect linked data becomes lib-extern */ @@ -230,8 +542,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->pv= NULL; /* looks like this is no-longer supported but NULL just incase */ men->bb= MEM_dupallocN(men->bb); @@ -242,21 +564,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); + } } } } @@ -272,7 +623,7 @@ void make_local_mesh(Mesh *me) { Main *bmain= G.main; Object *ob; - int is_local= FALSE, is_lib= FALSE; + int local=0, lib=0; /* - only lib users: do nothing * - only local users: set flag @@ -281,28 +632,32 @@ void make_local_mesh(Mesh *me) if(me->id.lib==NULL) return; if(me->id.us==1) { - id_clear_lib_data(bmain, &me->id); + me->id.lib= NULL; + me->id.flag= LIB_LOCAL; + + new_id(&bmain->mesh, (ID *)me, NULL); expand_local_mesh(me); return; } - for(ob= bmain->object.first; ob && ELEM(0, is_lib, is_local); ob= ob->id.next) { + for(ob= bmain->object.first; ob && ELEM(0, lib, local); ob= ob->id.next) { if(me == ob->data) { - if(ob->id.lib) is_lib= TRUE; - else is_local= TRUE; + if(ob->id.lib) lib= 1; + else local= 1; } } - if(is_local && is_lib == FALSE) { - id_clear_lib_data(bmain, &me->id); + if(local && lib==0) { + me->id.lib= NULL; + me->id.flag= LIB_LOCAL; + + new_id(&bmain->mesh, (ID *)me, NULL); expand_local_mesh(me); } - else if(is_local && is_lib) { + else if(local && lib) { Mesh *men= copy_mesh(me); men->id.us= 0; - - /* Remap paths of new ID using old library as base. */ BKE_id_lib_local_paths(bmain, &men->id); for(ob= bmain->object.first; ob; ob= ob->id.next) { @@ -581,13 +936,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 */ @@ -659,6 +1018,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 = mloop[(b+1)%mpoly->totloop].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) @@ -666,7 +1045,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; @@ -762,31 +1141,43 @@ void mball_to_mesh(ListBase *lb, Mesh *me) } make_edges(me, 0); // all edges - } + convert_mfaces_to_mpolys(me); + + me->totface = mesh_recalcTesselation( + &me->fdata, &me->ldata, &me->pdata, + me->mvert, me->totface, me->totloop, me->totpoly); + + mesh_update_customdata_pointers(me); + } } /* 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; @@ -825,7 +1216,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; @@ -963,11 +1356,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; @@ -984,12 +1401,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; } @@ -999,15 +1418,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->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface); 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(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; @@ -1068,10 +1491,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; @@ -1234,10 +1657,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--; } @@ -1248,6 +1677,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]; @@ -1258,10 +1697,98 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) } } - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, + me->totpoly, NULL, NULL, 0, NULL, NULL); } -void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3]) +void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys, + int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces, + int *origIndexFace, float (*faceNors_r)[3]) +{ + float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r; + float (*tnorms)[3], (*edgevecbuf)[3]; + float **vertcos = NULL, **vertnos = NULL; + BLI_array_declare(vertcos); + BLI_array_declare(vertnos); + int i, j, maxPolyVerts = 0; + MFace *mf; + MPoly *mp; + MLoop *ml; + + if (numPolys == 0) { + return; + } + + mp = mpolys; + for (i=0; i<numPolys; i++, mp++) { + maxPolyVerts = MAX2(mp->totloop, maxPolyVerts); + } + + if (maxPolyVerts == 0) { + return; + } + + /*first go through and calculate normals for all the polys*/ + edgevecbuf = MEM_callocN(sizeof(float)*3*maxPolyVerts, "edgevecbuf mesh.c"); + tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c"); + 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"); + + 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]); + } + + accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop); + } + + /* 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); + } + + if (origIndexFace && fnors==faceNors_r && numFaces) { + mf = mfaces; + for (i=0; i<numFaces; i++, mf++, origIndexFace++) { + if (*origIndexFace < numPolys) { + VECCOPY(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"); + } + } + } + + BLI_array_free(vertcos); + BLI_array_free(vertnos); + MEM_freeN(edgevecbuf); + MEM_freeN(tnorms); + if (fnors != faceNors_r) + MEM_freeN(fnors); + if (pnors != polyNors_r) + MEM_freeN(pnors); + + fnors = pnors = NULL; + +} + +void mesh_calc_tessface_normals(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"); @@ -1299,6 +1826,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) + BLI_cellalloc_free(ld->disps); + + ld->disps = BLI_cellalloc_calloc(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); + + BLI_edgehash_free(eh, NULL); +} + float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] { int i, numVerts = me->totvert; @@ -1306,27 +1986,32 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] if (numVerts_r) *numVerts_r = numVerts; for (i=0; i<numVerts; i++) - VECCOPY(cos[i], me->mvert[i].co); + copy_v3_v3(cos[i], me->mvert[i].co); 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; @@ -1342,17 +2027,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++; } } @@ -1370,14 +2055,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); @@ -1524,6 +2209,289 @@ void mesh_pmv_off(Mesh *me) } } +void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata, + CustomData *pdata, int lindex[3], int findex, + int polyindex) +{ + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL); + int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + for (j=0; j<3; j++) { + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); + + for (j=0; j<3; j++) { + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL); + + for (j=0; j<3; j++) { + mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + +/* + this function recreates a tesselation. + returns number of tesselation faces. + */ +int mesh_recalcTesselation(CustomData *fdata, + CustomData *ldata, CustomData *pdata, + MVert *mvert, int totface, int UNUSED(totloop), + int totpoly) +{ + MPoly *mp, *mpoly; + MLoop *ml, *mloop; + MFace *mf = NULL, *mface; + BLI_array_declare(mf); + EditVert *v, *lastv, *firstv; + EditFace *f; + int *origIndex = NULL; + BLI_array_declare(origIndex); + int *polyIndex = NULL; + BLI_array_declare(polyIndex); + int i, j, k, lindex[4], *polyorigIndex; + int numTex, numCol; + + mpoly = CustomData_get_layer(pdata, CD_MPOLY); + mloop = CustomData_get_layer(ldata, CD_MLOOP); + + numTex = CustomData_number_of_layers(ldata, CD_MLOOPUV); + numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + + k = 0; + mp = mpoly; + polyorigIndex = CustomData_get_layer(pdata, CD_ORIGINDEX); + for (i=0; i<totpoly; i++, mp++) { + if (mp->totloop > 2) { + 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); + + BLI_edgefill(2); + for (f=fillfacebase.first; f; f=f->next) { + BLI_array_growone(mf); + BLI_array_append(polyIndex, i); + + /*these are loop indices, they'll be transformed + into vert indices later.*/ + mf[k].v1 = f->v1->keyindex; + mf[k].v2 = f->v2->keyindex; + mf[k].v3 = f->v3->keyindex; + mf[k].v4 = 0; + + mf[k].mat_nr = mp->mat_nr; + mf[k].flag = mp->flag; + + if (polyorigIndex) { + BLI_array_append(origIndex, polyorigIndex[polyIndex[k]]); + } + + k++; + } + + BLI_end_edgefill(); + } + } + + CustomData_free(fdata, totface); + memset(fdata, 0, sizeof(CustomData)); + totface = k; + + CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mf, totface); + CustomData_add_layer(fdata, CD_POLYINDEX, CD_ASSIGN, polyIndex, totface); + if (origIndex) { + CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, origIndex, totface); + } + + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + /* 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 = CustomData_get_layer(pdata, CD_NORMAL); + float *fnors = CustomData_add_layer(fdata, CD_NORMAL, CD_CALLOC, NULL, totface); + for (i=0; i<totface; i++, fnors++) { + copy_v3_v3(fnors, &pnors[polyIndex[i]]); + } + } + + mface = mf; + for (i=0; i<totface; i++, mf++) { + /*sort loop indices to ensure winding is correct*/ + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + + mesh_loops_to_tri_corners(fdata, ldata, pdata, + lindex, i, polyIndex[i]); + } + + return totface; +} + +/* + * COMPUTE POLY NORMAL + * + * Computes the normal of a planar + * polygon See Graphics Gems for + * computing newell normal. + * +*/ +static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvert, float *normal) +{ + + MVert *v1, *v2, *v3; + double u[3], v[3], w[3]; + double n[3] = {0.0, 0.0, 0.0}, l; + int i; + + for(i = 0; i < mpoly->totloop; i++){ + v1 = mvert + loopstart[i].v; + v2 = mvert + loopstart[(i+1)%mpoly->totloop].v; + v3 = mvert + loopstart[(i+2)%mpoly->totloop].v; + + VECCOPY(u, v1->co); + VECCOPY(v, v2->co); + VECCOPY(w, v3->co); + + /*this fixes some weird numerical error*/ + if (i==0) { + u[0] += 0.0001f; + u[1] += 0.0001f; + u[2] += 0.0001f; + } + + /* newell's method + + so thats?: + (a[1] - b[1]) * (a[2] + b[2]); + a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2] + + odd. half of that is the cross product. . .what's the + other half? + + also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2]) + */ + + n[0] += (u[1] - v[1]) * (u[2] + v[2]); + n[1] += (u[2] - v[2]) * (u[0] + v[0]); + n[2] += (u[0] - v[0]) * (u[1] + v[1]); + } + + l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; + l = sqrt(l); + + if (l == 0.0) { + normal[0] = 0.0f; + normal[1] = 0.0f; + normal[2] = 1.0f; + + return; + } else l = 1.0f / l; + + n[0] *= l; + n[1] *= l; + n[2] *= l; + + normal[0] = (float) n[0]; + normal[1] = (float) n[1]; + normal[2] = (float) n[2]; +} + +void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float *no) +{ + if(mpoly->totloop > 4) { + mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no); + } + else if(mpoly->totloop == 3){ + MVert *v1, *v2, *v3; + + v1 = mvarray + (loopstart++)->v; + v2 = mvarray + (loopstart++)->v; + v3 = mvarray + loopstart->v; + normal_tri_v3( no,v1->co, v2->co, v3->co); + } + else if(mpoly->totloop == 4){ + MVert *v1, *v2, *v3, *v4; + + v1 = mvarray + (loopstart++)->v; + v2 = mvarray + (loopstart++)->v; + v3 = mvarray + (loopstart++)->v; + v4 = mvarray + loopstart->v; + normal_quad_v3( no,v1->co, v2->co, v3->co, v4->co); + } + else{ /*horrible, two sided face!*/ + no[0] = 0.0; + no[1] = 0.0; + no[2] = 1.0; + } +} + /* basic vertex data functions */ int minmax_mesh(Mesh *me, float min[3], float max[3]) { diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index ec24f72874d..d8e91a140f7 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -358,7 +358,7 @@ int BKE_mesh_validate(Mesh *me, int do_verbose) int BKE_mesh_validate_dm(DerivedMesh *dm) { - return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); + return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), TRUE, FALSE); } void BKE_mesh_calc_edges(Mesh *mesh, int update) @@ -369,6 +369,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; @@ -381,20 +382,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); + } } } @@ -415,9 +433,29 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&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..45c642fc0f3 --- /dev/null +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -0,0 +1,218 @@ +/* + * ***** 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 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 numTex, numCol; + 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); + + /*needed later*/ + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); + + totvert = dm->getNumVerts(dm); + totedge = dm->getNumEdges(dm); + totface = dm->getNumFaces(dm); + + vtable = MEM_callocN(sizeof(void**)*totvert, "vert table in BMDM_Copy"); + etable = MEM_callocN(sizeof(void**)*totedge, "edge table in BMDM_Copy"); + + /*do verts*/ + mv = mvert = dm->dupVertArray(dm); + for (i=0; i<totvert; i++, mv++) { + v = BM_Make_Vert(bm, mv->co, NULL); + normal_short_to_float_v3(v->no, mv->no); + v->head.hflag = MEFlags_To_BMFlags(mv->flag, BM_VERT); + + CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data); + vtable[i] = v; + } + MEM_freeN(mvert); + + /*do edges*/ + me = medge = dm->dupEdgeArray(dm); + for (i=0; i<totedge; i++, me++) { + e = BM_Make_Edge(bm, vtable[me->v1], vtable[me->v2], NULL, 0); + + e->head.hflag = MEFlags_To_BMFlags(me->flag, BM_EDGE); + + CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data); + etable[i] = e; + } + MEM_freeN(medge); + + /*do faces*/ + 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); + + ml = mloop + mp->loopstart; + for (j=0; j<mp->totloop; j++, ml++) { + BLI_array_growone(verts); + BLI_array_growone(edges); + + 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 = MEFlags_To_BMFlags(mp->flag, BM_FACE); + 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); + else BMEdit_RecalcTesselation(em); + + return em; +} + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index ae0774eb34f..6db24258dca 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -42,6 +42,7 @@ #include "BLI_pbvh.h" #include "BLI_editVert.h" #include "BLI_utildefines.h" +#include "BLI_cellalloc.h" #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" @@ -50,6 +51,7 @@ #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_subsurf.h" +#include "BKE_tessmesh.h" #include "BKE_object.h" @@ -64,7 +66,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) { @@ -75,7 +77,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; @@ -127,6 +129,9 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_fi static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) { + if (!ob || !mmd) + return 0; + if(render) return (mmd->modifier.scene)? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl): mmd->renderlvl; else if(ob->mode == OB_MODE_SCULPT) @@ -177,7 +182,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); } @@ -234,7 +239,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); @@ -253,26 +258,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); + MDisps *mdisp, *md; + int i, j, totlvl= 0; - for(i = 0; i < me->totface; ++i, ++mdisp) { - int S = me->mface[i].v4 ? 4 : 3; - - if(mdisp->totdisp == 0) continue; - - while(1) { - int side = (1 << (totlvl-1)) + 1; - int lvl_totdisp = side*side*S; - if(mdisp->totdisp == lvl_totdisp) - break; - else if(mdisp->totdisp < lvl_totdisp) - --totlvl; - else - ++totlvl; + 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; } } @@ -285,10 +295,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); @@ -300,31 +310,27 @@ 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; - float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + for(i = 0; i < totloop; ++i) { + int totdisp = multires_grid_tot[lvl]; + float (*disps)[3] = BLI_cellalloc_calloc(sizeof(float) * 3 * totdisp, "multires disps"); if(mdisps[i].disps) - MEM_freeN(mdisps[i].disps); + BLI_cellalloc_free(mdisps[i].disps); mdisps[i].disps = disps; mdisps[i].totdisp = totdisp; @@ -385,44 +391,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 = BLI_cellalloc_calloc(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; + BLI_cellalloc_free(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); } } @@ -438,8 +443,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); @@ -594,7 +599,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); @@ -611,9 +616,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 */ @@ -658,10 +663,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); @@ -671,7 +676,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); @@ -682,7 +687,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) { @@ -706,18 +711,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; } @@ -731,23 +748,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(S = 0; S < numVerts; ++S, ++gIndex) { + 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, ++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++) { @@ -810,8 +832,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; @@ -825,7 +847,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); @@ -868,7 +890,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); @@ -879,20 +901,141 @@ 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, *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 = BLI_cellalloc_calloc(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); + } + + ccgdm->needsFree = 1; + ccgdm->release(ccgdm); +} + void multires_stitch_grids(Object *ob) { /* utility for smooth brush */ @@ -953,8 +1096,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]); @@ -973,7 +1118,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) @@ -1029,7 +1177,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) int x, y, S; float (*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */ - disps = MEM_callocN(sizeof(float) * 3 * newtotdisp, "multires disps"); + disps = BLI_cellalloc_calloc(sizeof(float) * 3 * newtotdisp, "multires disps"); out = disps; for(S = 0; S < nvert; S++) { @@ -1046,7 +1194,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) } } - MEM_freeN(mdisp->disps); + BLI_cellalloc_free(mdisp->disps); mdisp->totdisp= newtotdisp; mdisp->disps= disps; @@ -1054,15 +1202,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 = BLI_cellalloc_calloc(sizeof(float)*3*totdisp, "multires disp in conversion"); + mdisps2[k].totdisp = totdisp; + memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp*j, totdisp); + } + + } } } @@ -1587,8 +1753,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; @@ -1602,7 +1768,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; @@ -1610,8 +1777,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) return; @@ -1647,15 +1814,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++) { @@ -1728,6 +1895,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; @@ -1778,6 +1946,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) @@ -2185,13 +2354,13 @@ void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) MDisps *src; if(dst->disps) - MEM_freeN(dst->disps); + BLI_cellalloc_free(dst->disps); side = sqrt(tri1->totdisp / 3); st = (side<<1)-1; dst->totdisp = 4 * side * side; - out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps"); + out = dst->disps = BLI_cellalloc_calloc(3*dst->totdisp*sizeof(float), "join disps"); for(S = 0; S < 4; S++) for(y = 0; y < side; ++y) diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index e3b5b83964e..53eee35de3a 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -135,7 +135,7 @@ int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, //calculate number of tris nfaces = dm->getNumFaces(dm); - faces = dm->getFaceArray(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 ffd49ecc57d..5ad7432fa39 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -85,6 +85,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" @@ -1730,7 +1731,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; @@ -1739,7 +1740,22 @@ static void give_parvert(Object *par, int nr, float *vec) Mesh *me= par->data; DerivedMesh *dm; - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; + + if(em) { + BMVert *eve; + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + int *keyindex = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX); + + if(keyindex && *keyindex==nr) { + memcpy(vec, eve->co, sizeof(float)*3); + break; + } + } + } + dm = (em)? em->derivedFinal: par->derivedFinal; if(dm) { @@ -1767,9 +1783,6 @@ static void give_parvert(Object *par, int nr, float *vec) dm->getVertCo(dm, 0, vec); } } - - if(em) - BKE_mesh_end_editmesh(me, em); } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { Nurb *nu; @@ -2528,22 +2541,19 @@ 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); + makeDerivedMesh(scene, ob, em, scene->customdata_mask, 0); /* was CD_MASK_BAREMESH */ } else - makeDerivedMesh(scene, ob, NULL, scene->customdata_mask); + 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; - unsigned int data_mask= scene->customdata_mask | ob->customdata_mask | CD_MASK_BAREMESH; + BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL; if(em) { - makeDerivedMesh(scene, ob, em, data_mask); /* was CD_MASK_BAREMESH */ - BKE_mesh_end_editmesh(ob->data, em); + makeDerivedMesh(scene, ob, em, scene->customdata_mask | CD_MASK_BAREMESH, 0); /* was CD_MASK_BAREMESH */ } else - makeDerivedMesh(scene, ob, NULL, data_mask); + makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH, 0); #endif } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d28fe8b8509..82da0e549d9 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -55,6 +55,8 @@ #include "BLI_threads.h" #include "BLI_linklist.h" #include "BLI_bpath.h" +#include "BLI_cellalloc.h" +#include "BLI_math.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -695,7 +697,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; @@ -798,9 +800,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) @@ -1539,7 +1541,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); } @@ -1587,11 +1589,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 */ @@ -1660,7 +1662,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; @@ -1684,15 +1686,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; @@ -1750,7 +1752,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); @@ -3326,10 +3328,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]); @@ -3644,7 +3646,6 @@ void make_local_particlesettings(ParticleSettings *part) } else if(is_local && is_lib) { ParticleSettings *partn= psys_copy_settings(part); - partn->id.us= 0; /* Remap paths of new ID using old library as base. */ @@ -3684,7 +3685,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 @@ -3696,7 +3697,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); @@ -4341,7 +4342,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); } @@ -4361,14 +4362,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); } @@ -4527,7 +4528,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}; sim.scene= scene; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index cb12230615e..0caad666226 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -57,7 +57,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" @@ -67,6 +66,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLI_linklist.h" +#include "BLI_edgehash.h" +#include "BLI_cellalloc.h" #include "BKE_main.h" #include "BKE_animsys.h" @@ -347,9 +348,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"); @@ -518,8 +519,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; } @@ -778,7 +779,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: @@ -808,7 +809,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); @@ -820,7 +821,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; @@ -868,7 +869,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); @@ -1035,7 +1036,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; @@ -1112,7 +1113,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); @@ -1138,7 +1139,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]); @@ -1196,7 +1197,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) { @@ -1271,7 +1272,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D } else { if(dm->numFaceData) - COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); + COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); } if(COMPARE_ORIG_INDEX) { @@ -3448,7 +3449,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); } @@ -3483,7 +3484,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if(dvert) { if(!dvert->totweight) { - dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->dw = BLI_cellalloc_calloc(sizeof(MDeformWeight), "deformWeight"); dvert->totweight = 1; } @@ -3504,7 +3505,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if(dvert) { if(!dvert->totweight) { - dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->dw = BLI_cellalloc_calloc(sizeof(MDeformWeight), "deformWeight"); dvert->totweight = 1; } /* roots should be 1.0, the rest can be anything from 0.0 to 1.0 */ diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index aed246690bd..fb8bb791f32 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,11 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c DerivedMesh *object_get_derived_final(Object *ob) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; - if(em) { + if (em) + { DerivedMesh *dm = em->derivedFinal; - BKE_mesh_end_editmesh(me, em); return dm; } @@ -587,7 +589,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 60941ef78a3..038e48f5769 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" @@ -314,7 +314,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; } @@ -325,7 +325,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 @@ -333,16 +333,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); } @@ -359,7 +359,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 @@ -1343,7 +1343,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); - smd->coll->dm = CDDM_copy(dm); + smd->coll->dm = CDDM_copy(dm, 1); // rigid movement support copy_m4_m4(smd->coll->mat_old, smd->coll->mat); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 61dea5773e9..9e82bae9195 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); /// @@ -159,7 +164,8 @@ static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) { return edgeBase + x-1; } } -static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) { + +BM_INLINE int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) { int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f)); int numVerts = ccgSubSurf_getFaceNumVerts(f); @@ -196,13 +202,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) @@ -213,8 +218,9 @@ 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); @@ -222,12 +228,13 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, 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); 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; @@ -250,8 +257,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex); float uv[3]; - uv[0]= (tface+v->f)->uv[v->tfindex][0]; - uv[1]= (tface+v->f)->uv[v->tfindex][1]; + uv[0]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[0]; + uv[1]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[1]; uv[2]= 0.0f; ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv); @@ -263,18 +270,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; - 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); 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); @@ -296,14 +307,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*) 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); @@ -315,18 +332,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), 0, 1, 0); - if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) { + if(!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) { ccgSubSurf_free(uvss); return; } @@ -349,6 +370,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]; @@ -364,12 +386,22 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, float *c = faceGridData[(y + 1)*gridSize + x + 1].co; float *d = faceGridData[(y + 1)*gridSize + x + 0].co; - 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 (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; } } } @@ -380,65 +412,123 @@ 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 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); +} + +#if 0 +static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, + int drawInteriorEdges, int useSubsurfUv, + DerivedMesh *dm, struct MultiresSubsurf *ms) +{ + DerivedMesh *cgdm, *result; + double curt = PIL_check_seconds_timer(); + + cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); + result = CDDM_copy(cgdm, 1); + + printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt); + + cgdm->needsFree = 1; + cgdm->release(cgdm); + + CDDM_calc_normals(result); + + return result; } +#endif -static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, +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); @@ -471,38 +561,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_face_data_layer(dm, CD_ORIGINDEX); + for (i=0; i<dm->numPolyData; i++, mp++) { + CCGFace *f=NULL; - 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); + BLI_array_empty(fVerts); - // this is very bad, means mesh is internally consistent. - // it is not really possible to continue without modifying - // other parts of code significantly to handle missing faces. - // since this really shouldn't even be possible we just bail. - if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3, + 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), 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; } /***/ @@ -519,9 +614,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); @@ -563,32 +658,32 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { ccgEdgeIterator_free(ei); ccgVertIterator_free(vi); } -static int ccgDM_getNumVerts(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumVerts(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalVerts(ccgdm->ss); + return ccgSubSurf_getNumFinalVerts(cgdm->ss); } -static int ccgDM_getNumEdges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumEdges(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalEdges(ccgdm->ss); + return ccgSubSurf_getNumFinalEdges(cgdm->ss); } -static int ccgDM_getNumFaces(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; +static int cgdm_getNumTessFaces(DerivedMesh *dm) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; - return ccgSubSurf_getNumFinalFaces(ccgdm->ss); + return ccgSubSurf_getNumFinalFaces(cgdm->ss); } static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; DMGridData *vd; int i; memset(mv, 0, sizeof(*mv)); - if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { + if((vertNum < cgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -601,10 +696,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; @@ -613,7 +708,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); @@ -635,28 +730,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); @@ -681,13 +776,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; @@ -697,18 +792,48 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSideEdges; int gridInternalEdges; + 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; + } - i = 0; - while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge) + if (i < 0) { + i = 0; + break; + } + + if (i > lastface) { + i = lastface; + break; + + } + + if (i == lasti) + break; + + lasti = previ; + } + + i = i > 0 ? i - 1 : i; + 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); @@ -736,18 +861,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; @@ -760,8 +885,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; @@ -772,19 +897,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.numFaceData) + return; - i = 0; - while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace) - ++i; + i = cgdm->reverseFaceMap[faceNum]; - f = ccgdm->faceMap[i].face; + f = cgdm->faceMap[i].face; /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/ - offset = faceNum - ccgdm->faceMap[i].startFace; + offset = faceNum - cgdm->faceMap[i].startFace; grid = offset / gridFaces; offset %= gridFaces; y = offset / gridSideEdges; @@ -804,8 +929,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; @@ -815,7 +940,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); @@ -844,7 +969,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++) { @@ -861,7 +986,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); @@ -872,25 +997,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); @@ -902,7 +1027,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); @@ -911,7 +1036,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); @@ -925,7 +1050,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)); @@ -953,18 +1078,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; @@ -982,6 +1107,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; @@ -992,9 +1122,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; @@ -1075,14 +1314,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); @@ -1090,9 +1329,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); @@ -1111,8 +1350,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,8 +1482,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(draw ccgEdgeIterator_free(ei); } static void ccgDM_drawLooseEdges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -1367,20 +1606,20 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) } /* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); GPUVertexAttribs gattribs; DMVertexAttribs attribs= {{{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; @@ -1408,7 +1647,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v totface = ccgSubSurf_getNumFaces(ss); for(a = 0, i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; + CCGFace *f = cgdm->faceMap[i].face; int S, x, y, drawSmooth; int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); int origIndex = ccgDM_getFaceMapIndex(ss, f); @@ -1507,12 +1746,12 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v ccgFaceIterator_free(fi); } -static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { +static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } /* 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; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -1660,15 +1899,15 @@ 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; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); int gridSize = ccgSubSurf_getGridSize(ss); unsigned char *cp1, *cp2; int useTwoSide=1; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); cp1= col1; if(col2) { @@ -1729,30 +1968,30 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), uns ccgFaceIterator_free(fi); } -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), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; - MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); - char *faceFlags = ccgdm->faceFlags; + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; + MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + char *faceFlags = cgdm->faceFlags; int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; - ccgdm_pbvh_update(ccgdm); + ccgdm_pbvh_update(cgdm); if(!mcol) - mcol = dm->getFaceDataArray(dm, CD_MCOL); + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); 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)); @@ -1872,21 +2111,21 @@ 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)) { - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); + cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL); } -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) +static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); + cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } -static void ccgDM_drawUVEdges(DerivedMesh *dm) +static void cgdm_drawUVEdges(DerivedMesh *dm) { - MFace *mf = dm->getFaceArray(dm); - MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); + MFace *mf = dm->getTessFaceArray(dm); + MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if (tf) { @@ -1917,25 +2156,25 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm) static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs), int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) { - 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; @@ -2037,9 +2276,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u } } } -static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; +static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = cgdm->ss; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -2067,9 +2306,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); @@ -2098,9 +2337,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)) { @@ -2118,7 +2357,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)) { @@ -2131,6 +2370,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); @@ -2147,12 +2390,66 @@ 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; @@ -2167,8 +2464,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; @@ -2181,8 +2478,8 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type) { if(type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; int *origindex; int a, i, index, totnone, totorig, totedge; int edgeSize= ccgSubSurf_getEdgeSize(ss); @@ -2199,7 +2496,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++) @@ -2216,19 +2513,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) { if(type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - CCGSubSurf *ss= ccgdm->ss; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= cgdm->ss; int *origindex; int a, i, index, totface; int gridFaces = ccgSubSurf_getGridSize(ss) - 1; - DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX); + 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); @@ -2239,19 +2536,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) return origindex; } - return DM_get_face_data_layer(dm, type); + return DM_get_tessface_data_layer(dm, type); } static int ccgDM_getNumGrids(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm; int index, numFaces, numGrids; - numFaces= ccgSubSurf_getNumFaces(ccgdm->ss); + numFaces= ccgSubSurf_getNumFaces(cgdm->ss); numGrids= 0; for(index=0; index<numFaces; index++) { - CCGFace *f = ccgdm->faceMap[index].face; + CCGFace *f = cgdm->faceMap[index].face; numGrids += ccgSubSurf_getFaceNumVerts(f); } @@ -2260,11 +2557,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; @@ -2297,15 +2594,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); @@ -2313,10 +2610,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; @@ -2324,12 +2621,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++) { @@ -2343,43 +2640,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) @@ -2461,55 +2758,84 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) return ccgdm->pbvh; } +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 = ccgDM_getMinMax; - ccgdm->dm.getNumVerts = ccgDM_getNumVerts; - ccgdm->dm.getNumFaces = ccgDM_getNumFaces; + ccgdm->dm.getMinMax = cgdm_getMinMax; + ccgdm->dm.getNumVerts = cgdm_getNumVerts; + ccgdm->dm.getNumEdges = cgdm_getNumEdges; + ccgdm->dm.getNumTessFaces = cgdm_getNumTessFaces; + ccgdm->dm.getNumFaces = cgdm_getNumTessFaces; + + ccgdm->dm.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.copyTessFaceArray = ccgDM_copyFinalFaceArray; + ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray; + ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray; ccgdm->dm.getVertData = DM_get_vert_data; ccgdm->dm.getEdgeData = DM_get_edge_data; - ccgdm->dm.getFaceData = DM_get_face_data; + ccgdm->dm.getTessFaceData = DM_get_face_data; ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; - ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer; + ccgdm->dm.getTessFaceDataArray = ccgDM_get_face_data_layer; ccgdm->dm.getNumGrids = ccgDM_getNumGrids; ccgdm->dm.getGridSize = ccgDM_getGridSize; ccgdm->dm.getGridData = ccgDM_getGridData; @@ -2518,35 +2844,45 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getFaceMap = ccgDM_getFaceMap; ccgdm->dm.getPBVH = ccgDM_getPBVH; - ccgdm->dm.getVertCos = ccgdm_getVertCos; - ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert; - ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge; - ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter; + ccgdm->dm.getTessFace = ccgDM_getFinalFace; + ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; + ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; + ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; + ccgdm->dm.getVertData = DM_get_vert_data; + ccgdm->dm.getEdgeData = DM_get_edge_data; + ccgdm->dm.getTessFaceData = DM_get_face_data; + + ccgdm->dm.calcNormals = ccgDM_calcNormals; + + 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); @@ -2556,7 +2892,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); @@ -2565,7 +2901,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); @@ -2574,139 +2910,194 @@ 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_face_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); + for (s=0; s<numVerts; s++) { + BLI_array_growone(loopidx); + loopidx[s] = loopindex++; + } + + BLI_array_empty(vertidx); + for(s = 0; s < numVerts; s++) { + CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s); + + BLI_array_growone(vertidx); + vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + } + - vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + /*I think this is for interpolating the center vert?*/ + w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1); + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; } - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0], - numVerts, vertNum); ++vertNum; - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + /*interpolate per-vert data*/ + for(s = 0; s < numVerts; s++) { for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[x][0][0]; - w[S] = weight[x][0][1]; - w[nextS] = weight[x][0][2]; - w[otherS] = weight[x][0][3]; - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, - numVerts, vertNum); + w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts; + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; + } + ++vertNum; } } - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + /*interpolate per-vert data*/ + for(s = 0; s < numVerts; s++) { for(y = 1; y < gridFaces; y++) { for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[y * gridFaces + x][0][0]; - w[S] = weight[y * gridFaces + x][0][1]; - w[nextS] = weight[y * gridFaces + x][0][2]; - w[otherS] = weight[y * gridFaces + x][0][3]; - DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, - numVerts, vertNum); + w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts; + DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2, + numVerts, vertNum); + + if (vertOrigIndex) { + *vertOrigIndex = ORIGINDEX_NONE; + ++vertOrigIndex; + } + ++vertNum; } } } - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; - - weight = (numVerts == 4) ? qweight : tweight; - - for(y = 0; y < gridFaces; y++) { - for(x = 0; x < gridFaces; x++) { - FaceVertWeight w; - int j; - - for(j = 0; j < 4; ++j) { - w[j][prevS] = (*weight)[j][0]; - w[j][S] = (*weight)[j][1]; - w[j][nextS] = (*weight)[j][2]; - w[j][otherS] = (*weight)[j][3]; + if (has_edge_origindex) { + for(i = 0; i < numFinalEdges; ++i) + *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i, + CD_ORIGINDEX) = ORIGINDEX_NONE; + } + + for (s=0; s<numVerts; s++) { + /*interpolate per-face data*/ + for (y=0; y<gridFaces; y++) { + for (x=0; x<gridFaces; x++) { + w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts; + CustomData_interp(&dm->loopData, &ccgdm->dm.loopData, + loopidx, w2, NULL, numVerts, loopindex2); + loopindex2++; + + /*copy over poly data, e.g. mtexpoly*/ + CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1); + + /*generate tesselated face data used for drawing*/ + ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData, + &ccgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol); + + /*set original index data*/ + if (faceOrigIndex) { + *faceOrigIndex = origIndex; + faceOrigIndex++; + } + if (polyOrigIndex) { + *polyOrigIndex = origIndex; + polyOrigIndex++; } - DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL, - &w, 1, faceNum); - weight++; + ccgdm->reverseFaceMap[faceNum] = index; - ++faceNum; + faceNum++; } } } - faceFlags[index*2] = mface[origIndex].flag; - faceFlags[index*2 + 1] = mface[origIndex].mat_nr; - edgeNum += numFinalEdges; } - if(useSubsurfUv) { - CustomData *fdata = &ccgdm->dm.faceData; - CustomData *dmfdata = &dm->faceData; - int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE); - int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE); - - for (i=0; i<numlayer && i<dmnumlayer; i++) - set_subsurf_uv(ss, dm, &ccgdm->dm, i); - } - - edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags"); - for(index = 0; index < totedge; ++index) { CCGEdge *e = ccgdm->edgeMap[index].edge; int numFinalEdges = edgeSize - 1; + int mapIndex = ccgDM_getEdgeMapIndex(ss, e); int x; int vertIdx[2]; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); @@ -2720,6 +3111,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; @@ -2728,32 +3122,63 @@ 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 vertIdx; + int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v); + int vidx; - vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); + vidx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); ccgdm->vertMap[index].startVert = vertNum; /* set the vert base vert */ *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum; - DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1); + DM_copy_vert_data(dm, &ccgdm->dm, vidx, vertNum, 1); + if (vertOrigIndex) { + *vertOrigIndex = mapIndex; + ++vertOrigIndex; + } ++vertNum; } - MEM_freeN(qweight); - MEM_freeN(tweight); + ccgdm->dm.numVertData = vertNum; + ccgdm->dm.numEdgeData = edgeNum; + ccgdm->dm.numFaceData = faceNum; + ccgdm->dm.numLoopData = loopindex2; + ccgdm->dm.numPolyData = faceNum; + + BLI_array_free(vertidx); + BLI_array_free(loopidx); + free_ss_weights(&wtable); return ccgdm; } @@ -2770,7 +3195,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); - CCGDerivedMesh *result; + CCGDerivedMesh *result = NULL; if(forEditMode) { int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; @@ -2799,7 +3224,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( result->freeSS = 1; } else { - int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); + int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental); int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; CCGSubSurf *ss; @@ -2824,7 +3249,14 @@ struct DerivedMesh *subsurf_make_derived_from_derived( smd->mCache = ss = _getSubSurf(smd->mCache, levels, useAging, 0, useSimple); - 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, 0, useSimple); + + ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + + } result = getCCGDerivedMesh(smd->mCache, drawInteriorEdges, |