2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2013 Blender Foundation
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Joshua Leung, Sergej Reich
25 * ***** END GPL LICENSE BLOCK *****
30 * \brief Blender-side interface and methods for dealing with Rigid Body simulations
40 #include "MEM_guardedalloc.h"
42 #include "BLI_blenlib.h"
49 #include "DNA_group_types.h"
50 #include "DNA_meshdata_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_object_force.h"
53 #include "DNA_rigidbody_types.h"
54 #include "DNA_scene_types.h"
56 #include "BKE_cdderivedmesh.h"
57 #include "BKE_effect.h"
58 #include "BKE_global.h"
59 #include "BKE_library.h"
61 #include "BKE_object.h"
62 #include "BKE_pointcache.h"
63 #include "BKE_rigidbody.h"
65 #include "RNA_access.h"
69 /* ************************************** */
70 /* Memory Management */
72 /* Freeing Methods --------------------- */
74 /* Free rigidbody world */
75 void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
81 if (rbw->physics_world) {
82 /* free physics references, we assume that all physics objects in will have been added to the world */
84 if (rbw->constraints) {
85 for (go = rbw->constraints->gobject.first; go; go = go->next) {
86 if (go->ob && go->ob->rigidbody_constraint) {
87 RigidBodyCon *rbc = go->ob->rigidbody_constraint;
89 if (rbc->physics_constraint)
90 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
95 for (go = rbw->group->gobject.first; go; go = go->next) {
96 if (go->ob && go->ob->rigidbody_object) {
97 RigidBodyOb *rbo = go->ob->rigidbody_object;
99 if (rbo->physics_object)
100 RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
104 /* free dynamics world */
105 RB_dworld_delete(rbw->physics_world);
111 BKE_ptcache_free_list(&(rbw->ptcaches));
112 rbw->pointcache = NULL;
114 /* free effector weights */
115 if (rbw->effector_weights)
116 MEM_freeN(rbw->effector_weights);
118 /* free rigidbody world itself */
122 /* Free RigidBody settings and sim instances */
123 void BKE_rigidbody_free_object(Object *ob)
125 RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
131 /* free physics references */
132 if (rbo->physics_object) {
133 RB_body_delete(rbo->physics_object);
134 rbo->physics_object = NULL;
137 if (rbo->physics_shape) {
138 RB_shape_delete(rbo->physics_shape);
139 rbo->physics_shape = NULL;
142 /* free data itself */
144 ob->rigidbody_object = NULL;
147 /* Free RigidBody constraint and sim instance */
148 void BKE_rigidbody_free_constraint(Object *ob)
150 RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
156 /* free physics reference */
157 if (rbc->physics_constraint) {
158 RB_constraint_delete(rbc->physics_constraint);
159 rbc->physics_constraint = NULL;
162 /* free data itself */
164 ob->rigidbody_constraint = NULL;
167 /* Copying Methods --------------------- */
169 /* These just copy the data, clearing out references to physics objects.
170 * Anything that uses them MUST verify that the copied object will
171 * be added to relevant groups later...
174 RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
176 RigidBodyOb *rboN = NULL;
178 if (ob->rigidbody_object) {
179 /* just duplicate the whole struct first (to catch all the settings) */
180 rboN = MEM_dupallocN(ob->rigidbody_object);
182 /* tag object as needing to be verified */
183 rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
185 /* clear out all the fields which need to be revalidated later */
186 rboN->physics_object = NULL;
187 rboN->physics_shape = NULL;
190 /* return new copy of settings */
194 RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
196 RigidBodyCon *rbcN = NULL;
198 if (ob->rigidbody_constraint) {
199 /* just duplicate the whole struct first (to catch all the settings) */
200 rbcN = MEM_dupallocN(ob->rigidbody_constraint);
202 /* tag object as needing to be verified */
203 rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE;
205 /* clear out all the fields which need to be revalidated later */
206 rbcN->physics_constraint = NULL;
209 /* return new copy of settings */
213 /* preserve relationships between constraints and rigid bodies after duplication */
214 void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
220 /* ************************************** */
221 /* Setup Utilities - Validate Sim Instances */
223 /* get the appropriate DerivedMesh based on rigid body mesh source */
224 static DerivedMesh *rigidbody_get_mesh(Object *ob)
226 if (ob->rigidbody_object->mesh_source == RBO_MESH_DEFORM) {
227 return ob->derivedDeform;
229 else if (ob->rigidbody_object->mesh_source == RBO_MESH_FINAL) {
230 return ob->derivedFinal;
233 return CDDM_from_mesh(ob->data);
237 /* create collision shape of mesh - convex hull */
238 static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed)
240 rbCollisionShape *shape = NULL;
241 DerivedMesh *dm = NULL;
245 if (ob->type == OB_MESH && ob->data) {
246 dm = rigidbody_get_mesh(ob);
247 mvert = (dm) ? dm->getVertArray(dm) : NULL;
248 totvert = (dm) ? dm->getNumVerts(dm) : 0;
251 printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n");
255 shape = RB_shape_new_convex_hull((float *)mvert, sizeof(MVert), totvert, margin, can_embed);
258 printf("ERROR: no vertices to define Convex Hull collision shape with\n");
261 if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE)
267 /* create collision shape of mesh - triangulated mesh
268 * returns NULL if creation fails.
270 static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
272 rbCollisionShape *shape = NULL;
274 if (ob->type == OB_MESH) {
275 DerivedMesh *dm = NULL;
281 int triangle_index = 0;
283 dm = rigidbody_get_mesh(ob);
285 /* ensure mesh validity, then grab data */
289 DM_ensure_tessface(dm);
291 mvert = dm->getVertArray(dm);
292 totvert = dm->getNumVerts(dm);
293 mface = dm->getTessFaceArray(dm);
294 totface = dm->getNumTessFaces(dm);
296 /* sanity checking - potential case when no data will be present */
297 if ((totvert == 0) || (totface == 0)) {
298 printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
304 /* count triangles */
305 for (i = 0; i < totface; i++) {
306 (mface[i].v4) ? (tottris += 2) : (tottris += 1);
309 /* init mesh data for collision shape */
310 mdata = RB_trimesh_data_new(tottris, totvert);
312 RB_trimesh_add_vertices(mdata, (float *)mvert, totvert, sizeof(MVert));
314 /* loop over all faces, adding them as triangles to the collision shape
315 * (so for some faces, more than triangle will get added)
317 for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
318 /* add first triangle - verts 1,2,3 */
319 RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v2, mface->v3);
322 /* add second triangle if needed - verts 1,3,4 */
324 RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v3, mface->v4);
328 RB_trimesh_finish(mdata);
330 /* construct collision shape
332 * These have been chosen to get better speed/accuracy tradeoffs with regards
333 * to limitations of each:
334 * - BVH-Triangle Mesh: for passive objects only. Despite having greater
335 * speed/accuracy, they cannot be used for moving objects.
336 * - GImpact Mesh: for active objects. These are slower and less stable,
337 * but are more flexible for general usage.
339 if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) {
340 shape = RB_shape_new_trimesh(mdata);
343 shape = RB_shape_new_gimpact_mesh(mdata);
347 /* cleanup temp data */
348 if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
353 printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
359 /* Create new physics sim collision shape for object and store it,
360 * or remove the existing one first and replace...
362 static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
364 RigidBodyOb *rbo = ob->rigidbody_object;
365 rbCollisionShape *new_shape = NULL;
367 float size[3] = {1.0f, 1.0f, 1.0f};
370 float capsule_height;
371 float hull_margin = 0.0f;
372 bool can_embed = true;
379 /* don't create a new shape if we already have one and don't want to rebuild it */
380 if (rbo->physics_shape && !rebuild)
383 /* if automatically determining dimensions, use the Object's boundbox
384 * - assume that all quadrics are standing upright on local z-axis
385 * - assume even distribution of mass around the Object's pivot
386 * (i.e. Object pivot is centralized in boundbox)
388 // XXX: all dimensions are auto-determined now... later can add stored settings for this
389 /* get object dimensions without scaling */
390 bb = BKE_object_boundbox_get(ob);
392 size[0] = (bb->vec[4][0] - bb->vec[0][0]);
393 size[1] = (bb->vec[2][1] - bb->vec[0][1]);
394 size[2] = (bb->vec[1][2] - bb->vec[0][2]);
396 mul_v3_fl(size, 0.5f);
398 if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
399 /* take radius as largest x/y dimension, and height as z-dimension */
400 radius = MAX2(size[0], size[1]);
403 else if (rbo->shape == RB_SHAPE_SPHERE) {
404 /* take radius to the the largest dimension to try and encompass everything */
405 radius = MAX3(size[0], size[1], size[2]);
408 /* create new shape */
409 switch (rbo->shape) {
411 new_shape = RB_shape_new_box(size[0], size[1], size[2]);
414 case RB_SHAPE_SPHERE:
415 new_shape = RB_shape_new_sphere(radius);
418 case RB_SHAPE_CAPSULE:
419 capsule_height = (height - radius) * 2.0f;
420 new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
422 case RB_SHAPE_CYLINDER:
423 new_shape = RB_shape_new_cylinder(radius, height);
426 new_shape = RB_shape_new_cone(radius, height * 2.0f);
429 case RB_SHAPE_CONVEXH:
430 /* try to emged collision margin */
431 has_volume = (MIN3(size[0], size[1], size[2]) > 0.0f);
433 if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume)
435 new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
436 if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
437 rbo->margin = (can_embed && has_volume) ? 0.04f : 0.0f; /* RB_TODO ideally we shouldn't directly change the margin here */
439 case RB_SHAPE_TRIMESH:
440 new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
443 /* assign new collision shape if creation was successful */
445 if (rbo->physics_shape)
446 RB_shape_delete(rbo->physics_shape);
447 rbo->physics_shape = new_shape;
448 RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
450 /* use box shape if we can't fall back to old shape */
451 else if (rbo->physics_shape == NULL) {
452 rbo->shape = RB_SHAPE_BOX;
453 rigidbody_validate_sim_shape(ob, true);
457 /* --------------------- */
459 /* helper function to calculate volume of rigidbody object */
460 // TODO: allow a parameter to specify method used to calculate this?
461 void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
463 RigidBodyOb *rbo = ob->rigidbody_object;
465 float size[3] = {1.0f, 1.0f, 1.0f};
471 /* if automatically determining dimensions, use the Object's boundbox
472 * - assume that all quadrics are standing upright on local z-axis
473 * - assume even distribution of mass around the Object's pivot
474 * (i.e. Object pivot is centralised in boundbox)
475 * - boundbox gives full width
477 // XXX: all dimensions are auto-determined now... later can add stored settings for this
478 BKE_object_dimensions_get(ob, size);
480 if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
481 /* take radius as largest x/y dimension, and height as z-dimension */
482 radius = MAX2(size[0], size[1]) * 0.5f;
485 else if (rbo->shape == RB_SHAPE_SPHERE) {
486 /* take radius to the the largest dimension to try and encompass everything */
487 radius = max_fff(size[0], size[1], size[2]) * 0.5f;
490 /* calculate volume as appropriate */
491 switch (rbo->shape) {
493 volume = size[0] * size[1] * size[2];
496 case RB_SHAPE_SPHERE:
497 volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
500 /* for now, assume that capsule is close enough to a cylinder... */
501 case RB_SHAPE_CAPSULE:
502 case RB_SHAPE_CYLINDER:
503 volume = (float)M_PI * radius * radius * height;
507 volume = (float)M_PI / 3.0f * radius * radius * height;
510 case RB_SHAPE_CONVEXH:
511 case RB_SHAPE_TRIMESH:
513 if (ob->type == OB_MESH) {
514 DerivedMesh *dm = rigidbody_get_mesh(ob);
517 int totvert, totface;
519 /* ensure mesh validity, then grab data */
523 DM_ensure_tessface(dm);
525 mvert = dm->getVertArray(dm);
526 totvert = dm->getNumVerts(dm);
527 mface = dm->getTessFaceArray(dm);
528 totface = dm->getNumTessFaces(dm);
530 if (totvert > 0 && totface > 0) {
531 BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL);
534 /* cleanup temp data */
535 if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
540 /* rough estimate from boundbox as fallback */
541 /* XXX could implement other types of geometry here (curves, etc.) */
542 volume = size[0] * size[1] * size[2];
547 #if 0 // XXX: not defined yet
548 case RB_SHAPE_COMPOUND:
554 /* return the volume calculated */
555 if (r_vol) *r_vol = volume;
558 void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
560 RigidBodyOb *rbo = ob->rigidbody_object;
562 float size[3] = {1.0f, 1.0f, 1.0f};
567 /* if automatically determining dimensions, use the Object's boundbox
568 * - assume that all quadrics are standing upright on local z-axis
569 * - assume even distribution of mass around the Object's pivot
570 * (i.e. Object pivot is centralised in boundbox)
571 * - boundbox gives full width
573 // XXX: all dimensions are auto-determined now... later can add stored settings for this
574 BKE_object_dimensions_get(ob, size);
576 /* calculate volume as appropriate */
577 switch (rbo->shape) {
579 case RB_SHAPE_SPHERE:
580 case RB_SHAPE_CAPSULE:
581 case RB_SHAPE_CYLINDER:
585 /* take radius as largest x/y dimension, and height as z-dimension */
587 /* cone is geometrically centered on the median,
588 * center of mass is 1/4 up from the base
590 r_com[2] = -0.25f * height;
593 case RB_SHAPE_CONVEXH:
594 case RB_SHAPE_TRIMESH:
596 if (ob->type == OB_MESH) {
597 DerivedMesh *dm = rigidbody_get_mesh(ob);
600 int totvert, totface;
602 /* ensure mesh validity, then grab data */
606 DM_ensure_tessface(dm);
608 mvert = dm->getVertArray(dm);
609 totvert = dm->getNumVerts(dm);
610 mface = dm->getTessFaceArray(dm);
611 totface = dm->getNumTessFaces(dm);
613 if (totvert > 0 && totface > 0) {
614 BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com);
617 /* cleanup temp data */
618 if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
625 #if 0 // XXX: not defined yet
626 case RB_SHAPE_COMPOUND:
633 /* --------------------- */
636 * Create physics sim representation of object given RigidBody settings
638 * \param rebuild Even if an instance already exists, replace it
640 static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rebuild)
642 RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
647 * - object doesn't have RigidBody info already: then why is it here?
652 /* make sure collision shape exists */
653 /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
654 if (rbo->physics_shape == NULL || rebuild)
655 rigidbody_validate_sim_shape(ob, true);
657 if (rbo->physics_object && rebuild == false) {
658 RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
660 if (!rbo->physics_object || rebuild) {
661 /* remove rigid body if it already exists before creating a new one */
662 if (rbo->physics_object) {
663 RB_body_delete(rbo->physics_object);
666 mat4_to_loc_quat(loc, rot, ob->obmat);
668 rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot);
670 RB_body_set_friction(rbo->physics_object, rbo->friction);
671 RB_body_set_restitution(rbo->physics_object, rbo->restitution);
673 RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping);
674 RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
675 RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
677 if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
678 RB_body_deactivate(rbo->physics_object);
681 RB_body_set_linear_factor(rbo->physics_object,
682 (ob->protectflag & OB_LOCK_LOCX) == 0,
683 (ob->protectflag & OB_LOCK_LOCY) == 0,
684 (ob->protectflag & OB_LOCK_LOCZ) == 0);
685 RB_body_set_angular_factor(rbo->physics_object,
686 (ob->protectflag & OB_LOCK_ROTX) == 0,
687 (ob->protectflag & OB_LOCK_ROTY) == 0,
688 (ob->protectflag & OB_LOCK_ROTZ) == 0);
690 RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
691 RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
694 if (rbw && rbw->physics_world)
695 RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
698 /* --------------------- */
701 * Create physics sim representation of constraint given rigid body constraint settings
703 * \param rebuild Even if an instance already exists, replace it
705 static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, bool rebuild)
707 RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
716 * - object should have a rigid body constraint
717 * - rigid body constraint should have at least one constrained object
723 if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
724 if (rbc->physics_constraint) {
725 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
726 RB_constraint_delete(rbc->physics_constraint);
727 rbc->physics_constraint = NULL;
732 if (rbc->physics_constraint && rebuild == false) {
733 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
735 if (rbc->physics_constraint == NULL || rebuild) {
736 rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object;
737 rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object;
739 /* remove constraint if it already exists before creating a new one */
740 if (rbc->physics_constraint) {
741 RB_constraint_delete(rbc->physics_constraint);
742 rbc->physics_constraint = NULL;
745 mat4_to_loc_quat(loc, rot, ob->obmat);
750 rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2);
753 rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2);
756 rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2);
757 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
758 RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
761 RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f);
763 case RBC_TYPE_SLIDER:
764 rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2);
765 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
766 RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
768 RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f);
770 case RBC_TYPE_PISTON:
771 rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2);
772 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
773 lin_lower = rbc->limit_lin_x_lower;
774 lin_upper = rbc->limit_lin_x_upper;
780 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
781 ang_lower = rbc->limit_ang_x_lower;
782 ang_upper = rbc->limit_ang_x_upper;
788 RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper);
790 case RBC_TYPE_6DOF_SPRING:
791 rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
793 RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
794 RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
795 RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
797 RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
798 RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
799 RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
801 RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
802 RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
803 RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
805 RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
808 if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
809 rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
811 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
812 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
814 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
816 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
817 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
819 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
821 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
822 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
824 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
826 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
827 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
829 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
831 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
832 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
834 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
836 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
837 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
839 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
842 rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
844 RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG);
845 RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse);
846 RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity);
850 else { /* can't create constraint without both rigid bodies */
854 RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED);
856 if (rbc->flag & RBC_FLAG_USE_BREAKING)
857 RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold);
859 RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX);
861 if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)
862 RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations);
864 RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
867 if (rbw && rbw->physics_world && rbc->physics_constraint) {
868 RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
872 /* --------------------- */
874 /* Create physics sim world given RigidBody world settings */
875 // NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet!
876 void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
882 /* create new sim world */
883 if (rebuild || rbw->physics_world == NULL) {
884 if (rbw->physics_world)
885 RB_dworld_delete(rbw->physics_world);
886 rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity);
889 RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations);
890 RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
893 /* ************************************** */
894 /* Setup Utilities - Create Settings Blocks */
896 /* Set up RigidBody world */
897 RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
899 /* try to get whatever RigidBody world that might be representing this already */
903 * - there must be a valid scene to add world to
904 * - there mustn't be a sim world using this group already
909 /* create a new sim world */
910 rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld");
912 /* set default settings */
913 rbw->effector_weights = BKE_add_effector_weights(NULL);
917 rbw->time_scale = 1.0f;
919 rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
920 rbw->num_solver_iterations = 10; /* 10 is bullet default */
922 rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches));
923 rbw->pointcache->step = 1;
925 /* return this sim world */
929 RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw)
931 RigidBodyWorld *rbwn = MEM_dupallocN(rbw);
933 if (rbw->effector_weights)
934 rbwn->effector_weights = MEM_dupallocN(rbw->effector_weights);
936 id_us_plus(&rbwn->group->id);
937 if (rbwn->constraints)
938 id_us_plus(&rbwn->constraints->id);
940 rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, false);
942 rbwn->objects = NULL;
943 rbwn->physics_world = NULL;
949 void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
951 if (rbw->group && rbw->group->id.newid)
952 rbw->group = (Group *)rbw->group->id.newid;
953 if (rbw->constraints && rbw->constraints->id.newid)
954 rbw->constraints = (Group *)rbw->constraints->id.newid;
955 if (rbw->effector_weights->group && rbw->effector_weights->group->id.newid)
956 rbw->effector_weights->group = (Group *)rbw->effector_weights->group->id.newid;
959 /* Add rigid body settings to the specified object */
960 RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
963 RigidBodyWorld *rbw = scene->rigidbody_world;
966 * - rigidbody world must exist
967 * - object must exist
968 * - cannot add rigid body if it already exists
970 if (ob == NULL || (ob->rigidbody_object != NULL))
973 /* create new settings data, and link it up */
974 rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
976 /* set default settings */
981 rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
982 rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
984 rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
986 rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
987 rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
989 rbo->lin_damping = 0.04f; /* 0.04 is game engine default */
990 rbo->ang_damping = 0.1f; /* 0.1 is game engine default */
994 /* use triangle meshes for passive objects
995 * use convex hulls for active objects since dynamic triangle meshes are very unstable
997 if (type == RBO_TYPE_ACTIVE)
998 rbo->shape = RB_SHAPE_CONVEXH;
1000 rbo->shape = RB_SHAPE_TRIMESH;
1002 rbo->mesh_source = RBO_MESH_DEFORM;
1004 /* set initial transform */
1005 mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
1007 /* flag cache as outdated */
1008 BKE_rigidbody_cache_reset(rbw);
1010 /* return this object */
1014 /* Add rigid body constraint to the specified object */
1015 RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
1018 RigidBodyWorld *rbw = scene->rigidbody_world;
1021 * - rigidbody world must exist
1022 * - object must exist
1023 * - cannot add constraint if it already exists
1025 if (ob == NULL || (ob->rigidbody_constraint != NULL))
1028 /* create new settings data, and link it up */
1029 rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon");
1031 /* set default settings */
1037 rbc->flag |= RBC_FLAG_ENABLED;
1038 rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
1040 rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
1041 rbc->num_solver_iterations = 10; /* 10 is Bullet default */
1043 rbc->limit_lin_x_lower = -1.0f;
1044 rbc->limit_lin_x_upper = 1.0f;
1045 rbc->limit_lin_y_lower = -1.0f;
1046 rbc->limit_lin_y_upper = 1.0f;
1047 rbc->limit_lin_z_lower = -1.0f;
1048 rbc->limit_lin_z_upper = 1.0f;
1049 rbc->limit_ang_x_lower = -M_PI_4;
1050 rbc->limit_ang_x_upper = M_PI_4;
1051 rbc->limit_ang_y_lower = -M_PI_4;
1052 rbc->limit_ang_y_upper = M_PI_4;
1053 rbc->limit_ang_z_lower = -M_PI_4;
1054 rbc->limit_ang_z_upper = M_PI_4;
1056 rbc->spring_damping_x = 0.5f;
1057 rbc->spring_damping_y = 0.5f;
1058 rbc->spring_damping_z = 0.5f;
1059 rbc->spring_stiffness_x = 10.0f;
1060 rbc->spring_stiffness_y = 10.0f;
1061 rbc->spring_stiffness_z = 10.0f;
1063 rbc->motor_lin_max_impulse = 1.0f;
1064 rbc->motor_lin_target_velocity = 1.0f;
1065 rbc->motor_ang_max_impulse = 1.0f;
1066 rbc->motor_ang_target_velocity = 1.0f;
1068 /* flag cache as outdated */
1069 BKE_rigidbody_cache_reset(rbw);
1071 /* return this object */
1075 /* ************************************** */
1078 /* Get RigidBody world for the given scene, creating one if needed
1080 * \param scene Scene to find active Rigid Body world for
1082 RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
1088 return scene->rigidbody_world;
1091 void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
1093 RigidBodyWorld *rbw = scene->rigidbody_world;
1094 RigidBodyOb *rbo = ob->rigidbody_object;
1100 /* remove from rigidbody world, free object won't do this */
1101 if (rbw->physics_world && rbo->physics_object)
1102 RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
1104 /* remove object from array */
1105 if (rbw && rbw->objects) {
1106 for (i = 0; i < rbw->numbodies; i++) {
1107 if (rbw->objects[i] == ob) {
1108 rbw->objects[i] = NULL;
1114 /* remove object from rigid body constraints */
1115 if (rbw->constraints) {
1116 for (go = rbw->constraints->gobject.first; go; go = go->next) {
1117 Object *obt = go->ob;
1118 if (obt && obt->rigidbody_constraint) {
1119 rbc = obt->rigidbody_constraint;
1120 if (ELEM(ob, rbc->ob1, rbc->ob2)) {
1121 BKE_rigidbody_remove_constraint(scene, obt);
1128 /* remove object's settings */
1129 BKE_rigidbody_free_object(ob);
1131 /* flag cache as outdated */
1132 BKE_rigidbody_cache_reset(rbw);
1135 void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
1137 RigidBodyWorld *rbw = scene->rigidbody_world;
1138 RigidBodyCon *rbc = ob->rigidbody_constraint;
1140 /* remove from rigidbody world, free object won't do this */
1141 if (rbw && rbw->physics_world && rbc->physics_constraint) {
1142 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
1144 /* remove object's settings */
1145 BKE_rigidbody_free_constraint(ob);
1147 /* flag cache as outdated */
1148 BKE_rigidbody_cache_reset(rbw);
1152 /* ************************************** */
1153 /* Simulation Interface - Bullet */
1155 /* Update object array and rigid body count so they're in sync with the rigid body group */
1156 static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
1161 n = BLI_countlist(&rbw->group->gobject);
1163 if (rbw->numbodies != n) {
1165 rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
1168 for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
1169 Object *ob = go->ob;
1170 rbw->objects[i] = ob;
1174 static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
1176 float adj_gravity[3];
1178 /* adjust gravity to take effector weights into account */
1179 if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
1180 copy_v3_v3(adj_gravity, scene->physics_settings.gravity);
1181 mul_v3_fl(adj_gravity, rbw->effector_weights->global_gravity * rbw->effector_weights->weight[0]);
1184 zero_v3(adj_gravity);
1187 /* update gravity, since this RNA setting is not part of RigidBody settings */
1188 RB_dworld_set_gravity(rbw->physics_world, adj_gravity);
1190 /* update object array in case there are changes */
1191 rigidbody_update_ob_array(rbw);
1194 static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
1200 /* only update if rigid body exists */
1201 if (rbo->physics_object == NULL)
1204 if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) {
1205 DerivedMesh *dm = ob->derivedDeform;
1207 MVert *mvert = dm->getVertArray(dm);
1208 int totvert = dm->getNumVerts(dm);
1209 BoundBox *bb = BKE_object_boundbox_get(ob);
1211 RB_shape_trimesh_update(rbo->physics_shape, (float *)mvert, totvert, sizeof(MVert), bb->vec[0], bb->vec[6]);
1215 mat4_decompose(loc, rot, scale, ob->obmat);
1217 /* update scale for all objects */
1218 RB_body_set_scale(rbo->physics_object, scale);
1219 /* compensate for embedded convex hull collision margin */
1220 if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH)
1221 RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2]));
1223 /* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */
1224 if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
1225 RB_body_set_kinematic_state(rbo->physics_object, true);
1226 RB_body_set_mass(rbo->physics_object, 0.0f);
1229 /* update rigid body location and rotation for kinematic bodies */
1230 if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
1231 RB_body_activate(rbo->physics_object);
1232 RB_body_set_loc_rot(rbo->physics_object, loc, rot);
1234 /* update influence of effectors - but don't do it on an effector */
1235 /* only dynamic bodies need effector update */
1236 else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) {
1237 EffectorWeights *effector_weights = rbw->effector_weights;
1238 EffectedPoint epoint;
1239 ListBase *effectors;
1241 /* get effectors present in the group specified by effector_weights */
1242 effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
1244 float eff_force[3] = {0.0f, 0.0f, 0.0f};
1245 float eff_loc[3], eff_vel[3];
1247 /* create dummy 'point' which represents last known position of object as result of sim */
1248 // XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
1249 RB_body_get_position(rbo->physics_object, eff_loc);
1250 RB_body_get_linear_velocity(rbo->physics_object, eff_vel);
1252 pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
1254 /* calculate net force of effectors, and apply to sim object
1255 * - we use 'central force' since apply force requires a "relative position" which we don't have...
1257 pdDoEffectors(effectors, NULL, effector_weights, &epoint, eff_force, NULL);
1259 printf("\tapplying force (%f,%f,%f) to '%s'\n", eff_force[0], eff_force[1], eff_force[2], ob->id.name + 2);
1260 /* activate object in case it is deactivated */
1261 if (!is_zero_v3(eff_force))
1262 RB_body_activate(rbo->physics_object);
1263 RB_body_apply_central_force(rbo->physics_object, eff_force);
1265 else if (G.f & G_DEBUG)
1266 printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
1269 pdEndEffectors(&effectors);
1271 /* NOTE: passive objects don't need to be updated since they don't move */
1273 /* NOTE: no other settings need to be explicitly updated here,
1274 * since RNA setters take care of the rest :)
1279 * Updates and validates world, bodies and shapes.
1281 * \param rebuild Rebuild entire simulation
1283 static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
1289 BKE_rigidbody_validate_sim_world(scene, rbw, true);
1290 rigidbody_update_sim_world(scene, rbw);
1292 /* XXX TODO For rebuild: remove all constraints first.
1293 * Otherwise we can end up deleting objects that are still
1294 * referenced by constraints, corrupting bullet's internal list.
1296 * Memory management needs redesign here, this is just a dirty workaround.
1298 if (rebuild && rbw->constraints) {
1299 for (go = rbw->constraints->gobject.first; go; go = go->next) {
1300 Object *ob = go->ob;
1302 RigidBodyCon *rbc = ob->rigidbody_constraint;
1303 if (rbc && rbc->physics_constraint) {
1304 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
1305 RB_constraint_delete(rbc->physics_constraint);
1306 rbc->physics_constraint = NULL;
1312 /* update objects */
1313 for (go = rbw->group->gobject.first; go; go = go->next) {
1314 Object *ob = go->ob;
1316 if (ob && ob->type == OB_MESH) {
1317 /* validate that we've got valid object set up here... */
1318 RigidBodyOb *rbo = ob->rigidbody_object;
1319 /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
1320 BKE_object_where_is_calc(scene, ob);
1323 /* Since this object is included in the sim group but doesn't have
1324 * rigid body settings (perhaps it was added manually), add!
1325 * - assume object to be active? That is the default for newly added settings...
1327 ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
1328 rigidbody_validate_sim_object(rbw, ob, true);
1330 rbo = ob->rigidbody_object;
1333 /* perform simulation data updates as tagged */
1334 /* refresh object... */
1336 /* World has been rebuilt so rebuild object */
1337 rigidbody_validate_sim_object(rbw, ob, true);
1339 else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
1340 rigidbody_validate_sim_object(rbw, ob, false);
1342 /* refresh shape... */
1343 if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
1344 /* mesh/shape data changed, so force shape refresh */
1345 rigidbody_validate_sim_shape(ob, true);
1346 /* now tell RB sim about it */
1347 // XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies
1348 RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
1350 rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
1353 /* update simulation object... */
1354 rigidbody_update_sim_ob(scene, rbw, ob, rbo);
1358 /* update constraints */
1359 if (rbw->constraints == NULL) /* no constraints, move on */
1361 for (go = rbw->constraints->gobject.first; go; go = go->next) {
1362 Object *ob = go->ob;
1365 /* validate that we've got valid object set up here... */
1366 RigidBodyCon *rbc = ob->rigidbody_constraint;
1367 /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
1368 BKE_object_where_is_calc(scene, ob);
1371 /* Since this object is included in the group but doesn't have
1372 * constraint settings (perhaps it was added manually), add!
1374 ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
1375 rigidbody_validate_sim_constraint(rbw, ob, true);
1377 rbc = ob->rigidbody_constraint;
1380 /* perform simulation data updates as tagged */
1382 /* World has been rebuilt so rebuild constraint */
1383 rigidbody_validate_sim_constraint(rbw, ob, true);
1385 else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
1386 rigidbody_validate_sim_constraint(rbw, ob, false);
1388 rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
1394 static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
1398 for (go = rbw->group->gobject.first; go; go = go->next) {
1399 Object *ob = go->ob;
1402 RigidBodyOb *rbo = ob->rigidbody_object;
1403 /* reset kinematic state for transformed objects */
1404 if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) {
1405 RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
1406 RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
1407 /* deactivate passive objects so they don't interfere with deactivation of active objects */
1408 if (rbo->type == RBO_TYPE_PASSIVE)
1409 RB_body_deactivate(rbo->physics_object);
1415 bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
1417 return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->pointcache->startframe);
1420 /* Sync rigid body and object transformations */
1421 void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
1423 RigidBodyOb *rbo = ob->rigidbody_object;
1425 /* keep original transform for kinematic and passive objects */
1426 if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE)
1429 /* use rigid body transform after cache start frame if objects is not being transformed */
1430 if (BKE_rigidbody_check_sim_running(rbw, ctime) && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
1431 float mat[4][4], size_mat[4][4], size[3];
1433 normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point
1434 quat_to_mat4(mat, rbo->orn);
1435 copy_v3_v3(mat[3], rbo->pos);
1437 mat4_to_size(size, ob->obmat);
1438 size_to_mat4(size_mat, size);
1439 mul_m4_m4m4(mat, mat, size_mat);
1441 copy_m4_m4(ob->obmat, mat);
1443 /* otherwise set rigid body transform to current obmat */
1445 mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
1449 /* Used when canceling transforms - return rigidbody and object to initial states */
1450 void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
1452 RigidBodyOb *rbo = ob->rigidbody_object;
1454 /* return rigid body and object to their initial states */
1455 copy_v3_v3(rbo->pos, ob->loc);
1456 copy_v3_v3(ob->loc, loc);
1458 if (ob->rotmode > 0) {
1459 eulO_to_quat(rbo->orn, ob->rot, ob->rotmode);
1460 copy_v3_v3(ob->rot, rot);
1462 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
1463 axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle);
1464 copy_v3_v3(ob->rotAxis, rotAxis);
1465 ob->rotAngle = rotAngle;
1468 copy_qt_qt(rbo->orn, ob->quat);
1469 copy_qt_qt(ob->quat, quat);
1471 if (rbo->physics_object) {
1472 /* allow passive objects to return to original transform */
1473 if (rbo->type == RBO_TYPE_PASSIVE)
1474 RB_body_set_kinematic_state(rbo->physics_object, true);
1475 RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn);
1477 // RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
1480 void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
1483 rbw->pointcache->flag |= PTCACHE_OUTDATED;
1486 /* ------------------ */
1488 /* Rebuild rigid body world */
1489 /* NOTE: this needs to be called before frame update to work correctly */
1490 void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
1492 RigidBodyWorld *rbw = scene->rigidbody_world;
1495 int startframe, endframe;
1497 BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
1498 BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
1499 cache = rbw->pointcache;
1501 /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
1502 if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) {
1503 cache->flag |= PTCACHE_OUTDATED;
1506 if (ctime == startframe + 1 && rbw->ltime == startframe) {
1507 if (cache->flag & PTCACHE_OUTDATED) {
1508 BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
1509 rigidbody_update_simulation(scene, rbw, true);
1510 BKE_ptcache_validate(cache, (int)ctime);
1511 cache->last_exact = 0;
1512 cache->flag &= ~PTCACHE_REDO_NEEDED;
1517 /* Run RigidBody simulation for the specified physics world */
1518 void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
1521 RigidBodyWorld *rbw = scene->rigidbody_world;
1524 int startframe, endframe;
1526 BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
1527 BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
1528 cache = rbw->pointcache;
1530 if (ctime <= startframe) {
1531 rbw->ltime = startframe;
1534 /* make sure we don't go out of cache frame range */
1535 else if (ctime > endframe) {
1539 /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
1540 if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
1542 else if (rbw->objects == NULL)
1543 rigidbody_update_ob_array(rbw);
1545 /* try to read from cache */
1546 // RB_TODO deal with interpolated, old and baked results
1547 if (BKE_ptcache_read(&pid, ctime)) {
1548 BKE_ptcache_validate(cache, (int)ctime);
1553 /* advance simulation, we can only step one frame forward */
1554 if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) {
1555 /* write cache for first frame when on second frame */
1556 if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
1557 BKE_ptcache_write(&pid, startframe);
1560 /* update and validate simulation */
1561 rigidbody_update_simulation(scene, rbw, false);
1563 /* calculate how much time elapsed since last step in seconds */
1564 timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
1565 /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */
1566 RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
1568 rigidbody_update_simulation_post_step(rbw);
1570 /* write cache for current frame */
1571 BKE_ptcache_validate(cache, (int)ctime);
1572 BKE_ptcache_write(&pid, (unsigned int)ctime);
1577 /* ************************************** */
1579 #else /* WITH_BULLET */
1583 # pragma GCC diagnostic push
1584 # pragma GCC diagnostic ignored "-Wunused-parameter"
1587 void BKE_rigidbody_free_world(RigidBodyWorld *rbw) {}
1588 void BKE_rigidbody_free_object(Object *ob) {}
1589 void BKE_rigidbody_free_constraint(Object *ob) {}
1590 struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
1591 struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
1592 void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {}
1593 void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
1594 void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; }
1595 void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) { zero_v3(r_com); }
1596 struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
1597 struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
1598 void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
1599 struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; }
1600 struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; }
1601 struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; }
1602 void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {}
1603 void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {}
1604 void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {}
1605 void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {}
1606 bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; }
1607 void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
1608 void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
1609 void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
1612 # pragma GCC diagnostic pop
1615 #endif /* WITH_BULLET */