modifying the height of a cylinder

Post Reply
ed_welch
Posts: 43
Joined: Wed Mar 04, 2015 6:16 pm

modifying the height of a cylinder

Post by ed_welch »

Hi,
Is there anyway to update the height of a cylinder?
The only way I could figure out how to do it is deleting the old shape and creating a new one, but that is a pretty inefficient way to do it - I mean it's going to cause memory fragmentation.
This is how I do it at the moment:

Code: Select all

	btCylinderShapeZ* pCylinder = new btCylinderShapeZ(btVector3(radius, radius, height));
	m_pBody->setCollisionShape(pCylinder);
	if (m_pCylinder) delete m_pCylinder;
	m_pCylinder = pCylinder;
	g_physics.GetWorld()->updateAabbs();
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: modifying the height of a cylinder

Post by drleviathan »

The short answer is: You could derive your own CustomCylinderShape class from btCylinderShapeZ to provide the functionality that you want. It will all work fine as long as you handle the complications correctly (see long answer below).

The long answer is more complicated, but if you are really concerned about memory fragmentation then you can hop these hoops.

Looking at the documentation we discover that btCylinderShape derives from btConvexInternalShape. After examining the code we learn that btCylinderShape is storing most of its length in btConvexInternalShape::m_implicitShapeDimensions. There is a method called btConvexInternalShape::setImplicitShapeDimensions() however there are also some comments there about how you want to be careful when using it -- not only do you want to update the world Aabb's, but you also need to flush relevant contact points.

Not mentioned in those comments is the fact that the "shape dimensions" have had the "margin" subtracted from from them. The value of the margin can be explicitly overridden, but its default value is a function of the shape's dimensions when it is created. So, if you want to change the effective dimensions of a cylinder you may need to recompute both margin and implicit shape dimensions -- this is the logic you would have to implement in your CustomCylinderShape class.

Dunno exactly what you're doing with cylinders, but if you have lots of them, plenty of memory available, and you're changing their lengths frequently you might consider using a "shape manager factory" class that instantiates shapes, keeps track of all instances and their ref counts, and does delayed garbage collection of unused shapes.
ed_welch
Posts: 43
Joined: Wed Mar 04, 2015 6:16 pm

Re: modifying the height of a cylinder

Post by ed_welch »

drleviathan wrote:The short answer is: You could derive your own CustomCylinderShape class from btCylinderShapeZ to provide the functionality that you want. It will all work fine as long as you handle the complications correctly (see long answer below).

The long answer is more complicated, but if you are really concerned about memory fragmentation then you can hop these hoops.

Looking at the documentation we discover that btCylinderShape derives from btConvexInternalShape. After examining the code we learn that btCylinderShape is storing most of its length in btConvexInternalShape::m_implicitShapeDimensions. There is a method called btConvexInternalShape::setImplicitShapeDimensions() however there are also some comments there about how you want to be careful when using it -- not only do you want to update the world Aabb's, but you also need to flush relevant contact points.

Not mentioned in those comments is the fact that the "shape dimensions" have had the "margin" subtracted from from them. The value of the margin can be explicitly overridden, but its default value is a function of the shape's dimensions when it is created. So, if you want to change the effective dimensions of a cylinder you may need to recompute both margin and implicit shape dimensions -- this is the logic you would have to implement in your CustomCylinderShape class.

Dunno exactly what you're doing with cylinders, but if you have lots of them, plenty of memory available, and you're changing their lengths frequently you might consider using a "shape manager factory" class that instantiates shapes, keeps track of all instances and their ref counts, and does delayed garbage collection of unused shapes.
Thanks for the answer. I think I got it now. This is what I do:

Code: Select all

void ECylinder::setDimensions(float radius, float height)
{
	btVector3 halfExtents(radius, radius, height);
	setSafeMargin(halfExtents);
	btVector3 margin(getMargin(),getMargin(),getMargin());
	m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
}

g_physics.GetWorld()->removeRigidBody(m_pBody);
m_pCylinder->setDimensions(radius, height);
g_physics.GetWorld()->addRigidBody(m_pBody);

Post Reply