[SOLVED] body position problem

Rasengan

17-07-2008 12:05:35

Hello,

My NxOgre::body it's not @ the same pose in the remote debugger and render.
Someone have an idea?

Thanks for help.

Rasengan

17-07-2008 16:55:46

After trying to set mesh alignment with meshMagick, I've used this:

NxOgre::Body* body = ...


NxOgre::OgreNodeRenderable* renderable
= static_cast<NxOgre::OgreNodeRenderable*>(body->getRenderable());

Vector3 offset = ent->getBoundingBox().getCenter()-renderable->getScaleAsOgreVector3();
body->setGlobalPosition(offset);


and deal with mGraphicsModelScale... :?

Even is not elegant, it works with static body, actor and mesh are @ the same position.
When I set a dynamic body, the actor never match the mesh position.

I've to deal with all bodies like this? :evil:

Rasengan

18-07-2008 14:24:32

OK!

First: make sure that our geometry alignment is correct. I've used MeshMagick and set x,y,z @ center.

The problem was simply a scale factor in the .scene file! :) (I use DotSceneLoader)
I've scale the geometry with MeshMagick and leave the scale factor to 1 in the .scene file, and remove the unnecessary above code.

Everything works fine, static or dynamic object!

Another thing: if I use CN_ACCUMULATOR OR CN_VARIABLE for scene params, the dynamics objects seems to not synchronize exactly their positions with PhysX when these objects are moving... There is a sleep() or wakeUp() problem somewhere?

To solve this, I'm forced to use CN_FIXED. It's not a problem at all but with CN_FIXED, there is some camera collision stuttering...

betajaen

18-07-2008 15:57:47

If you use the accumulator, then you can tell all of your bodies including the Camera attached to it; to use the "interpolation" render mode. It should smooth out the movement across the frames. The position won't be exactly as it should be but near enough.

mcaden

21-07-2008 18:54:36

Rasengan,

Can you share your dotscene/NxOgre solution? Everything I'm finding is ridiculously outdated. I can't tell what works/what doesn't, what's final release code/what's old development or testing code.

Rasengan

22-07-2008 10:08:58

well, there is nothing really famous but here is the code:



/*
-----------------------------------------------------------------------------
Filename: TestNxOgre.h
-----------------------------------------------------------------------------

This source file is generated by the Ogre AppWizard.

Check out: http://conglomerate.berlios.de/wiki/doku.php?id=ogrewizards

Based on the Example Framework for OGRE
(Object-oriented Graphics Rendering Engine)

Copyright (c) 2000-2007 The OGRE Team
For the latest info, see http://www.ogre3d.org/

You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the OGRE engine.
-----------------------------------------------------------------------------
*/

#include <Ogre.h>
#include <NxOgre.h>
#include <ExampleApplication.h>
#include <DotSceneLoader.h>

#include "ExampleLoadingBar.h"


#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include "../res/resource.h"
#endif

#define DEFAULT_CAM_SPEED 5.0
#define TURBO 50.0


// Globals.
NxOgre::Scene* gScene;
NxOgre::Body* gCameraActor;
NxOgre::Actor* gCollisionActor;
NxReal gCamSpeed = DEFAULT_CAM_SPEED;
Ogre::Light* gMainLight;


class NxFrameListener: public ExampleFrameListener
{
private:

protected:

public:
NxFrameListener(RenderWindow* pWin, Camera* pCam)
: ExampleFrameListener(pWin, pCam)
{
}

bool frameStarted(const Ogre::FrameEvent &evt)
{
bool ret = ExampleFrameListener::frameStarted(evt);

if (!ret) return false;

if (mKeyboard->isKeyDown(OIS::KC_A)) {
translateHorz(-gCamSpeed);
}
else if (mKeyboard->isKeyDown(OIS::KC_D)) {
translateHorz(gCamSpeed);
}


if (mKeyboard->isKeyDown(OIS::KC_W)) {
translate(-gCamSpeed);
}
else if (mKeyboard->isKeyDown(OIS::KC_S)) {
translate(gCamSpeed);
}

if (mKeyboard->isKeyDown(OIS::KC_Q)) {
translateVert(gCamSpeed);
}
else if (mKeyboard->isKeyDown(OIS::KC_Z)) {
translateVert(-gCamSpeed);
}

if (mMouse->getMouseState().X.rel != 0) {
pan(-mMouse->getMouseState().X.rel * 0.13);
}
if (mMouse->getMouseState().Y.rel != 0) {
tilt(-mMouse->getMouseState().Y.rel * 0.13);
}

if (mMouse->getMouseState().buttonDown( OIS::MB_Right ))
{
gCamSpeed = TURBO;
}
else
{
gCamSpeed = DEFAULT_CAM_SPEED;
}

if (mKeyboard->isKeyDown(OIS::KC_SPACE))
{
gScene->setGravity(Vector3(0, -70, 0));
}

return true;
}

void translateVert(NxReal vTrans)
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(0, vTrans, 0);
gCameraActor->addForce(trans, NX_IMPULSE, true);
}

