Here is my class i use to compute normals
Vec3sort = class()
function Vec3sort:init()
end
function Vec3sort:blend(ms,color1)
local i=1
local newColors = {}
local r,g,b,a,c,c1
while i<=#(ms.colors) do
c = ms:color(i)
c1 = color1[i]
c.r = c.r * c1.r / 255
c.g = c.g * c1.g / 255
c.b = c.b * c1.b / 255
newColors[i] = c
--print(c1)
i = i + 1
end
return newColors
end
function Vec3sort:shade(t,lightDir,min,max,slope)
local center, amplitude = (max+min)/2, (max-min)/2
local i=1
local a
local newColors = {}
local steepness = slope or 2
while i<=#t do
-- shadow
a = - t[i]:dot(lightDir) * steepness
if a>1 then a =1 elseif a<-1 then a=-1 end
a = center + amplitude*a
-- set color
a = color(a,a,a,alpha)
newColors[i] = a
i = i + 1
end
return newColors
end
function Vec3sort:verticeNormals(t)
local out = {}
local s = Vec3sort:intSort(t)
local nf = Vec3sort:faceNormals(t)
local i=1
local imax = #s
local n,v,j,i0,i1,k,p
-- init loop
j=s[i].x ; v = nf[ s[i].y ] ; n=1 ; i0=i ; i1=i
i = i + 1
while i<= imax do
if s[i].x == j then -- this is the same vector
-- accumulate
v = v + nf[ s[i].y ]
n = n + 1
i1 = i
end
if s[i].x ~= j or i==imax then -- this is the same vector
-- compute normal
v = v/n
v = v:normalize()
-- save last normal
for k=i0,i1 do
out[s[k].y] = v
end
-- init loop
j=s[i].x ; v = nf[ s[i].y ] ; n=1 ; i0=i ; i1=i
end
i = i + 1
end
--[[
-- verification
for i=1,#t do
v = out[i]
print(v.x.." "..v.y.." "..v.z)
end
]]
return out
end
local clock = os.clock
function Vec3sort:faceNormals(t)
local out = {}
local imax = math.floor(#t/3)
local i=1
local v1,v2,v3,a,b,normal
local t1 = clock()+1/40
while i<= imax do
-- get triangle vertices
v1 = t[1 + i*3-3]
v2 = t[1 + i*3-2]
v3 = t[1 + i*3-1]
-- compute normal vector
a = v1-v2
b = v1-v3
normal = a:cross(b):normalize()
-- compute normal vector orientation
a = (v1+v2+v3)/3
b = a:dot(normal)
if b>0 then b=1 else b=-1 end
normal = normal * b
-- write result
out[1 + i*3-3] = normal
out[1 + i*3-2] = normal
out[1 + i*3-1] = normal
i = i + 1
end
return out
end
local floor = math.floor
function Vec3sort:intSort(t)
-- t is a table ov vec3
local s = {}
local i
for i=1,#t do
s[i] = vec4(t[i].x,t[i].y,t[i].z,i)
end
local function compVec3(a,b)
local out = false
if floor(a[1])<floor(b[1]) then out = true
elseif floor(a[1])==floor(b[1]) then
if floor(a[2])<floor(b[2]) then out = true
elseif floor(a[2])==floor(b[2]) then
if floor(a[3])<floor(b[3]) then out = true end
end
end
return out
end
table.sort(s,compVec3)
local v
--[[
for i=1,#s do
v = s[i]
print(v.x.." "..v.y.." "..v.z.." "..v.w)
end
]]
local out={}
local n = 1
out[1] = vec2(n,s[1].w)
for i=2,#s do
if compVec3(s[i-1],s[i]) then n = n + 1 end
out[i] = vec2(n,s[i].w)
end
--[[
for i=1,#s do
v = out[i]
print(v.x.." "..v.y)
end
]]
return out
end
function Vec3sort:sort(t)
-- t is a table ov vec3
local s = {}
local i
for i=1,#t do
s[i] = vec4(t[i].x,t[i].y,t[i].z,i)
end
local function compVec3(a,b)
local out = false
if a[1]<b[1] then out = true
elseif a[1]==b[1] then
if a[2]<b[2] then out = true
elseif a[2]==b[2] then
if a[3]<b[3] then out = true end
end
end
return out
end
table.sort(s,compVec3)
local v
--[[
for i=1,#s do
v = s[i]
print(v.x.." "..v.y.." "..v.z.." "..v.w)
end
]]
local out={}
local n = 1
out[1] = vec2(n,s[1].w)
for i=2,#s do
if compVec3(s[i-1],s[i]) then n = n + 1 end
out[i] = vec2(n,s[i].w)
end
--[[
for i=1,#s do
v = out[i]
print(v.x.." "..v.y)
end
]]
return out
end
In the setup i create a ‘normals’ object to which i pass the mesh vertice table to compute the normals (smooth normals here). You can also use faceNormals() if you want not smooth shadows
normals = Vec3sort()
nor = normals:verticeNormals(obj.ms.vertices)
Hope that helps you…