diff --git a/data/images/measure002a.png b/data/images/measure002a.png new file mode 100644 index 0000000..adf5e6f Binary files /dev/null and b/data/images/measure002a.png differ diff --git a/data/models/unit_cube.obj b/data/models/unit_cube.obj new file mode 100644 index 0000000..d58995e --- /dev/null +++ b/data/models/unit_cube.obj @@ -0,0 +1,38 @@ +# Blender 4.0.2 +# www.blender.org +o Cube +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0000 1.0000 -0.0000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.125000 0.750000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +s 0 +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/4/2 4/3/2 8/5/2 7/6/2 +f 7/6/3 8/5/3 6/7/3 5/8/3 +f 5/8/4 6/7/4 2/9/4 1/10/4 +f 3/11/5 7/6/5 5/8/5 1/12/5 +f 8/5/6 4/13/6 2/14/6 6/7/6 diff --git a/data/scripts/classes/obj.lua b/data/scripts/classes/obj.lua new file mode 100644 index 0000000..311babd --- /dev/null +++ b/data/scripts/classes/obj.lua @@ -0,0 +1,125 @@ +---@class Obj +---@field model string +---@field texture string +---@field texture_size integer +---@field position Vector3 +---@field triangles table +local Obj = {} + +local Vector3 = require "types.vector3" + +Obj.__index = Obj + +local function string_split(str, delimiter) + local res = {} + local i = 0 + local f + local match = '(.-)' .. delimiter .. '()' + + if string.find(str, delimiter) == nil then + return {str} + end + + for sub, j in string.gmatch(str, match) do + i = i + 1 + res[i] = sub + f = j + end + + if i ~= 0 then + res[i+1] = string.sub(str, f) + end + + return res +end + +---parses the obj file and triangulates it for drawing +---@param model string path to obj model +---@param texture {file: string, size: number} +---@param position Vector3? +---@return Obj +function Obj.create(model, texture, position) + local pos + if position ~= nil then + pos = position + else + pos = Vector3() + end + local obj = { + model = model, + texture = texture.file, + texture_size = texture.size, + position = pos:copy(), + + triangles = {} + } + obj.position = obj.position:copy() + setmetatable(obj, Obj) + -- adapted from https://github.com/karai17/lua-obj/blob/master/obj_loader.lua + -- Copyright (c) 2014 Landon Manning - LManning17@gmail.com - LandonManning.com + -- MIT + local file = file_read{file = obj.model} + local lines = string_split(file, "\r?\n") + local obj_data = { + v = {}, + vt = {}, + f = {}, + } + for _, line in ipairs(lines) do + local l = string_split(line, "%s+") + if l[1] == "v" then + local v = { + x = tonumber(l[2]), + y = tonumber(l[3]), + z = tonumber(l[4]), + } + table.insert(obj_data.v, v) + elseif l[1] == "vt" then + local vt = { + x = tonumber(l[2]) * obj.texture_size, + y = tonumber(l[3]) * obj.texture_size, + } + table.insert(obj_data.vt, vt) + elseif l[1] == "f" then + local f = {} + for i = 2, #l do + local split = string_split(l[i], "/") + local v = {} + + v.v = tonumber(split[1]) + if split[2] ~= "" then v.vt = tonumber(split[2]) end + -- v.vn = tonumber(split[3]) + + table.insert(f, v) + end + table.insert(obj_data.f, f) + end + end + for _, face in ipairs(obj_data.f) do + for i = 2, #face - 1 do + local triangle = { + v0 = obj_data.v[face[1].v], + v1 = obj_data.v[face[i].v], + v2 = obj_data.v[face[i + 1].v], + uv0 = obj_data.vt[face[1].vt], + uv1 = obj_data.vt[face[i].vt], + uv2 = obj_data.vt[face[i + 1].vt], + texture = obj.texture + } + table.insert(obj.triangles, triangle) + end + end + return obj +end + +function Obj:draw() + for _, triangle in ipairs(self.triangles) do + local newt = util.shallow_copy(triangle) + newt.v0 = Vector3(triangle.v0) + self.position + newt.v1 = Vector3(triangle.v1) + self.position + newt.v2 = Vector3(triangle.v2) + self.position + draw_triangle(newt) + end +end + +return Obj \ No newline at end of file diff --git a/data/scripts/game.lua b/data/scripts/game.lua index ffaeab2..6454492 100644 --- a/data/scripts/game.lua +++ b/data/scripts/game.lua @@ -3,6 +3,10 @@ local player = require "classes.player" local Vector3 = require "types.vector3" local List = require "types.list" +local Obj = require "classes.obj" + +local cube = Obj.create("models/unit_cube.obj", {file = "images/measure002a.png", size = 512}, Vector3(0, 1, 0)) + local Feed = require "classes.feed" ---@type List local feed = List() @@ -41,10 +45,6 @@ function game_tick() -- ctx.initialization_needed is true first frame and every time dynamic reload is performed if ctx.initialization_needed then audio_play{audio = "music/bg1.xm", loops = true, channel = "music"} - -- ctx.udata persists on reload - ctx.udata = { - capture = false, - } player.ThrowPressed:connect(create_feed) -- spawn some ducks @@ -55,7 +55,13 @@ function game_tick() duck.SeekFeed:connect(duck_seek_feed) duck.index = i end - + end + + -- ctx.udata persists on reload + if ctx.udata == nil then + ctx.udata = { + capture = false, + } end ctx.mouse_capture = ctx.udata.capture @@ -80,4 +86,7 @@ function game_tick() texture_region = { x = 0, y = 0, w = 512, h = 512 }, } draw_quad(util.merge(q, params)) + cube.position.x = math.sin(ctx.frame_number * 0.01) + cube.position.z = math.cos(ctx.frame_number * 0.01) + cube:draw() end