Page 1 of 1
Camera Flickers When Setting Target
Posted: Tue Dec 13, 2005 1:40 am
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]
Posted: Tue Dec 13, 2005 7:57 am
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
Posted: Tue Dec 13, 2005 7:45 pm
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.
Posted: Tue Dec 13, 2005 9:59 pm
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).
Posted: Tue Dec 13, 2005 10:59 pm
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
Posted: Tue Dec 13, 2005 11:03 pm
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.
Knops
Posted: Tue Dec 13, 2005 11:30 pm
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).
Posted: Wed Dec 14, 2005 1:28 am
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..
Posted: Wed Dec 14, 2005 3:42 pm
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
![Wink ;)](./images/smilies/icon_wink.gif)
Posted: Sat Dec 17, 2005 7:16 am
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.
Posted: Sun Dec 18, 2005 6:16 am
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
Posted: Sun Dec 18, 2005 4:20 pm
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
![Very Happy :D](./images/smilies/icon_biggrin.gif)
.