[Bf-blender-cvs] [924ee69] mesh-transfer-data: Mesh Transfer Data **********

Bastien Montagne noreply at git.blender.org
Fri Oct 3 22:51:00 CEST 2014


Commit: 924ee6922a8ab8a1b16798beb2ad42109d7e3096
Author: Bastien Montagne
Date:   Fri Sep 12 11:47:31 2014 +0200
Branches: mesh-transfer-data
https://developer.blender.org/rB924ee6922a8ab8a1b16798beb2ad42109d7e3096

Mesh Transfer Data
**********

WARNING - fully non-functional commit (not even compilable!).

Mesh transfer data (data here being either real CD layers, like e.g. skinning weights, UVs, etc., or 'fake' ones, like e.g. vgroups, shapekeys, but also edge crease, smooth/sharp/seam flags, etc.) is subdivided in several sub-modules:
* Mapping between mesh elements (verts, edges, polys or loops), in BKE's `mesh_mapping`.
* Mapping between data layers (for non-singleton data types), mostly handled in `ED_object` and BKE's `customdata` areas.
* Transfer of single data layer, mostly handled in BKE's `customdata` area.

Additional possibilities (only relevant for a subset of data types) are barely sketched up currently:
* A way to filter which elements of destination we actually want to affect (currently, all, also the possibility to only affect those below a given threshold - could also add e.g. vgroup-based selection, etc.).
* A way to alter destination elements' data in other ways than mere replace (add/sub/mul/div/etc.).

All this is designed to be both easy to setup (code-wise) for simple types, and yet flexible enough to be usable by complex/weird data types like vgroups and shapekeys. For now, it is only expected to work in Object/modifier contexts, not quite sure whether having this in BMesh would be that much useful?

Mesh Elements Mapping
-----
This part is rather independent. Vertices and edges mappings are implemented (but not really tested yet, think will have to write some gtests for that anyway). Polygons are also finished, but not tested at all. Loops are mostly written, but not yet finished nor compilable (the most complex ones, since we have to take islands in consideration here).

Note mapping supports a distance threshold, to prevent geometry to far away from each other to match.

Data Layers Mapping
-----
This is handled by a struct defined in BKE_customdata, but filled in ED_object code. Each instance of DataTransferLayerMapping contains all data needed to execute the data transfer for each element of the mesh mapping.

`object_transfer_data.c` handles the generation of those data layers mapping instance for basic types (usual CDLayers, but also bitflags and simple data like edge crease), complex types like vgroups and shapekeys are handled by dedicated helpers in there own files - trying to keep code well ordered.

Transfer of Single Data Layer
-----
This is a low-level simple func in BKE_customdata, that executes the data transfer itself, including weighted interpolation if needed. It expects pre-computed inputs (mesh elements' and data layers' mappings).

High Level
-----
`ED_data_transfer` is the high-level interface to all this, used by the `OBJECT_OT_data_transfer` operator. Once again, not all features are implemented yet, by far.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_bvhutils.h
M	source/blender/blenkernel/BKE_customdata.h
M	source/blender/blenkernel/BKE_mesh_mapping.h
M	source/blender/blenkernel/BKE_modifier.h
M	source/blender/blenkernel/intern/bvhutils.c
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/blenkernel/intern/mesh_mapping.c
M	source/blender/editors/include/ED_object.h
M	source/blender/editors/object/CMakeLists.txt
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_ops.c
A	source/blender/editors/object/object_transfer_data.c
M	source/blender/editors/object/object_vgroup.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 2249d2b..2fc2240 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1077,6 +1077,7 @@ class VIEW3D_MT_object(Menu):
         layout.separator()
 
         layout.operator("object.join")
