well first of all remove the interpolation and make sure everything is working like this:
rotation := rV;
well first of all remove the interpolation and make sure everything is working like this:
rotation := rV;
Hello Dan, Yes it does work fine, expect still the limitation on the Y axis,
However after a bit testing i see the problem is on the xz rotation it takes 2*PI for full rotation, on the Y Axis, it would technically take 4*PI, so instead i will do a basic test for flipping the camera, and changing the right and up vectors so the view will then be upside down.
Last edited by Colin; 17-11-2012 at 10:36 AM.
Download the Ziron Assembler
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
OK i have my camera system working exactly how i want it except for 1 problem, I have uploaded test build, press N to spawn a ball, then if you press down and to the left so the ball rolls around the camera will at 1 point spin in the opposite direction back to the ball.
New code:
else everything is nice, camera moves very smoothly for the most part, just this problem that is a pain...Code:// // sets the look at target of the camera // procedure TCameraController.setTarget(const targ: TD3DXMatrix); const tween = 0.01; var pos, rV: TD3DXVector3; diff: TD3DXVector3; begin pos := D3DXVector3(targ._41, targ._42+5, targ._43); // + 5 look slightly above the object D3DXVec3Subtract(diff, pos, position); D3DXVec3Normalize(diff, diff); rV := D3DXVector3( arctan2(diff.z, diff.x), arcsin(diff.y), 0 ); rotation.x := (rV.x * tween) + rotation.x * (1 - tween); rotation.y := (rV.y * tween) + rotation.y * (1 - tween); rotation.z := (rV.z * tween) + rotation.z * (1 - tween); end; // // sets the position of the camera somewhere behind the object, either facing or by velocity // procedure TCameraController.Follow(m: TD3DXMatrix; heading: TD3DXVector3); const Dist = 20; MaxDist = 50; DefHeight = 15; var tweenSpeed: TD3DXVector3; absdist: TD3DXVector3; pos: TD3DXVector3; gPoint: TD3DXVector3; begin pos := D3DXVector3(m._41, m._42, m._43); if (heading.x > 0.00001) and (heading.z > 0.00001) then begin D3DXVec3Normalize(heading, heading); gPoint.x := m._41 + -Dist*heading.x; gPoint.z := m._43 + -Dist*heading.z; gPoint.y := m._42 + DefHeight; end else begin D3DXVec3Normalize(heading, pos); gPoint.x := m._41 + -Dist*heading.x; gPoint.z := m._43 + -Dist*heading.z; gPoint.y := m._42 + DefHeight; end; absdist := D3DXVector3(abs(pos.x-position.x), abs(pos.y-position.y), abs(pos.z-position.z) ); if absdist.x > MaxDist then tweenSpeed.x := 0.005 * (absdist.x - (MaxDist-1)) else tweenSpeed.x := 0.005; tweenSpeed.y := 0.005; if absdist.z > MaxDist then tweenSpeed.z := 0.005 * (absdist.z - (MaxDist-1)) else tweenSpeed.z := 0.005; position.x := (gPoint.x * tweenSpeed.x) + position.x * (1 - tweenSpeed.x); position.y := (gPoint.y * tweenSpeed.y) + position.y * (1 - tweenSpeed.y); position.z := (gPoint.z * tweenSpeed.z) + position.z * (1 - tweenSpeed.z); end;
Any ideas?
Thanks.
Last edited by Colin; 17-11-2012 at 03:18 PM.
Download the Ziron Assembler
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
you are again interpolating the angles, only doing it manually this time instead of using a d3dx function.Code:rotation.x := (rV.x * tween) + rotation.x * (1 - tween); rotation.y := (rV.y * tween) + rotation.y * (1 - tween); rotation.z := (rV.z * tween) + rotation.z * (1 - tween);
ok I suppose I have to explain why that is bad. as (I assume) you know arctan2 gives you an angle between
-Pi and Pi, and you store these angles in your rotation variable. every time you adjust your camera you get a
new angle and you interpolate between the old rotation variable and the new rV variable. the values that you
interpolate are angles (-Pi..Pi). so here's an example of the major issue with angles: what if the old angle is
-0.9 * Pi and the new angle is 0.9 * Pi? the actual angular difference here is only 0.2 * Pi but if you
numerically interpolate between these angles by a step size of 0.5 (for example) you will end up exactly at 0!
while you expect to be at Pi, so your camera will turn exactly in the opposite direction.
as I have said before, you should instead interpolate the direction vectors of the camera. the easiest way to
do that is to store the current direction vector and the new direction vector, interpolate between them and
extract your angles from the result. but since I see that you are trying to only deal with the angles you should
simply convert the rotation variable angles into a vector, interpolate it with the diff vector then extract the
angles from the result.
ok at this point if you need more help I can give you the code that will simply work. but that would be no fun would it
I understand the issue yes, this is the problem that i have been mainly trying to solve.
What do you mean by "convert the rotation variable angles into a vector" ? the rotation variable is already a vector ?
Download the Ziron Assembler
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
no it's not=) you just store the angles it in a vector format that's it. what you need to do is convert these angles into a 3d direction vector.
ok, here's how you do it:
then you find the "diff" vector just as you do now.Code:var Dir: TD3DXVector3; sh, ch, sv, cv: Single; ... SinCos(rotation.x, sh, ch); SinCos(rotation.y, sv, cv); Dir.x := ch * cv; Dir.y := sv; Dir.z := sh * cv;
interpolate between the Dir and diff vector (Dir is the old camera direction, diff is the new camera direction).
so you might want to do something like this:
and finally convert the Dir vector to rotation angles. I don't know why you are using a 3d vector for rotationCode:Dir.x := Dir.x + (diff.x - Dir.x) * tween; Dir.y := Dir.y + (diff.y - Dir.y) * tween; Dir.z := Dir.z + (diff.z - Dir.z) * tween; D3DXVec3Normalize(Dir, Dir);
angles, but here it is:
overall this approach should work fine. however, there is still a more consistent and reliable way of spherically interpolating quaternions instead of vectors,Code:rotation := D3DXVector3( arctan2(Dir.z, Dir.x), arcsin(Dir.y), 0 );
but that is a tale for another time.
Last edited by Dan; 17-11-2012 at 03:59 PM.
Hello Dan,
Thanks for the code, and for the explanation, it has helped me to understand the idea behind the method. I have updated the procedure with your code and now it works exactly as it should.
Once I finish adding an Actor class, then maybe i will come back to working on the camera class to look into the quaternion alternatives.Code:// // sets the look at target of the camera // procedure TCameraController.setTarget(const targ: TD3DXMatrix); const tween = 0.01; var pos, diff, Dir: TD3DXVector3; sh, ch, sv, cv: Extended; begin SinCos(rotation.x, sh, ch); SinCos(rotation.y, sv, cv); Dir := D3DXVector3(ch * cv, sv, sh * cv); pos := D3DXVector3(targ._41, targ._42+1, targ._43); // + 1 look slightly above the object D3DXVec3Subtract(diff, pos, position); D3DXVec3Normalize(diff, diff); Dir := D3DXVector3( Dir.x + (diff.x - Dir.x) * tween, Dir.y + (diff.y - Dir.y) * tween, Dir.z + (diff.z - Dir.z) * tween ); D3DXVec3Normalize(Dir, Dir); rotation := D3DXVector3( arctan2(Dir.z, Dir.x), arcsin(Dir.y), 0 ); end;
Thanks again
Download the Ziron Assembler
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
Bookmarks