I use these functions in almost everything I code…they come in useful. They also are not very intuitive or straightforward. The delta yaw functions will find the required change in heading that the node must change to point towards the other node/point. The getyaw returns the absolute yaw. The pprint function flushes the buffer so it appears straight away on non cmd prompt outputs. The measurements class finds the dimensions of the node tree in question.
I have added to this as I have needed, and maybe it will help someone.
from pandac.PandaModules import *
from math import *
import sys
def pprint(s,n=True):
if type(s)!=str:
s = repr(s)
if n: s+='\n'
sys.stdout.write(s)
sys.stdout.flush()
def dsin(angle):
a = sin(radians(angle))
if abs(a)<.001: a=0
return a
def dcos(angle):
a = cos(radians(angle))
if abs(a)<.001: a=0
return a
def sgn(val):
if val>0: return 1
elif val<0: return -1
else: return 0
def deltaYaw(obj1,obj2):
'''returns the shortest angle required to rotate obj1 to point towards obj2. in the x-y plane (heading)'''
pos = obj2.getPos()
pos.setZ(obj1.getZ())
point = obj1.getRelativePoint(render,pos)
a=degrees(atan2(point.getY(),point.getX()))#-90
if a<-90 and a>-180: #is negative for this quadrant????
return 90-a
return a-90
def deltaYaw2(obj1,x2,y2):
point = obj1.getRelativePoint(render,Vec3(x2,y2,0))
a=degrees(atan2(point.getY(),point.getX()))#-90
if a<-90 and a>-180:
return 90-a
return a-90
def deltaYaw3(a1,a2):
while a1<0: a1+=360
while a2<0: a2+=360
while a1>360: a1-=360
while a2>360: a2-=360
a = a2-a1
if abs(a)>180:
a = (360-abs(a))*sgn(-a)
return a
def getYaw(obj1,obj2):
pos1 = obj1.getPos()
pos2 = obj2.getPos()
return getYaw3(pos1[0],pos2[0],pos1[1],pos2[1])
def getyaw2(obj1,x,y):
pos = obj1.getPos()
return getYaw3(pos[0],x,pos[1],y)
def getYaw3(x1,x2,y1,y2):
a=degrees(atan2(y2-y1,x2-x1))
while a<-90: a+=360
while a>270: a-=360
if a>=0 and a<=180:
return 180-a
if a<=0 and a>=-180:
return -180-a
#returns measurements in world coordinates
class measurements(object):
@staticmethod
def height(node):
pt1, pt2 = node.getTightBounds()
modelZDim = pt2.getZ() - pt1.getZ()
return modelZDim
@staticmethod
def width(node):
pt1, pt2 = node.getTightBounds()
modelXDim = pt2.getX() - pt1.getX()
return modelXDim
@staticmethod
def length(node):
pt1, pt2 = node.getTightBounds()
modelYDim = pt2.getY() - pt1.getY()
return modelYDim
@staticmethod
def biggestSideBase(node):
"""returns the bigger between width and length"""
pt1, pt2 = node.getTightBounds()
modelYDim = (pt2.getY() - pt1.getY())
modelXDim = (pt2.getX() - pt1.getX())
if modelXDim > modelYDim: return modelXDim
return modelYDim
@staticmethod
def biggestSide(node):
"""returns the biggest between width,length and height"""
pt1, pt2 = node.getTightBounds()
modelYDim = (pt2.getY() - pt1.getY())
modelXDim = (pt2.getX() - pt1.getX())
modelZDim = (pt2.getZ() - pt1.getZ())
if modelXDim > modelYDim:
if modelXDim>modelZDim: return modelXDim
else: return modelZDim
else:
if modelYDim>modelZDim: return modelYDim
else: return modelZDim
The fundamental problem these solve is that the trig functions assume that zero is based off the positive x axis while panda (and most 3d engines) define zero as off of the positive y axis.