void translate(NxReal rtrans)
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(0, 0, rtrans);
gCameraActor->addForce(trans, NX_IMPULSE, true);
}

void translateHorz(NxReal hTrans)
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(hTrans, 0, 0);
gCameraActor->addForce(trans, NX_IMPULSE, true);
}

/** \brief Horizontal rotational movement */
void pan(NxReal hRot)
{
mCamera->yaw(Ogre::Degree(hRot));
}

/** \brief Vertical rotational movement */
void tilt(NxReal vRot)
{
mCamera->pitch(Ogre::Degree(vRot));
}

};


class NxOgreApp : public ExampleApplication
{
public:
NxOgreApp()
{
}

~NxOgreApp()
{
destroyNxWorld();
}

protected:
NxOgre::World* mWorld;

//ExampleLoadingBar mLoadingBar;

/*void loadResources(void)
{
mLoadingBar.start(mWindow, 1, 1);

// Turn off rendering of everything except overlays
mSceneMgr->clearSpecialCaseRenderQueues();
mSceneMgr->addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
mSceneMgr->setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);

// Initialise the rest of the resource groups, parse scripts etc
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
ResourceGroupManager::getSingleton().loadResourceGroup(
ResourceGroupManager::getSingleton().getWorldResourceGroupName(),
false, true);

ResourceGroupManager::getSingleton().loadResourceGroup("Acropolis",true, false);

// Back to full rendering
mSceneMgr->clearSpecialCaseRenderQueues();
mSceneMgr->setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);

mLoadingBar.finish();
}*/



void createNxWorld(void)
{
NxOgre::PhysXParams physXparams;
physXparams.setToDefault();
physXparams.mTimeController = NxOgre::PhysXParams::TC_OGRE;
physXparams.mUseLog = true;
//physXparams.mDebugVisualisation.mCollisionEdges = true;

mWorld = new NxOgre::World(physXparams);
//mWorld->createDebugRenderer(mSceneMgr);
mWorld->getPhysXDriver()->createDebuggerConnection();
}

void createNxBarrels()
{
NxOgre::ActorParams actorParams;
actorParams.setToDefault();
actorParams.mMass = 30.0;

// Adding mesh to NxOgre ressources.
NxOgre::Resources::ResourceSystem::getSingleton()->addMeshAs("file://barrel.nxs","barrelCollisionMesh");

// Getting the Mesh.
NxOgre::Resources::Mesh* barrelCollisionMesh =
NxOgre::Resources::ResourceSystem::getSingleton()->getMesh("barrelCollisionMesh");

// Create some barrels.
for (int y=100; y < 200; y+=25)
{
for (int x=30; x < 110; x+=10)
{
for (int z=0; z < 80; z+=10)
{
std::string uid("id_barrel"+y);uid+=""+x;uid+=""+z;

NxOgre::NodeRenderableParams nrparams;
nrparams.setToDefault();
nrparams.mIdentifier = uid;
nrparams.mIdentifierUsage = NxOgre::NodeRenderableParams::IU_Create;
nrparams.mMode = NxOgre::RenderableSource::RM_Interpolate;
nrparams.mGraphicsModel = "Barrel.mesh";

NxOgre::Body* b = gScene->createBody
(
uid,
new NxOgre::Convex(barrelCollisionMesh),
Vector3(x, y, z),
nrparams,
actorParams
);
}
}
}

}


void createNxScene(void)
{
NxOgre::SceneParams sceneParams;
sceneParams.setToDefault();
sceneParams.mRenderer = NxOgre::SceneParams::RN_OGRE;
sceneParams.mGravity = NxVec3(0, 0, 0);
sceneParams.mFloor = false;
sceneParams.mController = NxOgre::SceneParams::CN_ACCUMULATOR;

gScene = mWorld->createScene("Main Scene", sceneParams);

// Create sablon node.
SceneNode* sablonNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("SablonNode");

// Load sablon scene and attach to node.
DotSceneLoader sceneLoader;
sceneLoader.parseDotScene("sablon_collision.scene", "General", mSceneMgr, sablonNode);

// Create sablon collision geometry.
createCollisionGeometry(sablonNode->getPosition());

// Add some dynamic barrels.
createNxBarrels();

}


void createNxCameraActor(void)
{
NxOgre::NodeRenderableParams renderableParams;
renderableParams.setToDefault();
renderableParams.mIdentifier = "CakeSmartCamera";
renderableParams.mIdentifierUsage = NxOgre::NodeRenderableParams::IU_Create;
renderableParams.mMode = NxOgre::RenderableSource::RM_Interpolate;

NxOgre::ActorParams actorParams;
actorParams.setToDefault();
actorParams.mMass = 1;
actorParams.mDensity = 0;
actorParams.mLinearDamping = 10;
actorParams.mAngularDamping = 10;
actorParams.mBodyFlags |= NX_BF_DISABLE_GRAVITY;
actorParams.mBodyFlags |= NX_BF_FROZEN_ROT;

NxOgre::Pose cameraPose(Vector3(0, 50, 0), mCamera->getOrientation());

gCameraActor = gScene->createBody("CakeSmartCamera", new NxOgre::Sphere(1), cameraPose, renderableParams, actorParams);

NxOgre::OgreNodeRenderable* renderable;

if (gCameraActor)
{
renderable =
static_cast<NxOgre::OgreNodeRenderable*>
(
gCameraActor->getUserData()->RenderPtr->getRenderable()
);
}

if (mCamera->isAttached())
mCamera->getParentSceneNode()->detachObject(mCamera);

renderable->getNode()->attachObject(mCamera);

}

void createCamera(void)
{
ExampleApplication::createCamera();

mCamera->setFOVy(Radian(Degree(75)));
mCamera->setNearClipDistance(0.1);
mCamera->setFarClipDistance(10000);
mCamera->setPosition(0, 0, 0);
mCamera->lookAt(0, 0, -1);
}

void createCollisionGeometry(Vector3 pCollisionPose)
{
// Adding mesh to NxOgre ressources.
NxOgre::Resources::ResourceSystem::getSingleton()->addMeshAs("file://sablonCollision.nxs","sablonCollisionGeometry");

// Getting the Mesh.
NxOgre::Resources::Mesh* collisionMesh =
NxOgre::Resources::ResourceSystem::getSingleton()->getMesh("sablonCollisionGeometry");

// Link the mesh with static actor.
gCollisionActor =
gScene->createActor
(
"Collision Mesh",
new NxOgre::TriangleMesh(collisionMesh),
pCollisionPose,
"static: yes"
);

}


void destroyNxWorld(void)
{
if (NULL != mWorld)
{
mWorld->getPhysXDriver()->destroyDebuggerConnection();
delete mWorld;
}
}


void chooseSceneManager(void)
{
mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE);
}



