some question about PhysX

javid

17-12-2009 07:01:37

For some reasons, I need to integrate PhysX with Ogre by myself.
So far, I just need the example "Character controller" in PhysX SDK to be implemented by Ogre.
The basic architecture is like the NxOgre, I create an basic class "PActor.h", and it have a virtual function called "Advanced".
Then I start to create the CharacterController.h , PBox.h to implement the updating the position according to its NxActor.

So, in the frame listener, I update the PhysX and then update all actor in the scene :

gScene->simulate(evt.timeSinceLastFrame);
gScene->flushStream();
gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);//stop the simulation of this frame
for( ActorList::iterator it = actorlist->begin() ; it != actorlist->end() ; it++)
it->second->Advance();

The architecture is very simple and easy to implement.

However, the main question is how to write the Advance function?
Here is a Box class :

#ifndef PBOX_H
#define PBOX_H
#include "POgreActor.h"
#include "CollisionGroup.h"
#include <conio.h>

class PBox : public PActor
{
public:
PBox( string actorName, NxVec3 position , const Ogre::String& meshName ,Ogre::SceneManager* smgr, NxScene* scene )
{
gScene = scene;
mSceneManager = smgr;

/////////////////////////////for ogre /////////////////////////////////
mEntity = mSceneManager->createEntity( actorName ,meshName);

mNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mNode->attachObject( mEntity );
mNode->setPosition( position.x , position.z, position.y );
//mNode->showBoundingBox(true);
//get mesh size from bouding box :
AxisAlignedBox spbox = mNode->getAttachedObject(actorName)->getBoundingBox();
Ogre::Vector3 min = spbox.getMinimum()*mNode->getScale();
Ogre::Vector3 max = spbox.getMaximum()*mNode->getScale();
Ogre::Real paddingFactor = Ogre::MeshManager::getSingleton().getBoundsPaddingFactor();
Ogre::Vector3 newMin = min+(max-min)*paddingFactor;
Ogre::Vector3 newMax = max+(min-max)*paddingFactor;
box_size = newMax - newMin;

// Create body
NxBodyDesc bodyDesc;
bodyDesc.angularDamping = 0.5f;
bodyDesc.mass = 1;

NxBoxShapeDesc boxDesc;
boxDesc.dimensions = NxVec3((float)box_size.x, (float)box_size.y, (float)box_size.z);
boxDesc.group = GROUP_COLLIDABLE_NON_PUSHABLE;
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&boxDesc);
actorDesc.body = &bodyDesc;

actorDesc.globalPose.t = position;
actor = gScene->createActor(actorDesc);
};
void Advance(){
Real quat[16];
actor->getGlobalPose().getRowMajor44(quat);//.getColumnMajor44(quat);
Ogre::Matrix4 m4(quat[0], quat[1], quat[2], quat[3],
quat[4], quat[5], quat[6], quat[7],
quat[8], quat[9], quat[10], quat[11],
quat[12], quat[13], quat[14], quat[15]);
mNode->setPosition(m4.getTrans().x );
mNode->setOrientation(m4.extractQuaternion());
}

};
#endif


Set 1 :
Here is the weird Result in Ogre :

Actual position in PhysX :


Set 2 :
Here is the weird Result in Ogre :

Actual position in PhysX :


Do you notice the difference between this two pictures? The position in PhysX is different from the position in Ogre. I wonder whether the definition of position in Ogre is same as PhysX? I try several days, but in vain.
So I try to set the position of sceneNode to match the mass center position of physx. It become worse...
How can I make them precisely coordinated ?

2. the same problem, why the character controller always float over the ground for a slight height?
here is my character controller :

#include <stdio.h>
#include "MyCharacterController.h"
#include "POgreActor.h"
#include <conio.h>

#define COLLIDABLE_MASK (1<<GROUP_COLLIDABLE_NON_PUSHABLE) | (1<<GROUP_COLLIDABLE_PUSHABLE)

MyCharacterController::MyCharacterController(NxControllerManager* manager , Ogre::SceneManager* smgr , NxScene *scene, NxVec3 pos)
{
mManager = manager;
gScene = scene;
mSceneManager = smgr;

mEntity = mSceneManager->createEntity( "myplayer" ,"robot.mesh");
mNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mNode->attachObject( mEntity );
mNode->setPosition( pos.x , pos.z, pos.y );
mNode->setScale(0.2,0.2,0.2);
mNode->yaw(Ogre::Radian(-90));

//get mesh size :
Ogre::AxisAlignedBox spbox = mNode->getAttachedObject("myplayer")->getBoundingBox();
Ogre::Vector3 min = spbox.getMinimum()*mNode->getScale();
Ogre::Vector3 max = spbox.getMaximum()*mNode->getScale();
Ogre::Real paddingFactor = Ogre::MeshManager::getSingleton().getBoundsPaddingFactor();
// adjust min & max to exclude the padding factor..
Ogre::Vector3 newMin = min+(max-min)*paddingFactor;
Ogre::Vector3 newMax = max+(min-max)*paddingFactor;
box_size = newMax - newMin;

//initialize character characteristic
gCharacterSpeed = 1;
gCharacterVec = NxVec3(1,0,0);
bPushCharacter = false;
gDefaultGravity = NxVec3(0,-9.8,0);

NxCapsuleControllerDesc desc;
desc.position.x = pos.x;
desc.position.y = pos.y;
desc.position.z = pos.z;
desc.height = box_size.y-7; //height;
desc.radius = ( (box_size.x+box_size.z) / 2 ) / 2 ;//radius;
desc.skinWidth = 0.1f;
desc.slopeLimit = cosf(NxMath::degToRad(45.0f));
desc.stepOffset = 0.5f;
desc.upDirection = NX_Y;
desc.climbingMode = CLIMB_EASY;
desc.callback = &mReport;

mController = mManager->createController(scene, desc);
actor = mController->getActor();


}

void MyCharacterController::Move(const NxVec3 &disp, NxU32 &flag)
{
mController->move(disp, COLLIDABLE_MASK, 0.001, flag);
}

NxActor* MyCharacterController::GetCharacterActor()
{
return actor;
}

void MyCharacterController::Advance(){

NxVec3 disp;
if(actor->getGlobalPosition().y != 0 )
disp = gDefaultGravity;

if (bPushCharacter)
{
NxVec3 horizontalDisp = gCharacterVec;
horizontalDisp.y = 0.0f;
horizontalDisp.normalize();
disp += horizontalDisp * gCharacterSpeed;
}

NxU32 collisionFlags;
Move( disp, collisionFlags);
mManager->updateControllers();

Ogre::Real quat[16];

actor->getGlobalPose().getRowMajor44(quat);//.getColumnMajor44(quat);
Ogre::Matrix4 m4(quat[0], quat[1], quat[2], quat[3],
quat[4], quat[5], quat[6], quat[7],
quat[8], quat[9], quat[10], quat[11],
quat[12], quat[13], quat[14], quat[15]);
mNode->setPosition( m4.getTrans().x , m4.getTrans().y - box_size.y/2 , m4.getTrans().z);
//mNode->setOrientation(m4.extractQuaternion());
}

void MyCharacterController::Forward(bool go , NxVec3 direction){
bPushCharacter = go;
gCharacterVec = direction ;
}