[Bf-blender-cvs] [2a41da1d915] fracture_modifier: experimental bind of animated vertices (other object) to shards
Martin Felke
noreply at git.blender.org
Fri Jan 12 13:15:49 CET 2018
Commit: 2a41da1d915215ea5e0a080caf9813872bf57e8d
Author: Martin Felke
Date: Fri Jan 12 13:15:22 2018 +0100
Branches: fracture_modifier
https://developer.blender.org/rB2a41da1d915215ea5e0a080caf9813872bf57e8d
experimental bind of animated vertices (other object) to shards
this transfers vertex motion during simulation and allows some kind of "deformation" of the fractured mesh, without
refracturing it
===================================================================
M release/scripts/startup/bl_operators/presets.py
M release/scripts/startup/bl_ui/properties_physics_fracture.py
M source/blender/blenkernel/BKE_fracture.h
M source/blender/blenkernel/intern/fracture.c
M source/blender/blenkernel/intern/pointcache.c
M source/blender/blenkernel/intern/rigidbody.c
M source/blender/blenloader/intern/readfile.c
M source/blender/blenloader/intern/writefile.c
M source/blender/editors/object/object_intern.h
M source/blender/editors/object/object_modifier.c
M source/blender/editors/object/object_ops.c
M source/blender/makesdna/DNA_modifier_types.h
M source/blender/makesrna/intern/rna_fracture.c
M source/blender/modifiers/intern/MOD_fracture.c
M source/blender/modifiers/intern/MOD_remesh.c
===================================================================
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 0ac0c2fa201..ecfdfe8fbb3 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -706,6 +706,8 @@ class AddPresetFracture(AddPresetBase, Operator):
"fracture.min_acceleration",
"fracture.max_acceleration",
"fracture.acceleration_fade",
+ "fracture.use_animated_mesh",
+ "fracture.animated_mesh_input",
]
preset_subdir = "fracture"
diff --git a/release/scripts/startup/bl_ui/properties_physics_fracture.py b/release/scripts/startup/bl_ui/properties_physics_fracture.py
index e6cf1d43926..d0ffd3e8d73 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fracture.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fracture.py
@@ -131,6 +131,12 @@ class PHYSICS_PT_fracture(PhysicButtonsPanel, Panel):
row.prop(md, "use_smooth")
row = layout.row()
row.prop(md, "auto_execute")
+ row.prop(md, "use_animated_mesh")
+ row = layout.row()
+ row.prop(md, "animated_mesh_input")
+ row = layout.row()
+ row.context_pointer_set("modifier", md)
+ row.operator("object.fracture_anim_bind", text="Bind", icon="UV_VERTEXSEL")
row = layout.row(align=True)
row.prop(md, "splinter_axis")
layout.prop(md, "splinter_length")
diff --git a/source/blender/blenkernel/BKE_fracture.h b/source/blender/blenkernel/BKE_fracture.h
index f610dc6e469..de9024a5c19 100644
--- a/source/blender/blenkernel/BKE_fracture.h
+++ b/source/blender/blenkernel/BKE_fracture.h
@@ -129,5 +129,6 @@ void BKE_bm_mesh_hflag_flush_vert(struct BMesh *bm, const char hflag);
void BKE_meshisland_constraint_create(struct FractureModifierData* fmd, struct MeshIsland *mi1, struct MeshIsland *mi2, int con_type, float thresh);
void BKE_update_acceleration_map(struct FractureModifierData *fmd, struct MeshIsland* mi, struct Object* ob, int ctime, float acc, struct RigidBodyWorld *rbw);
void BKE_update_velocity_layer(struct FractureModifierData *fmd, struct MeshIsland *mi);
+void BKE_read_animated_loc_rot(struct FractureModifierData *fmd, Object *ob, bool do_bind);
#endif /* BKE_FRACTURE_H */
diff --git a/source/blender/blenkernel/intern/fracture.c b/source/blender/blenkernel/intern/fracture.c
index 1d70868edd6..bbd72fffe8a 100644
--- a/source/blender/blenkernel/intern/fracture.c
+++ b/source/blender/blenkernel/intern/fracture.c
@@ -3789,3 +3789,266 @@ void BKE_update_velocity_layer(FractureModifierData *fmd, MeshIsland *mi)
velZ[mi->vertex_indices[i]] = rbo->lin_vel[2] + rbo->ang_vel[2];
}
}
+
+/* gah, it could be that simple, if each mod handled its stuff itself */
+static DerivedMesh *eval_mod_stack_simple(Object *ob)
+{
+ DerivedMesh *dm = NULL;
+ ModifierData *md;
+
+ if (ob->type != OB_MESH)
+ return NULL;
+
+ if (ob->data == NULL)
+ return NULL;
+
+ dm = CDDM_from_mesh(ob->data);
+
+ for (md = ob->modifiers.first; md; md = md->next)
+ {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (mti->deformVerts && (md->mode & (eModifierMode_Realtime | eModifierMode_Render)))
+ {
+ float (*vertexCos)[3];
+ int totvert = dm->getNumVerts(dm);
+
+ vertexCos = MEM_callocN(sizeof(float) * 3 * totvert, "Vertex Cos");
+ dm->getVertCos(dm, vertexCos);
+ mti->deformVerts(md, ob, dm, vertexCos, totvert, 0);
+ CDDM_apply_vert_coords(dm, vertexCos);
+ MEM_freeN(vertexCos);
+ CDDM_calc_normals(dm);
+ }
+
+ if (mti->applyModifier && (md->mode & (eModifierMode_Realtime | eModifierMode_Render)))
+ {
+ DerivedMesh *ndm;
+
+ ndm = mti->applyModifier(md, ob, dm, 0);
+ if (ndm != dm)
+ {
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+ dm = ndm;
+ CDDM_calc_normals(dm);
+ }
+ }
+
+ return dm;
+}
+
+void BKE_read_animated_loc_rot(FractureModifierData *fmd, Object *ob, bool do_bind)
+{
+ //to be called after rigidbodies have been actually created... from MOD_fracture.c
+ //rotation is optional, remesher + particlesystem can provide it
+ float *quatX, *quatY, *quatZ, *quatW;
+ MVert *mvert = NULL;
+ MeshIsland *mi, **mi_array;
+ DerivedMesh *dm = NULL;
+ int totvert, count = 0, i = 0;
+ KDTree *tree = NULL;
+ float obquat[4];
+ bool *used;
+
+ if (!fmd->anim_mesh_ob)
+ return;
+
+ if (fmd->anim_mesh_ob == ob)
+ return;
+
+ dm = eval_mod_stack_simple(fmd->anim_mesh_ob);
+
+ if (!dm)
+ return;
+
+ totvert = dm->getNumVerts(dm);
+
+ if (totvert == 0) {
+ dm->release(dm);
+ return;
+ }
+
+ count = BLI_listbase_count(&fmd->meshIslands);
+ mat4_to_quat(obquat, ob->obmat);
+
+ if (do_bind) {
+
+ tree = BLI_kdtree_new(count);
+ fmd->anim_bind_len = MAX2(totvert, count);
+ if (fmd->anim_bind) {
+ MEM_freeN(fmd->anim_bind);
+ }
+
+ //TODO, possibly a weak solution, but do we really want to store the length too ?
+ fmd->anim_bind = MEM_mallocN(sizeof(AnimBind) * fmd->anim_bind_len, "anim_bind");
+ for (i = 0; i < fmd->anim_bind_len; i++)
+ {
+ fmd->anim_bind[i].mi = -1;
+ fmd->anim_bind[i].v = -1;
+ zero_v3(fmd->anim_bind[i].offset);
+ }
+ }
+
+
+ mi_array = MEM_mallocN(sizeof(MeshIsland*) * count, "mi_array");
+
+ i = 0;
+ for (mi = fmd->meshIslands.first; mi; mi = mi->next)
+ {
+ float co[3];
+ copy_v3_v3(co, mi->rigidbody->pos);
+ if (do_bind)
+ BLI_kdtree_insert(tree, i, co);
+ mi_array[i] = mi;
+ i++;
+ }
+
+ if (do_bind)
+ BLI_kdtree_balance(tree);
+
+ mvert = dm->getVertArray(dm);
+
+ quatX = CustomData_get_layer_named(&dm->vertData, CD_PROP_FLT, "quatX");
+ quatY = CustomData_get_layer_named(&dm->vertData, CD_PROP_FLT, "quatY");
+ quatZ = CustomData_get_layer_named(&dm->vertData, CD_PROP_FLT, "quatZ");
+ quatW = CustomData_get_layer_named(&dm->vertData, CD_PROP_FLT, "quatW");
+
+ //check vertexcount and islandcount, TODO for splitshards... there it might differ, ignore then for now
+ //later do interpolation ? propagate to islands somehow then, not yet now...
+ //also maybe skip for dynamic for now, since this is totally different
+
+ //bind loop, bind the verts to the shards
+ if (do_bind)
+ {
+ //counter, verts per island or vice versa
+ int c;
+
+ //bindcounter
+ int b = 0;
+ used = MEM_callocN(sizeof(bool) * count, "used");
+
+ //less shards than verts, can maximal map 1 : 1
+ c = (int)ceilf((float)count / (float)totvert)+1;
+
+ for (i = 0; i < totvert; i++)
+ {
+ KDTreeNearest *n;
+ float co[3];
+ int r, j;
+
+ n = MEM_mallocN(sizeof(KDTreeNearest) * c, "nearest");
+ copy_v3_v3(co, mvert[i].co);
+ r = BLI_kdtree_find_nearest_n(tree, co, n, c);
+ for (j = 0; j < r; j++)
+ {
+ float diff[3];
+ if (b == fmd->anim_bind_len)
+ break;
+
+ if (used[n[j].index])
+ continue;
+
+ fmd->anim_bind[b].v = i;
+ fmd->anim_bind[b].mi = n[j].index;
+ //fmd->anim_bind[b].dist = n[j].dist;
+ sub_v3_v3v3(diff, co, n[j].co);
+ //copy_v3_v3(fmd->anim_bind[b].orco, co);
+ copy_v3_v3(fmd->anim_bind[b].offset, diff);
+ used[n[j].index] = true;
+ b++;
+ }
+
+ if (n)
+ MEM_freeN(n);
+
+ if (b == fmd->anim_bind_len)
+ break;
+ }
+
+ if (tree)
+ BLI_kdtree_free(tree);
+
+ if (used)
+ MEM_freeN(used);
+ }
+
+
+ {
+ int j = 0;
+ //map 1 vert to several shards, maxium 1 : 1
+ for (i = 0; i < fmd->anim_bind_len; i++)
+ {
+ float co[3]; // orco[3], diff[3];
+ int index = -1;
+
+ if (!fmd->anim_bind)
+ continue;
+
+ index = fmd->anim_bind[i].mi;
+
+ if (index == -1)
+ continue;
+
+ mi = mi_array[index];
+
+ //only let kinematic rbs do this, active ones are being taken care of by bullet
+ if (mi && mi->rigidbody && mi->rigidbody->flag & RBO_FLAG_KINEMATIC)
+ {
+ //the 4 rot layers *should* be aligned, caller needs to ensure !
+ bool quats = quatX && quatY && quatZ && quatW;
+ float quat[4] = { 1, 0, 0, 0};
+
+
+ if (fmd->anim_bind[i].v >= totvert) {
+ continue;
+ }
+
+ copy_v3_v3(co, mvert[fmd->anim_bind[i].v].co);
+ //sub_v3_v3v3(orco, co, fmd->anim_bind[i].orco);
+ //sub_v3_v3v3(diff, co, mi->centroid);
+
+ /*if (!(compare_v3v3(diff, orco, 0.1f)))
+ { //did the index shuffle ? might be if there is a sudden increase in distance
+ mi->rigidbody->flag &= ~RBO_FLAG_KINEMATIC;
+ mi->rigidbody->flag |= RBO_FLAG_NEEDS_VALIDATE;
+ continue;
+ }*/
+
+ sub_v3_v3(co, fmd->anim_bind[i].offset);
+ mul_m4_v3(ob->obmat, co);
+ copy_v3_v3(mi->rigidbody->pos, co);
+
+ if (quats)
+ {
+ quat[0] = quatX[fmd->anim_bind[i].v];
+ quat[1] = quatY[fmd->anim_bind[i].v];
+ quat[2] = quatZ[fmd->anim_bind[i].v];
+ quat[3] = quatW[fmd->anim_bind[i].v];
+
+ copy_qt_qt(mi->rigidbody->orn, quat);
+ }
+ else {
+ float no[3], vec[3] = {0, 0, 1}, quat[4];
+ normal_short_to_float_v3(no, mvert[fmd->anim_bind[i].v].no);
+ rotation_between_vecs_to_quat(quat, vec, no);
+ mul_qt_qtqt(quat, obquat, quat);
+ copy_qt_qt(mi->rigidbody->orn, quat);
+ }
+
+ mi->rigidbody->flag |= RBO_FLAG_NEEDS_VALIDATE;
+ //mi->rigidbody->flag |= RBO_FLAG_NEEDS_RESHAPE;
+ if (mi->rigidbody->physics_object)
+ {
+ RB_body_set_loc_rot(mi->rigidbody->physics_object, mi->rigidbody->pos, mi->rigidbody->orn);
+ }
+ }
+ }
+ }
+
+ if (dm)
+ dm->release(dm);
+
+
+ MEM_freeN(mi_array);
+}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index c34d1fe0cc0..d2ed49d1d49 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1355,13 +1355,17 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int cfra
}
#ifdef WITH_BULLET
- RB_body_get_position(rbo->physics_object, rbo->pos);
- RB_body_get_orientation(rbo->physics_object, rbo->orn);
+ if (!(fmd && fmd->use_animated_mesh && fmd->anim_mesh_ob && (rbo->flag & RBO_FLAG_KINEMATIC)))
+ {
+ RB_body_get_position(rbo->physics_object, rbo->pos);
+ RB_body_get_orientation(rbo->physics_object, rbo->orn);
+ }
RB_body_get_linear_velocity(rbo->physics_object, rbo->lin_vel);
RB_body_get_angular_velocity(rbo->physics_object, rbo->ang_vel);
- if (fmd)
+ //this is only fo
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list