// Scene creation
void createScene(void)
{
// Set ambient light
//mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

gMainLight = mSceneMgr->createLight("Main Light");
gMainLight->setType(Ogre::Light::LT_POINT);
gMainLight->setDiffuseColour(0.8, 0.8, 0.8);
//gMainLight->setDirection(mCamera->getDirection());
//l->setAttenuation(100, 1, 0.5, 0.5);
gMainLight->setCastShadows(true);

mSceneMgr->setSkyBox(true, "Examples/MorningSkyBox", 5000);

// Create PhysX stuff.
createNxWorld();
createNxScene();
createNxCameraActor();

}

void createFrameListener()
{
mFrameListener = new NxFrameListener(mWindow, mCamera);
mFrameListener->showDebugOverlay(false);
mRoot->addFrameListener(mFrameListener);
}

};




#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char**argv)
#endif
{
// Create application object
NxOgreApp app;

try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}

return 0;
}

#ifdef __cplusplus
}
#endif


Need some refactor, especially for the camera but it's just for testing.

The world gravity start with 0, some barrels are created in the sky. We can push the barrels and with the SPACE key, the gravity is changed (with high value..) and we can see them falling, and colliding with some parts of the geometry.

The rendered geometry is loaded by DotSceneLoader and the corresponding basic collision geometry is a TriangleMesh based on nxs file.

We can use a "camera turbo" when we "right click" on the mouse but with the turbo the collisions not match (especially when strafing). CCD is required.

This example inherit from ExampleApplication and ExampleFrameListener, so I've put some comments in ExampleFrameListener::frameStarted, leaving only the mouse and keyboard inputs processing.

For the problem of geometry alignment, the original camera position is set to 0 in the createCamera() and I deal with camera actor position in the createNxCameraActor() to set it's position. There is no more problem with that.

betajaen

22-07-2008 10:30:31

Question; Does this even work? "std::string uid("id_barrel"+y);uid+=""+x;uid+=""+z; ". For the record; if you want a load of barrels sequentially numbers, then call them all barrel. NxOgre will intelligently name the next barrel; barrel1, barrel2, etc.

Rasengan

22-07-2008 10:39:48

Does this even work? "std::string uid("id_barrel"+y);uid+=""+x;uid+=""+z; ".
Yes

For the record; if you want a load of barrels sequentially numbers, then call them all barrel. NxOgre will intelligently name the next barrel; barrel1, barrel2, etc.



nrparams.mIdentifier = "barrel";
...
NxOgre::Body* b =
gScene->createBody
(
nrparams.mIdentifier,
new NxOgre::Convex(barrelCollisionMesh),
Vector3(x, y, z),
nrparams,
actorParams
);


App crash saying that scene node with name "barrel" already exists..

betajaen

22-07-2008 11:55:38

Oh. NxOgre can handle duplicate names doesn't mean Ogre can. But we can always trick it.

mScene->createBody("Barrel;barrel.mesh", new NxOgre::Convex(barrelCollisionMesh), Vector3(x, y, z), actorParams);

mcaden

22-07-2008 12:02:27

Oh sorry, I meant the dotscene loader itself. Which one are you using?

Rasengan

22-07-2008 12:16:29

Oh. NxOgre can handle duplicate names doesn't mean Ogre can. But we can always trick it.

mScene->createBody("Barrel;barrel.mesh", new NxOgre::Convex(barrelCollisionMesh), Vector3(x, y, z), actorParams);


It works! :wink:

But what about with NodeRenderableParams ? ( RM_Interpolate, even it seems that interpolation work)

Rasengan

22-07-2008 12:27:13

Oh sorry, I meant the dotscene loader itself. Which one are you using?

this: http://www.ogre3d.org/wiki/index.php/New_DotScene_Loader

:arrow: Some .scene exporters use different names for child nodes attributes. Ex: Blender export rotations by adding "rotation x=..." and some versions of DotSceneLoader ckeck for "qx" attribute (from quaternions), maybe you have to check this, and update some parts of the code, but there are many versions, so...maybe you don't do anything :)

betajaen

22-07-2008 12:30:59

But what about with NodeRenderableParams ? ( RM_Interpolate, even it seems that interpolation work)

Body* b = mScene->createBody("Barrel;barrel.mesh", new NxOgre::Convex(barrelCollisionMesh), Vector3(x, y, z), actorParams);
b->setRenderMode(RenderableSource::RM_Interpolate);

Rasengan

22-07-2008 13:50:14

oups, sry.. :wink:

mcaden

22-07-2008 15:47:50

Thanks Ras, I read somewhere in the thread for that loader that there are "more stable and better featured" loaders out there. But my main concern is whether it works or not.

I've been rather busy as my wife is in the last couple weeks of pregnancy so I haven't had the time to try and plug in 2 or 3 options and find/make one work.

mcaden

02-08-2008 07:38:54

it's things like this:

//! @todo Fix this crap!

that send up some red flags about that scene loader. It does appear to be the newest and best other than ogremax though...but I don't use 3ds max so I don't think ogremax is the right choice as it would probably require a lot more tweaking to work with code exported from blender.

I'll just have to tweak it a bit so it'll load NxOgre objects for those that should be, and leave as Ogre those I don't want.