I’m a developer making his first foray into 3D graphics.
I’m working on a project where I need to display a starmap of real stars, potentially showing up to around 30k points at once (zoomed all the way out).
I’ve built a small Panda3D app that places the stars well and lets me zoom and rotate very nicely. However, in a test run of 10,000 stars, it gets very slow when zoomed out (on decent hardware, rendering with OpenGL).
I have a single “Stars” node which has associated with it a Geom for each star, rendered as points.
Is there a more efficient (or better) approach?
Is it normal to see heavy processor usage even when not rotating or zooming the camera (hence, no movement)?
So, a little experimenting yielded results, so I’ll share:
I was creating a new Geom for each star and attaching it to a node. Calling flattenStrong() on the parent node caused a performance gain at the cost of increased initial time spent loading the map. This made me think there must be efficiency to be gained in how its built.
So, I tried creating a single Geom points table, adding a vertex for each star. Rendering the many vertexes on the single Geom in a single node is much more efficient, and shows no performance loss when zoomed out at all! Additionally, CPU usage is down to expected levels.
the results you got are exactly what one would expect.
grafic cards are incredibly good at rendering stuff. they literally handle millions of triangles without a sweat.
however, due to the electronic design of the hardware, they totaly fail at high number of individual geoms.
keeping the number of individual nodes down is adviced. at around 200 nodes (on screen) most cards start to noticably slow down.
however, you should keep enough nodes to allow efficient frustum-culling so panda can drop most of what’s outside the view. so usualy you need to find a good balance for best results.
there also is a nice chapter about performance on the manual (you may have read it already since you used flatten )
So with my current approach, I basically have 1 node that holds 1 Geom, and the Geom has 30,000 vertexes. Does this arrangement pose problems for the frustum culling, since there is a single node?
If so, are there any recommended changes to the approach? Perhaps taking the total number of stars, dividing by 100 (or so), and creating a grid of nodes, each containing a single geom which contains vertexes related to the stars in that node’s grid? Do you imagine this might improve performance even further?
if you only have one node, there is no way to cull away anything that’s not within view. but since the starmap doesnt slow your game down (even if completely visible) it should be ok.
dividing geometry into big, efficient-cullable pieces was more a general statement in case you encounter such a situation. (usualy when doing regular indoor/outdoor scenes where the camera is surrounded by lots of geometry)
I’m reading on collision detection now, as it seems the most appropriate approach to make stars selectable. Since each star is actually a vertex in a Geom, I am expecting that detecting collision on one star will actually match the entire Geom rather than the specific vertex.
I’m unsure as to what approach to take in order to make individual stars selectable. Invisible collidable spheres at the same position as each vertex?
again, you’r assumtions are correct. the result of a collision detection doesnt give you the vertices. (which would be quite impossible since vertices are infinitly small and thus un-collideable for a picking ray).
seperate (invisible) geometry is a good idea in your case. to speed up collisions you may want to group nearby starts under a node.
in your case i’d recommend to use an octree-like structure. dont hasitate to waste a few extra nodes for collisions.
I’m famimliar with octrees, kd-trees, etc in concept, and I’ve implemented a custom path-based partitioning similar to octrees before; however, I do not believe I’ve ever made use of a traditional octree. Might there be somewhere you could recommend I go to learn more about using octrees in Panda3D?
Many thanks for all of your input.
I’ve run across treeform’s octree stuff in the forum. In this case, where I will be procedurally placing many invisible collision nodes, would I attach them all to a root node, then use his octreefy(node) function?
i dont know if treeforms script works on collision solids. it was made to process triangle-geometry into an collision optimized way.
if you know octrees already. just use nodepathes to build your tree. at the end of your tree-branches there should be a cuple of close-together collision solids.
other than creating new nodepathes and reparenting your collision solids, there should be nothing you need to do. panda will process it correctly all by itself.