so I'm quite new to Bullet but really like what you created here.
I tried to import two .stl files and get the minimum distance between these two meshes.
The problem is, the position of the mesh. So while the shape has its absolut positions, once I apply the shape to a rigid body I have to give it a motionState and therefore a transform with an origin. As a result, the two bodies are on the same position and not as they have been placed in the absolut stl coordinates (or am I wrong?) . Is there maybe another solution to get the closesed distance of two meshes?
Also I did not implement the debug drawer yet, maybe someone can point me in the right direction where to find an easy to copy example? (Wiki is not working anymore )
My code:
Code: Select all
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "btBulletDynamicsCommon.h"
struct MySTLTriangle
{
float normal[3];
float vertex0[3];
float vertex1[3];
float vertex2[3];
};
struct MyContactResultCallback : public btCollisionWorld::ContactResultCallback
{
bool m_connected;
btScalar m_margin;
MyContactResultCallback() : m_connected(false), m_margin(0.05)
{
}
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1)
{
std::cout << "Distance: " << cp.getDistance() << std::endl;
if (cp.getDistance() <= m_margin)
m_connected = true;
return 1.f;
}
};
int main() {
std::cout << "Hello, World!" << std::endl;
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface *overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver *solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld
*dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
///-----initialization_end-----
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape *> collisionShapes;
///create a few basic rigid bodies
btCollisionObject motor;
btTriangleMesh tetraMesh;
//read all vertices of the triangles from the stl file
std::ifstream stlInput ("motor.stl");
std::string line;
while(std::getline(stlInput, line)){
std::istringstream iss(line);
float vertex1, vertex2, vertex3;
std::string tag;
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec1 = btVector3(vertex1, vertex2, vertex3);
std::getline(stlInput, line);
iss.str(line);
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec2 = btVector3(vertex1, vertex2, vertex3);
std::getline(stlInput, line);
iss.str(line);
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec3 = btVector3(vertex1, vertex2, vertex3);
tetraMesh.addTriangle(vec1, vec2, vec3);
}
btConvexTriangleMeshShape *tetraShape = new btConvexTriangleMeshShape(&tetraMesh, false);
collisionShapes.push_back(tetraShape);
motor.setCollisionShape(tetraShape);
btVector3 localInertia(0, 0, 0);
btTransform trans;
trans.setIdentity();
motor.setWorldTransform(trans);
btDefaultMotionState *motionState = new btDefaultMotionState(trans);
btRigidBody *body = new btRigidBody(1, motionState, tetraShape, localInertia);
dynamicsWorld->addRigidBody(body);
/// --------------------------
btCollisionObject screw;
btTriangleMesh tetraScrew;
//read all vertices of the triangles from the stl file
std::ifstream stlInputScrew ("screw1.stl");
std::string lineScrew;
while(std::getline(stlInputScrew, lineScrew)){
std::istringstream iss(lineScrew);
float vertex1, vertex2, vertex3;
std::string tag;
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec1 = btVector3(vertex1, vertex2, vertex3);
std::getline(stlInput, lineScrew);
iss.str(lineScrew);
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec2 = btVector3(vertex1, vertex2, vertex3);
std::getline(stlInput, lineScrew);
iss.str(lineScrew);
if (!(iss >> tag >> vertex1 >> vertex2 >> vertex3) || tag != "vertex") {continue;}
auto vec3 = btVector3(vertex1, vertex2, vertex3);
tetraScrew.addTriangle(vec1, vec2, vec3);
}
btConvexTriangleMeshShape *tetraShapeScrew = new btConvexTriangleMeshShape(&tetraScrew, false);
collisionShapes.push_back(tetraShapeScrew);
screw.setCollisionShape(tetraShapeScrew);
btVector3 localInertiaScrew(0, 0, 0);
btTransform transScrew;
transScrew.setIdentity();
screw.setWorldTransform(transScrew);
btDefaultMotionState *motionStateScrew = new btDefaultMotionState(transScrew);
btRigidBody *bodyScrew = new btRigidBody(1, motionStateScrew, tetraShapeScrew, localInertiaScrew);
dynamicsWorld->addRigidBody(bodyScrew);
MyContactResultCallback result;
dynamicsWorld->contactPairTest(&motor, &screw, result);
std::string connected = "False";
if(result.m_connected) connected = "True";
std::cout << "Connected? " << connected << std::endl;
return 0;
}