[Bf-blender-cvs] [a2787c1] strand_nodes: Simple contact detection method for hair editing, using the typical BVH closest point method.
Lukas Tönne
noreply at git.blender.org
Sun Aug 7 10:39:42 CEST 2016
Commit: a2787c1f747ea066a65b41344f90fae22f2b5c4a
Author: Lukas Tönne
Date: Fri Jul 29 12:12:03 2016 +0200
Branches: strand_nodes
https://developer.blender.org/rBa2787c1f747ea066a65b41344f90fae22f2b5c4a
Simple contact detection method for hair editing, using the typical BVH closest point method.
This method is just a placeholder, in the future it would be worthwhile to use Bullet collision
detection with ghost objects for this.
Also the code should eventually be abstracted a bit to make it agnostic to mesh formats, so it
can be used for BMesh as well as DNA strand data or physics simulation.
===================================================================
M source/blender/blenkernel/BKE_editstrands.h
M source/blender/blenkernel/intern/editstrands.c
M source/blender/bmesh/intern/bmesh_strands_conv.c
M source/blender/bmesh/intern/bmesh_strands_conv.h
M source/blender/editors/hair/hair_edit.c
M source/blender/editors/transform/transform_conversions.c
M source/blender/physics/BPH_strands.h
M source/blender/physics/intern/strands.cpp
===================================================================
diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h
index 2fc0728..b40819d 100644
--- a/source/blender/blenkernel/BKE_editstrands.h
+++ b/source/blender/blenkernel/BKE_editstrands.h
@@ -42,10 +42,12 @@
#include "bmesh.h"
struct BMesh;
+struct CollisionContactCache;
struct DerivedMesh;
struct GPUStrandsConverter;
struct Mesh;
struct Object;
+struct Scene;
struct Strands;
struct StrandFiber;
@@ -87,7 +89,10 @@ typedef float (*BMEditStrandsLocations)[3];
BMEditStrandsLocations BKE_editstrands_get_locations(struct BMEditStrands *edit);
void BKE_editstrands_free_locations(BMEditStrandsLocations locs);
-void BKE_editstrands_solve_constraints(struct Object *ob, struct BMEditStrands *es, BMEditStrandsLocations orig);
+void BKE_editstrands_get_collision_contacts(struct Scene *scene, struct Object *ob, struct BMEditStrands *edit,
+ struct CollisionContactCache *cache);
+
+void BKE_editstrands_solve_constraints(struct Scene *scene, struct Object *ob, struct BMEditStrands *es, BMEditStrandsLocations orig);
void BKE_editstrands_ensure(struct BMEditStrands *es);
/* === particle conversion === */
diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index a8e180c..c59604b 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -41,8 +41,10 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
#include "BKE_bvhutils.h"
+#include "BKE_collision.h"
#include "BKE_customdata.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
@@ -221,11 +223,82 @@ void BKE_editstrands_free_locations(BMEditStrandsLocations locs)
MEM_freeN(locs);
}
-void BKE_editstrands_solve_constraints(Object *ob, BMEditStrands *es, BMEditStrandsLocations orig)
+static void get_dm_collision_contacts(BMEditStrands *edit, float obmat[4][4],
+ DerivedMesh *dm, float dm_obmat[4][4], int collider_index,
+ CollisionContactCache *cache)
+{
+ BMesh *bm = edit->base.bm;
+ BVHTreeFromMesh treedata = {NULL};
+
+ bvhtree_from_mesh_looptri(&treedata, dm, 0.0, 2, 6);
+ if (!treedata.tree)
+ return;
+
+ /* Vertices must be transformed to DM space for lookups.
+ * Results are then transformed to world space.
+ */
+ float dm_imat[4][4];
+ invert_m4_m4(dm_imat, dm_obmat);
+ float vertmat[4][4];
+ mul_m4_m4m4(vertmat, dm_imat, obmat);
+
+ BMIter iter;
+ BMVert *vert;
+ int vert_index;
+ BM_ITER_MESH_INDEX(vert, &iter, bm, BM_VERTS_OF_MESH, vert_index) {
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+
+ float co[3];
+ mul_v3_m4v3(co, vertmat, vert->co);
+
+ float radius = BM_elem_float_data_named_get(&bm->vdata, vert, CD_PROP_FLT, CD_HAIR_RADIUS);
+
+ BLI_bvhtree_find_nearest(treedata.tree, co, &nearest, treedata.nearest_callback, &treedata);
+
+ if (nearest.index != -1) {
+ CollisionContactPoint *pt = BKE_collision_cache_add(cache, 0, collider_index,
+ vert_index, nearest.index);
+ mul_v3_m4v3(pt->point_world_a, dm_imat, co);
+ mul_v3_m4v3(pt->point_world_b, dm_imat, nearest.co);
+ mul_v3_mat3_m4v3(pt->normal_world_b, dm_imat, nearest.no);
+
+ float vec[3];
+ sub_v3_v3v3(vec, co, nearest.co);
+ mul_mat3_m4_v3(dm_imat, vec);
+ float dist = len_v3(vec);
+ if (dot_v3v3(vec, nearest.no) >= 0.0f)
+ pt->distance = dist - radius;
+ else
+ pt->distance = -dist - radius;
+ }
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+}
+
+void BKE_editstrands_get_collision_contacts(Scene *scene, Object *ob, BMEditStrands *edit,
+ CollisionContactCache *cache)
+{
+ HairEditSettings *settings = &scene->toolsettings->hair_edit;
+
+ if (settings->flag & HAIR_EDIT_DEFLECT_SCALP) {
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ get_dm_collision_contacts(edit, ob->obmat, dm, ob->obmat, 0, cache);
+ }
+
+ if (settings->deflect_group) {
+ /* TODO add collision group contacts */
+ /* ... */
+ }
+}
+
+void BKE_editstrands_solve_constraints(Scene *scene, Object *ob, BMEditStrands *es, BMEditStrandsLocations orig)
{
BKE_editstrands_ensure(es);
- BPH_strands_solve_constraints(ob, es, orig);
+ BPH_strands_solve_constraints(scene, ob, es, orig);
}
static void editstrands_calc_segment_lengths(BMesh *bm)
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.c b/source/blender/bmesh/intern/bmesh_strands_conv.c
index f15455d..cce8945 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.c
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.c
@@ -51,6 +51,7 @@ const char *CD_HAIR_SEGMENT_LENGTH = "HAIR_SEGMENT_LENGTH";
const char *CD_HAIR_MASS = "HAIR_MASS";
const char *CD_HAIR_WEIGHT = "HAIR_WEIGHT";
const char *CD_HAIR_ROOT_LOCATION = "HAIR_ROOT_LOCATION";
+const char *CD_HAIR_RADIUS = "HAIR_RADIUS";
/* ------------------------------------------------------------------------- */
@@ -90,6 +91,9 @@ void BM_strands_cd_flag_apply(BMesh *bm, const char UNUSED(cd_flag))
if (CustomData_get_named_layer_index(&bm->vdata, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH) < 0) {
BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
}
+ if (CustomData_get_named_layer_index(&bm->vdata, CD_PROP_FLT, CD_HAIR_RADIUS) < 0) {
+ BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLT, CD_HAIR_RADIUS);
+ }
}
char BM_strands_cd_flag_from_bmesh(BMesh *UNUSED(bm))
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.h b/source/blender/bmesh/intern/bmesh_strands_conv.h
index 498af26..5dea2a6 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.h
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.h
@@ -44,6 +44,7 @@ extern const char *CD_HAIR_SEGMENT_LENGTH;
extern const char *CD_HAIR_MASS;
extern const char *CD_HAIR_WEIGHT;
extern const char *CD_HAIR_ROOT_LOCATION;
+extern const char *CD_HAIR_RADIUS;
void BM_strands_cd_validate(struct BMesh *bm);
void BM_strands_cd_flag_ensure(struct BMesh *bm, const char cd_flag);
diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c
index 7c41354..be70a4e 100644
--- a/source/blender/editors/hair/hair_edit.c
+++ b/source/blender/editors/hair/hair_edit.c
@@ -346,7 +346,7 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
bool step_updated = hair_brush_step(&tool_data);
if (step_updated)
- BKE_editstrands_solve_constraints(ob, edit, NULL);
+ BKE_editstrands_solve_constraints(scene, ob, edit, NULL);
updated |= step_updated;
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 463b3f9..ccd0038 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2166,7 +2166,7 @@ void flushTransStrands(TransInfo *t)
BMEditStrands *edit = BKE_editstrands_from_object(ob);
BMEditStrandsLocations origlocs = t->custom.type.data;
- BKE_editstrands_solve_constraints(ob, edit, origlocs);
+ BKE_editstrands_solve_constraints(scene, ob, edit, origlocs);
}
/* ********************* mesh ****************** */
diff --git a/source/blender/physics/BPH_strands.h b/source/blender/physics/BPH_strands.h
index 068c47f..bc829fd 100644
--- a/source/blender/physics/BPH_strands.h
+++ b/source/blender/physics/BPH_strands.h
@@ -32,10 +32,11 @@
extern "C" {
#endif
-struct Object;
struct BMEditStrands;
+struct Object;
+struct Scene;
-void BPH_strands_solve_constraints(struct Object *ob, struct BMEditStrands *es, float (*orig)[3]);
+void BPH_strands_solve_constraints(struct Scene *scene, struct Object *ob, struct BMEditStrands *es, float (*orig)[3]);
#ifdef __cplusplus
}
diff --git a/source/blender/physics/intern/strands.cpp b/source/blender/physics/intern/strands.cpp
index 2049d6d..1d7c2eb 100644
--- a/source/blender/physics/intern/strands.cpp
+++ b/source/blender/physics/intern/strands.cpp
@@ -36,8 +36,10 @@ extern "C" {
#include "DNA_customdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_bvhutils.h"
+#include "BKE_collision.h"
#include "BKE_customdata.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
@@ -410,8 +412,10 @@ static void strands_solve_inverse_kinematics(Object *ob, BMEditStrands *edit, fl
}
}
-void BPH_strands_solve_constraints(Object *ob, BMEditStrands *edit, float (*orig)[3])
+void BPH_strands_solve_constraints(Scene *scene, Object *ob, BMEditStrands *edit, float (*orig)[3])
{
+ HairEditSettings *settings = &scene->toolsettings->hair_edit;
+
strands_apply_root_locations(edit);
if (true) {
@@ -421,4 +425,14 @@ void BPH_strands_solve_constraints(Object *ob, BMEditStrands *edit, float (*orig
if (orig)
strands_solve_inverse_kinematics(ob, edit, orig);
}
+
+
+ /* Deflection */
+ if (settings->flag & HAIR_EDIT_USE_DEFLECT) {
+ CollisionContactCache *contacts = BKE_collision_cache_create();
+
+ BKE_editstrands_get_collision_contacts(scene, ob, edit, contacts);
+
+ BKE_collision_cache_free(contacts);
+ }
}
More information about the Bf-blender-cvs
mailing list