Camera Flickers When Setting Target

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
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Camera Flickers When Setting Target

Post by Irme »

Okay, i KNOW this has been asked before on the forums.. but i searched 20 pages back on the results and had no luck on a resoloution.. this is what i am doing: I have a 3rd person camera basicly, and i want it to rotate around the player when i move the mouse back and forth, here is my rotate routine

Code: Select all

        Public Sub RotateCamera(ByVal Horiz As Integer)            
            Dim tempPos As Vector3D = MyCamera.Position

            tempPos.RotateXZBy(Horiz, MyTarget.Position)

            MyCamera.Position = tempPos
            MyCamera.Target = MyTarget.Position
            MyCamera.UpdateAbsolutePosition()            
        End Sub
it is rotating like i wanted it to, but the screen flickers like mad when its rotating. ive tracked it down to setting the target. but i don't know how to overcome this... anyhelp would be great![/code]
Guest

Post by Guest »

I am having similar nighmares in my project with cam->setTarget. It appears that it was only intended for occasional updates (possibly) or at least doesn't work 100% smoothly when updating in a looped call. Why? Because it is not timedelta'd or fixed time steped (like irrlichts internal functions such as SceneNodeAnimtors are). So you get jerky inbetween movements jittering from one frame to the next.

I would love rock solid super smooth cameras in irrlicht but it always seems to depend on fate, if my system is being ever so slightly busy with something else (even minor) then it can jitter the update (this is even with using cam->updateAbsolutePosition()).

Please, if anyone knows how to get rock solid moving cameras with smoothly updating targeting then let everyone know :)

Also any chance niko of a locked to cam position "target animator" so that you move the camera and can move a target seperatly both with a similar animator and both in sync/smoothly so we don't have to setTarget manually?

thanks
pfo
Posts: 370
Joined: Mon Aug 29, 2005 10:54 pm
Location: http://web.utk.edu/~pfox1

Post by pfo »

I've got pretty smooth camera movement, the trick is to be aware of how much 'force' you apply to the camera at any given point. From rest, the camera should accelerate slowly until reaches some top speed. When controls are released, it should decelerate slowly and eventually stop. Most people are just like 'adding 5 units per frame in the forward direction', this will not be smooth. I put up a post somewhere showing how to use virtual mass with the camera, check it out for some smoother behavior.
Knops

Post by Knops »

Im also using my "own" camera which is 100% smooth (when you play with 10frames its, of course, not smooth). Like pfo said, dont rotate the camera at once, e.g. when you move your mouse left set a target (add your value there) and then let your camera rotate to that target each frame untill it is reached (and there you have to find the "smooth"-center of rotating-speed and how much you increase your rotation-degrees).

Only problem is that the irrlicht frustum doesnt work correct now so I had to implement my own, too (and clip all objects).
Guest

Post by Guest »

erm guys - it is a fixed camera using a scene node animator I am talking about not an FPS type with user input. Imagine a CUT SCENE camera moving around a scene with NO user input at all. It jitters slightly on its own. If you use SET TARGET to make it point to a target at the same time it is more obvious (the set target being a non time based update).

Just load up the Irrlicht demo and tell me you don't see stutters from the spline animator ? they may be slight but they are there - now add that to a set target every frame and you get something not 100% smooth. It is not bad by any means but not perfect either.

Yeah I could use an FPS cam and simlulate key presses if moving it in straight lines (instead of animators) using ease in/out but that is convoluted and avoids the issue.

cheers
Guest

Post by Guest »

oh and also try using a a cam that has a scene node animator moving it left so the scene moves right. You have to update the target every frame to stop it "looking" at the old target and rotating.

By using an FPS camera and adding an animator (just to move it left) it should in theory just move with it's target always in front (ie like strafing) but I am not sure if that is the best way to simulate what I want. If there is no better way then I will have to use FPS cam and disable the mouse/key input on it.
Guest

Knops

Post by Guest »

I am not using my cam for cut scenes.. but I could, its the same procedure. I dont use animators at all, and updating the target every frame is absolutely no problem and in this case a MUST (irrlicht need to pass that to the render api every frame so it doesnt matter).
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

okay... now that the thread has been successfully hijacked by "Guest" lets get back to the topic...


my goal again is to be able to mouse move the camera around the "player node" i had this working before without the glitch in version 12 - is there something that has changed in the update that would affect this?? also, what are any soloutions out there that are .net compatable i'm willing to take..

Thanks..
knops

Post by knops »

Irme wrote:okay... now that the thread has been successfully hijacked by "Guest" lets get back to the topic...


my goal again is to be able to mouse move the camera around the "player node" i had this working before without the glitch in version 12 - is there something that has changed in the update that would affect this?? also, what are any soloutions out there that are .net compatable i'm willing to take..

Thanks..
well this is no .NET but it should work (you need some changes I guess), here is some code of my 3rd person cam... here are the private members of the class (for an overview).

Code: Select all

	// irrlicht container
	scene::ICameraSceneNode* mCamera;
	scene::ISceneNode* mChase;

	// kamera einstellungen
	f32 mDegree;
	f32 mZoom;
	f32 mPitch;

	// kamera einstellungen
	f32 mDegreeTo;
	f32 mZoomTo;
	f32 mPitchTo;

	// min/max werte
	f32 mZoomMax;
	f32 mZoomMin;		
	f32 mPitchMax;
	f32 mPitchMin;
(sorry for german comments Im too lazy to remove them). Basically you have 3 value (zoom, rotate and pitch) and 3 target value (zoomTo, pitchTo etc.). mChase is the scenen node you want to follow. Now your class should have functions for handling the movement.... I use something like Pitch() and PitchTo(), they look like this (nearly the same for all 3 types)

Code: Select all

void	CCamera::Pitch(f32 pValue)
{ 
	mPitch+=pValue;

	if(( mPitch < mPitchMin) || ( mPitch > mPitchMax ))
		mPitch-=pValue;

	mPitchTo=mPitch;
}

void	CCamera::PitchTo(f32 pValue)
{ 
	mPitchTo+=pValue;

	if(( mPitchTo < mPitchMin) || ( mPitchTo > mPitchMax ))
		mPitchTo-=pValue;
}

note how PitchTo only changes the target value (and not mPitch which is the current pitch of your cam). Now the last thing is an update method which caclulates and updates the position of the camera.... here it comes

Code: Select all

void	CCamera::Update(u32 pTime)
{
	if(( mCamera ) && ( mChase ))
	{
		// kamera auf ziele testen
		// ----------------------------------------------------

		// zoom target testen
		if( mZoom != mZoomTo)
		{
			f32 dir = f32(mZoomTo - mZoom);

			if( dir < 0 )
			{
				mZoom -= pTime * ZOOMTO_SPEED;
				if( mZoom < mZoomTo )
					mZoom = mZoomTo;
			}
			else
			{
				mZoom += pTime * ZOOMTO_SPEED;
				if( mZoom > mZoomTo )
					mZoom = mZoomTo;
			}
		}

		// rotation target testen
		if( mDegree != mDegreeTo)
		{
			f32 dir = f32(mDegreeTo - mDegree);

			if( dir < 0 ) 
			{
				mDegree -= pTime * ROTATETO_SPEED;
				if( mDegree < mDegreeTo )
					mDegree = mDegreeTo;
			}
			else
			{
				mDegree += pTime * ROTATETO_SPEED;
				if( mDegree > mDegreeTo )
					mDegree = mDegreeTo;
			}
		}

		// winkel target testen
		if( mPitch != mPitchTo)
		{
			f32 dir = f32(mPitchTo - mPitch);

			if( dir < 0 )
			{
				mPitch -= pTime * PITCHTO_SPEED;				
				if( mPitch < mPitchTo )
					mPitch = mPitchTo;
			}
			else
			{
				mPitch += pTime * PITCHTO_SPEED;				
				if( mPitch > mPitchTo )
					mPitch = mPitchTo;
			}

		}

		// kamera neu ausrichten
		// ----------------------------------------------------

		// verfolger position holen
		core::vector3df camPos = mChase->getPosition();
		core::vector3df tmpPos = camPos;

		// vertikalen abstand hinzurechnen
		tmpPos.X += mZoom;

		// tmpPos um camPos rotieren		
		tmpPos.rotateXYBy(mPitch, camPos);
		tmpPos.rotateXZBy(mDegree, camPos);


		// positionieren
		mCamera->setPosition( tmpPos );

		// lookat festlegen
		mCamera->setTarget( camPos );
	}
}

Well thats is basically, dont forget to add a camera scene node to irrlicht in the constructor (and place it in mCamera) and also initialize the values (like mMax.. and mMin). PITCHTO_SPEED etc. are just macros, simply type your favorit speed there (like I said before, you need to find the "good" center).

You now can move your cam with mouse, keys and so on.. this is what my event receiver looks like..

Code: Select all

	static f32 x = 0;
	static f32 y = 0;

	// maus bewegung für kamera
	if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
	{
		switch(event.MouseInput.Event)
		{
		// mausaxen
		case EMIE_MOUSE_MOVED:
			{
				// kamera drehen
				f32 tempx = (f32)event.MouseInput.X;
                Camera->Rotate( x-tempx );
				
				// kamera neigen
				f32 tempy = (f32)event.MouseInput.Y;
                Camera->Pitch( (y-tempy)/2 );			

				x=tempx;
				y=tempy;				
			}
			return true;

		// mausrad
		case EMIE_MOUSE_WHEEL:
			{
				// kamera zoomen
				Camera->ZoomTo(-event.MouseInput.Wheel*400);
			}
			return true;
		}
I think i've posted enough code, now its up to you ;)
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

Hey, thanks - i've been working on the code, got it all translated and have it working - have some bugs to work out, then ill post the code in vb.net for anybody that may want to use it.
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

Well here is the code as promised - i am using it just like this, works great! my main problem was that i was creating an FPS cam instead of a regular camera. once i did that it all started working great.

Code: Select all

Public Class I3RDPerson_Camera
        Const ZOOMTO_SPEED As Double = 5
        Const ROTATETO_SPEED As Double = 1
        Const PITCHTO_SPEED As Double = 1

        Dim mCamera As ICameraSceneNode
        Dim mChase As ISceneNode

        Dim mDegree As Double
        Dim mZoom As Double
        Dim mPitch As Double

        Dim mDegreeTo As Double
        Dim mZoomTo As Double
        Dim mPitchTo As Double

        Dim mZoomMax As Double
        Dim mZoomMin As Double
        Dim mPitchMax As Double
        Dim mPitchMin As Double

        Sub New(ByRef myCam As ICameraSceneNode, ByRef myTarget As ISceneNode)
            mCamera = myCam
            mChase = myTarget
            mZoomMax = 300
            mZoomMin = 1
            mPitchMax = 80
            mPitchMin = 15

            mPitchTo = 15
            mZoomTo = 100
            mDegreeTo = 0
        End Sub

        Sub Pitch(ByVal pValue As Double)
            mPitch += pValue
            If mPitch < mPitchMin Or mPitch > mPitchMax Then mPitch -= pValue
            mPitchTo = mPitch
        End Sub

        Sub PitchTo(ByVal pValue As Double)
            mPitchTo += pValue
            If mPitchTo < mPitchMin Or mPitchTo > mPitchMax Then mPitchTo -= pValue
        End Sub


        Sub Rotate(ByVal pValue As Double)
            mDegree += pValue
            mDegreeTo = mDegree
        End Sub

        Sub RotateTo(ByVal pValue As Double)
            mDegreeTo += pValue
        End Sub


        Sub Zoom(ByVal pValue As Double)
            mZoom += pValue
            If mZoom < mZoomMin Or mZoom > mZoomMax Then mZoom -= pValue
            mZoomTo = mZoom
        End Sub

        Sub ZoomTo(ByVal pValue As Double)
            mZoomTo += pValue
            If mZoomTo < mZoomMin Or mZoomTo > mZoomMax Then mZoomTo -= pValue
        End Sub


        Sub Update(ByVal pTime As Double)
            If Not mCamera Is Nothing And Not mChase Is Nothing Then

                'Zoom The Camera
                If mZoom <> mZoomTo Then
                    Dim dir As Double = mZoomTo - mZoom

                    If dir < 0 Then
                        mZoom -= pTime * ZOOMTO_SPEED
                        If mZoom < mZoomTo Then mZoom = mZoomTo
                    Else
                        mZoom += pTime * ZOOMTO_SPEED
                        If mZoom > mZoomTo Then mZoom = mZoomTo
                    End If
                End If
                mCamera.Target = mChase.Position
                'Rotate The Camera 
                If mDegree <> mDegreeTo Then
                    Dim dir As Double = mDegreeTo - mDegree

                    If dir < 0 Then
                        mDegree -= pTime * ROTATETO_SPEED
                        If mDegree < mDegreeTo Then mDegree = mDegreeTo
                    Else
                        mDegree += pTime * ROTATETO_SPEED
                        If mDegree > mDegreeTo Then mDegree = mDegreeTo
                    End If
                End If
                mCamera.Target = mChase.Position

                'Do The Pitch Stuff
                If mPitch <> mPitchTo Then
                    Dim dir As Double = mPitchTo - mPitch

                    If dir < 0 Then
                        mPitch -= pTime * PITCHTO_SPEED
                        If mPitch < mPitchTo Then mPitch = mPitchTo
                    Else
                        mPitch += pTime * PITCHTO_SPEED
                        If mPitch > mPitchTo Then mPitch = mPitchTo
                    End If
                End If

                'Update Camera Info
                Dim CamPos As Vector3D = mChase.Position
                Dim tmppos As Vector3D = CamPos

                tmppos.X += mZoom

                tmppos.RotateXYBy(mPitch, CamPos)
                tmppos.RotateXZBy(mDegree, CamPos)

                mCamera.Position = tmppos

                mCamera.Target = CamPos
            End If
        End Sub
    End Class
nutpor
Posts: 31
Joined: Sun Jun 12, 2005 5:06 pm
Location: Behind You ^_^

Post by nutpor »

Hmm... I've faced this problem before. I save position of scene node that camera will target at and use this position in camera->setTarget() in next frame. I think scene node will update its position in function OnPostRender() and that's make camera point in the wrong positions.
Hope this help :D .
Don't look back, Look in the ~MIRROR~ to look back.
Post Reply