Binding a camera to a body?

ocrim74

27-09-2006 11:18:11

Hi,

I have been working with Ogre and NxOgre for about 3 weeks. I use a convexShape as body, created from a mesh. Like in the examples. I have a static body, created from a mesh with walls. The collision detection works fine. Now I want to create a walkthrough in the building. My convexShape should be the character and I want to bind a camera to it. In my experiments I just was able to bind a camera to an entity, but how can I bind it to a body? How can I get the entity of the body? I tried "Betajaen's Top Tip!" at http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=2013. This works, but it only works if I press a key to move my convexShape.

Is there a better way to create a behavior like a character? I tried blueprint but I think its not finished yet, is that right?

Thanks for your answers, :wink:

ocrim

betajaen

27-09-2006 11:47:17

No, the current character system does work (sort of). You can't jump with it yet though so it's a little new and buggy although the old system is on the code (commented out) if you want to use that.

If you want the camera bound the body, then just attach it to the body's SceneNode.

myBody->mNode->attachObject(mCamera);

(Just remember to un-attach it before you delete world, as it'll delete the Camera and it'll crash).

The best example for this sort of thing (apart from the character tutorials) is Tutorial 116 in the CVS version of NxOgre, it binds the camera to a spherical body and allows proper movement in all axises.

If you don't use the CVS version, that tutorial can be found here: http://nxogre.cvs.sourceforge.net/nxogr ... iew=markup

BlasterN

27-09-2006 12:32:21

@betajaen
Here my jump code. only need to tweak the values.
I use:
CHARACTER_GRAVITY 90
mJumpHeight 95
mJumpTime 0.64
And my hero jump... a lot ^^
I wil send you the code when I have inet at home (a week)

if(mJumpTimeElapsed > mJumpTime)
mJumping=false;

if (mJumping)
{
//float h = 9.80665*mJumpTime*mJumpTime + mJumpTime*mJumpHeight;
//float h= mJumpTime*(9.80665*mJumpTime+mJumpHeight);
//mMovementVector.y += h*mJumpTimeElapsed - 9.80665*mJumpTimeElapsed;
mMovementVector.y += ( mJumpTime * (CHARACTER_GRAVITY * mJumpTime + mJumpHeight) ) * mJumpTimeElapsed
- (CHARACTER_GRAVITY * mJumpTimeElapsed);
}
else
{
mMovementVector.y -= (CHARACTER_GRAVITY *_time );
}


@ocrim74
check this code, do what you want but have code that you will never use because i part of my engine.
The code dont manage orientations because in other part I do setAutoTracking(true,node)
mOwner-getScenemanager() is the SceneMnaager you are using.
getNxScene() the nxOgre::scene

XCAMERA.H
#ifndef XCAMERA__H
#define XCAMERA__H

#include "OgreCamera.h"
#include "MapLoader.h"
#include "Functions.h"
#include "Globals.h"

namespace BENGINE
{

/**
Manage the Camera of each Map\n
@note
the camera could be, cinematic and player cam.\n
@note
<b>Cinematic camera</b>: Updated by a Entity\n
<b>Player Camera</b>: Updated by CharacterHero\n
@note
How to update the camera. As you can see the only method available are setPosition, setOrientation
Yaw, Pitch, Rool & lookAt.\n
So you need to create a Node that give you the camera position and Orientation BUT NEVER ATTACH the camera
to it. Update the values with code.
@remark
the name os the camera is allways the same: "MainCamera"

*/
class XCamera : public nxOgre::controllable, public NxUserControllerHitReport
{
public:
enum XCameraType{XCamera_CINEMATIC,XCamera_PLAYERCAM};
protected:
XCameraType mType;
Ogre::Camera* mCam;
Ogre::Viewport* mViewport;
MapLoader* mOwner;
Ogre::Vector3 mCamPosition;
Ogre::Quaternion mCamOrientation;

nxOgre::scene* mNxScene;
NxController* mController;

public:
XCamera(MapLoader* ml);
~XCamera()
{
//hide()
}
void setupPhysics();

void show();

void hide();

/**
WARNING! you have to be sure where you go, this Teleport the camera, no collisions
you can stuck the camere in a site that it will never came back.
*/
void setPosition(const Ogre::Vector3& v);

void setOrientation(const Ogre::Quaternion& q)
{
mCam->setOrientation(q);
}
void yaw(Ogre::Radian& rot)
{
mCam->yaw(rot);
}
void pitch(Ogre::Radian& rot)
{
mCam->pitch(rot);
}
void roll(Ogre::Radian& rot)
{
mCam->roll(rot);
}
/**
Move the camera to the position.\n
consider it like a alias of setPosition but with physics enabled. no teleport.
*/
void moveTo(const Ogre::Vector3& v);

Ogre::Camera* getCamera()
{
return mCam;
}

bool isCinematic()
{
return mType == XCamera_CINEMATIC ? true : false;
}
/**
Update Movement/Physics
*/
void simulate(float _time);
/**
*/
NxControllerAction onControllerHit(const NxControllersHit& hit);
/**
*/
NxControllerAction onShapeHit(const NxControllerShapeHit& hit);
};
}


