Hello, after I had a little trouble grasping the concepts of how meshes work and how to texture them (and subsequently receiving help from @Andrew_Stacey and @Shrike) I decided to create a tutorial on the basics of meshes. If you have time, please read it over and see where I have failed to explain things clearly, or where I give bad info. Once I get corrections made, I will add it to the wiki:
Mesh tutorial
In this tutorial, I am going to talk about what meshes are, why you might want to use them, and how to use them in Codea. To complete this tutorial, you probably want to have a basic understanding of Codea and the LUA language. Let’s call the level of difficulty “intermediate.”
What Meshes Are
First off, let’s talk about what a mesh is. You might think of a mesh as a 3D object, and meshes ARE a basic part of 3D objects. But a mesh could more accurately be defined as as a list of polygons, and more specifically, in the case of Codea, it is a list of triangles. These lists of polygons are very useful for both 2d and 3d game creation.
Basically any 2d or 3d shape can be broken up into a bunch of triangles. Generally, the more polygons used, the smoother the shape.
In modern 3d games, the models are composed of thousands (or tens of thousands) of polygons. To accomplish this feat, the iPad graphics hardware has been designed to manipulate and draw triangles extremely fast, much faster than just drawing pixels to the screen. By using meshes in Codea rather than using the sprite command, you can often drastically speed up the rendering in your game.
Your first mesh
To create a mesh you simply run the built in mesh function, which returns an empty mesh.
myMesh = mesh()
That mesh is pretty worthless without any triangles, so let’s add a triangle to it. Here is a diagram of the first mesh we are going to create:
And here is the code to add that triangle to our mesh:
myMesh.vertices = {vec2(0,0),vec2(100,0),vec2(0,100)}
And now we have a functional mesh. Let’s make a quick program to test it out:
function setup()
myMesh = mesh()
myMesh.vertices = {vec2(0,0),vec2(100,0),vec2(0,100)}
end
function draw()
background(40, 40, 50)
myMesh:draw()
end
Run this and you will see our grey triangle appear in the bottom left hand corner of the screen at the origin. The triangle is rendered in grey because we have not given it any color or texture. Let’s try giving it color first, and we will graduate to textures later.
Coloring Meshes
To add color to a mesh you pass a list of colors to the mesh that is equal in length to the number of vertices. This means that for every vertex in the list, you must provide a color. Our mesh currently has 1 triangle and therefore 3 vertices, so we need to give the mesh 3 colors. Here is the updated program with colors added:
function setup()
red = color(255, 0, 0, 255)
green = color(0, 255, 0, 255)
blue = color(0, 0, 255, 255)
myMesh = mesh()
myMesh.vertices = {vec2(0,0),vec2(100,0),vec2(0,100)}
myMesh.colors = {red, green, blue}
end
function draw()
background(40, 40, 50)
myMesh:draw()
end
Now our mesh is rendered in color, and we get a pretty neat gradient effect as the colors are blended between the vertices. You can use this technique to create gradient backgrounds, buttons, etc.
Texturing Meshes
Texturing meshes works a lot like coloring meshes, but instead of passing a list of colors, we will pass a list of texture coordinates. This is a process called U,V mapping. The x,y coordinate of each vertex is mapped to a coordinate on the texture, which is called the u,v coordinate, since x and y are already in use. (Hence the name U,V mapping) With the U,V coordinates, we use a “unit-square” system, which allows us to specify what portion of the texture we want to use for the triangle, instead of the exact pixels. (Don’t worry, this will be explained more clearly as you follow this example.)
This is a diagram of the unit square:
If you want to use the full width of the image, you would use 1 as the width. To use half of the width, you would use .50 as the width. Let’s take an image from the Codea spritepacks and use it as our texture. First get rid of the color code as we are now texturing instead. Next we want to make a triangle in U,V coordinates that matches our mesh triangle. It will look something like this:
So the texture coordinates for our triangle are going to be:
0,0 1,0 0,1
Can you see how those relate to our vertices? Remember they are:
0,0 100,0 0,100
Here is the updated code:
function setup()
img = readImage("Planet Cute:Icon") --Get the image
myMesh = mesh()
myMesh.vertices = {vec2(0,0),vec2(100,0),vec2(0,100)}
myMesh.texture = img --Set the image as texture
myMesh.texCoords = {vec2(0,0),vec2(1,0),vec2(0,1)}
end
function draw()
background(40, 40, 50)
myMesh:draw()
end
And if done correctly, we should now have half of the image drawn on our triangle. To see the rest of this image, I would really like to have another triangle to finish the rectangle. So, looking at this image:
You should see that the triangle we need to add to our mesh has the vertices: 0,100 100,100 100,0 And the texture coordinatesfor that new triangle will be: 0,1 1,1 1,0. Lets add them to our code:
function setup()
img = readImage("Planet Cute:Icon") --Get the image
myMesh = mesh()
myMesh.vertices = {vec2(0,0),vec2(100,0),vec2(0,100),vec2(0,100),vec2(100,100),vec2(100,0)}
myMesh.texture = img --Set the image as texture
myMesh.texCoords = {vec2(0,0),vec2(1,0),vec2(0,1),vec2(0,1),vec2(1,1),vec2(1,0)}
end
function draw()
background(40, 40, 50)
myMesh:draw()
end
And Voila, we have our image drawn correctly to a mesh. Now that we have learned how to draw a rectangular texture onto a mesh the hard way, lets look at a slightly simplified way of completing that same task.