How to use setInstanceCount(n) / Load the game faster

I’ve been looking for the answer for almost 2 days now and found nothing. I’m building a game with Panda3d engine and Python, and I wanted the floor to be tiled, so I was loading the ‘grass’ model as many times as I needed. When I play the game, though, it feels really really slow.

I found this article that explained how setInstanceCount(n) worked, but I found no examples on how to use it nor how to access the IDs of the models that were copied.

I tried replacing instanceTo() in other programs with setInstanceCount(n), but it doesn’t seem like it is working.

dancer = Actor.Actor("chorus-line-dancer.egg", {"kick":"kick.egg"})
dancer.loop("kick")
dancer.setPos(0,0,0)
for i in range(50):
    placeholder = render.attachNewNode("Dancer-Placeholder")
    placeholder.setPos(i*5, 0, 0)
    dancer.setInstanceCount(5)
    #Original: dancer.instanceTo(placeholder)

How do I achieve this? Also, how do I access the data of each models, say, to set the coordinate? It would help me if there was a simple example program. Thanks in advance.

setInstanceCount is a completely separate mechanism from instanceTo. With setInstanceCount, you create only one instance of the model, and then you write a shader that takes in an instance ID variable and repositions each actor to the position you want (eg. by passing the shader an array of positions, and using the instance ID as an index into that array).

You need to keep in mind to either make a custom bounding volume or disable culling when you do this since Panda has no way of knowing what sort of transformation you apply in the shader.

If your floor is a rectangle, then it will likely be far more efficient to simply create a single, large quad and then alter the texture scale such that the “grass” texture repeats. Something like this:

self.grass = loader.loadModel(<your grass model here>)
self.grass.setScale(width, length, 1)
self.grass.setTexScale(TextureStage.getDefault(), width, length)

If it’s important that you have lots of little tiles, consider flattening them together (presumably after placing them) or using the Rigid Body Combiner; in either case, take a look at this page.

Thanks. I actually experimented with .flattenStrong(), and it raised my frame rate to about 70fps. Also, I added trees and fog, and it looks great.

The problem is, the program takes literally 15 minutes (to be accurate 15:31:21) to load up, and I have no clue why. It gets stuck in the white screen for a looooooooong time and then it runs like nothing happened, even at a great frame rate. Does any of you know why?

It is hard to guess without seeing some code, but maybe you are doing something like running flattenStrong inside of a loop instead of just once at the end?

I actually do not know if flatStrong() is causing the problems I’m having. It may be that my scripting isn’t well, or it could just be that I’m loading too many models (15 minutes seem too long though). I uploaded my resources and the script on Google Drive so I’d be glad if you could take a look at it and tell me if there’s anything that I should be fixing.
https://drive.google.com/open?id=0B4roB9WFscpOOHFiaDNuUkI5ODA&authuser=0

From what I can tell, it just seems like there are a lot of models being combined and it takes a long time to process. There are a few ways you could make it load faster.

First of all would be to simplify the models, for example one of the trees was quite highly detailed. This makes less work for the flatten command.
Another approach would be to try grouping models together in chunks (for example in a grid of square cells). Running the flatten command on smaller batches of objects might have better performance.
Taking it a step further, you could have each cell as a model with the objects already placed and flattened.

A whole different way of approaching the problem would be to leave the more highly detailed models separate and apply LOD nodes on them to swap them out for simple versions at a distance and also to hide them from rendering completely when they are far away.

I’m interested about the Level Of Details node. How do I do that exactly? I Googled for a bit but I couldn’t seem to find much details.

LOD in itself doesn’t solve the problem of having too many geoms. If you have 500 separate nodes, the bottleneck is still going to be that you have 500 separate pieces of geometry, whether they’re low-polygon or high-polygon.

If LOD doesn’t help load the game faster, is reducing the models (or details in models) the only way to make the game load faster? Thanks for your help.

Can you post the output of model.ls() and model.analyze() for the model you’re trying to instance and flatten a lot? If the model is structured poorly, it may significantly harm flatten time; optimizing the model geometry beforehand could help a lot.

Ok. I did model.ls() and model.analyze() for all of my models that I’m using. Just so you know, I’m putting many many trees into this project.

---grass (ground)---
ModelRoot grassfield.egg
  GeomNode SketchUp (1 geoms: S:(MaterialAttrib TextureAttrib))
  PandaNode 
3 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
1 Geoms, with 1 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 GeomNodes.
8 vertices, 8 normals, 0 colors, 8 texture coordinates.
GeomVertexData arrays occupy 1K memory.
GeomPrimitive arrays occupy 1K memory.
8 triangles:
  8 of these are on 4 tristrips (2 average tris per strip).
  0 of these are independent triangles.
1 textures, estimated minimum 768K texture memory required.


---road (ground)---
ModelRoot road.egg
  GeomNode SketchUp (1 geoms: S:(MaterialAttrib TextureAttrib))
  PandaNode 
3 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
1 Geoms, with 1 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 GeomNodes.
8 vertices, 8 normals, 0 colors, 8 texture coordinates.
GeomVertexData arrays occupy 1K memory.
GeomPrimitive arrays occupy 1K memory.
4 triangles:
  4 of these are on 2 tristrips (2 average tris per strip).
  0 of these are independent triangles.
1 textures, estimated minimum 768K texture memory required.


---water (ground)---
ModelRoot water.egg
  GeomNode SketchUp (1 geoms: S:(MaterialAttrib TextureAttrib))
  PandaNode 
3 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
1 Geoms, with 1 GeomVertexDatas and 1 GeomVertexFormats, appear on 1 GeomNodes.
8 vertices, 8 normals, 0 colors, 8 texture coordinates.
GeomVertexData arrays occupy 1K memory.
GeomPrimitive arrays occupy 1K memory.
4 triangles:
  4 of these are on 2 tristrips (2 average tris per strip).
  0 of these are independent triangles.
1 textures, estimated minimum 768K texture memory required.


---tree1 (environment)---
ModelRoot tree1.egg
  PandaNode SketchUp
    GeomNode ID2 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID15 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID23 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID31 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID44 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID52 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID60 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID68 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID76 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID89 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID97 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID105 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID113 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID121 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID129 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID137 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID145 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID153 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID161 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID169 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID177 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID185 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID193 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID201 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID209 (1 geoms: S:(MaterialAttrib))
    GeomNode ID217 (1 geoms: S:(MaterialAttrib TextureAttrib))
    PandaNode ID225
      GeomNode ID225.Material2 (1 geoms: S:(MaterialAttrib TextureAttrib))
      GeomNode ID225.Material3 (1 geoms: S:(MaterialAttrib))
    PandaNode ID233
      GeomNode ID233.Material2 (1 geoms: S:(MaterialAttrib TextureAttrib))
      GeomNode ID233.Material3 (1 geoms: S:(MaterialAttrib))
    PandaNode ID241
      GeomNode ID241.Material2 (1 geoms: S:(MaterialAttrib TextureAttrib))
      GeomNode ID241.Material3 (1 geoms: S:(MaterialAttrib))
    PandaNode ID249
      GeomNode ID249.Material2 (1 geoms: S:(MaterialAttrib TextureAttrib))
      GeomNode ID249.Material3 (1 geoms: S:(MaterialAttrib))
    GeomNode ID257 (1 geoms: S:(MaterialAttrib))
    GeomNode ID263 (1 geoms: S:(MaterialAttrib))
    GeomNode ID269 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID277 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID285 (1 geoms: S:(MaterialAttrib TextureAttrib))
  PandaNode 
46 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
39 Geoms, with 39 GeomVertexDatas and 2 GeomVertexFormats, appear on 39 GeomNodes.
51568 vertices, 51568 normals, 0 colors, 51472 texture coordinates.
GeomVertexData arrays occupy 1612K memory.
GeomPrimitive arrays occupy 147K memory.
15 GeomVertexArrayDatas are redundant, wasting 1K.
7 GeomPrimitive arrays are redundant, wasting 1K.
25072 triangles:
  452 of these are on 186 tristrips (2.43011 average tris per strip).
  24620 of these are independent triangles.
3 textures, estimated minimum 960K texture memory required.


---tree2 (environment)---
ModelRoot tree2.egg
  PandaNode SketchUp
    GeomNode ID2 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID15 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID23 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID31 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID39 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID47 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
  PandaNode 
9 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
6 Geoms, with 6 GeomVertexDatas and 1 GeomVertexFormats, appear on 6 GeomNodes.
10134 vertices, 10134 normals, 0 colors, 10134 texture coordinates.
GeomVertexData arrays occupy 317K memory.
GeomPrimitive arrays occupy 68K memory.
11546 triangles:
  0 of these are on 0 tristrips.
  11546 of these are independent triangles.
1 textures, estimated minimum 337K texture memory required.


---TreasureChest (item)---
ModelRoot treasureChest.egg
  PandaNode SketchUp
    GeomNode ID2 (1 geoms: S:(MaterialAttrib))
    GeomNode ID10 (1 geoms: S:(MaterialAttrib))
    PandaNode ID16
      GeomNode ID16.Material2 (1 geoms: S:(MaterialAttrib TextureAttrib))
      GeomNode ID16.Material3 (1 geoms: S:(MaterialAttrib))
    GeomNode ID31 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID44 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID52 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID60 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID68 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID76 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID84 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID92 (1 geoms: S:(MaterialAttrib))
    GeomNode ID98 (1 geoms: S:(MaterialAttrib))
    GeomNode ID104 (1 geoms: S:(MaterialAttrib))
    GeomNode ID110 (1 geoms: S:(MaterialAttrib))
    GeomNode ID116 (1 geoms: S:(MaterialAttrib))
    GeomNode ID122 (1 geoms: S:(MaterialAttrib))
    GeomNode ID128 (1 geoms: S:(MaterialAttrib))
    GeomNode ID134 (1 geoms: S:(MaterialAttrib))
    GeomNode ID140 (1 geoms: S:(MaterialAttrib))
    GeomNode ID146 (1 geoms: S:(MaterialAttrib))
    GeomNode ID152 (1 geoms: S:(MaterialAttrib))
    GeomNode ID158 (1 geoms: S:(MaterialAttrib))
    GeomNode ID164 (1 geoms: S:(MaterialAttrib))
    GeomNode ID170 (1 geoms: S:(MaterialAttrib))
    GeomNode ID176 (1 geoms: S:(MaterialAttrib))
    GeomNode ID184 (1 geoms: S:(MaterialAttrib))
    GeomNode ID190 (1 geoms: S:(MaterialAttrib))
    GeomNode ID198 (1 geoms: S:(MaterialAttrib))
    GeomNode ID204 (1 geoms: S:(MaterialAttrib))
    GeomNode ID210 (1 geoms: S:(MaterialAttrib TextureAttrib))
    GeomNode ID218 (1 geoms: S:(MaterialAttrib))
  PandaNode 
36 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
32 Geoms, with 32 GeomVertexDatas and 2 GeomVertexFormats, appear on 32 GeomNodes.
1867 vertices, 1867 normals, 0 colors, 851 texture coordinates.
GeomVertexData arrays occupy 51K memory.
GeomPrimitive arrays occupy 9K memory.
6 GeomVertexArrayDatas are redundant, wasting 1K.
2 GeomPrimitive arrays are redundant, wasting 1K.
1473 triangles:
  154 of these are on 59 tristrips (2.61017 average tris per strip).
  1319 of these are independent triangles.
2 textures, estimated minimum 240K texture memory required.

Also, I should tell you that I used SketchUp from Google to create the 3D model.

I should have been more clear. What I meant to convey was that the LOD node can be used to not only switch between high and low resolution models, but also hide objects completely after a certain distance.
More info here: http://www.panda3d.org/manual/index.php/Level_of_Detail

The first tree is most definitely the biggest problem: it consists of 25k vertices spread out over 46 meshes. That should be improved drastically. Does the tree perhaps have 46 different textures, causing Panda not to flatten it on load?

Optimising the models before loading should improve this, either using a script or in the modelling program. (I’m afraid that SketchUp may not be the most suitable modelling program for this.)

Do you know any script or application that is able to do this? I’m using a Mac, and it would be better if it is free.
Sorry that I don’t know anything about this engine. I’m pretty new to Panda3D.
I appreciate your help.

Today I tried disabling the line that had the instruction to flattenStrong() one node. All the sudden, the game loaded right up. The problem is, though, the game is much much slower than when it’s ran with flattenStrong(). Are there any solutions to this? Is there any way to making the loading process faster without killing the loading time?

Is your world procedurally generated? If not, the right thing to do is to create your world in a modelling program, and instead of every tile being a separate mesh, you model it as one or more big meshes.

If so, you may have to start playing with the GeomVertexWriter interfaces to build up your world using triangles, creating everything as one large Geom from the get-go.

That said, making your tree models structured more simply would help as well. I think the egg-trans utility has some flags that might help.

Sorry for my extremely late reply.

Yes, the map is randomly generated every time the game is launched, so I don’t think I can make a big map’s data.

Also, I looked up GeomVertexWriter but I’m still confused about what it does. Is it possible for me to get some clarifications?

Thank you for you support.

Also, I tried making the models simpler. I now don’t use tree1 and I stripped tree2 to bear minimum.

It still takes whole 5 min to start up (better than 15 min, though). Is there anything that I should change? Also, here’s the new tree2:

---tree2 (environment)---
ModelRoot tree1.egg
  PandaNode SketchUp
    GeomNode ID2 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID15 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID23 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
    GeomNode ID31 (1 geoms: S:(MaterialAttrib TextureAttrib TransparencyAttrib))
  PandaNode 
7 total nodes (including 0 instances); 0 LODNodes.
0 transforms; 0% of nodes have some render attribute.
4 Geoms, with 4 GeomVertexDatas and 1 GeomVertexFormats, appear on 4 GeomNodes.
2328 vertices, 2328 normals, 0 colors, 2328 texture coordinates.
GeomVertexData arrays occupy 73K memory.
GeomPrimitive arrays occupy 28K memory.
2 GeomPrimitive arrays are redundant, wasting 14K.
4624 triangles:
  0 of these are on 0 tristrips.
  4624 of these are independent triangles.
1 textures, estimated minimum 337K texture memory required.

If the map is randomly generated, what you want to do is create code to build the geometry from the ground up, into large Geoms (rather than one per tile or feature or something). The manual chapter “Procedurally Generating 3D Models” should cover that.