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

Last change on this file since 522 was 520, checked in by epyon, 9 years ago
  • ecs updates
  • animation updates
  • ragdoll manager
  • lua has own random engine
  • several minor fixes
  • particle engine/particle group
  • shitload of other stuff
  • bullet world
File size: 9.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
92collision_shape bullet_world::create_box( const vec3& half_extens )
93{
94        return collision_shape{ ( void* )new btBoxShape( n2b( half_extens ) ) };
95}
96
97collision_shape bullet_world::create_static_plane( const vec3& norm, float cst )
98{
99        return collision_shape{ ( void* )new btStaticPlaneShape( n2b( norm ), cst ) };
100}
101
102void bullet_world::add_rigid_body( rigid_body body )
103{
104        SELF->addRigidBody( static_cast<btRigidBody*>( body.internal ) );
105}
106
107rigid_body bullet_world::create_rigid_body( float mass, const transform& tr, collision_shape shape, const vec3& com_offset )
108{
109        btCollisionShape* sh = static_cast<btCollisionShape*>( shape.internal );
110        bool is_dynamic = ( mass != 0.f );
111
112        btVector3 local_inertia( 0, 0, 0 );
113        if ( is_dynamic )
114                sh->calculateLocalInertia( mass, local_inertia );
115
116        motion_state* ms = new motion_state( tr, nv::transform( com_offset ) );
117
118        btRigidBody::btRigidBodyConstructionInfo rb_info( mass, ms, sh, local_inertia );
119        btRigidBody* body = new btRigidBody( rb_info );
120        return rigid_body{ body };
121}
122
123nv::collision_shape nv::bullet_world::create_mesh( array_view< vec3 > vtx, array_view< int > idx )
124{
125        btTriangleMesh* mesh = new btTriangleMesh;
126        for ( uint32 i = 0; i < idx.size() / 3; ++i )
127        {
128                mesh->addTriangle( n2b( vtx[idx[i * 3+0]] ), n2b(vtx[idx[i * 3+1]]), n2b( vtx[idx[i * 3+ 2]] ) );
129        }
130
131//      btTriangleIndexVertexArray* array = new btTriangleIndexVertexArray( idx.size() / 3, (int*)idx.data(), 3 * sizeof(int), vtx.size(), (float*)vtx.data(), sizeof(vtx) );
132        btBvhTriangleMeshShape* shape = new btBvhTriangleMeshShape( mesh, true );
133//      shape->buildOptimizedBvh();
134        return collision_shape{ shape, nullptr };
135}
136
137constraint 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 ) */ )
138{
139        btRigidBody* rba = static_cast<btRigidBody*>( a.internal );
140        btRigidBody* rbb = static_cast<btRigidBody*>( b.internal );
141        btHingeConstraint* hinge = new btHingeConstraint( *rba, *rbb, n2b( ta ), n2b( tb ) );
142        hinge->setLimit( low_high.x, low_high.y, params.x, params.y, params.z );
143        return constraint{ hinge };
144}
145
146constraint 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 ) */ )
147{
148        btRigidBody* rba = static_cast<btRigidBody*>( a.internal );
149        btRigidBody* rbb = static_cast<btRigidBody*>( b.internal );
150        btConeTwistConstraint* cone_twist = new btConeTwistConstraint( *rba, *rbb, n2b( ta ), n2b( tb ) );
151        cone_twist->setLimit( sst.x, sst.y, sst.z, params.x, params.y, params.z );
152        return constraint{ cone_twist };
153}
154
155void nv::bullet_world::remove_rigid_body( rigid_body body )
156{
157        SELF->removeRigidBody( static_cast<btRigidBody*>( body.internal ) );
158}
159
160void nv::bullet_world::add_constraint( constraint cons )
161{
162        SELF->addConstraint( static_cast<btTypedConstraint*>( cons.internal ), true );
163}
164
165void nv::bullet_world::set_rigid_body_damping( rigid_body body, float linear, float angular )
166{
167        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
168        rb->setDamping( linear, angular );
169}
170
171void nv::bullet_world::set_rigid_body_deactivation_time( rigid_body body, float time )
172{
173        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
174        rb->setDeactivationTime( time );
175}
176
177void nv::bullet_world::set_rigid_body_activation_state( rigid_body body, activation_state state )
178{
179        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
180        rb->setActivationState( state );
181}
182
183void nv::bullet_world::set_rigid_body_sleeping_thresholds( rigid_body body, float linear, float angular )
184{
185        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
186        rb->setSleepingThresholds( linear, angular );
187}
188
189void nv::bullet_world::set_rigid_body_linear_velocity( rigid_body body, const vec3& velocity )
190{
191        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
192        rb->setLinearVelocity( n2b( velocity ) );
193}
194
195void nv::bullet_world::set_rigid_body_ccd( rigid_body body, float radius, float threshold )
196{
197        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
198        rb->setCcdMotionThreshold( threshold );
199        rb->setCcdSweptSphereRadius( radius );
200}
201
202nv::transform nv::bullet_world::get_world_transform( rigid_body body )
203{
204        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
205        return static_cast<motion_state*>( rb->getMotionState() )->get_world_transform();
206}
207
208void nv::bullet_world::set_world_transform( rigid_body body, const nv::transform& tr )
209{
210        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
211        static_cast<motion_state*>( rb->getMotionState() )->set_world_transform( tr );
212}
213
214int nv::bullet_world::get_collision_flags( rigid_body body )
215{
216        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
217        return rb->getCollisionFlags();
218}
219
220void nv::bullet_world::set_collision_flags( rigid_body body, int flags )
221{
222        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
223        return rb->setCollisionFlags( flags );
224}
225
226class ClosestStaticRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
227{
228public:
229        ClosestStaticRayResultCallback( const btVector3& from, const btVector3&  to ) : btCollisionWorld::ClosestRayResultCallback( from, to ) {}
230
231        virtual btScalar addSingleResult( btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace )
232        {
233                if ( !rayResult.m_collisionObject->isStaticObject() )
234                        return 1.0;
235
236                return ClosestRayResultCallback::addSingleResult( rayResult, normalInWorldSpace );
237        }
238};
239
240
241bool nv::bullet_world::ray_test( const vec3& from, const vec3& to, vec3& hpos, vec3& hnorm, bool static_only )
242{
243        btVector3 bfrom( n2b( from ) );
244        btVector3 bto( n2b( to ) );
245        if ( !static_only )
246        {
247                btCollisionWorld::ClosestRayResultCallback raycb( bfrom, bto );
248                SELF->rayTest( bfrom, bto, raycb );
249                bool result = false;
250                if ( raycb.hasHit() )
251                {
252                        result = true;
253                        hpos = b2n( raycb.m_hitPointWorld );
254                        hnorm = b2n( raycb.m_hitNormalWorld );
255                }
256                return result;
257        }
258        else
259        {
260                ClosestStaticRayResultCallback raycb( bfrom, bto );
261                SELF->rayTest( bfrom, bto, raycb );
262                bool result = false;
263                if ( raycb.hasHit() )
264                {
265                        result = true;
266                        hpos = b2n( raycb.m_hitPointWorld );
267                        hnorm = b2n( raycb.m_hitNormalWorld );
268                }
269                return result;
270        }
271}
272
273void bullet_world::release( collision_shape sh )
274{
275        if ( !sh.internal ) return;
276        if ( sh.mesh );
277        {
278                btStridingMeshInterface* smi = static_cast<btStridingMeshInterface*>( sh.mesh );
279                delete smi;
280        }
281
282        btCollisionShape* cs = static_cast<btCollisionShape*>( sh.internal );
283        delete cs;
284
285}
286
287void bullet_world::release( constraint c )
288{
289        if ( !c.internal ) return;
290        btTypedConstraint* tc = static_cast<btTypedConstraint*>( c.internal );
291        SELF->removeConstraint( tc );
292        delete tc;
293}
294
295void bullet_world::release( rigid_body body )
296{
297        if ( !body.internal ) return;
298        btRigidBody* rb = static_cast<btRigidBody*>( body.internal );
299        SELF->removeRigidBody( rb );
300        delete rb;
301}
Note: See TracBrowser for help on using the repository browser.