Page 1 of 1

Convex Decomposition Issue with OBJ File

Posted: Thu Feb 21, 2019 8:50 pm
by Pappers
So recently I have been trying to modify Bullet's ImportOBJ demo (in Bullet 3) and the ConvexDecomposition demo (in Bullet 2.79, 2.80, etc.) by simply moving the attached objects into the specified directory and then changing the filepath to the objects specified.

The demos can find and detect the file, but the resulting convex hull is either incorrect or non-existent. In the case of the hand.obj, the resulting convex hull appears to be a line, and in the cup object (obj.obj), there doesn't seem to be a resulting convex hull. I have tried and uploaded other object files and they appear to work with the demo, but I want to figure out why exactly these two object files aren't properly decomposed.

To replicate this scenario, you can do the following:

For bullet version 2.79, 2.80, ... (pre-Bullet 3 I believe):

In main.cpp of Demos/ConvexDecompositionDemo:

Code: Select all

int main(int argc,char** argv)
{
        const char* filename = "0.obj.obj"; //Or 0.hand.obj


        ConvexDecompositionDemo* convexDecompDemo = new ConvexDecompositionDemo();

        convexDecompDemo->initPhysics(filename);
        
        // The rest is the same
        
In ConvexDecompositionDemo.cpp of Demos/ConvexDecompositionDemo:

Code: Select all

//Lines 79 to 82

void ConvexDecompositionDemo::initPhysics()
{
	initPhysics("0.obj.obj");
}

// Scroll further down the file...

// Lines 177 to 191

#ifndef NO_OBJ_TO_BULLET

	ConvexDecomposition::WavefrontObj wo;

	tcount = wo.loadObj(filename);

	if (!tcount)
	{
		//when running this app from visual studio, the default starting folder is different, so make a second attempt...
		tcount = wo.loadObj("../../0.obj.obj");
	}
	if (!tcount)
	{
		//cmake generated msvc files need 4 levels deep back... so make a 3rd attempt...
		tcount = wo.loadObj("../../../../0.obj.obj");
	}
	
// The rest should be the same
For Bullet 3, I believe the demo is called lImportObjDemo in Importers. Alternatively, there is also a ConvexDecomposition demo. Both of them still generate a convex hull that lacks any collision, and the coordinates of the hull itself is incorrect.

Re: Convex Decomposition Issue with OBJ File

Posted: Thu May 02, 2019 7:57 am
by LastBlow
The second object, the nut, seems to be good candidate for a convex hull object but the first, the virtual hand, is not a convex object because of the fingers and the curling palm and should be loaded as an impact mesh.

The impact meshes files have a specific data format in Bullet Physics. Here below some code to create an impact mesh, plus an example of an original .obj file of a chair, generated in Blender and formatted for Bullet Physics.

Code: Select all

std::shared_ptr<ImpactMesh> createImpactMesh(std::string nameNode,     // offroad truck, bunny, chair, revolution surface,...
	btGImpactMeshShape* impactMeshShape,
	const btVector3& position = btVector3(0.0f, 10.0f, 0.0f),
	std::string textureName = "bunny",
	const btVector3& impactMeshScale = btVector3(1.0f, 1.0f, 1.0f),
	const float& mass = 50.0f,
	const btQuaternion& orientation = btQuaternion(0.0f, 0.0f, 0.0f, 1.0f),
	std::string meshName = "bunny",
	bool addChild = true);

Code: Select all

std::shared_ptr<ImpactMesh> ObjectFactory::createImpactMesh(std::string nameNode, btGImpactMeshShape* impactMeshShape, 
	const btVector3& position, std::string textureName, const btVector3& impactMeshScale, const float& mass, 
	const btQuaternion& orientation, std::string meshName, bool addChild) {

	impactMeshShape->setLocalScaling(impactMeshScale);
	impactMeshShape->setMargin(0.04f);
	impactMeshShape->updateBound();

	std::shared_ptr<ImpactMesh> impactMesh = std::shared_ptr<ImpactMesh>(new ImpactMesh(nameNode,
		impactMeshShape, position, textureName, mass, orientation, meshName));

	if (m_dynamicsWorld && addChild)
		m_dynamicsWorld->addRigidBody(impactMesh->getRigidBody());

	if (m_world && addChild)
		m_world->addChild(impactMesh);

	impactMesh->initRenderer(m_renderer);

	return impactMesh;
}

Code: Select all

#ifndef IMPACT_MESH_H
#define IMPACT_MESH_H

#include "GeodePhysics.h"

#include "BulletCollision/Gimpact/btGImpactShape.h"


class ImpactMesh : public GeodePhysics {

public:
	ImpactMesh(std::string nameNode, btGImpactMeshShape* impactMeshShape, const btVector3 &position, std::string textureName,
		const btScalar &mass, const btQuaternion &orientation, std::string meshName);

	~ImpactMesh() {}

	virtual void update() override;

	virtual void deleteAllChildren() override {}
	virtual void printAllChildren() override {}

private:

};

#endif

Code: Select all

#include "ImpactMesh.h"

#include <glm/gtc/matrix_transform.hpp>

#include "utils.h"
#include "log.h"


ImpactMesh::ImpactMesh(std::string nameNode, btGImpactMeshShape* impactMeshShape, const btVector3 &position, std::string textureName,
	const btScalar &mass, const btQuaternion &orientation, std::string meshName) :
	GeodePhysics(nameNode, impactMeshShape, position, textureName, mass, orientation, meshName) {

	logFileStderr("MESSAGE: Using mesh \"%s\"... \n", m_meshesNames[0].c_str());
	logFileStderr("MESSAGE: Using texture \"%s\"... \n", m_texturesNames[0].c_str());

	btVector3 halfSize = impactMeshShape->getLocalScaling();

	btTransform transform = m_rigidBody->getWorldTransform();

	m_modelMatrix = bullet2glm(transform) * glm::scale(glm::mat4(1.0), bullet2glm(halfSize));
	// logFileStderr("model matrix: \n"); printMat4(m_modelMatrix);

	// print();
}


void ImpactMesh::update() {

	btTransform transform = m_rigidBody->getWorldTransform();

	const btGImpactMeshShape* impactMeshShape = static_cast<const btGImpactMeshShape*>(m_collisionShape);
	btVector3 halfSize = impactMeshShape->getLocalScaling();

	m_modelMatrix = bullet2glm(transform) * glm::scale(glm::mat4(1.0), bullet2glm(halfSize));
	// logFileStderr("transform matrix: \n"); printMat4(bullet2glm(transform));

	m_boundingSphereCenter = bullet2glm(m_rigidBody->getCenterOfMassPosition() + btVector3(0.0f, m_boundingSphereRadius, 0.0f));
}