Scale values in transform Matrix of a rigid body LOST
Posted: Tue Jan 26, 2010 7:45 am
Hi, all
I need the transform matrix which contains the scale value to set the original transform of the rigid body, and after simulation I update the vertex of the rigid body under the original transform. So, the scale value is important to me.
I set the scale values to (3.0,3.0,3.0) before simulation, and get the scale values after simulation, it is (1.0, 1.0, 1.0).It seems that the scale values lost.
Here is the complete code which is modified from HelloWorld.cpp:
#include "btBulletDynamicsCommon.h"
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
const float scale = 3.0f;
btScalar stm[4][4] =
{
{scale, 0.0f, 0.0f, 0.0f},
{0.0f, scale, 0.0f, 0.0f},
{0.0f, 0.0f, scale, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
};
/// This is a Hello World program for running a basic Bullet physics simulation
void printMatrix(const std::string& tip, const btScalar m[][4] )
{
//btScalar &m[4][4] = matrix;
cout <<tip<<endl;
cout <<"matrix: {"<<endl;
for(int i=0; i<4; ++i)
{
printf("\t{%f, %f, %f, %f}\n", m[0], m[1], m[2], m[3] );
}
cout <<"}"<<endl;
}
void printObjMatrix( btRigidBody* body, const string& tip )
{
//
btTransform trans;
btScalar tmp[4][4];
body->getMotionState()->getWorldTransform(trans);
trans.getOpenGLMatrix(&(tmp[0][0]));
printMatrix(tip, tmp);
}
int main(int argc, char** argv)
{
int i;
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
///the maximum size of the collision world. Make sure objects stay within these boundaries
///Don't make the world AABB size too large, it will harm simulation quality and performance
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
int maxProxies = 1024;
btAxisSweep3* overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(0.5)));
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
{
//create a dynamic rigidbody
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
btCollisionShape* colShape = new btSphereShape(btScalar(1.));
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
//************* set the scale component *****************
startTransform.setFromOpenGLMatrix(&(stm[0][0]));
//*******************************************************
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(2,10,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
dynamicsWorld->addRigidBody(body);
//********* out put Matrix of before simulation ***********
printObjMatrix(body, "get matrix before bullet sim:");
//*********************************************************
}
/// Do some simulation
for (i=0;i<100;i++)
{
dynamicsWorld->stepSimulation(1.f/60.f,10);
//print positions of all objects
// for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--)
// {
int j = 1;
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
//printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
//********* out put Matrix of the last frame ***********
if(i==99){
printObjMatrix(body, "get matrix after bullet sim:");
}
//******************************************************
}
// }
}
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray();
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
//delete collision shapes
for (int j=0;j<collisionShapes.size();j++)
{
btCollisionShape* shape = collisionShapes[j];
collisionShapes[j] = 0;
delete shape;
}
//delete dynamics world
delete dynamicsWorld;
//delete solver
delete solver;
//delete broadphase
delete overlappingPairCache;
//delete dispatcher
delete dispatcher;
delete collisionConfiguration;
//next line is optional: it will be cleared by the destructor when the array goes out of scope
collisionShapes.clear();
}
and the result is:
get matrix before bullet sim:
matrix: {
{3.000000, 0.000000, 0.000000, 0.000000}
{0.000000, 3.000000, 0.000000, 0.000000}
{0.000000, 0.000000, 3.000000, 0.000000}
{2.000000, 10.000000, 0.000000, 1.000000}
}
get matrix after bullet sim:
matrix: {
{1.000000, -0.000002, 0.000000, 0.000000}
{0.000002, 1.000000, 0.000000, 0.000000}
{-0.000000, -0.000000, 1.000000, 0.000000}
{2.000000, 0.999999, -0.000000, 1.000000}
}
so, could you tell me why? whether it is a bug, or Is there any reason for doing this?
Thank you.
I need the transform matrix which contains the scale value to set the original transform of the rigid body, and after simulation I update the vertex of the rigid body under the original transform. So, the scale value is important to me.
I set the scale values to (3.0,3.0,3.0) before simulation, and get the scale values after simulation, it is (1.0, 1.0, 1.0).It seems that the scale values lost.
Here is the complete code which is modified from HelloWorld.cpp:
#include "btBulletDynamicsCommon.h"
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
const float scale = 3.0f;
btScalar stm[4][4] =
{
{scale, 0.0f, 0.0f, 0.0f},
{0.0f, scale, 0.0f, 0.0f},
{0.0f, 0.0f, scale, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
};
/// This is a Hello World program for running a basic Bullet physics simulation
void printMatrix(const std::string& tip, const btScalar m[][4] )
{
//btScalar &m[4][4] = matrix;
cout <<tip<<endl;
cout <<"matrix: {"<<endl;
for(int i=0; i<4; ++i)
{
printf("\t{%f, %f, %f, %f}\n", m[0], m[1], m[2], m[3] );
}
cout <<"}"<<endl;
}
void printObjMatrix( btRigidBody* body, const string& tip )
{
//
btTransform trans;
btScalar tmp[4][4];
body->getMotionState()->getWorldTransform(trans);
trans.getOpenGLMatrix(&(tmp[0][0]));
printMatrix(tip, tmp);
}
int main(int argc, char** argv)
{
int i;
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
///the maximum size of the collision world. Make sure objects stay within these boundaries
///Don't make the world AABB size too large, it will harm simulation quality and performance
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
int maxProxies = 1024;
btAxisSweep3* overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(0.5)));
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
{
//create a dynamic rigidbody
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
btCollisionShape* colShape = new btSphereShape(btScalar(1.));
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
//************* set the scale component *****************
startTransform.setFromOpenGLMatrix(&(stm[0][0]));
//*******************************************************
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(2,10,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
dynamicsWorld->addRigidBody(body);
//********* out put Matrix of before simulation ***********
printObjMatrix(body, "get matrix before bullet sim:");
//*********************************************************
}
/// Do some simulation
for (i=0;i<100;i++)
{
dynamicsWorld->stepSimulation(1.f/60.f,10);
//print positions of all objects
// for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--)
// {
int j = 1;
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
//printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
//********* out put Matrix of the last frame ***********
if(i==99){
printObjMatrix(body, "get matrix after bullet sim:");
}
//******************************************************
}
// }
}
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray();
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
//delete collision shapes
for (int j=0;j<collisionShapes.size();j++)
{
btCollisionShape* shape = collisionShapes[j];
collisionShapes[j] = 0;
delete shape;
}
//delete dynamics world
delete dynamicsWorld;
//delete solver
delete solver;
//delete broadphase
delete overlappingPairCache;
//delete dispatcher
delete dispatcher;
delete collisionConfiguration;
//next line is optional: it will be cleared by the destructor when the array goes out of scope
collisionShapes.clear();
}
and the result is:
get matrix before bullet sim:
matrix: {
{3.000000, 0.000000, 0.000000, 0.000000}
{0.000000, 3.000000, 0.000000, 0.000000}
{0.000000, 0.000000, 3.000000, 0.000000}
{2.000000, 10.000000, 0.000000, 1.000000}
}
get matrix after bullet sim:
matrix: {
{1.000000, -0.000002, 0.000000, 0.000000}
{0.000002, 1.000000, 0.000000, 0.000000}
{-0.000000, -0.000000, 1.000000, 0.000000}
{2.000000, 0.999999, -0.000000, 1.000000}
}
so, could you tell me why? whether it is a bug, or Is there any reason for doing this?
Thank you.