Damping with Runge-Kutta
I am trying to apply spring damping to a simple first person camera demo to give it a smoother effect. The problem is it becomes jerky when I use a slow forward speed. I''m thinking this is due to an Euler Integration problem.
Can someone help and explain what I need to do to this:
In my spring damping function (taken from game programming gems 1)... where does the problem lie? F = (-k_s * x) - (k_d * v)
3d vectors: disp, currPos, trgPos, trgPrevPos, velocity
disp = currPos - trgPos;
velocity = (prevTrgPos - trgPos) * deltaTime;
forceMag = springConst * (springLen - disp.length()) + dampConst * )DotProduct(disp, velocity) / disp.length());
disp.normalize();
disp *= forceMag * deltaTime;
return currPos += disp;
quote:
Original post by newpers
I am trying to apply spring damping to a simple first person camera demo to give it a smoother effect. The problem is it becomes jerky when I use a slow forward speed. I''m thinking this is due to an Euler Integration problem.
Good observation! Euler integration is inherently unstable when you have springs, unless you add damping.
quote:
Original post by newpers
Can someone help and explain what I need to do to this:
In my spring damping function (taken from game programming gems 1)... where does the problem lie? F = (-k_s * x) - (k_d * v)
3d vectors: disp, currPos, trgPos, trgPrevPos, velocity
disp = currPos - trgPos;
velocity = (prevTrgPos - trgPos) * deltaTime;
forceMag = springConst * (springLen - disp.length()) + dampConst * )DotProduct(disp, velocity) / disp.length());
disp.normalize();
disp *= forceMag * deltaTime;
return currPos += disp;
There isn''t a problem with the Game Programming Gems formula. I see a few problems with your implementation.
I''m taking trgPos to be the position of the object the camera is looking at, and currPos to be the position of the camera. And springLen is the unstretched length of the spring.
Looks like your velocity calc is wrong. Velocity is distance travelled per unit time, but you are calculating distance travelled times time. I would also say that, since it is the camera motion you want to smooth, you should be calculating the camera velocity not target velocity. So I believe you want velocity to be:
velocity = (prevCameraPos - currPos) / deltaTime;
Now, your velocity will be larger.
It also looks like you''re calculating your force magnitude wrong in one place. You have your damping acting in the wrong direction, in the same direction as the projected velocity. It should be in the opposite direction. You should have:
forceMag = springConst * (springLen - disp.length()) - dampConst * )DotProduct(disp, velocity) / disp.length());
Apart from that, I don''t immediately see anything major wrong with your implementation. If these fixes don''t work, it may be that you are just operating outside of the stable parameters for Euler integration. For example, if damping is not enough Euler will be unstable. If damping is too much it will be unstable, strangely. And regardless of damping, if your spring is too stiff then Euler will never be stable.
It may be worth exploring an alternate integration routine. The title of your thread is "Damping with Runge-Kutta" but you have not mentioned RK in your discussion. Have you actually tried RK?
Jeff Lander (I believe) did demonstrate RK vs. other methods in one or more articles in Game Developer Magazine. You can read the articles online at www.gamasutra.com (features->programming), which requires a free registration.
You can also download a presentation and technical paper that I presented at GDC 2001 on the subject of numerical methods and stability for game physics. Its fairly technical, but could be helpful. You can find my documents here:
http://www.gdconf.com/archives/proceedings/2001/prog_papers.html
The paper and presentation are available in PDF and Word/Powerpoint format. You''ll want to focus on the numerical stability part primarily.
Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
That whole code goes into a function named SpringDamp(...).
<>
You are correct, velocity = deltaX / deltaTime... At first when I saw this I thought the Author screwed up. In fact deltaTime is always < 0 (and is around .01) and is calculated by subtracting the tick times and dividing by 1000.. so i guess multiplying by .01 saves from converting that number, then dividing... I may not be right though.
<
You are correct, velocity = deltaX / deltaTime... At first when I saw this I thought the Author screwed up. In fact deltaTime is always < 0 (and is around .01) and is calculated by subtracting the tick times and dividing by 1000.. so i guess multiplying by .01 saves from converting that number, then dividing... I may not be right though.
Oh, I didn''t realize that whole code block came from GPG I. I thought just the equation "F = ..." came from the book. Doesn''t mean there isn''t an error, though! But it surely is possible to move delta_time''s around sometimes to reduce the number of divides.
Did the rest of my analysis make sense? Did it help?
Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Did the rest of my analysis make sense? Did it help?
Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement