161 lines
5.4 KiB
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
|
|
|
|
-- --------------------------------------------------------------------------------------------------------
|