This may be a bug, or may be not.
i use bullet2.75 and vc2005. You can reproduce my link2001 error like this:
Add preprocessor BT_USE_DOUBLE_PRECISION to appHelloWorld project, and rebuild it.
it will complain that:
Code: Select all
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btCollisionShape::getBoundingSphere(class btVector3 &,double &)const " (?getBoundingSphere@btCollisionShape@@UBEXAAVbtVector3@@AAN@Z)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual double __thiscall btCollisionShape::getAngularMotionDisc(void)const " (?getAngularMotionDisc@btCollisionShape@@UBENXZ)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual double __thiscall btCollisionShape::getContactBreakingThreshold(void)const " (?getContactBreakingThreshold@btCollisionShape@@UBENXZ)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btBoxShape::calculateLocalInertia(double,class btVector3 &)const " (?calculateLocalInertia@btBoxShape@@UBEXNAAVbtVector3@@@Z)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btSphereShape::calculateLocalInertia(double,class btVector3 &)const " (?calculateLocalInertia@btSphereShape@@UBEXNAAVbtVector3@@@Z)
So, fix it if it'is a bug, or tell me how to deal with it when i wann use DOUBLE PRECISION.
Thank you very much!
The following is my original thread, and can be ingored.
my project is a dll project, i use some code of HelloWorld.cpp,
I include the lib directory:
Code: Select all
E:\dev\physics\bullet\2.75\out\debug_dll8\libs
Code: Select all
libBulletColladaConverter_d.lib
libbulletcollision_d.lib
libbulletdynamics_d.lib
libbulletmath_d.lib
libbulletmultithreaded_d.lib
libbulletopenglsupport_d.lib
libbulletsoftbody_d.lib
libcolladadom_d.lib
libconvexdecomposition_d.lib
libGIMPACTUtils_d.lib
libglui_d.lib
libiff_d.lib
liblibxml_d.lib
Code: Select all
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btCollisionShape::getBoundingSphere(class btVector3 &,double &)const " (?getBoundingSphere@btCollisionShape@@UBEXAAVbtVector3@@AAN@Z)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual double __thiscall btCollisionShape::getAngularMotionDisc(void)const " (?getAngularMotionDisc@btCollisionShape@@UBENXZ)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual double __thiscall btCollisionShape::getContactBreakingThreshold(void)const " (?getContactBreakingThreshold@btCollisionShape@@UBENXZ)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btBoxShape::calculateLocalInertia(double,class btVector3 &)const " (?calculateLocalInertia@btBoxShape@@UBEXNAAVbtVector3@@@Z)
1>Solver.obj : error LNK2001: unresolved external symbol"public: virtual void __thiscall btSphereShape::calculateLocalInertia(double,class btVector3 &)const " (?calculateLocalInertia@btSphereShape@@UBEXNAAVbtVector3@@@Z)
Code: Select all
#include "Solver.h"
#include <iostream>
Solver* Solver::m_instance = NULL;
Solver::Solver()
{
collisionConfiguration = NULL;
dispatcher = NULL;
solver = NULL;
overlappingPairCache = NULL;
dynamicsWorld = NULL;
}
Solver::~Solver()
{
}
Solver* Solver::getInstance()
{
if(m_instance == NULL){
m_instance = new Solver();
}
return m_instance;
}
void Solver::initWorld()
{
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
dispatcher = new btCollisionDispatcher(collisionConfiguration);
///the maximum size of the collision world. Make sure objects stay within these boundaries
///Don't make the world AABB size too large, it will harm simulation quality and performance
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
int maxProxies = 1024;
overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
solver = new btSequentialImpulseConstraintSolver;
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
}
void Solver::initGround()
{
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-56,0));
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
}
void Solver::initRigidbody()
{
//create a dynamic rigidbody
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
btCollisionShape* colShape = new btSphereShape(btScalar(1.));
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(2,10,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
dynamicsWorld->addRigidBody(body);
}
void Solver::simulate(const double time, const double duration)
{
dynamicsWorld->stepSimulation(duration, 10);
}
void Solver::getTransform(const size_t bodyIndex,
double &px, double &py, double &pz,
double &rx, double &ry, double &rz, double &rw)
{
assert(bodyIndex < dynamicsWorld->getNumCollisionObjects() && bodyIndex>=0);
//print positions of all objects
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[bodyIndex];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
btVector3 position(trans.getOrigin());
btQuaternion rotation(trans.getRotation());
//output
px = position.x();
py = position.y();
pz = position.z();
rx = rotation.getX();
ry = rotation.getY();
rz = rotation.getZ();
rw = rotation.getW();
//printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
}
}
void Solver::destructALL()
{
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
for (int i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
//delete collision shapes
for (int j=0;j<collisionShapes.size();j++)
{
btCollisionShape* shape = collisionShapes[j];
collisionShapes[j] = 0;
delete shape;
}
//delete dynamics world
delete dynamicsWorld;
//delete solver
delete solver;
//delete broadphase
delete overlappingPairCache;
//delete dispatcher
delete dispatcher;
delete collisionConfiguration;
//next line is optional: it will be cleared by the destructor when the array goes out of scope
collisionShapes.clear();
}