local ffi = require("ffi") local C = ffi.C local core = require("pxl8.core") local world = {} local Bsp = {} Bsp.__index = Bsp function Bsp:face_count() return C.demo3d_bsp_face_count(self._ptr) end function Bsp:face_normal(face_id) return C.demo3d_bsp_face_normal(self._ptr, face_id) end function Bsp:light_at(x, y, z, ambient) return C.demo3d_bsp_light_at(self._ptr, x, y, z, ambient or 0) end function Bsp:face_set_material(face_id, material_id) C.demo3d_bsp_face_set_material(self._ptr, face_id, material_id) end world.Bsp = Bsp local Chunk = {} Chunk.__index = Chunk function Chunk:bsp() if self._ptr == nil then return nil end if self._ptr.bsp == nil then return nil end return setmetatable({ _ptr = self._ptr.bsp }, Bsp) end function Chunk:ready() return self._ptr ~= nil and self._ptr.bsp ~= nil end function Chunk:version() if self._ptr == nil then return 0 end return self._ptr.version end world.Chunk = Chunk local World = {} World.__index = World function World.get() local w = C.demo3d_get_world(core.sys) if w == nil then return nil end return setmetatable({ _ptr = w }, World) end function World:active_chunk() local ptr = C.demo3d_world_active_chunk(self._ptr) if ptr == nil then return nil end return setmetatable({ _ptr = ptr }, Chunk) end function World:init_local_player(x, y, z) C.demo3d_world_init_local_player(self._ptr, x, y, z) end function World:set_look(yaw, pitch) C.demo3d_world_set_look(self._ptr, yaw, pitch or 0) end function World:local_player() local ptr = C.demo3d_world_local_player(self._ptr) if ptr == nil then return nil end return ptr end function World:point_solid(x, y, z) return C.demo3d_world_point_solid(self._ptr, x, y, z) end function World:ray(from_x, from_y, from_z, to_x, to_y, to_z) local from = ffi.new("pxl8_vec3", {x = from_x, y = from_y, z = from_z}) local to = ffi.new("pxl8_vec3", {x = to_x, y = to_y, z = to_z}) return C.demo3d_world_ray(self._ptr, from, to) end function World:render(camera_pos) local vec = ffi.new("pxl8_vec3", {x = camera_pos[1], y = camera_pos[2], z = camera_pos[3]}) C.demo3d_world_render(self._ptr, core.gfx, vec) end function World:set_bsp_material(material_id, material) C.demo3d_world_set_bsp_material(self._ptr, material_id, material._ptr) end function World:sweep(from_x, from_y, from_z, to_x, to_y, to_z, radius) local from = ffi.new("pxl8_vec3", {x = from_x, y = from_y, z = from_z}) local to = ffi.new("pxl8_vec3", {x = to_x, y = to_y, z = to_z}) return C.demo3d_world_sweep(self._ptr, from, to, radius) end function World:set_sim_config(config) C.demo3d_world_set_sim_config(self._ptr, config) end function World:push_input(input_msg) C.demo3d_world_push_input(self._ptr, input_msg) end world.World = World function world.sim_config(opts) opts = opts or {} return ffi.new("demo3d_sim_config", { move_speed = opts.move_speed or 180.0, ground_accel = opts.ground_accel or 10.0, air_accel = opts.air_accel or 1.0, stop_speed = opts.stop_speed or 100.0, friction = opts.friction or 6.0, gravity = opts.gravity or 800.0, jump_velocity = opts.jump_velocity or 200.0, player_radius = opts.player_radius or 16.0, player_height = opts.player_height or 72.0, max_pitch = opts.max_pitch or 1.5, }) end function world.sim_move_player(entity, input_msg, sim_world, config, dt) C.demo3d_sim_move_player(entity, input_msg, sim_world, config, dt) end function world.sim_trace(sim_world, from_x, from_y, from_z, to_x, to_y, to_z, radius, height) local from = ffi.new("pxl8_vec3", {x = from_x, y = from_y, z = from_z}) local to = ffi.new("pxl8_vec3", {x = to_x, y = to_y, z = to_z}) return C.demo3d_sim_trace(sim_world, from, to, radius, height) end function world.sim_check_ground(sim_world, x, y, z, radius) local pos = ffi.new("pxl8_vec3", {x = x, y = y, z = z}) return C.demo3d_sim_check_ground(sim_world, pos, radius) end function World:sim_world(x, y, z) local pos = ffi.new("pxl8_vec3", {x = x, y = y, z = z}) return C.demo3d_world_sim_world(self._ptr, pos) end function world.make_input_msg(opts) opts = opts or {} return ffi.new("demo3d_input_msg", { move_x = opts.move_x or 0, move_y = opts.move_y or 0, look_dx = opts.look_dx or 0, look_dy = opts.look_dy or 0, buttons = opts.buttons or 0, }) end return world