Procedural model based on Z of other mesh

Hello all,

This is my first post on the forums, and I’ve just recently started playing around with Panda3d, but I’ve been using Python for quite a while both at work and for leisure. Feel free to yell at me if I posted on the wrong board!

I’m having trouble coming up with an efficient way of finding the Z location of a mesh (or collision mesh) given an X,Y coordinate. A little background of what I’m trying to do (in case I’m going about this alllll wrong). I have a nodePath which I want to surround by a circle or torus of sorts. The thing is, I want the vertices of this circle/torus to be a constant z offset from an uneven ground plane that the nodePath sits upon. This made me think I needed to produce this object procedurally (I’m unaware of a way to manipulate vertices of a preloaded node, but this could also be a possibility).

The generation code for the circle/torus is elementary, it’s obtaining a z offset at every vertex of the circle/torus that’s getting me. My first thought was to create a temporary dummy node with a CollisionHandlerQueue to grab the z location at every vertex:

def setupGroundCollision(node):
     groundRay = PandaModules.CollisionRay()
     groundRay.setOrigin(0,0,1000)
     groundRay.setDirection(0,0,-1)
     groundCol = PandaModules.CollisionNode('groundRay')
     groundCol.addSolid(groundRay)
     groundCol.setFromCollideMask(PandaModules.BitMask32.bit(0))
     groundCol.setIntoCollideMask(PandaModules.BitMask32.allOff())
     groundColNp = node.attachNewNode(groundCol)
     groundHandler = PandaModules.CollisionHandlerQueue()
     base.cTrav.addCollider(groundColNp, groundHandler)
     return groundHandler

class SomeClass:
   def __init__():
      return 0

   def addMovementCircle(self):
      numPoints = 8
      format=GeomVertexFormat.getV3n3cpt2()
      vdata=GeomVertexData('square', format, Geom.UHDynamic)

      vertex=GeomVertexWriter(vdata, 'vertex')
      normal=GeomVertexWriter(vdata, 'normal')
      color=GeomVertexWriter(vdata, 'color')
      texcoord=GeomVertexWriter(vdata, 'texcoord')
      
      zGetter=render.attachNewNode("dummyNode")
      zHandler = setupGroundCollision(zGetter)
      for i in range(numPoints):
         angle = (i*(math.pi*2/numPoints))
         x = self.stats['movement']*math.cos(angle)+self.pandaNode.getX()
         y = self.stats['movement']*math.sin(angle)+self.pandaNode.getY()
         zGetter.setPos(x,y,1000)
         base.cTrav.traverse(render)
         if (zHandler.getNumEntries() > 0):
            z = zHandler.getEntry(0).getSurfacePoint(render).getZ() + 1.5
         else:
            z = 1.5
         vertex.addData3f(x,y,z)
         normal.addData3f(Vec3(2*x-1, 2*y-1, 2*z-1).normalize())
         color.addData4f(0.0,0.0,1.0,1.0)
         z += -.1
         vertex.addData3f(x,y,z)
         normal.addData3f(Vec3(2*x-1, 2*y-1, 2*z-1).normalize())
         color.addData4f(0.0,0.0,1.0,1.0)
         angle = (i*(math.pi*2/numPoints))
         x = (self.stats['movement']+.1)*math.cos(angle)+self.pandaNode.getX()
         y = (self.stats['movement']+.1)*math.sin(angle)+self.pandaNode.getY()
         z += 0
         vertex.addData3f(x,y,z)
         normal.addData3f(Vec3(2*x-1, 2*y-1, 2*z-1).normalize())
         color.addData4f(1.0,1.0,1.0,1.0)
         z += .1
         vertex.addData3f(x,y,z)
         normal.addData3f(Vec3(2*x-1, 2*y-1, 2*z-1).normalize())
         color.addData4f(1.0,1.0,1.0,1.0)
      zGetter.removeNode()
       
      circle = Geom(vdata)
      for i in range(numPoints):
         for j in range(4):
            tri=GeomTriangles(Geom.UHDynamic)
            tri.addVertex(((i+0)%numPoints)*4+(j  )%4)
            tri.addVertex(((i+0)%numPoints)*4+(j+1)%4)
            tri.addVertex(((i+1)%numPoints)*4+(j  )%4)
            circle.addPrimitive(tri)
            tri.addVertex(((i+1)%numPoints)*4+(j+1)%4)
            tri.addVertex(((i+0)%numPoints)*4+(j+1)%4)
            tri.addVertex(((i+1)%numPoints)*4+(j  )%4)
            circle.addPrimitive(tri)
      snode=GeomNode('circle')
      snode.addGeom(circle)
      self.movementCircle=render.attachNewNode(snode)
      self.movementCircle.setTwoSided(True)
      return 0

(Warning: I took most of the class out, I probably missed a dependency, so don’t bother trying to run the code, if anyone wants I’ll post a runnable version.)

Even it it’s slow, I won’t be calling the method too often, but it would be nice to be able to up the amount of points in the circle/torus without having a huge fps spike. Another option would be to try and thread this process. Is it a good idea to thread code that procedurally generates a mesh?

Thanks in advance for helping the noobie! Oh, and it’s very nice to meet you all!