You can easily implement a basic lighting by multiplying the color with the cosine of the angle between a light direction and the normal in a vertex. Add some ambient light and voila…
--# Main
-- 3D example
-- Use this function to perform your initial setup
function setup()
print("Hello World!")
parameter("FieldOfView", 10, 140, 20)
parameter("Ambient", 0, 1, 0.4)
scn=Scene()
scn:add(Sphere(30,vec3(0,0,0),"SpaceCute:Background"))
zoom3d=Zoom3D(120,20,vec3(0,0,0))
ambient=nil
end
function touched(touch)
zoom3d:touched(touch)
end
-- This function gets called once every frame
function draw()
if (ambient~=Ambient) then
ambient=Ambient
scn:setLighting(ambient)
end
zoom3d:draw()
-- This sets a dark background color
background(0, 0, 0, 255)
-- Do your 3D drawing here
scn:draw()
-- Restore orthographic projection
ortho()
-- Restore the view matrix to the identity
viewMatrix(matrix())
-- Draw a label at the top of the screen
fill(255)
font("MyriadPro-Bold")
fontSize(30)
text("3D example", WIDTH/2, HEIGHT - 30)
end
--# Sphere
Sphere = class()
function Sphere:init(size,pos, texture,colour,lightDir)
-- you can accept and set parameters here
self.size = size or 1
self.pos = pos or vec3(0,0,0)
self.color = colour or color(255, 255, 255, 255)
-- all the unique vertices that make up a cube
local vertices = {
vec3(-1, 0, 0),
vec3( 1, 0, 0),
vec3( 0, 1, 0),
vec3( 0, -1, 0),
vec3( 0, 0, 1),
vec3( 0, 0, -1)
}
self.verts = {
vertices[1], vertices[5], vertices[3],
vertices[3], vertices[5], vertices[2],
vertices[2], vertices[5], vertices[4],
vertices[4], vertices[5], vertices[1],
vertices[1], vertices[3], vertices[6],
vertices[3], vertices[2], vertices[6],
vertices[2], vertices[4], vertices[6],
vertices[4], vertices[1], vertices[6]
}
for i=1,3 do
self:subdivide()
end
self.texCoords ={}
for i=1,#self.verts do
local v=math.acos(-self.verts[i].y)/math.pi
local u= ( math.acos(-self.verts[i].x/(math.sin(v*math.pi))) ) / (2*math.pi)
if 1.0 - math.abs(self.verts[i].y) <0.05 then
u=0.5
end
if self.verts[i].z>0 then
u=1-u;
end
table.insert(self.texCoords,vec2(u*0.94+0.03,v*0.45+0.24))
end
self.mesh = mesh()
self.mesh.vertices = self.verts
--sprite("Planet Cute:Wood Block")
self.mesh.texture = texture
self.mesh.texCoords = self.texCoords
self:setLighting(ambient,lightDir)
end
function Sphere:setLighting(ambient,lightDir)
ambient = ambient or 0.4
lightDir = lightDir or vec3(2,1,1)
local vcolors = {}
lightDir=lightDir:normalize()
for i=1,#self.verts do
local f=ambient
local n=self.verts[i]:normalize()
local i1=n:dot(lightDir)
if i1>0 then
f = f + i1*(1.0-ambient)
end
table.insert(vcolors,color(self.color.r*f,self.color.g*f,self.color.b*f,self.color.a))
end
self.mesh.colors=vcolors
end
function Sphere:subdivide()
local verts={}
for i=1,#self.verts,3 do
local arr={self.verts[i],self.verts[i+1],self.verts[i+2]}
table.insert(arr,(arr[1]+arr[2]):normalize())
table.insert(arr,(arr[2]+arr[3]):normalize())
table.insert(arr,(arr[1]+arr[3]):normalize())
table.insert(verts,arr[1])
table.insert(verts,arr[4])
table.insert(verts,arr[6])
table.insert(verts,arr[4])
table.insert(verts,arr[2])
table.insert(verts,arr[5])
table.insert(verts,arr[5])
table.insert(verts,arr[3])
table.insert(verts,arr[6])
table.insert(verts,arr[4])
table.insert(verts,arr[5])
table.insert(verts,arr[6])
end
self.verts=verts
end
function Sphere:draw()
pushMatrix()
translate(self.pos.x,self.pos.y,self.pos.z)
scale(self.size/2,self.size/2,self.size/2)
self.mesh:draw()
popMatrix()
end
function Sphere:touched(touch)
-- Codea does not automatically call this method
end
--# Scene
Scene = class()
function Scene:init()
self.objs = {}
end
function Scene:add(obj)
self.objs[obj]=1
end
function Scene:remove(obj)
self.objs[obj]=nil
end
function Scene:setLighting(ambient,lightDir)
for obj,_ in pairs(self.objs) do
obj:setLighting(ambient,lightDir)
end
end
function Scene:draw()
for obj,_ in pairs(self.objs) do
obj:draw()
end
end