Propose a new feature: relative targets

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Propose a new feature: relative targets

Post by Hirogen »

I would like to propose a new feature to make the target of a camera relative to its parent.

In ICameraSceneNode.h you have to add

Code: Select all

		//! Sets if target is relative to parent 
		/**  */
		virtual void setIsTargetRelative( bool targetRelative )
		{
			IsTargetRelative = targetRelative;
		}

		//! Returns if target is relative to parent
		/**  */
		virtual bool isTargetRelative() 
		{
			return IsTargetRelative;
		} 

	private:
		bool IsTargetRelative;
Furthermore OnRegisterSceneNode() has to be changed in CCameraSceneNode

Code: Select all

//! prerender
void CCameraSceneNode::OnRegisterSceneNode()
{
	// if upvector and vector to the target are the same, we have a
	// problem. so solve this problem:

	core::vector3df pos = getAbsolutePosition();
	
	core::vector3df target = Target;
	
	if (isTargetRelative())
	{
		core::matrix4 targetTransformation;
		targetTransformation.setTranslation(target);
		targetTransformation =
			Parent->getAbsoluteTransformation() * targetTransformation;
		target = targetTransformation.getTranslation();
	}

	core::vector3df tgtv = target - pos;
	tgtv.normalize();

	core::vector3df up = UpVector;
	up.normalize();

	f32 dp = tgtv.dotProduct(up);

	if ( core::equals ( fabs ( dp ), 1.f ) )
	{
		up.X += 0.5f;
	}

	ViewArea.Matrices [ video::ETS_VIEW ].buildCameraLookAtMatrixLH(pos, target, up);
	ViewArea.setTransformState ( video::ETS_VIEW );
	recalculateViewArea();

	if ( SceneManager->getActiveCamera () == this )
		SceneManager->registerNodeForRendering(this, ESNRP_CAMERA);

	if (IsVisible)
		ISceneNode::OnRegisterSceneNode();
}
[/quote]

But there is one problem using a Maya camera. The feature only works correct if a fix in animate() is deactivated which is

Code: Select all

	// jox: fixed bug: jitter when rotating to the top and bottom of y
	UpVector.set(0,1,0);
	UpVector.rotateXYBy(-nRotY, core::vector3df(0,0,0));
	UpVector.rotateXZBy(-nRotX+180.f, core::vector3df(0,0,0));
The problem occurs when the parent node rotates around its y-axis without a translation.

Maybe someone could help me to find a way to combine this feature an the jitter bugfix.
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

I am not convinced yet, that this is a useful addition. What do you need it for and why do you want to specify the target in camera space?
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Post by Hirogen »

Well, it's a simple solution to create a third person camera. When you make a camera a child of a node, the camera normally doesn't really follow the object. Only the position of the camera follows the movement but not the point it looks at. If you constantly want to see an object from the same point of view, you can do it that way. In a racing game for an example you would always see your vehicle from the same perspective until you change the view angle. The advantage is that the followed object doesn't need to be the center (target of the camera) when using relative targets.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Most of the time you don't even want your camera to be a child of something anyway, I can't think of a good example of when you would.
Cameras as children of the thing they're looking at gives this ugly locked view effect. A much nicer effect is to make the camera smoothly follow a dummy node while smoothly looking towards a target dummy node.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Post by Hirogen »

Principally you are right. But if you focus a dummy node the user cannot simply turn the camera to look at another point.
I mean, you can create a camera for a racing game with dummy nodes. That's no problem - you are right. But by doing this the player has no possibility to change his point of view.
I can't really see your problem. It would just be an additional feature. There would be no must to use it.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

You can just use getAbsolutePosition().

camera->setTarger(dummyNode->getAbsolutePosition());

This returns the position in world space.

Offcourse you probably already know this right? So whats wrong with this simple solution? It avoids adding yet another function to the engine...
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Post by Hirogen »

The simple solution you mentioned is similiar to my proposal but not exactly the same.
I will try to explain the difference. Imagine you are travelling by train. The dummy target node may be positioned somewhere in front of the train and is a child node of the train. Our camera shall behave as a passenger on the train would see the world. Using the the dummy target node the passenger would never be able to look outside the window, because the target is fixed in front of the train. But when you can make the target relative to the train, it works. If the user doesn't change the camera it is as if the passenger would stand still on the train. But on the other side the passenger can still "walk" around on the train, he can look in the direction of the movement of the train, or as well to the end of the train.
rooly
Posts: 224
Joined: Tue Oct 25, 2005 4:32 pm
Location: Louisiana, USA, backwater country
Contact:

Post by rooly »

nope, thats still a dummy node child-ed to the train, with the camera->setTarget(dummy->getAbsolutePosition)

of course, if your talking about an fps camera, then this still isn't a problem, because the FPS camera can have a positional parent and not have it's target bound to a specific point.
When banks compete, you win.
When ISPs compete, you win.
When electronics retailers compete, you win.
When governments compete...you get drafted.
Nalin
Posts: 194
Joined: Thu Mar 30, 2006 12:34 am
Location: Lacey, WA, USA
Contact:

Post by Nalin »

I actually think it should be implemented. Think about it. The camera is probably the only scene object in the engine which isn't fully affected by changes in it's parent. I was actually surprised when I found that out. To me, everything about the engine seemed intuitive except for that. It could also make things a lot more simple.

