Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Oeser <info@graphics-engineer.com>2020-04-09 19:49:40 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2020-09-17 23:39:57 +0300
commit39de0b79fd635ed67e8b1816c32199177d7f9f07 (patch)
treeb2838abd1c39d3c17e08438740c40c95c33a94f1
parent9ee588cd4af881f3432fddce3044e90bad4e30f6 (diff)
Pointclouds: support mesh <-> pointcloud in convert operator
Just converts verts to points and vice versa. Materials and Attribute layers are preserved (so for example if you set custom radii on the pointcloud, convert to mesh, then convert back to pointcloud, this will be preserved). Also not add a Radius layer by default (it is still added and filled when adding a pointcloud object from the menu), a global Radius property that will be used if there is no radius attribute can be added later. A Radius attribute can also be added in the pointcloud data properties (and filled via python). This will also add a new utility function that copies materials between datablocks: BKE_id_materials_copy ref T75717 Differential Revision: https://developer.blender.org/D7391
-rw-r--r--source/blender/blenkernel/BKE_material.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h11
-rw-r--r--source/blender/blenkernel/BKE_pointcloud.h5
-rw-r--r--source/blender/blenkernel/intern/material.c21
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c97
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/blenkernel/intern/pointcloud.c29
-rw-r--r--source/blender/editors/object/CMakeLists.txt5
-rw-r--r--source/blender/editors/object/object_add.c59
9 files changed, 220 insertions, 11 deletions
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index a30d7d55985..a6d8d2d2d8b 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -99,6 +99,7 @@ void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
struct bNode *BKE_texpaint_slot_material_find_node(struct Material *ma, short texpaint_slot);
/* rna api */
+void BKE_id_materials_copy(struct Main *bmain, struct ID *id_src, struct ID *id_dst);
void BKE_id_material_resize(struct Main *bmain, struct ID *id, short totcol, bool do_id_user);
void BKE_id_material_append(struct Main *bmain, struct ID *id, struct Material *ma);
struct Material *BKE_id_material_pop(struct Main *bmain,
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 6e8c67dde5f..39b15bdd48d 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -54,6 +54,7 @@ struct MemArena;
struct Mesh;
struct ModifierData;
struct Object;
+struct PointCloud;
struct Scene;
#ifdef __cplusplus
@@ -172,6 +173,16 @@ void BKE_mesh_to_curve(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+void BKE_pointcloud_from_mesh(struct Mesh *me, struct PointCloud *pointcloud);
+void BKE_mesh_to_pointcloud(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_mesh_from_pointcloud(struct PointCloud *pointcloud, struct Mesh *me);
+void BKE_pointcloud_to_mesh(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
bool BKE_mesh_material_index_used(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
diff --git a/source/blender/blenkernel/BKE_pointcloud.h b/source/blender/blenkernel/BKE_pointcloud.h
index 295744af5b4..f850e716ea6 100644
--- a/source/blender/blenkernel/BKE_pointcloud.h
+++ b/source/blender/blenkernel/BKE_pointcloud.h
@@ -32,7 +32,12 @@ struct Object;
struct PointCloud;
struct Scene;
+/* PointCloud datablock */
+extern const char *POINTCLOUD_ATTR_POSITION;
+extern const char *POINTCLOUD_ATTR_RADIUS;
+
void *BKE_pointcloud_add(struct Main *bmain, const char *name);
+void *BKE_pointcloud_add_default(struct Main *bmain, const char *name);
struct PointCloud *BKE_pointcloud_copy(struct Main *bmain, const struct PointCloud *pointcloud);
struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 885cc1baefc..d8c0b5d6dce 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -535,6 +535,27 @@ static void material_data_index_clear_id(ID *id)
}
}
+void BKE_id_materials_copy(Main *bmain, ID *id_src, ID *id_dst)
+{
+ Material ***matar_src = BKE_id_material_array_p(id_src);
+ const short *materials_len_p_src = BKE_id_material_len_p(id_src);
+
+ Material ***matar_dst = BKE_id_material_array_p(id_dst);
+ short *materials_len_p_dst = BKE_id_material_len_p(id_dst);
+
+ *materials_len_p_dst = *materials_len_p_src;
+ if (*materials_len_p_src != 0) {
+ (*matar_dst) = MEM_dupallocN(*matar_src);
+
+ for (int a = 0; a < *materials_len_p_src; a++) {
+ id_us_plus((ID *)(*matar_dst)[a]);
+ }
+
+ DEG_id_tag_update(id_dst, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+}
+
void BKE_id_material_resize(Main *bmain, ID *id, short totcol, bool do_id_user)
{
Material ***matar = BKE_id_material_array_p(id);
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 60a9ef2df55..557948ef3a4 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -28,6 +28,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "BLI_edgehash.h"
@@ -53,6 +54,8 @@
#include "BKE_curve.h"
/* -- */
#include "BKE_object.h"
+/* -- */
+#include "BKE_pointcloud.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -903,6 +906,100 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene),
}
}
+void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud)
+{
+ BLI_assert(me != NULL);
+
+ pointcloud->totpoint = me->totvert;
+ CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
+
+ /* Copy over all attributes. */
+ const CustomData_MeshMasks mask = {
+ .vmask = CD_MASK_PROP_ALL,
+ };
+ CustomData_merge(&me->vdata, &pointcloud->pdata, mask.vmask, CD_DUPLICATE, me->totvert);
+ BKE_pointcloud_update_customdata_pointers(pointcloud);
+ CustomData_update_typemap(&pointcloud->pdata);
+
+ MVert *mvert;
+ mvert = me->mvert;
+ for (int i = 0; i < me->totvert; i++, mvert++) {
+ copy_v3_v3(pointcloud->co[i], mvert->co);
+ }
+}
+
+void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
+
+ PointCloud *pointcloud = BKE_pointcloud_add(bmain, ob->id.name + 2);
+
+ BKE_pointcloud_from_mesh(me_eval, pointcloud);
+
+ BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)pointcloud);
+
+ id_us_min(&((Mesh *)ob->data)->id);
+ ob->data = pointcloud;
+ ob->type = OB_POINTCLOUD;
+
+ BKE_object_free_derived_caches(ob);
+}
+
+void BKE_mesh_from_pointcloud(PointCloud *pointcloud, Mesh *me)
+{
+ BLI_assert(pointcloud != NULL);
+
+ me->totvert = pointcloud->totpoint;
+
+ /* Merge over all attributes. */
+ const CustomData_MeshMasks mask = {
+ .vmask = CD_MASK_PROP_ALL,
+ };
+ CustomData_merge(&pointcloud->pdata, &me->vdata, mask.vmask, CD_DUPLICATE, pointcloud->totpoint);
+
+ /* Convert the Position attribute to a mesh vertex. */
+ me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
+ CustomData_update_typemap(&me->vdata);
+
+ const int layer_idx = CustomData_get_named_layer_index(
+ &me->vdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION);
+ CustomDataLayer *pos_layer = &me->vdata.layers[layer_idx];
+ float(*positions)[3] = pos_layer->data;
+
+ MVert *mvert;
+ mvert = me->mvert;
+ for (int i = 0; i < me->totvert; i++, mvert++) {
+ copy_v3_v3(mvert->co, positions[i]);
+ }
+
+ /* Delete Position attribute since it is now in vertex coordinates. */
+ CustomData_free_layer(&me->vdata, CD_PROP_FLOAT3, me->totvert, layer_idx);
+}
+
+void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob)
+{
+ BLI_assert(ob->type == OB_POINTCLOUD);
+
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ PointCloud *pointcloud_eval = (PointCloud *)ob_eval->runtime.data_eval;
+
+ Mesh *me = BKE_mesh_add(bmain, ob->id.name + 2);
+
+ BKE_mesh_from_pointcloud(pointcloud_eval, me);
+
+ BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)me);
+
+ id_us_min(&((PointCloud *)ob->data)->id);
+ ob->data = me;
+ ob->type = OB_MESH;
+
+ BKE_object_free_derived_caches(ob);
+}
+
/* Create a temporary object to be used for nurbs-to-mesh conversion.
*
* This is more complex that it should be because BKE_mesh_from_nurbs_displist() will do more than
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 07a20c417fe..23faaff7734 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -48,6 +48,7 @@
#include "DNA_meta_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -1285,7 +1286,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
case OB_HAIR:
return BKE_hair_add(bmain, name);
case OB_POINTCLOUD:
- return BKE_pointcloud_add(bmain, name);
+ return BKE_pointcloud_add_default(bmain, name);
case OB_VOLUME:
return BKE_volume_add(bmain, name);
case OB_EMPTY:
diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c
index 6ec305a971c..02f318445ac 100644
--- a/source/blender/blenkernel/intern/pointcloud.c
+++ b/source/blender/blenkernel/intern/pointcloud.c
@@ -53,8 +53,8 @@
static void pointcloud_random(PointCloud *pointcloud);
-static const char *POINTCLOUD_ATTR_POSITION = "Position";
-static const char *POINTCLOUD_ATTR_RADIUS = "Radius";
+const char *POINTCLOUD_ATTR_POSITION = "Position";
+const char *POINTCLOUD_ATTR_RADIUS = "Radius";
static void pointcloud_init_data(ID *id)
{
@@ -70,15 +70,7 @@ static void pointcloud_init_data(ID *id)
NULL,
pointcloud->totpoint,
POINTCLOUD_ATTR_POSITION);
- CustomData_add_layer_named(&pointcloud->pdata,
- CD_PROP_FLOAT,
- CD_CALLOC,
- NULL,
- pointcloud->totpoint,
- POINTCLOUD_ATTR_RADIUS);
BKE_pointcloud_update_customdata_pointers(pointcloud);
-
- pointcloud_random(pointcloud);
}
static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
@@ -221,6 +213,23 @@ void *BKE_pointcloud_add(Main *bmain, const char *name)
return pointcloud;
}
+void *BKE_pointcloud_add_default(Main *bmain, const char *name)
+{
+ PointCloud *pointcloud = BKE_libblock_alloc(bmain, ID_PT, name, 0);
+
+ pointcloud_init_data(&pointcloud->id);
+
+ CustomData_add_layer_named(&pointcloud->pdata,
+ CD_PROP_FLOAT,
+ CD_CALLOC,
+ NULL,
+ pointcloud->totpoint,
+ POINTCLOUD_ATTR_RADIUS);
+ pointcloud_random(pointcloud);
+
+ return pointcloud;
+}
+
PointCloud *BKE_pointcloud_copy(Main *bmain, const PointCloud *pointcloud)
{
PointCloud *pointcloud_copy;
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index be6c0658b1f..a1f8061c9f7 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -86,4 +86,9 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_EXPERIMENTAL_FEATURES)
+ add_definitions(-DWITH_PARTICLE_NODES)
+ add_definitions(-DWITH_HAIR_NODES)
+endif()
+
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index fa1d147dc5e..fe68195409f 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -41,6 +41,7 @@
#include "DNA_object_fluidsim_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
@@ -2328,8 +2329,15 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
static const EnumPropertyItem convert_target_items[] = {
{OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
+#ifdef WITH_PARTICLE_NODES
+ {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text/Pointcloud", ""},
+#else
{OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
+#endif
{OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve/Mesh", ""},
+#ifdef WITH_PARTICLE_NODES
+ {OB_POINTCLOUD, "POINTCLOUD", ICON_OUTLINER_OB_POINTCLOUD, "Pointcloud from Mesh", ""},
+#endif
{0, NULL, 0, NULL, NULL},
};
@@ -2467,6 +2475,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
MetaBall *mb;
Mesh *me;
Object *ob_gpencil = NULL;
+ PointCloud *pointcloud;
const short target = RNA_enum_get(op->ptr, "target");
bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
@@ -2636,6 +2645,31 @@ static int object_convert_exec(bContext *C, wmOperator *op)
}
ob_gpencil->actcol = actcol;
}
+ else if (ob->type == OB_MESH && target == OB_POINTCLOUD) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original mesh's usage count */
+ me = newob->data;
+ id_us_min(&me->id);
+
+ /* make a new copy of the mesh */
+ newob->data = BKE_mesh_copy(bmain, me);
+ }
+ else {
+ newob = ob;
+ }
+
+ BKE_mesh_to_pointcloud(bmain, depsgraph, scene, newob);
+
+ if (newob->type == OB_POINTCLOUD) {
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ ED_rigidbody_object_remove(bmain, scene, newob);
+ }
+ }
else if (ob->type == OB_MESH) {
ob->flag |= OB_DONE;
@@ -2821,6 +2855,31 @@ static int object_convert_exec(bContext *C, wmOperator *op)
mballConverted = 1;
}
}
+ else if (ob->type == OB_POINTCLOUD && target == OB_MESH) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original pointclouds's usage count */
+ pointcloud = newob->data;
+ id_us_min(&pointcloud->id);
+
+ /* make a new copy of the pointcloud */
+ newob->data = BKE_pointcloud_copy(bmain, pointcloud);
+ }
+ else {
+ newob = ob;
+ }
+
+ BKE_pointcloud_to_mesh(bmain, depsgraph, scene, newob);
+
+ if (newob->type == OB_MESH) {
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ ED_rigidbody_object_remove(bmain, scene, newob);
+ }
+ }
else {
continue;
}