Camera rotation/movement (Createing my own camera)

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Guest

Camera rotation/movement (Createing my own camera)

Post by Guest »

Hi everyone! Turboferret here.
I'm making my own camera in Irrlicht, but the camera is very glitchy and jumpy. And at the start, when the camera has not yet moved, it jerks around so much when you try to rotate that it's almost impossible to do something sane!

Anyway, please scan through the provided source if you have time

Code: Select all

#include "../include/cCamera.h"

cCamera::cCamera()
{
	cameraStyle = CS_NONE;
	doMouseMovement = true;
	firstUpdate = true;

	angleY = 0.0f;
	angleZ = 0.0f;
	minAngle = -45.0f;
	maxAngle = 89.0f;

	zoomIn = false;
	zoomOut = false;

	minDist = 1;
	maxDist = 100;
	boxSize = 0;
	zoomSpeed = 10;

	targetOffset = vector3df(0, 0, 0);

	invertX = false;
	invertY = true;
	invertZ = true;

	forwardIndex = 0;
	sidewardIndex = 0;
}

cCamera::~cCamera()
{
}

bool cCamera::createCamera(ISceneManager* Smgr, ICursorControl* cursorcontrol, cEvent* event, f32 rotatespeed, f32 movespeed)
{
	if(camera)
		delete camera;
	if((camera = Smgr->addCameraSceneNode()) == NULL)
		return false;
	Smgr->setActiveCamera(camera);
	eventManager = event;
	rotateSpeed = rotatespeed;
	moveSpeed = movespeed;
	smgr = Smgr;
	cursorControl = cursorcontrol;
	moveSpeed /= 1000.0f;
	return true;
}

void cCamera::moveForward(long distance)
{
//	camera->setTarget(vector3df(0.0f, 0.0f, 1.0f));
	vector3df pos = camera->getPosition();
	vector3df movedir = camera->getTarget();
	movedir.normalize();
	pos += movedir * (f32)distance;
	camera->setPosition(pos);
	camera->setTarget(pos + movedir);
	camera->updateAbsolutePosition();
}

void cCamera::moveSideward(long distance)
{
	camera->setTarget(vector3df(0.0f, 0.0f, 1.0f));
	vector3df pos = camera->getPosition();
	vector3df strafevect = camera->getTarget();
	strafevect = strafevect.crossProduct(camera->getUpVector());
	strafevect.normalize();
	pos += strafevect * (f32)-distance;
	camera->setPosition(pos);
	camera->setTarget(pos + camera->getTarget());
	camera->updateAbsolutePosition();
}

void cCamera::update()
{
	if(smgr->getActiveCamera() != camera)
		return;
	if(cameraStyle <= CS_NONE || cameraStyle >= CS_LAST)
		return;
	if(firstUpdate)
	{
		if(cursorControl)
			cursorControl->setPosition(0.5f, 0.5f);
		lastTime = GetTickCount();
		firstUpdate = false;
		return;
	}
	if(eventManager->keys[ZOOMIN])
		zoomIn = true;
	else
		zoomIn = false;
	if(eventManager->keys[ZOOMOUT])
		zoomOut = true;
	else
		zoomOut = false;

	switch(cameraStyle)
	{
	case CS_1ST:
		update1ST();
		break;
	case CS_3RD:
		update3RD();
		break;
	case CS_RTS:
		break;
	}
}

void cCamera::updateMousePos()
{
	position2d<irr::f32> pos = cursorControl->getRelativePosition();
	if(pos.X < (0.5f))  pos.X = (0.5f);
	if(pos.X > (0.5f))  pos.X = (0.5f);
	if(pos.Y < (0.5f))  pos.Y = (0.5f);
	if(pos.Y > (0.5f))  pos.Y = (0.5f);
	cursorControl->setPosition(pos);
}

void cCamera::update1ST()
{
	s32 now = GetTickCount();
	s32 timeDiff = now - lastTime;
	lastTime = now;

	camera->setTarget(vector3df(0.0f, 0.0f, 1.0f));
	if(!cursorControl)
		return;
	if(doMouseMovement)
	{
		position2d<f32> pos = cursorControl->getRelativePosition();
		if(pos.X < 0.5f-EPSILON)
			angleY += (pos.X-(0.5f))*rotateSpeed;
		if(pos.X > 0.5f+EPSILON)
			angleY += (pos.X-(0.5f))*rotateSpeed;
		if(angleY > 360.0f)
			angleY -= 360.0f;
		if(angleY < 0.0f)
			angleY += 360.0f;
		if(pos.Y < 0.5f-EPSILON)
			angleZ += (pos.Y-(0.5f))*rotateSpeed;
		if(pos.Y > 0.5f+EPSILON)
			angleZ += (pos.Y-(0.5f))*rotateSpeed;
		if(angleZ < minAngle)       angleZ = minAngle;
		else if(angleZ > maxAngle)  angleZ = maxAngle;

		updateMousePos();
	}

	// Create translation vector - is this correct?
	vector3df dist = camera->getTarget() - camera->getPosition();
	vector3df translation((f32)dist.getLength(), 0, 0);
	translation.rotateXYBy(-angleZ, vector3df(0,0,0));
	translation.rotateXZBy(-angleY, vector3df(0,0,0));

	// update position
	vector3df pos = camera->getPosition();
	vector3df movedir = camera->getTarget() + translation;
	movedir.normalize();

	if(forwardIndex != 0)
	{
		pos += movedir * (f32)/*timeDiff */forwardIndex * moveSpeed;
		forwardIndex = 0;
	}

	if(sidewardIndex != 0)
	{
		vector3df strafevect = camera->getTarget() + translation;
		strafevect = strafevect.crossProduct(camera->getUpVector());
		strafevect.normalize();
		pos -= strafevect * (f32)/*timeDiff */sidewardIndex * moveSpeed;
		sidewardIndex = 0;
	}
	// write translation
	camera->setPosition(pos);
	// write right target
	targetVector = camera->getTarget();
	camera->setTarget(pos + translation + targetVector);

	camera->updateAbsolutePosition();
}
Thanks!
NovaCoder
Posts: 28
Joined: Wed May 26, 2004 11:36 am
Contact:

Post by NovaCoder »

I'm still struggling to work them out myself but this bit looks odd to me.

Code: Select all

void cCamera::update1ST() 
{ 
   camera->setTarget(vector3df(0.0f, 0.0f, 1.0f)); 
}
Why do you need to update the target to (0,0,1)?

This bit is also a bit strange:

Code: Select all

   // Create translation vector - is this correct? 
   vector3df dist = camera->getTarget() - camera->getPosition(); 
   vector3df translation((f32)dist.getLength(), 0, 0); 
Shouldn't you be moving along the 'Z' plane as in:

Code: Select all

vector3df translation(0, 0, (f32)dist.getLength())
- Nova
turboferret

Post by turboferret »

this seems to take away the jerkyness, but there are still problems. thanks for the reply though, novacoder. if you don't mind sharing your camera code it would be greatly appreciated.
NovaCoder
Posts: 28
Joined: Wed May 26, 2004 11:36 am
Contact:

Post by NovaCoder »

Ok sounds good, PM me and we'll try and we'll work some things out together.
- Nova
turboferret
Posts: 49
Joined: Thu Aug 12, 2004 12:42 pm
Location: Sweden
Contact:

Post by turboferret »

Okay, I sorted it out by ripping CCameraSceneNodeFPS

Code: Select all

void cCamera::update1ST()
{
	s32 now = GetTickCount();
	s32 timeDiff = now - lastTime;
	lastTime = now;

	camera->setTarget(vector3df(0.0f, 0.0f, 1.0f));
	if(!cursorControl && doMouseMovement)
		return;

	vector3df RelativeRotation = camera->getRotation();

	RelativeRotation.X *= -1.0f;
	RelativeRotation.Y *= -1.0f;

	if(doMouseMovement)
	{
		if(!newStyle)
		{
			position2d<f32> cursorpos = cursorControl->getRelativePosition();
			if(cursorpos.X < 0.49f || cursorpos.X > 0.51f ||
				cursorpos.Y < 0.49f || cursorpos.Y > 0.51f)
			{
				RelativeRotation.Y += (0.5f - cursorpos.X) * rotateSpeed * timeDiff * (invertY ? -1 : 1);
				RelativeRotation.X += (0.5f - cursorpos.Y) * rotateSpeed * timeDiff * (invertX ? -1 : 1);

				cursorControl->setPosition(0.5f, 0.5f);

				if (RelativeRotation.X > 89.0f) RelativeRotation.X = 89.0f;
				if (RelativeRotation.X < -89.0f) RelativeRotation.X = -89.0f;
			}
		}
		else
		{
			newStyle = false;
			cursorControl->setPosition(0.5f, 0.5f);
		}
	}

	matrix4 mat;
	mat.setRotationDegrees(vector3df(-camera->getRotation().X, -camera->getRotation().Y, 0));
	vector3df Target = camera->getTarget();
	mat.transformVect(Target);
	camera->setTarget(Target);

	vector3df pos = camera->getPosition();	

	vector3df movedir = camera->getTarget();
	movedir.normalize();
	if(forwardIndex != 0)
		pos += movedir * (f32)timeDiff * moveSpeed * forwardIndex;
	forwardIndex = 0;

	// strafing

	vector3df strafevect = camera->getTarget();
	strafevect = strafevect.crossProduct(camera->getUpVector());
	strafevect.normalize();
	if(sidewardIndex != 0)
		pos += strafevect * (f32)timeDiff * moveSpeed * -sidewardIndex;
	sidewardIndex = 0;

	// write translation

	camera->setPosition(pos);

	// write right target

	targetVector = camera->getTarget();
	camera->setTarget(camera->getTarget() + pos);

	RelativeRotation.X *= -1.0f;
	RelativeRotation.Y *= -1.0f;

	camera->setRotation(RelativeRotation);

	camera->updateAbsolutePosition();
}
Hope it helps! Increment forwardIndex and sidewardIndex to move in those directions and decrement them to move in the opposite direction.
This monkey is useless, it only has ONE ass!!!
Post Reply