[Solved] Calculating Vector to Move Object with Camera

Problems building or running the engine, queries about how to use features etc.
User avatar
Salmod
Halfling
Posts: 87
Joined: Wed Nov 09, 2005 12:58 am
Location: London, UK

[Solved] Calculating Vector to Move Object with Camera

Post by Salmod »

Hi,

I am working on a demo using NxOgre and am making an avatar representation... What I want is an actual character (i.e. the player) and then a floating hand, which is fixed at 0.5m from the character, but move with the camera orientation (kinda like a crosshair), but still stays 0.5m from the character...

To keep this post easy to understand, think of the hand as just a small box bounding a hand shape. I'm having trouble working out the movement vector for the box each frame... I think I have an idea how to do it in theory as follows:

Code: Select all

At the start of each frame
   oldPosition = hand.getPosition() ;
   move main character and/or camera ;
   Use the orientation of the camera and offset from character (0.5m) to get the projected new position of the hand;
   moveVector = newPosition - oldPosition ;
However I can't quite figure out exactly what calculations I need to do in the code to get the new position correctly (assuming the method is correct in the first place)... If anyone could explain it to me step by step, or give me an Ogre code sample that does this, I would really really appreciate it!

Thanks in advance for any help!
-[ salmod ]-
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2

Post by Kencho »

Well, the most basic way to put the box around the character (no orientation for now; assuming not attached to any node other than the root->world coordinates) at 0.5m horizontally in the direction of the camera is:
Get the player world position
Get the camera orientation and multiply Vector3::UNIT_Z with that quaternion.
Then take that direction vector, and make it's y component zero.
Normalise it and multiply it with 0.5
Add that direction vector to the player position vector.
That's the new position for the hand.

If you want to change its orientation also, you could use the setDirection method using the direction method calculated before.

It's a bit dirty, but as I don't know exactly what you want and what you have (node hierarchy and such) I can't help more :)
Image
User avatar
Salmod
Halfling
Posts: 87
Joined: Wed Nov 09, 2005 12:58 am
Location: London, UK

Post by Salmod »

Hi Kencho,

Thanks for the quick reply...I've been trying the steps you provided for ages, but it doesnt seem to work... It looks like the hand ignores the camera completely, and move opposite to the character (i.e. char forward, hand backward, char left, hand right)... And despite starting the hand at eye level, it always seems to be near the floor... Heres my code in update hand:

Code: Select all

Ogre::Vector3 charPos = NxTools::convert(mAvatar->nxChar->mController->getActor()->getGlobalPosition()) ;

	Ogre::Quaternion camOrientation = mOgre->mCamera->getOrientation() ;
	Ogre::Vector3 directionToCam = camOrientation * Ogre::Vector3::UNIT_Z ;
	directionToCam.y = 0 ;
	directionToCam.normalise() ;
	directionToCam = directionToCam	* 0.5 ; 
	Ogre::Vector3 newHandPos = charPos + directionToCam ; 
NxVec3 newPos = NxTools::convert(newHandPos) ;
	mAvatar->nxHandChar->mController->getActor()->setGlobalPosition(newPos);

	lastHandPos = newHandPos ; 
NxTools::convert just converts from Ogre:Vector3 to NxVec3 or vica-a-versa... The controller class containing this function is a frame listener, and updateHand() is the last thing called in frameStarted (after the mouse/keyboard processing)... lastHandPos is initialised in the construtor using getPosition on the hand...

I'm really tearing what little hair I have out over this! :( I've spoken to Betajaen as well, and he suggested a formula as follows:

Code: Select all

newHandPos = charPos + (camOrientation * Ogre::Vector3(0.5,0,0))
But this seems to get pretty much the same behaviour as the above code...

Regarding how I eventually want the hand to move - I need it to follow directly where the camera is pointing, as if it were attached to a ray 0.5m in length shooting from the camera. It doesnt matter which way the hand actually points, as long as its position is correct... Also, this is the physics representation of the hand I'm moving, rather than a sceneNode - so I don't really want to be using setPosition, but rather move(moveVector)...

Any more ideas :?:
-[ salmod ]-
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2

Post by Kencho »

Yep, more ideas are coming :)
First, betajaen's formula looks better and more efficient than mine, so use it (though the vector should be Vector3 (0, 0, 0.5)).
And second, how are you creating/initialising the camera? If I recall correctly, the example application framework does by initialising the camera looking in the NEGATIVE_UNIT_Z, so if you have attached it to a node and rotate the node, the reference direction is NEGATIVE_UNIT_Z, not UNIT_Z. So instead of Vector3(0, 0, 0.5) you should use the opposite: Vector3 (0, 0, -0.5).
That would explain the symmetric movement and should work fine now :)
Image
User avatar
Salmod
Halfling
Posts: 87
Joined: Wed Nov 09, 2005 12:58 am
Location: London, UK

Post by Salmod »

OMG - thank you (and Betajaen) SO much - it looks like it's working! :D

Here's the current updateHand() code:

Code: Select all

	// Update the hand
	Ogre::Vector3 charPos = NxTools::convert(mAvatar->nxChar->mController->getActor()->getGlobalPosition()) ;
	charPos.y += 0.7 ;
	Ogre::Quaternion camOrientation = mOgre->mCamera->getOrientation() ;
	Ogre::Vector3 newHandPos = charPos + (camOrientation * Ogre::Vector3(0,0,-0.5)) ;
	Ogre::Vector3 handMoveDirection = newHandPos - lastHandPos ;
	NxVec3 moveVector = NxTools::convert(handMoveDirection) ;
	mAvatar->nxHandChar->mController->move(moveVector, mWorld->getScene("NxHouse")->findGroupIndex("default"), 
		0.001f, mAvatar->nxHandChar->mCollisionFlags) ;

	lastHandPos = newHandPos ; 
And it moves properly, without setPosition! :) There seem to be some minor problems with tunneling through walls and stuff - but I kinda expected that, and I should be able to work around it...

In case you're wondering, I add 0.7 to charPos.y because getPosition returns the center of the controller, and the camera is actually 0.7 above the center.

Also, regarding the camera setup - I'm not using the example framework (although I based my own framework on it quite heavily), but the camera is created looking along the -Z axis - so you were right about that. :)

I was wondering, when you use the lookAt() function for the camera, does this become the original vector used to get the quaternion return by getOrientation() ?

Also, what is the easiest way to get the actual vector describing the direction the camera is pointing? (or is this what we get by doing camOrientation * Vector3::NEGATIVE_UNIT_Z?)

Thanks again for the help Kencho (and Betajaen!) :D
-[ salmod ]-
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2

Post by Kencho »

lookAt rotates the camera so that it looks in the desired direction. Cameras don't have a "reference vector", so any modification to it's direction or orientation will modify that vector. So in practical terms, yes, it does, though theorethically it doesn't as there isn't one (well, NGEATIVE_UNIT_Z by default, and impossible to change).

Camera::getDirection is what you're looking for. It should work fine, doing what we're doing righ now, but as I'm not sure if this method takes also the orientation of the parent scene nodes (the most common structure, specially with orbitting cameras like GTA's), I didn't tell you about it. You can play with these methods and try anyways. Now you know most of the maths underneath :)

PS: "Tagged" the thread as Solved. This is a quite common question, and much people will find it easier to find the solution this way. Hope you don't mind :)
Image