What I’m trying to do is to project a bunch of rays from a node but I don’t want them to be parallel but to go out in a angle (like light coming from a flash-light) and I want to control both the horizontal and vertical angles (also negative angles and parallel lines at 90deg).
I tried using a LensNode, tried some trigonometry but I had little success, something was always wrong. My last attempt was to make a quaternion, set its heading and pitch then get its forward vector, it would be quite elegant and simple… if it worked. I’m not sure if I’m doing something wrong, or if it’s some inherent property of quaternions but the vector I get is just slightly wrong (at least in one plane):
This is how I expect it to look:
(this is from a orographic camera, there are 5 rows and 5 columns of rays, but the rays overlap all nice)
…and this is what I get:
Here is my code:
from panda3d.core import *
from direct.showbase import ShowBase
from direct.showbase.DirectObject import DirectObject
from direct.gui.OnscreenText import OnscreenText
# Function to put instructions on the screen.
def addInstructions(pos, msg):
return OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), scale=.05,
shadow=(0, 0, 0, 1), parent=base.a2dTopLeft,
pos=(0.08, -pos - 0.04), align=TextNode.ALeft)
class App(DirectObject):
def __init__(self):
self.base = ShowBase.ShowBase()
#make the camera orthographic
self.base.disableMouse()
base.camLens=OrthographicLens()
film_size=Vec2(base.get_size())
film_size/=film_size[0]/16 #zoom out
base.camLens.set_film_size(film_size)
base.cam.node().set_lens(base.camLens)
#instructions
self.inst1 = addInstructions(0.06, "UP ARROW: View from top")
self.inst2 = addInstructions(0.12, "RIGHT ARROW: View from side")
self.inst3 = addInstructions(0.18, "Current view:")
#view from the side
self.set_view((-100, 0, 0), (-90, 0, 0), 'side')
node=render.attach_new_node('node')
rows=5
columns=5
row_offset=0.5
column_offset=0.5
row_angle=30.0
column_angle=15.0
lines=[]
q=Quat()
for row in range(rows):
for column in range(columns):
local_origin=Point3(row*row_offset, 0, column*column_offset)
origin=render.get_relative_point(node, local_origin)
#scale the angles
hpr=(row_angle-row_angle*row/(rows-1)*2.0,
-1.0*(column_angle-column_angle*column/(columns-1)*2.0),
0.0)
q.set_hpr(hpr)
v=q.get_forward()*100.0 #target a point 100.0 units away
target=render.get_relative_vector(node, v)+origin
lines.append((origin, target))
#draw lines
l=LineSegs()
for origin, target in lines:
l.move_to(origin)
l.draw_to(target)
line=render.attach_new_node(l.create())
#key binds
self.accept('arrow_right', self.set_view, [(-100, 0, 0), (-90, 0, 0), 'side'])
self.accept('arrow_up', self.set_view, [(0, 0, 100), (-90, -90, 0), 'top'])
def set_view(self, pos, hpr, name):
'''Sets the camera hpr and pos andl also display a name'''
base.camera.set_pos(pos)
base.camera.set_hpr(hpr)
self.inst3.destroy()
self.inst3 = addInstructions(0.18, "Current view: "+name)
#run it
app=App()
app.base.run()
If someone has any insights how to fix this, or some other idea how to get the same result please do help.