How to reduce lag

Hi

In my sandbox game, I have lots of meshes/blocks to render. This causes massive lag when I have generated some terrain and my question is how to minimize this lag. I need to be able to remove and place blocks so I can’t use flatten_strong. How does Minecraft handle so many meshes at once?

/Isak

In short, you have to work directly with the geometry. That is, you must add vertices to an existing primitive or remove them. Perhaps even with direct memory access.

Expanding a little on the above, I strongly suspect that the way that Minecraft handles some many meshes is that it doesn’t–it just gives the illusion that it does.

I don’t know for certain, but I imagine that in Minecraft each region of the terrain (i.e. excluding creatures and the like) is a single mesh (or perhaps a few meshes). When a block is removed or added, the relevant mesh is updated.

Does this mean that all my meshes are updated too often and it is the reason I get so much lag? Is there a way to control when the meshes are updated and only make the relevant meshes update when I want to? How do implement this?

It’s more likely, I think, that you simply have too many meshes.

You see, a major limiter for modern graphics cards, as I understand it, is not the polygon count–as we know, that ceiling is quite high these days. Instead, it’s the batch count: the number of separate “chunks” that the card can handle at once.

Thus, given the same number of polygons, it may sometimes be better to have those polygons be held in a smaller number of meshes than to have them spread across many meshes. That said, this isn’t a hard-and-fast rule–sometimes it better to aid culling by breaking things up, or to find a balance between the two.

From what I gather, it’s generally best to have no more than a few hundred individual meshes.

You need to reduce the number of primitives you send to the graphics card. You can do this by changing the previous geometry, adding multiple vertices, or deleting them.

By analogy with this example.

The essence of the problem is in the number. If you notice that many small files on the hard disk are copied longer than one large one. This is the same problem.

Thanks for the replies!

As I understand it, I need to reduce the number of meshes somehow. Can I do this by having all blocks of an in-game chunk reparented to the NodePath of that chunk for instance? I have also seen samples using some culling functionality, is that relevant?

/Isak

When you call flatten_strong, it combines all the primitives into one. Initially, you had to design your work based on the modification of the primitive. At the moment, there is no simple solution other than this.

OK, So if I was to create a NodePath (A), NodePath (B) and NodePath ©. And then call reparent_to(A) on B and C and after that call flatten_strong on A, would that mean that I would have one single mesh (A) which contains both B and C. Have I understood this correctly?

/Isak

Yes, but this is a slow operation, if you want to change the geometry later, it will no longer be possible without the methods of modifying the feature.

This is an irreversible action.

Indeed; for a game in the vein of Minecraft direct manipulation of the mesh-data might be better–more effective and quicker to run–than use of “flattenStrong”.

I think that there have been a few threads on the forum dealing with such issues, even specifically with Minecraft-like projects. Serega linked to one above, and searching might turn up more. These might provide further information for the implementation of your project.

I have now tried putting all NodePaths in a chunk under one NodePath, so that I get one NodePath per chunk, and called flatten_strong. But the texture wraps in a very weird way. How do I prevent this? What happens with textures when you call flatten_strong?

Your message is not enough to draw conclusions about the problem.
You can create a short code to make it clear what is happening.

I have a pattern of using flatten_strong in python. I don’t think C++ will be any different.

from panda3d.core import NodePath
from direct.showbase.ShowBase import ShowBase

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        all_node = NodePath('all')

        for i in range(0, 20):
            for j in range(0, 20):
                model = loader.load_model("box")
                model.clear_model_nodes()
                model.set_pos(i, j, 0)
                model.reparent_to(all_node)

        all_node.flatten_strong()
        all_node.reparent_to(render)

        print(all_node.ls())

app = MyApp()
app.run()

Sorry if I wasn’t clear enough. Just like your code below I have a NodePath (all) which I am reparenting some nodes to (box). Then I call flatten_strong on all_node and reparent it to render. This reduces lag significantly. The only problem is that every “box” needs to have a unique texture which flatten_strong seems to merge into one texture.

This is without flatten_strong (As I want it to look, but not performing that well):

This is with flatten_strong (Textures get messed up):

Hope you understand!
By the way, what does clear_model_nodes do?

/Isak

How are your blocks UV-mapped? Do they use UV-coordinates defined in a modelling package (e.g. Blender), or are they generated programmatically in some way, either by your code or Panda?

The blocks are using a cubemap for textures which I then load in code. By doing it this way I can have only one model (block.egg) for all types of blocks.

I can only assume that you need to split geoms with different textures into separate ones.

I’m guessing that it’s the cube-map that’s the problem: Having been flattened, the models no longer have distinct positions, rotations, etc. Everything has a position and rotation of zero, with its vertices providing the actual location of the object.

Without distinct positions and/or rotations per model, the cube-map code might be becoming confused–hence the single patch of grass spread oddly over one location, and the radial pattern on the ground.