I want to leverage Panda3D’s collision system to trace an obj model with collision rays and generate sort of a “point cloud”.
Speed and run-time optimizations are not relevant because I’m not building a “game” - just this single purpose
I currently have a collision system set up using the built in engine in Panda, and it works with CollisionBoxes
. I looked online for a mesh collider solution, someone said it’s possible to: make any visible mesh be an “into” collision solid by setting the appropriate collide mask on it
.
I tried the following:
Collision ray code
def cast_ray(self, a, b):
ray = CollisionRay()
ray.setOrigin(a)
ray.setDirection(b-a)
rayNode = CollisionNode("ray")
rayNode.addSolid(ray)
rayNodePath = self.scene.render.attachNewNode(rayNode)
rayNodePath.node().setIntoCollideMask(BitMask32.allOff())
rayNodePath.node().setFromCollideMask(BitMask32.bit(0))
rayQueue = CollisionHandlerQueue()
self.scene.cTrav.addCollider(rayNodePath, rayQueue)
self.scene.cTrav.traverse(self.scene.render)
Obj code
def add_rock(self, position):
box_n = self.scene.loader.loadModel("./obj/stone_1.obj")
box_n.setScale(1, 1, 1)
box_n.setPos(position + Point3(0, 0, .5))
box_n.flattenLight()
box_n.setTextureOff()
box_n.node().setIntoCollideMask(BitMask32.bit(0))
box_n.reparentTo(self.scene.render)
So I tried to set box_n.node().setIntoCollideMask(BitMask32.bit(0))
but it doesn’t work
What else am I missing?
You can see an example of this here, I believe:
https://docs.panda3d.org/1.10/python/programming/collision-detection/clicking-on-3d-objects
One thing that I note is that it’s not clear that the node on which you’re setting the bitmask is actually the model’s collision-node. It might be worth searching the loaded model for CollisionNodes, and then operating specifically on those. (See this manual page for more.)
@Thaumaturge
Still feel like I’m missing something…
Following the object clicking tutorial, I added a tag to the object, but it still wasn’t picked up.
As for the second reference, ls()
prints out the following
ModelRoot stone_1.obj S:(TextureAttrib)
PandaNode stone_1.obj
GeomNode stone1 (1 geoms: S:(MaterialAttrib))
I also tried to add a collision node with setIntoCollide, and now ls()
prints out
ModelRoot stone_1.obj S:(TextureAttrib)
PandaNode stone_1.obj
GeomNode stone1 (1 geoms: S:(MaterialAttrib))
CollisionNode box (0 solids) [test_tag] (hidden)
CollisionNode displays 0 solids… maybe that’s the issue? How can I add a “mesh collider”?
Hmm… It is odd that there are zero solids! It suggests that there might be a problem with the model itself.
[edit] Ah, I didn’t notice that you said that you added the collision node yourself. Indeed, a collision node with no solids won’t do much, I daresay. [/edit]
That said, if you just want to collide with visible geometry, then you needn’t have a collision node. Instead, you can set the ray to collide with the “visible geometry” bitmask–see the third line of the first piece of code in that “clicking on 3D objects” page.
2 Likes
It worked!!! Thank you
For future reference, adjustments to the code above:
For the ray
rayNodePath.node().setFromCollideMask(GeomNode.getDefaultCollideMask())
And for the obj
def add_rock(self, position):
box_n = self.scene.loader.loadModel("./obj/stone_1.obj")
box_n.setScale(1, 1, 1)
box_n.setPos(position + Point3(0, 0, .5))
box_n.node().setIntoCollideMask(GeomNode.getDefaultCollideMask())
box_n.reparentTo(self.scene.render)
2 Likes