Is there an easy way to script an object flying around in a circle using intervals? I want to place the object at a position X,Y,Z and orient it with its instantaneous heading angle Psi and a constant roll angle.
Say we want an object to fly at a constant translational velocity Vt meters per second and an altitude H meters in a circle of radius R meters. To place this object in Panda3D we will need to compute the X & Y ground coordinates in meters and the heading angle Psi for any time T.
If I were to do this manually I would use code similar to the following. I would like to perform this using Intervals because that would greatly ease the coding of my input deck parsing.
w = float(Vt)/float(R)
theta = w*float(t) # Angle from X axis to point (x,y) on circle
x = float(R)*math.cos(theta)
y = float(R)*math.sin(theta)
psi = math.fmod((math.pi/2.0 + theta),math.pi*2.0) # Heading angle
R = 1000
Vt = 100
t = 0.0
dt = 0.1
psiD = 90.0
thetaD = 0.0
while thetaD <= 360.0:
tSample = getTrajectorySample(t,R,Vt)
x = tSample
y = tSample
z = 100
psiD = float(tSample)*180.0/math.pi
thetaD = float(tSample)*180.0/math.pi
s = "T: %7.2f, X: %8.2f, Y: %8.2f, Gamma: %8.2f, Theta: %8.2f" % \
# In Panda3D I would do this now
# object setHpr(psiD,0,-10)
t = t + dt
You could use the LerpFunctionInterval to call any arbitrary function each frame with a different value of t. This function might, for instance, compute the appropriate X, Y, Z for the corresponding point around the circle, very much like the body of your for loop.
But if all you want is to move your object in a circle, it might be much easier just to parent it to a node that’s got a LerpHprInterval on it, such that the parent node is rotating in a circle. If the local pos is then set R meters away from the origin, then your object will rotate in a circle of radius R.
From this code I see two instances of NodePath, one created with a call to render.attachNewNode(…) and one created with a call to loader.loadModel(…). The “hrpInterval(…)” method of each of these NodePath instances is being called. Unfortunately, the documentation for NodePath makes no mention of a method “hprInterval(…)”. Apparently, by looking at the other calls (e.g. loop() ), the “hrpInterval(…)” method is returning a reference to an instance of Interval encapsulated by that class. The only problem at this point (other than not knowing the origin of the hprInterval() method) is that I don’t know what the arguments to that method are. I need to understand precisely what the arguments to that method are in order to use it for my problem. So … baffled … I take a wild guess and hope that these nodes are actually of type Actor. I go to Documentation->List of Classes->Actor and find no method “hprInterval()”. At this point I am getting a little frustrated because there are obviously a lot of other programmers who figured this out and I am feeling a tad dumb because of my lack of success so far. Just for funsies, I go look at the documentation for the Interval constructor:
__init__(nodePath, hpr, duration, name)
Unfortunately, there is no documentation for the arguments … just their names.
Looking at the calls to “hprInterval(…)” in the example code shows me that the first argument is a scalar value … hmmmm … it looks like this is the rotation rate or maybe the rotation period. Now the second argument is a Vec3 of what I suspect are some sort of angular components (HPR).
And the sleuthing goes on …
Maybe I am just a little slow but then again, I don’t quite think this is all that simple.
As it happens, i = nodePath.hprInterval(args) is an undocumented shortcut for i = LerpHprInterval(nodePath, args). All of the arguments to nodePath.hprInterval() are the same as those for the LerpHprInterval constructor, with the exception of the first argument (the NodePath), which does not appear in the argument list because it is given by the calling object.