Merging r58778 through r59080 from trunk into soc-2013-depsgraph_mt
[blender.git] / intern / rigidbody / rb_bullet_api.cpp
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 rb_bullet_api.cpp
29  *  \ingroup RigidBody
30  *  \brief Rigid Body API implementation for Bullet
31  */
32
33 /*
34 Bullet Continuous Collision Detection and Physics Library
35 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
36
37 This software is provided 'as-is', without any express or implied warranty.
38 In no event will the authors be held liable for any damages arising from the use of this software.
39 Permission is granted to anyone to use this software for any purpose, 
40 including commercial applications, and to alter it and redistribute it freely, 
41 subject to the following restrictions:
42
43 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
44 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
45 3. This notice may not be removed or altered from any source distribution.
46 */
47  
48 /* This file defines the "RigidBody interface" for the 
49  * Bullet Physics Engine. This API is designed to be used
50  * from C-code in Blender as part of the Rigid Body simulation
51  * system.
52  *
53  * It is based on the Bullet C-API, but is heavily modified to 
54  * give access to more data types and to offer a nicer interface.
55  *
56  * -- Joshua Leung, June 2010
57  */
58
59 #include <stdio.h>
60 #include <errno.h>
61
62 #include "RBI_api.h"
63
64 #include "btBulletDynamicsCommon.h"
65
66 #include "LinearMath/btVector3.h"
67 #include "LinearMath/btScalar.h"        
68 #include "LinearMath/btMatrix3x3.h"
69 #include "LinearMath/btTransform.h"
70 #include "LinearMath/btConvexHullComputer.h"
71
72 #include "BulletCollision/Gimpact/btGImpactShape.h"
73 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
74 #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
75
76 struct rbDynamicsWorld {
77         btDiscreteDynamicsWorld *dynamicsWorld;
78         btDefaultCollisionConfiguration *collisionConfiguration;
79         btDispatcher *dispatcher;
80         btBroadphaseInterface *pairCache;
81         btConstraintSolver *constraintSolver;
82         btOverlapFilterCallback *filterCallback;
83 };
84 struct rbRigidBody {
85         btRigidBody *body;
86         int col_groups;
87 };
88
89 struct rbCollisionShape {
90         btCollisionShape *cshape;
91         btTriangleMesh *mesh;
92 };
93
94 struct rbFilterCallback : public btOverlapFilterCallback
95 {
96         virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const
97         {
98                 rbRigidBody *rb0 = (rbRigidBody *)((btRigidBody *)proxy0->m_clientObject)->getUserPointer();
99                 rbRigidBody *rb1 = (rbRigidBody *)((btRigidBody *)proxy1->m_clientObject)->getUserPointer();
100                 
101                 bool collides;
102                 collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
103                 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
104                 collides = collides && (rb0->col_groups & rb1->col_groups);
105                 
106                 return collides;
107         }
108 };
109
110 static inline void copy_v3_btvec3(float vec[3], const btVector3 &btvec)
111 {
112         vec[0] = (float)btvec[0];
113         vec[1] = (float)btvec[1];
114         vec[2] = (float)btvec[2];
115 }
116 static inline void copy_quat_btquat(float quat[4], const btQuaternion &btquat)
117 {
118         quat[0] = btquat.getW();
119         quat[1] = btquat.getX();
120         quat[2] = btquat.getY();
121         quat[3] = btquat.getZ();
122 }
123
124 /* ********************************** */
125 /* Dynamics World Methods */
126
127 /* Setup ---------------------------- */
128
129 rbDynamicsWorld *RB_dworld_new(const float gravity[3])
130 {
131         rbDynamicsWorld *world = new rbDynamicsWorld;
132         
133         /* collision detection/handling */
134         world->collisionConfiguration = new btDefaultCollisionConfiguration();
135         
136         world->dispatcher = new btCollisionDispatcher(world->collisionConfiguration);
137         btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher *)world->dispatcher);
138         
139         world->pairCache = new btDbvtBroadphase();
140         
141         world->filterCallback = new rbFilterCallback();
142         world->pairCache->getOverlappingPairCache()->setOverlapFilterCallback(world->filterCallback);
143
144         /* constraint solving */
145         world->constraintSolver = new btSequentialImpulseConstraintSolver();
146
147         /* world */
148         world->dynamicsWorld = new btDiscreteDynamicsWorld(world->dispatcher,
149                                                            world->pairCache,
150                                                            world->constraintSolver,
151                                                            world->collisionConfiguration);
152
153         RB_dworld_set_gravity(world, gravity);
154         
155         return world;
156 }
157
158 void RB_dworld_delete(rbDynamicsWorld *world)
159 {
160         /* bullet doesn't like if we free these in a different order */
161         delete world->dynamicsWorld;
162         delete world->constraintSolver;
163         delete world->pairCache;
164         delete world->dispatcher;
165         delete world->collisionConfiguration;
166         delete world->filterCallback;
167         delete world;
168 }
169
170 /* Settings ------------------------- */
171
172 /* Gravity */
173 void RB_dworld_get_gravity(rbDynamicsWorld *world, float g_out[3])
174 {
175         copy_v3_btvec3(g_out, world->dynamicsWorld->getGravity());
176 }
177
178 void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3])
179 {
180         world->dynamicsWorld->setGravity(btVector3(g_in[0], g_in[1], g_in[2]));
181 }
182
183 /* Constraint Solver */
184 void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations)
185 {
186         btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo();
187         
188         info.m_numIterations = num_solver_iterations;
189 }
190
191 /* Split Impulse */
192 void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse)
193 {
194         btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo();
195         
196         info.m_splitImpulse = split_impulse;
197 }
198
199 /* Simulation ----------------------- */
200
201 void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep)
202 {
203         world->dynamicsWorld->stepSimulation(timeStep, maxSubSteps, timeSubStep);
204 }
205
206 /* Export -------------------------- */
207
208 /* Exports entire dynamics world to Bullet's "*.bullet" binary format
209  * which is similar to Blender's SDNA system...
210  * < rbDynamicsWorld: dynamics world to write to file
211  * < filename: assumed to be a valid filename, with .bullet extension 
212  */
213 void RB_dworld_export(rbDynamicsWorld *world, const char *filename)
214 {
215         //create a large enough buffer. There is no method to pre-calculate the buffer size yet.
216         int maxSerializeBufferSize = 1024 * 1024 * 5;
217         
218         btDefaultSerializer *serializer = new btDefaultSerializer(maxSerializeBufferSize);
219         world->dynamicsWorld->serialize(serializer);
220         
221         FILE *file = fopen(filename, "wb");
222         if (file) {
223                 fwrite(serializer->getBufferPointer(), serializer->getCurrentBufferSize(), 1, file);
224                 fclose(file);
225         }
226         else {
227                  fprintf(stderr, "RB_dworld_export: %s\n", strerror(errno));
228         }
229 }
230
231 /* ********************************** */
232 /* Rigid Body Methods */
233
234 /* Setup ---------------------------- */
235
236 void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_groups)
237 {
238         btRigidBody *body = object->body;
239         object->col_groups = col_groups;
240         
241         world->dynamicsWorld->addRigidBody(body);
242 }
243
244 void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *object)
245 {
246         btRigidBody *body = object->body;
247         
248         world->dynamicsWorld->removeRigidBody(body);
249 }
250
251 /* Collision detection */
252
253 void RB_world_convex_sweep_test(rbDynamicsWorld *world, rbRigidBody *object, const float loc_start[3], const float loc_end[3], float v_location[3],  float v_hitpoint[3],  float v_normal[3], int *r_hit)
254 {
255         btRigidBody *body = object->body;
256         btCollisionShape *collisionShape = body->getCollisionShape();
257         /* only convex shapes are supported, but user can specify a non convex shape */
258         if (collisionShape->isConvex()) {
259                 btCollisionWorld::ClosestConvexResultCallback result(btVector3(loc_start[0], loc_start[1], loc_start[2]), btVector3(loc_end[0], loc_end[1], loc_end[2]));
260
261                 btQuaternion obRot = body->getWorldTransform().getRotation();
262                 
263                 btTransform rayFromTrans;
264                 rayFromTrans.setIdentity();
265                 rayFromTrans.setRotation(obRot);
266                 rayFromTrans.setOrigin(btVector3(loc_start[0], loc_start[1], loc_start[2]));
267
268                 btTransform rayToTrans;
269                 rayToTrans.setIdentity();
270                 rayToTrans.setRotation(obRot);
271                 rayToTrans.setOrigin(btVector3(loc_end[0], loc_end[1], loc_end[2]));
272                 
273                 world->dynamicsWorld->convexSweepTest((btConvexShape*) collisionShape, rayFromTrans, rayToTrans, result, 0);
274                 
275                 if (result.hasHit()) {
276                         *r_hit = 1;
277                         
278                         v_location[0] = result.m_convexFromWorld[0]+(result.m_convexToWorld[0]-result.m_convexFromWorld[0])*result.m_closestHitFraction;
279                         v_location[1] = result.m_convexFromWorld[1]+(result.m_convexToWorld[1]-result.m_convexFromWorld[1])*result.m_closestHitFraction;
280                         v_location[2] = result.m_convexFromWorld[2]+(result.m_convexToWorld[2]-result.m_convexFromWorld[2])*result.m_closestHitFraction;
281                         
282                         v_hitpoint[0] = result.m_hitPointWorld[0];
283                         v_hitpoint[1] = result.m_hitPointWorld[1];
284                         v_hitpoint[2] = result.m_hitPointWorld[2];
285                         
286                         v_normal[0] = result.m_hitNormalWorld[0];
287                         v_normal[1] = result.m_hitNormalWorld[1];
288                         v_normal[2] = result.m_hitNormalWorld[2];
289                         
290                 }
291                 else {
292                         *r_hit = 0;
293                 }
294         }
295         else{
296                 /* we need to return a value if user passes non convex body, to report */
297                 *r_hit = -2;
298         }
299 }
300
301 /* ............ */
302
303 rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4])
304 {
305         rbRigidBody *object = new rbRigidBody;
306         /* current transform */
307         btTransform trans;
308         trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
309         trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
310         
311         /* create motionstate, which is necessary for interpolation (includes reverse playback) */
312         btDefaultMotionState *motionState = new btDefaultMotionState(trans);
313         
314         /* make rigidbody */
315         btRigidBody::btRigidBodyConstructionInfo rbInfo(1.0f, motionState, shape->cshape);
316         
317         object->body = new btRigidBody(rbInfo);
318         
319         object->body->setUserPointer(object);
320         
321         return object;
322 }
323
324 void RB_body_delete(rbRigidBody *object)
325 {
326         btRigidBody *body = object->body;
327         
328         /* motion state */
329         btMotionState *ms = body->getMotionState();
330         if (ms)
331                 delete ms;
332         
333         /* collision shape is done elsewhere... */
334         
335         /* body itself */
336         
337         /* manually remove constraint refs of the rigid body, normally this happens when removing constraints from the world
338          * but since we delete everything when the world is rebult, we need to do it manually here */
339         for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) {
340                 btTypedConstraint *con = body->getConstraintRef(i);
341                 body->removeConstraintRef(con);
342         }
343         
344         delete body;
345         delete object;
346 }
347
348 /* Settings ------------------------- */
349
350 void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape)
351 {
352         btRigidBody *body = object->body;
353         
354         /* set new collision shape */
355         body->setCollisionShape(shape->cshape);
356         
357         /* recalculate inertia, since that depends on the collision shape... */
358         RB_body_set_mass(object, RB_body_get_mass(object));
359 }
360
361 /* ............ */
362
363 float RB_body_get_mass(rbRigidBody *object)
364 {
365         btRigidBody *body = object->body;
366         
367         /* there isn't really a mass setting, but rather 'inverse mass'  
368          * which we convert back to mass by taking the reciprocal again 
369          */
370         float value = (float)body->getInvMass();
371         
372         if (value)
373                 value = 1.0 / value;
374                 
375         return value;
376 }
377
378 void RB_body_set_mass(rbRigidBody *object, float value)
379 {
380         btRigidBody *body = object->body;
381         btVector3 localInertia(0, 0, 0);
382         
383         /* calculate new inertia if non-zero mass */
384         if (value) {
385                 btCollisionShape *shape = body->getCollisionShape();
386                 shape->calculateLocalInertia(value, localInertia);
387         }
388         
389         body->setMassProps(value, localInertia);
390         body->updateInertiaTensor();
391 }
392
393
394 float RB_body_get_friction(rbRigidBody *object)
395 {
396         btRigidBody *body = object->body;
397         return body->getFriction();
398 }
399
400 void RB_body_set_friction(rbRigidBody *object, float value)
401 {
402         btRigidBody *body = object->body;
403         body->setFriction(value);
404 }
405
406
407 float RB_body_get_restitution(rbRigidBody *object)
408 {
409         btRigidBody *body = object->body;
410         return body->getRestitution();
411 }
412
413 void RB_body_set_restitution(rbRigidBody *object, float value)
414 {
415         btRigidBody *body = object->body;
416         body->setRestitution(value);
417 }
418
419
420 float RB_body_get_linear_damping(rbRigidBody *object)
421 {
422         btRigidBody *body = object->body;
423         return body->getLinearDamping();
424 }
425
426 void RB_body_set_linear_damping(rbRigidBody *object, float value)
427 {
428         RB_body_set_damping(object, value, RB_body_get_linear_damping(object));
429 }
430
431 float RB_body_get_angular_damping(rbRigidBody *object)
432 {
433         btRigidBody *body = object->body;
434         return body->getAngularDamping();
435 }
436
437 void RB_body_set_angular_damping(rbRigidBody *object, float value)
438 {
439         RB_body_set_damping(object, RB_body_get_linear_damping(object), value);
440 }
441
442 void RB_body_set_damping(rbRigidBody *object, float linear, float angular)
443 {
444         btRigidBody *body = object->body;
445         body->setDamping(linear, angular);
446 }
447
448
449 float RB_body_get_linear_sleep_thresh(rbRigidBody *object)
450 {
451         btRigidBody *body = object->body;
452         return body->getLinearSleepingThreshold();
453 }
454
455 void RB_body_set_linear_sleep_thresh(rbRigidBody *object, float value)
456 {
457         RB_body_set_sleep_thresh(object, value, RB_body_get_angular_sleep_thresh(object));
458 }
459
460 float RB_body_get_angular_sleep_thresh(rbRigidBody *object)
461 {
462         btRigidBody *body = object->body;
463         return body->getAngularSleepingThreshold();
464 }
465
466 void RB_body_set_angular_sleep_thresh(rbRigidBody *object, float value)
467 {
468         RB_body_set_sleep_thresh(object, RB_body_get_linear_sleep_thresh(object), value);
469 }
470
471 void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular)
472 {
473         btRigidBody *body = object->body;
474         body->setSleepingThresholds(linear, angular);
475 }
476
477 /* ............ */
478
479 void RB_body_get_linear_velocity(rbRigidBody *object, float v_out[3])
480 {
481         btRigidBody *body = object->body;
482         
483         copy_v3_btvec3(v_out, body->getLinearVelocity());
484 }
485
486 void RB_body_set_linear_velocity(rbRigidBody *object, const float v_in[3])
487 {
488         btRigidBody *body = object->body;
489         
490         body->setLinearVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
491 }
492
493
494 void RB_body_get_angular_velocity(rbRigidBody *object, float v_out[3])
495 {
496         btRigidBody *body = object->body;
497         
498         copy_v3_btvec3(v_out, body->getAngularVelocity());
499 }
500
501 void RB_body_set_angular_velocity(rbRigidBody *object, const float v_in[3])
502 {
503         btRigidBody *body = object->body;
504         
505         body->setAngularVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
506 }
507
508 void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z)
509 {
510         btRigidBody *body = object->body;
511         body->setLinearFactor(btVector3(x, y, z));
512 }
513
514 void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z)
515 {
516         btRigidBody *body = object->body;
517         body->setAngularFactor(btVector3(x, y, z));
518 }
519
520 /* ............ */
521
522 void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic)
523 {
524         btRigidBody *body = object->body;
525         if (kinematic)
526                 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
527         else
528                 body->setCollisionFlags(body->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
529 }
530
531 /* ............ */
532
533 void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation)
534 {
535         btRigidBody *body = object->body;
536         if (use_deactivation)
537                 body->forceActivationState(ACTIVE_TAG);
538         else
539                 body->setActivationState(DISABLE_DEACTIVATION);
540 }
541 void RB_body_activate(rbRigidBody *object)
542 {
543         btRigidBody *body = object->body;
544         body->setActivationState(ACTIVE_TAG);
545 }
546 void RB_body_deactivate(rbRigidBody *object)
547 {
548         btRigidBody *body = object->body;
549         body->setActivationState(ISLAND_SLEEPING);
550 }
551
552 /* ............ */
553
554
555
556 /* Simulation ----------------------- */
557
558 /* The transform matrices Blender uses are OpenGL-style matrices, 
559  * while Bullet uses the Right-Handed coordinate system style instead.
560  */
561
562 void RB_body_get_transform_matrix(rbRigidBody *object, float m_out[4][4])
563 {
564         btRigidBody *body = object->body;
565         btMotionState *ms = body->getMotionState();
566         
567         btTransform trans;
568         ms->getWorldTransform(trans);
569         
570         trans.getOpenGLMatrix((btScalar *)m_out);
571 }
572
573 void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float rot[4])
574 {
575         btRigidBody *body = object->body;
576         btMotionState *ms = body->getMotionState();
577         
578         /* set transform matrix */
579         btTransform trans;
580         trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
581         trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
582         
583         ms->setWorldTransform(trans);
584 }
585
586 void RB_body_set_scale(rbRigidBody *object, const float scale[3])
587 {
588         btRigidBody *body = object->body;
589         
590         /* apply scaling factor from matrix above to the collision shape */
591         btCollisionShape *cshape = body->getCollisionShape();
592         if (cshape) {
593                 cshape->setLocalScaling(btVector3(scale[0], scale[1], scale[2]));
594                 
595                 /* GIimpact shapes have to be updated to take scaling into account */
596                 if (cshape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
597                         ((btGImpactMeshShape *)cshape)->updateBound();
598         }
599 }
600
601 /* ............ */
602 /* Read-only state info about status of simulation */
603
604 void RB_body_get_position(rbRigidBody *object, float v_out[3])
605 {
606         btRigidBody *body = object->body;
607         
608         copy_v3_btvec3(v_out, body->getWorldTransform().getOrigin());
609 }
610
611 void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
612 {
613         btRigidBody *body = object->body;
614         
615         copy_quat_btquat(v_out, body->getWorldTransform().getRotation());
616 }
617
618 /* ............ */
619 /* Overrides for simulation */
620
621 void RB_body_apply_central_force(rbRigidBody *object, const float v_in[3])
622 {
623         btRigidBody *body = object->body;
624         
625         body->applyCentralForce(btVector3(v_in[0], v_in[1], v_in[2]));
626 }
627
628 /* ********************************** */
629 /* Collision Shape Methods */
630
631 /* Setup (Standard Shapes) ----------- */
632
633 rbCollisionShape *RB_shape_new_box(float x, float y, float z)
634 {
635         rbCollisionShape *shape = new rbCollisionShape;
636         shape->cshape = new btBoxShape(btVector3(x, y, z));
637         shape->mesh = NULL;
638         return shape;
639 }
640
641 rbCollisionShape *RB_shape_new_sphere(float radius)
642 {
643         rbCollisionShape *shape = new rbCollisionShape;
644         shape->cshape = new btSphereShape(radius);
645         shape->mesh = NULL;
646         return shape;
647 }
648
649 rbCollisionShape *RB_shape_new_capsule(float radius, float height)
650 {
651         rbCollisionShape *shape = new rbCollisionShape;
652         shape->cshape = new btCapsuleShapeZ(radius, height);
653         shape->mesh = NULL;
654         return shape;
655 }
656
657 rbCollisionShape *RB_shape_new_cone(float radius, float height)
658 {
659         rbCollisionShape *shape = new rbCollisionShape;
660         shape->cshape = new btConeShapeZ(radius, height);
661         shape->mesh = NULL;
662         return shape;
663 }
664
665 rbCollisionShape *RB_shape_new_cylinder(float radius, float height)
666 {
667         rbCollisionShape *shape = new rbCollisionShape;
668         shape->cshape = new btCylinderShapeZ(btVector3(radius, radius, height));
669         shape->mesh = NULL;
670         return shape;
671 }
672
673 /* Setup (Convex Hull) ------------ */
674
675 rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count, float margin, bool *can_embed)
676 {
677         btConvexHullComputer hull_computer = btConvexHullComputer();
678         
679         // try to embed the margin, if that fails don't shrink the hull
680         if (hull_computer.compute(verts, stride, count, margin, 0.0f) < 0.0f) {
681                 hull_computer.compute(verts, stride, count, 0.0f, 0.0f);
682                 *can_embed = false;
683         }
684         
685         rbCollisionShape *shape = new rbCollisionShape;
686         btConvexHullShape *hull_shape = new btConvexHullShape(&(hull_computer.vertices[0].getX()), hull_computer.vertices.size());
687         
688         shape->cshape = hull_shape;
689         shape->mesh = NULL;
690         return shape;
691 }
692
693 /* Setup (Triangle Mesh) ---------- */
694
695 /* Need to call rbTriMeshNewData() followed by rbTriMeshAddTriangle() several times 
696  * to set up the mesh buffer BEFORE calling rbShapeNewTriMesh(). Otherwise,
697  * we get nasty crashes...
698  */
699
700 rbMeshData *RB_trimesh_data_new()
701 {
702         // XXX: welding threshold?
703         return (rbMeshData *) new btTriangleMesh(true, false);
704 }
705  
706 void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
707 {
708         btTriangleMesh *meshData = reinterpret_cast<btTriangleMesh*>(mesh);
709         
710         /* cast vertices to usable forms for Bt-API */
711         btVector3 vtx1((btScalar)v1[0], (btScalar)v1[1], (btScalar)v1[2]);
712         btVector3 vtx2((btScalar)v2[0], (btScalar)v2[1], (btScalar)v2[2]);
713         btVector3 vtx3((btScalar)v3[0], (btScalar)v3[1], (btScalar)v3[2]);
714         
715         /* add to the mesh 
716          *      - remove duplicated verts is enabled
717          */
718         meshData->addTriangle(vtx1, vtx2, vtx3, false);
719 }
720  
721 rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
722 {
723         rbCollisionShape *shape = new rbCollisionShape;
724         btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
725         
726         /* triangle-mesh we create is a BVH wrapper for triangle mesh data (for faster lookups) */
727         // RB_TODO perhaps we need to allow saving out this for performance when rebuilding?
728         btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(tmesh, true, true);
729         
730         shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
731         shape->mesh = tmesh;
732         return shape;
733 }
734
735 rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
736 {
737         rbCollisionShape *shape = new rbCollisionShape;
738         /* interpret mesh buffer as btTriangleIndexVertexArray (i.e. an impl of btStridingMeshInterface) */
739         btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
740         
741         btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(tmesh);
742         gimpactShape->updateBound(); // TODO: add this to the update collision margin call?
743         
744         shape->cshape = gimpactShape;
745         shape->mesh = tmesh;
746         return shape;
747 }
748
749 /* Cleanup --------------------------- */
750
751 void RB_shape_delete(rbCollisionShape *shape)
752 {
753         if (shape->cshape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) {
754                 btBvhTriangleMeshShape *child_shape = ((btScaledBvhTriangleMeshShape *)shape->cshape)->getChildShape();
755                 if (child_shape)
756                         delete child_shape;
757         }
758         if (shape->mesh)
759                 delete shape->mesh;
760         delete shape->cshape;
761         delete shape;
762 }
763
764 /* Settings --------------------------- */
765
766 float RB_shape_get_margin(rbCollisionShape *shape)
767 {
768         return shape->cshape->getMargin();
769 }
770
771 void RB_shape_set_margin(rbCollisionShape *shape, float value)
772 {
773         shape->cshape->setMargin(value);
774 }
775
776 /* ********************************** */
777 /* Constraints */
778
779 /* Setup ----------------------------- */
780
781 void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions)
782 {
783         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
784         
785         world->dynamicsWorld->addConstraint(constraint, disable_collisions);
786 }
787
788 void RB_dworld_remove_constraint(rbDynamicsWorld *world, rbConstraint *con)
789 {
790         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
791         
792         world->dynamicsWorld->removeConstraint(constraint);
793 }
794
795 /* ............ */
796
797 static void make_constraint_transforms(btTransform &transform1, btTransform &transform2, btRigidBody *body1, btRigidBody *body2, float pivot[3], float orn[4])
798 {
799         btTransform pivot_transform = btTransform();
800         pivot_transform.setOrigin(btVector3(pivot[0], pivot[1], pivot[2]));
801         pivot_transform.setRotation(btQuaternion(orn[1], orn[2], orn[3], orn[0]));
802         
803         transform1 = body1->getWorldTransform().inverse() * pivot_transform;
804         transform2 = body2->getWorldTransform().inverse() * pivot_transform;
805 }
806
807 rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2)
808 {
809         btRigidBody *body1 = rb1->body;
810         btRigidBody *body2 = rb2->body;
811         
812         btVector3 pivot1 = body1->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
813         btVector3 pivot2 = body2->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
814         
815         btTypedConstraint *con = new btPoint2PointConstraint(*body1, *body2, pivot1, pivot2);
816         
817         return (rbConstraint *)con;
818 }
819
820 rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
821 {
822         btRigidBody *body1 = rb1->body;
823         btRigidBody *body2 = rb2->body;
824         btTransform transform1;
825         btTransform transform2;
826         
827         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
828         
829         btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
830         
831         /* lock all axes */
832         for (int i = 0; i < 6; i++)
833                 con->setLimit(i, 0, 0);
834         
835         return (rbConstraint *)con;
836 }
837
838 rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
839 {
840         btRigidBody *body1 = rb1->body;
841         btRigidBody *body2 = rb2->body;
842         btTransform transform1;
843         btTransform transform2;
844         
845         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
846         
847         btHingeConstraint *con = new btHingeConstraint(*body1, *body2, transform1, transform2);
848         
849         return (rbConstraint *)con;
850 }
851
852 rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
853 {
854         btRigidBody *body1 = rb1->body;
855         btRigidBody *body2 = rb2->body;
856         btTransform transform1;
857         btTransform transform2;
858         
859         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
860         
861         btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true);
862         
863         return (rbConstraint *)con;
864 }
865
866 rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
867 {
868         btRigidBody *body1 = rb1->body;
869         btRigidBody *body2 = rb2->body;
870         btTransform transform1;
871         btTransform transform2;
872         
873         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
874         
875         btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true);
876         con->setUpperAngLimit(-1.0f); // unlock rotation axis
877         
878         return (rbConstraint *)con;
879 }
880
881 rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
882 {
883         btRigidBody *body1 = rb1->body;
884         btRigidBody *body2 = rb2->body;
885         btTransform transform1;
886         btTransform transform2;
887         
888         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
889         
890         btTypedConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
891         
892         return (rbConstraint *)con;
893 }
894
895 rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
896 {
897         btRigidBody *body1 = rb1->body;
898         btRigidBody *body2 = rb2->body;
899         btTransform transform1;
900         btTransform transform2;
901         
902         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
903         
904         btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true);
905         
906         return (rbConstraint *)con;
907 }
908
909 rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
910 {
911         btRigidBody *body1 = rb1->body;
912         btRigidBody *body2 = rb2->body;
913         btTransform transform1;
914         btTransform transform2;
915         
916         make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
917         
918         btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
919         
920         /* unlock constraint axes */
921         for (int i = 0; i < 6; i++) {
922                 con->setLimit(i, 0.0f, -1.0f);
923         }
924         /* unlock motor axes */
925         con->getTranslationalLimitMotor()->m_upperLimit.setValue(-1.0f, -1.0f, -1.0f);
926         
927         return (rbConstraint*)con;
928 }
929
930 /* Cleanup ----------------------------- */
931
932 void RB_constraint_delete(rbConstraint *con)
933 {
934         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
935         delete constraint;
936 }
937
938 /* Settings ------------------------- */
939
940 void RB_constraint_set_enabled(rbConstraint *con, int enabled)
941 {
942         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
943         
944         constraint->setEnabled(enabled);
945 }
946
947 void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper)
948 {
949         btHingeConstraint *constraint = reinterpret_cast<btHingeConstraint*>(con);
950         
951         // RB_TODO expose these
952         float softness = 0.9f;
953         float bias_factor = 0.3f;
954         float relaxation_factor = 1.0f;
955         
956         constraint->setLimit(lower, upper, softness, bias_factor, relaxation_factor);
957 }
958
959 void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper)
960 {
961         btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con);
962         
963         constraint->setLowerLinLimit(lower);
964         constraint->setUpperLinLimit(upper);
965 }
966
967 void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper)
968 {
969         btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con);
970         
971         constraint->setLowerLinLimit(lin_lower);
972         constraint->setUpperLinLimit(lin_upper);
973         constraint->setLowerAngLimit(ang_lower);
974         constraint->setUpperAngLimit(ang_upper);
975 }
976
977 void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper)
978 {
979         btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
980         
981         constraint->setLimit(axis, lower, upper);
982 }
983
984 void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness)
985 {
986         btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
987         
988         constraint->setStiffness(axis, stiffness);
989 }
990
991 void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping)
992 {
993         btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
994         
995         // invert damping range so that 0 = no damping
996         constraint->setDamping(axis, 1.0f - damping);
997 }
998
999 void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable)
1000 {
1001         btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
1002         
1003         constraint->enableSpring(axis, enable);
1004 }
1005
1006 void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con)
1007 {
1008         btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
1009         
1010         constraint->setEquilibriumPoint();
1011 }
1012
1013 void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations)
1014 {
1015         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
1016         
1017         constraint->setOverrideNumSolverIterations(num_solver_iterations);
1018 }
1019
1020 void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold)
1021 {
1022         btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
1023         
1024         constraint->setBreakingImpulseThreshold(threshold);
1025 }
1026
1027 void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang)
1028 {
1029         btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
1030         
1031         constraint->getTranslationalLimitMotor()->m_enableMotor[0] = enable_lin;
1032         constraint->getRotationalLimitMotor(0)->m_enableMotor = enable_ang;
1033 }
1034
1035 void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang)
1036 {
1037         btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
1038         
1039         constraint->getTranslationalLimitMotor()->m_maxMotorForce.setX(max_impulse_lin);
1040         constraint->getRotationalLimitMotor(0)->m_maxMotorForce = max_impulse_ang;
1041 }
1042
1043 void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang)
1044 {
1045         btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
1046         
1047         constraint->getTranslationalLimitMotor()->m_targetVelocity.setX(velocity_lin);
1048         constraint->getRotationalLimitMotor(0)->m_targetVelocity = velocity_ang;
1049 }
1050
1051 /* ********************************** */