Plugged the bullet physics engine, which created using primitives ISceneNode *Node = smgr->addCubeSceneNode(1.0f); all the clashes were considered normal and physics worked. When drew in MilkShape 3D square and uploaded it using IAnimatedMesh* mailbox_mesh = smgr->getMesh(media/map/box/box.ms3d"); the collision ceased to operate normally.
There is such a line
btVector3 HalfExtents(TScale.X / 2, TScale.Y / 2, TScale.Z / 2);
btCollisionShape* Shape = new btBoxShape(HalfExtents);
Then I understood from the center of the cube are considered to be the border of the object for the collision. When loading a mesh following occurs
Here is how the cube looks like in the editor
Here is how the cube looks if you do the following
btVector3 HalfExtents(TScale.X + 1000, TScale.Y + 1000, TScale.Z + 1000);
The edges were more than he cubic
It turns out that the edges of the mesh are not considered properly, how to properly implement this?
irrlicht + bullet getmesh() not working properly
Re: irrlicht + bullet getmesh() not working properly
Function to create a mesh
Code: Select all
void CrMailbox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass) {
IAnimatedMesh* mailbox_mesh = smgr->getMesh("media/map/box/box.ms3d");
ISceneNode* mailbox_node = smgr->addMeshSceneNode(mailbox_mesh, 0, -1);
mailbox_node->setScale(TScale);
mailbox_node->setMaterialType(EMT_SOLID);
mailbox_node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(TPosition);
btDefaultMotionState* MotionState = new btDefaultMotionState(Transform);
btVector3 HalfExtents(TScale.X, TScale.Y, TScale.Z);
btCollisionShape* Shape = new btBoxShape(HalfExtents);
btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);
btRigidBody* RigidBody = new btRigidBody(TMass, MotionState, Shape, LocalInertia);
RigidBody->setFriction(1000);
//RigidBody->setRestitution(1);
//RigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
RigidBody->setUserPointer((void *)(mailbox_node));
World->addRigidBody(RigidBody);
Objects.push_back(RigidBody);
}
Re: irrlicht + bullet getmesh() not working properly
Mesh center should be at (0,0,0) and from editor screenshot that seams to be the case.
So it might be because youre only taking into account scale of object and not the object size itself. you should get object size and multiply it by scale to get correct bbox extents for bullet I think.
I would recommend implementing debug drawing functions for bullet.
So it might be because youre only taking into account scale of object and not the object size itself. you should get object size and multiply it by scale to get correct bbox extents for bullet I think.
I would recommend implementing debug drawing functions for bullet.
Working on game: Marrbles (Currently stopped).
Re: irrlicht + bullet getmesh() not working properly
I have experienced this issue to. Collision mesh did not work properly. I had no clues how to workaround it until enable debug drawing.
After that I saw that collision mesh(and also ITriangleSelector returned from ISceneCollisionManager) is transformed relative to original mesh(translated, rotated, scaled). After some researching I found that if I export my model from 3ds max with resetXForm, mesh works properly.
If you use 3ds max too, try to apply resetXForm modifier to your model and than merge all modifies into one. It should help.
After that I saw that collision mesh(and also ITriangleSelector returned from ISceneCollisionManager) is transformed relative to original mesh(translated, rotated, scaled). After some researching I found that if I export my model from 3ds max with resetXForm, mesh works properly.
If you use 3ds max too, try to apply resetXForm modifier to your model and than merge all modifies into one. It should help.
Re: irrlicht + bullet getmesh() not working properly
I looked in the wrappers and saw functions for converting vectors, tried to use them on a clean bullet and put it to work, the functions of the post
Code: Select all
inline static btVector3 irrVectorToBulletVector(const irr::core::vector3df & toConvert)
{
return btVector3(toConvert.X,toConvert.Y,toConvert.Z);
}
-
- Posts: 1010
- Joined: Mon Oct 24, 2011 10:03 pm
- Location: 0x45 61 72 74 68 2c 20 69 6e 20 74 68 65 20 73 6f 6c 20 73 79 73 74 65 6d
Re: irrlicht + bullet getmesh() not working properly
You PM'd me and requested help on using bullet without a wrappereasy163 wrote:I looked in the wrappers and saw functions for converting vectors, tried to use them on a clean bullet and put it to work, the functions of the post
Code: Select all
inline static btVector3 irrVectorToBulletVector(const irr::core::vector3df & toConvert) { return btVector3(toConvert.X,toConvert.Y,toConvert.Z); }
Here you go:
config.h
Code: Select all
// <headers>
#include "irrlicht/irrlicht.h"
#include "btBulletDynamicsCommon.h"
#include <string>
#include "stdlib.h"
#include "stdio.h"
// </headers>
// <namespaces!>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// </namespaces!>
Code: Select all
#include "config.h"
#include "time.h"
//Global bullet vars
static bool Done = false;
static btDiscreteDynamicsWorld *dynamicsWorld;
static list<btRigidBody *> objects;
//Global Irrlicht vars
static IrrlichtDevice *device;
static IVideoDriver *driver;
static ISceneManager *smgr;
static ITimer *timer;
//static IGUIEnvironment *guienv;
//static IFileSystem *filesys;
//static ILogger *logger;
//Bullet Related Functions
static void createStartScene();
static void createBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass);
static void createSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass);
void UpdatePhysics(u32 TDeltaTime);
static void UpdateRender(btRigidBody *TObject);
static void ClearObjects();
static int GetRandInt(int TMax) {return rand() % TMax; }
class EventReceiverClass : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent &TEvent)
{
if(TEvent.EventType == EET_KEY_INPUT_EVENT && !TEvent.KeyInput.PressedDown)
{
switch(TEvent.KeyInput.Key)
{
case KEY_ESCAPE:
Done=true;
break;
case KEY_KEY_Q:
createBox(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), vector3df(GetRandInt(3)+0.5f,GetRandInt(3)+0.5f, GetRandInt(3)+0.5f),1.0f);
break;
case KEY_KEY_W:
createSphere(btVector3(GetRandInt(10) - 5.0f, 7.0f, GetRandInt(10) - 5.0f), GetRandInt(5) / 5.0f + 0.2f, 1.0f);
break;
case KEY_KEY_E:
createStartScene();
break;
default:
return false;
break;
}
return true;
}
return false;
}
};
int main()
{
srand(time(NULL));
int screenHeight = 800, screenWidth = 600;
EventReceiverClass receiver;
device = createDevice(EDT_OPENGL, dimension2d<u32>(screenHeight, screenWidth), 32, false, false, false, &receiver);
if (device == 0)
{
return 1;
}
//guienv = device->getGUIEnvironment();
timer = device->getTimer();
driver = device->getVideoDriver();
smgr = device->getSceneManager();
device->getCursorControl()->setVisible(false);
btBroadphaseInterface *broadPhase = new btAxisSweep3(btVector3(-1000,-1000,-1000), btVector3(1000,1000,1000));
btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
btSequentialImpulseConstraintSolver *solver = new btSequentialImpulseConstraintSolver();
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadPhase, solver, collisionConfiguration);
ICameraSceneNode *camera = smgr->addCameraSceneNodeFPS(0,100,25);
camera->setPosition(vector3df(0,5,-5));
camera->setTarget(vector3df(0,0,0));
/*IGUISkin* skin = guienv->getSkin();
skin->setColor(EGDC_BUTTON_TEXT, SColor(255,200,200,200));
guienv->addStaticText(L"Hit Q to spawn a cube, W for a sphere and E to reset or escape to exit.", rect<s32>(0,0,200,100), false);
IGUIStaticText* versionText = guienv->addStaticText(L"", rect<s32>(0,0,300,200),false);
versionText->setText(string);*/
smgr->addLightSceneNode(0, vector3df(2, 5, -2), SColorf(4, 4, 4, 1));
createStartScene();
driver->getTexture("resources/textures/tex.jpg");
driver->getTexture("resources/textures/tex1.jpg");
u32 timeStamp = timer->getTime(), DeltaTime = 0;
while(Done == false)
{
device->run();
if(device->isWindowActive())
{
DeltaTime = timer->getTime() - timeStamp;
timeStamp = timer->getTime();
UpdatePhysics(DeltaTime);
driver->beginScene(true,true,SColor(255,55,0,155));
smgr->drawAll();
//guienv->drawAll();
driver->endScene();
int FPS = driver->getFPS(), lastFPS = -1;
if(lastFPS != FPS)
{
stringw str = L"COLLISION TEST [";
str += driver->getName();
str += "] FPS:";
str += FPS;
str += " VERSION:";
str += auto__RC_FILEVERSION_STRING;
device->setWindowCaption(str.c_str());
lastFPS=FPS;
}
}
device->yield();
}
ClearObjects();
delete dynamicsWorld;
delete solver;
delete dispatcher;
delete broadPhase;
delete collisionConfiguration;
device->drop();
getchar();
return 0;
}
void UpdatePhysics(u32 TDeltaTime)
{
dynamicsWorld->stepSimulation(TDeltaTime * 0.001f, 60);
for(list<btRigidBody *>::Iterator Iterator = objects.begin(); Iterator != objects.end(); ++Iterator)
{
UpdateRender(*Iterator);
}
}
void createStartScene()
{
ClearObjects();
createBox(btVector3(0.0f,0.0f,0.0f), vector3df(10.0f,0.5f,10.0f), 0.0f);
}
void createBox(const btVector3 &TPosition, const vector3df &TScale, btScalar TMass)
{
ISceneNode *node = smgr->addCubeSceneNode(1.0f);
node->setScale(TScale);
node->setMaterialFlag(EMF_LIGHTING, 1);
node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
node->setMaterialTexture(0,driver->getTexture("resources/textures/tex.jpg"));
btTransform bulletTransform;
bulletTransform.setIdentity();
bulletTransform.setOrigin(TPosition);
btDefaultMotionState *motionState = new btDefaultMotionState(bulletTransform);
btVector3 halfExtents(TScale.X * 0.5f, TScale.Y * 0.5f, TScale.Z * 0.5f);
btCollisionShape *shape = new btBoxShape(halfExtents);
btVector3 localInertia;
shape->calculateLocalInertia(TMass, localInertia);
btRigidBody *rigidBody = new btRigidBody(TMass, motionState, shape, localInertia);
rigidBody->setUserPointer((void*)(node));
dynamicsWorld->addRigidBody(rigidBody);
objects.push_back(rigidBody);
}
void createSphere(const btVector3 &TPosition, btScalar TRadius, btScalar TMass)
{
ISceneNode *node = smgr->addSphereSceneNode(TRadius, 32);
node->setMaterialFlag(EMF_LIGHTING, 1);
node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
node->setMaterialTexture(0,driver->getTexture("resources/textures/tex1.jpg"));
btTransform bulletTransform;
bulletTransform.setIdentity();
bulletTransform.setOrigin(TPosition);
btDefaultMotionState *motionState = new btDefaultMotionState(bulletTransform);
btCollisionShape *shape = new btSphereShape(TRadius);
btVector3 localInertia;
shape->calculateLocalInertia(TMass, localInertia);
btRigidBody *rigidBody = new btRigidBody(TMass,motionState,shape,localInertia);
rigidBody->setUserPointer((void*)(node));
dynamicsWorld->addRigidBody(rigidBody);
objects.push_back(rigidBody);
}
void UpdateRender(btRigidBody *TObject)
{
ISceneNode *node = static_cast<ISceneNode *>(TObject->getUserPointer());
btVector3 point = TObject->getCenterOfMassPosition();
node->setPosition(vector3df((f32)point[0], (f32)point[1], (f32)point[2]));
vector3df Euler;
const btQuaternion& TQuaternion = TObject->getOrientation();
quaternion q(TQuaternion.getX(), TQuaternion.getY(), TQuaternion.getZ(), TQuaternion.getW());
q.toEuler(Euler);
Euler *= RADTODEG;
node->setRotation(Euler);
}
void ClearObjects()
{
for(list<btRigidBody *>::Iterator Iterator = objects.begin(); Iterator != objects.end(); ++Iterator)
{
btRigidBody *object = *Iterator;
ISceneNode *node = static_cast<ISceneNode *>(object->getUserPointer());
node->remove();
dynamicsWorld->removeRigidBody(object);
delete object->getMotionState();
delete object->getCollisionShape();
delete object;
}
objects.clear();
}
Something along those lines should work, this code isn't commented nor can I guarantee that it is particularly useful, it's mostly written from memory and UNTESTED
"this is not the bottleneck you are looking for"