Hi all. I have what I think should be an easy question. How do I create polyhedrons in Bullet that aren't boxes? I'm trying to build a physics approximation of some complex geometry and it would be helpful to be able to make shapes like the one I've included (a hexahedron).
Apologies if I've missed something obvious; I didn't see anything in the demos I checked out or via a quick forum search. Oh, and if you don't mind including code (or pointing me to demo code), I'd appreciate it.
Thanks!
Creating non-rectangular shapes w/ >4 sides
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Creating non-rectangular shapes w/ >4 sides
You do not have the required permissions to view the files attached to this post.
-
- Posts: 149
- Joined: Fri May 24, 2013 6:08 am
Re: Creating non-rectangular shapes w/ >4 sides
There's a snippet on building trimeshes here:
http://bulletphysics.org/mediawiki-1.5. ... e_Snippets
http://bulletphysics.org/mediawiki-1.5. ... e_Snippets
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Re: Creating non-rectangular shapes w/ >4 sides
Thanks for that! I'll play around with it and see if it gives what I need. In the meantime, any other suggestions are welcome.
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Re: Creating non-rectangular shapes w/ >4 sides
The method posted above seems to work, but I think I'm doing something wrong somewhere because I can't get my shape to work if it's not static. I just stuck it into AppBasicDemo like this:
When the object is static, it works okay and shows up like in the picture. When it is dynamic, though, it crashes. Debugging shows that the problem is in btTriangleMeshShape.cpp here:
Based on where it kicked me out, I'm guessing it thinks my shape is concave. But... it shouldn't be, right? What's going on here?
Code: Select all
//Triangle mesh hexahedron
btTriangleMesh *mTriMesh = new btTriangleMesh();
// For whatever your source of triangles is
// give the three points of each triangle:
//1
btVector3 v0(0,0,0);
btVector3 v1(0,0,.5);
btVector3 v2(-.25,0,0);
mTriMesh->addTriangle(v0,v1,v2);
//2
v0.setValue(-.25,0,.5);
mTriMesh->addTriangle(v0,v1,v2);
//3
v1.setValue(-.5,0,0);
mTriMesh->addTriangle(v0,v1,v2);
//4
v2.setValue(-.25,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//5
v0.setValue(-.5,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//6
v1.setValue(-.25,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//7
v0.setValue(0,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//8
v2.setValue(0,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//9
v1.setValue(-.25,-.15,.5);
v2.setValue(0,0,.5);
mTriMesh->addTriangle(v0,v1,v2);
//10
v0.setValue(-.25,0,.5);
mTriMesh->addTriangle(v0,v1,v2);
//11
v1.setValue(0,0,0);
v0.setValue(0,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//12
v2.setValue(0,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//13
v0.setValue(-.5,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//14
v2.setValue(-.5,0,0);
mTriMesh->addTriangle(v0,v1,v2);
btCollisionShape *mTriMeshShape = new btBvhTriangleMeshShape(mTriMesh,true);
//if(mass != 0.0) //attempted mass of 1
//{
// mTriMeshShape->calculateLocalInertia(mass,inertia);
//}
btTrans.setOrigin(btVector3(0,3,0));
btDefaultMotionState* triMotionState = new btDefaultMotionState(btTrans);
btRigidBody::btRigidBodyConstructionInfo hexCI(0,triMotionState,mTriMeshShape); //static like this works
btRigidBody* hexRigidBody = new btRigidBody(hexCI);
hexRigidBody->setContactProcessingThreshold(BT_LARGE_FLOAT); //don't really know what this does; stole it from DemoApplication and seems to have no effect
m_dynamicsWorld->addRigidBody(hexRigidBody);
hexRigidBody->setCollisionFlags(hexRigidBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); //Makes boxes use the custom callback function
Code: Select all
void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
(void)mass;
//moving concave objects not supported
btAssert(0);
inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
}
You do not have the required permissions to view the files attached to this post.
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Re: Creating non-rectangular shapes w/ >4 sides
Well, I found some problems with my self-determined triangle mesh, so I modified it a bit. This makes me really wish I knew how to get the mesh from the proprietary software I'm using... even getting the vertexes from 12 triangles is a pain! I made the changes below, but it still crashes in the same place when I attempt to make the shape dynamic.
Is what I'm trying to do not possible, or am I making a mistake somewhere (probably much more likely)?
Code: Select all
//1 - verified
btVector3 v0(0,0,0);
btVector3 v1(0,0,.5);
btVector3 v2(-.5,0,0);
mTriMesh->addTriangle(v0,v1,v2);
//2 - verified
v0.setValue(-.25,0,.5);
mTriMesh->addTriangle(v0,v1,v2);
//3 - verified
v1.setValue(-.5,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//4 - verified
v2.setValue(-.25,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//5 - verified
v0.setValue(0,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//6 - verified
v1.setValue(0,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//7 - verified
v0.setValue(0,0,.5);
v1.setValue(-.25,0,.5);
mTriMesh->addTriangle(v0,v1,v2);
//8 - verified
v1.setValue(0,-.15,.5);
mTriMesh->addTriangle(v0,v1,v2);
//9 - verified
v2.setValue(0,0,0);
mTriMesh->addTriangle(v0,v1,v2);
//10 - verified
v0.setValue(0,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
//11 - verified
v1.setValue(-.5,0,0);
mTriMesh->addTriangle(v0,v1,v2);
//12
v2.setValue(-.5,-.15,0);
mTriMesh->addTriangle(v0,v1,v2);
-
- Posts: 43
- Joined: Sat May 26, 2012 1:09 am
Re: Creating non-rectangular shapes w/ >4 sides
btBvhTriangleMeshShape is for static meshes; GImpact can be used for dynamic meshes:
http://bulletphysics.org/Bullet/BulletF ... Shape.html
If the shapes are convex, it may also be worth looking at the btConvexHullShape:
http://bulletphysics.org/Bullet/BulletF ... Shape.html
http://bulletphysics.org/Bullet/BulletF ... Shape.html
If the shapes are convex, it may also be worth looking at the btConvexHullShape:
http://bulletphysics.org/Bullet/BulletF ... Shape.html
-
- Posts: 456
- Joined: Tue Dec 25, 2007 1:06 pm
Re: Creating non-rectangular shapes w/ >4 sides
A btConvexHullShape best fits any convex polygon in Bullet: IMO you should use it.
Additionally, it's easier: you just need to pass in your (8?) vertices
But remember that the center of mass of the object is vertex (0,0,0)! (So you may need to perform a shift operation on your vertices).
Additionally, it's easier: you just need to pass in your (8?) vertices
But remember that the center of mass of the object is vertex (0,0,0)! (So you may need to perform a shift operation on your vertices).
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Re: Creating non-rectangular shapes w/ >4 sides
Thanks, guys! I managed to build my dynamic hexahedron using btConvexHullShape. The center of gravity thing is kind of annoying, though... that's going to make placing my objects a headache. Do you know of any way to get Bullet to calculate a new center of gravity so I don't have to figure it out for myself every time I create a shape this way?
I'm including the code I used in case it is helpful to anyone else searching the forums (or for improvement suggestions, of course ).
I'm including the code I used in case it is helpful to anyone else searching the forums (or for improvement suggestions, of course ).
Code: Select all
//convexhull hexahedron
btVector3 verts[8] = {
btVector3(0,0,0),
btVector3(-.5,0,0),
btVector3(-.5,-.15,0),
btVector3(0,-.15,0),
btVector3(0,0,.5),
btVector3(0,-.15,.5),
btVector3(-.25,-.15,.5),
btVector3(-.25,0,.5)
};
btVector3 shift = btVector3(-.1875,-.075,.25); //not exact, just a test to get the COM inside the shape
btConvexHullShape * hexShape = new btConvexHullShape();
for(int i = 0; i<8; i++)
{
verts[i] = verts[i] - shift; //should center the hexahedron (roughly) around (0,0,0)
hexShape->addPoint(verts[i]);
}
if(mass != 0.0) //inertia only needs to be calculated for non-static objects, and mass = 0 objects are static in Bullet
{
hexShape->calculateLocalInertia(mass,inertia);
}
btTrans.setOrigin(btVector3(0,3,0));
btDefaultMotionState* hexMotionState = new btDefaultMotionState(btTrans);
btRigidBody::btRigidBodyConstructionInfo hexCI(mass,hexMotionState,hexShape,inertia);
btRigidBody* hexRigidBody = new btRigidBody(hexCI);
hexRigidBody->setContactProcessingThreshold(BT_LARGE_FLOAT);
m_dynamicsWorld->addRigidBody(hexRigidBody);
hexRigidBody->setCollisionFlags(hexRigidBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); //Makes boxes use the custom callback function
You do not have the required permissions to view the files attached to this post.
-
- Posts: 48
- Joined: Thu Dec 12, 2013 4:04 pm
Re: Creating non-rectangular shapes w/ >4 sides
I found this thread after some searching http://www.bulletphysics.org/Bullet/php ... shift+demo and tried to cannibalize the relevant parts in the hopes that I could get Bullet to figure out the center of mass for me:
Unfortunately, this doesn't seem to work, at least not as I've implemented it. The shape still behaves as if all of the mass is located at the corner (0,0,0), giving it really wonky motion. Can anyone see what I've done wrong?
Thanks again for all of the guidance so far.
Code: Select all
//convexhull hexahedron (not centered on the origin)
btVector3 verts[8] = {
btVector3(0,0,0),
btVector3(-.5,0,0),
btVector3(-.5,-.15,0),
btVector3(0,-.15,0),
btVector3(0,0,.5),
btVector3(0,-.15,.5),
btVector3(-.25,-.15,.5),
btVector3(-.25,0,.5)
};
//this shape will be the hexahedron
btConvexHullShape * hexShape = new btConvexHullShape();
for(int i = 0; i<8; i++)
{
hexShape->addPoint(verts[i]);
}
//make a compound shape for use of calculatePrincipalAxisTransform
btCompoundShape* hexCompound = new btCompoundShape();
btTransform hexLocalTrans;
hexLocalTrans.setIdentity();
//add the off-center hull shape to the compound shape
hexCompound->addChildShape(hexLocalTrans, hexShape);
btTransform principal;
btVector3 principalInertia;
//if I had multiple shapes in the compound, this would handle them
btScalar* masses = new btScalar[hexCompound->getNumChildShapes()];
for (int j=0;j<hexCompound->getNumChildShapes();j++)
{
//evenly distribute mass
masses[j]=mass/hexCompound->getNumChildShapes();
}
hexCompound->calculatePrincipalAxisTransform(masses,principal,principalInertia);
btCompoundShape* newHexCompound = new btCompoundShape();
for (int i=0;i<hexCompound->getNumChildShapes();i++)
{
btTransform newChildTransform = principal.inverse()*hexCompound->getChildTransform(i);
newHexCompound->addChildShape(newChildTransform,hexCompound->getChildShape(i));
}
//hexShape->initializePolyhedralFeatures(); //seems to sharpen the shape but leave an annoying invisible border
if(mass != 0.0)
{
newHexCompound->calculateLocalInertia(mass,inertia);
}
btTrans.setOrigin(btVector3(0,3,0));
btDefaultMotionState* hexMotionState = new btDefaultMotionState(btTrans);
btRigidBody::btRigidBodyConstructionInfo hexCI(mass,hexMotionState,newHexCompound,inertia);
btRigidBody* hexRigidBody = new btRigidBody(hexCI);
hexRigidBody->setContactProcessingThreshold(BT_LARGE_FLOAT);
m_dynamicsWorld->addRigidBody(hexRigidBody);
Thanks again for all of the guidance so far.