Getting the mouse worldspace position under the mouse?

I am finding documentation on this website and boards woefully inadequate. I keep trying to find a solution to the problem of getting a world space position under the mouse so that I can drop an object there (in world space) but I’ve found solutions that don’t work. Most are from 2009. For example in some solutions there are objects and methods used or referenced that are never declared let alone defined so finding the appropriate tools to even get it working is a nightmare. In other areas it is suggested to use callbacks for inputs because polling is less reliable, I’ve found this to be not the case and in fact when I use a callback it doesn’t work. I am very frustrated right now, and another thing that makes me a little irked (I do software engineering as a hobby) is the taxonomy of this engine. Example: ShowBase?? What in the world does that even mean? mouseWatcherNode ?? Again why the ridiculous and non-descriptive naming scheme? I get it sort of describes what it does but why couldn’t you have found a better more concise name and separated the keyboard concerns from it??

Is there some relatively simple way of doing this mouse to world space thing? It must intersect with the geometry from the user camera perspective.

I’m sorry to read that you’ve been so frustrated. :/

So, if I understand you correctly, you want to find a position under the mouse-cursor that corresponds to the nearest geometry surface–is that correct?

If so, then a ray-cast would seem to be the simplest solution. The manual describes a means of doing so on this page, I believe.

There is one caveat: the method described on that page has the ray colliding with visible geometry, which isn’t as efficient as colliding with dedicated collision geometry. Thus I’d suggest that, if feasible, you modify the code to instead intersect with collision geometry that you then provide. Of course, if that’s not feasible–if colliding with visible geometry is one of your requirements, for example–then the code given on that page should be fine, I think!

I mean, I don’t think that the standard solutions have changed since then.

Come to that, I’m curious if I may: what solutions have you tried that didn’t work?

I can’t speak for the original designers, but I imagine that it’s the “base object of the ‘show’”–the terminology of the last word perhaps having come about due to the engine’s origins in creating things for Disney, if I recall correctly.

I think that this is pretty much what it says: it’s a node in the scene-graph that “watches”–i.e. provides information on–the mouse.

Otherwise… naming isn’t always designed from the ground up–perhaps especially in a project as large as an engine like this.

Sometimes names arise from specific associations that are later left behind (as I speculated for ShowBase); sometimes they were clear to the original designers, if not to later users; sometimes they come from roles that once they fulfilled, but no longer serve. And likely other sources besides.

And I suppose that these names could be changed… but that incurs the risk of breaking extant code, and of confusing users who are used to the old names. Furthermore, it may incur significant work, for very little benefit.

It’s done like this, it’s a dirty solution. How to do this correctly, said @Thaumaturge

from direct.showbase.ShowBase import ShowBase
from panda3d.core import *

base = ShowBase()

CurPicker = CollisionTraverser()
CurPicker.showCollisions(render)
CurPickerOr = CollisionHandlerQueue()
CurPickerNod = CollisionNode('mouseRay')
CurPickerCam = camera.attachNewNode(CurPickerNod)
CurPickerNod.setFromCollideMask(BitMask32.bit(1))
CurPickerNod.setIntoCollideMask(BitMask32.allOff())
CurPickerRay = CollisionRay()
CurPickerNod.addSolid(CurPickerRay)
CurPicker.addCollider(CurPickerCam, CurPickerOr)

Object = loader.loadModel("panda")
Object.reparentTo(render)
Object.setPos(0, 50, 0)
Object.setCollideMask(BitMask32.bit(1))

def Pick():
   if base.mouseWatcherNode.hasMouse():
       mpos = base.mouseWatcherNode.getMouse()
       CurPickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
       CurPicker.traverse(render)
       CurPickerOr.sortEntries()
       if (CurPickerOr.getNumEntries() > 0):
           info = CurPickerOr.getEntry(0)
           print (info.getSurfacePoint(render))
  
base.accept('mouse1',Pick)

base.run()

The most interesting thing is that this code worked without an exit error before.

1 Like

Trying your code on my end (using Panda 1.10.7), I’m not getting an error on exiting–everything seems to work as expected. What error are you getting on your end?

Traceback (most recent call last):
  File "main.py", line 34, in <module>
    base.run()
  File "D:\Panda3D-1.10.7-x64\direct\showbase\ShowBase.py", line 3319, in run
    self.taskMgr.run()
  File "D:\Panda3D-1.10.7-x64\direct\task\Task.py", line 541, in run
    self.step()
  File "D:\Panda3D-1.10.7-x64\direct\task\Task.py", line 495, in step
    self.mgr.poll()
  File "D:\Panda3D-1.10.7-x64\direct\showbase\EventManager.py", line 49, in eventLoopTask
    self.doEvents()
  File "D:\Panda3D-1.10.7-x64\direct\showbase\EventManager.py", line 43, in doEvents
    processFunc(dequeueFunc())
  File "D:\Panda3D-1.10.7-x64\direct\showbase\EventManager.py", line 99, in processEvent
    messenger.send(eventName, paramList)
  File "D:\Panda3D-1.10.7-x64\direct\showbase\Messenger.py", line 337, in send
    self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
  File "D:\Panda3D-1.10.7-x64\direct\showbase\Messenger.py", line 422, in __dispatch
    result = method (*(extraArgs + sentArgs))
  File "D:\Panda3D-1.10.7-x64\direct\showbase\ShowBase.py", line 2975, in windowEvent
    self.userExit()
  File "D:\Panda3D-1.10.7-x64\direct\showbase\ShowBase.py", line 3094, in userExit
    self.finalizeExit()
  File "D:\Panda3D-1.10.7-x64\direct\showbase\ShowBase.py", line 3101, in finalizeExit
    sys.exit()
SystemExit
>>>

This happens when the window is closed.

Weird–I wonder why you get it and I don’t? Especially as–if I’m reading this correctly–the “error” is “SystemExit”, which, yes, is what you’re trying to do!

It looks like this reaction is spreading to the entire Panda. I did something wrong, the last thing I did was delete all the system path variables. Hmm as it is connected…

1 Like

Never mind, I was running Python interactively without creating a thread for it.

1 Like

Aah, fair enough! I’m glad that you found the problem! (And that it was something fairly straightforward!) :slight_smile:

I hope I wasn’t too rude earlier. I’ve been having a bit of a fit in the morning lately… the heater in my room at uni keeps waking me up and then I can’t fall back asleep… leads to a lot of anxiety (and anger) later on after attempting to stay awake with coffee…

I dunno about the raycast code I looked at because I had trouble finding what class datatype it was using… I did get something other than a zero vec3, but it was some obscenely large or small value (I’m talking scientific notation in the printout type of scale) that did not help.

I actually had no idea that Panda3d was made for Disney. Good to know. I’ll try figuring this out further…

Um heads up this just occurred and IDK what I did to cause it. I don’t recall changing anything between my last boot up and this occurring.

Speaking for myself, don’t worry about it–I think that most of us have times that find us irritable. :slight_smile:

And indeed, the circumstances that you describe do seem like they could incur some irritatability, indeed!

Perhaps it would help to see the your code–then perhaps we can see where you’re going wrong!

In general, however, and when using Panda’s internal collision system (as opposed to a third-party system like Bullet), a ray-cast produces a CollisionEntry object. (See here for more detail.) This object contains a number of pieces of data, including a hit-position, hit-normal, the NodePath that was hit, and more.

That said, perhaps a practical example might help. Aside from the one in the manual, and the one provided by serega above, my “Beginner’s Tutorial” covers basic ray-casting. Perhaps the description given there will help you to figure out what particular is causing you trouble.

The specific lesson that starts teaching the matter is this one, I believe–but it does refer to and build upon elements from previous lessons, so you may want to start earlier in the tutorial, perhaps even from the beginning.

That is odd! Again, it might help to see your code–but otherwise, are you seeing any error output along with this behaviour, perhaps?

1 Like

I’m not sure. I’ve been looking at my VCS to find what change I could have made that caused this but nothing helps.

I do not want to give up my code. Other demos of using panda3d and kivy work just fine…

Something I’ve discovered: I checked out an earlier (working) commit and I still get this problem.

I mean, you don’t have to show the whole thing. (Indeed, I’d rather you didn’t: that could be a lot of code to comb through!) Instead, it might help to see relevant excerpts, which is likely safe enough unless you’re doing something quite cutting-edge.

That said, if your earlier commit is showing the problem, then it may not be in your code, as such, but perhaps in your environment.

Hmm… You say that the panda demos work, but your own code doesn’t. Are you running them in different manners at all–say via your IDE when running your code and via a terminal when running the demos?

And what happens if you run a very simple “hello world”-style program in place of your own code–something like the following:

from direct.showbase.ShowBase import ShowBase

from direct.gui.OnscreenText import OnscreenText

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.text = OnscreenText("KITTENS!", scale = 0.5)

app = Game()
app.run()

Nah. I literally copied & pasted your code and same thing…

On a related note… where are the config.prc and log file folders located under ubuntu linux with p3d? I haven’t found them documented anywhere nor do I know what to look for to find them.

WEIRD. I just reinstalled panda3d to my local conda environment and it seems to work again… Or at least I’m getting errors instead of a blank screen. I’m gonna keep investi-muh-gating.

Very strange! I’m glad that you’ve made progress, at least!

Just to check: What happens if you run a Panda program–such as the “hello world” program that I gave above–from the terminal? Something like this:

python3 testProgram.py

I think that the location depends on whether you installed Panda via pip/pip3 or via a deb-installer.

On my installation, the PRC-file seems to be located on the following path:

/usr/local/lib/python3.6/dist-packages/panda3d/etc

I’m not sure about the log-file–I haven’t looked for one for ages, and have had enough installations of Panda3D that I wouldn’t likely be confident that any log that I found by searching would be from the current one. ^^;

I recall seeing mention of its location somewhere, but I forget where, alas…

(I’ve generally found that, when using the SDK and thus being in debug-mode, relevant messages tend to be printed to the terminal or IDE output-window, so a log-file hasn’t been important to me.)

I did run your hello world program. That’s the one I copied and pasted. Same problem before. I seem to be able to get things done now though. Apart from VCS issues…

I took the presence of the IDE in the background of your screenshot to indicate that you ran it through the IDE, and not through a terminal. If that’s not the case, then fair enough!

But yeah, if you have things working, then nevermind either way!