Page 1 of 1

why isn't my OnAnimate() being called ?

Posted: Thu Apr 12, 2007 2:31 pm
by danut007ro
Hi !
I'm trying to write a FPS-like camera, with a few modifications (swim up and down, right-click transform the camera in a maya-like camera), but my OnAnimate() function isn't called...

I modified the code from source (CCameraSceneNode and CCameraFPSSceneNode), but I can't see where I'm wrong...

I'm showing the camera like this :

Code: Select all

ICameraSceneNode* cam = new CMyCamera(0, smgr, device, -1, vector3df(0, 0, -300));
smgr->setActiveCamera(cam);
cam->drop();
So if someone who knows better can take a look on the sources, I'll be grateful...

Thanks...

myCamera.h :

Code: Select all

#ifndef MYCAMERA_INCLUDED
#define MYCAMERA_INCLUDED

#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

class CMyCamera : public ICameraSceneNode
{
public:
	CMyCamera(ISceneNode* parent, ISceneManager* mgr, IrrlichtDevice* device, s32 id, 
		const core::vector3df& position = core::vector3df(0,0,0),
		const core::vector3df& lookat = core::vector3df(0,0,100));
	virtual ~CMyCamera();

	virtual bool OnEvent(SEvent event);
	virtual void OnAnimate(u32 timeMs);

	virtual void setProjectionMatrix(const core::matrix4& projection);
	virtual const core::matrix4& getProjectionMatrix();
	virtual const core::matrix4& getViewMatrix();
	virtual void setTarget(const core::vector3df& pos);
	virtual core::vector3df getTarget() const;
	virtual void setUpVector(const core::vector3df& pos);
	virtual core::vector3df getUpVector() const;
	virtual f32 getNearValue();
	virtual f32 getFarValue();
	virtual f32 getAspectRatio();
	virtual f32 getFOV();
	virtual void setNearValue(f32 zn);
	virtual void setFarValue(f32 zf);
	virtual void setAspectRatio(f32 aspect);
	virtual void setFOV(f32 fovy);

	virtual void OnRegisterSceneNode();
	virtual void render();

	virtual const core::aabbox3d<f32>& getBoundingBox() const;
	virtual const SViewFrustum* getViewFrustum() const;
	virtual void setInputReceiverEnabled(bool enabled);
	virtual bool isInputReceiverEnabled();
	virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0);
	virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
	virtual ESCENE_NODE_TYPE getType() { return ESNT_CAMERA; }

	virtual core::vector3df getAbsolutePosition() const;

	virtual void setRotateSpeed(const f32 speed);
	virtual void setMoveSpeed(const f32 speed);
	virtual f32 getRotateSpeed();
	virtual f32 getMoveSpeed();

protected:
	void animate(u32 timeMs);
	void recalculateProjectionMatrix();
	void recalculateViewArea();

	IrrlichtDevice* pDevice;
	gui::ICursorControl* CursorControl;
	core::position2d<f32> CenterCursor;
	bool Keys[8];

	core::vector3df Target;
	core::vector3df UpVector;
	f32 Fovy;
	f32 Aspect;
	f32 ZNear;
	f32 ZFar;
	SViewFrustum ViewArea;
	bool InputReceiverEnabled;

	f32 MoveSpeed;
	f32 RotateSpeed;
	f32 AroundSpeed;
	f32 ZoomSpeed;

	bool firstUpdate;
	s32 LastAnimationTime;
	core::vector3df TargetVector;
};

#endif
myCamera.cpp :

Code: Select all

#include "stdafx.h"
#include "myCamera.h"

const f32 MAX_VERTICAL_ANGLE = 88.0f; 

CMyCamera::CMyCamera(ISceneNode* parent, ISceneManager* mgr, IrrlichtDevice* device, s32 id, const core::vector3df& position, const core::vector3df& lookat)
: pDevice(device), UpVector(0.0f, 1.0f, 0.0f), Target(lookat), Fovy(core::PI / 2.5f), Aspect(4.0f / 3.0f), ZNear(1.0f), ZFar(3000.0f), 
InputReceiverEnabled(true), MoveSpeed(200.0f), RotateSpeed(1500.0f), AroundSpeed(-1500.0f), ZoomSpeed(200.0f), 
firstUpdate(true), 
ICameraSceneNode(0, mgr, id, position, core::vector3df(0.0f, 0.0f, 0.0f), core::vector3df(1.0f, 1.0f, 1.0f))
{
	video::IVideoDriver* d = mgr->getVideoDriver();
	if (d)
		Aspect = (f32)d->getCurrentRenderTargetSize().Width / (f32)d->getCurrentRenderTargetSize().Height;

	if (pDevice)
	{
		CursorControl = pDevice->getCursorControl();
		if (CursorControl)
			CursorControl->grab();
	}

	MoveSpeed /= 1000.0f;

	recalculateProjectionMatrix();
	recalculateViewArea();
}

CMyCamera::~CMyCamera()
{
	if (CursorControl)
		CursorControl->drop();
}

bool CMyCamera::OnEvent(SEvent event)
{
	if (InputReceiverEnabled)
	{
		if (event.EventType == EET_KEY_INPUT_EVENT)
			switch (event.KeyInput.Key)
			{
			case irr::KEY_KEY_W :
				Keys[0] = event.KeyInput.PressedDown;
				return true;
			case irr::KEY_KEY_S :
				Keys[1] = event.KeyInput.PressedDown;
				return true;
			case irr::KEY_KEY_A :
				Keys[2] = event.KeyInput.PressedDown;
				return true;
			case irr::KEY_KEY_D :
				Keys[3] = event.KeyInput.PressedDown;
				return true;
			case irr::KEY_KEY_R :
				Keys[4] = event.KeyInput.PressedDown;
				return true;
			case irr::KEY_KEY_F :
				Keys[5] = event.KeyInput.PressedDown;
				return true;
			}


	}
	return false;
}

void CMyCamera::animate(u32 timeMs)
{
	// camera activa ?
	const u32 camIsMe = SceneManager->getActiveCamera() == this;

	if (firstUpdate)
	{
		if (CursorControl && camIsMe)
		{
			CursorControl->setPosition(0.5f, 0.5f);
			CenterCursor = CursorControl->getRelativePosition();
		}

		LastAnimationTime = pDevice->getTimer()->getTime();

		firstUpdate = false;
	}

	// calculeaza diferenta de timp, doar pt. camera activa = curenta
	f32 timeDiff = 0.f;
	if (camIsMe)
	{
		timeDiff = (f32)(timeMs - LastAnimationTime);
		LastAnimationTime = timeMs;
	}

	// update position
	core::vector3df pos = getPosition();	

	// Update rotation
	//if (InputReceiverEnabled)
	{
		Target.set(0,0,1);

		if (CursorControl && InputReceiverEnabled && camIsMe)
		{
			core::position2d<f32> cursorpos = CursorControl->getRelativePosition();

			if (!core::equals(cursorpos.X, CenterCursor.X) || !core::equals(cursorpos.Y, CenterCursor.Y))
			{
				RelativeRotation.X *= -1.0f;
				RelativeRotation.Y *= -1.0f;
				RelativeRotation.Y += (0.5f - cursorpos.X) * RotateSpeed;
				RelativeRotation.X = core::clamp(RelativeRotation.X + (0.5f - cursorpos.Y) * RotateSpeed, -MAX_VERTICAL_ANGLE, +MAX_VERTICAL_ANGLE);
				RelativeRotation.X *= -1.0f;
				RelativeRotation.Y *= -1.0f;

				CursorControl->setPosition(0.5f, 0.5f);
				CenterCursor = CursorControl->getRelativePosition();
			}
		}

		// set target
		core::matrix4 mat;
		mat.setRotationDegrees(core::vector3df(RelativeRotation.X, RelativeRotation.Y, 0));
		mat.transformVect(Target);

		core::vector3df movedir = Target;
		movedir.normalize();

		if (InputReceiverEnabled && camIsMe)
		{
			if (Keys[0])
				pos += movedir * timeDiff * MoveSpeed;
			if (Keys[1])
				pos -= movedir * timeDiff * MoveSpeed;
			core::vector3df strafevect = Target;
			strafevect = strafevect.crossProduct(UpVector);
			strafevect.normalize();
			if (Keys[2])
				pos += strafevect * timeDiff * MoveSpeed;
			if (Keys[3])
				pos -= strafevect * timeDiff * MoveSpeed;
		}

		setPosition(pos);
	}

	TargetVector = Target;
	Target += pos;
}

