rigidbody: Add generic spring constraint
[blender.git] / source / blender / blenkernel / intern / rigidbody.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung, Sergej Reich
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file rigidbody.c
29  *  \ingroup blenkernel
30  *  \brief Blender-side interface and methods for dealing with Rigid Body simulations
31  */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stddef.h>
36 #include <float.h>
37 #include <math.h>
38 #include <limits.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_math.h"
44
45 #include "RBI_api.h"
46
47 #include "DNA_anim_types.h"
48 #include "DNA_group_types.h"
49 #include "DNA_mesh_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"
55
56 #include "BKE_animsys.h"
57 #include "BKE_cdderivedmesh.h"
58 #include "BKE_effect.h"
59 #include "BKE_group.h"
60 #include "BKE_object.h"
61 #include "BKE_mesh.h"
62 #include "BKE_pointcache.h"
63 #include "BKE_rigidbody.h"
64 #include "BKE_global.h"
65 #include "BKE_utildefines.h"
66
67 #include "RNA_access.h"
68
69 /* ************************************** */
70 /* Memory Management */
71
72 /* Freeing Methods --------------------- */
73
74 /* Free rigidbody world */
75 void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
76 {
77         /* sanity check */
78         if (!rbw)
79                 return;
80
81         if (rbw->physics_world) {
82                 /* free physics references, we assume that all physics objects in will have been added to the world */
83                 GroupObject *go;
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;
88
89                                         if (rbc->physics_constraint)
90                                                 RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
91                                 }
92                         }
93                 }
94                 if (rbw->group) {
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;
98
99                                         if (rbo->physics_object)
100                                                 RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
101                                 }
102                         }
103                 }
104                 /* free dynamics world */
105                 RB_dworld_delete(rbw->physics_world);
106         }
107         if (rbw->objects)
108                 free(rbw->objects);
109
110         /* free cache */
111         BKE_ptcache_free_list(&(rbw->ptcaches));
112         rbw->pointcache = NULL;
113
114         /* free effector weights */
115         if (rbw->effector_weights)
116                 MEM_freeN(rbw->effector_weights);
117
118         /* free rigidbody world itself */
119         MEM_freeN(rbw);
120 }
121
122 /* Free RigidBody settings and sim instances */
123 void BKE_rigidbody_free_object(Object *ob)
124 {
125         RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
126
127         /* sanity check */
128         if (rbo == NULL)
129                 return;
130
131         /* free physics references */
132         if (rbo->physics_object) {
133                 RB_body_delete(rbo->physics_object);
134                 rbo->physics_object = NULL;
135         }
136
137         if (rbo->physics_shape) {
138                 RB_shape_delete(rbo->physics_shape);
139                 rbo->physics_shape = NULL;
140         }
141
142         /* free data itself */
143         MEM_freeN(rbo);
144         ob->rigidbody_object = NULL;
145 }
146
147 /* Free RigidBody constraint and sim instance */
148 void BKE_rigidbody_free_constraint(Object *ob)
149 {
150         RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
151
152         /* sanity check */
153         if (rbc == NULL)
154                 return;
155
156         /* free physics reference */
157         if (rbc->physics_constraint) {
158                 RB_constraint_delete(rbc->physics_constraint);
159                 rbc->physics_constraint = NULL;
160         }
161
162         /* free data itself */
163         MEM_freeN(rbc);
164         ob->rigidbody_constraint = NULL;
165 }
166
167 /* Copying Methods --------------------- */
168
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...
172  */
173
174 RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
175 {
176         RigidBodyOb *rboN = NULL;
177
178         if (ob->rigidbody_object) {
179                 /* just duplicate the whole struct first (to catch all the settings) */
180                 rboN = MEM_dupallocN(ob->rigidbody_object);
181
182                 /* tag object as needing to be verified */
183                 rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
184
185                 /* clear out all the fields which need to be revalidated later */
186                 rboN->physics_object = NULL;
187                 rboN->physics_shape = NULL;
188         }
189
190         /* return new copy of settings */
191         return rboN;
192 }
193
194 RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
195 {
196         RigidBodyCon *rbcN = NULL;
197
198         if (ob->rigidbody_constraint) {
199                 /* just duplicate the whole struct first (to catch all the settings) */
200                 rbcN = MEM_dupallocN(ob->rigidbody_constraint);
201
202                 // RB_TODO be more clever about copying constrained objects
203
204                 /* tag object as needing to be verified */
205                 rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE;
206
207                 /* clear out all the fields which need to be revalidated later */
208                 rbcN->physics_constraint = NULL;
209         }
210
211         /* return new copy of settings */
212         return rbcN;
213 }
214
215 /* ************************************** */
216 /* Setup Utilities - Validate Sim Instances */
217
218 /* create collision shape of mesh - convex hull */
219 static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed)
220 {
221         rbCollisionShape *shape = NULL;
222         Mesh *me = NULL;
223
224         if (ob->type == OB_MESH && ob->data) {
225                 me = ob->data;
226         }
227         else {
228                 printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n");
229         }
230
231         if (me && me->totvert) {
232                 shape = RB_shape_new_convex_hull((float *)me->mvert, sizeof(MVert), me->totvert, margin, can_embed);
233         }
234         else {
235                 printf("ERROR: no vertices to define Convex Hull collision shape with\n");
236         }
237
238         return shape;
239 }
240
241 /* create collision shape of mesh - triangulated mesh
242  * returns NULL if creation fails.
243  */
244 static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
245 {
246         rbCollisionShape *shape = NULL;
247
248         if (ob->type == OB_MESH) {
249                 DerivedMesh *dm = CDDM_from_mesh(ob->data, ob);
250
251                 MVert *mvert;
252                 MFace *mface;
253                 int totvert;
254                 int totface;
255
256                 /* ensure mesh validity, then grab data */
257                 DM_ensure_tessface(dm);
258
259                 mvert   = (dm) ? dm->getVertArray(dm) : NULL;
260                 totvert = (dm) ? dm->getNumVerts(dm) : 0;
261                 mface   = (dm) ? dm->getTessFaceArray(dm) : NULL;
262                 totface = (dm) ? dm->getNumTessFaces(dm) : 0;
263
264                 /* sanity checking - potential case when no data will be present */
265                 if ((totvert == 0) || (totface == 0)) {
266                         printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
267                 }
268                 else {
269                         rbMeshData *mdata;
270                         int i;
271
272                         /* init mesh data for collision shape */
273                         mdata = RB_trimesh_data_new();
274
275                         /* loop over all faces, adding them as triangles to the collision shape
276                          * (so for some faces, more than triangle will get added)
277                          */
278                         for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
279                                 /* add first triangle - verts 1,2,3 */
280                                 {
281                                         MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
282                                         MVert *vb = (IN_RANGE(mface->v2, 0, totvert)) ? (mvert + mface->v2) : (mvert);
283                                         MVert *vc = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
284
285                                         RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
286                                 }
287
288                                 /* add second triangle if needed - verts 1,3,4 */
289                                 if (mface->v4) {
290                                         MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
291                                         MVert *vb = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
292                                         MVert *vc = (IN_RANGE(mface->v4, 0, totvert)) ? (mvert + mface->v4) : (mvert);
293
294                                         RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
295                                 }
296                         }
297
298                         /* construct collision shape
299                          *
300                          * These have been chosen to get better speed/accuracy tradeoffs with regards
301                          * to limitations of each:
302                          *    - BVH-Triangle Mesh: for passive objects only. Despite having greater
303                          *                         speed/accuracy, they cannot be used for moving objects.
304                          *    - GImpact Mesh:      for active objects. These are slower and less stable,
305                          *                         but are more flexible for general usage.
306                          */
307                         if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) {
308                                 shape = RB_shape_new_trimesh(mdata);
309                         }
310                         else {
311                                 shape = RB_shape_new_gimpact_mesh(mdata);
312                         }
313                 }
314
315                 /* cleanup temp data */
316                 if (dm) {
317                         dm->release(dm);
318                 }
319         }
320         else {
321                 printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
322         }
323
324         return shape;
325 }
326
327 /* Create new physics sim collision shape for object and store it,
328  * or remove the existing one first and replace...
329  */
330 void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild)
331 {
332         RigidBodyOb *rbo = ob->rigidbody_object;
333         rbCollisionShape *new_shape = NULL;
334         BoundBox *bb = NULL;
335         float size[3] = {1.0f, 1.0f, 1.0f};
336         float radius = 1.0f;
337         float height = 1.0f;
338         float capsule_height;
339         float hull_margin = 0.0f;
340         bool can_embed = true;
341
342         /* sanity check */
343         if (rbo == NULL)
344                 return;
345
346         /* don't create a new shape if we already have one and don't want to rebuild it */
347         if (rbo->physics_shape && !rebuild)
348                 return;
349
350         /* if automatically determining dimensions, use the Object's boundbox
351          *      - assume that all quadrics are standing upright on local z-axis
352          *      - assume even distribution of mass around the Object's pivot
353          *        (i.e. Object pivot is centralised in boundbox)
354          */
355         // XXX: all dimensions are auto-determined now... later can add stored settings for this
356         /* get object dimensions without scaling */
357         bb = BKE_object_boundbox_get(ob);
358         if (bb) {
359                 size[0] = (bb->vec[4][0] - bb->vec[0][0]);
360                 size[1] = (bb->vec[2][1] - bb->vec[0][1]);
361                 size[2] = (bb->vec[1][2] - bb->vec[0][2]);
362         }
363         mul_v3_fl(size, 0.5f);
364
365         if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
366                 /* take radius as largest x/y dimension, and height as z-dimension */
367                 radius = MAX2(size[0], size[1]);
368                 height = size[2];
369         }
370         else if (rbo->shape == RB_SHAPE_SPHERE) {
371                 /* take radius to the the largest dimension to try and encompass everything */
372                 radius = MAX3(size[0], size[1], size[2]);
373         }
374
375         /* create new shape */
376         switch (rbo->shape) {
377                 case RB_SHAPE_BOX:
378                         new_shape = RB_shape_new_box(size[0], size[1], size[2]);
379                         break;
380
381                 case RB_SHAPE_SPHERE:
382                         new_shape = RB_shape_new_sphere(radius);
383                         break;
384
385                 case RB_SHAPE_CAPSULE:
386                         capsule_height = (height - radius) * 2.0f;
387                         new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
388                         break;
389                 case RB_SHAPE_CYLINDER:
390                         new_shape = RB_shape_new_cylinder(radius, height);
391                         break;
392                 case RB_SHAPE_CONE:
393                         new_shape = RB_shape_new_cone(radius, height * 2.0f);
394                         break;
395
396                 case RB_SHAPE_CONVEXH:
397                         /* try to emged collision margin */
398                         if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
399                                 hull_margin = 0.04f;
400                         new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
401                         if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
402                                 rbo->margin = (can_embed) ? 0.04f : 0.0f;  /* RB_TODO ideally we shouldn't directly change the margin here */
403                         break;
404                 case RB_SHAPE_TRIMESH:
405                         new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
406                         break;
407         }
408         /* assign new collision shape if creation was successful */
409         if (new_shape) {
410                 if (rbo->physics_shape)
411                         RB_shape_delete(rbo->physics_shape);
412                 rbo->physics_shape = new_shape;
413                 RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
414         }
415 }
416
417 /* --------------------- */
418
419 /* Create physics sim representation of object given RigidBody settings
420  * < rebuild: even if an instance already exists, replace it
421  */
422 void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild)
423 {
424         RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
425         float loc[3];
426         float rot[4];
427
428         /* sanity checks:
429          *      - object doesn't have RigidBody info already: then why is it here?
430          */
431         if (rbo == NULL)
432                 return;
433
434         /* make sure collision shape exists */
435         /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
436         if (rbo->physics_shape == NULL || rebuild)
437                 BKE_rigidbody_validate_sim_shape(ob, true);
438
439         if (rbo->physics_object) {
440                 if (rebuild == false)
441                         RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
442         }
443         if (!rbo->physics_object || rebuild) {
444                 /* remove rigid body if it already exists before creating a new one */
445                 if (rbo->physics_object) {
446                         RB_body_delete(rbo->physics_object);
447                 }
448
449                 mat4_to_loc_quat(loc, rot, ob->obmat);
450
451                 rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot);
452
453                 RB_body_set_friction(rbo->physics_object, rbo->friction);
454                 RB_body_set_restitution(rbo->physics_object, rbo->restitution);
455
456                 RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping);
457                 RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
458                 RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
459
460                 if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
461                         RB_body_deactivate(rbo->physics_object);
462
463
464                 RB_body_set_linear_factor(rbo->physics_object,
465                                                                   (ob->protectflag & OB_LOCK_LOCX) == 0,
466                                           (ob->protectflag & OB_LOCK_LOCY) == 0,
467                                           (ob->protectflag & OB_LOCK_LOCZ) == 0);
468                 RB_body_set_angular_factor(rbo->physics_object,
469                                            (ob->protectflag & OB_LOCK_ROTX) == 0,
470                                            (ob->protectflag & OB_LOCK_ROTY) == 0,
471                                            (ob->protectflag & OB_LOCK_ROTZ) == 0);
472
473                 RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
474                 RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
475         }
476
477         if (rbw && rbw->physics_world)
478                 RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
479 }
480
481 /* --------------------- */
482
483 /* Create physics sim representation of constraint given rigid body constraint settings
484  * < rebuild: even if an instance already exists, replace it
485  */
486 void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild)
487 {
488         RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
489         float loc[3];
490         float rot[4];
491         float lin_lower;
492         float lin_upper;
493         float ang_lower;
494         float ang_upper;
495
496         /* sanity checks:
497          *      - object should have a rigid body constraint
498          *  - rigid body constraint should have at least one constrained object
499          */
500         if (rbc == NULL) {
501                 return;
502         }
503
504         if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
505                 if (rbc->physics_constraint) {
506                         RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
507                         RB_constraint_delete(rbc->physics_constraint);
508                         rbc->physics_constraint = NULL;
509                 }
510                 return;
511         }
512
513         if (rbc->physics_constraint) {
514                 if (rebuild == false)
515                         RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
516         }
517         if (rbc->physics_constraint == NULL || rebuild) {
518                 rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object;
519                 rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object;
520
521                 /* remove constraint if it already exists before creating a new one */
522                 if (rbc->physics_constraint) {
523                         RB_constraint_delete(rbc->physics_constraint);
524                         rbc->physics_constraint = NULL;
525                 }
526
527                 mat4_to_loc_quat(loc, rot, ob->obmat);
528
529                 if (rb1 && rb2) {
530                         switch (rbc->type) {
531                                 case RBC_TYPE_POINT:
532                                         rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2);
533                                         break;
534                                 case RBC_TYPE_FIXED:
535                                         rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2);
536                                         break;
537                                 case RBC_TYPE_HINGE:
538                                         rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2);
539                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
540                                                 RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
541                                         }
542                                         else
543                                                 RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f);
544                                         break;
545                                 case RBC_TYPE_SLIDER:
546                                         rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2);
547                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
548                                                 RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
549                                         else
550                                                 RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f);
551                                         break;
552                                 case RBC_TYPE_PISTON:
553                                         rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2);
554                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
555                                                 lin_lower = rbc->limit_lin_x_lower;
556                                                 lin_upper = rbc->limit_lin_x_upper;
557                                         }
558                                         else {
559                                                 lin_lower = 0.0f;
560                                                 lin_upper = -1.0f;
561                                         }
562                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
563                                                 ang_lower = rbc->limit_ang_x_lower;
564                                                 ang_upper = rbc->limit_ang_x_upper;
565                                         }
566                                         else {
567                                                 ang_lower = 0.0f;
568                                                 ang_upper = -1.0f;
569                                         }
570                                         RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper);
571                                         break;
572                                 case RBC_TYPE_6DOF_SPRING:
573                                         rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
574
575                                         RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
576                                         RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
577                                         RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
578
579                                         RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
580                                         RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
581                                         RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
582
583                                         RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
584                                         RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
585                                         RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
586
587                                         RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
588                                 /* fall through */
589                                 case RBC_TYPE_6DOF:
590                                         if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
591                                                 rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
592
593                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
594                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
595                                         else
596                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
597
598                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
599                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
600                                         else
601                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
602
603                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
604                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
605                                         else
606                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
607
608                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
609                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
610                                         else
611                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
612
613                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
614                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
615                                         else
616                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
617
618                                         if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
619                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
620                                         else
621                                                 RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
622                                         break;
623                         }
624                 }
625
626                 RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED);
627
628                 if (rbc->flag & RBC_FLAG_USE_BREAKING)
629                         RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold);
630                 else
631                         RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX);
632
633                 if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)
634                         RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations);
635                 else
636                         RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
637         }
638
639         if (rbw && rbw->physics_world && rbc->physics_constraint) {
640                 RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
641         }
642 }
643
644 /* --------------------- */
645
646 /* Create physics sim world given RigidBody world settings */
647 // NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet!
648 void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild)
649 {
650         /* sanity checks */
651         if (rbw == NULL)
652                 return;
653
654         /* create new sim world */
655         if (rebuild || rbw->physics_world == NULL) {
656                 if (rbw->physics_world)
657                         RB_dworld_delete(rbw->physics_world);
658                 rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity);
659         }
660
661         RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations);
662         RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
663 }
664
665 /* ************************************** */
666 /* Setup Utilities - Create Settings Blocks */
667
668 /* Set up RigidBody world */
669 RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
670 {
671         /* try to get whatever RigidBody world that might be representing this already */
672         RigidBodyWorld *rbw;
673
674         /* sanity checks
675          *      - there must be a valid scene to add world to
676          *      - there mustn't be a sim world using this group already
677          */
678         if (scene == NULL)
679                 return NULL;
680
681         /* create a new sim world */
682         rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld");
683
684         /* set default settings */
685         rbw->effector_weights = BKE_add_effector_weights(NULL);
686
687         rbw->ltime = PSFRA;
688
689         rbw->time_scale = 1.0f;
690
691         rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
692         rbw->num_solver_iterations = 10; /* 10 is bullet default */
693
694         rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches));
695         rbw->pointcache->step = 1;
696
697         /* return this sim world */
698         return rbw;
699 }
700
701 /* Add rigid body settings to the specified object */
702 RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
703 {
704         RigidBodyOb *rbo;
705         RigidBodyWorld *rbw = scene->rigidbody_world;
706
707         /* sanity checks
708          *      - rigidbody world must exist
709          *      - object must exist
710          *      - cannot add rigid body if it already exists
711          */
712         if (ob == NULL || (ob->rigidbody_object != NULL))
713                 return NULL;
714
715         /* create new settings data, and link it up */
716         rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
717
718         /* set default settings */
719         rbo->type = type;
720
721         rbo->mass = 1.0f;
722
723         rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
724         rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
725
726         rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
727
728         rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
729         rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
730
731         rbo->lin_damping = 0.04f; /* 0.04 is game engine default */
732         rbo->ang_damping = 0.1f; /* 0.1 is game engine default */
733
734         rbo->col_groups = 1;
735
736         /* use triangle meshes for passive objects
737          * use convex hulls for active objects since dynamic triangle meshes are very unstable
738          */
739         if (type == RBO_TYPE_ACTIVE)
740                 rbo->shape = RB_SHAPE_CONVEXH;
741         else
742                 rbo->shape = RB_SHAPE_TRIMESH;
743
744         /* set initial transform */
745         mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
746
747         /* flag cache as outdated */
748         BKE_rigidbody_cache_reset(rbw);
749
750         /* return this object */
751         return rbo;
752 }
753
754 /* Add rigid body constraint to the specified object */
755 RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
756 {
757         RigidBodyCon *rbc;
758         RigidBodyWorld *rbw = scene->rigidbody_world;
759
760         /* sanity checks
761          *      - rigidbody world must exist
762          *      - object must exist
763          *      - cannot add constraint if it already exists
764          */
765         if (ob == NULL || (ob->rigidbody_constraint != NULL))
766                 return NULL;
767
768         /* create new settings data, and link it up */
769         rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon");
770
771         /* set default settings */
772         rbc->type = type;
773
774         rbc->ob1 = NULL;
775         rbc->ob2 = NULL;
776
777         rbc->flag |= RBC_FLAG_ENABLED;
778         rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
779
780         rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
781         rbc->num_solver_iterations = 10; /* 10 is Bullet default */
782
783         rbc->limit_lin_x_lower = -1.0f;
784         rbc->limit_lin_x_upper = 1.0f;
785         rbc->limit_lin_y_lower = -1.0f;
786         rbc->limit_lin_y_upper = 1.0f;
787         rbc->limit_lin_z_lower = -1.0f;
788         rbc->limit_lin_z_upper = 1.0f;
789         rbc->limit_ang_x_lower = -M_PI_4;
790         rbc->limit_ang_x_upper = M_PI_4;
791         rbc->limit_ang_y_lower = -M_PI_4;
792         rbc->limit_ang_y_upper = M_PI_4;
793         rbc->limit_ang_z_lower = -M_PI_4;
794         rbc->limit_ang_z_upper = M_PI_4;
795
796         rbc->spring_damping_x = 0.5f;
797         rbc->spring_damping_y = 0.5f;
798         rbc->spring_damping_z = 0.5f;
799         rbc->spring_stiffness_x = 10.0f;
800         rbc->spring_stiffness_y = 10.0f;
801         rbc->spring_stiffness_z = 10.0f;
802
803         /* flag cache as outdated */
804         BKE_rigidbody_cache_reset(rbw);
805
806         /* return this object */
807         return rbc;
808 }
809
810 /* ************************************** */
811 /* Utilities API */
812
813 /* Get RigidBody world for the given scene, creating one if needed
814  * < scene: Scene to find active Rigid Body world for
815  */
816 RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
817 {
818         /* sanity check */
819         if (scene == NULL)
820                 return NULL;
821
822         return scene->rigidbody_world;
823 }
824
825 void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
826 {
827         RigidBodyWorld *rbw = scene->rigidbody_world;
828         RigidBodyOb *rbo = ob->rigidbody_object;
829         RigidBodyCon *rbc;
830         GroupObject *go;
831         int i;
832
833         if (rbw) {
834                 /* remove from rigidbody world, free object won't do this */
835                 if (rbw->physics_world && rbo->physics_object)
836                         RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
837
838                 /* remove object from array */
839                 if (rbw && rbw->objects) {
840                         for (i = 0; i < rbw->numbodies; i++) {
841                                 if (rbw->objects[i] == ob) {
842                                         rbw->objects[i] = NULL;
843                                         break;
844                                 }
845                         }
846                 }
847
848                 /* remove object from rigid body constraints */
849                 if (rbw->constraints) {
850                         for (go = rbw->constraints->gobject.first; go; go = go->next) {
851                                 Object *obt = go->ob;
852                                 if (obt) {
853                                         rbc = obt->rigidbody_constraint;
854                                         if (rbc->ob1 == ob) {
855                                                 rbc->ob1 = NULL;
856                                                 rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
857                                         }
858                                         if (rbc->ob2 == ob) {
859                                                 rbc->ob2 = NULL;
860                                                 rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
861                                         }
862                                 }
863                         }
864                 }
865         }
866
867         /* remove object's settings */
868         BKE_rigidbody_free_object(ob);
869
870         /* flag cache as outdated */
871         BKE_rigidbody_cache_reset(rbw);
872 }
873
874 void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
875 {
876         RigidBodyWorld *rbw = scene->rigidbody_world;
877         RigidBodyCon *rbc = ob->rigidbody_constraint;
878
879         if (rbw) {
880                 /* remove from rigidbody world, free object won't do this */
881                 if (rbw && rbw->physics_world && rbc->physics_constraint)
882                         RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
883         }
884         /* remove object's settings */
885         BKE_rigidbody_free_constraint(ob);
886
887         /* flag cache as outdated */
888         BKE_rigidbody_cache_reset(rbw);
889 }
890
891
892 /* ************************************** */
893 /* Simulation Interface - Bullet */
894
895 /* Update object array and rigid body count so they're in sync with the rigid body group */
896 static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
897 {
898         GroupObject *go;
899         int i, n;
900
901         n = BLI_countlist(&rbw->group->gobject);
902
903         if (rbw->numbodies != n) {
904                 rbw->numbodies = n;
905                 rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
906         }
907
908         for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
909                 Object *ob = go->ob;
910                 rbw->objects[i] = ob;
911         }
912 }
913
914 static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
915 {
916         float adj_gravity[3];
917
918         /* adjust gravity to take effector weights into account */
919         if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
920                 copy_v3_v3(adj_gravity, scene->physics_settings.gravity);
921                 mul_v3_fl(adj_gravity, rbw->effector_weights->global_gravity * rbw->effector_weights->weight[0]);
922         }
923         else {
924                 zero_v3(adj_gravity);
925         }
926
927         /* update gravity, since this RNA setting is not part of RigidBody settings */
928         RB_dworld_set_gravity(rbw->physics_world, adj_gravity);
929
930         /* update object array in case there are changes */
931         rigidbody_update_ob_array(rbw);
932 }
933
934 static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
935 {
936         float loc[3];
937         float rot[4];
938         float scale[3];
939
940         /* only update if rigid body exists */
941         if (rbo->physics_object == NULL)
942                 return;
943
944         mat4_decompose(loc, rot, scale, ob->obmat);
945
946         /* update scale for all objects */
947         RB_body_set_scale(rbo->physics_object, scale);
948         /* compensate for embedded convex hull collision margin */
949         if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH)
950                 RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2]));
951
952         /* update rigid body location and rotation for kinematic bodies */
953         if (rbo->flag & RBO_FLAG_KINEMATIC) {
954                 RB_body_activate(rbo->physics_object);
955                 RB_body_set_loc_rot(rbo->physics_object, loc, rot);
956         }
957         /* update influence of effectors - but don't do it on an effector */
958         /* only dynamic bodies need effector update */
959         else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) {
960                 EffectorWeights *effector_weights = rbw->effector_weights;
961                 EffectedPoint epoint;
962                 ListBase *effectors;
963
964                 /* get effectors present in the group specified by effector_weights */
965                 effectors = pdInitEffectors(scene, ob, NULL, effector_weights);
966                 if (effectors) {
967                         float force[3] = {0.0f, 0.0f, 0.0f};
968                         float loc[3], vel[3];
969
970                         /* create dummy 'point' which represents last known position of object as result of sim */
971                         // XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
972                         RB_body_get_position(rbo->physics_object, loc);
973                         RB_body_get_linear_velocity(rbo->physics_object, vel);
974
975                         pd_point_from_loc(scene, loc, vel, 0, &epoint);
976
977                         /* calculate net force of effectors, and apply to sim object
978                          *      - we use 'central force' since apply force requires a "relative position" which we don't have...
979                          */
980                         pdDoEffectors(effectors, NULL, effector_weights, &epoint, force, NULL);
981                         if (G.f & G_DEBUG)
982                                 printf("\tapplying force (%f,%f,%f) to '%s'\n", force[0], force[1], force[2], ob->id.name + 2);
983                         /* activate object in case it is deactivated */
984                         if (!is_zero_v3(force))
985                                 RB_body_activate(rbo->physics_object);
986                         RB_body_apply_central_force(rbo->physics_object, force);
987                 }
988                 else if (G.f & G_DEBUG)
989                         printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
990
991                 /* cleanup */
992                 pdEndEffectors(&effectors);
993         }
994         /* NOTE: passive objects don't need to be updated since they don't move */
995
996         /* NOTE: no other settings need to be explicitly updated here,
997          * since RNA setters take care of the rest :)
998          */
999 }
1000
1001 /* Updates and validates world, bodies and shapes.
1002  * < rebuild: rebuild entire simulation
1003  */
1004 static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int rebuild)
1005 {
1006         GroupObject *go;
1007
1008         /* update world */
1009         if (rebuild)
1010                 BKE_rigidbody_validate_sim_world(scene, rbw, true);
1011         rigidbody_update_sim_world(scene, rbw);
1012
1013         /* update objects */
1014         for (go = rbw->group->gobject.first; go; go = go->next) {
1015                 Object *ob = go->ob;
1016
1017                 if (ob && ob->type == OB_MESH) {
1018                         /* validate that we've got valid object set up here... */
1019                         RigidBodyOb *rbo = ob->rigidbody_object;
1020                         /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
1021                         BKE_object_where_is_calc(scene, ob);
1022
1023                         if (rbo == NULL) {
1024                                 /* Since this object is included in the sim group but doesn't have
1025                                  * rigid body settings (perhaps it was added manually), add!
1026                                  *      - assume object to be active? That is the default for newly added settings...
1027                                  */
1028                                 ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
1029                                 BKE_rigidbody_validate_sim_object(rbw, ob, true);
1030
1031                                 rbo = ob->rigidbody_object;
1032                         }
1033                         else {
1034                                 /* perform simulation data updates as tagged */
1035                                 /* refresh object... */
1036                                 if (rebuild) {
1037                                         /* World has been rebuilt so rebuild object */
1038                                         BKE_rigidbody_validate_sim_object(rbw, ob, true);
1039                                 }
1040                                 else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
1041                                         BKE_rigidbody_validate_sim_object(rbw, ob, false);
1042                                 }
1043                                 /* refresh shape... */
1044                                 if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
1045                                         /* mesh/shape data changed, so force shape refresh */
1046                                         BKE_rigidbody_validate_sim_shape(ob, true);
1047                                         /* now tell RB sim about it */
1048                                         // XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies
1049                                         RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
1050                                 }
1051                                 rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
1052                         }
1053
1054                         /* update simulation object... */
1055                         rigidbody_update_sim_ob(scene, rbw, ob, rbo);
1056                 }
1057         }
1058         /* update constraints */
1059         if (rbw->constraints == NULL) /* no constraints, move on */
1060                 return;
1061         for (go = rbw->constraints->gobject.first; go; go = go->next) {
1062                 Object *ob = go->ob;
1063
1064                 if (ob) {
1065                         /* validate that we've got valid object set up here... */
1066                         RigidBodyCon *rbc = ob->rigidbody_constraint;
1067                         /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
1068                         BKE_object_where_is_calc(scene, ob);
1069
1070                         if (rbc == NULL) {
1071                                 /* Since this object is included in the group but doesn't have
1072                                  * constraint settings (perhaps it was added manually), add!
1073                                  */
1074                                 ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
1075                                 BKE_rigidbody_validate_sim_constraint(rbw, ob, true);
1076
1077                                 rbc = ob->rigidbody_constraint;
1078                         }
1079                         else {
1080                                 /* perform simulation data updates as tagged */
1081                                 if (rebuild) {
1082                                         /* World has been rebuilt so rebuild constraint */
1083                                         BKE_rigidbody_validate_sim_constraint(rbw, ob, true);
1084                                 }
1085                                 else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
1086                                         BKE_rigidbody_validate_sim_constraint(rbw, ob, false);
1087                                 }
1088                                 rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
1089                         }
1090                 }
1091         }
1092 }
1093
1094 /* Sync rigid body and object transformations */
1095 void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime)
1096 {
1097         RigidBodyWorld *rbw = scene->rigidbody_world;
1098         RigidBodyOb *rbo = ob->rigidbody_object;
1099
1100         /* keep original transform for kinematic and passive objects */
1101         if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE)
1102                 return;
1103
1104         /* use rigid body transform after cache start frame */
1105         if (ctime > rbw->pointcache->startframe) {
1106                 float mat[4][4], size_mat[4][4], size[3];
1107
1108                 /* keep original transform when the simulation is muted */
1109                 if (rbw->flag & RBW_FLAG_MUTED)
1110                         return;
1111
1112                 normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point
1113                 quat_to_mat4(mat, rbo->orn);
1114                 copy_v3_v3(mat[3], rbo->pos);
1115
1116                 mat4_to_size(size, ob->obmat);
1117                 size_to_mat4(size_mat, size);
1118                 mult_m4_m4m4(mat, mat, size_mat);
1119
1120                 copy_m4_m4(ob->obmat, mat);
1121         }
1122         /* otherwise set rigid body transform to current obmat */
1123         else {
1124                 mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
1125         }
1126 }
1127
1128 void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
1129 {
1130         if (rbw)
1131                 rbw->pointcache->flag |= PTCACHE_OUTDATED;
1132 }
1133
1134 /* ------------------ */
1135
1136 /* Run RigidBody simulation for the specified physics world */
1137 void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
1138 {
1139         float timestep;
1140         RigidBodyWorld *rbw = scene->rigidbody_world;
1141         PointCache *cache;
1142         PTCacheID pid;
1143         int startframe, endframe;
1144
1145         BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
1146         BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
1147         cache = rbw->pointcache;
1148
1149         /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
1150         if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) {
1151                 cache->flag |= PTCACHE_OUTDATED;
1152         }
1153
1154         if (ctime <= startframe) {
1155                 rbw->ltime = startframe;
1156                 /* reset and rebuild simulation if necessary */
1157                 if (cache->flag & PTCACHE_OUTDATED) {
1158                         BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
1159                         rigidbody_update_simulation(scene, rbw, true);
1160                         BKE_ptcache_validate(cache, (int)ctime);
1161                         cache->last_exact = 0;
1162                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1163                 }
1164                 return;
1165         }
1166         /* rebuild world if it's outdated on second frame */
1167         else if (ctime == startframe + 1 && rbw->ltime == startframe && cache->flag & PTCACHE_OUTDATED) {
1168                 BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
1169                 rigidbody_update_simulation(scene, rbw, true);
1170         }
1171         /* make sure we don't go out of cache frame range */
1172         else if (ctime > endframe) {
1173                 ctime = endframe;
1174         }
1175
1176         /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
1177         if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
1178                 return;
1179         else if (rbw->objects == NULL)
1180                 rigidbody_update_ob_array(rbw);
1181
1182         /* try to read from cache */
1183         // RB_TODO deal with interpolated, old and baked results
1184         if (BKE_ptcache_read(&pid, ctime)) {
1185                 BKE_ptcache_validate(cache, (int)ctime);
1186                 rbw->ltime = ctime;
1187                 return;
1188         }
1189
1190         /* advance simulation, we can only step one frame forward */
1191         if (ctime == rbw->ltime + 1) {
1192                 /* write cache for first frame when on second frame */
1193                 if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
1194                         BKE_ptcache_write(&pid, startframe);
1195                 }
1196
1197                 /* update and validate simulation */
1198                 rigidbody_update_simulation(scene, rbw, false);
1199
1200                 /* calculate how much time elapsed since last step in seconds */
1201                 timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
1202                 /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */
1203                 RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
1204
1205                 /* write cache for current frame */
1206                 BKE_ptcache_validate(cache, (int)ctime);
1207                 BKE_ptcache_write(&pid, (unsigned int)ctime);
1208
1209                 rbw->ltime = ctime;
1210         }
1211 }
1212 /* ************************************** */