Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dermotbalson/a692c5b3d4f35a8a7b5f3c7e848ed580 to your computer and use it in GitHub Desktop.
Save dermotbalson/a692c5b3d4f35a8a7b5f3c7e848ed580 to your computer and use it in GitHub Desktop.
Step by step mesh
--# Notes
--[[
** What is a mesh? **
A mesh is a quick way of drawing a shape. It is a set of points which create an outline (or wirefame) of an object
It is made up of triangles (groups of three points)
Triangles are used because a triangle has the smallest number of points that encloses an area
Each triangle corner is known as a VERTEX, and has a position and a colour
The colours of all the points inside the triangle are interpolated from the colours of the three corners
This means you can draw quite complex shapes without having to say what colour every pixel is going to be - your program will figure that out itself, just from the colours at the corners of each triangle.
** Should I learn meshes? **
When you are starting out with Codea, you don't need to worry about "meshes", because for simple 2D projects,
sprites are usually the simplest option.
But as you develop your skills, you should learn about meshes, because
* they are used to draw everything (sprites are meshes),
* you can deform or twist meshes more easily than sprites, because you can move any of the vertices
* if you have hundreds of sprites to draw, a single mesh may draw much faster than sprites, because there
is some setting up before each sprite (which is a mesh) is drawn
* meshes are the only way to draw in 3D
So the best approach may be to use sprites until you are very comfortable with 2D graphics, and then
learn about meshes.
This set of demos shows you the basics of meshes for 2D graphics. For 3D meshes, see the 3D demo app.
--]]
--# Triangle
--Triangle
--in this demo, we'll draw just one triangle, with a different colour at each corner
--so you can see the interpolation
function setup()
m=mesh() --always start by creating an empty mesh
--create a table of three vec2(x,y) positions to make a triangle
--vertices must always be in groups of three, making triangles
m.vertices={vec2(300,400),vec2(500,400),vec2(400,560)}
--we'll make each vertex colour different so you can see the interpolation
m.colors={color(255,0,0),color(255,255,0),color(0,255,0)}
--if you wanted ALL the colours to be the same, you can just write this
--m:setColors(color(255,255,0))
end
function draw()
background(180)
m:draw() --draws the mesh with the positions and fills it with the colour we defined
end
function PrintExplanation()
output.clear()
print("All meshes are made up of triangles.\n\nThis demo creates a mesh of just one triangle in a fixed place")
print("Look at the code for details")
print("When you understand it, choose the next step with the slider at the top, and press the Run button.")
end
--# Square
--Square
function setup()
m=mesh()
--a square is made up of two triangles next to each other
--a square has 4 corners, and 2 triangles have 6 corners, so two of the vertices get used twice
--the vertices start to get messy, so it's easiest to first define the corners of the square
--I'm doing it in the order - bottom left, bottom right, top left, top right
local bL, bR, tR, tL = vec2(300,400), vec2(500,400), vec2(500,600), vec2(300,600) --positions of corners
--now we create two sets of three vertices to make two triangles
--it is best to list vertices anticlockwise
m.vertices={bL,bR,tR, tR,tL,bL} --can you see how each set of three forms a triangle?
--we'll colour each triangle a different colour
c1, c2 = color(255,0,0), color(255,255,0)
--assign the colours to the six vertices in order, three red then three yellow
m.colors={c1,c1,c1, c2,c2,c2}
end
function draw()
background(180)
m:draw()
end
function PrintExplanation()
output.clear()
print("Now we create a square made up of two triangles next to each other.")
print("The two triangles are given different colours so you can see them clearly")
end
--# AddRect
--Using addRect for rectangles
--[[
To make it easier to add rectangles, which are used for many shapes, Codea has some special functions
addRect adds a rectangle to a mesh, and there are other functions to make it easy to change the vertex
positions, and even rotate them
This demo uses addRect to make a shape from several rectangles to show how easy it is.
--]]
function setup()
m=mesh()
--addRect adds a rectangle
--first two parameters are the centre point, next two are width, height
--we'll build a stick person
m:addRect(400,350,100,200) --body
m:addRect(365,200,30,150)--leg
m:addRect(435,200,30,150) --leg
m:addRect(400,435,350,30) --arms
m:addRect(400,480,50,60) --head
--our mesh now has 5 rectangles, each with 2 triangles of 3 vertices, so it has 5x2x3=30 vertices in total
--Codea creates all these vertices for us
print("Number of vertices = "..m.size) --we'll check this
--we'll set all the vertex colours to yellow, we can do this with one command
m:setColors(color(255,255,0))
end
function draw()
background(180)
m:draw()
end
function PrintExplanation()
output.clear()
print("It's messy working with vertices, so addRect makes it easy to create rectangles")
print("If you made this shape using triangles, you would need to define 10 triangles and 30 vertices, instead of just 5 lines of code!")
end
--# Texture
--Adding an image, known as a TEXTURE
--[[
We can add a picture to our mesh, rather than a colour.
You need to tell Codea which part of the texture image is at each vertex in the mesh, as a fraction 0-1
An image texture is a rectangle, and the positions of its corners are
bottom left = (0,0)
bottom right = (1,0) ie all the way to the right, on the bottom
top left = (0,1) ie on the left, all the way to the top
top right = (1,1) ie all the way to the right and all the way up
So if a picture is 100x200 pixels, and a vertex is at (50,150) on the picture, then the texture position
is (0.5,0.75) ie (50/100,150/200)
You must set these positions for each vertex, but if you create your rectangles with addRect, and if your rectangle
uses the whole picture, Codea will do all the work for you.
--]]
function setup()
m=mesh()
--choose a picture to draw (change it if you like)
img=readImage("Planet Cute:Character Princess Girl")
m:addRect(400,400,img.width,img.height) --same size as image
--let's add a second one, twice the size
--Codea will scale the image to the size of the rectangle
m:addRect(250,250,img.width*2,img.height*2)
m.texture=img --it's this easy to use an image
--it will be used for all the rectangles on this mesh
--there's no need to set the texture positions if we use addRect, because Codea will do it for us
--the only time you need to do it yourself is if you don't want to use the whole image
--we'll look at that option later
end
function draw()
background(180)
m:draw()
end
function PrintExplanation()
output.clear()
print("We can use a texture (ie picture) instead of colours on our rectangles")
end
--# Tiling
--Using the same image repeatedly to "tile" an area
--[[
If you add rectangles with addRect and a texture image, you can create a tiled effect, repeating the image
across an area. That's because Codea will use the texture image for EACH rectangle in the mesh.
The demo below creates a castle like this.
But there is one problem. We want to create a floor, a castle, and soldiers, each with different texture images.
However, a mesh can only have one texture image attached.
One solution is to create a separate mesh for each image, and that's what we'll do here.
In the next demo, we'll show a different solution.
--]]
function setup()
x,y=100,100 --start drawing here
size=70 --size of tiles
SetupMeshes()
end
function SetupMeshes()
--create one mesh for the bottom layer, a grassy surface
local imgFloor=readImage("Platformer Art:Block Grass")
floor=mesh()
for i=1,8 do --calculate positions and add rectangles
local xx=x+(i-0.5)*size --mid point of rectangle
floor:addRect(xx,y+size/2,imgFloor.width,size)
end
floor.texture=imgFloor
--another mesh for the brick castle
local imgBlock=readImage("Platformer Art:Block Brick")
--problem - image has round edges that leave gaps when we stack them, so trim the edges off
imgBlock=imgBlock:copy(3,3,imgBlock.width-6,imgBlock.height-6)
castle=mesh()
castle.texture=imgBlock
--we'll build a castle, 6 blocks wide by 7 high, with some gaps for windows and the castle top
--here is a map of the castle in a table
map={}
map[1]="bs b" --mark each block position with a "b", and each soldier with "s", gaps with " "
map[2]="bbbbbb" --you can change these if you like
map[3]="bbbbsb"
map[4]="bbbbbb"
map[5]="bsbbbb"
map[6]="bbbbbb"
map[7]="bbssbb"
--create a separate mesh for soldiers
imgSoldier=readImage("Planet Cute:Character Boy")
soldiers=mesh()
soldiers.texture=imgSoldier
--read the map and add soldiers and blocks to their meshes
for i=1,#map do
local yy = y+size*(#map-i+3/2) --y position of this block
for j=1,map[i]:len() do
local xx = x+(j+0.5)*size --x position of this block
local a=map[i]:sub(j,j) --get map character (b, s or blank)
if a~=" " then
if a=="b" then castle:addRect(xx,yy,size,size)
elseif a=="s" then soldiers:addRect(xx,yy,imgSoldier.width,imgSoldier.height)
end
end
end
end
end
function draw()
background(170, 194, 211, 255)
floor:draw()
soldiers:draw()
castle:draw()
end
function PrintExplanation()
output.clear()
print("We can 'tile' images using a mesh")
end
--# Tilemap
--Using several images on one texture
--[[
A problem with meshes is that each can only have ONE texture image attached
In the previous demo, we made a separate mesh for each texture image.
But there is another way that is used by most game developers.
We put all the pictures into a single image, put all our rectangles into one mesh using that image,
and then tell Codea which part of the image to use for each rectangle.
A combined image of this kind is often called a spritesheet
Normally, you'll create the spritesheet beforehand, but we'll do it as part of this demo
Then we'll add some rectangles, and tell Codea which part of the image to use for each of them
if we used addRect, Codea provides a function setRectTex to add texture positions for each rectangle
We give it the x,y value of the bottom left corner, and the width and height
All these values need to be a fraction of width and height, ie between 0 and 1
Note - is it better to use a spritesheet or separate meshes? A single mesh draws faster than many separate meshes,
although the difference is so small that you probably won't notice until you have hundreds of rectangles.
Most of the time, it doesn't matter, and you can choose whichever suits you best.
--]]
function setup()
--combine three pictures into one image
img,imgPos=MakeSpriteSheet() --returns the image, and the positions of the three pictures on that image
--now our mesh
m=mesh()
--add three rectangles
m:addRect(200,350,101,171)
m:addRect(300,450,101,171)
m:addRect(400,550,101,171)
m.texture=img --set the texture image
--now we need to use setRectTex to tell Codea which part of the image to use for each rectangle
--the values have to be fractions of width and height, so let's get the width and height of the total image
local w,h=img.width,img.height
--loop through all the rectangles and add texture positions to them
for i=1,3 do
--get the texture positions for this rectangle (give it a short name to make the code below easier to read)
local p=imgPos[i]
--because there are three rectangles created with addRect, we need to tell Codea which one we want
--Codea numbers them 1,2,3... in the order they are created
--we'll use the pictures in the same order as the rectangles, ie the left hand picture will be used
--for the first rectangle, so we can simply use our looping counter i as the rectangle number
--that's why the first item in brackets below is i, it tells Codea which rectangle we want
--the other items are the x,y position of the bottom left corner, and width and height
--all of these must be fractions 0-1, which is why I divide by w and h
m:setRectTex(i, p.pos.x/w, p.pos.y/h, p.w/w, p.h/h)
end
end
function draw()
background(180)
fill(0)
text("These three rectangles\nare on a single mesh",200,500)
m:draw()
--draw the spritesheet as well
text("..using this texture image which has three pictures on it",250,200)
sprite(img,50,50)
end
--the MakeSpriteSheet function creates the image and gives us a table of positions (imgPos) for each picture
--There are three items in imgPos, which we need for setting texture positions in the mesh
--pos (x,y position of bottom left corner),
--w (width) in pixels, and
--h (height) in pixels
function MakeSpriteSheet()
--make a list of the pics we want
pics={"Planet Cute:Character Boy","Planet Cute:Character Pink Girl","Planet Cute:Character Princess Girl"}
--they are all 101 x 171 pixels, and we'll draw them in a row from left to right
--we'll leave a few pixels in between, drawing them 105 pixels apart, so we need an image 315 x171 pixels
local img=image(315,171)
setContext(img) --tell Codea to draw on this image instead of the screen
local imgPos={} --make a table to tell us how to find these images later
--we'll store the bottom left x and y, width, height
--naming the table items makes the code easier to use later
imgPos[1]={pos=vec2(0,0), w=101,h=171}
imgPos[2]={pos=vec2(105,0),w=101,h=171}
imgPos[3]={pos=vec2(210,0),w=101,h=171}
--sprite command usually needs the mid point position of each image, but we only have the bottom left corner
--so we can tell sprite to use that instead
spriteMode(CORNER)
for i=1,3 do
sprite(pics[i],imgPos[i].pos.x,imgPos[i].pos.y)
end
setContext() --stop drawing on the image
return img,imgPos --return the image and the positions of the pictures
end
function PrintExplanation()
output.clear()
print("We can use several different pictures in a mesh, by first combining them into one image")
end
--# Moving_1
--Moving our rectangles
--[[
We have several rectangles in a mesh
Now how do we move them and rotate them, especially if they are all moving differently?
There is a special setRect command for this, if we've added the rectangles with addRect
We'll use the previous example of three images and a spritesheet, in this demo, and move and rotate them
--]]
function setup()
img,imgPos=MakeSpriteSheet() ---same as previous demo
SetupMesh() --put all the mesh code in its own function to keep it tidy
end
function SetupMesh()
--you can do this first part any way you like
rects={} --a table to hold position and movement details for all our rectangles
--note the items are named, to make the code easier to follow when we draw
--pos=current position,
--vel=velocity (is added to pos each time we draw)
--angle=rotation angle,
--rot=change in rotation, ie we add rot to angle when we draw
rects[1] = {pos=vec2(200,350), vel=vec2(0.1,0.2), angle=0, rot=0.1}
rects[2] = {pos=vec2(300,450), vel=vec2(0.1,-0.1), angle=0, rot=-0.3}
rects[3] = {pos=vec2(400,550), vel=vec2(-0.1,-0.2), angle=0, rot=0.2}
--now the mesh
m=mesh()
--add our three rectangles
--we can position them all at 0,0 because we will be changing their positions every frame
--When we change the positions, we will need to tell Codea which rectangle to change
--It is a good idea to store the rectangle number while we are creating it, because in more complex
--projects, we may be working with hundreds of rectangles
--Codea helps us by returning the rectangle number when you use addRect, so we'll store that to use later
for i=1,3 do
rects[i].id = m:addRect(0,0,101,171)
end
m.texture = img --and the texture image
--this next part is the same as the last demo, we set the texture positions for each rectangle
local w,h = img.width,img.height
for i=1,3 do
local p = imgPos[i]
m:setRectTex(rects[i].id, p.pos.x/w, p.pos.y/h, p.w/w, p.h/h)
end
end
function draw()
background(180)
--reposition and rotate all our rectangles using setRect
for i=1,#rects do
local r=rects[i] --put the position details for this rect into r to make the code below easier to read
--setRect parameters are rectangle number, x,y position, width, height, rotation angle in radians
m:setRect(i, r.pos.x, r.pos.y, 101, 171, math.rad(r.angle)) --pretty easy, huh?
--update position and rotation for this rectangle
r.pos = r.pos+r.vel
r.angle = r.angle+r.rot
end
m:draw()
end
function MakeSpriteSheet() --same as the last demo
--make a list of the pics we want
pics={"Planet Cute:Character Boy","Planet Cute:Character Pink Girl","Planet Cute:Character Princess Girl"}
--they are all 101 x 171 pixels, and we'll draw them in a row from left to right
--we'll leave a few pixels in between, drawing them 105 pixels apart, so we need an image 315 x171 pixels
local img=image(315,171)
setContext(img) --tell Codea to draw on this image instead of the screen
local imgPos={} --make a table to tell us how to find these images later
--we'll store the start x, start y, width, height
--naming the table items makes the code easier to use later
imgPos[1]={pos=vec2(0,0), w=101,h=171}
imgPos[2]={pos=vec2(105,0),w=101,h=171}
imgPos[3]={pos=vec2(210,0),w=101,h=171}
--sprite command usually needs the mid point position of each image, but we only have the bottom left corner
--so we can tell sprite to use that instead
spriteMode(CORNER)
for i=1,3 do
sprite(pics[i],imgPos[i].pos.x,imgPos[i].pos.y)
end
setContext() --stop drawing on the image
return img,imgPos --return the image and the positions of the pictures
end
function PrintExplanation()
output.clear()
print("We can easily move and rotate our rectangle images")
end
--# Moving_2
--Moving and rotating a whole mesh
--[[
If you want to move and rotate a whole mesh, maybe with several objects, this is the way to do it
1. When you create your mesh, centre it on (0,0). Your mesh will rotate around a point, usually the centre of the
mesh - make this (0,0). You don't need to make a vertex for it, but all your other points must be positioned
relative to it.
For example, if you have a 100 x 50 rectangle, then if its centre is at (0,0), the four corners will be at
(-50,-25), (50,-25), (50,25), (-50,25)
2. Before drawing, "translate" to the position you want. This redefines the point (0,0) as that position, and if
you now draw your mesh [which is centred on (0,0) ] it will actually draw at the translated position. If it
sounds confusing, imagine you are drawing on a sheet of paper, and the position (0,0) is under your hand,
where it is easiest to draw. You want to draw something in the top left corner, which means stretching and
not drawing as well. So instead, you pull the paper toward you, so the top left corner is under your hand. You
have just "translated" [your drawing position] to the top left corner.
If we couldn't translate like this, we would have to adjust the position of EVERY vertex before drawing - and
when you have meshes with thousands of vertices, that is a lot of work! And if the mesh is rotating...!!
3. After translating, rotate, and then draw. Imagine our piece of paper again. We've pulled it toward us so the
place we want to draw is under our hand. But we want to draw something at an angle of 30 degrees. So we turn
the paper around that point by 30 degrees, so now we can draw the image the right way up.
4. When we're done, reverse the rotation and translation. Codea does this using two oddly named functions
pushMatrix() --stores the current screen settings
popMatrix --puts back the screen settings you stored with pushMatrix
The names push and pop are chosen because the settings are stored in a "stack", and the usual names for
adding to a stack and getting items from it, are "push" and "pop"
This demo shows how to do this using the stick figure from an earlier demo
--]]
function setup()
--create the stick figure from the addRect demo, centred on (0,0)
--the previous stick figure is not centred on (0,0), so how did I know where the middle was?
--I cheated by getting the previous demo to add up all the vertices, and took the average, which was (400,333)
--I subtracted this from all the vertex positions, to centre the figure on (0,0)
m=mesh()
m:addRect(0,17,100,200) --body
m:addRect(-35,-133,30,150)--leg
m:addRect(35,-133,30,150) --leg
m:addRect(0,102,350,30) --arms
m:addRect(0,147,50,60) --head
m:setColors(color(255,255,0))
--we'll make it move slowly across the screen, and rotate
pos = vec2(150,150) --starting position
posChange = vec2(0.3,0.2) --how far it moves each time we draw
angle = 0 --rotation angle
angleChange=0.1 --change in angle each time we draw
end
function draw()
background(200)
pushMatrix() --store screen settings
translate(pos.x,pos.y)
rotate(angle)
m:draw()
popMatrix() --restore screen settings
--update position and angle
pos=pos+posChange
angle=angle+angleChange
end
function PrintExplanation()
output.clear()
print("Moving and rotating a whole mesh is a little different")
end
--# Curves
--Curves (when addRect is not enough - creating your own mesh, vertex by vertex)
--[[
Because meshes use triangles with straight edges, rectangular objects are the easiest to make in 3D (which is why
Minecraft looks the way it does), and addRect is very useful. But what if you need to draw other shapes, like
curves?
VERTICES
You will have to set all the vertices yourself, grouped into triangles, and if you want a smooth curve, you may
need a lot of them.
There is a special triangulate command in Codea that may help. If you give it a table of points which make a shape (the points must be in clockwise or anticlockwise order), it will return a set of triangles that can be used in a mesh.
TEXTURE IMAGE
Then, if you want to attach an image to the mesh, you have to define all the texture positions for each vertex.
Generally, in 2D, it's easiest to use rectangles with curved texture images, to create smooth curves (eg to create a circle, make a picture of a circle and add it as a texture on a mesh rectangle).
THIS DEMO
We'll create a circular set of points - you choose how many points using the parameter slider - and use the
triangulate command to make mesh triangles from these points. Each triangle will be a different colour so you can see how they were created.
You can turn on the Texture option to see an image put onto this circular mesh, instead of colours. This requires
us to set texture positions for each point in our mesh.
--]]
function setup()
parameter.integer("Points",5,100,5,MakePizza)
parameter.boolean("ShowTriangle",false,MakePizza)
parameter.boolean("UseTexture",false,MakePizza)
end
--makes a circular mesh
function MakePizza()
--r is radius, n is number of points
r,n=300,Points
pizza=mesh()
v={}
for i=1,n do
--calculate x,y position of point
local a=2*math.pi*i/n --angle in radians
--yes, time for high school math again!
v[i]=vec2(r*math.sin(a), r*math.cos(a))
end
pizza.vertices=triangulate(v)
--if UseTexture is set, define texture positions for each point in the mesh
if UseTexture then
local img=readImage("Cargo Bot:Starry Background") --pick a square image to put on the circle
--imagine laying the image on top of the circle and resizing it, so the circle just fits inside it
--the middle of the circle - which is the point (0,0) - will be at the middle of the image
--the width of the image will equal the radius of the circle
--the texture positions are fractions (0-1) of the width of the image
--to turn our screen positions into texture positions, this is the adjustment
--texture position of point(x,y) = (0.5,0.5) + (x,y) * 0.5/r
--we start at (0.5,0.5) because this is the texture equivalent of the circle centre of (0,0)
--then we divide by r, and divide by 2 because our radius r is half the width (or height)
--perhaps you can start to see how meshes can get tricky!
t={}
for i=1,pizza.size do --m.size tells us how many vertices there are (same as #pizza.vertices)
--when you store vertices in a mesh, it is done as a vec3, we need a vec2, ie just the x,y part
local p=vec2(pizza.vertices[i].x,pizza.vertices[i].y) --get the vertex position as a vec2
t[i]=vec2(0.5,0.5) + p*0.5/r
end
pizza.texCoords=t
pizza.texture=img
pizza:setColors(color(255)) --remove individual triangle colours
elseif ShowTriangle then --colour each slice(ie each triangle of three vertices) a different colour
colors={}
for i=1,pizza.size,3 do --m.size tells us how many vertices there are (same as #pizza.vertices)
local c=color(math.random(0,255),math.random(0,255),math.random(0,255))
colors[i],colors[i+1],colors[i+2]=c,c,c
end
pizza.colors=colors
pizza.texCoords,pizza.texture=nil,nil --remove texture if we were using one
else --just use once colour for the whole shape
pizza:setColors(color(186, 88, 181, 255))
end
end
function draw()
background(200)
translate(WIDTH/2,HEIGHT/2)
pizza:draw()
end
function PrintExplanation()
output.clear()
print("This demo draws a circle - you can adjust the number of points")
print("The triangulate function is used to make triangles from a set of points")
print("The ShowTriangle parameter gives each triangle a different colour")
print("The UseTexture parameter attaches an image texture")
end
--# 3D
--[[
Some 3D objects have thousands of vertices, which is why most people create them using a
program like Blender, which does the hard work for you.
one of the hardest in 3D is a sphere,
especially if you want to wrap an image around it.
The very basic 3D demo below draws a 3D block. Even with a simple block, you can see how much work it is!
To learn more, look at the 3D demo app.
--]]
function setup()
img=readImage("Platformer Art:Block Brick")
--make it square by trimming off the bottom
img=img:copy(3,3,img.width-6,img.height-6)
b=MakeBlock(30,20,10,img)
r,dr=vec3(0,0,0),vec3(0.2,-0.33,0.27)
end
function draw()
background(150)
perspective() --turn on 3D
camera(-10,10,100,0,0,0)
rotate(r.x,1,0,0)
rotate(r.y,0,1,0)
rotate(r.z,0,0,1)
b:draw()
r=r+dr
end
function MakeBlock(w,h,d) --width,height,depth
local m=mesh()
--define the 8 corners of the block ,centred on (0,0,0)
local fbl=vec3(-w/2,-h/2,d/2) --front bottom left
local fbr=vec3(w/2,-h/2,d/2) --front bottom right
local ftr=vec3(w/2,h/2,d/2) --front top right
local ftl=vec3(-w/2,h/2,d/2) --front top left
local bbl=vec3(-w/2,-h/2,-d/2) --back bottom left (as viewed from the front)
local bbr=vec3(w/2,-h/2,-d/2) --back bottom right
local btr=vec3(w/2,h/2,-d/2) --back top right
local btl=vec3(-w/2,h/2,-d/2) --back top left
--now create the 6 faces of the block, each is two triangles with 3 vertices (arranged anticlockwise)
--so that is 36 vertices
--for each face, I'm going to start at bottom left, then bottom right, then top right, and for the second
--triangle, top right, top left, then bottom left
m.vertices={
fbl,fbr,ftr, ftr,ftl,fbl, --front face
bbl,fbl,ftl, ftl,btl,bbl, --left face
fbr,bbr,btr, btr,ftr,fbr, --right face
ftl,ftr,btr, btr,btl,ftl, --top face
bbl,bbr,fbr, fbr,fbl,bbl, --bottom face
bbr,bbl,btl, btl,btr,bbr --back face
}
--add texture positions, we will use the same image for each face so we only need 4bcorner positions
local bl,br,tr,tl=vec2(0,0),vec2(1,0),vec2(1,1),vec2(0,1)
local t={}
for i=1,6 do --use a loop to add texture positions for each face, as they are the same for each face
t[#t+1]=bl
t[#t+1]=br
t[#t+1]=tr
t[#t+1]=tr
t[#t+1]=tl
t[#t+1]=bl
end
m.texCoords=t
m.texture=img
m:setColors(color(200))
return m
end
function PrintExplanation()
output.clear()
print("A simple 3D block mesh")
end
--# Main
-- MultiStep
function setup()
steps = listProjectTabs()
if steps[1]=="Notes" then table.remove(steps,1) end --remove first tab if named Notes
table.remove(steps) --remove the last tab
startStep()
global = "select a step"
end
function showList()
output.clear()
for i=1,#steps do print(i,steps[i]) end
end
function startStep()
if cleanup then cleanup() end
lastStep=Step or readProjectData("lastStep") or 1
lastStep=math.min(lastStep,#steps)
saveProjectData("lastStep",lastStep)
parameter.clear()
parameter.integer("Step", 1, #steps, lastStep,showList)
parameter.action("Run", startStep)
loadstring(readProjectTab(steps[Step]))()
if PrintExplanation then PrintExplanation() end
setup()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment