Using btCylinderShape as a world shape

food.poison
Posts: 1
Joined: Thu Dec 30, 2010 11:19 am

Using btCylinderShape as a world shape

Post by food.poison »

Hi there,

I'm just getting my hands dirty with Bullet at the moment. What I'm trying to do is to build kind of like a pasta jar sort of world (please google image "pasta glass jar"), where a bunch of solid bodies inside the cylinder collides with each other, and I'm wondering what's the best way to create the cylinder container world.

One of the sample codes that I found uses btBoxShape, and then with a forloop with getPlaneEquation to get each sides, building the world boundary 6-sided box with btStaticPlaneShape on each side. At least that's my understanding, the following is the part of the code.

Code: Select all

btBoxShape* worldBoxShape = new btBoxShape(btVector3(10,15,10));

///create 6 planes/half spaces
for (int i = 0 ; i < 6; i++)
{
	btTransform groundTransform;
	groundTransform.setIdentity();
	groundTransform.setOrigin(btVector3(0,15,0));
	btVector4 planeEq;
	worldBoxShape->getPlaneEquation(planeEq,i);
	
	btCollisionShape* groundShape = new btStaticPlaneShape(-planeEq,planeEq[3]);
	
	... (adds the side as a world boundary)...
}
I'm wondering if I wanted cylinder-shaped boundaries, is this the sort of procedure to go about doing it? A cylinder only has 3 sides right? (one of them being the cylindrical curve)
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Using btCylinderShape as a world shape

Post by Flix »

To tell the truth, I just had a quick look at your post (without reading it all), so please forgive me if this answer is not appropriate...

An empty (i.e. concave) cylinder can be better built as a compound shape.
The base can be a simple cylinder shape, and the lateral surface can be made with convex hull shapes (or boxes too).

I remember I built a similiar shape (without the base) for this demo:http://bulletphysics.org/Bullet/phpBB3/ ... 98&start=0 (I just wanted to paste here the code for such a shape, but at the moment I can't find it; anyway you can download the whole code and look for it: it's in a simple static method as far as I remember).

Please note that (for the lateral surface) I used multiple "rows" because the base shape was a brick, but you can just use a single "row" of shapes (with the base shape height = your cylinder height, excluding the base...).

Hope it helps.

P.S. If your cylinder is static, you can exclude the (cylinder) base at all and place it on a (common) planar static surface.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Using btCylinderShape as a world shape

Post by Flix »

I've finally found the code (actually I've downloaded my demo again...), and here it it (I hope it works):

Code: Select all

// Creates a compound shaped tower centered at the ground level
static btCompoundShape* BuildTowerCompoundShape(const btVector3& brickFullDimensions=btVector3(4.0,3.0,2.0),unsigned int numRows=10,unsigned int numBricksPerRow=10,bool useConvexHullShape=true)
{
		if (numBricksPerRow<3) numBricksPerRow = 3;
		
		const btVector3 brickHalfDimensions = brickFullDimensions*btScalar(0.5);
		const btScalar h=brickFullDimensions.y(); const btScalar hh= h*0.5f;
		const btScalar l=brickFullDimensions.x(); const btScalar hl= l*0.5f; 
		const btScalar z=brickFullDimensions.z(); const btScalar hz= z*0.5f;  

		const btScalar perimeter = l*numBricksPerRow;
		const btScalar radius = perimeter/(2.0f*3.1415f) + hz;
		const btScalar elementOffsetAngle = btRadians(360.0f/numBricksPerRow);
		const btScalar floorOffsetAngleBase = elementOffsetAngle * 0.5f;
		btScalar collisionMargin(0.0);
		
		btCollisionShape* shape = NULL;
		if (!useConvexHullShape) shape = new btBoxShape(brickHalfDimensions);
		else	{
			const btScalar HL = hl + z * btTan(floorOffsetAngleBase);		

			btVector3 points[8]={
				btVector3(HL,hh,hz),
				btVector3(-HL,hh,hz),
				btVector3(hl,hh,-hz),
				btVector3(-hl,hh,-hz),

				btVector3(HL,-hh,hz),
				btVector3(-HL,-hh,hz),
				btVector3(hl,-hh,-hz),
				btVector3(-hl,-hh,-hz)				
			};
			//btConvexHullShape* chs = new btConvexHullShape(&points.x(),sizeof(points)/sizeof(points[0]));
			// /*
			btConvexHullShape* chs = new btConvexHullShape();
			for (int t=0;t<sizeof(points)/sizeof(points[0]);t++) chs->addPoint(points[t]);
			// */
			shape = chs;
			collisionMargin = 2.0f * shape->getMargin();	// ...so when using the convex hull shape we keep it into considerations (even if decreasing it probably helps)
		}
		if (!shape) return NULL;								
		
		btCompoundShape* csh = new btCompoundShape();
		
		btTransform T=btTransform::getIdentity();
		T.setOrigin(T.getOrigin()+T.getBasis().getColumn(1)*(hh+collisionMargin*0.5f));	
		btTransform T2;
		{
			for (unsigned f=0;f< numRows;f++)	{
				btScalar floorOffsetAngle = (f%2==1 ? floorOffsetAngleBase : 0.0f);
				for (unsigned t=0;t< numBricksPerRow;t++)	{
					T2=T;						
					T2.setRotation(btQuaternion(t * elementOffsetAngle+ floorOffsetAngle,0,0));//assignAY( t * elementOffsetAngle+ floorOffsetAngle );
					T2.setOrigin(T2.getOrigin()+T2.getBasis().getColumn(2)*radius);							
					// Body Creation:
					csh->addChildShape(T2,shape);
				}
				T.setOrigin(T.getOrigin()+T.getBasis().getColumn(1)*(h+collisionMargin));												
			}
		}	

		return csh;
}