|
|
|
@ -22,42 +22,121 @@ struct SDLHandles |
|
|
|
SDL_DisplayMode display_mode; |
|
|
|
SDL_DisplayMode display_mode; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: node/tree structure for entities
|
|
|
|
|
|
|
|
struct Node; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Entity |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
u32 num_meshes; |
|
|
|
|
|
|
|
GLmesh* meshes; |
|
|
|
|
|
|
|
glm::mat4* xform; |
|
|
|
|
|
|
|
char* name; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct RenderGroup |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
shader_program* shader; |
|
|
|
|
|
|
|
u32 num_entites; |
|
|
|
|
|
|
|
u32 max_entities; |
|
|
|
|
|
|
|
Entity* entities; |
|
|
|
|
|
|
|
char* name; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct RenderState |
|
|
|
struct RenderState |
|
|
|
{ |
|
|
|
{ |
|
|
|
memory_arena* asset_arena; |
|
|
|
|
|
|
|
transforms* xforms; // NOTE: would be part of camera in libTangerine
|
|
|
|
transforms* xforms; // NOTE: would be part of camera in libTangerine
|
|
|
|
SDLHandles* handles; |
|
|
|
SDLHandles* handles; |
|
|
|
GLContext* gl_ctx; |
|
|
|
GLContext* gl_ctx; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memory_arena* asset_arena; |
|
|
|
Assets* assets; |
|
|
|
Assets* assets; |
|
|
|
|
|
|
|
|
|
|
|
// FIXME: WIP
|
|
|
|
|
|
|
|
// TODO: need to initialize groups
|
|
|
|
|
|
|
|
memory_arena* rg_arena; |
|
|
|
memory_arena* rg_arena; |
|
|
|
u32 num_render_groups; |
|
|
|
u32 num_render_groups; |
|
|
|
u32 max_render_groups; |
|
|
|
u32 max_render_groups; |
|
|
|
RenderGroup* render_groups; |
|
|
|
RenderGroup* render_groups; |
|
|
|
|
|
|
|
|
|
|
|
// TODO: need to initialize mappings
|
|
|
|
|
|
|
|
u32 num_mappings; |
|
|
|
|
|
|
|
u32 max_mappings; |
|
|
|
|
|
|
|
ShaderToRenderGroupMapping* mappings; |
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: can remove these after implementing render groups
|
|
|
|
|
|
|
|
u32 num_gl_meshes; |
|
|
|
|
|
|
|
u32 max_gl_meshes; |
|
|
|
|
|
|
|
GLmesh* gl_meshes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u32 num_lights; |
|
|
|
u32 num_lights; |
|
|
|
u32 max_lights; |
|
|
|
u32 max_lights; |
|
|
|
PointLight* lights; |
|
|
|
PointLight* lights; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_ENTITY_COUNT 256 |
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
initRenderGroup(RenderGroup* rg, |
|
|
|
|
|
|
|
memory_arena* arena, |
|
|
|
|
|
|
|
shader_program* shader, |
|
|
|
|
|
|
|
u32 num_entities = DEFAULT_ENTITY_COUNT, |
|
|
|
|
|
|
|
const char* name = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
rg->max_entities = num_entities; |
|
|
|
|
|
|
|
rg->shader = shader; |
|
|
|
|
|
|
|
rg->name = arenaCopyCStr(arena, name); |
|
|
|
|
|
|
|
rg->entities = ARENA_ALLOC(arena, Entity, num_entities); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
freeRenderGroup(RenderGroup* rg, memory_arena* arena) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("%s(), should probably look into freeing arena memory?\n", |
|
|
|
|
|
|
|
__FUNCTION__); |
|
|
|
|
|
|
|
assert(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Entity* |
|
|
|
|
|
|
|
getFreeEntity(RenderGroup* rg) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (rg->num_entites < rg->max_entities) |
|
|
|
|
|
|
|
return &rg->entities[rg->num_entites++]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("%s(), render group full\n", __FUNCTION__); |
|
|
|
|
|
|
|
return nullptr; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
|
|
|
initEntity(Entity* e, |
|
|
|
|
|
|
|
memory_arena* arena, |
|
|
|
|
|
|
|
model* mdl, |
|
|
|
|
|
|
|
u32 num_attrib_mappings, |
|
|
|
|
|
|
|
GLBufferToAttribMapping* attrib_mappings, |
|
|
|
|
|
|
|
const char* name = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
e->num_meshes = mdl->num_meshes; |
|
|
|
|
|
|
|
e->meshes = ARENA_ALLOC(arena, GLmesh, e->num_meshes); |
|
|
|
|
|
|
|
e->xform = ARENA_ALLOC(arena, glm::mat4, 1); |
|
|
|
|
|
|
|
*e->xform = glm::mat4(1.f); |
|
|
|
|
|
|
|
e->name = arenaCopyCStr(arena, name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i< e->num_meshes; i++) { |
|
|
|
|
|
|
|
GLmesh* glm = &e->meshes[i]; |
|
|
|
|
|
|
|
*glm = loadGLMesh(mdl->meshes[i], GL_TRIANGLES, glm::vec3(0, 0, 0), |
|
|
|
|
|
|
|
num_attrib_mappings, attrib_mappings); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (glm->vao_id == 0) { |
|
|
|
|
|
|
|
printf("%s(), error initializing entity\n", __FUNCTION__); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
setEntityPosition(Entity* e, glm::vec3 pos) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*e->xform = glm::translate(*e->xform, pos); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
rotateEntity(Entity* e, glm::vec3 axis, float radians) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*e->xform = glm::rotate(*e->xform, radians, axis); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: equivalent to rgAppend() in libTangerine
|
|
|
|
// NOTE: equivalent to rgAppend() in libTangerine
|
|
|
|
model* |
|
|
|
model* |
|
|
|
getModel(RenderState* rs, const char* filepath) |
|
|
|
getModelByPath(RenderState* rs, const char* filepath) |
|
|
|
{ |
|
|
|
{ |
|
|
|
model* mdl = assetGetCached(rs->assets, utilFNV64a_str(filepath)); |
|
|
|
model* mdl = assetGetCached(rs->assets, utilFNV64a_str(filepath)); |
|
|
|
|
|
|
|
|
|
|
|
@ -67,13 +146,13 @@ getModel(RenderState* rs, const char* filepath) |
|
|
|
return mdl; |
|
|
|
return mdl; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GLmesh* |
|
|
|
RenderGroup* |
|
|
|
getFreeGLMesh(RenderState* rs) |
|
|
|
getFreeRenderGroup(RenderState* rs) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (rs->num_gl_meshes < rs->max_gl_meshes) |
|
|
|
if (rs->num_render_groups < rs->max_render_groups) |
|
|
|
return &rs->gl_meshes[rs->num_gl_meshes++]; |
|
|
|
return &rs->render_groups[rs->num_render_groups++]; |
|
|
|
|
|
|
|
|
|
|
|
printf("%s(), Error, rs->gl_meshes is full\n", __FUNCTION__); |
|
|
|
printf("%s(), no free render group\n", __FUNCTION__); |
|
|
|
return nullptr; |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -109,7 +188,7 @@ initAssets(memory_arena* arena, |
|
|
|
return assets; |
|
|
|
return assets; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define MAX_GL_MESHES 256 |
|
|
|
#define DEFAULT_RENDER_GROUP_COUNT 256 |
|
|
|
RenderState* |
|
|
|
RenderState* |
|
|
|
initRenderState() |
|
|
|
initRenderState() |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -117,13 +196,16 @@ initRenderState() |
|
|
|
|
|
|
|
|
|
|
|
if (rs) { |
|
|
|
if (rs) { |
|
|
|
rs->asset_arena = arenaInit(DEFAULT_ARENA_SIZE); |
|
|
|
rs->asset_arena = arenaInit(DEFAULT_ARENA_SIZE); |
|
|
|
rs->rg_arena = arenaInit(DEFAULT_ARENA_SIZE); |
|
|
|
|
|
|
|
rs->assets = initAssets(rs->asset_arena); |
|
|
|
rs->assets = initAssets(rs->asset_arena); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rs->rg_arena = arenaInit(DEFAULT_ARENA_SIZE); |
|
|
|
|
|
|
|
rs->max_render_groups = DEFAULT_RENDER_GROUP_COUNT; |
|
|
|
|
|
|
|
rs->render_groups = ARENA_ALLOC(rs->rg_arena, RenderGroup, |
|
|
|
|
|
|
|
DEFAULT_RENDER_GROUP_COUNT); |
|
|
|
|
|
|
|
|
|
|
|
rs->gl_ctx = initGLContext(rs->asset_arena); |
|
|
|
rs->gl_ctx = initGLContext(rs->asset_arena); |
|
|
|
rs->xforms = ARENA_ALLOC(rs->asset_arena, transforms, 1); |
|
|
|
rs->xforms = ARENA_ALLOC(rs->asset_arena, transforms, 1); |
|
|
|
rs->handles = UTIL_ALLOC(1, SDLHandles); |
|
|
|
rs->handles = UTIL_ALLOC(1, SDLHandles); |
|
|
|
rs->max_gl_meshes = MAX_GL_MESHES; |
|
|
|
|
|
|
|
rs->gl_meshes = ARENA_ALLOC(rs->rg_arena, GLmesh, MAX_GL_MESHES); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rs; |
|
|
|
return rs; |
|
|
|
@ -233,20 +315,12 @@ addShaders(RenderState* rs) |
|
|
|
bool |
|
|
|
bool |
|
|
|
loadScene(RenderState* rs) |
|
|
|
loadScene(RenderState* rs) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const u32 NUM_CUBES = 4; |
|
|
|
|
|
|
|
glm::vec3 cube_locs[NUM_CUBES] = { |
|
|
|
|
|
|
|
glm::vec3(-10, 10, 0), |
|
|
|
|
|
|
|
glm::vec3(-10, -10, 0), |
|
|
|
|
|
|
|
glm::vec3( 10, 10, 0), |
|
|
|
|
|
|
|
glm::vec3( 10, -10, 0), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shader_program* s_default = getShaderByName("default", rs->gl_ctx); |
|
|
|
shader_program* s_default = getShaderByName("default", rs->gl_ctx); |
|
|
|
shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); |
|
|
|
shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); |
|
|
|
if (!s_default || !s_debug) return false; |
|
|
|
if (!s_default || !s_debug) return false; |
|
|
|
|
|
|
|
|
|
|
|
// TODO: full lighting model
|
|
|
|
// TODO: full lighting model
|
|
|
|
model* tex_cube = getModel(rs, "../data/textured_cube.gltf"); |
|
|
|
model* tex_cube = getModelByPath(rs, "../data/textured_cube.gltf"); |
|
|
|
assert(tex_cube != nullptr && tex_cube->num_meshes > 0); |
|
|
|
assert(tex_cube != nullptr && tex_cube->num_meshes > 0); |
|
|
|
const mesh& texmesh = tex_cube->meshes[0]; |
|
|
|
const mesh& texmesh = tex_cube->meshes[0]; |
|
|
|
|
|
|
|
|
|
|
|
@ -259,30 +333,42 @@ loadScene(RenderState* rs) |
|
|
|
{ "normal", nullptr, normal_attrib, texmesh.normals } |
|
|
|
{ "normal", nullptr, normal_attrib, texmesh.normals } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: load meshes
|
|
|
|
const u32 NUM_CUBES = 4; |
|
|
|
GLmesh* gl_texmesh = getFreeGLMesh(rs); |
|
|
|
glm::vec3 cube_locs[NUM_CUBES] = { |
|
|
|
if (!gl_texmesh) return false; |
|
|
|
glm::vec3(-10, 10, 0), |
|
|
|
|
|
|
|
glm::vec3(-10, -10, 0), |
|
|
|
*gl_texmesh = loadGLMesh(texmesh, GL_TRIANGLES, glm::vec3(-5, -5, 0), 2, |
|
|
|
glm::vec3( 10, 10, 0), |
|
|
|
attrib_mappings); |
|
|
|
glm::vec3( 10, -10, 0), |
|
|
|
if (gl_texmesh->vao_id == 0) return false; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
gl_texmesh = getFreeGLMesh(rs); |
|
|
|
|
|
|
|
if (!gl_texmesh) return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*gl_texmesh = loadGLMesh(texmesh, GL_TRIANGLES, glm::vec3(5, 5, 0), 2, |
|
|
|
RenderGroup* orange_cubes = getFreeRenderGroup(rs); |
|
|
|
attrib_mappings); |
|
|
|
assert(orange_cubes != nullptr); |
|
|
|
if (gl_texmesh->vao_id == 0) return false; |
|
|
|
initRenderGroup(orange_cubes, rs->rg_arena, s_debug, NUM_CUBES, |
|
|
|
|
|
|
|
"debug_cubes"); |
|
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i < NUM_CUBES; i++) { |
|
|
|
for (u32 i = 0; i < NUM_CUBES; i++) { |
|
|
|
GLmesh* gmesh = getFreeGLMesh(rs); |
|
|
|
Entity* e = getFreeEntity(orange_cubes); |
|
|
|
if (!gmesh) return false; |
|
|
|
assert(e != nullptr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, |
|
|
|
|
|
|
|
"debug_box")) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// FIXME: this doesn't actually do anything
|
|
|
|
|
|
|
|
freeRenderGroup(orange_cubes, rs->rg_arena); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*gmesh = loadGLMesh(texmesh, GL_TRIANGLES, cube_locs[i], 2, |
|
|
|
setEntityPosition(e, cube_locs[i]); |
|
|
|
attrib_mappings); |
|
|
|
|
|
|
|
if (gmesh->vao_id == 0) return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RenderGroup* debug_cube_group = getFreeRenderGroup(rs); |
|
|
|
|
|
|
|
assert(debug_cube_group != nullptr); |
|
|
|
|
|
|
|
initRenderGroup(debug_cube_group, rs->rg_arena, s_default, 1, |
|
|
|
|
|
|
|
"orange_cubes"); |
|
|
|
|
|
|
|
Entity* e = getFreeEntity(debug_cube_group); |
|
|
|
|
|
|
|
assert(e != nullptr); |
|
|
|
|
|
|
|
initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, "orange_box"); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -294,9 +380,6 @@ loop(RenderState* rs) |
|
|
|
bool running = true; |
|
|
|
bool running = true; |
|
|
|
SDL_Event e; |
|
|
|
SDL_Event e; |
|
|
|
|
|
|
|
|
|
|
|
shader_program* s_default = getShaderByName("default", rs->gl_ctx); |
|
|
|
|
|
|
|
shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (running) { |
|
|
|
while (running) { |
|
|
|
frame_start = SDL_GetTicks(); |
|
|
|
frame_start = SDL_GetTicks(); |
|
|
|
|
|
|
|
|
|
|
|
@ -312,14 +395,18 @@ loop(RenderState* rs) |
|
|
|
glClearColor(0.2, 0.2, 0.2, 1); |
|
|
|
glClearColor(0.2, 0.2, 0.2, 1); |
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i < rs->num_gl_meshes; i++) { |
|
|
|
for (u32 i = 0; i < rs->num_render_groups; i++) { |
|
|
|
GLmesh& glm = rs->gl_meshes[i]; |
|
|
|
RenderGroup& rg = rs->render_groups[i]; |
|
|
|
*glm.model_xform = glm::rotate( |
|
|
|
|
|
|
|
*glm.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0)); |
|
|
|
for (u32 j = 0; j < rg.num_entites; j++) { |
|
|
|
// FIXME: need a shader to gl_mesh mapping
|
|
|
|
Entity& e = rg.entities[j]; |
|
|
|
//shader_program* s = (glm.shader) ? glm.shader : s_debug;
|
|
|
|
rotateEntity(&e, glm::vec3(0, 1, 0), (float) M_PI / 60); |
|
|
|
shader_program* s = s_debug; |
|
|
|
|
|
|
|
renderVAO(&glm, s); |
|
|
|
for (u32 k = 0; k < e.num_meshes; k++) { |
|
|
|
|
|
|
|
GLmesh& glm = e.meshes[k]; |
|
|
|
|
|
|
|
renderVAO(&glm, e.xform, rg.shader); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SDL_GL_SwapWindow(rs->handles->window); |
|
|
|
SDL_GL_SwapWindow(rs->handles->window); |
|
|
|
@ -359,11 +446,6 @@ main() |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
|
|
|
shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); |
|
|
|
|
|
|
|
dumpShader(s_debug->prog_id); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!loadScene(rs)) { |
|
|
|
if (!loadScene(rs)) { |
|
|
|
LOG(Error) << "error loading scene\n"; |
|
|
|
LOG(Error) << "error loading scene\n"; |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
|