Changing part of an EggData's mesh color/texture

I am trying to replicate the “highlight a square with the mouse” behavior of the “chessboard” exercise using a mesh of EggPolygons (generated by code) in a single EggData instead of using an individual node for each square. I think I understand how to do the collision part of it and calculate which square needs to be highlighted, but I’m not sure how or if it’s possible to dig into the EggData and change the color or texture of the correct poly.

I suspect it might not be possible to do it this way since it is all in a single node, but I wonder if it’s possible to maybe delete that poly out of this node/mesh and put it into a different node/mesh so it can have a different render state?

So, I guess my question boils down to: Is it possible to edit/delete/insert mesh data that is already in an EggData, or do you need to regenerate the whole thing when something changes (which seems like it might be prohibitively slow)?

If it is not possible, what might an alternative be besides having each square as it’s own node?

Thanks for reading my ramblings. :slight_smile:

It might be a lot easier to create or unhide a single poly geom at the highlight location that is slightly above the original. This way it could have its own color/texture and use effects like additive.

Ah, that is an interesting idea. I think I understand what you mean by “additive effect” but I’m not sure how to go about implementing it. Do any of the sample programs demonstrate that technique, or is there somewhere else I can see an example of it?

If you mean what will it look like visually, it will just add the colors of object with whatever is behind it, resulting in a brighter color. So you could have a solid color poly on top and you would still see the texture of the object underneath, but it would be brighter.
If you want to know how to apply the effect, check out this thread:
[url]Additive Alpha]

I am doing something wrong. This code results in a flat grey poly over the 8,8 square instead of a “highlight”. Where have I gone wrong?

from direct.showbase.ShowBase import ShowBase
from direct.task.Task import Task
from random import random,randint
from panda3d.core import *
from panda3d.egg import *

loadPrcFileData("editor-startup", "show-frame-rate-meter #t") 
loadPrcFileData("editor-startup", "sync-video #f") 

class GridData(object):
   def __init__(self, width, height):
      self.width = width
      self.height = height
      self.state = [False for x in range(width*height)]
      
class GridView(object):
   def __init__(self, gridData):
      self.gridData = gridData
      self.eggTex = EggTexture("tex", Filename("0.png"))
      self.eggTex2 = EggTexture("tex2", Filename("1.png"))      
      self.generate()
      
   def generate(self):
      gridData = self.gridData
      self.data = EggData() 
      vp = EggVertexPool("grid")
      self.data.addChild(vp)
      for z in range(gridData.height):
         for x in range(gridData.width):
            poly = EggPolygon("%d_%d" % (x,z))
            self.data.addChild(poly)
            v = EggVertex()
            v.setPos(Point3D(x, 0, z))
            v.setUv(Point2D(0,0))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x+1, 0, z))
            v.setUv(Point2D(1,0))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x+1, 0, z+1))
            v.setUv(Point2D(1,1))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x, 0, z+1))
            v.setUv(Point2D(0,1))
            poly.addVertex(vp.addVertex(v))
            indx = z*gridData.width+x
            if gridData.state[indx] == False:
               poly.setTexture(self.eggTex)
               
            else:
               poly.setTexture(self.eggTex2)
                        
      self.data.recomputePolygonNormals()

   def highlightSq(self, x, z):
      gridData = self.gridData
      hIndx = z*(gridData.width+1)+x
      self.highlightData = EggData()
      vp = EggVertexPool("highlight")
      self.highlightData.addChild(vp)
      poly = EggPolygon()
      self.highlightData.addChild(poly)
      v = EggVertex()
      v.setPos(Point3D(x, -.1, z))
      v.setUv(Point2D(0,0))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x+1, -.1, z))
      v.setUv(Point2D(1,0))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x+1, -.1, z+1))
      v.setUv(Point2D(1,1))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x, -.1, z+1))
      v.setUv(Point2D(0,1))
      poly.addVertex(vp.addVertex(v))
      poly.setColor(VBase4(.5,.5,.5,1))
      self.highlightData.recomputePolygonNormals()

   def getHighlightNodePath(self):
      node = loadEggData(self.highlightData)
      nodepath = NodePath(node)
      nodepath.setName("highlight")
      return nodepath
      
   def getNodePath(self):
      node = loadEggData(self.data)
      node.setIntoCollideMask(BitMask32.bit(1))
      nodepath = NodePath(node)
      nodepath.setName("grid_node")
      return nodepath
      
