Added primitive support to immediate renderer and put blender addon under version control

dev
Shariq Shah 8 years ago
parent 8782bf27ac
commit 9c2856eb87
  1. 1
      README.md
  2. BIN
      assets/models/cube.symbres
  3. BIN
      assets/models/sphere.symbres
  4. 4
      assets/shaders/im_geom.frag
  5. 4
      assets/shaders/im_geom.vert
  6. 2
      assets/test_scene.symtres
  7. 34
      blender_addon/io_symmetry_exp/__init__.py
  8. 95
      blender_addon/io_symmetry_exp/exporter.py
  9. 14
      build/genie.lua
  10. 60
      src/libsymmetry/game.c
  11. 774
      src/libsymmetry/geometry.c
  12. 124
      src/libsymmetry/im_render.c
  13. 26
      src/libsymmetry/im_render.h

@ -155,6 +155,7 @@
- ## TODO - ## TODO
- Convert IM_Vertex array to only be used as temporary storage for vertices between begin and end calls
- Physics forces/torque etc - Physics forces/torque etc
- Replace all renderer_check_gl calls with GL_CHECK macro - Replace all renderer_check_gl calls with GL_CHECK macro
- Fix lights type not being correctly saved/loaded from file - Fix lights type not being correctly saved/loaded from file

Binary file not shown.

Binary file not shown.

@ -1,10 +1,10 @@
//include version.glsl //include version.glsl
in vec4 color; uniform vec4 geom_color;
out vec4 frag_color; out vec4 frag_color;
void main() void main()
{ {
frag_color = color; frag_color = geom_color;
} }

@ -3,12 +3,8 @@
uniform mat4 mvp; uniform mat4 mvp;
in vec3 vPosition; in vec3 vPosition;
in vec4 vColor;
out vec4 color;
void main() void main()
{ {
gl_Position = mvp * vec4(vPosition, 1.0); gl_Position = mvp * vec4(vPosition, 1.0);
color = vColor;
} }

@ -40,7 +40,7 @@ Entity
scale : 1.000 1.000 1.000 scale : 1.000 1.000 1.000
material : Blinn_Phong material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000 rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh geometry : sphere.symbres
is_listener : false is_listener : false
position : 0.000 50.000 0.000 position : 0.000 50.000 0.000
parent : ROOT parent : ROOT

@ -0,0 +1,34 @@
bl_info = {
"name": "Export to Symmetry",
"description": "Export to a format that can be read by Symmetry",
"author": "Shariq Shah",
"version": (0, 1),
"blender": (2, 79, 0),
"location": "File > Export > Export to Symmetry",
"category": "Import-Export"
}
# Ensure that we reload our dependencies if we ourselves are reloaded by Blender
if "bpy" in locals():
import imp;
if "exporter" in locals():
imp.reload(exporter);
import bpy
from . import exporter
def menu_func(self, context):
self.layout.operator(ExportSymmetry.bl_idname, text="Symbres (.symbres)");
def register():
bpy.utils.register_module(__name__);
bpy.types.INFO_MT_file_export.append(menu_func);
def unregister():
bpy.utils.unregister_module(__name__);
bpy.types.INFO_MT_file_export.remove(menu_func);
if __name__ == "__main__":
register()

@ -0,0 +1,95 @@
import bpy
import bmesh
import struct
from math import radians
from bpy_extras.io_utils import ExportHelper
class ExportSymmetry(bpy.types.Operator, ExportHelper):
bl_idname = "export_symmetry.symbres";
bl_label = "Symmetry Exporter";
bl_options = {'PRESET'};
filename_ext = ".symbres";
def execute(self, context):
scene = context.scene
activeObject = scene.objects.active
if not activeObject or str(activeObject.type) != 'MESH':
raise NameError("Cannot export : Object %s is not a mesh" % activeObject)
print("Exporting : " + activeObject.name)
# Rotate -90 deg on x axis to compensate for blender's different orientation
activeObject.rotation_euler[0] = radians(-90)
bpy.ops.object.transform_apply(location = True, scale = True, rotation = True)
mesh = activeObject.to_mesh(scene, True, 'PREVIEW')
bm = bmesh.new()
bm.from_mesh(mesh)
bmesh.ops.triangulate(bm, faces = bm.faces)
indices = []
vertices = []
normals = []
uvs = []
if len(mesh.uv_layers) > 0:
uv_layer = bm.loops.layers.uv.values()[0]
index = 0;
for face in bm.faces:
for loop in face.loops:
uv = loop[uv_layer].uv
uv.y = 1.0 - uv.y
vert = loop.vert
vertices.append(vert.co.to_tuple())
normals.append(vert.normal.to_tuple())
uvs.append(uv.to_tuple())
indices.append(index)
index += 1
else:
raise NameError("No uv layers detected. Did you forget to unwrap?")
bm.free()
del bm
# Reset object's previous rotation
activeObject.rotation_euler[0] = radians(90)
bpy.ops.object.transform_apply(location = True, scale = True, rotation = True)
file = open(self.filepath, 'bw')
# Header
file.write(struct.pack('i', len(indices)))
file.write(struct.pack('i', len(vertices)))
file.write(struct.pack('i', len(normals)))
file.write(struct.pack('i', len(uvs)))
print ("Num Indices : %d" % len(indices))
print ("Indices : \n %s \n\n" % str(indices))
print ("Num Vertices : %d" % len(vertices))
print ("Vertices : \n %s \n\n" % str(vertices))
print ("Num Normals : %d" % len(normals))
print ("Normals : \n %s \n\n" % str(normals))
print ("Num UVs : %d" % len(uvs))
print ("UVs : \n %s \n\n" % str(uvs))
# Body
for index in indices:
file.write(struct.pack('i', index))
for vertex in vertices:
file.write(struct.pack('fff', vertex[0], vertex[1], vertex[2]))
for normal in normals:
file.write(struct.pack('fff', normal[0], normal[1], normal[2]))
for uv in uvs:
file.write(struct.pack('ff', uv[0], uv[1]))
file.close()
print("Done!")
return {'FINISHED'};