void CMyCamera::OnAnimate(u32 timeMs)
{
	animate(timeMs);

	core::list<ISceneNodeAnimator*>::Iterator ait = Animators.begin();
	for (; ait != Animators.end(); ait++)
		(*ait)->animateNode(this, timeMs);

	updateAbsolutePosition();
	Target = getPosition() + TargetVector;

	core::list<ISceneNode*>::Iterator it = Children.begin();
	for (; it != Children.end(); it++)
		(*it)->OnAnimate(timeMs);
}

void CMyCamera::setInputReceiverEnabled(bool enabled)
{
   if(!InputReceiverEnabled && enabled)
      firstUpdate = true;

   InputReceiverEnabled = enabled;
}

bool CMyCamera::isInputReceiverEnabled()
{
	_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
	return InputReceiverEnabled;
}

void CMyCamera::setProjectionMatrix(const core::matrix4& projection)
{
	ViewArea.Matrices[video::ETS_PROJECTION] = projection;
	ViewArea.setTransformState(video::ETS_PROJECTION);
}

const core::matrix4& CMyCamera::getProjectionMatrix()
{
	return ViewArea.Matrices[video::ETS_PROJECTION];
}

const core::matrix4& CMyCamera::getViewMatrix()
{
	return ViewArea.Matrices[video::ETS_VIEW];
}

void CMyCamera::setTarget(const core::vector3df& pos)
{
	updateAbsolutePosition();
	core::vector3df vect = pos - getAbsolutePosition();
	vect = vect.getHorizontalAngle();
	RelativeRotation.X = vect.X;
	RelativeRotation.Y = vect.Y;

	if (RelativeRotation.X > MAX_VERTICAL_ANGLE)
		 RelativeRotation.X -= 360.0f;
}

core::vector3df CMyCamera::getTarget() const
{
	return Target;
}

void CMyCamera::setUpVector(const core::vector3df& pos)
{
	UpVector = pos;
}

core::vector3df CMyCamera::getUpVector() const
{
	return UpVector;
}

f32 CMyCamera::getNearValue()
{
	return ZNear;
}

f32 CMyCamera::getFarValue()
{
	return ZFar;
}

f32 CMyCamera::getAspectRatio()
{
	return Aspect;
}

f32 CMyCamera::getFOV()
{
	return Fovy;
}

void CMyCamera::setNearValue(f32 f)
{
	ZNear = f;
	recalculateProjectionMatrix();
}

void CMyCamera::setFarValue(f32 f)
{
	ZFar = f;
	recalculateProjectionMatrix();
}

void CMyCamera::setAspectRatio(f32 f)
{
	Aspect = f;
	recalculateProjectionMatrix();
}

void CMyCamera::setFOV(f32 f)
{
	Fovy = f;
	recalculateProjectionMatrix();
}

void CMyCamera::recalculateProjectionMatrix()
{
	ViewArea.Matrices[video::ETS_PROJECTION].buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar);
	ViewArea.setTransformState(video::ETS_PROJECTION);
}

void CMyCamera::OnRegisterSceneNode()
{
	core::vector3df pos = getAbsolutePosition();
	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();
}

void CMyCamera::render()
{	
	video::IVideoDriver* driver = SceneManager->getVideoDriver();
	if (driver)
	{
		driver->setTransform(video::ETS_PROJECTION, ViewArea.Matrices[video::ETS_PROJECTION]);
		driver->setTransform(video::ETS_VIEW, ViewArea.Matrices[video::ETS_VIEW]);
	}
}

const core::aabbox3d<f32>& CMyCamera::getBoundingBox() const
{
	return ViewArea.getBoundingBox();
}

const SViewFrustum* CMyCamera::getViewFrustum() const
{
	return &ViewArea;
}

core::vector3df CMyCamera::getAbsolutePosition() const
{
	return AbsoluteTransformation.getTranslation();
}

void CMyCamera::recalculateViewArea()
{
	ViewArea.cameraPosition = getAbsolutePosition();
	ViewArea.setFrom ( ViewArea.Matrices [ SViewFrustum::ETS_VIEW_PROJECTION_3 ] );
/*
	video::IVideoDriver* driver = SceneManager->getVideoDriver();
	if ( driver)
	{
		driver->setTransform(video::ETS_PROJECTION, ViewArea.Matrices [ video::ETS_PROJECTION ] );
		driver->setTransform(video::ETS_VIEW, ViewArea.Matrices [ video::ETS_VIEW ] );
	}
*/
}

void CMyCamera::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)
{
	ISceneNode::serializeAttributes(out, options);

	out->addVector3d("Target", Target);
	out->addVector3d("UpVector", UpVector);
	out->addFloat("Fovy", Fovy);
	out->addFloat("Aspect", Aspect);
	out->addFloat("ZNear", ZNear);
	out->addFloat("ZFar", ZFar);
}

void CMyCamera::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
	ISceneNode::deserializeAttributes(in, options);

	Target = in->getAttributeAsVector3d("Target");
	UpVector = in->getAttributeAsVector3d("UpVector");
	Fovy = in->getAttributeAsFloat("Fovy");
	Aspect = in->getAttributeAsFloat("Aspect");
	ZNear = in->getAttributeAsFloat("ZNear");
	ZFar = in->getAttributeAsFloat("ZFar");

	recalculateProjectionMatrix();
	recalculateViewArea();	
}

void CMyCamera::setRotateSpeed(const f32 speed)
{
	RotateSpeed = speed;	
}

void CMyCamera::setMoveSpeed(const f32 speed)
{
	MoveSpeed = speed;
}

f32 CMyCamera::getRotateSpeed()
{
	return RotateSpeed;
}

f32 CMyCamera::getMoveSpeed()
{
	return MoveSpeed;
}

any help ?

Posted: Fri Apr 13, 2007 8:46 pm
by danut007ro
no one can't help? pls?

Posted: Fri Apr 13, 2007 9:08 pm
by Dr.Bunshin
Hey danut

How do you know its not getting called?

Posted: Fri Apr 13, 2007 9:44 pm
by danut007ro
used a debugger...

Posted: Sat Apr 14, 2007 3:00 am
by vitek
You need to put the camera into the scene graph. You need to pass a valid ISceneNode pointer to the constructor, and your MyCamera constructor needs to pass the parent pointer to the base class.

Travis

Posted: Sat Apr 14, 2007 3:12 am
by danut007ro
Thanks for the reply.

I modified the code for creating camera like this :

Code: Select all

ICameraSceneNode* cam = new CMyCamera(smgr->getRootSceneNode(), smgr, device, -1, vector3df(0, 0, -300));
Also modified the constructor to pass the scenenode like this :

Code: Select all

ICameraSceneNode(parent, mgr, id, position, core::vector3df(0.0f, 0.0f, 0.0f), core::vector3df(1.0f, 1.0f, 1.0f))
But now the camera spawns at (0, 0, 0) and I cannot move it. It looks like it wants to move, because for one frame it moves but then comes back to (0, 0, 0).

Thanks again....

Posted: Sat Apr 14, 2007 2:36 pm
by Halan
you also have to alter the target and update the absolute position!