Last active
September 11, 2015 16:03
-
-
Save GlueBalloon/9d81558f78f984ca30b1 to your computer and use it in GitHub Desktop.
YojimboDrawWithDice
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
--# Main | |
-- MakeDice | |
function setup() | |
colorPicker = SwipeColorPicker() | |
colorPicker.position.x, colorPicker.position.y = 50, 50 | |
makeDice = MakeDice() | |
usingMiniBufferAndOverlay = false | |
texture = makeDice.mesh.texture | |
colorCoordinates = {} | |
if usingMiniBufferAndOverlay then | |
overlayImage = image(WIDTH/4, HEIGHT/4) | |
else | |
overlayImage = image(WIDTH,HEIGHT) | |
end | |
setUpBufferDisplay() | |
profiler.init() | |
local newX = 400 | |
tween( 90, makeDice.rotate, { x = newX }, { easing = tween.easing.linear, loop = tween.loop.pingpong } ) | |
textMode(CORNER) | |
planeShader = shader(PlaneShader.v, PlaneShader.f) | |
end | |
function setUpBufferDisplay() | |
if usingMiniBufferAndOverlay then | |
bufferImage = image(WIDTH/4, HEIGHT/4) | |
else | |
bufferImage = image(WIDTH, HEIGHT) | |
end | |
local bufferFract = 1 / 6 | |
cameoSize = vec2(WIDTH * bufferFract, HEIGHT * bufferFract) | |
camoPos = vec2((cameoSize.x/2)+20, (cameoSize.y/2)+20) | |
setContext(bufferImage) --fill image with yellow for visibility | |
strokeWidth(0) | |
fill(220, 210, 122, 255) | |
rect(0,0,WIDTH,HEIGHT) | |
setContext() | |
end | |
function draw() | |
-- backingMode(STANDARD) | |
background(69, 119, 104, 255) | |
drawPlane() | |
draw2D() | |
profiler.draw() | |
end | |
function drawPlane() | |
pushMatrix() | |
-- makeDice:setupPerspective() | |
if touching then | |
toggleShader(true) | |
drawClipToBufferPosition(touching) | |
toggleShader(false) | |
-- touching = nil | |
end | |
-- pushMatrix() | |
makeDice:draw() | |
popMatrix() | |
end | |
function draw2D() | |
ortho() | |
viewMatrix(matrix()) | |
-- if #colorCoordinates > 0 then | |
if touching then | |
drawTouchesToTexture() | |
touching = nil | |
end | |
if usingMiniBufferAndOverlay then | |
sprite(overlayImage, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) | |
sprite(bufferImage, camoPos.x, camoPos.y, cameoSize.x, cameoSize.y) | |
end | |
colorPicker:draw() | |
end | |
function drawTouchesToTexture() | |
local textureX, textureY, baseX, baseY, marker, intCoord, fX, fY | |
textureX, textureY = 0, 0 | |
-- for i in ipairs(colorCoordinates) do | |
-- coord = colorCoordinates[i] * 0.25 | |
if usingMiniBufferAndOverlay then | |
coord = touching * 0.25 | |
else | |
coord = touching | |
end | |
intCoord = vec2(math.floor(coord.x), math.floor(coord.y)) | |
baseX, baseY, marker = bufferImage:get(intCoord.x, intCoord.y) | |
if marker == 1 then | |
fX, fY = baseX / 255, baseY / 255 | |
textureX = texture.width * fX | |
textureY = texture.height * fY | |
lastTexX = lastTexX or textureX | |
lastTexY = lastTexY or textureY | |
setContext(texture) | |
stroke(colorPicker.color) | |
strokeWidth(2) | |
line(textureX, textureY, lastTexX, lastTexY) | |
-- ellipse(textureX, textureY, 25) | |
setContext() | |
lastTexX, lastTexY = textureX, textureY | |
end | |
-- end | |
-- text("x: "..textureX..", y: "..math.floor(textureY, 10, 10)) | |
-- end | |
-- colorCoordinates = {} | |
end | |
function touched(touch) | |
if usingMiniBufferAndOverlay then | |
setContext(overlayImage) | |
fill(227, 255, 0, 255) | |
ellipse(touch.x/4, touch.y/4, 3) | |
setContext() | |
end | |
touching = vec2(touch.x, touch.y) | |
if touch.state == ENDED then | |
touching, lastTexX, lastTexY = nil,nil, nil | |
end | |
--[[ | |
if touch.state == MOVING then | |
touching = vec2(touch.x, touch.y) | |
-- table.insert(colorCoordinates, vec2(touch.x, touch.y)) | |
else | |
toggleShader(false) | |
end | |
]] | |
colorPicker:touched(touch) | |
end | |
function drawClipToBufferPosition(touch) | |
setContext(bufferImage) | |
pushMatrix() | |
if usingMiniBufferAndOverlay then | |
clip((touch.x*0.25) - 10, (touch.y*0.25) - 10, 20, 20) | |
else | |
clip(touch.x - 5, touch.y - 5, 10, 10) | |
end | |
makeDice:draw() | |
clip() | |
popMatrix() | |
setContext() | |
end | |
function toggleShader(onOrOff) | |
if onOrOff == true then | |
makeDice.mesh.shader = planeShader | |
else | |
makeDice.mesh.shader = nil | |
end | |
end | |
profiler={} | |
function profiler.init(silent) | |
profiler.del=0 | |
profiler.c=0 | |
profiler.fps=0 | |
profiler.mem=0 | |
if not silent then | |
parameter.watch("profiler.fps") | |
parameter.watch("profiler.mem") | |
end | |
end | |
function profiler.draw() | |
profiler.del = profiler.del + DeltaTime | |
profiler.c = profiler.c + 1 | |
if profiler.c==10 then | |
profiler.fps=profiler.c/profiler.del | |
profiler.del=0 | |
profiler.c=0 | |
profiler.mem=collectgarbage("count", 2) | |
end | |
end | |
--# MakeDice | |
MakeDice = class() | |
function MakeDice:init() | |
self:createDiceMesh() | |
end | |
function MakeDice:draw() | |
self:setupPerspective() | |
self.mesh:draw() | |
end | |
function MakeDice:createDiceMesh() | |
self.mesh=Mesh7().blk.mesh | |
self.centre=vec3(0,0,0) | |
self.rotate=vec3(45,0,20) | |
self.size=vec2(6,6,0) | |
strokeWidth(10) | |
stroke(255, 0, 0, 255) | |
self.img=self.mesh.texture | |
self.shaderImg=image(self.img.width, self.img.height) | |
end | |
function MakeDice:setupPerspective() | |
perspective() | |
camera(0,0,900,0,0,-1) | |
scale(self.size.x, self.size.y,0) | |
translate(self.centre.x, self.centre.y, self.centre.z) | |
rotate(self.rotate.x,1,0,0) | |
rotate(self.rotate.y,0,1,0) | |
rotate(self.rotate.z,0,0,1) | |
end | |
PlaneShader = { | |
v = [[ | |
uniform mat4 modelViewProjection; | |
attribute vec4 position; | |
attribute vec2 texCoord; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
f = [[ | |
precision highp float; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
lowp float marker = 1.0 /255.0; | |
gl_FragColor = vec4(vTexCoord.x,vTexCoord.y,marker,1.0); | |
} | |
]]} | |
--# Mesh7_aka_IgnatzDice | |
--Mesh7 | |
--[[ | |
In this demo, I've added a texture from the internet to make the dice more interesting | |
I've also added a fake highlight to the dice spots to give them some depth | |
Changes are marked CHANGED | |
No changes to Block, so I just used Block3 from the previous demo | |
--]] | |
Mesh7 = class() | |
function Mesh7:init(x) | |
self.FieldOfView=45 | |
self.CamHeight=300 | |
self.Angle=0 | |
local sideSize=50 | |
local imgData={0,0,1,1/6, 0,1/6,1,2/6, 0,2/6,1,3/6, 0,3/6,1,4/6, 0,4/6,1,5/6, 0,5/6,1,1} | |
local largerImage = image(WIDTH/2,HEIGHT/2) | |
setContext(largerImage) | |
sprite("Cargo Bot:Opening Background", WIDTH/4, HEIGHT/4, WIDTH/2, HEIGHT/2) | |
setContext() | |
local img2 = largerImage | |
self.blk=Block3(sideSize,sideSize,sideSize,img2,imgData) | |
end | |
function Mesh7:draw() | |
-- First arg is FOV, second is aspect | |
perspective(self.FieldOfView, WIDTH/HEIGHT) | |
-- Position the camera up and back, look at origin | |
camera(0,self.CamHeight,-300, 0,0,0, 0,1,0) | |
pushMatrix() | |
rotate(self.Angle,0,1,0) | |
self.blk:draw() | |
popMatrix() | |
end | |
function Mesh7:touched(touch) | |
local xx,yy=math.floor(touch.x*3/WIDTH),math.floor(touch.y*3/HEIGHT) | |
if xx==0 then self.Angle=self.Angle-15 elseif xx==2 then self.Angle=self.Angle+15 end | |
if yy==0 then self.CamHeight=self.CamHeight-50 elseif yy==2 then self.CamHeight=self.CamHeight+50 end | |
end | |
--Block3 | |
--[[ | |
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 either | |
(a) a texture based on an image, so it is visible | |
(b) a table of colors, one color per side | |
In the case of (a), 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 | |
NB this has been extended to you can specify the part of the image to use for each face separately.In this case, you need to specify four numbers per face, or 24 in total | |
--]] | |
Block3 = class() --taken from 3D lab project | |
--t=either string name of image, or an array of 6 colors, one per block face | |
function Block3:init(w,h,d,t,r) --width,height,depth,texture/colors, (optional) texture range (see above) | |
self.width=w | |
self.height=h | |
self.depth=d | |
if type(t)=="string" or type(t)=="userdata" then --CHANGED to trap cases where we provide an actual image | |
self.type="Image" --CHANGED | |
self.tex=t --string name of an image in the library, or the image itself | |
--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 | |
else --we are given a table of colors, one per face | |
self.type="Colors" --CHANGED | |
self.colrs=t | |
end | |
self.mesh=self:createBlock() | |
end | |
function Block3: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 or colors | |
if self.type=="Image" then --texture --CHANGED | |
if #self.texR==4 then | |
--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 | |
self.texCoords = {} | |
for i=1,6 do | |
table.insert(self.texCoords,BL) | |
table.insert(self.texCoords,BR) | |
table.insert(self.texCoords,TR) | |
table.insert(self.texCoords,BL) | |
table.insert(self.texCoords,TR) | |
table.insert(self.texCoords,TL) | |
end | |
else --user has specified image fractions for each face | |
self.texCoords = {} | |
local u=0 | |
for i=1,6 do | |
local BL=vec2(self.texR[u+1],self.texR[u+2]) --bottom left | |
local BR=vec2(self.texR[u+3],self.texR[u+2]) --bottom right | |
local TR=vec2(self.texR[u+3],self.texR[u+4]) --top right | |
local TL=vec2(self.texR[u+1],self.texR[u+4]) --top left | |
u = u + 4 | |
table.insert(self.texCoords,BL) | |
table.insert(self.texCoords,BR) | |
table.insert(self.texCoords,TR) | |
table.insert(self.texCoords,BL) | |
table.insert(self.texCoords,TR) | |
table.insert(self.texCoords,TL) | |
end | |
end | |
else --colors, one per face | |
self.texColrs={} | |
for i=1,6 do | |
for j=1,6 do | |
table.insert(self.texColrs,self.colrs[i]) | |
end | |
end | |
end | |
--put it all together | |
local ms = mesh() | |
ms.vertices = cubeverts | |
ms.texture = self.tex | |
if self.texCoords~=nil then ms.texCoords = self.texCoords end | |
ms:setColors(255,255,255,255) | |
if self.texColrs~=nil then ms.colors=self.texColrs end | |
return ms | |
end | |
function Block3:draw() | |
self.mesh:draw() | |
end | |
--# SwipeColorPicker | |
SwipeColorPicker = class() | |
function SwipeColorPicker:init(x) | |
self.hsv = vec4(0.5,1.0,1.0,1.0) | |
self.color = self:updateRGB() | |
self.size = 80 | |
self.position = vec2(200,200) | |
self.active = false | |
end | |
function SwipeColorPicker:swipeHorizontal(amount) | |
amount = amount / WIDTH | |
self:hsvShift(amount, 0) | |
end | |
function SwipeColorPicker:hsvShift(h,v) | |
self.hsv.x = self.hsv.x + h | |
if self.hsv.y < 1 then | |
self.hsv.y = self.hsv.y - v | |
if self.hsv.y < 0 then | |
self.hsv.y = 0 | |
end | |
if self.hsv.y > 1 then | |
self.hsv.z = self.hsv.z - math.fmod(self.hsv.y, 1) | |
self.hsv.y = 1 | |
end | |
else | |
self.hsv.z = self.hsv.z + v | |
if self.hsv.z > 1 then | |
self.hsv.y = self.hsv.y - math.fmod(self.hsv.z, 1) | |
self.hsv.z = 1 | |
end | |
end | |
self:updateRGB() | |
end | |
function SwipeColorPicker:swipeVertical(amount) | |
amount = amount / HEIGHT * 3 | |
self:hsvShift(0, amount) | |
end | |
function SwipeColorPicker:draw() | |
-- Codea does not automatically call this method | |
-- background(self.color) | |
pushStyle() | |
ellipseMode(CENTER) | |
if self.active then | |
fill(197, 167, 167, 109) | |
ellipse(self.position.x, self.position.y-0.5, self.size+6) | |
ellipse(self.position.x, self.position.y+1.5, self.size+6) | |
end | |
-- the bezels | |
fill(self.color) | |
ellipse(self.position.x, self.position.y + 2, self.size) | |
fill(0, 0, 0, 179) | |
ellipse(self.position.x, self.position.y + 2, self.size) | |
fill(self.color) | |
ellipse(self.position.x, self.position.y - 2, self.size) | |
fill(255, 255, 255, 145) | |
ellipse(self.position.x, self.position.y - 2, self.size) | |
-- the color | |
fill(self.color) | |
ellipse(self.position.x, self.position.y, self.size) | |
popStyle() | |
end | |
function SwipeColorPicker:touched(touch) | |
local insideCircle | |
if touch.state == BEGAN then | |
local radius = self.size * 0.5 | |
local closeEnoughX = math.abs(touch.x-self.position.x) < radius | |
local closeEnoughY = math.abs(touch.y-self.position.y) < radius | |
if closeEnoughX and closeEnoughY then | |
self.active = true | |
end | |
end | |
if self.active then | |
if math.abs(touch.deltaX) > math.abs(touch.deltaY) then | |
self:swipeHorizontal(touch.deltaX) | |
else | |
self:swipeVertical(touch.deltaY) | |
end | |
if touch.state == ENDED then | |
self.active = false | |
end | |
end | |
end | |
function SwipeColorPicker:updateRGB() | |
self.color = color(self:hsvToRGB(self.hsv.x, self.hsv.y,self.hsv.z)) | |
return self.color | |
end | |
function SwipeColorPicker:hsvToRGB(h, s, v) | |
--thanks to SkyTheCoder on the Codea forums | |
local r, g, b | |
local i = math.floor(h * 6) | |
local f = h * 6 - i | |
local p = v * (1 - s) | |
local q = v * (1 - f * s) | |
local t = v * (1 - (1 - f) * s) | |
local switch = i % 6 | |
if switch == 0 then | |
r = v | |
g = t | |
b = p | |
elseif switch == 1 then | |
r = q | |
g = v | |
b = p | |
elseif switch == 2 then | |
r = p | |
g = v | |
b = t | |
elseif switch == 3 then | |
r = p | |
g = q | |
b = v | |
elseif switch == 4 then | |
r = t | |
g = p | |
b = v | |
elseif switch == 5 then | |
r = v | |
g = p | |
b = q | |
end | |
return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment