I have added to my project support of Soft Body. Everything works fine, without one method. I can't update Ogre Mesh regarding to btSoftBody. Thus, my Entity isn't deformed when btSoftBody is deformed.
Code: Select all
- (id) initSoftBody:(ibWorld*)_world Entity:(iEntity*)entity Name:(NSString*)_name {
self = [super init];
if ([_world supportSoftWorld]) {
m_softBodyWorldInfo.air_density = (btScalar)1.2;
m_softBodyWorldInfo.m_gravity = _world.world->getGravity();
m_softBodyWorldInfo.m_dispatcher = _world.dispatcher;
m_softBodyWorldInfo.m_sparsesdf.Reset();
m_softBodyWorldInfo.m_broadphase = _world.broadPhase;
m_softBodyWorldInfo.m_sparsesdf.Initialize();
softBody = new BtOgre::BtOgreSoftBody(&m_softBodyWorldInfo);
Ogre::MeshPtr myMesh = entity.ent->getMesh();
MeshData MyMeshData = *(MeshUtils::getMeshData(myMesh));
unsigned long* indices = new unsigned long[MyMeshData.triangleCount*3];
MeshUtils::meshBuffersToArrays(myMesh, MyMeshData.vertices, indices);
psb = softBody->create(entity.ent,
MyMeshData.vertexCount,
MyMeshData.vertices,
MyMeshData.triangleCount*3,
(unsigned int*)indices);
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.1;
psb->m_cfg.piterations = 2;
psb->m_cfg.kDF = 0.5;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->generateClusters(0);
psb->randomizeConstraints();
psb->setTotalMass(100,true);
/*// _softBody->m_cfg.kDP = 0.001; // Damping coefficient
_softBody->m_cfg.kDF = 0.5; // Dynamic friction coefficient
// _softBody->m_cfg.kMT = 0.01; // Pose matching coefficient
// _softBody->m_cfg.kPR = 2500;
// _softBody->m_cfg.kCHR = 1; // Rigid contacts hardness
// _softBody->m_cfg.kKHR = 0.8; // Kinetic contacts hardness
// _softBody->m_cfg.kSHR = 1; // Soft contacts hardness
_softBody->m_cfg.piterations = 2; // Positions solver iterations
_softBody->m_materials[0]->m_kLST = 0.45;
btSoftBody::Material* softBodyMaterial = _softBody->appendMaterial();
softBodyMaterial->m_kLST = 0.5; // Linear stiffness coefficient
softBodyMaterial->m_kAST = 0.1; // Area/Angular stiffness coefficient
softBodyMaterial->m_kVST = 0.5; // Volume stiffness coefficient
btScalar mass(WorldMetricsHelper::kg(60));
_softBody->setTotalMass(mass, true);
// _softBody->setPose(false, true); // XXX Set current state as a pose
// _softBody->generateBendingConstraints(2, softBodyMaterial);
_softBody->randomizeConstraints();*/
psb->setUserPointer((__bridge void *)_name);
//if (typeid(_world.world) == typeid(btSoftRigidDynamicsWorld)) {
btSoftRigidDynamicsWorld *softWorld = (btSoftRigidDynamicsWorld *)_world.world;
softWorld->addSoftBody(psb);
//}
} else {
softBody = nil;
psb = nil;
}
return self;
}
- (void) update {
if (softBody)
softBody->updateOgreMesh();
}
Code: Select all
btSoftBody* BtOgreSoftBody::create(Entity *entity, const unsigned int vertexCount, const Vector3* vertexBuffer, const unsigned int indexCount, const unsigned int* indexBuffer)
{
assert(vertexCount && (indexCount >= 6) &&
("Mesh must have some vertices and at least 6 indices (2 triangles)"));
static int createCount = 0;
internalId = createCount;
createCount++;
printf("Creating softbody %d\n", internalId);
mEntity = entity;
mDupVertices = new int[vertexCount];
mNewIndexes = new int[vertexCount];
mDupVerticesCount = 0;
int i, j;
for (i = 0; i < vertexCount; i++)
{
Vector3 v1 = vertexBuffer[i];
mDupVertices[i] = -1;
mNewIndexes[i] = i - mDupVerticesCount;
for (j = 0; j < i; j++)
{
Vector3 v2 = vertexBuffer[j];
if (v1 == v2)
{
mDupVertices[i] = j;
mDupVerticesCount++;
break;
}
}
}
printf("dupVerticesCount %d\n", mDupVerticesCount);
int newVertexCount = vertexCount - mDupVerticesCount;
printf("newVertexCount %d\n", newVertexCount);
btScalar vertices[newVertexCount * 3];
for (i = 0, j = 0; i < vertexCount; i++)
{
if (mDupVertices[i] == -1)
{
Vector3 v = vertexBuffer[i];
vertices[j++] = v.x;
vertices[j++] = v.y;
vertices[j++] = v.z;
}
}
int indexes[indexCount];
int idx;
for (i = 0; i < indexCount; i++)
{
indexes[i] = getBulletIndex(indexBuffer[i]);
}
int ntriangles = indexCount / 3;
mSoftBody = btSoftBodyHelpers::CreateFromTriMesh(*mWorldInfo, vertices, indexes, ntriangles);
btTransform trs;
trs.setIdentity();
trs.setOrigin(Convert::toBullet(entity->getParentNode()->getPosition()));
trs.setRotation(Convert::toBullet(entity->getParentNode()->getOrientation()));
mSoftBody->transform(trs);
mSoftBody->setUserPointer(this);
return mSoftBody;
}
int BtOgreSoftBody::getBulletIndex(int idx)
{
int idxDup = mDupVertices[idx];
return mNewIndexes[idxDup == -1 ? idx : idxDup];
}
void BtOgreSoftBody::updateOgreMesh()
{
Ogre::Node *ogreNode = mEntity->getParentNode();
//printf("updateOgreMesh %d %s %s\n", internalId, mEntity->getName().c_str(), ogreNode->getName().c_str());
MeshPtr mesh = mEntity->getMesh();
Mesh::SubMeshIterator subMeshI = mesh->getSubMeshIterator();
SubMesh* subMesh = NULL;
VertexData* vData = NULL;
VertexDeclaration* vDeclaration = NULL;
const VertexElement* vPosElement = NULL;
bool isSharedVerticesAdded = false;
unsigned short bufferIndex = 0;
HardwareVertexBufferSharedPtr vBuffer;
// Can not do arithmetic operations on void*
unsigned char* lockedMem = NULL;
float* vPosition;
btSoftBody::tNodeArray& btNodes = mSoftBody->m_nodes;
//printf("Bullet nodes size %d\n", btNodes.size());
int ogreVertexIdx = 0;
btVector3 btPosOffset;
while (subMeshI.hasMoreElements()) {
subMesh = subMeshI.getNext();
if (subMesh->useSharedVertices) {
if (isSharedVerticesAdded) {
continue;
}
vData = mesh->sharedVertexData;
// We need to add shared vertices only once
isSharedVerticesAdded = true;
} else {
vData = subMesh->vertexData;
}
vDeclaration = vData->vertexDeclaration;
vPosElement = vDeclaration->findElementBySemantic(VES_POSITION);
bufferIndex = vPosElement->getSource();
vBuffer = vData->vertexBufferBinding->getBuffer(bufferIndex);
// Lock the buffer before reading from it
lockedMem = static_cast<unsigned char*>(vBuffer->lock(HardwareBuffer::HBL_DISCARD));
// Read each vertex
for (unsigned int i = 0; i < vData->vertexCount; ++i) {
vPosElement->baseVertexPointerToElement(lockedMem, &vPosition);
int idx = getBulletIndex(ogreVertexIdx);
const btVector3 &btPos = btNodes[idx].m_x;
if (ogreVertexIdx == 0) {
btPosOffset = btPos;
}
*vPosition++ = btPos.x() - btPosOffset.x();
*vPosition++ = btPos.y() - btPosOffset.y();
*vPosition = btPos.z() - btPosOffset.z();
// Point to the next vertex
lockedMem += vBuffer->getVertexSize();
ogreVertexIdx++;
}
vBuffer->unlock();
}
btTransform transform = mSoftBody->getWorldTransform();
btQuaternion rot = transform.getRotation();
ogreNode->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
btVector3 pos = transform.getOrigin();
ogreNode->setPosition(pos.x() + btPosOffset.x(), pos.y() + btPosOffset.y(), pos.z() + btPosOffset.z());
}