pxl8/client/src/lua/pxl8/gfx3d.lua
asrael 49256db1bd refactor: reorganize pxl8 into client/src/ module structure
- core/: main entry, types, logging, I/O, RNG
- asset/: ase loader, cart, save, embed
- gfx/: graphics, animation, atlas, fonts, tilemap, transitions
- sfx/: audio
- script/: lua/fennel runtime, REPL
- hal/: platform abstraction (SDL3)
- world/: BSP, world, procedural gen
- math/: math utilities
- game/: GUI, replay
- lua/: Lua API modules
2026-01-15 08:41:59 -06:00

161 lines
4.3 KiB
Lua

local ffi = require("ffi")
local C = ffi.C
local core = require("pxl8.core")
local gfx3d = {}
local Camera3D = {}
Camera3D.__index = Camera3D
function Camera3D.new()
local cam = C.pxl8_3d_camera_create()
if cam == nil then
return nil
end
return setmetatable({ _ptr = cam }, Camera3D)
end
function Camera3D:destroy()
if self._ptr then
C.pxl8_3d_camera_destroy(self._ptr)
self._ptr = nil
end
end
function Camera3D:get_forward()
local v = C.pxl8_3d_camera_get_forward(self._ptr)
return {v.x, v.y, v.z}
end
function Camera3D:get_position()
local v = C.pxl8_3d_camera_get_position(self._ptr)
return {v.x, v.y, v.z}
end
function Camera3D:get_right()
local v = C.pxl8_3d_camera_get_right(self._ptr)
return {v.x, v.y, v.z}
end
function Camera3D:get_up()
local v = C.pxl8_3d_camera_get_up(self._ptr)
return {v.x, v.y, v.z}
end
function Camera3D:lookat(eye, target, up)
up = up or {0, 1, 0}
local eye_vec = ffi.new("pxl8_vec3", {x = eye[1], y = eye[2], z = eye[3]})
local target_vec = ffi.new("pxl8_vec3", {x = target[1], y = target[2], z = target[3]})
local up_vec = ffi.new("pxl8_vec3", {x = up[1], y = up[2], z = up[3]})
C.pxl8_3d_camera_lookat(self._ptr, eye_vec, target_vec, up_vec)
end
function Camera3D:set_perspective(fov, aspect, near, far)
C.pxl8_3d_camera_set_perspective(self._ptr, fov, aspect, near, far)
end
function Camera3D:set_position(x, y, z)
local pos = ffi.new("pxl8_vec3", {x = x, y = y, z = z})
C.pxl8_3d_camera_set_position(self._ptr, pos)
end
function Camera3D:set_rotation(pitch, yaw, roll)
C.pxl8_3d_camera_set_rotation(self._ptr, pitch, yaw or 0, roll or 0)
end
function Camera3D:update(dt)
C.pxl8_3d_camera_update(self._ptr, dt)
end
gfx3d.Camera3D = Camera3D
local Mesh = {}
Mesh.__index = Mesh
function Mesh.new(vertices, indices)
local vertex_count = #vertices
local index_count = #indices
local mesh = C.pxl8_mesh_create(vertex_count, index_count)
if mesh == nil then
return nil
end
local self = setmetatable({ _ptr = mesh }, Mesh)
for _, v in ipairs(vertices) do
local vert = ffi.new("pxl8_vertex", {
position = {x = v.x or 0, y = v.y or 0, z = v.z or 0},
normal = {x = v.nx or 0, y = v.ny or 0, z = v.nz or 0},
u = v.u or 0,
v = v.v or 0,
color = v.color or 0,
light = v.light or 255,
})
C.pxl8_mesh_push_vertex(mesh, vert)
end
for i = 1, #indices, 3 do
C.pxl8_mesh_push_triangle(mesh, indices[i], indices[i+1], indices[i+2])
end
return self
end
function Mesh:destroy()
if self._ptr then
C.pxl8_mesh_destroy(self._ptr)
self._ptr = nil
end
end
function Mesh:clear()
if self._ptr then
C.pxl8_mesh_clear(self._ptr)
end
end
gfx3d.Mesh = Mesh
function gfx3d.draw_mesh(mesh, opts)
opts = opts or {}
local model = C.pxl8_mat4_identity()
local material = ffi.new("pxl8_material", {
texture_id = opts.texture or 0,
alpha = opts.alpha or 255,
blend_mode = opts.blend_mode or 0,
dither = opts.dither ~= false,
double_sided = opts.double_sided or false,
dynamic_lighting = opts.lighting or false,
per_pixel = opts.per_pixel or false,
vertex_color_passthrough = opts.passthrough or false,
emissive_intensity = opts.emissive or 0.0,
})
C.pxl8_3d_draw_mesh(core.gfx, mesh._ptr, model, material)
end
function gfx3d.begin_frame(camera, uniforms)
uniforms = uniforms or {}
local u = ffi.new("pxl8_3d_uniforms", {
ambient = uniforms.ambient or 0,
fog_color = uniforms.fog_color or 0,
fog_density = uniforms.fog_density or 0.0,
time = uniforms.time or 0.0,
})
C.pxl8_3d_begin_frame(core.gfx, camera._ptr, u)
end
function gfx3d.clear(color)
C.pxl8_3d_clear(core.gfx, color or 0)
end
function gfx3d.clear_depth()
C.pxl8_3d_clear_depth(core.gfx)
end
function gfx3d.draw_line(p0, p1, color)
local vec0 = ffi.new("pxl8_vec3", {x = p0[1], y = p0[2], z = p0[3]})
local vec1 = ffi.new("pxl8_vec3", {x = p1[1], y = p1[2], z = p1[3]})
C.pxl8_3d_draw_line(core.gfx, vec0, vec1, color)
end
function gfx3d.end_frame()
C.pxl8_3d_end_frame(core.gfx)
end
return gfx3d