+        layout.operator("object.data_transfer")
 
         layout.separator()
 
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 4bc8fc4..f8649e9 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -56,8 +56,8 @@ typedef struct BVHTreeFromMesh {
 	struct MEdge *edge;     /* only used for BVHTreeFromMeshEdges */
 	struct MFace *face;
 	bool vert_allocated;
-	bool face_allocated;
 	bool edge_allocated;
+	bool face_allocated;
 
 	/* radius for raycast */
 	float sphere_radius;
@@ -69,36 +69,28 @@ typedef struct BVHTreeFromMesh {
 } BVHTreeFromMesh;
 
 /*
- * Builds a bvh tree where nodes are the vertexs of the given mesh.
+ * Builds a bvh tree where nodes are the relevant elements of the given mesh.
  * Configures BVHTreeFromMesh.
  *
  * The tree is build in mesh space coordinates, this means special care must be made on queries
  * so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
+ * Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree.
  * 
  * free_bvhtree_from_mesh should be called when the tree is no longer needed.
  */
 BVHTree *bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
-
-/*
- * Builds a bvh tree where nodes are the faces of the given mesh.
- * Configures BVHTreeFromMesh.
- *
- * The tree is build in mesh space coordinates, this means special care must be made on queries
- * so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
- *
- * The returned value is the same as in data->tree, its only returned to make it easier to test
- * the success 
- * 
- * free_bvhtree_from_mesh should be called when the tree is no longer needed.
- */
-BVHTree *bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
+                                    const bool vert_allocated, bool *mask, int numVerts_active,
+                                    float epsilon, int tree_type, int axis);
 
 BVHTree *bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
+BVHTree *bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, struct MVert *vert, const bool vert_allocated,
+                                    struct MFace *face, const int numFaces, const bool face_allocated,
+                                    bool *mask, int numFaces_active,
+                                    float epsilon, int tree_type, int axis);
+
 /*
  * Frees data allocated by a call to bvhtree_from_mesh_*.
  */
@@ -115,11 +107,12 @@ float nearest_point_in_tri_surface_squared(const float v0[3], const float v1[3],
  */
 
 //Using local coordinates
-#define BVHTREE_FROM_FACES      0
-#define BVHTREE_FROM_VERTICES   1
-#define BVHTREE_FROM_EDGES      2
-
-#define BVHTREE_FROM_FACES_EDITMESH  3
+enum {
+	BVHTREE_FROM_VERTS           = 0,
+	BVHTREE_FROM_EDGES           = 1,
+	BVHTREE_FROM_FACES           = 2,
+	BVHTREE_FROM_FACES_EDITMESH  = 3,
+};
 
 typedef struct LinkNode *BVHCache;
 
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 9a6524c..f08fd3c 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -41,6 +41,8 @@ extern "C" {
 #include "BLI_sys_types.h"
 #include "BLI_utildefines.h"
 
+#include "DNA_customdata_types.h"
+
 struct BMesh;
 struct ID;
 struct CustomData;
@@ -77,6 +79,9 @@ extern const CustomDataMask CD_MASK_EVERYTHING;
 
 void customData_mask_layers__print(CustomDataMask mask);
 
+typedef void (*cd_interp)(void **sources, const float *weights, const float *sub_weights, int count, void *dest);
+typedef void (*cd_copy)(const void *source, void *dest, int count);
+
 /**
  * Checks if the layer at physical offset \a layer_n (in data->layers) support math
  * the below operations.
@@ -245,14 +250,14 @@ void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int typ
 void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
 
 bool CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
+const char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
 
 /* gets a pointer to the active or first layer of type
  * returns NULL if there is no layer of type
  */
 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);
+void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name);
 int CustomData_get_offset(const struct CustomData *data, int type);
 int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
 
@@ -360,6 +365,60 @@ void CustomData_external_read(struct CustomData *data,
 void CustomData_external_reload(struct CustomData *data,
                                 struct ID *id, CustomDataMask mask, int totelem);
 
+/* Mesh-to-mesh transfer data. */
+
+struct Mesh2MeshMapping;
+typedef struct DataTransferLayerMapping DataTransferLayerMapping;
+
+typedef void (*cd_datatransfer_interp)(const DataTransferLayerMapping *laymap,
+                                       void **sources, const float *weights, int count, void *dest);
+
+/* Fake CD_LAYERS (those are actually 'real' data stored directly into elements' structs). */
+enum {
+	CD_FAKE             = 1 << 8,
+
+	/* Vertices. */
+	CD_FAKE_MDEFORMVERT = CD_FAKE | CD_MDEFORMVERT,  /* *sigh* due to how vgroups are stored :( . */
+	CD_FAKE_SHAPEKEY    = CD_FAKE | CD_SHAPEKEY,  /* Not available as real CD layer in non-bmesh context. */
+
+	/* Edges. */
+	CD_FAKE_SEAM        = CD_FAKE | 100,  /* UV seam flag for edges. */
+	CD_FAKE_CREASE      = CD_FAKE | CD_CREASE,  /* *sigh*. */
+
+	/* Multiple types of mesh elements... */
+	CD_FAKE_BWEIGHT     = CD_FAKE | CD_BWEIGHT,  /* *sigh*. */
+
+	CD_FAKE_SHARP       = CD_FAKE | 200,  /* Sharp flag for edges, smooth flag for faces. */
+};
+
+enum {
+	ME_VERT = 1,
+	ME_EDGE = 2,
+	ME_POLY = 3,
+	ME_LOOP = 4,
+};
+
+typedef struct DataTransferLayerMapping {
+	DataTransferLayerMapping *next, *prev;
+
+	int data_type;
+
+	void *data_src;      /* Data source array (can be regular CD data, vertices/edges/etc., keyblocks...). */
+	void *data_dst;      /* Data dest array (same type as dat_src). */
+	int data_n_src;      /* Index to affect in data_src (used e.g. for vgroups). */
+	int data_n_dst;      /* Index to affect in data_dst (used e.g. for vgroups). */
+	size_t elem_size;    /* Size of one element of data_src/data_dst. */
+
+	size_t data_size;    /* Size of actual data we transfer. */
+	size_t data_offset;  /* Offset of actual data we transfer (in element contained in data_src/dst). */
+	uint64_t data_flag;  /* For bitflag transfer, flag(s) to affect in transfered data. */
+
+	cd_datatransfer_interp interp;
+} DataTransferLayerMapping;
+
+/* Those functions assume src_n and dst_n layers of given type exist in resp. src and dst. */
+void CustomData_data_transfer(const struct Mesh2MeshMapping *m2mmap, const DataTransferLayerMapping *laymap);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index ed7e506..235bb45 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -31,6 +31,9 @@
  *  \ingroup bke
  */
 
+struct CustomData;
+struct DerivedMesh;
+struct MVert;
 struct MPoly;
 struct MEdge;
 struct MLoop;
@@ -109,6 +112,10 @@ void BKE_mesh_vert_poly_map_create(
         MeshElemMap **r_map, int **r_mem,
         const struct MPoly *mface, const struct MLoop *mloop,
         int totvert, int totface, int totloop);
+void BKE_mesh_vert_loop_map_create(
+        MeshElemMap **r_map, int **r_mem,
+        const struct MPoly *mface, const struct MLoop *mloop,
+        int totvert, int totface, int totloop);
 void BKE_mesh_vert_edge_map_create(
         MeshElemMap **r_map, int **r_mem,
         const struct MEdge *medge, int totvert, int totedge);
@@ -129,6 +136,149 @@ int *BKE_mesh_calc_smoothgroups(
         const struct MLoop *mloop, const int totloop,
         int *r_totgroup, const bool use_bitflags);
 
+/* Generic ways to map some geometry elements from a source mesh to a dest one. */
+
+typedef struct Mesh2MeshMappingItem {
+	int nbr_sources;
+	int *indices_src;  /* NULL if no source found. */
+	float *weights_src;  /* NULL if no source found, else, always normalized! */
+	float hit_distance;  /* FLT_MAX if irrelevant or no source found. */
+	int island;  /* For loops only. */
+} Mesh2MeshMappingItem;
+
+/* All mapping computing func return this. */
+typedef struct Mesh2MeshMapping {
+	Mesh2MeshMappingItem *items;  /* Array, one item per dest element. */
+	int nbr_items;
+	void *mem;  /* Memory handler, internal use only. */
+} Mesh2MeshMapping;
+
+
+typedef struct Mesh2MeshMappingIslandItem {
+	int nbr_polys;
+	int *polys_idx;
+} Mesh2MeshMappingIslandItem;
+
+/* For loops, to which poly island each lo

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list