sokol-luajit/lua/engine/gameobject.lua

161 lines
5.4 KiB
Lua

local tinsert = table.insert
local utils = require("lua.utils")
local hmm = require("hmm")
local ffi = require("ffi")
local geom = require("lua.gltfloader.geometry-utils")
-- --------------------------------------------------------------------------------------------------------
-- Internal storage for a mesh gameobject
--
-- Note: components allowed are currently 16. I think if you are adding more than that, then you
-- have a poor design. This needs to be simple and clean. I may reduce to 12 or less.
ffi.cdef[[
enum {
COMPONENTS_MAX = 10
};
typedef struct gameobject {
unsigned int id;
const char * name;
hmm_vec3 pos;
hmm_quaternion rot;
hmm_vec3 scale;
unsigned int components[COMPONENTS_MAX];
unsigned int sibling;
unsigned int parent;
} gameobject;
]]
-- --------------------------------------------------------------------------------------------------------
local GAMEOBJECTS_MAX = 1000 -- Conservative alloc. This will be about 96K mem wise.
local GAMEOBJECTS_REALLOC_THRESHOLD = 0.9 -- 90% hit, then realloc
-- --------------------------------------------------------------------------------------------------------
local gameobject = {
-- All gameobjects are stored in a memory block.
all_gameobjects = ffi.new("gameobject[?]", GAMEOBJECTS_MAX),
-- This count is important - if it reached 90% it does a realloc and doubles and copies gameobjects
alloc_count = GAMEOBJECTS_MAX,
count = 0,
lookup_ids = {},
lookup_names = {}, -- Note name lookup can be messy. Esp if duplicate names are used
}
-- --------------------------------------------------------------------------------------------------------
-- Clears the gameobject array
-- We dont reset the alloc_count, incase the user wants to refill. Faster to leave it.
gameobject.reset = function( )
gameobject.count = 0
gameobject.all_gameobjects = ffi.new("gameobject[?]", gameobject.alloc_count)
gameobject.lookup_ids = {}
gameobject.lookup_names = {}
end
-- --------------------------------------------------------------------------------------------------------
gameobject.check = function( )
if(gameobject.count / gameobject.alloc_count > GAMEOBJECTS_REALLOC_THRESHOLD) then
gameobject.alloc_count = gameobject.alloc_count * 2
local newobjects = ffi.new("gameobject[?]", gameobject.alloc_count)
ffi.copy(newobjects, gameobject.all_gameobjects, gameobject.count * ffi.sizeof("gameobject"))
gameobject.all_gameobjects = newobjects
end
end
-- --------------------------------------------------------------------------------------------------------
gameobject.create = function( id, name, pos, rot, scale, parent )
-- Sometimes the original gameobject name is used
if(type(name)=="cdata") then name = ffi.string(name) end
pos = pos or hmm.HMM_Vec3(0, -999999, 0)
rot = rot or hmm.HMM_Quaternion(0, 0, 0, 0)
local scale = hmm.HMM_Vec3(0, 0, 0)
gameobject.check()
local gobj_index = gameobject.count
local gobj = ffi.cast("gameobject *", gameobject.all_gameobjects + gameobject.count)
gobj.id = id or gobj_index
gobj.name = ffi.string(name or "dummy")
gobj.pos = pos
gobj.rot = rot
gobj.scale = scale
gobj.parent = parent or 0 -- Must be an index!!!
-- Reverse lookups - will be useful if needed. May add spatial as well.
gameobject.lookup_ids[gobj.id] = gobj_index
gameobject.lookup_names[gobj.name] = gobj_index
gameobject.count = gameobject.count + 1
return gobj_index
end
-- --------------------------------------------------------------------------------------------------------
gameobject.get_go = function( id )
assert(id < gameobject.count and id >= 0)
return gameobject.all_gameobjects[id]
end
-- --------------------------------------------------------------------------------------------------------
gameobject.goname = function( id )
assert(id < gameobject.count and id >= 0)
return ffi.string(gameobject.all_gameobjects[id].name)
end
-- --------------------------------------------------------------------------------------------------------
gameobject.set_position = function( id, pos )
assert(id < gameobject.count and id >= 0)
gameobject.all_gameobjects[id].pos = pos
end
-- --------------------------------------------------------------------------------------------------------
gameobject.set_rotation = function( id, rot )
assert(id < gameobject.count and id >= 0)
gameobject.all_gameobjects[id].rot = rot
end
-- --------------------------------------------------------------------------------------------------------
gameobject.set_scale = function( id, scale )
assert(id < gameobject.count and id >= 0)
gameobject.all_gameobjects[id].scale = scale
end
-- --------------------------------------------------------------------------------------------------------
gameobject.set_parent = function( id, parent )
assert(id < gameobject.count and id >= 0)
assert(parent < gameobject.count and parent >= 0)
gameobject.all_gameobjects[id].parent = parent
end
-- --------------------------------------------------------------------------------------------------------
gameobject.get_mesh = function(id)
assert(id < gameobject.count and id >= 0)
local go = gameobject.all_gameobjects[id]
return geom:GetMesh(ffi.string(go.name))
end
-- --------------------------------------------------------------------------------------------------------
return gameobject
-- --------------------------------------------------------------------------------------------------------