Meshes in Cargo-Bot

I was having a look at the source of Cargo-Bot and I noticed that the sprite() method is never used, but rather everything is managed by the Screen object instance that draws to (a pool of?) meshes.

Is that because it’s super fast, or something? Cargo-Bot doesn’t even have a huge number of sprites, so should we all be using meshes rather than sprites…

Actually, I guess my real question is: what is a mesh?!

Mr. Speaker, Mr. Vice President, members of Congress:

Yes, mesh is much faster. At some point cargo bot started to be sluggish, especially on iPad 1, so I converted everything to meshes. They are specially quicker when you’re drawing many instances of the same sprite (don’t ask me why). So that’s one way to think about mesh - a quick way to draw many instances of the same sprite. There’s another way to think about it too, which is more low level, something to do with triangles or what not. I haven’t tried to use it that way but some folks here have used it to make awesome looking things.

@mrspeaker here’s an overview of how mesh and sprite() differ

sprite( “MySprite”, x, y, … )

Every draw call

  1. Look up texture for “MySprite”
  2. Allocate memory for six vertices
  3. Assign texture coordinates
  4. Set up OpenGL state ← can be expensive
  5. Submit six vertices to OpenGL ← has a lot of overhead

a mesh:draw() call which draws 100 “MySprite” rects at once

Once off

  1. Look up texture for “MySprite”
  2. Allocate memory for 100 * 6 vertices
  3. Assign texture coordinates

Every draw call (mesh:draw())

  1. Set up OpenGL state
  2. Submit 100 * 6 vertices to OpenGL

So if you were to draw 100 sprites, you would have to do all five steps 100 times every draw call. There is a lot of overhead going back and repeating those steps for every sprite on the screen (especially when they are all the same texture). With a mesh, the first three steps happen once, when the mesh is created or modified.

Also, the most important part is that the mesh submits all its data to the GPU in one go — so doesn’t have to keep sending small batches of 6 vertices for every sprite you want to render. There is a lot of overhead in sending data to the GPU, it’s better to send as much as possible in one call.

It would be better at this point to have just one packed texture (or a small set if too large) containing all the base texures. uv map allows to use one or anyway just a few bunch of meshes, reducing at min the drawcall.

@shrike yes, that’s how Cargo-Bot does it.

Ok, so there’s something I’m missing, because looking at the code and at the spritepack it doesn’t seem to me that’s the way cargo boat does.

In the sprite pack there’s exactly one image for each object in the game (i.e. 9 images for all the low res crates used in the solution area, 3 per color), and (if I correctly understood) the screen:dodraw() function creates one mesh per z per image name, so at the end 9 meshes.

What I meant was, for example, to have just one image containing all the crates, created with some tool like TexturePacker, and a configuration file describing the packed texture, so to have at the end just one mesh for all the crates.

Sorry shrike, you’re right. @ruilov actually wrote a texture packing tool in Codea (code is on the forums). But perhaps Cargo-Bot didn’t need to use it.

Yes I’ve looked at his atlas code some days ago.

When I bought codea my first plan was to use it as prototype tool and it would be nice to share the same resources I’m already using with other projects, where I’m using texture packer to pack all resources for static and animated sprites, tiles ecc.

Hoping in more free time next days I’d like to recreate all the basic code I need for that, from textureset to animated sprite. It should be pretty easy but it requires time and moreover I’m not so used to coding in lua, but it’s a good excuse to learn it :slight_smile:

Anyway looking at @ruilov code (both atlas wrapper and Cargo-Bot code) was very inspiring

Version 1.4 will be much better for texture packing — because you will be able to save the packed texture back out of Codea into a sprite pack using the new saveImage() function.

Right I didn’t use the atlas code in cargo-bot. I think it could be integrated into the screen class without any other changes (at least that’s what i tried to do - actually spriteobj would need changes too) but in the end a separate mesh for each sprite at each z level was fast enough so i didn’t bother

@shrike please share your code when you do it. My texture packing, in the atals code, was a pretty dumb one and I’d love to have a better version so i can start using in my codea projects

Working on smooth animations right now, and doing some optimizations…

I my previous version, I was using around 10 individual animated parts (head, body, both feet, both arms, weapon, eyes, helm, blob shadow).
Each part was an individual mesh, animated using trig and mesh:setRect.
It was drawing up to 20 characters running around on screen before dropping below 40fps on my iPad 1, which was fine for what I wanted.
I knew I wasn’t using it properly (too many draw calls, and mesh:setRect’s power was wasted)

Now, i’m creating an atlas from a set of random images, and building a single mesh containing 10 rects, each having their own texture coordinates using mesh:setRectTex, while animation is done using mesh:setRect(id, …).

Needless to say, while it’s a bit more complex to setup, it’s so much faster (drawing 200 64*128 animated characters at above 30fps)… Hell, we could make a RTS with Codea :open_mouth: