miscellaneous useful functions

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.

Actually, I think those delta yaw functions could also be implemented faster, using Vec3.angleRad and Vec3.angleDeg.

I think that even if using those you still have to find out the value that the vector should be which means either setting up dummy nodes and calling lookat and getH() (and cos and sin and adjustments for them) or transforming the point as I am, then converting it into a normalized vector, then calling the function, then figuring out which direction to go as it returns an unsigned angle according to the docs. The question boils down to is atan2 faster or slower than angleDeg/angleRad although I believe there is slightly more overhead in that more things need to be created (vectors and such) for angleDeg.

In the end it does not matter as these are fast enough; I am calling them 50-60 times a frame and not noticing any slowdown (although it is locked to 60 frames a second…) I use them to compute hpr intervals constantly.