[Bf-blender-cvs] [9b4912b] alembic: New shrinkwrap modifier for cached hair data.
Lukas Tönne
noreply at git.blender.org
Wed Apr 29 14:16:32 CEST 2015
Commit: 9b4912ba9eac21db6e3c91b567ac2127829342d9
Author: Lukas Tönne
Date: Wed Apr 29 14:12:41 2015 +0200
Branches: alembic
https://developer.blender.org/rB9b4912ba9eac21db6e3c91b567ac2127829342d9
New shrinkwrap modifier for cached hair data.
This is experimental. It might work for simple collision-like features,
by keeping goal positions for hair above the mesh surface. However, the
nature of nearest-point lookup on meshes means that the goal position
can flip to the other side of a mesh rapidly, which would lead to
strong forces and unstable behavior.
This code should be seen as an experiment.
===================================================================
M release/scripts/startup/bl_ui/properties_object.py
M source/blender/blenkernel/BKE_cache_library.h
M source/blender/blenkernel/intern/cache_library.c
M source/blender/makesdna/DNA_cache_library_types.h
M source/blender/makesrna/intern/rna_cache_library.c
===================================================================
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index c3d25f7..64c5c08 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -457,7 +457,7 @@ class OBJECT_PT_cache_library(ObjectButtonsPanel, Panel):
def HAIR_SIMULATION(self, context, layout, cachelib, md):
params = md.parameters
- col = layout.column()
+ col = layout.column(align=True)
col.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
sub = col.column()
if (md.object):
@@ -507,6 +507,21 @@ class OBJECT_PT_cache_library(ObjectButtonsPanel, Panel):
layout.prop(md, "use_double_sided")
+ def SHRINK_WRAP(self, context, layout, cachelib, md):
+ col = layout.column(align=True)
+ col.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
+ sub = col.column()
+ if (md.object):
+ sub.prop_search(md, "hair_system", md.object, "particle_systems")
+ else:
+ sub.enabled = False
+ sub.prop(md, "hair_system")
+
+ layout.prop_search(md, "target", context.blend_data, "objects", icon='OBJECT_DATA')
+
+ layout = layout.column()
+ layout.active = md.hair_system is not None
+
# Simple human-readable size (based on http://stackoverflow.com/a/1094933)
diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index eb334f3..bc48b60 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -49,6 +49,7 @@ struct CacheModifier;
struct ID;
struct CacheProcessData;
struct BVHTreeFromMesh;
+struct Strands;
struct ClothModifierData;
@@ -170,6 +171,9 @@ struct CacheModifier *BKE_cache_modifier_copy(struct CacheLibrary *cachelib, str
void BKE_cache_modifier_foreachIDLink(struct CacheLibrary *cachelib, struct CacheModifier *md, CacheModifier_IDWalkFunc walk, void *userdata);
+bool BKE_cache_modifier_find_object(struct DupliCache *dupcache, struct Object *ob, struct DupliObjectData **r_data);
+bool BKE_cache_modifier_find_strands(struct DupliCache *dupcache, struct Object *ob, int hair_system, struct DupliObjectData **r_data, struct Strands **r_strands);
+
/* ========================================================================= */
typedef struct CacheEffectorInstance {
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index b3530ce..fd21635 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -825,7 +825,53 @@ int BKE_cache_effectors_eval(CacheEffector *effectors, int tot, CacheEffectorPoi
return applied;
}
-/* ------------------------------------------------------------------------- */
+/* ========================================================================= */
+
+bool BKE_cache_modifier_find_object(DupliCache *dupcache, Object *ob, DupliObjectData **r_data)
+{
+ DupliObjectData *dobdata;
+
+ if (!ob)
+ return false;
+ dobdata = BKE_dupli_cache_find_data(dupcache, ob);
+ if (!dobdata)
+ return false;
+
+ if (r_data) *r_data = dobdata;
+ return true;
+}
+
+bool BKE_cache_modifier_find_strands(DupliCache *dupcache, Object *ob, int hair_system, DupliObjectData **r_data, Strands **r_strands)
+{
+ DupliObjectData *dobdata;
+ ParticleSystem *psys;
+ DupliObjectDataStrands *link;
+ Strands *strands;
+
+ if (!ob)
+ return false;
+ dobdata = BKE_dupli_cache_find_data(dupcache, ob);
+ if (!dobdata)
+ return false;
+
+ psys = BLI_findlink(&ob->particlesystem, hair_system);
+ if (!psys || !psys->part->type == PART_HAIR)
+ return false;
+
+ strands = NULL;
+ for (link = dobdata->strands.first; link; link = link->next) {
+ if (link->strands && STREQ(link->name, psys->name)) {
+ strands = link->strands;
+ break;
+ }
+ }
+ if (!strands)
+ return false;
+
+ if (r_data) *r_data = dobdata;
+ if (r_strands) *r_strands = strands;
+ return true;
+}
static void hairsim_params_init(HairSimParams *params)
{
@@ -882,43 +928,11 @@ static void hairsim_foreach_id_link(HairSimCacheModifier *hsmd, CacheLibrary *ca
walk(userdata, cachelib, &hsmd->modifier, (ID **)(&hsmd->object));
}
-static bool hairsim_find_data(HairSimCacheModifier *hsmd, DupliCache *dupcache, Object **r_ob, Strands **r_strands)
-{
- DupliObjectData *dobdata;
- ParticleSystem *psys;
- DupliObjectDataStrands *link;
- Strands *strands;
-
- if (!hsmd->object)
- return false;
- dobdata = BKE_dupli_cache_find_data(dupcache, hsmd->object);
- if (!dobdata)
- return false;
-
- psys = BLI_findlink(&hsmd->object->particlesystem, hsmd->hair_system);
- if (!psys || !psys->part->type == PART_HAIR)
- return false;
-
- strands = NULL;
- for (link = dobdata->strands.first; link; link = link->next) {
- if (link->strands && STREQ(link->name, psys->name)) {
- strands = link->strands;
- break;
- }
- }
- if (!strands)
- return false;
-
- *r_ob = hsmd->object;
- *r_strands = strands;
- return true;
-}
-
static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx, CacheProcessData *data, int frame, int frame_prev, eCacheLibrary_EvalMode UNUSED(eval_mode))
{
#define MAX_CACHE_EFFECTORS 64
- Object *ob;
+ Object *ob = hsmd->object;
Strands *strands;
float mat[4][4];
ListBase *effectors;
@@ -934,7 +948,7 @@ static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx
if (frame <= frame_prev)
return;
- if (!hairsim_find_data(hsmd, data->dupcache, &ob, &strands))
+ if (!BKE_cache_modifier_find_strands(data->dupcache, ob, hsmd->hair_system, NULL, &strands))
return;
if (hsmd->sim_params.flag & eHairSimParams_Flag_UseGoalStiffnessCurve)
@@ -971,6 +985,8 @@ CacheModifierTypeInfo cacheModifierType_HairSimulation = {
/* free */ (CacheModifier_FreeFunc)hairsim_free,
};
+/* ------------------------------------------------------------------------- */
+
static void forcefield_init(ForceFieldCacheModifier *ffmd)
{
ffmd->object = NULL;
@@ -1006,10 +1022,202 @@ CacheModifierTypeInfo cacheModifierType_ForceField = {
/* free */ (CacheModifier_FreeFunc)forcefield_free,
};
+/* ------------------------------------------------------------------------- */
+
+static void shrinkwrap_init(ShrinkWrapCacheModifier *smd)
+{
+ smd->object = NULL;
+ smd->hair_system = -1;
+}
+
+static void shrinkwrap_copy(ShrinkWrapCacheModifier *UNUSED(smd), ShrinkWrapCacheModifier *UNUSED(tsmd))
+{
+}
+
+static void shrinkwrap_free(ShrinkWrapCacheModifier *UNUSED(smd))
+{
+}
+
+static void shrinkwrap_foreach_id_link(ShrinkWrapCacheModifier *smd, CacheLibrary *cachelib, CacheModifier_IDWalkFunc walk, void *userdata)
+{
+ walk(userdata, cachelib, &smd->modifier, (ID **)(&smd->object));
+ walk(userdata, cachelib, &smd->modifier, (ID **)(&smd->target));
+}
+
+typedef struct ShrinkWrapCacheData {
+ DerivedMesh *dm;
+ BVHTreeFromMesh treedata;
+
+ ListBase instances;
+} ShrinkWrapCacheData;
+
+typedef struct ShrinkWrapCacheInstance {
+ struct ShrinkWrapCacheInstance *next, *prev;
+
+ float mat[4][4];
+ float imat[4][4];
+} ShrinkWrapCacheInstance;
+
+static void shrinkwrap_data_get_bvhtree(ShrinkWrapCacheData *data, DerivedMesh *dm, bool create_bvhtree)
+{
+ data->dm = CDDM_copy(dm);
+ if (!data->dm)
+ return;
+
+ DM_ensure_tessface(data->dm);
+ CDDM_calc_normals(data->dm);
+
+ if (create_bvhtree) {
+ bvhtree_from_mesh_faces(&data->treedata, data->dm, 0.0, 2, 6);
+ }
+}
+
+static void shrinkwrap_data_get_instances(ShrinkWrapCacheData *data, Object *ob, float obmat[4][4], ListBase *duplilist)
+{
+ DupliObject *dob;
+
+ for (dob = duplilist->first; dob; dob = dob->next) {
+ ShrinkWrapCacheInstance *inst;
+
+ if (dob->ob != ob)
+ continue;
+
+ inst = MEM_callocN(sizeof(ShrinkWrapCacheInstance), "shrink wrap instance");
+ mul_m4_m4m4(inst->mat, obmat, dob->mat);
+ invert_m4_m4(inst->imat, inst->mat);
+
+ BLI_addtail(&data->instances, inst);
+ }
+}
+
+static void shrinkwrap_data_free(ShrinkWrapCacheData *data)
+{
+ BLI_freelistN(&data->instances);
+
+ free_bvhtree_from_mesh(&data->treedata);
+
+ if (data->dm) {
+ data->dm->release(data->dm);
+ }
+}
+
+static void shrinkwrap_apply_vertex(ShrinkWrapCacheModifier *smd, ShrinkWrapCacheData *data, ShrinkWrapCacheInstance *inst, StrandsVertex *vertex, StrandsMotionState *UNUSED(state))
+{
+// const float *point = state->co;
+// float *npoint = state->co;
+ const float *point = vertex->co;
+ float *npoint = vertex->co;
+
+ BVHTreeNearest nearest = {0, };
+ float co[3];
+
+ if (!data->treedata.tree)
+ return;
+
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+
+ /* lookup in target space */
+ mul_v3_m4v3(co, inst->imat, point);
+
+ BLI_bvhtree_find_nearest(data->treedata.tree, co, &nearest, data->treedata.nearest_callback, &data->treedata);
+ if (nearest.index < 0)
+ return;
+
+ /* convert back to world space */
+ mul_m4_v3(inst->mat, nearest.co);
+ mul_mat3_m4_v3(inst->mat, nearest.no);
+
+ {
+ float vec[3];
+
+ sub_v3_v3v3(vec, point, nearest.co);
+
+ /* project along the distance vector */
+ if (dot_v3v3(vec, nearest.no) < 0.0f) {
+ sub_v3_v3v3(npoint, point, vec);
+ }
+ }
+}
+
+static void shrinkwrap_apply(ShrinkWrapCacheModifier *smd, ShrinkWrapCacheData *data, Strands *strands)
+{
+ StrandIterator it_strand;
+ for (BKE_strand_iter_init(&it_strand, strands); BKE_strand_iter_valid(&it_strand); BKE_strand_iter_next(&it_strand)) {
+ StrandVertexIterator it_vert;
+ for (BKE_strand_vertex_iter_init(&it_vert, &it_strand); BKE_strand_vertex_iter_valid(&it_vert); BKE_strand_vertex_iter_next(&it_vert)) {
+ ShrinkWrapCacheInstance *inst;
+
+ /* XXX this is not great, the result depends on order of instances in the duplilist ...
+ * but good enough for single instance use case.
+ */
+ for (inst = data->instances.first; inst; inst = inst->next) {
+ shrinkwrap_apply_vertex(smd, data, inst, it_vert.vertex, it_vert.state);
+ }
+ }
+ }
+}
+
+static void shrinkwrap_process(ShrinkWrapCacheModifier *s
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list