125 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
---@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 |