Best way to 'hide' points in a GeomPoints primitive?

I am working on a point-cloud editor using panda3d. I have implemented my point-clouds with the GeomPoints primitive, and I need to ‘hide’ points based on user input. The points need to be visually hidden, as well as hidden from my shader-based selection method.

What’s the best way to hide these points? I’ve thought of several approaches so far:

  • Edit the raw geometry of the GeomPoints primitive (literally remove from the primitive and save the ‘hidden’ points, and re-add them when they are ‘shown’)

  • Shader-based method: Add an extra component to the custom GeomVertexFormat representing the GeomPoints vertex data that stores whether or not the point is visible. Write a custom vertex shader that skips over hidden points and somehow inject this shader in the normal render pipeline (is that even possible? I am pretty new to shader programming).

  • Use some built-in panda3d functionality that i’m not currently aware of.

Any ideas?

Hi!

You could indeed remove the vertex index from the GeomPoints primitive, e.g. using a memoryview:

points_prim = point_cloud.node().modify_geom(0).modify_primitive(0)
# the default index type is Geom.NT_uint16; Geom.NT_uint32 is only used
# when the model contains more than 65536 vertices (or when set explicitly)
int_format = "I" if points_prim.index_type == Geom.NT_uint32 else "H"
prim_array = points_prim.get_vertices()
prim_view = memoryview(prim_array).cast("B").cast(int_format)
prim_view[vertex_index:-1] = prim_view[vertex_index+1:]
prim_array.set_num_rows(prim_array.get_num_rows() - 1)

Instead of removing the vertex index, you could also overwrite it with the index of one of the remaining (“shown”) vertices:

prim_view[vertex_index] = other_vertex_index

This would be slightly faster, as it doesn’t require changing the size of the primitive. This might also be more convenient in that no indices are offset then.

As for the shader-based method, that should be possible in several ways. Although I’m far from a shader expert myself, it seems possible to accomplish this in either the vertex shader, the geometry shader or the fragment shader.

  • In the vertex shader, the “hidden” vertex could be positioned directly behind the camera, so it doesn’t get rendered. If I’m not much mistaken, p3d_ViewMatrixInverse[2].xyz gives the inverted camera direction vector, while p3d_ViewMatrixInverse[3].xyz is the camera origin. Adding these together should therefore result in a gl_Position that you can assign to the vertex to remove it from sight.

  • In the geometry shader, you would only call EmitVertex() and EndPrimitive() for “shown” vertices.

  • In the fragment shader, you would use discard for “hidden” vertices.

Since you already have a shader, it might be fairly easy to integrate either of the above methods into it. It is likely possible to combine shaders as well, but I have no experience with that.

Please note that none of the above has been tested, but I hope to have given you some useful hints nonetheless.
If you want, I could try to write and test some more complete shader code when I find the time.

1 Like

Thanks for the detailed tips on the shader methods! This feature got put on the back-burner but I’ll definitely reference your answer here when it comes time to implement.

Thanks!

1 Like