What options are there for speeding up visible geometry collisions (without using simplified Collision Geometry such as spheres, planes, etc…)?
I have spent quite some time looking at 2 options which unfortunately didn’t end up working out.
My first idea was to use trianglemesh from bullet. Unfortunately, I want to detect the interior of the mesh and the testAllRays query only returns the first surface of collision with the test ray. This doesn’t help me much because I must know all surfaces of a trianglemesh that the ray passes through.
My second idea was to implement this helper function:
[url]GeomNode vs CollisionPolygon]
Here is my code for converting a geometry into a set of collision polygons (below). Note that for the simple case of the prebuilt “smiley” model everything runs fine. But when I try to load my sketchup cylinder.egg file (I converted it using dae2egg) the converted collision solid isn’t at all like the visible geometry (missing triangles). So, is this an issue with dae2egg?
note: see my comments for where I specify what “works” and what doesn’t
code:
from direct.showbase.ShowBase import ShowBase
from panda3d.core import CollisionTraverser
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import CollisionNode
from panda3d.core import CollisionPolygon
from panda3d.core import NodePath
from panda3d.core import GeomVertexReader
from panda3d.core import BitMask32
from panda3d.core import PointLight
from panda3d.core import Point3
def geoms_to_collisions(incomingNode):
parent = NodePath('cGeomConversionParent')
for c in incomingNode.findAllMatches('**/+GeomNode'):
geomNode = c.node()
for i in range(geomNode.getNumGeoms()):
geom = geomNode.getGeom(i)
vdata = geom.getVertexData()
cChild = CollisionNode(c.getName())
for i in range(geom.getNumPrimitives()):
prim = geom.getPrimitive(i)
vertex = GeomVertexReader(vdata, 'vertex')
prim = prim.decompose()
for p in range(prim.getNumPrimitives()):
s = prim.getPrimitiveStart(p)
e = prim.getPrimitiveEnd(p)
v = []
for i in range(s, e):
vi = prim.getVertex(i)
vertex.setRow(vi)
v.append(vertex.getData3f())
colPoly = CollisionPolygon(*v)
cChild.addSolid(colPoly)
parent.attachNewNode (cChild)
return parent
ShowBase()
base.cTrav = CollisionTraverser()
#this works:
model = loader.loadModel('smiley')
#this doesn't
#model = loader.loadModel('cylinder.egg')
#model.reparentTo(render)
model.setPos(0, 25, 0)
#model.setCollideMask(BitMask32.bit(0))
model_NP = geoms_to_collisions(model)
model_NP.set_pos(0,25,0)
model_NP.reparentTo(render)
interior_test_ray = render.attachNewNode("interior_root")
inside_ray = CollisionRay() # Create the ray
inside_ray.setOrigin(0,0,0) # Set its origin
inside_ray.setDirection(1,0,0) # And its direction
rayCol = CollisionNode('insideRay') # Create and name the node
rayCol.addSolid(inside_ray) # Add the ray
rayCol.setFromCollideMask(BitMask32.bit(0)) # Set its bitmasks
rayCol.setIntoCollideMask(BitMask32.all_off())
insideColNp = interior_test_ray.attachNewNode(rayCol)
cRayHandler = CollisionHandlerQueue()
base.cTrav.addCollider(insideColNp, cRayHandler)
base.cTrav.showCollisions(render)
insideColNp.show()
insideColNp.posInterval(5, Point3(5, 25, -2), startPos=Point3(-10, 25, 1), fluid=1).loop()
redPointLight = render.attachNewNode( PointLight( "PointLight" ) )
render.setLight( redPointLight )
run()
not_working_model.zip (5.04 KB)