Unable to properly update a GeomNode

Hi! I’m new to the panda3d engine and I’m trying to make an app for 3d point cloud markup. I have multiple scenes with 200k points each so I decided to put them into a GeomNode for optimisation. Entity segmentation task is done, but now i need to name the entities, for example in scene 1 entity 1 is plate, 2 is cup, 3 is apple, etc. I made an OptionMenu with every entity in the scene. And when i press the button “Highlight” the selected entity changes it’s color to white, however the second time i choose the entity number, the picture doesn’t change and previous entity is still highlighted and the new entity doesn’t turn white. As far as i see, I’m able to get entity number correctly and change the color of it’s points to white, however I’m unable to correctly render or update the new cloud. Can anybody please help? Is there a proper way to do this? The code is down below

The code(I think the mistake is somewhere in the highlight_object method):

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import *
import numpy as np
import os

class PointCloudApp(ShowBase):
    def __init__(self):
        super().__init__()

        self.camera.setPos(2, 2, 2)
        self.camera.lookAt(-1, -1, -1)
        self.MouseSensitivity = 1
        self.n_objects = []

        path_to_dataset = 'known_diff_3_cameras'
        self.files_list = [os.path.join(path_to_dataset, f) for f in os.listdir(path_to_dataset) if
                      os.path.isfile(os.path.join(path_to_dataset, f))]

        file = self.files_list[1]
        np_pcd = np.load(file)
        new_column = np.zeros((np_pcd.shape[0], 1))
        np_pcd = np.hstack((np_pcd, new_column))
        print(file)
        print(np_pcd.shape)
        self.np_pcd = np_pcd
        self.n_objects = set(np_pcd[:, 9])
        self.points = np_pcd[:, :3]
        self.colors = np_pcd[:, 3:6] / 255.0
        self.object_ids = np_pcd[:, 9]

        self.create_gui()

        self.point_classes = {}

    def update_point_color(self, point_idx, color):
        
        color_writer = GeomVertexWriter(self.vdata, "color")
        color_writer.setRow(point_idx)
        color_writer.setData4f(*color)

    def create_gui(self):
      
        self.load_button = DirectButton(
            text="Load Points",
            scale=0.07,
            pos=(-1.12, 0, 0.9),
            command=self.load_points
        )

        self.class_entry = DirectEntry(
            text="",
            scale=0.07,
            pos=(-1.3, 0, 0.78),
            initialText="Class",
            numLines=1
        )
        self.selected_object = 0

        self.object_menu = DirectOptionMenu(
            text="Choose Object",
            scale=0.09,
            items=[str(i) for i in self.n_objects],
            initialitem=0,
            command=self.on_object_select,
            pos=(-1.31, 0, 0.65)
        )

        self.highlight_button = DirectButton(
            text="Highlight",
            scale=0.07,
            command=self.highlight_object,
            pos=(-1.16, 0, 0.55)
        )

    def on_object_select(self, obj_id):
        
        self.selected_object = int(float(obj_id))
        print(f"Selected Object: {self.selected_object}")

    def highlight_object(self):
       
        print(f"Highlighting Object: {self.selected_object}")

        color_writer = GeomVertexWriter(self.vdata, "color")
        for i, obj_id in enumerate(self.object_ids):
            color_writer.setRow(i)
            if obj_id == self.selected_object:
                print(i)
                color_writer.setData4f(1.0, 1.0, 1.0, 0.5) 
            else:
                color_writer.setData4f(*self.colors[i], 1.0) 

        geom = self.cloud_node.node().modifyGeom(0)
        geom.modifyVertexData()
        geom.markBoundsStale()



    def load_points(self):

        points = self.np_pcd
        format = GeomVertexFormat.getV3c4()
        self.vdata = GeomVertexData("points", format, Geom.UH_static)

        vertex_writer = GeomVertexWriter(self.vdata, "vertex")
        color_writer = GeomVertexWriter(self.vdata, "color")

        for point in points:
            vertex_writer.addData3f(*point[:3])
            color_writer.addData4f(*point[3:6]/255, 1)

        prim = GeomPoints(Geom.UH_static)
        prim.addNextVertices(len(points))
        prim.closePrimitive()

        geom = Geom(self.vdata)
        geom.addPrimitive(prim)
        geom_node = GeomNode("point_cloud")
        geom_node.addGeom(geom)


        self.cloud_node = self.render.attachNewNode(geom_node)
        self.cloud_node.setRenderModeThickness(3)

        self.cloud_node.setTag("point_cloud", "10")

        print(f"Loaded {len(points)} points.")
        center = np.mean(points, axis=0)
        extent = np.ptp(points, axis=0) 


if __name__ == "__main__":
    app = PointCloudApp()
    app.run()

Issue solved;
in the bottom of this page it says, that GeomVertexWriter may automatically (and transparently) force a copy of the data in the GeomVertexData. This seems to be the thing causing the problem.
Instead of creting 2 separate GeomVertexWriters for colors in load_points and highlight_object methods, i just created color_writer as attribute of the class in the load_points method and then used it as self.color_writer.setData4f() in highlight_object method.

If I understand you correctly, then I’ve been told that keeping a GeomVertexWriter across multiple frames is not the intended approach, nor safe.

(See this post for more.)

I’m not hugely familiar with the use of the GeomVertex -Writer/-Reader system in Panda, but looking at your code, I’m wondering whether the problem doesn’t instead lie with your calls to “modifyGeom” and “modifyVertexData” at the end of the “highlight_object” method.

Specifically, I don’t think that either is called for when using a GeomVertexWriter.

Further, looking at the API, I see that “modifyVertexData” is actually meant to return a reference to the geometry for the purposes of modifying it. I wonder whether it wasn’t invalidating your use of the GeomVertexWriter before it…

[edit]
Also, welcome to the forum! I hope that you find your time here to be positive! :slight_smile:

Also also: a quick ping to your user-name, @eakuz, to alert you of my response (hopefully), in case you hadn’t planned on reviewing the thread, given that it was marked as “solved”.