@ -19,7 +19,7 @@ solution "Symmetry"
end end
configuration "Debug" configuration "Debug"
if (_ACTION ~= nil and _ACTION ~= "postbuild_copy") then if (_ACTION ~= nil and _ACTION ~= "postbuild_copy" and _ACTION ~= "build_addon") then
os.mkdir(_ACTION .. "/debug") os.mkdir(_ACTION .. "/debug")
targetdir (_ACTION .. "/debug") targetdir (_ACTION .. "/debug")
end end
@ -27,7 +27,7 @@ solution "Symmetry"
flags { "Symbols" } flags { "Symbols" }
configuration "Release" configuration "Release"
if (_ACTION ~= nil and _ACTION ~= "postbuild_copy") then if (_ACTION ~= nil and _ACTION ~= "postbuild_copy" and _ACTION ~= "build_addon") then
os.mkdir(_ACTION .. "/release") os.mkdir(_ACTION .. "/release")
targetdir (_ACTION .. "/release") targetdir (_ACTION .. "/release")
end end
@ -133,3 +133,13 @@ solution "Symmetry"
configuration "Debug" configuration "Debug"
defines {"GL_DEBUG_CONTEXT"} defines {"GL_DEBUG_CONTEXT"}
newaction {
trigger = "build_addon",
description = "Build blender addon into zip file that can be loaded into blender",
execute = function ()
local output = os.outputof("cd ../blender_addon && zip -r io_symmetry_exp.zip io_symmetry_exp/__init__.py io_symmetry_exp/exporter.py && mv io_symmetry_exp.zip ../build");
printf("Output of blender addon build : \n%s\n", output)
end
}

@ -456,55 +456,59 @@ void debug(float dt)
vec3 im_position = { 0.f, 20.f, 0.f }; vec3 im_position = { 0.f, 20.f, 0.f };
vec3 im_scale = { 1.f, 1.f, 1.f }; vec3 im_scale = { 1.f, 1.f, 1.f };
quat im_rot = { 0.f, 0.f, 0.f, 1.f }; quat im_rot = { 0.f, 0.f, 0.f, 1.f };
vec4 im_color = { 0.f, 1.f, 1.f, 1.f };
quat_identity(&im_rot); quat_identity(&im_rot);
im_begin(im_position, im_rot, im_scale, GL_LINES); im_begin(im_position, im_rot, im_scale, im_color, GL_LINES);
im_color(0.f, 1.f, 0.f, 1.f);
im_pos(0.f, 0.f, 0.f); im_pos(0.f, 0.f, 0.f);
im_pos(100.f, 100.f, 10.f); im_pos(100.f, 100.f, 10.f);
im_end(); im_end();
im_position.x = -10; im_position.x = -10;
im_begin(im_position, im_rot, im_scale, GL_TRIANGLES);
im_color.x = 1.f;
im_color.y = 0.f;
im_begin(im_position, im_rot, im_scale, im_color, GL_TRIANGLES);
float length = 200 * sin(dt);
//Front //Front
im_pos(0.f, 0.f, 0.f); im_pos(0.f, 0.f, 0.f);
im_pos(0.f, 20.f, 0.f); im_pos(0.f, length, 0.f);
im_pos(20.f, 20.f, 0.f); im_pos(length, length, 0.f);
im_pos(20.f, 20.f, 0.f); im_pos(length, length, 0.f);
im_pos(20.f, 0.f, 0.f); im_pos(length, 0.f, 0.f);
im_pos( 0.f, 0.f, 0.f); im_pos( 0.f, 0.f, 0.f);
//Back //Back
im_pos(0.f, 0.f, 20.f); im_pos(0.f, 0.f, length);
im_pos(0.f, 20.f, 20.f); im_pos(0.f, length, length);
im_pos(20.f, 20.f, 20.f); im_pos(length, length, length);
im_pos(20.f, 20.f, 20.f); im_pos(length, length, length);
im_pos(20.f, 0.f, 20.f); im_pos(length, 0.f, length);
im_pos( 0.f, 0.f, 20.f); im_pos( 0.f, 0.f, length);
//Left //Left
im_pos(0.f, 0.f, 0.f); im_pos(0.f, 0.f, 0.f);
im_pos(0.f, 0.f, 20.f); im_pos(0.f, 0.f, length);
im_pos(0.f, 20.f, 20.f); im_pos(0.f, length, length);
im_pos(0.f, 20.f, 20.f); im_pos(0.f, length, length);
im_pos(0.f, 20.f, 0.f); im_pos(0.f, length, 0.f);
im_pos(0.f, 0.f, 20.f); im_pos(0.f, 0.f, length);
//Right //Right
im_pos(20.f, 0.f, 0.f); im_pos(length, 0.f, 0.f);
im_pos(20.f, 0.f, 20.f); im_pos(length, 0.f, length);
im_pos(20.f, 20.f, 20.f); im_pos(length, length, length);
im_pos(20.f, 20.f, 20.f); im_pos(length, length, length);
im_pos(20.f, 20.f, 0.f); im_pos(length, length, 0.f);
im_pos(20.f, 0.f, 20.f); im_pos(length, 0.f, length);
im_end(); im_end();
im_position.x = -30.f; im_position.x = -30.f;
im_begin(im_position, im_rot, im_scale, GL_LINES); im_begin(im_position, im_rot, im_scale, im_color, GL_LINES);
im_color(1.f, 1.f, 0.f, 1.f);
im_pos(0.f, 0.f, 0.f); im_pos(0.f, 0.f, 0.f);
im_pos(0.f, 0.f, 10.f); im_pos(0.f, 0.f, 10.f);
@ -520,7 +524,9 @@ void debug(float dt)
im_end(); im_end();
vec4 prim_color = {1.f, 1.f, 0.f, 1.f};
im_cube(5.f, im_position, im_rot, prim_color, GDM_TRIANGLES);
im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES);
} }
bool run(void) bool run(void)

@ -1,391 +1,391 @@
#include "geometry.h" #include "geometry.h"
#include "../common/array.h" #include "../common/array.h"
#include "../common/string_utils.h" #include "../common/string_utils.h"
#include "../common/log.h" #include "../common/log.h"
#include "renderer.h" #include "renderer.h"
#include "transform.h" #include "transform.h"
#include "../common/common.h" #include "../common/common.h"
#include "gl_load.h" #include "gl_load.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
/* Data */ /* Data */
static struct Geometry* geometry_list; static struct Geometry* geometry_list;
static int* empty_indices; static int* empty_indices;
static GLenum* draw_modes; static GLenum* draw_modes;
static int load_from_file(struct Geometry* geometry, const char* filename); static int load_from_file(struct Geometry* geometry, const char* filename);
static void create_vao(struct Geometry* geometry); static void create_vao(struct Geometry* geometry);
static struct Geometry* generate_new_index(int* out_new_index); static struct Geometry* generate_new_index(int* out_new_index);
void geom_init(void) void geom_init(void)
{ {
geometry_list = array_new(struct Geometry); geometry_list = array_new(struct Geometry);
empty_indices = array_new(int); empty_indices = array_new(int);
draw_modes = array_new_cap(GLenum, GDM_NUM_DRAWMODES); draw_modes = array_new_cap(GLenum, GDM_NUM_DRAWMODES);
draw_modes[GDM_TRIANGLES] = GL_TRIANGLES; draw_modes[GDM_TRIANGLES] = GL_TRIANGLES;
draw_modes[GDM_LINES] = GL_LINES; draw_modes[GDM_LINES] = GL_LINES;
draw_modes[GDM_POINTS] = GL_POINTS; draw_modes[GDM_POINTS] = GL_POINTS;
} }
int geom_find(const char* filename) int geom_find(const char* filename)
{ {
int index = -1; int index = -1;
for(int i = 0; i < array_len(geometry_list); i++) for(int i = 0; i < array_len(geometry_list); i++)
{ {
struct Geometry* geometry = &geometry_list[i]; struct Geometry* geometry = &geometry_list[i];
if(strcmp(geometry->filename, filename) == 0) if(strcmp(geometry->filename, filename) == 0)
{ {
index = i; index = i;
break; break;
} }
} }
return index; return index;
} }
void geom_bounding_volume_generate(int index) void geom_bounding_volume_generate(int index)
{ {
struct Geometry* geometry = &geometry_list[index]; struct Geometry* geometry = &geometry_list[index];
struct Bounding_Box* box = &geometry->bounding_box; struct Bounding_Box* box = &geometry->bounding_box;
struct Bounding_Sphere* sphere = &geometry->bounding_sphere; struct Bounding_Sphere* sphere = &geometry->bounding_sphere;
vec3_fill(&box->max, -FLT_MIN, -FLT_MIN, -FLT_MIN); vec3_fill(&box->max, -FLT_MIN, -FLT_MIN, -FLT_MIN);
vec3_fill(&box->min, FLT_MAX, FLT_MAX, FLT_MAX); vec3_fill(&box->min, FLT_MAX, FLT_MAX, FLT_MAX);
vec3_fill(&sphere->center, 0.f, 0.f, 0.f); vec3_fill(&sphere->center, 0.f, 0.f, 0.f);
sphere->radius = 0.f; sphere->radius = 0.f;
for(int i = 0; i < array_len(geometry->vertices); i++) for(int i = 0; i < array_len(geometry->vertices); i++)
{ {
vec3* vertex = &geometry->vertices[i]; vec3* vertex = &geometry->vertices[i];
if(vertex->x > box->max.x) box->max.x = vertex->x; if(vertex->x > box->max.x) box->max.x = vertex->x;
if(vertex->y > box->max.y) box->max.y = vertex->y; if(vertex->y > box->max.y) box->max.y = vertex->y;
if(vertex->z > box->max.z) box->max.z = vertex->z; if(vertex->z > box->max.z) box->max.z = vertex->z;
if(vertex->x < box->min.x) box->min.x = vertex->x; if(vertex->x < box->min.x) box->min.x = vertex->x;
if(vertex->y < box->min.y) box->min.y = vertex->y; if(vertex->y < box->min.y) box->min.y = vertex->y;
if(vertex->z < box->min.z) box->min.z = vertex->z; if(vertex->z < box->min.z) box->min.z = vertex->z;
} }
vec3_add(&sphere->center, &box->max, &box->min); vec3_add(&sphere->center, &box->max, &box->min);
vec3_scale(&sphere->center, &sphere->center, 0.5f); vec3_scale(&sphere->center, &sphere->center, 0.5f);
vec3 len_vec; vec3 len_vec;
vec3_sub(&len_vec, &box->max, &sphere->center); vec3_sub(&len_vec, &box->max, &sphere->center);
sphere->radius = fabsf(vec3_len(&len_vec)); sphere->radius = fabsf(vec3_len(&len_vec));
} }
void geom_bounding_volume_generate_all(void) void geom_bounding_volume_generate_all(void)
{ {
for(int i = 0; i < array_len(geometry_list); i++) for(int i = 0; i < array_len(geometry_list); i++)
geom_bounding_volume_generate(i); geom_bounding_volume_generate(i);
} }
static struct Geometry* generate_new_index(int* out_new_index) static struct Geometry* generate_new_index(int* out_new_index)
{ {
assert(out_new_index); assert(out_new_index);
int empty_len = array_len(empty_indices); int empty_len = array_len(empty_indices);
struct Geometry* new_geo = NULL; struct Geometry* new_geo = NULL;
if(empty_len > 0) if(empty_len > 0)
{ {
*out_new_index = empty_indices[empty_len - 1]; *out_new_index = empty_indices[empty_len - 1];
array_pop(empty_indices); array_pop(empty_indices);
new_geo = &geometry_list[*out_new_index]; new_geo = &geometry_list[*out_new_index];
} }
else else
{ {
new_geo = array_grow(geometry_list, struct Geometry); new_geo = array_grow(geometry_list, struct Geometry);
*out_new_index = array_len(geometry_list) - 1; *out_new_index = array_len(geometry_list) - 1;
} }
return new_geo; return new_geo;
} }
int geom_create_from_file(const char* name) int geom_create_from_file(const char* name)
{ {
assert(name); assert(name);
// check if exists // check if exists
int index = geom_find(name); int index = geom_find(name);
if(index == -1) if(index == -1)
{ {
/* add new geometry object or overwrite existing one */ /* add new geometry object or overwrite existing one */
struct Geometry* new_geo = NULL; struct Geometry* new_geo = NULL;
new_geo = generate_new_index(&index); new_geo = generate_new_index(&index);
assert(new_geo); assert(new_geo);
if(load_from_file(new_geo, name)) if(load_from_file(new_geo, name))
{ {
create_vao(new_geo); create_vao(new_geo);
geom_bounding_volume_generate(index); geom_bounding_volume_generate(index);
} }
else else
{ {
/* TODO: Some error here, find it and fix it */ /* TODO: Some error here, find it and fix it */
array_pop(geometry_list); array_pop(geometry_list);
index = -1; index = -1;
} }
} }
else else
{ {
geometry_list[index].ref_count++; geometry_list[index].ref_count++;
} }
return index; return index;
} }
int geom_create(const char* name, int geom_create(const char* name,
vec3* vertices, vec3* vertices,
vec2* uvs, vec2* uvs,
vec3* normals, vec3* normals,
uint* indices, uint* indices,
vec3* vertex_colors) vec3* vertex_colors)
{ {
assert(name && vertices && uvs && normals && indices); assert(name && vertices && uvs && normals && indices);
int index = -1; int index = -1;
/* add new geometry object or overwrite existing one */ /* add new geometry object or overwrite existing one */
struct Geometry* new_geo = NULL; struct Geometry* new_geo = NULL;
new_geo = generate_new_index(&index); new_geo = generate_new_index(&index);
assert(new_geo); assert(new_geo);
new_geo->filename = str_new(name); new_geo->filename = str_new(name);
new_geo->vertices = array_new_cap(vec3, array_len(vertices)); new_geo->vertices = array_new_cap(vec3, array_len(vertices));
array_copy(vertices, new_geo->vertices); array_copy(vertices, new_geo->vertices);
new_geo->normals = array_new_cap(vec3, array_len(normals)); new_geo->normals = array_new_cap(vec3, array_len(normals));
array_copy(normals, new_geo->normals); array_copy(normals, new_geo->normals);
new_geo->uvs = array_new_cap(vec2, array_len(uvs)); new_geo->uvs = array_new_cap(vec2, array_len(uvs));
array_copy(uvs, new_geo->uvs); array_copy(uvs, new_geo->uvs);
new_geo->indices = array_new_cap(uint, array_len(indices)); new_geo->indices = array_new_cap(uint, array_len(indices));
array_copy(indices, new_geo->indices); array_copy(indices, new_geo->indices);
if(vertex_colors) if(vertex_colors)
{ {
new_geo->vertex_colors = array_new_cap(vec3, array_len(vertex_colors)); new_geo->vertex_colors = array_new_cap(vec3, array_len(vertex_colors));
array_copy(vertex_colors, new_geo->vertex_colors); array_copy(vertex_colors, new_geo->vertex_colors);
} }
else else
{ {
new_geo->vertex_colors = array_new(vec3); new_geo->vertex_colors = array_new(vec3);
} }
create_vao(new_geo); create_vao(new_geo);
//generateBoundingBox(index); //generateBoundingBox(index);
return index; return index;
} }
void geom_remove(int index) void geom_remove(int index)
{ {
if(index >= 0 && index < array_len(geometry_list)) if(index >= 0 && index < array_len(geometry_list))
{ {
struct Geometry* geometry = &geometry_list[index]; struct Geometry* geometry = &geometry_list[index];
if(geometry->ref_count >= 0) if(geometry->ref_count >= 0)
{ {
geometry->ref_count--; geometry->ref_count--;
if(geometry->ref_count < 0) if(geometry->ref_count < 0)
{ {
if(geometry->indices) array_free(geometry->indices); if(geometry->indices) array_free(geometry->indices);
if(geometry->vertices) array_free(geometry->vertices); if(geometry->vertices) array_free(geometry->vertices);
if(geometry->uvs) array_free(geometry->uvs); if(geometry->uvs) array_free(geometry->uvs);
if(geometry->normals) array_free(geometry->normals); if(geometry->normals) array_free(geometry->normals);
if(geometry->vertex_colors) array_free(geometry->vertex_colors); if(geometry->vertex_colors) array_free(geometry->vertex_colors);
if(geometry->filename) free(geometry->filename); if(geometry->filename) free(geometry->filename);
geometry->indices = NULL; geometry->indices = NULL;
geometry->vertices = NULL; geometry->vertices = NULL;
geometry->uvs = NULL; geometry->uvs = NULL;
geometry->normals = NULL; geometry->normals = NULL;
geometry->vertex_colors = NULL; geometry->vertex_colors = NULL;
geometry->filename = NULL; geometry->filename = NULL;
glDeleteBuffers(1, &geometry->vertex_vbo); glDeleteBuffers(1, &geometry->vertex_vbo);
glDeleteBuffers(1, &geometry->color_vbo); glDeleteBuffers(1, &geometry->color_vbo);
glDeleteBuffers(1, &geometry->uv_vbo); glDeleteBuffers(1, &geometry->uv_vbo);
glDeleteBuffers(1, &geometry->normal_vbo); glDeleteBuffers(1, &geometry->normal_vbo);
glDeleteBuffers(1, &geometry->index_vbo); glDeleteBuffers(1, &geometry->index_vbo);
glDeleteVertexArrays(1, &geometry->vao); glDeleteVertexArrays(1, &geometry->vao);
geometry->vertex_vbo = 0; geometry->vertex_vbo = 0;
geometry->color_vbo = 0; geometry->color_vbo = 0;
geometry->uv_vbo = 0; geometry->uv_vbo = 0;
geometry->normal_vbo = 0; geometry->normal_vbo = 0;
geometry->index_vbo = 0; geometry->index_vbo = 0;
geometry->vao = 0; geometry->vao = 0;
array_push(empty_indices, index, int); array_push(empty_indices, index, int);
} }
} }
} }
} }
void geom_cleanup(void) void geom_cleanup(void)
{ {
for(int i = 0; i < array_len(geometry_list); i++) for(int i = 0; i < array_len(geometry_list); i++)
geom_remove(i); geom_remove(i);
array_free(geometry_list); array_free(geometry_list);
array_free(empty_indices); array_free(empty_indices);
array_free(draw_modes); array_free(draw_modes);
} }
static int load_from_file(struct Geometry* geometry, const char* filename) static int load_from_file(struct Geometry* geometry, const char* filename)
{ {
assert(filename); assert(filename);
int success = 1; int success = 1;
char* full_path = str_new("models/%s", filename); char* full_path = str_new("models/%s", filename);
FILE* file = platform->file.open(DIRT_INSTALL, full_path, "rb"); FILE* file = platform->file.open(DIRT_INSTALL, full_path, "rb");
free(full_path); free(full_path);
if(file) if(file)
{ {
const uint32 INDEX_SIZE = sizeof(uint32); const uint32 INDEX_SIZE = sizeof(uint32);
const uint32 VEC3_SIZE = sizeof(vec3); const uint32 VEC3_SIZE = sizeof(vec3);
const uint32 VEC2_SIZE = sizeof(vec2); const uint32 VEC2_SIZE = sizeof(vec2);
uint32 header[4]; uint32 header[4];
size_t bytes_read = 0; size_t bytes_read = 0;
if((bytes_read = fread(header, INDEX_SIZE, 4, file)) <= 0) if((bytes_read = fread(header, INDEX_SIZE, 4, file)) <= 0)
{ {
log_error("geometry:load_from_file", "Read failed"); log_error("geometry:load_from_file", "Read failed");
success = 0; success = 0;
} }
else else
{ {
uint32 indices_count = header[0]; uint32 indices_count = header[0];
uint32 vertices_count = header[1]; uint32 vertices_count = header[1];
uint32 normals_count = header[2]; uint32 normals_count = header[2];
uint32 uvs_count = header[3]; uint32 uvs_count = header[3];
// Indices // Indices
geometry->indices = array_new_cap(uint, indices_count); geometry->indices = array_new_cap(uint, indices_count);
fread(geometry->indices, INDEX_SIZE, indices_count, file); fread(geometry->indices, INDEX_SIZE, indices_count, file);
array_match_len_cap(geometry->indices); array_match_len_cap(geometry->indices);
// Vertices // Vertices
geometry->vertices = array_new_cap(vec3, vertices_count); geometry->vertices = array_new_cap(vec3, vertices_count);
fread(geometry->vertices, VEC3_SIZE, vertices_count, file); fread(geometry->vertices, VEC3_SIZE, vertices_count, file);
array_match_len_cap(geometry->vertices); array_match_len_cap(geometry->vertices);
// Normals // Normals
geometry->normals = array_new_cap(vec3, normals_count); geometry->normals = array_new_cap(vec3, normals_count);
fread(geometry->normals, VEC3_SIZE, normals_count, file); fread(geometry->normals, VEC3_SIZE, normals_count, file);
array_match_len_cap(geometry->normals); array_match_len_cap(geometry->normals);
// Uvs // Uvs
geometry->uvs = array_new_cap(vec2, uvs_count); geometry->uvs = array_new_cap(vec2, uvs_count);
fread(geometry->uvs, VEC2_SIZE, uvs_count, file); fread(geometry->uvs, VEC2_SIZE, uvs_count, file);
array_match_len_cap(geometry->uvs); array_match_len_cap(geometry->uvs);
geometry->vertex_colors = array_new(vec3); geometry->vertex_colors = array_new(vec3);
} }
fclose(file); fclose(file);
geometry->filename = str_new(filename); geometry->filename = str_new(filename);
geometry->draw_indexed = 1; geometry->draw_indexed = 1;
geometry->ref_count++; geometry->ref_count++;
} }
else else
{ {
success = 0; success = 0;
} }
return success; return success;
} }
static void create_vao(struct Geometry* geometry) static void create_vao(struct Geometry* geometry)
{ {
// TODO: Add support for different model formats and interleaving VBO // TODO: Add support for different model formats and interleaving VBO
assert(geometry); assert(geometry);
glGenVertexArrays(1, &geometry->vao); glGenVertexArrays(1, &geometry->vao);
glBindVertexArray(geometry->vao); glBindVertexArray(geometry->vao);
glGenBuffers(1, &geometry->vertex_vbo); glGenBuffers(1, &geometry->vertex_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_vbo);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
array_len(geometry->vertices) * sizeof(vec3), array_len(geometry->vertices) * sizeof(vec3),
geometry->vertices, geometry->vertices,
GL_STATIC_DRAW); GL_STATIC_DRAW);
renderer_check_glerror("geometry:create_vbo:vertex"); renderer_check_glerror("geometry:create_vbo:vertex");
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
if(array_len(geometry->normals) > 0) if(array_len(geometry->normals) > 0)
{ {
glGenBuffers(1, &geometry->normal_vbo); glGenBuffers(1, &geometry->normal_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->normal_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->normal_vbo);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
array_len(geometry->normals) * sizeof(vec3), array_len(geometry->normals) * sizeof(vec3),
geometry->normals, geometry->normals,
GL_STATIC_DRAW); GL_STATIC_DRAW);
renderer_check_glerror("geometry:create_vbo:normal"); renderer_check_glerror("geometry:create_vbo:normal");
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, 0);
} }
if(array_len(geometry->uvs) > 0) if(array_len(geometry->uvs) > 0)
{ {
glGenBuffers(1, &geometry->uv_vbo); glGenBuffers(1, &geometry->uv_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->uv_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->uv_vbo);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
array_len(geometry->uvs) * sizeof(vec2), array_len(geometry->uvs) * sizeof(vec2),
geometry->uvs, geometry->uvs,
GL_STATIC_DRAW); GL_STATIC_DRAW);
renderer_check_glerror("geometry:create_vbo:uv"); renderer_check_glerror("geometry:create_vbo:uv");
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
} }
if(array_len(geometry->vertex_colors) > 0) if(array_len(geometry->vertex_colors) > 0)
{ {
glGenBuffers(1, &geometry->color_vbo); glGenBuffers(1, &geometry->color_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->color_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->color_vbo);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
array_len(geometry->vertex_colors) * sizeof(vec3), array_len(geometry->vertex_colors) * sizeof(vec3),
geometry->vertex_colors, geometry->vertex_colors,
GL_STATIC_DRAW); GL_STATIC_DRAW);
renderer_check_glerror("geometry:create_vbo:color"); renderer_check_glerror("geometry:create_vbo:color");
glEnableVertexAttribArray(3); glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0);
} }
if(array_len(geometry->indices) > 0) if(array_len(geometry->indices) > 0)
{ {
glGenBuffers(1, &geometry->index_vbo); glGenBuffers(1, &geometry->index_vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, glBufferData(GL_ELEMENT_ARRAY_BUFFER,
array_len(geometry->indices) * sizeof(GLuint), array_len(geometry->indices) * sizeof(GLuint),
geometry->indices, geometry->indices,
GL_STATIC_DRAW); GL_STATIC_DRAW);
geometry->draw_indexed = 1; geometry->draw_indexed = 1;
} }
glBindVertexArray(0); glBindVertexArray(0);
} }
void geom_render(int index, enum Geometry_Draw_Mode draw_mode) void geom_render(int index, enum Geometry_Draw_Mode draw_mode)
{ {
assert((int)draw_mode > -1 && draw_mode < GDM_NUM_DRAWMODES); assert((int)draw_mode > -1 && draw_mode < GDM_NUM_DRAWMODES && index >= 0);
struct Geometry* geo = &geometry_list[index]; struct Geometry* geo = &geometry_list[index];
glBindVertexArray(geo->vao); glBindVertexArray(geo->vao);
if(geo->draw_indexed) if(geo->draw_indexed)
glDrawElements(draw_modes[draw_mode], array_len(geo->indices), GL_UNSIGNED_INT, (void*)0); glDrawElements(draw_modes[draw_mode], array_len(geo->indices), GL_UNSIGNED_INT, (void*)0);
else else
glDrawArrays(draw_modes[draw_mode], 0, array_len(geo->vertices)); glDrawArrays(draw_modes[draw_mode], 0, array_len(geo->vertices));
glBindVertexArray(0); glBindVertexArray(0);
} }
int geom_render_in_frustum(int index, int geom_render_in_frustum(int index,
vec4* frustum, vec4* frustum,
struct Entity* entity, struct Entity* entity,
enum Geometry_Draw_Mode draw_mode) enum Geometry_Draw_Mode draw_mode)
{ {
struct Geometry* geometry = &geometry_list[index]; struct Geometry* geometry = &geometry_list[index];
int indices_rendered = 0; int indices_rendered = 0;
int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, entity); int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, entity);
if(intersection == IT_INTERSECT || intersection == IT_INSIDE) if(intersection == IT_INTERSECT || intersection == IT_INSIDE)
{ {
geom_render(index, draw_mode); geom_render(index, draw_mode);
indices_rendered = array_len(geometry->indices); indices_rendered = array_len(geometry->indices);
/* intersection = bv_intersect_frustum_box(frustum, &geometry->bounding_box, entity); */ /* intersection = bv_intersect_frustum_box(frustum, &geometry->bounding_box, entity); */
/* if(intersection == IT_INTERSECT || intersection == IT_INSIDE) */ /* if(intersection == IT_INTERSECT || intersection == IT_INSIDE) */
/* { */ /* { */
/* geom_render(index, draw_mode); */ /* geom_render(index, draw_mode); */
/* rendered = array_len(geometry->indices); */ /* rendered = array_len(geometry->indices); */
/* } */ /* } */
} }
return indices_rendered; return indices_rendered;
} }
struct Geometry* geom_get(int index) struct Geometry* geom_get(int index)
{ {
assert(index > -1 && index < array_len(geometry_list)); assert(index > -1 && index < array_len(geometry_list));
return &geometry_list[index]; return &geometry_list[index];
} }

@ -6,8 +6,9 @@
#include "../common/num_types.h" #include "../common/num_types.h"
#include "shader.h" #include "shader.h"
#include "../common/log.h" #include "../common/log.h"
#include "geometry.h"
#define MAX_IM_VERTICES 4096 #define MAX_IM_VERTICES 2048
#define MAX_IM_GEOMETRIES (MAX_IM_VERTICES / 2) #define MAX_IM_GEOMETRIES (MAX_IM_VERTICES / 2)
static struct static struct
@ -19,12 +20,11 @@ static struct
int im_shader; int im_shader;
int curr_geom; int curr_geom;
int curr_vertex; int curr_vertex;
vec4 default_color;
} }
IM_State; IM_State;
static struct IM_Geom* active_geom = NULL; static struct IM_Geom* active_geom = NULL;
static vec4 active_vertex_color = { 0.f, 0.f, 0.f, 0.f }; static int active_vertex_index = 0;
void im_init(void) void im_init(void)
{ {
@ -33,15 +33,15 @@ void im_init(void)
glGenBuffers(1, &IM_State.vbo); glGenBuffers(1, &IM_State.vbo);
glBindBuffer(GL_ARRAY_BUFFER, IM_State.vbo); glBindBuffer(GL_ARRAY_BUFFER, IM_State.vbo);
GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(struct IM_Vertex) * MAX_IM_VERTICES, NULL, GL_STREAM_DRAW)); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(struct IM_Vertex) * MAX_IM_VERTICES * MAX_IM_GEOMETRIES, NULL, GL_STREAM_DRAW));
//Position //Position
GL_CHECK(glVertexAttribPointer(ATTRIB_LOC_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(struct IM_Vertex), 0)); GL_CHECK(glVertexAttribPointer(ATTRIB_LOC_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(struct IM_Vertex), 0));
GL_CHECK(glEnableVertexAttribArray(ATTRIB_LOC_POSITION)); GL_CHECK(glEnableVertexAttribArray(ATTRIB_LOC_POSITION));
//Color ////Color
GL_CHECK(glVertexAttribPointer(ATTRIB_LOC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(struct IM_Vertex), sizeof(vec3))); //GL_CHECK(glVertexAttribPointer(ATTRIB_LOC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(struct IM_Vertex), sizeof(vec3)));
GL_CHECK(glEnableVertexAttribArray(ATTRIB_LOC_COLOR)); //GL_CHECK(glEnableVertexAttribArray(ATTRIB_LOC_COLOR));
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -51,8 +51,6 @@ void im_init(void)
memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES); memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES);
IM_State.curr_geom = -1; IM_State.curr_geom = -1;
IM_State.curr_vertex = 0; IM_State.curr_vertex = 0;
vec4_fill(&IM_State.default_color, 1.f, 0.f, 1.f, 1.f);
vec4_assign(&active_vertex_color, &IM_State.default_color);
IM_State.im_shader = shader_create("im_geom.vert", "im_geom.frag"); IM_State.im_shader = shader_create("im_geom.vert", "im_geom.frag");
} }
@ -72,7 +70,7 @@ void im_cleanup(void)
IM_State.im_shader = -1; IM_State.im_shader = -1;
} }
void im_begin(vec3 position, quat rotation, vec3 scale, int draw_mode) void im_begin(vec3 position, quat rotation, vec3 scale, vec4 color, int draw_mode)
{ {
if(active_geom) if(active_geom)
{ {
@ -82,36 +80,79 @@ void im_begin(vec3 position, quat rotation, vec3 scale, int draw_mode)
IM_State.curr_geom++; IM_State.curr_geom++;
active_geom = &IM_State.geometries[IM_State.curr_geom]; active_geom = &IM_State.geometries[IM_State.curr_geom];
active_geom->start_index = IM_State.curr_vertex; active_geom->start_index = IM_State.curr_vertex;
active_geom->type = IGT_DYNAMIC;
active_geom->draw_mode = draw_mode; active_geom->draw_mode = draw_mode;
vec3_assign(&active_geom->position, &position); vec3_assign(&active_geom->position, &position);
vec3_assign(&active_geom->scale, &scale); vec3_assign(&active_geom->scale, &scale);
vec4_assign(&active_geom->color, &color);
quat_assign(&active_geom->rotation, &rotation); quat_assign(&active_geom->rotation, &rotation);
} }
void im_pos(float x, float y, float z) void im_pos(float x, float y, float z)
{ {
vec3_fill(&IM_State.vertices[IM_State.curr_vertex].position, x, y, z); if(IM_State.curr_vertex == MAX_IM_VERTICES)
vec4_assign(&IM_State.vertices[IM_State.curr_vertex].color, &active_vertex_color); {
log_error("im_pos", "Buffer full!");
return;
}
vec3_fill(&IM_State.vertices[active_vertex_index].position, x, y, z);
IM_State.curr_vertex++; IM_State.curr_vertex++;
active_vertex_index++;
}
void im_cube(float length, vec3 position, quat rotation, vec4 color, int draw_mode)
{
if(active_geom)
{
log_error("im_begin", "im_begin called before im_end");
return;
}
IM_State.curr_geom++;
active_geom = &IM_State.geometries[IM_State.curr_geom];
active_geom->type = IGT_PRIMITIVE;
active_geom->draw_mode = draw_mode;
active_geom->prim_geom_index = geom_create_from_file("cube.symbres");
vec3_assign(&active_geom->position, &position);
vec3 scale = { length, length, length };
vec3_assign(&active_geom->scale, &scale);
vec4_assign(&active_geom->color, &color);
quat_assign(&active_geom->rotation, &rotation);
active_geom = NULL;
} }
void im_color(float r, float g, float b, float a) void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode)
{ {
vec4_fill(&active_vertex_color, r, g, b, a); if(active_geom)
{
log_error("im_begin", "im_begin called before im_end");
return;
}
IM_State.curr_geom++;
active_geom = &IM_State.geometries[IM_State.curr_geom];
active_geom->type = IGT_PRIMITIVE;
active_geom->draw_mode = draw_mode;
active_geom->prim_geom_index = geom_create_from_file("sphere.symbres");
vec3_assign(&active_geom->position, &position);
vec3 scale = { radius, radius, radius };
vec3_assign(&active_geom->scale, &scale);
quat_assign(&active_geom->rotation, &rotation);
vec4_assign(&active_geom->color, &color);
active_geom = NULL;
} }
void im_end(void) void im_end(void)
{ {
active_geom->num_vertices = IM_State.curr_vertex - active_geom->start_index; active_geom->num_vertices = active_vertex_index + 1;
glBindBuffer(GL_ARRAY_BUFFER, IM_State.vbo); glBindBuffer(GL_ARRAY_BUFFER, IM_State.vbo);
glBufferSubData(GL_ARRAY_BUFFER, GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER,
sizeof(struct IM_Vertex) * active_geom->start_index, sizeof(struct IM_Vertex) * active_geom->start_index,
sizeof(struct IM_Vertex) * active_geom->num_vertices, sizeof(struct IM_Vertex) * active_geom->num_vertices,
&IM_State.vertices[active_geom->start_index]); &IM_State.vertices[0]));
renderer_check_glerror("sprite_batch_end:glBufferSubData");
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
active_geom = NULL; active_geom = NULL;
vec4_assign(&active_vertex_color, &IM_State.default_color); active_vertex_index = 0;
memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES);
} }
void im_render(struct Entity* active_viewer) void im_render(struct Entity* active_viewer)
@ -121,31 +162,40 @@ void im_render(struct Entity* active_viewer)
shader_bind(IM_State.im_shader); shader_bind(IM_State.im_shader);
{ {
static mat4 mvp, translation, rotation, scale; static mat4 mvp, translation, rotation, scale;
glBindVertexArray(IM_State.vao); glBindVertexArray(IM_State.vao);
for(int i = 0; i <= IM_State.curr_geom; i++) for(int i = 0; i <= IM_State.curr_geom; i++)
{ {
struct IM_Geom* geom = &IM_State.geometries[i]; struct IM_Geom* geom = &IM_State.geometries[i];
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_identity(&scale); mat4_identity(&scale);
mat4_identity(&translation); mat4_identity(&translation);
mat4_identity(&rotation); mat4_identity(&rotation);
mat4_scale(&scale, geom->scale.x, geom->scale.y, geom->scale.z); mat4_scale(&scale, geom->scale.x, geom->scale.y, geom->scale.z);
mat4_translate(&translation, geom->position.x, geom->position.y, geom->position.z); mat4_translate(&translation, geom->position.x, geom->position.y, geom->position.z);
mat4_from_quat(&rotation, &geom->rotation); mat4_from_quat(&rotation, &geom->rotation);
mat4_mul(&mvp, &mvp, &translation); mat4_mul(&mvp, &mvp, &translation);
mat4_mul(&mvp, &mvp, &rotation); mat4_mul(&mvp, &mvp, &rotation);
mat4_mul(&mvp, &mvp, &scale); mat4_mul(&mvp, &mvp, &scale);
mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &mvp); mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &mvp);
shader_set_uniform_mat4(IM_State.im_shader, "mvp", &mvp); shader_set_uniform_mat4(IM_State.im_shader, "mvp", &mvp);
shader_set_uniform_vec4(IM_State.im_shader, "geom_color", &geom->color);
glDrawArrays(geom->draw_mode, geom->start_index, geom->num_vertices); if(geom->type == IGT_DYNAMIC)
{
glDrawArrays(geom->draw_mode, geom->start_index, geom->num_vertices);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
geom_render(geom->prim_geom_index, geom->draw_mode);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
} }
glBindVertexArray(0); glBindVertexArray(0);

@ -6,7 +6,12 @@
struct IM_Vertex struct IM_Vertex
{ {
vec3 position; vec3 position;
vec4 color; };
enum IM_Geom_Type
{
IGT_PRIMITIVE = 0,
IGT_DYNAMIC
}; };
struct IM_Geom struct IM_Geom
@ -14,8 +19,18 @@ struct IM_Geom
vec3 position; vec3 position;
quat rotation; quat rotation;
vec3 scale; vec3 scale;
int start_index; vec4 color;
int num_vertices; int type;
union
{
struct
{
int start_index;
int num_vertices;
};
int prim_geom_index;
};
int draw_mode; int draw_mode;
}; };
@ -23,9 +38,10 @@ struct Entity;
void im_init(void); void im_init(void);
void im_cleanup(void); void im_cleanup(void);
void im_begin(vec3 position, quat rotation, vec3 scale, int draw_mode); void im_begin(vec3 position, quat rotation, vec3 scale, vec4 color, int draw_mode);
void im_pos(float x, float y, float z); void im_pos(float x, float y, float z);
void im_color(float r, float g, float b, float a); // set active color void im_cube(float length, vec3 position, quat rotation, vec4 color, int draw_mode);
void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode);
void im_end(void); void im_end(void);
void im_render(struct Entity* active_viewer); void im_render(struct Entity* active_viewer);

Loading…
Cancel
Save