Ogre Bullet, Soft Body

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
ENGine
Goblin
Posts: 266
Joined: Fri Jan 27, 2006 9:13 pm
Location: Belarus
x 2
Contact:

Ogre Bullet, Soft Body

Post by ENGine »

Hi, all.

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();
}
BtOgreSoftBody:

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());
    }
My ogreNode is moving regarding to bullet soft body position. But I have no method for updating Ogre::Mesh. Please, share this. Thanks a lot.
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Ogre Bullet, Soft Body

Post by c6burns »

BtOgreSoftBody::updateOgreMesh every frame ... step through the method and find out why it isn't working, if it isn't.
Last edited by c6burns on Mon Jan 26, 2015 6:59 am, edited 3 times in total.
User avatar
ENGine
Goblin
Posts: 266
Joined: Fri Jan 27, 2006 9:13 pm
Location: Belarus
x 2
Contact:

Re: Ogre Bullet, Soft Body

Post by ENGine »

I call BtOgreSoftBody::updateOgreMesh every frame:

Code: Select all

- (void)renderOneFrame:(NSTimer*)theTimer {
	[mWorld simulate:theTimer.timeInterval];
	[character simulate:theTimer.timeInterval];
	[softBody updateOgreMesh];
	[mRootManager] renderOneFrame];
}
But the result is updating position of SceneNode regarding to SoftBody, but the Entity isn't updated/deformed.
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Ogre Bullet, Soft Body

Post by c6burns »

Ooops I accidentally edited my last post instead of replying.

Anyway ... crash course in problem solving:
USE THE DEBUGGER

As I suggested before, step through the call to updateOgreMesh and see why it isn't updating the vertex buffer. Otherwise wait for someone to explain to you exactly why your program doesn't work. Your choice, I suppose.

Funny this reminds me of the dichotomy between people who do and don't know how to fix a toilet. When your toilet breaks do you go to the toilet's web forum and ask why it broke, or do you open the toilet and try to figure it out? The former might get you an easy fix so it's not a terrible idea, but the latter is always going to teach you something about the internals of what you are using, which is generally not a bad thing. OSS is full of broken toilets :lol:
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Ogre Bullet, Soft Body

Post by jacmoe »

It feels like 90% of my programming time is spent fixing OSS toilets .. :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
frostbyte
Orc Shaman
Posts: 737
Joined: Fri May 31, 2013 2:28 am
x 65

Re: Ogre Bullet, Soft Body

Post by frostbyte »

i have a relative that helps in chip design, when you ask him what he does, he usualy replies..."i'm a plumber" :lol:
the woods are lovely dark and deep
but i have promises to keep
and miles to code before i sleep
and miles to code before i sleep..

coolest videos link( two minutes paper )...
https://www.youtube.com/user/keeroyz/videos
User avatar
Zonder
Ogre Magi
Posts: 1168
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 73

Re: Ogre Bullet, Soft Body

Post by Zonder »

frostbyte wrote:i have a relative that helps in chip design, when you ask him what he does, he usualy replies..."i'm a plumber" :lol:
it's a good analogy :lol:
There are 10 types of people in the world: Those who understand binary, and those who don't...
User avatar
ENGine
Goblin
Posts: 266
Joined: Fri Jan 27, 2006 9:13 pm
Location: Belarus
x 2
Contact:

Re: Ogre Bullet, Soft Body

Post by ENGine »

Guys, I so need the help. During few day I'm trying to solve this trouble. I tried to use another method:

Code: Select all

void BtOgreSoftBody::updateOgreMeshFromBulletMesh()
	{
		MeshPtr mesh= mEntity->getMesh();
		Mesh::SubMeshIterator subMeshI = mesh->getSubMeshIterator();
		SubMesh* submesh = NULL;
		
		while (subMeshI.hasMoreElements()) {
			submesh = subMeshI.getNext();
			
			Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
			if (!submesh->useSharedVertices)
			{
				const Ogre::VertexElement* posElem =vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
				Ogre::HardwareVertexBufferSharedPtr vbuf= vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
				const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
				unsigned char* vertex =static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
				
				float* pReal;
				btSoftBody::tNodeArray&   nodes(mSoftBody->m_nodes);

				for (int j=0;j<nodes.size();++j)
				{
					posElem->baseVertexPointerToElement(vertex, &pReal);
					vertex += vSize;
					*pReal++= nodes[j].m_x.x();
					*pReal++= nodes[j].m_x.y();
					*pReal++= nodes[j].m_x.z();
				}
				vbuf->unlock();
			}
		}
	}
But the result is wrong (the mesh is deformed terrible). Please, help. Thanks
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Ogre Bullet, Soft Body

Post by c6burns »

Again, I'm interested to understand why you created a new method instead of working towards understanding the existing method? Are you avoiding debugging the existing method fully, or are you debugging it and finding out it doesn't work, and then not explaining any of that in your posts?

In your new method, you completely overlooked BtOgreSoftBody::getBulletIndex
frostbyte
Orc Shaman
Posts: 737
Joined: Fri May 31, 2013 2:28 am
x 65

Re: Ogre Bullet, Soft Body

Post by frostbyte »

after playing with softbody a bit- i discovered that softbody updating works fine for meshes with no animation, however
meshes with animation needs forcing their vbo to be sent to the gpu( i do this by mesh->setMaterialName( mesh->getMaterialName() ); any better way? )
this makes me wonder, does all of this means that meshes with no animation send there vbo to to gpu each frame??? this does'nt realy make sense....


there are still a few problems here
meshes with animation get streched along the z-axis...i suspect differences with int-format...
also playing animation while morphing a softbody mesh yield some realy weird effects( very cool and funny but unpredicted... )
the woods are lovely dark and deep
but i have promises to keep
and miles to code before i sleep
and miles to code before i sleep..

coolest videos link( two minutes paper )...
https://www.youtube.com/user/keeroyz/videos
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Ogre Bullet, Soft Body

Post by c6burns »

the softbody update code is locking/unlocking the vertex buffer ... so yes it's getting updated every frame if it's a softbody. Also I assume that's how software animation works as well (rewriting the vertices based on bone position/orientation/skinning weight), so you have these two different updates at different stages of rendering that are changing the buffer
engelfaul
Gnoblar
Posts: 1
Joined: Fri Apr 20, 2018 8:10 pm

Re: Ogre Bullet, Soft Body

Post by engelfaul »

ENGine wrote: Wed Jan 28, 2015 6:11 pm Guys, I so need the help. During few day I'm trying to solve this trouble. I tried to use another method:

But the result is wrong (the mesh is deformed terrible). Please, help. Thanks
Hi ENGine, can you make that the softbody simulation works fine? I did a similar code but my softbody only falls, I set some nodes with zero mass for simulate fixed parts but the others nodes with mass falls like a it was a independent nodes.

Thanks!

Engelfaul
Post Reply