Skip to content
Extraits de code Groupes Projets
Valider 11a5662b rédigé par ultrakatiz's avatar ultrakatiz
Parcourir les fichiers

Merge remote-tracking branch 'origin/sting'

# Conflicts:
#	examples/Test.ass
#	shape.lua
parents 3698c6d0 d08b96c5
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -3,4 +3,5 @@ require("kara3d.matrix") ...@@ -3,4 +3,5 @@ require("kara3d.matrix")
require("kara3d.quaternion") require("kara3d.quaternion")
require("kara3d.transform") require("kara3d.transform")
require("kara3d.shape") require("kara3d.shape")
require("kara3d.light")
require("kara3d.camera") require("kara3d.camera")
Impossible d'afficher diff de source : il est trop volumineux. Options pour résoudre ce problème : voir le blob.
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 vector.new(3, {255, 255, 255}), specular = spec or vector.new(3, {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
...@@ -2,8 +2,10 @@ require("kara3d.vector") ...@@ -2,8 +2,10 @@ require("kara3d.vector")
require("kara3d.matrix") require("kara3d.matrix")
require("kara3d.quaternion") require("kara3d.quaternion")
require("kara3d.transform") require("kara3d.transform")
require("kara3d.light")
require("kara3d.camera") require("kara3d.camera")
require("utils") require("utils")
re = require("re")
-- ********** DEFINITION AND GENERIC FUNCTIONS ********** -- ********** DEFINITION AND GENERIC FUNCTIONS **********
...@@ -13,13 +15,23 @@ shape.__index = shape ...@@ -13,13 +15,23 @@ shape.__index = shape
face = {class = "face"} face = {class = "face"}
face.__index = face face.__index = face
-- Creates a new shape with transform t and faces f material = {class = "material"}
function shape.new(t, f) material.__index = material
local s = {transform = t, faces = f or {}}
setmetatable(s, shape)
return s
function material.new(amb, diff, spec, sh, al)
local m = {ambient = vector.new(3, amb) or vector.new(3, {1, 1, 1}),
diffuse = vector.new(3, diff) or vector.new(3, {1, 1, 1}),
specular = vector.new(3, spec) or vector.new(3, {1, 1, 1}),
shininess = sh or 1,
alpha = al or 0}
setmetatable(m, material)
return m
end end
-- Creates a new face with vertices c, normal n and tags t -- Creates a new face with vertices c, normal n and tags t
function face.new(v, n, t) function face.new(v, n, t)
local f = {vertices = v or {}, normal = n or -vector.cardinal(3, 3), tags = t} local f = {vertices = v or {}, normal = n or -vector.cardinal(3, 3), tags = t}
...@@ -27,6 +39,42 @@ function face.new(v, n, t) ...@@ -27,6 +39,42 @@ function face.new(v, n, t)
return f return f
end end
function face.shade(N, P, mat, lights, ambient, cam)
local Ka = mat.ambient
local Kd = mat.diffuse
local Ks = mat.specular
local shine = mat.shininess
local V = (cam.transform:position(true) - P):normalized()
local I = Ka * ambient
for i = 1, #lights do
local l = lights[i]
local L = (l.transform:position(true) - P):normalized()
local R = 2 * math.max(vector.dot(L, N), 0) * N - L
-- Diffuse component
I = I + Kd * math.max(vector.dot(L, N), 0) * l.diffuse
-- Specular component
I = I + Ks * math.pow(math.max(vector.dot(R, V), 0), shine) * l.specular
end
return I:clamp(0, 255)
end
-- Creates a new shape with transform t and faces f
function shape.new(t, f, mat)
local s = {transform = t, faces = f or {}, material = mat or material.new()}
setmetatable(s, shape)
return s
end
-- Clones this shape -- Clones this shape
function shape:clone() function shape:clone()
return shape.new(self.transform, table.copy(self.faces)) return shape.new(self.transform, table.copy(self.faces))
...@@ -34,10 +82,17 @@ end ...@@ -34,10 +82,17 @@ end
-- ********** INSTANCE FUNCTIONS ********** -- ********** INSTANCE FUNCTIONS **********
function shape:set_material(mat)
self.material = mat
return self
end
-- Generates a line for each face of this shape, with the indicated tags -- Generates a line for each face of this shape, with the indicated tags
-- The boolean cull determines if the faces facing away from the screen are -- The boolean cull determines if the faces facing away from the screen are
-- drawn or not -- drawn or not
function shape:draw(subs, line, tags, cull, cam) function shape:draw(subs, line, tags, cull, cam, ambient, lights)
local p = self.transform:position(true) local p = self.transform:position(true)
local tm = self.transform:matrix(true) local tm = self.transform:matrix(true)
local c = vector.cardinal(4, 4) local c = vector.cardinal(4, 4)
...@@ -52,15 +107,17 @@ function shape:draw(subs, line, tags, cull, cam) ...@@ -52,15 +107,17 @@ function shape:draw(subs, line, tags, cull, cam)
for i = 1, #self.faces do for i = 1, #self.faces do
local face = self.faces[i] local face = self.faces[i]
local norm = quaternion.mul_vector(r, face.normal)
local n = quaternion.mul_vector(cam_inv_rot, norm)
local vs = face.vertices local vs = face.vertices
local v = m * (vs[#vs] + c) local v = m * (vs[#vs] + c)
v = (1 / v:w()) * v v = (1 / v:w()) * v
local n = (tm * (face.normal + c) - p):set_size(3) local world_n = (tm * (face.normal + c) - p):set_size(3)
local c_to_v = (tm * (vs[#vs] + c) - camp):set_size(3):normalize() local c_to_v = (tm * (vs[#vs] + c) - camp):set_size(3):normalize()
if not (cull and vector.dot(c_to_v, n) > 0) then if not (cull and vector.dot(c_to_v, world_n) > 0) then
local l = table.copy(line) local l = table.copy(line)
l.text = (tags and "{" .. tags .. "}" or "") l.text = (tags and "{" .. tags .. "}" or "")
...@@ -78,9 +135,17 @@ function shape:draw(subs, line, tags, cull, cam) ...@@ -78,9 +135,17 @@ function shape:draw(subs, line, tags, cull, cam)
.. (-v:y() * yres / 2) .. " " .. (-v:y() * yres / 2) .. " "
end end
face_center = (1 / #vs) * face_center local P = (p + sum) * (1/#vs)
l.text = l.text local color = face.shade(n, P, self.material, lights, ambient, cam)
local colorstr = string.format("{\\c%s\\alpha%s}",
ass_color(color:x(), color:y(), color:z()),
ass_alpha(self.material.alpha)
)
l.text = colorstr .. str
face_center = (1 / #vs) * face_center
-- layers must be between 0 and 9999999999 -- layers must be between 0 and 9999999999
l.layer = math.floor(-face_center:z()) l.layer = math.floor(-face_center:z())
l.effect = "fx" l.effect = "fx"
...@@ -117,3 +182,49 @@ function shape.cube(t, size) ...@@ -117,3 +182,49 @@ function shape.cube(t, size)
return shape.new(t, {left, right, bottom, top, back, front}) return shape.new(t, {left, right, bottom, top, back, front})
end end
--[[
Load shape from mesh file. Only .off files supported for now, though
]]--
function shape.load(t, file)
local vertices = {}
local faces = {}
local vertexNumber = nil
local faceNumber = nil
local vertexRead = 0
local facesRead = 0
local linenumber = 0
for line in io.lines(file) do
linenumber = linenumber + 1
local blankMatch = re.match(line, "OFF|#.*")
if blankMatch == nil then
local matches = re.split(line, "[[:blank:]]+", true)
if matches ~= nil then
if vertexNumber == nil or faceNumber == nil then
vertexNumber = tonumber(matches[1])
faceNumber = tonumber(matches[2])
else
if vertexRead < vertexNumber then
vertices[#vertices+1] = vector.new(3, {tonumber(matches[1]), tonumber(matches[2]), tonumber(matches[3])})
vertexRead = vertexRead + 1
else
local faceSize = tonumber(matches[1])
local faceVertices = {}
for i = 1, faceSize do
faceVertices[i] = vertices[tonumber(matches[i+1]) + 1]
end
local normal = vector.cross(faceVertices[2] - faceVertices[1],
faceVertices[3] - faceVertices[1])
:normalized()
faces[#faces+1] = face.new(faceVertices, normal)
facesRead = facesRead + 1
end
end
end
end
end
return shape.new(t, faces)
end
...@@ -139,6 +139,12 @@ function vector:y() return self.values[2] end ...@@ -139,6 +139,12 @@ function vector:y() return self.values[2] end
function vector:z() return self.values[3] end function vector:z() return self.values[3] end
function vector:w() return self.values[4] end function vector:w() return self.values[4] end
-- Clamp vector values
function vector:clamp(min, max)
for i = 1, self.size do self:set(i, clamp(self:get(i), min, max)) end
return self
end
-- ********** OPERATOR OVERLOADING ********** -- ********** OPERATOR OVERLOADING **********
-- + binary operator overload -- + binary operator overload
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter