Thread: Smoothly rotating to another angle on pano nodes
Status: Alpha
Brought to you by:
cwalther
|
From: James C. W. <jfc...@ya...> - 2009-12-10 06:25:51
|
Hi all,
I've been working on a library for cubic panorama rotation, and have run into a problem.
When I run this code, Pipmak will smoothly rotate to either 90, 90, or 90, -90(disregarding panorama limits), and slowly spins.
I can tell there's something wrong with this code, but I don't know what it is exactly, or how to fix it. Can anyone suggest a possible solution? Thanks very much, if anyone can.
CODE**********************************************
cubic { "front.jpg", "right.jpg", "back.jpg", "left.jpg", "top.jpg", "bottom.jpg" }
local tarAZ, tarEL = 45, 45
local viewAZ, viewEL = pipmak.getviewdirection()
local speedAZ, speedEL
if viewAZ > tarAZ then
speedAZ = viewAZ / tarAZ
elseif viewAZ < tarAZ then
speedAZ = tarAZ / viewAZ
end
if viewEL > tarEL then
speedEL = viewEL / tarEL
elseif viewEL < tarEL then
speedEL = tarEL / viewEL
end
hotspotmap "hotspotmap.png"
hotspot {
onmousedown = function()
pipmak.schedule(
0.02,
function()
viewAZ, viewEL = pipmak.getviewdirection()
if viewAZ == tarAZ and viewEL == tarEL then
viewAZ, viewEL = tarAZ, tarEL
else
pipmak.setviewdirection( viewAZ + 0.8, viewEL * speedEL + 0.8 )
end
return 0.02
end
)
end
}
END CODE *************************************
Thanks again,
James
|
|
From: Christian W. <cwa...@gm...> - 2009-12-19 22:37:40
|
James C. Wilson wrote:
> When I run this code, Pipmak will smoothly rotate to either 90, 90, or
> 90, -90(disregarding panorama limits), and slowly spins.
> I can tell there's something wrong with this code, but I don't know what
> it is exactly, or how to fix it. Can anyone suggest a possible solution?
I probably can, if you can explain what exactly you want to achieve, or
what you expect this code to do. I can see that it approximately does
what you describe, but I can't tell in how far that is not what you expect.
A few comments on details that seem strange to me:
> local tarAZ, tarEL = 45, 45
> local viewAZ, viewEL = pipmak.getviewdirection()
> local speedAZ, speedEL
>
> if viewAZ > tarAZ then
> speedAZ = viewAZ / tarAZ
> elseif viewAZ < tarAZ then
> speedAZ = tarAZ / viewAZ
Are you aware that you may be dividing by zero here?
> end
You don't handle the case viewAZ == tarAZ here and leave speedAZ = nil
in that case, is that what you want?
> if viewEL > tarEL then
> speedEL = viewEL / tarEL
> elseif viewEL < tarEL then
> speedEL = tarEL / viewEL
> end
> hotspotmap "hotspotmap.png"
> hotspot {
> onmousedown = function()
> pipmak.schedule(
> 0.02,
> function()
> viewAZ, viewEL = pipmak.getviewdirection()
> if viewAZ == tarAZ and viewEL == tarEL then
> viewAZ, viewEL = tarAZ, tarEL
What's the point of this assignment? It has no effect since in the "if"
statement you just checked that its outcome is already true before.
> pipmak.setviewdirection( viewAZ + 0.8, viewEL * speedEL + 0.8 )
> end
> return 0.02
If you always return a number, the timer will repeat indefinitely, is
that what you want?
> end
> )
> end
> }
-Christian
|
|
From: James C. W. <jfc...@ya...> - 2009-12-20 02:17:17
|
Yesterday I realized most of those problems, and fixed them. The new code runs very well, but oddly enough, doesn't return to exactly the defined target location, missing by about 1.5 degrees x, and 0.2 degrees y.
Here's the new code, commented. Sorry about not commenting the older code-it was quite late.
--included in node.lua
hotspot {
onmousedown = function()
autoPan_tarAZ, autoPan_tarEL = 270, 4
autoPan_time = 1
autoPan()
end
}
--autoPan.lua: an add-on file included in main.lua.
autoPan_funcCount = 0 --the number of times the function has been run.
autoPan_time = 1 --the duration, in seconds, the rotation should take to complete, set
--by onenternode in node.lua
autoPan_rate = 0.025 --the framrate of the rotation, e.g. how many times it runs per
--second.
autoPan_iterCount = 0 --the number of times the function should run, in order to get to the --target angle.
autoPan_tarAZ, autoPan_tarEL = 0, 0 --The target angle.
autoPan_viewAZ, autoPan_viewEL = pipmak.getviewdirection() --the current angle.
autoPan_speedAZ, autoPan_speedEL = 0 --the degree value which gets added to the
--current view angle each time the function runs.
function autoPan() --defining the function
pipmak.schedule(
autoPan_rate, --borrowing the framerate from the global autopan_rate.
function()
autoPan_viewAZ, autoPan_viewEL = pipmak.getviewdirection() --each time the function --is called, set the global to match the current viewing angle.
if autoPan_funcCount == 0 then --if the function has been run 0 times,
autoPan_iterCount = (autoPan_time) / autoPan_rate --then divide the duration of the
--event by the framrate, getting the number of times the function should be run, and dumping it into autoPan_iterCount,
autoPan_speedAZ = (autoPan_tarAZ - autoPan_viewAZ) / autoPan_iterCount
-- Subtract the AZ viewing angle from the
--target, and divide by autopan_iterCount, to get the the degree value which gets added to
--the current view angle each time the function runs.
autoPan_speedEL = (autoPan_tarEL - autoPan_viewEL) / autoPan_iterCount
-- Subtract the EL viewing angle from the
--target, and divide by autopan_iterCount, to get the the degree value which gets added to
--the current view angle each time the function runs.
end
if autoPan_funcCount == autoPan_iterCount then --if the # of times the function
--has been run equals the target number of times, then...
autoPan_funcCount = 0 --reset to 0,
return --stop the function.
else --if NOT, then...
autoPan_funcCount = autoPan_funcCount + 1 --increase the # of times the function
--has been run by 1.
pipmak.setviewdirection(autoPan_viewAZ + autoPan_speedAZ, autoPan_viewEL + autoPan_speedEL ) --add the neccessary change to each
--degree axis, as determined by the previous calcualtions.
end
return autoPan_rate --borrowing the framerate from the global autopan_rate.
end
)
end
CODE END.
Thanks,
James
--- On Sat, 12/19/09, Christian Walther <cwa...@gm...> wrote:
From: Christian Walther <cwa...@gm...>
Subject: Re: Smoothly rotating to another angle on pano nodes
To: pip...@li...
Date: Saturday, December 19, 2009, 4:41 PM
James C. Wilson wrote:
> When I run this code, Pipmak will smoothly rotate to either 90, 90, or
> 90, -90(disregarding panorama limits), and slowly spins.
> I can tell there's something wrong with this code, but I don't know what
> it is exactly, or how to fix it. Can anyone suggest a possible solution?
I probably can, if you can explain what exactly you want to achieve, or
what you expect this code to do. I can see that it approximately does
what you describe, but I can't tell in how far that is not what you expect.
A few comments on details that seem strange to me:
> local tarAZ, tarEL = 45, 45
> local viewAZ, viewEL = pipmak.getviewdirection()
> local speedAZ, speedEL
>
> if viewAZ > tarAZ then
> speedAZ = viewAZ / tarAZ
> elseif viewAZ < tarAZ then
> speedAZ = tarAZ / viewAZ
Are you aware that you may be dividing by zero here?
> end
You don't handle the case viewAZ == tarAZ here and leave speedAZ = nil
in that case, is that what you want?
> if viewEL > tarEL then
> speedEL = viewEL / tarEL
> elseif viewEL < tarEL then
> speedEL = tarEL / viewEL
> end
> hotspotmap "hotspotmap.png"
> hotspot {
> onmousedown = function()
> pipmak.schedule(
> 0.02,
> function()
> viewAZ, viewEL = pipmak.getviewdirection()
> if viewAZ == tarAZ and viewEL == tarEL then
> viewAZ, viewEL = tarAZ, tarEL
What's the point of this assignment? It has no effect since in the "if"
statement you just checked that its outcome is already true before.
> pipmak.setviewdirection( viewAZ + 0.8, viewEL * speedEL + 0.8 )
> end
> return 0.02
If you always return a number, the timer will repeat indefinitely, is
that what you want?
> end
> )
> end
> }
-Christian
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________
Pipmak-Users mailing list
Pip...@li...
news://news.gmane.org/gmane.games.devel.pipmak.user
https://lists.sourceforge.net/lists/listinfo/pipmak-users
|
|
From: Christian W. <cwa...@gm...> - 2009-12-20 11:18:08
|
James C. Wilson wrote: > Yesterday I realized most of those problems, and fixed them. The new > code runs very well, but oddly enough, doesn't return to exactly the > defined target location, missing by about 1.5 degrees x, and 0.2 degrees y. I don't know if that's the whole cause of your deviation, but when you add up a lot of little steps like this you can accumulate a lot of rounding error. Keep in mind that floating-point numbers such as the ones used by Lua have limited precision, and some (most) real numbers cannot be represented exactly as floating-point numbers (even if they can be represented exactly as decimal numbers, e.g. 0.1). Also, what you get back from pipmak.getviewdirection() is not equal in general to what you put into pipmak.setviewdirection(), because Pipmak internally stores them as single-precision floating-point numbers (corresponding to about 9 decimal digits), while Lua uses double-precision numbers (about 18 decimal digits). You shouldn't stop your loop when a certain number of iteration is reached, but when the target angles are reached. And you can't count on them being reached exactly, you need to stop once you're close enough (e.g. less than half a step off) and then snap to the correct target value. More comments: - Why are you putting the parameters into global variables instead of passing them to the autoPan function as arguments? You could also put the intermediate results (autoPan_funcCount etc.) into local variables of the autoPan function, they are visible from the inner function (see <http://www.lua.org/manual/5.0/manual.html#visibility>). You should only use global variables when you have to, since they make your code less encapsulated and harder to maintain - for example, if somewhere else you later happen to use the same global variable name for a different purpose, that can cause hard to find bugs. (Plus, in Lua, they are less efficient than local variables). > autoPan_rate = 0.025 --the framrate of the rotation, e.g. how many > times it runs per second. - No. That's not the rate, that's the inverse of the rate, how many seconds each iteration takes. - Your timer never stops if autoPan_iterCount happens not to be a whole number (autoPan_time isn't a whole multiple of autoPan_rate). -Christian |
|
From: James C. W. <jfc...@ya...> - 2009-12-21 03:18:24
|
Hi Christian, I improved the inexact rotation issue, it's now exact to the thousandth degree on AZ, and the hundreth on EL. That works for me. >You shouldn't stop your loop when a certain number of iteration is >reached, but when the target angles are reached. And you can't count on >them being reached exactly, you need to stop once you're close enough >(e.g. less than half a step off) and then snap to the correct target value Okay, done. >- Why are you putting the parameters into global variables instead of >passing them to the autoPan function as arguments? You could also put >the intermediate results (autoPan_funcCount etc.) into local variables >of the autoPan function, they are visible from the inner function Could you tell me how these are done? I can't find any examples in the demo or in Lua refman, maybe I'm looking in the wrong places... I tried putting the variables into the function as locals, right inside the function autoPan() declaration, and this works with the default values, but I don't know how to "contact" and alter the state of these while calling the function. Thanks, James --- On Sun, 12/20/09, Christian Walther <cwa...@gm...> wrote: From: Christian Walther <cwa...@gm...> Subject: Re: Smoothly rotating to another angle on pano nodes To: pip...@li... Date: Sunday, December 20, 2009, 5:22 AM James C. Wilson wrote: > Yesterday I realized most of those problems, and fixed them. The new > code runs very well, but oddly enough, doesn't return to exactly the > defined target location, missing by about 1.5 degrees x, and 0.2 degrees y. I don't know if that's the whole cause of your deviation, but when you add up a lot of little steps like this you can accumulate a lot of rounding error. Keep in mind that floating-point numbers such as the ones used by Lua have limited precision, and some (most) real numbers cannot be represented exactly as floating-point numbers (even if they can be represented exactly as decimal numbers, e.g. 0.1). Also, what you get back from pipmak.getviewdirection() is not equal in general to what you put into pipmak.setviewdirection(), because Pipmak internally stores them as single-precision floating-point numbers (corresponding to about 9 decimal digits), while Lua uses double-precision numbers (about 18 decimal digits). You shouldn't stop your loop when a certain number of iteration is reached, but when the target angles are reached. And you can't count on them being reached exactly, you need to stop once you're close enough (e.g. less than half a step off) and then snap to the correct target value. More comments: - Why are you putting the parameters into global variables instead of passing them to the autoPan function as arguments? You could also put the intermediate results (autoPan_funcCount etc.) into local variables of the autoPan function, they are visible from the inner function (see <http://www.lua.org/manual/5.0/manual.html#visibility>). You should only use global variables when you have to, since they make your code less encapsulated and harder to maintain - for example, if somewhere else you later happen to use the same global variable name for a different purpose, that can cause hard to find bugs. (Plus, in Lua, they are less efficient than local variables). > autoPan_rate = 0.025 --the framrate of the rotation, e.g. how many > times it runs per second. - No. That's not the rate, that's the inverse of the rate, how many seconds each iteration takes. - Your timer never stops if autoPan_iterCount happens not to be a whole number (autoPan_time isn't a whole multiple of autoPan_rate). -Christian ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Pipmak-Users mailing list Pip...@li... news://news.gmane.org/gmane.games.devel.pipmak.user https://lists.sourceforge.net/lists/listinfo/pipmak-users |
|
From: Christian W. <cwa...@gm...> - 2009-12-21 09:50:32
|
James C. Wilson wrote:
> >- Why are you putting the parameters into global variables instead of
> >passing them to the autoPan function as arguments? You could also put
> >the intermediate results (autoPan_funcCount etc.) into local variables
> >of the autoPan function, they are visible from the inner function
> Could you tell me how these are done? I can't find any examples in the
> demo or in Lua refman, maybe I'm looking in the wrong places...
> I tried putting the variables into the function as locals, right inside
> the function autoPan() declaration, and this works with the default
> values, but I don't know how to "contact" and alter the state of these
> while calling the function.
You don't need to "contact" the local variables, you pass the ones you
need to set from outside as arguments. From inside, they are treated
indentically to local variables. Like this:
function autoPan(tarAZ, tarEL, time)
local rate = 0.025
local iterCount = time/rate
--...
pipmak.schedule(
rate,
function()
--do something involving tarAZ, tarEL, time, rate, iterCount, ...
end
)
end
and then you call it as
autoPan(270, 4, 1)
-Christian
|
|
From: James C. W. <jfc...@ya...> - 2009-12-30 00:01:13
|
Sorry for the late reply; holidays and all that. Thanks for the clarifaction. One problem that I've discovered with the "check if current direction ~ target direction and then angle the camera to precisly equal the target" is that if I pan myself while the program is running, the program loses track of where it's going, and hits the 80 EL pan limit, slowely spinning on the vertical access. Obviously, to make any of this effective the panorama must be frozen from player control. But since there's not any way to do that yet, I need to use the one that won't hit a dead end, and right now that's the version that checks how many times the function has run...Any suggestions? Thanks, James --- On Mon, 12/21/09, Christian Walther <cwa...@gm...> wrote: From: Christian Walther <cwa...@gm...> Subject: Re: Smoothly rotating to another angle on pano nodes To: pip...@li... Date: Monday, December 21, 2009, 4:49 AM James C. Wilson wrote: > >- Why are you putting the parameters into global variables instead of > >passing them to the autoPan function as arguments? You could also put > >the intermediate results (autoPan_funcCount etc.) into local variables > >of the autoPan function, they are visible from the inner function > Could you tell me how these are done? I can't find any examples in the > demo or in Lua refman, maybe I'm looking in the wrong places... > I tried putting the variables into the function as locals, right inside > the function autoPan() declaration, and this works with the default > values, but I don't know how to "contact" and alter the state of these > while calling the function. You don't need to "contact" the local variables, you pass the ones you need to set from outside as arguments. From inside, they are treated indentically to local variables. Like this: function autoPan(tarAZ, tarEL, time) local rate = 0.025 local iterCount = time/rate --... pipmak.schedule( rate, function() --do something involving tarAZ, tarEL, time, rate, iterCount, ... end ) end and then you call it as autoPan(270, 4, 1) -Christian ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Pipmak-Users mailing list Pip...@li... news://news.gmane.org/gmane.games.devel.pipmak.user https://lists.sourceforge.net/lists/listinfo/pipmak-users |
|
From: Christian W. <cwa...@gm...> - 2009-12-30 11:48:07
|
James C. Wilson wrote: > One problem that I've discovered with the > "check if current direction ~ target direction and then angle the camera > to precisly equal the target" is that if I pan myself while the program > is running, the program loses track of where it's going, and hits the 80 > EL pan limit, slowely spinning on the vertical access. Obviously, to > make any of this effective the panorama must be frozen from player > control. But since there's not any way to do that yet, I need to use the > one that won't hit a dead end, and right now that's the version that > checks how many times the function has run...Any suggestions? Instead of calculating the direction incrementally by adding small steps to the current direction, calculate it from scratch in every frame using the starting parameters (recorded when you start the animation) and the elapsed time (from the first argument of the timer function). -Christian |
|
From: James C. W. <jfc...@ya...> - 2010-01-01 06:21:15
|
Hi Christian, Hmmm...Doing that gradually slows it down till it's moving at a crawl. Eventually it reaches the target location, but it takes a while, and looks weird. I think it's because when th code runs every frame, while it avoids panning miscalualtions, it also makes the return value smaller with each run. --- On Wed, 12/30/09, Christian Walther <cwa...@gm...> wrote: From: Christian Walther <cwa...@gm...> Subject: Re: Smoothly rotating to another angle on pano nodes To: pip...@li... Date: Wednesday, December 30, 2009, 6:47 AM James C. Wilson wrote: > One problem that I've discovered with the > "check if current direction ~ target direction and then angle the camera > to precisly equal the target" is that if I pan myself while the program > is running, the program loses track of where it's going, and hits the 80 > EL pan limit, slowely spinning on the vertical access. Obviously, to > make any of this effective the panorama must be frozen from player > control. But since there's not any way to do that yet, I need to use the > one that won't hit a dead end, and right now that's the version that > checks how many times the function has run...Any suggestions? Instead of calculating the direction incrementally by adding small steps to the current direction, calculate it from scratch in every frame using the starting parameters (recorded when you start the animation) and the elapsed time (from the first argument of the timer function). -Christian ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Pipmak-Users mailing list Pip...@li... news://news.gmane.org/gmane.games.devel.pipmak.user https://lists.sourceforge.net/lists/listinfo/pipmak-users |