Super-fast mouse ray collisions with ground plane

Super-fast mouse ray collisions with ground plane

I was shocked to learn that many users do not know about the existence of many useful mathematical classes and functions that Panda provides. Thus, many users use Panda's collision system if they want to detect where a mouse ray hit a ground plane (for point-n-click movement in a 2d world) etc etc.
Thus, I quickly threw this snippet together that shows how to use the Plane class to calculate the intersection point with a mouse line. Super-fast. (Note that there are many more uses to this.)
Code: Select all
`from direct.showbase.ShowBase import Plane, ShowBase, Vec3, Point3, CardMakerclass YourClass(ShowBase):  def __init__(self):    ShowBase.__init__(self)    self.disableMouse()    self.camera.setPos(0, 60, 25)    self.camera.lookAt(0, 0, 0)    z = 0    self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, z))    self.model = loader.loadModel("jack")    self.model.reparentTo(render)    cm = CardMaker("blah")    cm.setFrame(-100, 100, -100, 100)    render.attachNewNode(cm.generate()).lookAt(0, 0, -1)    taskMgr.add(self.__getMousePos, "_YourClass__getMousePos")    def __getMousePos(self, task):    if base.mouseWatcherNode.hasMouse():      mpos = base.mouseWatcherNode.getMouse()      pos3d = Point3()      nearPoint = Point3()      farPoint = Point3()      base.camLens.extrude(mpos, nearPoint, farPoint)      if self.plane.intersectsLine(pos3d,          render.getRelativePoint(camera, nearPoint),          render.getRelativePoint(camera, farPoint)):        print "Mouse ray intersects ground plane at ", pos3d        self.model.setPos(render, pos3d)    return task.againYourClass();base.taskMgr.run()`
I prefer e-mail over PM
rdb

Posts: 8545
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Ooh, that looks good, pro-rsoft - thank you for it. ^_^
MWAHAHAHAHA!!!

*ahem*

Sorry.

Thaumaturge

Posts: 682
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

that's very good :)
babache

Posts: 1
Joined: Mon Jan 19, 2009 11:47 am

I have just found that in certain circumstances the intersection point may be not in front of the camera but behind it: imagine the plane is represented by ground, and your character with camera in eyes looks towards the horizon. If the mouse is above the horizon line then the intersection of the point and plane is behind the camera. Therefore, sometimes you will need the additional test, for example:
Code: Select all
`p = base.cam.getRelativePoint(render, pos3d)if not base.cam.node().isInView(p)    pos3d = False`
Thanks to pro-rsoft for his shadow mapping feature for the shader generator!

birukoff

Posts: 424
Joined: Thu Nov 08, 2007 7:03 am
Location: Russia, Moscow

You could first check to make sure that the mouse ray is not pointing in the same general direction of the plane's normal (using the dot product) to avoid the problem of the intersection point being behind the camera.

Derek

Posts: 19
Joined: Tue Mar 18, 2008 3:22 pm

Just wanted to note how easy it was to get this method to work. It's almost been a year now since the last post, has there been any improvements or "better" way to achieve the same thing?

Posts: 4
Joined: Wed Feb 25, 2009 3:52 am

Why are the following lines used in the code?
cm = CardMaker("blah")
cm.setFrame(-100, 100, -100, 100)
render.attachNewNode(cm.generate()).lookAt(0, 0, -1)
aashu

Posts: 15
Joined: Wed Jun 27, 2012 10:26 am

Oh, that just creates a big quad to visualise the ground plane.
rdb

Posts: 8545
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

@rdb thanks
aashu

Posts: 15
Joined: Wed Jun 27, 2012 10:26 am