--# Icosphere
Icosphere = class()
function Icosphere:init()
-- Initial stuff
self.faces = {}
self.vertices = {}
self.mesh = mesh()
self.mesh.texture = "Planet Cute:Grass Block"
self.iterationLevel = level
self:initVertices()
self:initFaces()
-- Subdivide
for i = 1, self.iterationLevel do
self:subdivideFaces()
end
-- Fix mesh verts
local ti = table.insert
local cl = color
local r = math.random
local ve = {}
local c = {}
local tx = {}
local main = cl(r(0,255),r(0,255),r(0,255))
for i,v in ipairs(self.faces) do
-- Change color slightly from original
clr = cl(main.r+r(-50,50),main.g+r(-50,50),main.b+r(-50,50))
-- Vertices
ti(ve,v[1])
ti(ve,v[2])
ti(ve,v[3])
-- Colors
ti(c,clr)
ti(c,clr)
ti(c,clr)
-- Texture (disabled for now)
--ti(tx,vec2(0,0))
--ti(tx,vec2(1,0))
--ti(tx,vec2(0.5,0.5))
end
self.mesh.vertices = ve
self.mesh:setColors(color(60,150,40))
self.mesh.colors = c
-- self.mesh.texCoords = tx -- Uncomment this line to show an image on each of the faces
end
function Icosphere:initVertices()
local t = (1 + math.sqrt(5)) / 2
local p = vec3
local function v(...)
table.insert(self.vertices,p(...):normalize())
end
v(-1, t, 0)
v( 1, t, 0)
v(-1,-t, 0)
v( 1,-t, 0)
v( 0,-1, t)
v( 0, 1, t)
v( 0,-1,-t)
v( 0, 1,-t)
v( t, 0,-1)
v( t, 0, 1)
v(-t, 0,-1)
v(-t, 0, 1)
end
function Icosphere:subdivideFaces()
local faces2 = {}
local function gm(v,v2)
return ((v+v2)/2):normalize()
end
local ti = table.insert
for i,tri in ipairs(self.faces) do
local a = gm(tri[1],tri[2])
local b = gm(tri[2],tri[3])
local c = gm(tri[3],tri[1])
ti(faces2,{tri[1],a,c})
ti(faces2,{tri[2],b,a})
ti(faces2,{tri[3],c,b})
ti(faces2,{a,b,c})
end
self.faces = faces2
end
function Icosphere:initFaces()
local function f(...)
table.insert(self.faces,self:triangleIndices(...))
end
f(1,12,6)
f(1,6,2)
f(1,2,8)
f(1,8,11)
f(1,11,12)
f(2,6,10)
f(6,12,5)
f(12,11,3)
f(11,8,7)
f(8,2,9)
f(4,10,5)
f(4,5,3)
f(4,3,7)
f(4,7,9)
f(4,9,10)
f(5,10,6)
f(3,5,12)
f(7,3,11)
f(9,7,8)
f(10,9,2)
end
function Icosphere:triangleIndices(i1,i2,i3)
return {
self.vertices[i1],
self.vertices[i2],
self.vertices[i3]
}
end
function Icosphere:draw()
pushMatrix()
scale(Zoom)
self.mesh:draw()
popMatrix()
end
--# Main
-- 3D Sphere
-- Use this function to perform your initial setup
function setup()
print("Hello Spheres!")
level = 0
i = Icosphere()
parameter.integer("level",0,10,1,function()
local pstr = string.format("Creating %d faces...",20*4^level)
if level > 4 then
pstr = pstr.." (may take a while)"
end
print(pstr)
i:init() -- init again with new level
collectgarbage()
end)
parameter.integer("Zoom",1,40)
slide = vec2(0,0)
camX, camY, camZ = -50,-50,-50
rotMatrix = matrix()
end
-- This function gets called once every frame
function draw()
-- This sets a light background color
background(226, 226, 235, 255)
-- Do your drawing here
perspective(45)
camera(camX,camY,camZ,0,0,0,1,0,0)
pushMatrix()
applyMatrix(rotMatrix)
i:draw()
popMatrix()
if slide:len()>0 then
rotMatrix = rotMatrix:rotate(slide:len(),slide.x,slide.y,0)
end
slide = slide * 0.9
end
function touched(touch)
slide.y = touch.deltaY
slide.x = touch.deltaX
end
-- Useless functions (did not work for rotation)
function rotateZ(x,y,z,r)
local l = math.sqrt(x^2+y^2)
local nx = x*math.cos(r) - y*math.sin(r)
local ny = y*math.cos(r) + x*math.sin(r)
return nx,ny,z
end
function rotateY(x,y,z,r)
local l = math.sqrt(x^2+y^2)
local nz = z*math.cos(r) - x*math.sin(r)
local nx = x*math.cos(r) + z*math.sin(r)
return nx,y,nz
end
function rotateX(x,y,z,r)
local l = math.sqrt(x^2+y^2)
local ny = y*math.cos(r) - z*math.sin(r)
local nz = z*math.cos(r) + y*math.sin(r)
return x,ny,nz
end
Unfortunately, rotation in 3D is not as easy as it seems. Neither is lighting. I tried shaders, but everything turns out black or invisible (because my understanding of shaders is limited). I wanted to make a globe from which points could be selected, for level selection and other purposes.
Final questions:
- How can I make touch rotation easier (for the user)?
- Is there a simple shader to render my sphere mesh as a wireframe?
- Are there any good 3d lighting tutorials out there (possibly for Codea)?
Thanks in advance!