source: trunk/src/bullet/bullet_world.cc @ 540

Last change on this file since 540 was 528, checked in by epyon, 9 years ago
  • physics updates
File size: 10.8 KB
Line 
1// Copyright (C) 2016 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/bullet/bullet_world.hh"
8
9#include "src/bullet/bullet_helper.hh"
10#include <btBulletDynamicsCommon.h>
11#include <btBulletCollisionCommon.h>
12
13using namespace nv;
14
15struct alignas( 16 ) motion_state : public btMotionState
16{
17        btTransform m_gfx_world_tr;
18        btTransform     m_com_offset;
19        btTransform     m_com_offset_inv;
20        SIMD_FORCE_INLINE void* operator new( size_t sz ) { return btAlignedAlloc( sz, 16 ); }
21        SIMD_FORCE_INLINE void  operator delete( void* ptr ) { btAlignedFree( ptr ); }
22
23        motion_state( const btTransform& start_tr = btTransform::getIdentity(), const btTransform& com_offset = btTransform::getIdentity() )
24                : m_gfx_world_tr( start_tr )
25                , m_com_offset( com_offset )
26                , m_com_offset_inv( m_com_offset.inverse() )
27        {
28        }
29
30        motion_state( const transform& startTrans = transform(), const nv::transform& com_offset = nv::transform() )
31                : m_gfx_world_tr( n2b( startTrans ) )
32                , m_com_offset( n2b( com_offset ) )
33                , m_com_offset_inv( m_com_offset.inverse() )
34        {
35        }
36
37        nv::transform get_world_transform() const
38        {
39                return b2n( m_gfx_world_tr );
40        }
41
42        void set_world_transform( const nv::transform& tr )
43        {
44                m_gfx_world_tr = n2b( tr );
45        }
46
47        virtual void    getWorldTransform( btTransform& com_world_tr ) const
48        {
49                com_world_tr = m_gfx_world_tr * m_com_offset_inv;
50        }
51
52        virtual void    setWorldTransform( const btTransform& com_world_tr )
53        {
54                m_gfx_world_tr = com_world_tr * m_com_offset;
55        }
56
57};
58
59
60#define SELF static_cast<btDiscreteDynamicsWorld*>( world )
61
62bullet_world::bullet_world()
63{
64        btBroadphaseInterface*               broadphase = new btDbvtBroadphase();
65        btDefaultCollisionConfiguration*     collisionConfiguration = new btDefaultCollisionConfiguration();
66        btCollisionDispatcher*               dispatcher = new btCollisionDispatcher( collisionConfiguration );
67        btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
68        btDiscreteDynamicsWorld*             dworld = new btDiscreteDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration );
69        world = dworld;
70}
71
72void bullet_world::set_gravity( const vec3& gravity )
73{
74        SELF->setGravity( n2b( gravity ) );
75}
76
77int nv::bullet_world::step_simulation( float dtime, int max_sub_steps /*= 1*/, float fixed_time_step /*= 1.0f / 60.0f */ )
78{
79        return SELF->stepSimulation( dtime, max_sub_steps, fixed_time_step );
80}
81
82collision_shape bullet_world::create_sphere( float radius )
83{
84        return collision_shape{ ( void* )new btSphereShape( radius ) };
85}
86
87nv::collision_shape nv::bullet_world::create_capsule( float radius, float height )
88{
89        return collision_shape{ ( void* )new btCapsuleShape( radius, height ) };
90}
91
92nv::collision_shape nv::bullet_world::create_cylinder( const vec3& half_extents )
93{
94        return collision_shape{ ( void* )new btCylinderShape( n2b( half_extents ) ) };
95}
96
97collision_shape bullet_world::create_box( const vec3& half_extens )
98{
99        return collision_shape{ ( void* )new btBoxShape( n2b( half_extens ) ) };
100}
101
102collision_shape bullet_world::create_static_plane( const vec3& norm, float cst )
103{
104        return collision_shape{ ( void* )new btStaticPlaneShape( n2b( norm ), cst ) };
105}
106
107void bullet_world::add_rigid_body( rigid_body body )
108{
109        SELF->addRigidBody( static_cast<btRigidBody*>( body.internal ) );
110}
111
112rigid_body bullet_world::create_rigid_body( float mass, const transform& tr, collision_shape shape, const vec3& com_offset )
113{
114        btCollisionShape* sh = static_cast<btCollisionShape*>( shape.internal );
115        bool is_dynamic = ( mass != 0.f );
116
117        btVector3 local_inertia( 0, 0, 0 );
118        if ( is_dynamic )
119                sh->calculateLocalInertia( mass, local_inertia );
120
121        motion_state* ms = new motion_state( tr, nv::transform( com_offset ) );
122
123        btRigidBody::btRigidBodyConstructionInfo rb_info( mass, ms, sh, local_inertia );
124        btRigidBody* body = new btRigidBody( rb_info );
125        return rigid_body{ body };
126}
127
128nv::collision_shape nv::bullet_world::create_mesh( array_view< vec3 > vtx, array_view< uint32 > idx )
129{
130        btTriangleMesh* mesh = new btTriangleMesh;
131        for ( uint32 i = 0; i < idx.size() / 3; ++i )
132        {
133                mesh->addTriangle( n2b( vtx[idx[i * 3+0]] ), n2b(vtx[idx[i * 3+1]]), n2b( vtx[idx[i * 3+ 2]] ) );
134        }
135
136//      btTriangleIndexVertexArray* array = new btTriangleIndexVertexArray( idx.size() / 3, (int*)idx.data(), 3 * sizeof(int), vtx.size(), (float*)vtx.data(), sizeof(vtx) );
137        btBvhTriangleMeshShape* shape = new btBvhTriangleMeshShape( mesh, true );
138//      shape->buildOptimizedBvh();
139        return collision_shape{ shape, nullptr };
140}
141
142void nv::bullet_world::set_local_scaling( collision_shape shape, const vec3& value )
143{
144        btCollisionShape* sh = static_cast<btCollisionShape*>( shape.internal );
145        sh->setLocalScaling( n2b( value ) );
146}
147
148vec3 nv::bullet_world::get_local_scaling( collision_shape shape )
149{
150        btCollisionShape* sh = static_cast<btCollisionShape*>( shape.internal );
151        return b2n( sh->getLocalScaling() );
152}
153
154constraint nv::bullet_world::create_hinge_constraint( rigid_body a, const transform& ta, rigid_body b, const transform& tb, const vec2& low_high, const vec3& params /*= vec3( 0.9f, 0.3f, 1.0f ) */ )
155{
156        btRigidBody* rba = static_cast<btRigidBody*>( a.internal );
157        btRigidBody* rbb = static_cast<btRigidBody*>( b.internal );
158        btHingeConstraint* hinge = new btHingeConstraint( *rba, *rbb, n2b( ta ), n2b( tb ) );
159        hinge->setLimit( low_high.x, low_high.y, params.x, params.y, params.z );
160        return constraint{ hinge };
161}
162
163constraint nv::bullet_world::create_cone_twist_constraint( rigid_body a, const transform& ta, rigid_body b, const transform& tb, const vec3& sst, const vec3& params /*= vec3( 1.0f, 0.3f, 1.0f ) */ )
164{
165        btRigidBody* rba = static_cast<btRigidBody*>( a.internal );
166        btRigidBody* rbb = static_cast<btRigidBody*>( b.internal );
167        btConeTwistConstraint* cone_twist = new btConeTwistConstraint( *rba, *rbb, n2b( ta ), n2b( tb ) );
168        cone_twist->setLimit( sst.x, sst.y, sst.z, params.x, params.y, params.z );
169        return constraint{ cone_twist };
170}
171
172void nv::bullet_world::remove_rigid_body( rigid_body body )
173{
174        SELF->removeRigidBody( static_cast<btRigidBody*>( body.internal ) );
175}
176
177void nv::bullet_world::add_constraint( constraint cons )
178{
179        SELF->addConstraint( static_cast<btTypedConstraint*>( cons.internal ), true );
180}
181
182void nv::bullet_world::set_rigid_body_damping( rigid_body body, float linear, float angular )
183{
184        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
185        rb->setDamping( linear, angular );
186}
187
188void nv::bullet_world::set_rigid_body_deactivation_time( rigid_body body, float time )
189{
190        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
191        rb->setDeactivationTime( time );
192}
193
194void nv::bullet_world::set_rigid_body_activation_state( rigid_body body, activation_state state )
195{
196        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
197        rb->setActivationState( state );
198}
199
200void nv::bullet_world::set_rigid_body_sleeping_thresholds( rigid_body body, float linear, float angular )
201{
202        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
203        rb->setSleepingThresholds( linear, angular );
204}
205
206void nv::bullet_world::set_rigid_body_linear_velocity( rigid_body body, const vec3& velocity )
207{
208        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
209        rb->setLinearVelocity( n2b( velocity ) );
210}
211
212void nv::bullet_world::set_rigid_body_ccd( rigid_body body, float radius, float threshold )
213{
214        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
215        rb->setCcdMotionThreshold( threshold );
216        rb->setCcdSweptSphereRadius( radius );
217}
218
219vec3 nv::bullet_world::get_rigid_body_linear_velocity( rigid_body body )
220{
221        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
222        return b2n( rb->getLinearVelocity() );
223}
224
225void nv::bullet_world::apply_central_impulse( rigid_body body, const vec3& impulse )
226{
227        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
228        rb->applyCentralImpulse( n2b( impulse ) );
229        rb->forceActivationState( ACTIVE_TAG );
230}
231
232nv::transform nv::bullet_world::get_world_transform( rigid_body body )
233{
234        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
235        return static_cast<motion_state*>( rb->getMotionState() )->get_world_transform();
236}
237
238void nv::bullet_world::set_world_transform( rigid_body body, const nv::transform& tr )
239{
240        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
241        static_cast<motion_state*>( rb->getMotionState() )->set_world_transform( tr );
242}
243
244int nv::bullet_world::get_collision_flags( rigid_body body )
245{
246        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
247        return rb->getCollisionFlags();
248}
249
250void nv::bullet_world::set_collision_flags( rigid_body body, int flags )
251{
252        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
253        return rb->setCollisionFlags( flags );
254}
255
256class ClosestStaticRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
257{
258public:
259        ClosestStaticRayResultCallback( const btVector3& from, const btVector3&  to ) : btCollisionWorld::ClosestRayResultCallback( from, to ) {}
260
261        virtual btScalar addSingleResult( btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace )
262        {
263                if ( !rayResult.m_collisionObject->isStaticObject() )
264                        return 1.0;
265
266                return ClosestRayResultCallback::addSingleResult( rayResult, normalInWorldSpace );
267        }
268};
269
270
271bool nv::bullet_world::ray_test( const vec3& from, const vec3& to, vec3& hpos, vec3& hnorm, bool static_only )
272{
273        btVector3 bfrom( n2b( from ) );
274        btVector3 bto( n2b( to ) );
275        if ( !static_only )
276        {
277                btCollisionWorld::ClosestRayResultCallback raycb( bfrom, bto );
278                SELF->rayTest( bfrom, bto, raycb );
279                bool result = false;
280                if ( raycb.hasHit() )
281                {
282                        result = true;
283                        hpos = b2n( raycb.m_hitPointWorld );
284                        hnorm = b2n( raycb.m_hitNormalWorld );
285                }
286                return result;
287        }
288        else
289        {
290                ClosestStaticRayResultCallback raycb( bfrom, bto );
291                SELF->rayTest( bfrom, bto, raycb );
292                bool result = false;
293                if ( raycb.hasHit() )
294                {
295                        result = true;
296                        hpos = b2n( raycb.m_hitPointWorld );
297                        hnorm = b2n( raycb.m_hitNormalWorld );
298                }
299                return result;
300        }
301}
302
303void bullet_world::release( collision_shape sh )
304{
305        if ( !sh.internal ) return;
306        if ( sh.mesh )
307        {
308                btStridingMeshInterface* smi = static_cast<btStridingMeshInterface*>( sh.mesh );
309                delete smi;
310        }
311
312        btCollisionShape* cs = static_cast<btCollisionShape*>( sh.internal );
313        delete cs;
314
315}
316
317void bullet_world::release( constraint c )
318{
319        if ( !c.internal ) return;
320        btTypedConstraint* tc = static_cast<btTypedConstraint*>( c.internal );
321        SELF->removeConstraint( tc );
322        delete tc;
323}
324
325void bullet_world::release( rigid_body body )
326{
327        if ( !body.internal ) return;
328        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
329        SELF->removeRigidBody( rb );
330        delete rb;
331}
Note: See TracBrowser for help on using the repository browser.