#endif


XCAMERA.CPP
#include "XCamera.h"
#include "MapLoader.h"


namespace BENGINE
{
//-----------------------------------------------------------------------
XCamera::XCamera(MapLoader* ml): mOwner(ml),
mCamOrientation(Ogre::Quaternion::IDENTITY),
mCamPosition(Ogre::Vector3::ZERO),
mType(XCamera_PLAYERCAM)
{
#ifdef NDEBUG
mNxScene=mOwner->getNxScene();
setupPhysics();
#endif
show();
OgreLog("[XCamera] new");
OgreLog(mCam->isAttached() == true ? "attached" : "noattached");
}
//-----------------------------------------------------------------------
void XCamera::show()
{
// Create the camera
mCam = mOwner->getSceneManager()->createCamera("MainCamera");
OgreLog("[XCamera] Camera Created: MainCamera.");

mCam->setPosition(this->mCamPosition);
#ifdef NDEBUG
mController->setPosition(NxExtendedVec3(mCamPosition.x,mCamPosition.y,mCamPosition.z));
#endif
mCam->setOrientation(this->mCamOrientation);
mCam->setNearClipDistance(5);

// Create one viewport, entire window
mViewport = Globals::getSingletonPtr()->mWindow->addViewport(mCam);
mViewport->setBackgroundColour(Ogre::ColourValue(0,0,0));

// Alter the camera aspect ratio to match the viewport
mCam->setAspectRatio(
Ogre::Real(mViewport->getActualWidth()) / Ogre::Real(mViewport->getActualHeight()));

OgreLog("[XCamera] Viewport Created");
}
//-----------------------------------------------------------------------
void XCamera::hide()
{
// save camera position and orientation
mCamPosition = mCam->getPosition();
mCamOrientation = mCam->getOrientation();

OgreLog("[XCamera] removeViewport.");
BENGINE::Globals::getSingletonPtr()->mWindow->
removeViewport(this->mViewport->getZOrder());
// destroy the camera and viewport

OgreLog("[XCamera] destroyCamera.");
mOwner->getSceneManager()->destroyCamera(mCam);
mCam=0;
mViewport=0;
}
//-----------------------------------------------------------------------

void XCamera::setupPhysics()
{
if (mNxScene)
{
// create the NxCapsuleController
NxCapsuleControllerDesc desc;
desc.setToDefault();
desc.height = NxMath::abs(1);
desc.radius = NxMath::abs(5);
desc.position.set(0,0,0);
desc.slopeLimit = 0; // its a camera!
desc.skinWidth = 0.25f; // I made this bigger because the camera can move very fast
desc.stepOffset = 0.40f;
desc.callback = this;
desc.upDirection = NX_Y;
mController = nxOgre::mControlMgr.createController(mNxScene->mScene,desc);

// adjust position to the real one.
mController->setCollision(true);
mController->setPosition(NxExtendedVec3(0,0,0));

OgreLog("[CharacterHero] Create Physics body.");

}
}
//-----------------------------------------------------------------------
void XCamera::setPosition(const Ogre::Vector3& v)
{
mCam->setPosition(v);
#ifdef NDEBUG
mController->setPosition(NxExtendedVec3(v.x,v.y,v.z));
#endif
}
//-----------------------------------------------------------------------
void XCamera::simulate(float _time)
{
OgreLog("simluate??!");
return;
}

void XCamera::moveTo(const Ogre::Vector3& v)
{
NxU32 mCollisionFlags;
NxVec3 translate=(NxTools::convert(v)-mController->getActor()->getGlobalPosition())*0.8;
mController->move(translate, mNxScene->findGroupIndex("default"), 0.5f, mCollisionFlags);
Ogre::Vector3 newPosition = NxTools::convert(mController->getActor()->getGlobalPosition());
mCam->setPosition(newPosition);

}
//-----------------------------------------------------------------------
NxControllerAction XCamera::onShapeHit(const NxControllerShapeHit& hit)
{
//OgreLog("dsajfnsdia");
return NX_ACTION_NONE;
}
//-----------------------------------------------------------------------
NxControllerAction XCamera::onControllerHit(const NxControllersHit& hit)
{
//OgreLog("?GDS?X?GD");
return NX_ACTION_NONE;
}
}

ocrim74

27-09-2006 13:50:55

Hi,

thank you for your helpful replies.

I tried the suggestion of betajean and it works fine. ;-)

Now I have a problem with the postitioning of the camera and my body at the same position.

If I set the Postion to Vector3(0,0,0) they both appear at this position, but if I choose another position they appear at different places.

It looks like this. It is my startposition inside my building.


myConvex->mNode->attachObject(mCamera);
myConvex->setGlobalPosition(Vector3(-26,0,6));
mCamera->setPosition(Vector3(-26,0,6) );


Do you have an idea what the problems is? Do I have to make a conversion of the positioning values? Is the problem in setting Position and GlobalPosition?

@BlasterN: I will try your solution later. ;-)

Thank you,

[Edit]

Sorry, now I know whats wrong. The position of the camera is set relative to myConvex.

If I do it this way, it works fine. ;-)


myConvex->mNode->attachObject(mCamera);
myConvex->setGlobalPosition(Vector3(-26,0,6));
mCamera->setPosition(Vector3(0,0,0) );



ocrim74

ocrim74

27-09-2006 16:39:49

Hi,

it´s me again. I have a problem with the orientation. If I change the orientation of the body myConvex with the following code the the view of the camera turns like expected.


myConvex->addTorque(Vector3(0,50,0));


But if I want to move the body to the direction of the orientation it does not work like expected. The moving direction is still the same as before rotating the body.


myConvex->addForce(mCamera->getOrientation() * Ogre::Vector3(0,0,150));


If I change the orientation of the camera by the mouse like in tutorialsimple.h it works.


mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);

mCamera->yaw(mRotX);
mCamera->pitch(mRotY);


Is it possible that the orientation will not be updated if I bind the camera to the body myConvex an rotate it with addForce?

I need a solution to change the orientation of camera and body.

Do you have any ideas?

Thanks,

ocrim74

wspnut

17-10-2006 03:37:21

Hey guys,

I'm trying to do a similar thing on a rotating ball. However, when torque is applied to the ball I *don't* want the camera to rotate along with it.

Is there any (easy) way to keep the ball steady so that it simply follows the ball?

Think of it as a 3rd person game, where the rolling ball is the 3rd person...

betajaen

17-10-2006 09:38:45

Yeah, just Betajaen's top tip in this case. It's just a simple case of trigonometry here.

wspnut

17-10-2006 13:43:22

Yeah, just Betajaen's top tip in this case. It's just a simple case of trigonometry here.

Yea I had tried betajaen's top tip, but the camera still rotates around the object... when it is turned =/

I'll play with it more when I get back from class, right now, I currently am doing the following at the end of newFrame for the position:

Vector3 offset = Vector3(0, 7, -7);
mCamera->setPosition(myBall->mNode->getPosition() + (myBall->mNode->getOrientation() * offset));
mCamera->lookAt(myBall->mNode->getPosition());

wspnut

17-10-2006 22:27:45

I changed my code to this and it seems to work a lot better:


Vector3 offset = Vector3(0, 7, -7);
Vector3 ballCenter = myBall->mNode->_getWorldAABB().getCenter();

mCamera->setPosition(ballCenter + offset);
mCamera->lookAt(ballCenter);



The only thing that bugs me is that the ball I'm tracking seems to jitter whenever it gets moving. When I did attachObject with it this never occured.

Is there something I can do to make it smoother? Is the bottom of newFrame() the wrong place to put this code?

betajaen

17-10-2006 23:01:25

The only thing that bugs me is that the ball I'm tracking seems to jitter whenever it gets moving. When I did attachObject with it this never occured.

Is there something I can do to make it smoother? Is the bottom of newFrame() the wrong place to put this code?


