What I want to do should be very simple, but there has to be some simple things that I am missing. Everything in the warehouse is made out of simple boxes scaled to their appropriate site. I have one and only one OpenGL Vertex Array Object that is a simple unit cube with the position at the center. Before I tried to integrate the physics this was working nicely. I used it to create racking, and boxes on the racking, etc.
Now that I've tried adding in the physics system, things have gotten quite hairy. It seems that I'm having some issues setting the the transformations and communicating between the physics and my graphics system.
I'll show 3 snippets of code:
This is the creation of a box object in my game engine. I use an attribute based object system.
Code: Select all
void Game::ConvertBoxToObject(float mass, std::string object_name, EG::Base::Math::Vector3f dimensions, EG::Base::Math::Vector3f position, std::string decal_map, std::string normal_map){
// Create Object
unsigned int object_id = scene_manager->GetScene()->GetObjectManager()->AddObject();
EG::Engine::Game::Object *new_object = scene_manager->GetScene()->GetObjectManager()->GetObjectById(object_id);
new_object->SetName(object_name);
// Add Transformation
EG::Base::Math::Transformationf object_transformation;
//object_transformation.Scale(dimensions);
//object_transformation.Translate(position);
EG::Engine::Game::ObjectTransformationAttribute *object_transformation_attribute = new EG::Engine::Game::ObjectTransformationAttribute(object_transformation);
//object_transformation_attribute->SetLocalScaling(dimensions);
new_object->AddBasicAttribute(object_transformation_attribute);
// Add Geometry
EG::Engine::Game::ObjectRenderingMeshGeometryAttribute *geometry_attribute = new EG::Engine::Game::ObjectRenderingMeshGeometryAttribute("box");
geometry_attribute->SetId("box");
new_object->AddRenderingAttribute(geometry_attribute);
// Add Material
EG::Engine::Graphics::RenderingMaterial *material = new EG::Engine::Graphics::RenderingMaterial();
material->AddTexture(EG::Engine::Graphics::RenderingMaterial::DECAL, decal_map);
material->AddTexture(EG::Engine::Graphics::RenderingMaterial::NORMAL, normal_map);
material->SetLightingParameters(0.5f, 1.0f, 0.2f, true);
new_object->AddRenderingAttribute(new EG::Engine::Game::ObjectRenderingMaterialAttribute(material));
// Add Physics
EG::Engine::Physics::BoxCollisionShape *collision_shape = new EG::Engine::Physics::BoxCollisionShape(dimensions);
collision_shape->SetMass(mass);
EG::Base::Math::Transformationf collision_shape_transformation;
collision_shape_transformation.Scale(dimensions);
collision_shape_transformation.Translate(position);
collision_shape->SetTransformation(collision_shape_transformation);
EG::Engine::Physics::RigidBody *rigid_body = new EG::Engine::Physics::RigidBody(new_object, collision_shape, scene_manager->GetRenderer()->GetMeshManager()->GetMesh("box"));
rigid_body->SetTargetGeometryAttribute(geometry_attribute);
new_object->AddControlAttribute(new EG::Engine::Game::ObjectRigidBodyControlAttribute(rigid_body));
}
Code: Select all
// First this gets called from the same file as the above code... Game.cpp
std::vector<EG::Engine::Game::ObjectControlAttribute *> *rigid_body_attributes = object->ControlAttributesType(EG::Engine::Game::ObjectAttribute::CONTROL_RIGID_BODY);
EG::Engine::Game::ObjectRigidBodyControlAttribute *rigid_body_attribute = static_cast<EG::Engine::Game::ObjectRigidBodyControlAttribute *>(rigid_body_attributes->at(0));
physics->AddObject(object, rigid_body_attribute->GetRigidBody());
// Then this is the actual Physics::AddObject code
EG::Engine::Physics::CollisionShape *collision_shape = rigid_body->GetCollisionShape();
EG::Base::Math::Transformationf collision_shape_transformation = collision_shape->GetTransformation();
EG::Base::Math::Vector3f local_scaling = collision_shape->GetLocalScaling();
btCollisionShape* bt_shape;
if (collision_shape->GetType() == EG::Engine::Physics::CollisionShape::BOX){
EG::Engine::Physics::BoxCollisionShape *box_collision_shape = static_cast<EG::Engine::Physics::BoxCollisionShape *>(collision_shape);
EG::Base::Math::Vector3f half_extents = box_collision_shape->GetHalfExtents();
btVector3 bt_half_extents(half_extents.X(), half_extents.Y(), half_extents.Z());
bt_shape = new btBoxShape(bt_half_extents);
bt_shape->setUserPointer(box_collision_shape);
//bt_shape->setLocalScaling(bt_half_extents);
all_set = true;
//std::cout << "Adding BT Collision Box " << object->Name() << std::endl;
}
if (all_set){
//bt_shape->setLocalScaling(btVector3(local_scaling.X(), local_scaling.Y(), local_scaling.Z()));
btTransform bt_transform;
bt_transform.setFromOpenGLMatrix(collision_shape_transformation.Data());
btDefaultMotionState *bt_motion_state = new btDefaultMotionState(bt_transform);
btVector3 local_inertia(0, 0, 0);
btScalar mass = collision_shape->GetMass();
bt_shape->calculateLocalInertia(mass, local_inertia);
btRigidBody *bt_rigid_body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(mass, bt_motion_state, bt_shape, local_inertia));
bt_rigid_body->setUserPointer(rigid_body);
rigid_body->SetBulletRigidBody(bt_rigid_body);
//bt_rigid_body->applyCentralForce(btVector3(0, -1, 0));
dynamics_world->addRigidBody(bt_rigid_body);
// TEST Put and Get
//btRigidBody *test_body = static_cast<btRigidBody *>(rigid_body->GetBulletRigidbody());
//EG::Engine::Physics::RigidBody *test_body_2 = static_cast<EG::Engine::Physics::RigidBody *>(test_body->getUserPointer());
//std::cout << "Get Receive Test: " << test_body_2->GetObject()->Name() << std::endl;
}
Code: Select all
void Physics::Update(EG::Engine::Game::ObjectManager *objects, float time_step){
dynamics_world->stepSimulation(time_step, 10);
// update all of the objects after the simulation is run!
btTransform bt_trans;
EG::Base::Math::Transformationf my_trans;
float gl_trans[16];
std::vector<unsigned int> object_ids = objects->ObjectIDs();
std::vector<unsigned int>::iterator object_id_iterator = object_ids.begin();
while (object_id_iterator != object_ids.end()){
EG::Engine::Game::Object *object = objects->GetObjectById(*object_id_iterator);
if (object->BasicAttributeCountType(EG::Engine::Game::ObjectAttribute::BASIC_TRANSFORMATION) > 0 && object->ControlAttributesCountType(EG::Engine::Game::ObjectAttribute::CONTROL_RIGID_BODY) > 0){
EG::Engine::Game::ObjectTransformationAttribute *transformation_attribute = static_cast<EG::Engine::Game::ObjectTransformationAttribute *>(object->BasicAttributesType(EG::Engine::Game::ObjectAttribute::BASIC_TRANSFORMATION)->at(0));
EG::Engine::Game::ObjectRigidBodyControlAttribute *rigid_body_attribute = static_cast<EG::Engine::Game::ObjectRigidBodyControlAttribute *>(object->ControlAttributesType(EG::Engine::Game::ObjectAttribute::CONTROL_RIGID_BODY)->at(0));
EG::Engine::Physics::RigidBody *rigid_body = rigid_body_attribute->GetRigidBody();
btRigidBody *bt_rigid_body = static_cast<btRigidBody *>(rigid_body->GetBulletRigidbody());
bt_rigid_body->getMotionState()->getWorldTransform(bt_trans);
bt_trans.getOpenGLMatrix(gl_trans);
my_trans.Set(gl_trans);
//btVector3 local_scaling = bt_rigid_body->getCollisionShape()->getLocalScaling();
//my_trans.Scale(local_scaling.getX(), local_scaling.getY(), local_scaling.getZ()); // NOTE: May not work if object gets rotated!
transformation_attribute->SetTransformation(my_trans);
}
++object_id_iterator;
}
}
Secondly when I do run this simulation, the scale of the collision boxes seem to be sqauring the scale. So things that are long are really long, and things that are thin, are very very thin.
This is what I'm not sure of. I can't find where that is happening! Is there a better set of commented documentation that I can look at to see where I'm going wrong? Or just better documentation in general. I've been playing with this for a day and this should be almost trivial. I'm sure I'm doing something stupid, but without better docs, I have no idea where to go from where I am.
Thanks in advance for reading my long post and considering responding!