2015-05-12 01:02:15 +00:00
# include "bulletshapemanager.hpp"
2015-11-16 23:18:27 +00:00
# include <osg/NodeVisitor>
# include <osg/TriangleFunctor>
2016-03-13 23:32:32 +00:00
# include <osg/Transform>
# include <osg/Drawable>
2015-11-16 23:18:27 +00:00
# include <BulletCollision/CollisionShapes/btTriangleMesh.h>
2021-09-11 13:49:47 +00:00
# include <components/misc/pathhelpers.hpp>
2021-02-03 12:25:09 +00:00
# include <components/sceneutil/visitor.hpp>
2015-05-12 01:02:15 +00:00
# include <components/vfs/manager.hpp>
# include <components/nifbullet/bulletnifloader.hpp>
2015-11-16 22:30:10 +00:00
# include "bulletshape.hpp"
2015-11-16 23:18:27 +00:00
# include "scenemanager.hpp"
2015-12-01 22:04:02 +00:00
# include "niffilemanager.hpp"
2016-02-05 22:59:37 +00:00
# include "objectcache.hpp"
2016-02-09 17:48:49 +00:00
# include "multiobjectcache.hpp"
2015-11-16 22:30:10 +00:00
namespace Resource
2015-05-12 01:02:15 +00:00
{
2015-11-16 23:18:27 +00:00
struct GetTriangleFunctor
{
GetTriangleFunctor ( )
2018-10-09 06:21:12 +00:00
: mTriMesh ( nullptr )
2015-11-16 23:18:27 +00:00
{
}
void setTriMesh ( btTriangleMesh * triMesh )
{
mTriMesh = triMesh ;
}
void setMatrix ( const osg : : Matrixf & matrix )
{
mMatrix = matrix ;
}
inline btVector3 toBullet ( const osg : : Vec3f & vec )
{
return btVector3 ( vec . x ( ) , vec . y ( ) , vec . z ( ) ) ;
}
2021-10-13 14:12:47 +00:00
void inline operator ( ) ( const osg : : Vec3 & v1 , const osg : : Vec3 & v2 , const osg : : Vec3 & v3 , bool _temp = false ) // Note: unused temp argument left here for OSG versions less than 3.5.6
2015-11-16 23:18:27 +00:00
{
if ( mTriMesh )
mTriMesh - > addTriangle ( toBullet ( mMatrix . preMult ( v1 ) ) , toBullet ( mMatrix . preMult ( v2 ) ) , toBullet ( mMatrix . preMult ( v3 ) ) ) ;
}
btTriangleMesh * mTriMesh ;
osg : : Matrixf mMatrix ;
} ;
/// Creates a BulletShape out of a Node hierarchy.
class NodeToShapeVisitor : public osg : : NodeVisitor
{
public :
NodeToShapeVisitor ( )
: osg : : NodeVisitor ( TRAVERSE_ALL_CHILDREN )
2017-10-15 15:03:11 +00:00
, mTriangleMesh ( nullptr )
2015-11-16 23:18:27 +00:00
{
}
2020-10-16 18:18:54 +00:00
void apply ( osg : : Drawable & drawable ) override
2015-11-16 23:18:27 +00:00
{
if ( ! mTriangleMesh )
2017-10-15 15:03:11 +00:00
mTriangleMesh . reset ( new btTriangleMesh ) ;
2015-11-16 23:18:27 +00:00
osg : : Matrixf worldMat = osg : : computeLocalToWorld ( getNodePath ( ) ) ;
osg : : TriangleFunctor < GetTriangleFunctor > functor ;
2017-10-15 15:03:11 +00:00
functor . setTriMesh ( mTriangleMesh . get ( ) ) ;
2015-11-16 23:18:27 +00:00
functor . setMatrix ( worldMat ) ;
drawable . accept ( functor ) ;
}
osg : : ref_ptr < BulletShape > getShape ( )
{
2015-11-17 00:51:21 +00:00
if ( ! mTriangleMesh )
return osg : : ref_ptr < BulletShape > ( ) ;
2015-11-16 23:18:27 +00:00
osg : : ref_ptr < BulletShape > shape ( new BulletShape ) ;
2021-10-30 01:38:38 +00:00
auto triangleMeshShape = std : : make_unique < TriangleMeshShape > ( mTriangleMesh . release ( ) , true ) ;
2021-01-30 14:03:02 +00:00
btVector3 aabbMin = triangleMeshShape - > getLocalAabbMin ( ) ;
btVector3 aabbMax = triangleMeshShape - > getLocalAabbMax ( ) ;
2021-10-27 23:43:25 +00:00
shape - > mCollisionBox . mExtents [ 0 ] = ( aabbMax [ 0 ] - aabbMin [ 0 ] ) / 2.0f ;
shape - > mCollisionBox . mExtents [ 1 ] = ( aabbMax [ 1 ] - aabbMin [ 1 ] ) / 2.0f ;
shape - > mCollisionBox . mExtents [ 2 ] = ( aabbMax [ 2 ] - aabbMin [ 2 ] ) / 2.0f ;
shape - > mCollisionBox . mCenter = osg : : Vec3f ( ( aabbMax [ 0 ] + aabbMin [ 0 ] ) / 2.0f ,
2021-01-30 14:03:02 +00:00
( aabbMax [ 1 ] + aabbMin [ 1 ] ) / 2.0f ,
( aabbMax [ 2 ] + aabbMin [ 2 ] ) / 2.0f ) ;
2021-10-30 01:38:38 +00:00
shape - > mCollisionShape . reset ( triangleMeshShape . release ( ) ) ;
2021-01-30 14:03:02 +00:00
2015-11-16 23:18:27 +00:00
return shape ;
}
private :
2017-10-15 15:03:11 +00:00
std : : unique_ptr < btTriangleMesh > mTriangleMesh ;
2015-11-16 23:18:27 +00:00
} ;
2015-12-01 22:04:02 +00:00
BulletShapeManager : : BulletShapeManager ( const VFS : : Manager * vfs , SceneManager * sceneMgr , NifFileManager * nifFileManager )
2016-02-06 15:57:54 +00:00
: ResourceManager ( vfs )
2016-02-09 17:48:49 +00:00
, mInstanceCache ( new MultiObjectCache )
2015-11-16 23:18:27 +00:00
, mSceneManager ( sceneMgr )
2015-12-01 22:04:02 +00:00
, mNifFileManager ( nifFileManager )
2015-05-12 01:02:15 +00:00
{
}
BulletShapeManager : : ~ BulletShapeManager ( )
{
}
2016-02-06 22:30:41 +00:00
osg : : ref_ptr < const BulletShape > BulletShapeManager : : getShape ( const std : : string & name )
2015-05-12 01:02:15 +00:00
{
2021-09-06 20:01:41 +00:00
const std : : string normalized = mVFS - > normalizeFilename ( name ) ;
2015-05-12 01:02:15 +00:00
osg : : ref_ptr < BulletShape > shape ;
2016-02-05 22:59:37 +00:00
osg : : ref_ptr < osg : : Object > obj = mCache - > getRefFromObjectCache ( normalized ) ;
if ( obj )
shape = osg : : ref_ptr < BulletShape > ( static_cast < BulletShape * > ( obj . get ( ) ) ) ;
else
2015-05-12 01:02:15 +00:00
{
2021-09-11 13:49:47 +00:00
if ( Misc : : getFileExtension ( normalized ) = = " nif " )
2015-11-16 23:18:27 +00:00
{
NifBullet : : BulletNifLoader loader ;
2018-07-08 19:22:34 +00:00
shape = loader . load ( * mNifFileManager - > get ( normalized ) ) ;
2015-11-16 23:18:27 +00:00
}
else
{
// TODO: support .bullet shape files
osg : : ref_ptr < const osg : : Node > constNode ( mSceneManager - > getTemplate ( normalized ) ) ;
osg : : ref_ptr < osg : : Node > node ( const_cast < osg : : Node * > ( constNode . get ( ) ) ) ; // const-trickery required because there is no const version of NodeVisitor
2021-02-03 12:25:09 +00:00
// Check first if there's a custom collision node
2021-02-03 19:16:54 +00:00
unsigned int visitAllNodesMask = 0xffffffff ;
2021-02-03 12:25:09 +00:00
SceneUtil : : FindByNameVisitor nameFinder ( " Collision " ) ;
2021-02-03 19:16:54 +00:00
nameFinder . setTraversalMask ( visitAllNodesMask ) ;
nameFinder . setNodeMaskOverride ( visitAllNodesMask ) ;
2021-02-03 12:25:09 +00:00
node - > accept ( nameFinder ) ;
if ( nameFinder . mFoundNode )
{
NodeToShapeVisitor visitor ;
2021-02-03 19:16:54 +00:00
visitor . setTraversalMask ( visitAllNodesMask ) ;
visitor . setNodeMaskOverride ( visitAllNodesMask ) ;
2021-02-03 12:25:09 +00:00
nameFinder . mFoundNode - > accept ( visitor ) ;
shape = visitor . getShape ( ) ;
}
// Generate a collision shape from the mesh
2015-11-17 00:51:21 +00:00
if ( ! shape )
2021-02-03 12:25:09 +00:00
{
NodeToShapeVisitor visitor ;
node - > accept ( visitor ) ;
shape = visitor . getShape ( ) ;
if ( ! shape )
return osg : : ref_ptr < BulletShape > ( ) ;
}
2015-11-16 23:18:27 +00:00
}
2015-05-12 01:02:15 +00:00
2016-02-05 22:59:37 +00:00
mCache - > addEntryToObjectCache ( normalized , shape ) ;
2015-05-12 01:02:15 +00:00
}
2016-02-06 22:30:41 +00:00
return shape ;
}
2015-05-12 01:02:15 +00:00
2016-02-09 17:48:49 +00:00
osg : : ref_ptr < BulletShapeInstance > BulletShapeManager : : cacheInstance ( const std : : string & name )
{
2021-09-06 20:01:41 +00:00
const std : : string normalized = mVFS - > normalizeFilename ( name ) ;
2016-02-09 17:48:49 +00:00
osg : : ref_ptr < BulletShapeInstance > instance = createInstance ( normalized ) ;
2017-10-15 15:01:18 +00:00
if ( instance )
mInstanceCache - > addEntryToObjectCache ( normalized , instance . get ( ) ) ;
2016-02-09 17:48:49 +00:00
return instance ;
}
osg : : ref_ptr < BulletShapeInstance > BulletShapeManager : : getInstance ( const std : : string & name )
{
2021-09-06 20:01:41 +00:00
const std : : string normalized = mVFS - > normalizeFilename ( name ) ;
2016-02-09 17:48:49 +00:00
osg : : ref_ptr < osg : : Object > obj = mInstanceCache - > takeFromObjectCache ( normalized ) ;
if ( obj . get ( ) )
return static_cast < BulletShapeInstance * > ( obj . get ( ) ) ;
else
return createInstance ( normalized ) ;
}
2016-02-06 22:30:41 +00:00
osg : : ref_ptr < BulletShapeInstance > BulletShapeManager : : createInstance ( const std : : string & name )
{
osg : : ref_ptr < const BulletShape > shape = getShape ( name ) ;
2016-02-05 22:59:37 +00:00
if ( shape )
2021-10-30 01:16:21 +00:00
return makeInstance ( std : : move ( shape ) ) ;
return osg : : ref_ptr < BulletShapeInstance > ( ) ;
2015-05-12 01:02:15 +00:00
}
2016-02-09 17:48:49 +00:00
void BulletShapeManager : : updateCache ( double referenceTime )
{
ResourceManager : : updateCache ( referenceTime ) ;
mInstanceCache - > removeUnreferencedObjectsInCache ( ) ;
}
2017-08-21 22:58:38 +00:00
void BulletShapeManager : : clearCache ( )
{
ResourceManager : : clearCache ( ) ;
mInstanceCache - > clear ( ) ;
}
2017-03-07 03:02:06 +00:00
void BulletShapeManager : : reportStats ( unsigned int frameNumber , osg : : Stats * stats ) const
2017-02-22 01:18:18 +00:00
{
stats - > setAttribute ( frameNumber , " Shape " , mCache - > getCacheSize ( ) ) ;
stats - > setAttribute ( frameNumber , " Shape Instance " , mInstanceCache - > getCacheSize ( ) ) ;
}
2015-05-12 01:02:15 +00:00
}