Oh no the jitter bug (not the dance)!

The jittering is because it's being pushed ever so slightly above it, then it falls down again. Hence the jitter. When it sleeps there are no forces applied to it so there is none.

What I can recommend is ignore the Y value and use your own. Perhaps from a raycast or just using 1.

wspnut

18-10-2006 02:03:04

The jittering is because it's being pushed ever so slightly above it, then it falls down again. Hence the jitter. When it sleeps there are no forces applied to it so there is none.

What I can recommend is ignore the Y value and use your own. Perhaps from a raycast or just using 1.


Couple questions...

A) When is "it" sleeping (why would it be?), and I'm guessing "it" is the ball?

B) Why would the ball be pushed "ever so slightly above it?" or is it the camera being pushed above the ball? If so, why is it being pushed?

C) How can I get the right placement above the ball while ignoring the y value? Eventually I'd like to have an uneven terrain that the ball can launch off of, and I'd like the camera to stay with the ball... so keeping the ball at a level above the terrain is a little out there...

Any more tips would be appreciated :)

betajaen

18-10-2006 11:51:46

How it works is when the ball moves, gravity is making the ball accelerate downwards, into the floor. Next the ball notices it's a little bit into the floor and moves out of it. Naturally there will be errors in this, hence the jitter. You only notice this when you have a camera attached, because it inherits the jitter too, and you notice this better since the entire screen is jittering and rather than the ball.

Basically there are a few ways of doing this (which have been discussed before) but I'll tell you again.

1. Ignore the Y value, always set it at a fixed number.

2. Ignore the Y. Ray cast downwards, add that to the radius of the ball. Apply that to Y.

3. Get Y across a number of frames. Use the average of that.

4. See if the problem is to do with the iterator, try using a fixed frame with either setting VSync, or creating a scene blueprint and adjusting the iterator settings in there.

wspnut

18-10-2006 19:27:09

Actually:

a) The problem only occurs when I *don't* attach the camera to the scene node. The entire frame does not jitter, only the ball does (as in, in relation to the floor, the ball does not jitter)


b) The ball jitters ANY time it moves. I start the ball at a high distance and let it drop to the floor and it jitters all the way down. The camera stays steady and falls (because on every frame I set its position relative to the ball's [but it's still not attached!]).


For instance, if I apply torque to the ball to the right, it moves to the right. As it rolls faster it starts jittering stronger. Same to the left or any direction the ball is currently moving in. It's not jittering on the Y axis at all really, but it is heavily in the directions it is moving. When the ball is standing still it's completely stable...

betajaen

18-10-2006 20:50:30

Ah!

I think I remember how I sorted this, basically your camera is one frame behind. If that makes any sense.

More about it here.

[Edit]

Perhaps it may be worth it for me to implement some sort of frameListener system within NxOgre so you can have synchronised movement like that.

wspnut

19-10-2006 00:23:26

Perhaps it may be worth it for me to implement some sort of frameListener system within NxOgre so you can have synchronised movement like that.

That'd be pretty slick =D

betajaen

19-10-2006 23:52:00

Here you go:


class testy : public iterationListener{

public:

Ogre::Camera *mCamera;
body *targetBody;

testy(Ogre::Camera *cam) {
mCamera = cam;
targetBody = 0;
}

void before(float deltaTime) {

}

void after(float deltaTime) {

if (targetBody == 0)
return;

Vector3 offset = Vector3(0, 7, -7);
Vector3 ballCenter = targetBody->mNode->_getWorldAABB().getCenter();

mCamera->setPosition(ballCenter + offset);
mCamera->lookAt(ballCenter);

}

void setTargetBody(body *t) {
targetBody = t;
}

};


...

mTesty = new testy(mCamera);
mWorld->addListener(mTesty);



There is a tiny flicker, but it's more graphics card bitmap than a wrong vector. But you probably know what to look for.

cecchisandrone

01-08-2008 17:16:48

Hi all.
Sorry if I revive this old post but it describes quite better my problem. I want to follow a body with my Ogre camera.
I tried with:
body->mNode->attachObject(mCamera) but it seems the member mNode is not existent in actual release.

betajaen

01-08-2008 17:25:58

I hate it when people bump threads that are two years out of date. Considering I posted some code (hint: "SmartCamera" ) that does the same thing with Bleeding.

Please use the search better next time.