For example, you parent something to the camera and position the camera a couple feet behind your object looking at it. Next, you rotate your object 90 degrees in any direction. If the camera followed its parent, it would move in a circle around the object while keeping itself locked onto it. Without correct parenting, you have to write code to keep the camera pointed at your object. Easy, I know, but it may still be a little tedious for a beginner to try to work it all out.

To me, it just makes sense. If I create an object and make it a child of another, moving and rotating the parent will cause the child to move and rotate with it too. It is like welding the two together. They move as a system. Since everything in the engine works that way, it seems weird and out of place for the camera to NOT work like that. I think adding the option to "weld" the camera to its parent would make the engine more intuitive to newbies. Keep the engine consistent.
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Post by Hirogen »

I made an example to illustrate what the problem is with the current solution in my point of view.

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")


int main()
{
	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
	IrrlichtDevice *Device = createDevice(driverType, core::dimension2d<s32>(800, 600),
		16, false, false, false);

	if (Device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = Device->getVideoDriver();
	IGUIEnvironment* env = Device->getGUIEnvironment();
	scene::ISceneManager* smgr = Device->getSceneManager();

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	smgr->addLightSceneNode();
	smgr->addLightSceneNode(0, core::vector3df(50,-50,100), video::SColorf(1.0f,1.0f,1.0f),20000);
	Device->getFileSystem()->addFolderFileArchive ( "../../media/" );


	// add floor
	irr::scene::ISceneNode* floor = smgr->addCubeSceneNode();
	floor->setScale(core::vector3df(100, 0.1,100));
	floor->setMaterialTexture(0, driver->getTexture("wall.bmp"));
	floor->setMaterialFlag( video::EMF_LIGHTING, false );

	// add plattform
	irr::scene::ISceneNode* plattform = smgr->addCubeSceneNode(10.0f);
	plattform->setMaterialFlag( video::EMF_LIGHTING, false );
	plattform->setPosition(core::vector3df(0, 0, 0));
	plattform->setMaterialTexture(0, driver->getTexture("rockwall.bmp"));

	// add target
	irr::scene::ISceneNode* target = smgr->addEmptySceneNode(plattform);
	target->setPosition (core::vector3df(-6,6,-6));

	// animate the plattform
	scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(
		core::vector3df(0,2,0), 100.0, 0.0001,
		core::vector3df(0,1,0));
	plattform->addAnimator(anim);
	scene::ISceneNodeAnimator* anim2  = smgr->createRotationAnimator(core::vector3df(0, 0.1, 0));
	plattform->addAnimator(anim2);


	// add skybox
	scene::ISceneNode* SkyBox = smgr->addSkyBoxSceneNode(
		driver->getTexture("irrlicht2_up.jpg"),
		driver->getTexture("irrlicht2_dn.jpg"),
		driver->getTexture("irrlicht2_lf.jpg"),
		driver->getTexture("irrlicht2_rt.jpg"),
		driver->getTexture("irrlicht2_ft.jpg"),
		driver->getTexture("irrlicht2_bk.jpg"));

	// add a camera scene node
	scene::ICameraSceneNode* Camera = smgr->addCameraSceneNodeMaya(0, 100, 20, 100);
	plattform->addChild(Camera);
	Camera->setPosition(core::vector3df(0, 6, 0));
	Camera->setUpVector(core::vector3df(0,1.0f,0));
	Camera->setTarget(target->getAbsolutePosition());


	// draw everything
	while(Device->run() && driver)
	{
		if (Device->isWindowActive())
		{
			// Refresh target
			Camera->setTarget(target->getAbsolutePosition());
			
			driver->beginScene(true, true, video::SColor(150,50,50,50));
			smgr->drawAll();
			env->drawAll();
			driver->endScene();

		}
		else
			Device->yield();
	}

	Device->drop();
	return 0;
}

The camera shall follow the position and the rotation (!) of the plattform (could be e.g. a train or ship in a game).

When the line

Code: Select all

Camera->setTarget(target->getAbsolutePosition());
is activated the camera follows the position and rotation, but you are not really able to control the Maya camera as you are used to do, because you cannot change your point of view freely and look to another point. When the line is deactivated you are able to rotate and move the camera, but the camera does no longer correctly follow the rotation of the plattform. No we also have another problem. The camera "rolls" as long as the code

Code: Select all

	UpVector.set(0,1,0);
	UpVector.rotateXYBy(-nRotY, core::vector3df(0,0,0));
	UpVector.rotateXZBy(-nRotX+180.f, core::vector3df(0,0,0));
in animate() in CCameraMayaSceneNode.cpp is active. I would call it a bug.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Oh I get it, so you mean relative rotation? As in you are standing on a platform and you want the camera to face in a direction effected by the platforms rotation? And you called it targets offcourse because ICameraSceneNode isnt effected by setRotation...


By the way, why cant you guys add a simple function in the header file of ICameraSceneNode for setRotation that takes the rotation and turns it into a unit vector of a target and calls set target from there? It would effectively be the same as set rotation, and would say us some hassle...
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Hirogen
Posts: 19
Joined: Tue May 29, 2007 5:55 am

Post by Hirogen »

Yes, you can regard it that way. When you have a relative position you can either use a relative rotation or a relative target to achieve the same aim.
I am just of the opinion that there should be a simple way to make all types of cameras following the whole movement (position and rotation) of a parent node, without loosing the possibility to move the camera relatively to its parent.
Post Reply