diff --git a/all.lua b/all.lua index 3834ea8af129a952137c66671170349b14bb4b72..1ad8f371e6959a5df8927cad158e9b648fb64167 100644 --- a/all.lua +++ b/all.lua @@ -3,3 +3,4 @@ require("kara3d.matrix") require("kara3d.quaternion") require("kara3d.transform") require("kara3d.shape") +require("kara3d.light") diff --git a/light.lua b/light.lua new file mode 100644 index 0000000000000000000000000000000000000000..2dce32a647d040c7cba52f079953062ccc8a3c98 --- /dev/null +++ b/light.lua @@ -0,0 +1,24 @@ +require("kara3d.vector") +require("kara3d.matrix") +require("kara3d.quaternion") +require("kara3d.transform") +require("utils") + + +light = {class = "light"} +light.__index = light + + +-- Creates a new light with transform t and RGB value diff and spec +function light.new(t, diff, spec) + local l = {transform = t, diffuse = diff or {255, 255, 255}, specular = spec or {255, 255, 255}} + setmetatable(l, light) + return l +end + + + +-- Clones this light +function light:clone() + return light.new(self.transform, table.copy(self.diffuse), table.copy(self.specular)) +end \ No newline at end of file diff --git a/shape.lua b/shape.lua index 64ef73cf6cb85d972ce2bf855c8332aee960c4ea..8043306f1018ffdcbb36b8562dbe1a2c666dbc86 100644 --- a/shape.lua +++ b/shape.lua @@ -2,6 +2,7 @@ require("kara3d.vector") require("kara3d.matrix") require("kara3d.quaternion") require("kara3d.transform") +require("kara3d.lights") require("utils") re = require("re") @@ -13,13 +14,22 @@ shape.__index = shape face = {class = "face"} face.__index = face --- Creates a new shape with transform t and faces f -function shape.new(t, f) - local s = {transform = t, faces = f or {}} - setmetatable(s, shape) - return s +material = {class = "material"} +material.__index = material + + + +function material.new(a, d, sp, sh) + local m = {ambient = a or vector.new(3, {1, 1, 1}), + diffuse = d or vector.new(3, {1, 1, 1}), + specular = sp or vector.new(3, {1, 1, 1}), + shininess = sh or 1} + setmetatable(m, material) + return m end + + -- Creates a new face with vertices c, normal n and tags t function face.new(v, n, t) local f = {vertices = v or {}, normal = n or -vector.cardinal(3, 3), tags = t} @@ -27,6 +37,51 @@ function face.new(v, n, t) return f end +function face:mean() + sum = vector.zero(3) + for i = 1, #self.vertices do + sum = sum + self.vertices[i] + end + return (1/(#self.vertices)) * sum +end + + +function face:shade(mat, lights, ambient) + local Ka = mat.ambient + local Kd = mat.diffuse + local Ks = mat.specular + local shine = mat.shininess + + local N = self.normal:normalized() + local P = self:mean():normalized() + local V = vector.new(3, {0, 0, -1}) + + local I = Ka * ambient + + for i = 1, #lights do + local l = lights[i] + local L = (light.transform:position(true) - P):normalized() + local R = 2 * vector.dot(L, N) * N - L + + -- Diffuse component + I = I + Kd * vector.dot(L, N) * l.diffuse + + -- Specular component + I = I + Ks * math.pow(vector.dot(R, V), shine) * l.specular + end + + return I +end + + +-- Creates a new shape with transform t and faces f +function shape.new(t, f) + local s = {transform = t, faces = f or {}} + setmetatable(s, shape) + return s +end + + -- Clones this shape function shape:clone() return shape.new(self.transform, table.copy(self.faces))