Created
April 9, 2013 14:38
-
-
Save dermotbalson/5346193 to your computer and use it in GitHub Desktop.
15. Mesh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
This demo is where it starts to get more complicated, even though we'll only create | |
a 3D block with just 8 triangles. There are several parts to this | |
1. creating 3D objects | |
2. placing them in 3D space | |
3. choosing our viewpoint in 3D space | |
CREATING THE BLOCK | |
I've put the code that creates the block in its own class underneath, so you can use it easily | |
in your own projects. (Trust me, you will never want to write this code yourself. It took me | |
about four hours just to understand it!). | |
Creation of the block is explained in that class. In this section, I'm going to talk about everything else | |
THE SCREEN CO-ORDINATES | |
First, when you draw in 3D, your screen no longer starts at 0,0 at lower left. Instead, the zero point, | |
or (0,0,0) - 3D, remember - is in the middle of your screen. | |
First, we need to set our own viewpoint. | |
PERSPECTIVE | |
Perspective is about what you can see, and has two parts | |
* Field of view is about how much of the scene you can see at once, in degrees. A setting of 20 zooms right in, while 90 takes you further out and see much more. Think of it as the width of your view. A good setting is 45. | |
* Aspect is the width to height ratio, and is normally set to the same ratio as the screen, WIDTH/HEIGHT | |
Having decided this, we set it like so | |
perspective(45, WIDTH/HEIGHT) | |
CAMERA | |
Having decided what we can see, we need to choose where we're going to see it from. | |
The camera function has three sets of x,y,z values | |
First, the location of your "eye" in space | |
x - Typically, you want to be looking straight at your screen, so you want x to be in the middle, which is 0 | |
y - If you want to look down on your picture, set y to a positive value, and vice versa | |
z - You won't want to be in the picture, so you should probably make z negative so it moves towards you | |
Next, what you are looking at, as a point in space. We'll use 0,0,0 | |
Finally, the viewer's stance. The normal position would be standing, ie vertical in the y direction, so you'd set 0,1,0. If you wanted to see it from a lying down position you could set 1,0,0. | |
So here is an example of the final settings | |
camera(0,300,-300, 0,0,0, 0,1,0) | |
DRAWING THE BLOCK | |
Having created the block, if we just draw it, it will appear in the middle of the screen, front face forward. | |
And that's what we'll do initially. | |
CHANGING THE OBJECT | |
There is something else you can alter as well, and that is rotating the object through any of the x,y or z axes, during the drawing process. This is done below to illustrate. | |
MAKING IT CHANGE AS YOU TOUCH THE SCREEN | |
The code at the bottom reacts to touches. If you touch left or right, it changes the angle of rotation (which rotates the block). If you touch high or low, it changes the camera height (y axis). | |
--]] | |
function setup() | |
FieldOfView=45 | |
CamHeight=300 | |
Angle=0 | |
--I'm using some art, and it has rounded edges, which will make my block look funny | |
--so I'll leave out the first and last 5% along the x and y axis | |
blk=Block(150,100,50,"Platformer Art:Block Brick",{.05,.05,.95,.95}) | |
end | |
function draw() | |
background(0) | |
-- First arg is FOV, second is aspect | |
perspective(FieldOfView, WIDTH/HEIGHT) | |
-- Position the camera up and back, look at origin | |
camera(0,CamHeight,-300, 0,0,0, 0,1,0) | |
pushMatrix() | |
rotate(Angle,0,1,0) | |
blk:draw() | |
-- Restore orthographic projection | |
ortho() | |
-- Restore the view matrix to the identity | |
viewMatrix(matrix()) | |
output.clear() | |
print("We play with one 3D block") | |
print("Touching left/right rotates block\nTouching high/low changes camera height") | |
popMatrix() | |
end | |
function touched(touch) | |
local xx,yy=math.floor(touch.x*3/WIDTH),math.floor(touch.y*3/HEIGHT) | |
if xx==0 then Angle=Angle-15 elseif xx==2 then Angle=Angle+15 end | |
if yy==0 then CamHeight=CamHeight-50 elseif yy==2 then CamHeight=CamHeight+50 end | |
end | |
--Block | |
--[[ | |
This class creates a rectangular 3D block with 12 triangles covered with a single texture | |
This is about as simple as it gets, and there is still a lot of code | |
We tell the class how big we want the block to be, ie width, depth and height | |
We also give it a texture based on an image, so it is visible | |
We don't always want to use the whole image, so we provide an optional array (parameter r below) | |
that lets the user specify the start and end x,y position | |
eg if you only want to use the part of the image from x=0.2 to .6, and y=0.1 to .9, then you | |
pass in an array {0.2,0.1,0.6,0.9} ie starting x,y position, then ending x,y position | |
If you omit this array then the range 0,1 will be used | |
--]] | |
Block = class() --taken from 3D lab project | |
function Block:init(w,h,d,t,r) --width,height,depth,texture, (optional) texture range (see above) | |
self.width=w | |
self.height=h | |
self.depth=d | |
self.tex=t --string name of an image in the library | |
--if no limits specified on which part of image to draw, set to 0,1 | |
if r~=nil then self.texR=r else self.texR={0,0,1,1} end | |
self.blk=self:createBlock() | |
end | |
function Block:createBlock() | |
-- all the unique vertices that make up a block | |
--There are only 8 corners in a cube - we define them as vertices | |
--all measurements are taken from the centre of the block | |
--so bottom left front has x of -1/2 width, y of -1/2 height, and z of 1/2 depth | |
local w,h,d=self.width,self.height,self.depth | |
local v = { | |
vec3(-0.5*w, -0.5*h, 0.5*d), -- Left bottom front | |
vec3( 0.5*w, -0.5*h, 0.5*d), -- Right bottom front | |
vec3( 0.5*w, 0.5*h, 0.5*d), -- Right top front | |
vec3(-0.5*w, 0.5*h, 0.5*d), -- Left top front | |
vec3(-0.5*w, -0.5*h, -0.5*d), -- Left bottom back | |
vec3( 0.5*w, -0.5*h, -0.5*d), -- Right bottom back | |
vec3( 0.5*w, 0.5*h, -0.5*d), -- Right top back | |
vec3(-0.5*w, 0.5*h, -0.5*d), -- Left top back | |
} | |
-- now construct a block out of the vertices above | |
--there are 6 sides, each made up of 2 triangles, each with 3 vertices | |
--so we need to assign 36 vertices in total | |
--the 8 vectors are assigned to the 8 corners as follows | |
--1,2,3,4 anticlockwise round front starting bottom left | |
--5,6,7,8 clockwise round back starting bottom right (assuming you are looking at the back) | |
--the first three vectors below use vectors 1,2 and 3. If you look above, you'll | |
--see those are for left and right of bottom front, plus right top of front | |
--so this is the right hand triangle for the front side | |
local cubeverts = { | |
-- Front, Right, Back, Left, Top, Bottom | |
v[1], v[2], v[3], v[1], v[3], v[4], | |
v[2], v[6], v[7], v[2], v[7], v[3], | |
v[6], v[5], v[8], v[6], v[8], v[7], | |
v[5], v[1], v[4], v[5], v[4], v[8], | |
v[4], v[3], v[7], v[4], v[7], v[8], | |
v[5], v[6], v[2], v[5], v[2], v[1], | |
} | |
-- add texture | |
--create vectors to be assigned to four corners of each face | |
local BL=vec2(self.texR[1],self.texR[2]) --bottom left | |
local BR=vec2(self.texR[3],self.texR[2]) --bottom right | |
local TR=vec2(self.texR[3],self.texR[4]) --top right | |
local TL=vec2(self.texR[1],self.texR[4]) --top left | |
-- apply the texture coordinates to each triangle | |
--we need to add them to each of the vertexes in the same order as above | |
--that means on each face we need to add them in the order BL, BR, TR, BL, TR, TL | |
local cubetexCoords = {} | |
for i=1,6 do | |
table.insert(cubetexCoords,BL) | |
table.insert(cubetexCoords,BR) | |
table.insert(cubetexCoords,TR) | |
table.insert(cubetexCoords,BL) | |
table.insert(cubetexCoords,TR) | |
table.insert(cubetexCoords,TL) | |
end | |
--put it all together | |
local ms = mesh() | |
ms.vertices = cubeverts | |
ms.texture = self.tex | |
ms.texCoords = cubetexCoords | |
ms:setColors(255,255,255,255) | |
return ms | |
end | |
function Block:draw() | |
self.blk:draw() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment