Hello,
I need some help getting collision to work with multiple cameras. What I have is three display regions and three cameras. Two display regions are side by side and will be used to compare two models, while the third will be used as a sort of HUD. The collision I am trying to do is picking a 3D object by making a collision ray. Any help in setting the cameras and the collision rays/queues would be vary helpful. Thanks in advanced.
some code…
setting the HUD camera up and creating the display regions
#hud camera (drawn over top of regular camera to prevent z fighting between model and 3d hud elements
self.hudCam = Camera('hudCamera')
self.orthoLens = OrthographicLens()
self.orthoLens.setFilmSize(1,.8)
self.hudCam.setLens(self.orthoLens)
self.hudCamera = render.attachNewNode(self.hudCam)
self.hudCamera.setPos(constants.position_hudcamera) #make it beyond the clipping plane so the other cameras can't see it
#set up camera display regions (orbitCamera1, orbitCamera2, hud)
self.dr = base.camNode.getDisplayRegion(0) #get the default display region
self.dr.setActive(0) #activate or deactivate the default display region (1=activate, 0=deactivate)
self.window = self.dr.getWindow() #get the current window
#create the two model cameras
self.orbitCamera1 = classFactories.OrbitCamera()
self.orbitCamera2 = classFactories.OrbitCamera()
self.drModel1 = self.window.makeDisplayRegion(constants.display_region_model1.getX(),constants.display_region_model1.getY(),constants.display_region_model1.getZ(),constants.display_region_model1.getW()) #create a display region that covers the left side of the screen
self.drModel1.setCamera(self.orbitCamera1.getCameraNodePath())
self.drModel2 = self.window.makeDisplayRegion(constants.display_region_model2.getX(),constants.display_region_model2.getY(),constants.display_region_model2.getZ(),constants.display_region_model2.getW())
self.drModel2.setCamera(self.orbitCamera2.getCameraNodePath())
self.drHud = self.window.makeDisplayRegion(constants.display_region_hud.getX(),constants.display_region_hud.getY(),constants.display_region_hud.getZ(),constants.display_region_hud.getW()) #create a display region that covers the whole screen for the hud
self.drHud.setCamera(self.hudCamera)
# dummy node for orbitCamera1, we will rotate the dummy node fro camera rotation
self.parentnode1 = render.attachNewNode('camparent1')
self.parentnode1.reparentTo(render)#self.shoeImpression) # inherit transforms
self.parentnode1.setEffect(CompassEffect.make(render)) # NOT inherit rotation
self.parentnode1.setPos(constants.position1.getX(),constants.position1.getY()+2,constants.position1.getZ())
self.orbitCamera1.reparentTo(self.parentnode1)
self.orbitCamera1.lookAt(self.parentnode1)
self.orbitCamera1.setY(constants.orbit_cam_default_distance_to_model) # camera distance from model
# dummy node for orbitCamera2, we will rotate the dummy node fro camera rotation
self.parentnode2 = render.attachNewNode('camparent2')
self.parentnode2.reparentTo(render)#self.shoeImpression) # inherit transforms
self.parentnode2.setEffect(CompassEffect.make(render)) # NOT inherit rotation
self.parentnode2.setPos(constants.position2.getX(),constants.position2.getY()+2,constants.position2.getZ())
self.orbitCamera2.reparentTo(self.parentnode2)
self.orbitCamera2.lookAt(self.parentnode2)
self.orbitCamera2.setY(constants.orbit_cam_default_distance_to_model) # camera distance from model
collision setup
#collision setup
base.cTrav = CollisionTraverser()
self.queue_model1 = CollisionHandlerQueue()
self.queue_model2 = CollisionHandlerQueue()
self.queue_hud = CollisionHandlerQueue()
#picker for the model
self.pickerNode = CollisionNode('mouseRay1')
self.pickerNP = camera.attachNewNode(self.pickerNode)
self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.pickerRay = CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
base.cTrav.addCollider(self.pickerNP, self.queue_model1)
#picker for model 2
self.pickerNode2 = CollisionNode('mouseRay2')
self.pickerNP2 = camera.attachNewNode(self.pickerNode2)
self.pickerNode2.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.pickerRay2 = CollisionRay()
self.pickerNode2.addSolid(self.pickerRay2)
base.cTrav.addCollider(self.pickerNP2, self.queue_model2)
#picker for the hud
self.hudPickerNode = CollisionNode('hudMouseRay')
self.hudPickerNP = self.hudCamera.attachNewNode(self.hudPickerNode)
self.hudPickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.hudPickerRay = CollisionRay()
self.hudPickerNode.addSolid(self.hudPickerRay)
base.cTrav.addCollider(self.hudPickerNP, self.queue_hud)
the clicking code. Only the HUD clicking works (there is a 3D model on the HUD), and when a display region is clicked it is recognized but it doesnt queue/detect any collision (so it prints “rbitCamera1 click ‘+str(base.mouseWatcherNode.getMouseX())+’,’+str(base.mouseWatcherNode.getMouseY())”)
def click(self):
base.cTrav.showCollisions(render)
base.cTrav.traverse(render)
if base.mouseWatcherNode.hasMouse():
mpos = base.mouseWatcherNode.getMouse()
print ' '
#perform collisions for the mouse based on which side of the screen it is on, this prevents both models
# from getting collision events generated for them
if base.mouseWatcherNode.getMouseY() > -0.5:
if base.mouseWatcherNode.getMouseX() < 0.0:
#do collisions from first model camera
print 'orbitCamera1 click '+str(base.mouseWatcherNode.getMouseX())+','+str(base.mouseWatcherNode.getMouseY())
self.pickerRay.setFromLens(self.orbitCamera1.getCameraNode(), mpos.getX(), mpos.getY())
if self.queue_model1.getNumEntries() > 0:
print ' '+str(self.queue_model1.getNumEntries())+' collisions detected'
# This is so we get the closest object.
self.queue_model1.sortEntries()
print' collision handle: '+str(self.queue_model1.getEntry(0))
self.handleClicked(self.queue_model1.getEntry(0),self.orbitCamera1)
self.queue_model1.clearEntries()
else:
#do collisions from second model camera
print 'orbitCamera2 click '+str(base.mouseWatcherNode.getMouseX())+','+str(base.mouseWatcherNode.getMouseY())
self.pickerRay2.setFromLens(self.orbitCamera2.getCameraNode(), mpos.getX(), mpos.getY())
if self.queue_model2.getNumEntries() > 0:
print ' '+str(self.queue_model2.getNumEntries())+' collisions detected'
# This is so we get the closest object.
self.queue_model2.sortEntries()
print' collision handle: '+str(self.queue_model2.getEntry(0))
self.handleClicked(self.queue_model2.getEntry(0),self.orbitCamera2)
self.queue_model2.clearEntries()
else:
#do collisions from hud camera
print 'hudCamera click '+str(base.mouseWatcherNode.getMouseX())+','+str(base.mouseWatcherNode.getMouseY())
self.hudPickerRay.setFromLens(base.hudCam,mpos.getX(),mpos.getY())
if self.queue_hud.getNumEntries() > 0:
print ' '+str(self.queue_hud.getNumEntries())+' collisions detected'
# This is so we get the closest object.
self.queue_hud.sortEntries()
print' collision handle: '+str(self.queue_hud.getEntry(0))
self.handleClicked(self.queue_hud.getEntry(0),self.hudCamera)
self.queue_hud.clearEntries()
this is a class that holds the camera and all its data
from direct.showbase.ShowBase import ShowBase
from pandac.PandaModules import PandaNode
import sys
from panda3d.core import *
import constants
class OrbitCamera(PandaNode):
def __init__(self):
#ShowBase.__init__(self)
self.myCam = Camera('myCamera')
self.myCamera = render.attachNewNode(self.myCam)
#camera limit variables
self.heading_limit_upper = 90
self.heading_limit_lower = -90
self.pitch_limit_upper = 90
self.pitch_limit_lower = -90
self.zoom_speed = constants.orbit_cam_zoom_speed
self.heading = 0
self.pitch = 0
def setHeadingLimits(self, upper_limit, lower_limit):
self.heading_limit_upper = upper_limit
self.heading_limit_lower = lower_limit
def setPitchLimits(self, upper_limit, lower_limit):
self.pitch_limit_upper = upper_limit
self.pitch_limit_lower = lower_limit
def getLimits(self):
limits = [self.heading_limit_upper, self.heading_limit_lower, self.pitch_limit_upper, self.pitch_limit_lower]
return limits
def getCameraNodePath(self):
return self.myCamera
def getCameraNode(self):
return self.myCam
def zoom(self, direction):
self.myCamera.setY(self.myCamera.getY() + self.zoom_speed * direction * globalClock.getDt())
return direction
def setLens(self,lens):
self.myCam.setLens(lens)
return True
def setPos(self, px, py, pz):
self.myCamera.setPos(px,py,pz)
return True
def setPos(self, pos):
self.myCamera.setPos(pos)
def setY(self, py):
self.myCamera.setY(py)
return True
def setHeading(self,new_heading):
if new_heading > self.heading_limit_upper:
self.heading = self.heading_limit_upper
elif new_heading < self.heading_limit_lower:
self.heading = self.heading_limit_lower
else:
self.heading = new_heading
return self.heading
def getHeading(self):
return self.heading
def setPitch(self, new_pitch):
if new_pitch > self.pitch_limit_upper:
self.pitch = self.pitch_limit_upper
elif new_pitch < self.pitch_limit_lower:
self.pitch = self.pitch_limit_lower
else:
self.pitch = new_pitch
return self.pitch
def getPitch(self):
return self.pitch
def reparentTo(self, parent_path):
self.myCamera.reparentTo(parent_path)
def lookAt(self, target_path):
self.myCamera.lookAt(target_path)