Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --# 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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement