Linking an actor with Ogre Camera

Rasengan

10-07-2008 17:59:15

Hello,


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

gCameraActor->setGlobalPosition(mCamera->getPosition());
gCameraActor->setGlobalOrientation(mCamera->getOrientation());

return ret;
}


With this simple code, the camera collision run's well with pushable objects, but not with static objects, for sure.

Obviously, to deal with both static and dynamic objects, the code would probably looks like this:



mCamera->setPosition(gCameraActor->getGlobalPositionAsOgreVector3());
gCameraActor->setGlobalOrientation(mCamera->getOrientation());


and not like the first example.

We can see in ExampleFrameListener::frameStarted(...) the member mTranslateVector witch is used for mCamera translations.

Has someone an idea to deal with this member to set the actor position, or maybe I'm completly wrong about the way I want to link actor and camera? I've to deal with Forces?

Thanks for reply.

betajaen

10-07-2008 18:17:16

You should use a Camera attached to an NxActor moved around using forces, anything else is overly complicated and results in many bugs or workarounds.

This is what I use in Cake 4 and works very well:

Setup code

class SmartCamera {
void setup() {
NodeRenderableParams renderableParams;
renderableParams.setToDefault();
renderableParams.mIdentifier = "CakeSmartCamera";
renderableParams.mIdentifierUsage = NodeRenderableParams::IU_Create;
renderableParams.mMode = RenderableSource::RM_Interpolate;

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 actorPose(
Vector3(0,15,22)
);

mActor = scene->createBody("CakeSmartCamera", new NxOgre::Sphere(0.25f), actorPose, renderableParams, actorParams);

if (mActor)
mRenderable = static_cast<OgreNodeRenderable*>(mActor->getVoidPointer()->RenderPtr->getRenderable());

if (mCamera->isAttached())
mCamera->getParentSceneNode()->detachObject(mCamera);
mRenderable->getNode()->attachObject(mCamera);
}
};



Movement code

class SmartCamera {
// ...

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

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

void translateHorz(NxReal hTrans) {
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(hTrans, 0, 0);
mActor->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));
}
};


Simple keyboard and mouse mapping

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


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

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

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

Rasengan

10-07-2008 18:29:59

wow!

We can use cake?

Rasengan

10-07-2008 18:44:13

Yes, thank you!

betajaen

10-07-2008 19:07:12

Well you can use that from Cake but I frown upon people using Cake as a base for their application though.

Rasengan

10-07-2008 19:14:53

Betajean your code example have solved my problems!

I've have made little changes to adapt with my app and now all works very well! Tank you!

Maybe I'll use Cake too as a base app!

betajaen

10-07-2008 19:30:03

I frown upon people using Cake as a base for their application though.

I am now frowning. You can make a NxOgre/Ogre application pretty easily, you don't need Cake.

Rasengan

10-07-2008 19:37:17

I frown upon people using Cake as a base for their application though.

I am now frowning. You can make a NxOgre/Ogre application pretty easily, you don't need Cake.


Ha ok, I had not understood. (because my poor english...), well, I tweak a little OgreAppWizard to generate Ogre<->NxOgre projects, it's sufficient at the moment.

Thanks for help!

jonnys

19-07-2008 19:38:31

When i try to use the code that betajaen gave in a previous post i get the following errors:


------ Build started: Project: OgreTest, Configuration: Debug Win32 ------
1>Compiling...
1>Main.cpp
1>: error C2227: left of '->RenderPtr' must point to class/struct/union/generic type
1> type is 'void *'
1>: error C2227: left of '->getRenderable' must point to class/struct/union/generic type
2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


This is my system:

NxOgre 1.0.20 Bleeding Edge (Debug) started. Working with
- PhysX => 2.7.3 (273)
- Ogre => 1.4.9 (Eihort)
- Hardware => Probably
- Platform => Windows (Debug)



What can i do to fix it?

Rasengan

19-07-2008 19:48:27

Try this:


mRenderable = static_cast<NxOgre::OgreNodeRenderable*>(mActor->getRenderable());

mcaden

19-07-2008 19:50:39

I just fixed this for myself :)

replace

mRenderable = static_cast<OgreNodeRenderable*>(mActor->getVoidPointer()->RenderPtr->getRenderable());


with

mRenderable = static_cast<OgreNodeRenderable*>(mActor->getUserData()->RenderPtr->getRenderable());







EDIT: I tried Rasengan's fix instead of mine. Didn't work for me, I get error C2039: 'getRenderable' : is not a member of 'NxOgre::Actor'

betajaen

19-07-2008 19:57:30

"getRenderable" is part of Body and/or RenderableSource though :D

jonnys

20-07-2008 21:27:57

I am having a problem with my cake smart camera. I set it up and the program runs but then I test it by creating a box body to collide with. When I move the camera to the box body, It goes through it does not collide, or push the box (which is what I want it to do). Is it a special Actor parameter that I did not set?

Here is my code (Setting up camera) and a box body to test camera collision:

//---------------------------------------------------------NXOGRE---------------------------------
using namespace NxOgre;


//nxogre testing
mWorld = new NxOgre::World("time-controller: ogre");

//nxogre scene
mScene = mWorld->createScene("Main", "gravity: 0 -9.788 0, floor: yes, renderer: ogre");

ActorParams ap;
ap.setToDefault();
ap.mMass = 0.2;
ap.mDensity = 2;

//ap.mLinearDamping = 10;
//ap.mAngularDamping = 10;
ap.mBodyFlags |= NX_BF_DISABLE_GRAVITY;
//ap.mBodyFlags |= NX_BF_FROZEN_ROT;

body = mScene->createBody("Crate;box.mesh", new NxOgre::Cube(50.0f), Vector3(700,100,730),ap);

//A renderable node to be used if the camera has an actual model
OgreNodeRenderable* mRenderable2(0);
mRenderable2 = static_cast<OgreNodeRenderable*>(body->getUserData()->RenderPtr->getRenderable());
mRenderable2->getNode()->showBoundingBox(true);


//Setting up NxOgre with the ogre camera
//A renderable node to be used if the camera has an actual model
OgreNodeRenderable* mRenderable(0);

NodeRenderableParams renderableParams;
renderableParams.setToDefault();
renderableParams.mIdentifier = "NxOgreCam";
renderableParams.mIdentifierUsage = NodeRenderableParams::IU_Create;
renderableParams.mMode = RenderableSource::RM_Interpolate;


ActorParams actorParams;
actorParams.setToDefault();
actorParams.mMass = 0.5;
actorParams.mDensity = 1;
actorParams.mLinearDamping = 10;
actorParams.mAngularDamping = 10;
actorParams.mBodyFlags |= NX_BF_DISABLE_GRAVITY;
//actorParams.mBodyFlags |= NX_BF_FROZEN_ROT;
//actorParams.mBodyFlags = NX_BF_KINEMATIC;

NxOgre::Pose actorPose(Vector3(mCamera->getPosition()));

mCamActor = mScene->createBody("NxOgreCam", new NxOgre::Sphere(10.0f), actorPose, renderableParams, actorParams);


if (mCamActor)
mRenderable = static_cast<OgreNodeRenderable*>(mCamActor->getUserData()->RenderPtr->getRenderable());

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

//Add the camera to the NxActor
mRenderable->getNode()->attachObject(mCamera);

//----------------------------------------------NXOGRE----------------------------------------------------


This is my code for moving the camera:


if(mKeyboard->isKeyDown(KC_A))
// mTranslateVector.x = -mMoveScale; // Move camera left
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(-50.0f, 0, 0);
mCamActor->addForce(trans, NX_IMPULSE, true);
}

if(mKeyboard->isKeyDown(KC_D))
// mTranslateVector.x = mMoveScale; // Move camera RIGHT
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(50.0f, 0, 0);
mCamActor->addForce(trans, NX_IMPULSE, true);
}

if(mKeyboard->isKeyDown(KC_UP) || mKeyboard->isKeyDown(KC_W) )
// mTranslateVector.z = -mMoveScale; // Move camera forward
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(0, 0, -50.0f);
mCamActor->addForce(trans, NX_IMPULSE, true);

}

if(mKeyboard->isKeyDown(KC_DOWN) || mKeyboard->isKeyDown(KC_S) )
// mTranslateVector.z = mMoveScale; // Move camera backward
{
Ogre::Vector3 trans = mCamera->getOrientation() * Ogre::Vector3(0, 0, 50.0f);
mCamActor->addForce(trans, NX_IMPULSE, true);
}


Also I put this in because I was not sure if the camera was properly linked to the mCamActor

bool frameStarted(const FrameEvent &evt)
{
mAnimationState->addTime(evt.timeSinceLastFrame);

mCamera->setPosition(mCamActor->getGlobalPositionAsOgreVector3());


Note:: My ultimate goal is to set up a FPS camera that collides with objects like crate and weapons. :D

Rasengan

21-07-2008 00:20:32

It's not necessary to set the camera position in the framelistener, because you have attached it to a node. There is no collision in the remote debugger tool? The position of you camera and your cube is the same on both the render and debugger tool? I had many problems with this.

ps: it's not better to set your camera mass to 1.0, at least?

betajaen

21-07-2008 00:35:09

Everything in the remote debugger is exactly how it is positioned in PhysX and NxOgre; neither modifies the position - unless you use interpolation, and only then it's very slight.

Mass should be 1.0 or higher (1.0 is fine) and density should be 0.

jonnys

21-07-2008 00:49:38

Thank you guys for being so helpful...but I don't understand.

1. First of all whats a remote debugger?, and what does it have to do with me not seeing any collision rendered.

2. Also what do I have to do to implement collision with NxOgre bodies/actors?

And to Rasengan
There is no collision in the remote debugger tool?
What do you mean?

3. Are there any problems with my code why I'm not seeing the collision?

mcaden

21-07-2008 05:31:05

I had the same prob. Rasengan was so kind as to help me with that:

If you inherit from ExampleFrameListener, remove or comment the original camera position computing (no more need to compute this...), leaving keyboard and mouse inputs and don't forget to set the new camera position based on to the attached actor.


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

if (!ret) return false;

... camera actor translations and mouse mapping code...

mCamera->setPosition(gCameraActor->getGlobalPositionAsOgreVector3());
...


The camera will collide with all defined static or dynamic actors. (or body...)

If is a static body, the camera will stop, else PhysX is applied.

:idea: Edit: mcaden, consider in using the visual remote debugger tool, all PhysX stuff is rendered into this tool, so you can easily compare the effective render and your PhysX world.



2nd, the remote debugger is a tool that is a part of the PhysX SDK. You can go to \Bin\win32\RemoteDebugger.exe and run that.

You'll need to run that, and change the code referring to it to:

mWorld->getPhysXDriver()->createDebuggerConnection("localhost");

and run your program. It'll connect to the Remote debugger. Move around and collide a bit in your game, then go back to the remote debugger. Hit the square button (stop) and explore a bit. You'll find lists of items and you can view a timeline of the colliding objects as bounding boxes.

Hope this helps.

jonnys

21-07-2008 07:45:37

Thanks alot... I used the Visual remote debbugger to find out that my box mesh and the body (collision model) are not aligned properly (so sometimes I "collide" in "mid-air" and sometimes I go through the box rendered in the ogrescene)... I followed all the instructions. What could be the reasons it is misaligned?

mcaden

21-07-2008 08:27:35

Did you remove?

mCamera->setPosition(mCamActor->getGlobalPositionAsOgreVector3());


Make sure you're setting the position through NxOgre and not Ogre by using Pose so there's not a difference between the collision box and the mesh.

I did that with this code:


Entity *ent = mSceneMgr->createEntity( "Garm", "Garm.mesh" );
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "GarmNode", Vector3( 0, 0, 0 ) );
node->attachObject( ent );

NodeRenderableParams vp;
vp.setToDefault();
vp.mGraphicsModel = "Garm.mesh";
vp.mGraphicsModelScale = NxVec3(1, 1, 1);
vp.mIdentifier = "GarmNode";
vp.mIdentifierUsage = vp.IU_Use;
NxOgre::Pose actorPose(10, 15, 35 );

Ogre::AxisAlignedBox garmBounds = node->getAttachedObject("Garm" )->getBoundingBox();
mPlayer = mScene->createBody(vp.mIdentifier, new Cube( garmBounds.getSize() ), actorPose, vp,
ActorParams("mass: 10"));
}


So that way the collision box is the same exact size as the Mesh's bounding box, and they are aligned right. You'll notice I put the mesh at 0,0,0, and then set the position with

NxOgre::Pose actorPose(10, 15, 35 );




I've only been using Ogre for about 2 weeks now, and NxOgre for like a week so if I'm wrong, somebody please correct me.

jonnys

21-07-2008 17:39:35

Thanks for the replies guys... but now...I am officially fed up... :x I do everything that you guys say to try and help me but the collision model and the mesh are still not aligned.

I found out something though..that when I change actorPose to actorPose(0,0, 0); The collision model and mesh are aligned.

But as soon as I position the Body by using actorPose and changing it to say.. actorPose(10, 15, 35 ); The mesh and collision model become misaligned.

Is it something with NxOgre itself? I am going to try another model.

btw... When I created the model in milkshape3d I created the box in the center of the axis..

mcaden

21-07-2008 19:10:49

Did you change mass back to 1?

Can you post your updated code?

betajaen

21-07-2008 19:21:30

Is it something with NxOgre itself? I am going to try another model.

No it isn't NxOgre. It doesn't do anything like that to produce a strange result.

Can you just try some well tested code, instead of playing around with the params.

const Ogre::Vector3 garm_bb_size = Ogre::Vector3(2,2,2);
mScene->createBody("garm.mesh", new Cube(garm_bb_size), Ogre::Vector3(10,15,35), "mass: 10");

netsurferj

21-07-2008 19:29:27

I have no idea if this might help. I had the same "weird results", but that was because I scaled the scene node of the body, and not the collision model, so the model was larger than the displayed mesh. You scale the collision model using ShapeParams.

jonnys

21-07-2008 20:10:04

I think I got it. But I am not 100% sure (prob 70 :) ) I know exactly what the problem was. My camera is colliding with the box model properly now (both the Remote Debugger and Ogre Scene correspond) , so its ok. These are the things I changed:

1. I used some of the code mcaden showed me.

2. I had mCamera->setPosition(mCamActor->getGlobalPositionAsOgreVector3()); in frameStarted and I removed it. Don't know why it was there in the first place.

3. I made my camera sphere collision model bigger from 1 to 10 NxOgre::Sphere(10.0f) because I saw in the remote debugger that, the sphere was kinda too small and was missing the box collision model, even though, in ogre, my camera was going through it (the box) .

4. And I found out that for my camera actor movement code, I used Ogre Reals and not NxReal. I guess that can cause inaccuracy.

Overall I think the problem was my camera orientation and/or the size of the camera collision sphere.
It has to be big enough to actually enclose your camera/viewport. I guess my problem was that the small camera sphere collision model was not at the center of my ogre camera so it did not correspond with what I was seeing on my monitor.

I also think it has something to do with the collision model scaling that netsurferj mentioned, but that was in the code that mcaden posted earlier though.

Again thanks to mcaden, Rasengan and last but not least betajaen.. And all the other persons that helped me. :) This was one of the fastest responding forums I have ever been in.

betajaen

21-07-2008 20:41:51

Glad you have it fixed. But a "10.0f" sphere is huge, it's like almost three times the height of you.