class MyApp(ShowBase):
   def __init__(self):
      ShowBase.__init__(self)
      self.disableMouse()
      self.gridData = GridData(10,10)
      self.gridView = GridView(self.gridData)
      node = self.gridView.getNodePath()
      node.reparentTo(self.render)
      self.gridView.highlightSq(8,8)
      node = self.gridView.getHighlightNodePath()
      node.reparentTo(self.render)      
      node.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
      self.setupLights()
      self.camera.setPos(5,-15,-4)
      self.camera.setHpr(0,30,0)
      
   def setupLights(self):
      plight = PointLight('plight')
      plight.setColor(VBase4(1, 1, 1, 1))
      plight.setAttenuation(Point3(0, 0, 0.2))
      plnp = self.render.attachNewNode(plight)
      plnp.setPos(5, -2, 5)
      self.render.setLight(plnp)
      alight = AmbientLight('alight')
      alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
      alnp = self.render.attachNewNode(alight)
      self.render.setLight(alnp)      


app = MyApp()
app.run()

Ah yes, you must ensure that the additive part is rendered after the rest of the scene, which you do with bins.
For example (do once):

bins = CullBinManager.getGlobalPtr()
bins.addBin('highlight', CullBinEnums.BTStateSorted, 25)

Do for each part of the scene you want additive:

node.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
node.setBin('highlight', 25)

The 25 is the priority. Most things in the scene will be in the default bin with a default priority of 20, so if you want it to render after you set a higher number.

Something’s still not right, I still see the grey poly. Here’s what the relevant section of MyApp.init() looks like:

      self.gridView.highlightSq(8,8)
      node = self.gridView.getHighlightNodePath()
      node.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
      bins = CullBinManager.getGlobalPtr() 
      bins.addBin('highlight', CullBinEnums.BTStateSorted, 25)
      node.setBin('highlight', 25)
      node.reparentTo(self.render)      

Hmm that is strange.
I’ve used your code as posted and changed the init function as follows:

   def __init__(self):
      ShowBase.__init__(self)
      self.disableMouse()
      self.gridData = GridData(10,10)
      self.gridView = GridView(self.gridData)
      node = self.gridView.getNodePath()
      node.reparentTo(self.render)
      self.gridView.highlightSq(8,8)
      node = self.gridView.getHighlightNodePath()
      node.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
      bins = CullBinManager.getGlobalPtr()
      bins.addBin('highlight', CullBinEnums.BTStateSorted, 25)
      node.setBin('highlight', 25)
      node.reparentTo(self.render)      
      self.setupLights()
      self.camera.setPos(5,-15,-4)
      self.camera.setHpr(0,30,0)
     

The result being a square which brightens the texture underneath.
If the above does not work for you, perhaps it is due to a difference in the version of Panda. Maybe try one of the nightly builds?

I tried the latest build (#378) and it still doesn’t work. :frowning: Are there any diagnostic messages I can print out to see where the problem might be?

Not that I know of.
I have no idea why it would work for me but not for you.

Does anyone else have any ideas? :slight_smile:

Does anyone know of any other scripts that use the technique? At least I can see if those work for me.

Frustrating.

Can you post your complete program again?

from direct.showbase.ShowBase import ShowBase
from direct.task.Task import Task
from random import random,randint
from panda3d.core import *
from panda3d.egg import *

loadPrcFileData("editor-startup", "show-frame-rate-meter #t") 
loadPrcFileData("editor-startup", "sync-video #f") 

class GridData(object):
   def __init__(self, width, height):
      self.width = width
      self.height = height
      self.state = [False for x in range(width*height)]
      
class GridView(object):
   def __init__(self, gridData):
      self.gridData = gridData
      self.eggTex = EggTexture("tex", Filename("0.png"))
      self.eggTex2 = EggTexture("tex2", Filename("1.png"))      
      self.generate()
      
   def generate(self):
      gridData = self.gridData
      self.data = EggData() 
      vp = EggVertexPool("grid")
      self.data.addChild(vp)
      for z in range(gridData.height):
         for x in range(gridData.width):
            poly = EggPolygon("%d_%d" % (x,z))
            self.data.addChild(poly)
            v = EggVertex()
            v.setPos(Point3D(x, 0, z))
            v.setUv(Point2D(0,0))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x+1, 0, z))
            v.setUv(Point2D(1,0))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x+1, 0, z+1))
            v.setUv(Point2D(1,1))
            poly.addVertex(vp.addVertex(v))
            v = EggVertex()
            v.setPos(Point3D(x, 0, z+1))
            v.setUv(Point2D(0,1))
            poly.addVertex(vp.addVertex(v))
            indx = z*gridData.width+x
            if gridData.state[indx] == False:
               poly.setTexture(self.eggTex)
               
            else:
               poly.setTexture(self.eggTex2)
                        
      self.data.recomputePolygonNormals()

   def highlightSq(self, x, z):
      gridData = self.gridData
      hIndx = z*(gridData.width+1)+x
      self.highlightData = EggData()
      vp = EggVertexPool("highlight")
      self.highlightData.addChild(vp)
      poly = EggPolygon()
      self.highlightData.addChild(poly)
      v = EggVertex()
      v.setPos(Point3D(x, -.1, z))
      v.setUv(Point2D(0,0))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x+1, -.1, z))
      v.setUv(Point2D(1,0))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x+1, -.1, z+1))
      v.setUv(Point2D(1,1))
      poly.addVertex(vp.addVertex(v))
      v = EggVertex()
      v.setPos(Point3D(x, -.1, z+1))
      v.setUv(Point2D(0,1))
      poly.addVertex(vp.addVertex(v))
      poly.setColor(VBase4(.5,.5,.5,1))
      self.highlightData.recomputePolygonNormals()

   def getHighlightNodePath(self):
      node = loadEggData(self.highlightData)
      nodepath = NodePath(node)
      nodepath.setName("highlight")
      return nodepath
      
   def getNodePath(self):
      node = loadEggData(self.data)
      node.setIntoCollideMask(BitMask32.bit(1))
      nodepath = NodePath(node)
      nodepath.setName("grid_node")
      return nodepath
      
class MyApp(ShowBase):
   def __init__(self):
      ShowBase.__init__(self) 
      self.disableMouse() 
      self.gridData = GridData(10,10) 
      self.gridView = GridView(self.gridData) 
      node = self.gridView.getNodePath() 
      node.reparentTo(self.render) 
      self.gridView.highlightSq(8,8) 
      node = self.gridView.getHighlightNodePath() 
      node.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd)) 
      bins = CullBinManager.getGlobalPtr() 
      bins.addBin('highlight', CullBinEnums.BTStateSorted, 25) 
      node.setBin('highlight', 25) 
      node.reparentTo(self.render)      
      self.setupLights() 
      self.camera.setPos(5,-15,-4) 
      self.camera.setHpr(0,30,0) 
      
   def setupLights(self):
      plight = PointLight('plight')
      plight.setColor(VBase4(1, 1, 1, 1))
      plight.setAttenuation(Point3(0, 0, 0.2))
      plnp = self.render.attachNewNode(plight)
      plnp.setPos(5, -2, 5)
      self.render.setLight(plnp)
      alight = AmbientLight('alight')
      alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
      alnp = self.render.attachNewNode(alight)
      self.render.setLight(alnp)      


app = MyApp()
app.run()

I figured something out. I changed this:

      bins = CullBinManager.getGlobalPtr() 
      bins.addBin('highlight', CullBinEnums.BTStateSorted, 25) 
      node.setBin('highlight', 25) 

to:

node.setBin('fixed', 10)

I still do not understand why my other code worked for teedee and did not work for me however. Can anyone explain that? Why didn’t adding a new bin work for me?