First commit

dev
Shariq Shah 10 years ago
commit b764ec95e7
  1. 4
      .dir-locals.el
  2. 29
      premake4.lua
  3. 133
      src/array.c
  4. 41
      src/array.h
  5. 50
      src/game.c
  6. 7
      src/game.h
  7. 72
      src/input.c
  8. 23
      src/input.h
  9. 547
      src/linmath.h
  10. 24
      src/log.c
  11. 7
      src/log.h
  12. 54
      src/main.c
  13. 25
      src/renderer.c
  14. 10
      src/renderer.h
  15. 107
      src/string_utils.c
  16. 12
      src/string_utils.h
  17. 94
      src/window_system.c
  18. 22
      src/window_system.h

@ -0,0 +1,4 @@
((c-mode .
((company-clang-arguments . ("-I/mnt/Dev/Projects/Symmetry/include/GLFW"))
(flycheck-clang-include-path . ("/mnt/Dev/Projects/Symmetry/include/GLFW")))
))

@ -0,0 +1,29 @@
solution "Symmetry"
configurations {"Debug", "Release"}
location "build"
language "C"
includedirs {"include/**"}
buildoptions {"-Wall", "-std=c11"}
linkoptions { "`pkg-config --libs --static glfw3`" }
links {"GLEW"}
-- local cmd_stream = assert(io.popen("pkg-config --libs --static glfw3", r))
-- local libs_to_link = assert(cmd_stream:read("*all"))
-- cmd_stream:close()
-- libs_to_link = string.gsub(libs_to_link, "-lglfw", "")
-- libs_to_link = string.gsub(libs_to_link, "\n", "")
-- linkoptions {libs_to_link}
project "Symmetry"
kind "ConsoleApp"
files { "src/*.h", "src/*.c"}
configuration "Debug"
flags {"Symbols"}
targetdir "bin/debug"
configuration "Release"
defines {"NDEBUG"}
flags {"Optimize"}
targetdir "bin/release"

@ -0,0 +1,133 @@
#include <stdlib.h>
#include <string.h>
#include "array.h"
#define ARRAY_MIN_CAPACITY 2
static bool array_reallocate(Array* array);
Array* array_new_(size_t object_size)
{
Array* newArray = malloc(sizeof(Array));
newArray->object_size = object_size;
newArray->length = 0;
newArray->capacity = ARRAY_MIN_CAPACITY;
newArray->data = malloc(newArray->object_size * newArray->capacity);
return newArray;
}
void array_free(Array* array)
{
free(array->data);
free(array);
}
void* array_get(Array* array, unsigned int index)
{
return array->data + (array->object_size * index);
}
void* array_top(Array* array)
{
return array->data + (array->object_size * (array->length - 1));
}
void* array_add(Array* array)
{
/* if capacity is full, double size */
if(++array->length > array->capacity)
{
array->capacity = array->capacity << 1; /* LShift by 1 means (number * number) */
char* new_data = realloc(array->data, array->object_size * array->capacity);
if(new_data)
{
array->data = new_data;
}
else
{
array->length--;
array->capacity = array->capacity >> 1;
/* TODO: Error handling here! */
}
}
/* return new location added */
return array->data + (array->object_size * (array->length - 1));
}
void array_reset(Array* array, unsigned int length)
{
free(array->data);
array->length = length;
array->capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length;
array->data = malloc(array->object_size * array->capacity);
}
bool array_pop(Array* array)
{
bool success = false;
if(array->length > 0)
{
array->length--;
success = array_reallocate(array);
}
return success;
}
bool array_reallocate(Array* array)
{
bool success = true;
/* If capacity is too big i.e. 4 times larger than length, halve it */
if((array->length << 2) < array->capacity && array->capacity > ARRAY_MIN_CAPACITY)
{
array->capacity = array->capacity >> 1;
char* new_data = realloc(array->data, array->object_size * array->capacity);
if(new_data)
array->data = new_data;
else
success = false;
}
return success;
}
bool array_remove_at(Array* array, unsigned int index)
{
bool success = false;
if(array->length > 0)
{
unsigned int next_index = index++;
if(next_index < array->length)
{
array->length--;
char* current_location = array->data + (array->object_size * index);
char* location_after_obj = current_location + array->object_size;
memmove(current_location,
location_after_obj,
array->object_size * ((array->length - 1) - next_index));
success = array_reallocate(array);
}
else
{
success = array_pop(array);
}
}
return success;
}
void* array_begin(Array* array)
{
return array->data;
}
void* array_end(Array* array)
{
return array->data + (array->object_size * array->length);
}
void array_sort(Array* array, int (*compar)(const void*, const void*))
{
qsort(array->data, array->length, array->object_size, compar);
}

@ -0,0 +1,41 @@
#ifndef ARRAY_H
#define ARRAY_H
#include <stddef.h>
#include <stdbool.h>
typedef struct
{
char* data; // actual data
unsigned int capacity; // current capacity i.e memory allocated
unsigned int length; // current length of array
size_t object_size; // size per element
} Array;
Array* array_new_(size_t object_size);
#define array_new(type) array_new_(sizeof(type)); // Use this for array creation
void array_free(Array* array);
// All the macros with _val return by value while the function returns pointer
void* array_get(Array* array, unsigned int index);
#define array_get_val(array, type, index) (*((type*) array_get(array, index)))
void* array_top(Array* array);
#define array_top_val(array, type) (*((type*) array_top(array)))
void* array_add(Array* array);
#define array_add_val(array, type) (*((type*) array_add(array)))
void array_reset(Array* array, unsigned int length); // Resize to length objects whose data is unspecified
#define array_clear(array) array_reset(array, 0)
bool array_pop(Array* array); // Remove object with highest index
bool array_remove_at(Array* array, unsigned int index);
void* array_begin(Array* array);
void* array_end(Array* array);
void array_sort(Array* array, int (*compar)(const void*, const void*)); // Sort array by providing a comparator function
#endif

@ -0,0 +1,50 @@
#include "game.h"
#include "GLFW/glfw3.h"
#include "window_system.h"
#include "input.h"
#include "renderer.h"
#include "log.h"
void run(void);
void update(void);
void render(void);
void game_init(void)
{
GLFWwindow* window = window_get_active();
input_init(window);
renderer_init(window);
run();
}
void run(void)
{
while(!window_should_close())
{
update();
render();
window_swap_buffers();
window_poll_events();
}
}
void update(void)
{
if(input_get_key_state(GLFW_KEY_A, GLFW_REPEAT))
log_message("A released");
if(input_get_mousebutton_state(GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS))
log_message("Left mouse released");
}
void render(void)
{
renderer_draw();
}
void game_cleanup(void)
{
input_cleanup();
renderer_cleanup();
}

@ -0,0 +1,7 @@
#ifndef game_H
#define game_H
void game_init(void);
void game_cleanup(void);
#endif

@ -0,0 +1,72 @@
#include <assert.h>
#include "input.h"
#include "GLFW/glfw3.h"
#include "window_system.h"
#include "log.h"
void input_on_key(GLFWwindow* window, int key, int scancode, int action, int mods);
void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods);
void input_on_cursor_move(GLFWwindow* window, double xpos, double ypos);
void input_init(GLFWwindow* window)
{
glfwSetMouseButtonCallback(window, input_on_mousebutton);
glfwSetKeyCallback(window, input_on_key);
glfwSetCursorPosCallback(window, input_on_cursor_move);
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
}
void input_cleanup(void)
{
}
void input_on_cursor_move(GLFWwindow* window, double xpos, double ypos)
{
}
void input_get_cursor_pos(double* xpos, double* ypos)
{
assert(xpos && ypos);
GLFWwindow* window = window_get_active();
glfwGetCursorPos(window, xpos, ypos);
}
void input_on_key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}
void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods)
{
}
void input_set_cursor_mode(Cursor_Mode mode)
{
GLFWwindow* window = window_get_active();
int cursor_mode = GLFW_CURSOR_NORMAL;
if(mode == CM_HIDDEN)
cursor_mode = GLFW_CURSOR_HIDDEN;
else if(mode == CM_HIDDEN)
cursor_mode = GLFW_CURSOR_DISABLED;
glfwSetInputMode(window, GLFW_CURSOR, cursor_mode);
}
bool input_get_key_state(int key, int state_type)
{
GLFWwindow* window = window_get_active();
int current_state = glfwGetKey(window, key);
return current_state == state_type ? true : false;
}
bool input_get_mousebutton_state(int button, int state_type)
{
GLFWwindow* window = window_get_active();
int current_state = glfwGetMouseButton(window, button);
return current_state == state_type ? true : false;
}

@ -0,0 +1,23 @@
#ifndef input_H
#define input_H
#include <stdbool.h>
struct GLFWwindow;
typedef struct GLFWwindow GLFWwindow;
typedef enum
{
CM_NORMAL = 0,
CM_LOCKED,
CM_HIDDEN
} Cursor_Mode;
void input_init(GLFWwindow* window);
void input_cleanup(void);
bool input_get_mousebutton_state(int button, int state_type);
bool input_get_key_state(int key, int state_type);
void input_get_cursor_pos(double* xpos, double* ypos);
void input_set_cursor_mode(Cursor_Mode mode);
#endif

@ -0,0 +1,547 @@
#ifndef linmath_H
#define linmath_H
#include <math.h>
#define LINMATH_H_DEFINE_VEC(n) \
typedef float vec##n[n]; \
static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] + b[i]; \
} \
static inline void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] - b[i]; \
} \
static inline void vec##n##_scale(vec##n r, vec##n const v, float const s) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = v[i] * s; \
} \
static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
{ \
float p = 0.; \
int i; \
for(i=0; i<n; ++i) \
p += b[i]*a[i]; \
return p; \
} \
static inline float vec##n##_len(vec##n const v) \
{ \
return sqrtf(vec##n##_mul_inner(v,v)); \
} \
static inline void vec##n##_norm(vec##n r, vec##n const v) \
{ \
float k = 1.0 / vec##n##_len(v); \
vec##n##_scale(r, v, k); \
}
LINMATH_H_DEFINE_VEC(2)
LINMATH_H_DEFINE_VEC(3)
LINMATH_H_DEFINE_VEC(4)
static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
}
static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
{
float p = 2.f*vec3_mul_inner(v, n);
int i;
for(i=0;i<3;++i)
r[i] = v[i] - p*n[i];
}
static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
r[3] = 1.f;
}
static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
{
float p = 2.f*vec4_mul_inner(v, n);
int i;
for(i=0;i<4;++i)
r[i] = v[i] - p*n[i];
}
typedef vec4 mat4x4[4];
static inline void mat4x4_identity(mat4x4 M)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = i==j ? 1.f : 0.f;
}
static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = N[i][j];
}
static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[k][i];
}
static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[i][k];
}
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
{
int i, j;
for(j=0; j<4; ++j)
for(i=0; i<4; ++i)
M[i][j] = N[j][i];
}
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]);
}
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]);
}
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
{
int i;
for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k);
}
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
{
int i;
vec4_scale(M[0], a[0], x);
vec4_scale(M[1], a[1], y);
vec4_scale(M[2], a[2], z);
for(i = 0; i < 4; ++i) {
M[3][i] = a[3][i];
}
}
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
{
mat4x4 temp;
int k, r, c;
for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
temp[c][r] = 0.f;
for(k=0; k<4; ++k)
temp[c][r] += a[k][r] * b[c][k];
}
mat4x4_dup(M, temp);
}
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
{
int i, j;
for(j=0; j<4; ++j) {
r[j] = 0.f;
for(i=0; i<4; ++i)
r[j] += M[i][j] * v[i];
}
}
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
{
mat4x4_identity(T);
T[3][0] = x;
T[3][1] = y;
T[3][2] = z;
}
static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
{
vec4 t = {x, y, z, 0};
vec4 r;
int i;
for (i = 0; i < 4; ++i) {
mat4x4_row(r, M, i);
M[3][i] += vec4_mul_inner(r, t);
}
}
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
{
int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
}
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) {
vec3_norm(u, u);
mat4x4 T;
mat4x4_from_vec3_mul_outer(T, u, u);
mat4x4 S = {
{ 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0},
{ u[1], -u[0], 0, 0},
{ 0, 0, 0, 0}
};
mat4x4_scale(S, S, s);
mat4x4 C;
mat4x4_identity(C);
mat4x4_sub(C, C, T);
mat4x4_scale(C, C, c);
mat4x4_add(T, T, C);
mat4x4_add(T, T, S);
T[3][3] = 1.;
mat4x4_mul(R, M, T);
} else {
mat4x4_dup(R, M);
}
}
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{1.f, 0.f, 0.f, 0.f},
{0.f, c, s, 0.f},
{0.f, -s, c, 0.f},
{0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, 0.f, s, 0.f},
{ 0.f, 1.f, 0.f, 0.f},
{ -s, 0.f, c, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, s, 0.f, 0.f},
{ -s, c, 0.f, 0.f},
{ 0.f, 0.f, 1.f, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
{
float s[6];
float c[6];
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
}
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
{
mat4x4_dup(R, M);
float s = 1.;
vec3 h;
vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h);
vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h);
vec3_norm(R[1], R[1]);
s = vec3_mul_inner(R[0], R[1]);
vec3_scale(h, R[1], s);
vec3_sub(R[0], R[0], h);
vec3_norm(R[0], R[0]);
}
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][0] = (r+l)/(r-l);
M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f;
}
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n);
M[3][3] = 1.f;
}
static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
{
/* NOTE: Degrees are an unhandy unit to work with.
* linmath.h uses radians for everything! */
float const a = 1.f / tan(y_fov / 2.f);
m[0][0] = a / aspect;
m[0][1] = 0.f;
m[0][2] = 0.f;
m[0][3] = 0.f;
m[1][0] = 0.f;
m[1][1] = a;
m[1][2] = 0.f;
m[1][3] = 0.f;
m[2][0] = 0.f;
m[2][1] = 0.f;
m[2][2] = -((f + n) / (f - n));
m[2][3] = -1.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = -((2.f * f * n) / (f - n));
m[3][3] = 0.f;
}
static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
{
/* Adapted from Android's OpenGL Matrix.java. */
/* See the OpenGL GLUT documentation for gluLookAt for a description */
/* of the algorithm. We implement it in a straightforward way: */
/* TODO: The negation of of can be spared by swapping the order of
* operands in the following cross products in the right way. */
vec3 f;
vec3_sub(f, center, eye);
vec3_norm(f, f);
vec3 s;
vec3_mul_cross(s, f, up);
vec3_norm(s, s);
vec3 t;
vec3_mul_cross(t, s, f);
m[0][0] = s[0];
m[0][1] = t[0];
m[0][2] = -f[0];
m[0][3] = 0.f;
m[1][0] = s[1];
m[1][1] = t[1];
m[1][2] = -f[1];
m[1][3] = 0.f;
m[2][0] = s[2];
m[2][1] = t[2];
m[2][2] = -f[2];
m[2][3] = 0.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = 0.f;
m[3][3] = 1.f;
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
}
typedef float quat[4];
static inline void quat_identity(quat q)
{
q[0] = q[1] = q[2] = 0.f;
q[3] = 1.f;
}
static inline void quat_add(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] + b[i];
}
static inline void quat_sub(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] - b[i];
}
static inline void quat_mul(quat r, quat p, quat q)
{
vec3 w;
vec3_mul_cross(r, p, q);
vec3_scale(w, p, q[3]);
vec3_add(r, r, w);
vec3_scale(w, q, p[3]);
vec3_add(r, r, w);
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
}
static inline void quat_scale(quat r, quat v, float s)
{
int i;
for(i=0; i<4; ++i)
r[i] = v[i] * s;
}
static inline float quat_inner_product(quat a, quat b)
{
float p = 0.f;
int i;
for(i=0; i<4; ++i)
p += b[i]*a[i];
return p;
}
static inline void quat_conj(quat r, quat q)
{
int i;
for(i=0; i<3; ++i)
r[i] = -q[i];
r[3] = q[3];
}
static inline void quat_rotate(quat r, float angle, vec3 axis) {
vec3 v;
vec3_scale(v, axis, sinf(angle / 2));
int i;
for(i=0; i<3; ++i)
r[i] = v[i];
r[3] = cosf(angle / 2);
}
#define quat_norm vec4_norm
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
{
quat v_ = {v[0], v[1], v[2], 0.f};
quat_conj(r, q);
quat_norm(r, r);
quat_mul(r, v_, r);
quat_mul(r, q, r);
}
static inline void mat4x4_from_quat(mat4x4 M, quat q)
{
float a = q[3];
float b = q[0];
float c = q[1];
float d = q[2];
float a2 = a*a;
float b2 = b*b;
float c2 = c*c;
float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c);
M[0][3] = 0.f;
M[1][0] = 2*(b*c - a*d);
M[1][1] = a2 - b2 + c2 - d2;
M[1][2] = 2.f*(c*d + a*b);
M[1][3] = 0.f;
M[2][0] = 2.f*(b*d + a*c);
M[2][1] = 2.f*(c*d - a*b);
M[2][2] = a2 - b2 - c2 + d2;
M[2][3] = 0.f;
M[3][0] = M[3][1] = M[3][2] = 0.f;
M[3][3] = 1.f;
}
static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
{
/* XXX: The way this is written only works for othogonal matrices. */
/* TODO: Take care of non-orthogonal case. */
quat_mul_vec3(R[0], q, M[0]);
quat_mul_vec3(R[1], q, M[1]);
quat_mul_vec3(R[2], q, M[2]);
R[3][0] = R[3][1] = R[3][2] = 0.f;
R[3][3] = 1.f;
}
static inline void quat_from_mat4x4(quat q, mat4x4 M)
{
float r=0.f;
int i;
int perm[] = { 0, 1, 2, 0, 1 };
int *p = perm;
for(i = 0; i<3; i++) {
float m = M[i][i];
if( m < r )
continue;
m = r;
p = &perm[i];
}
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
if(r < 1e-6) {
q[0] = 1.f;
q[1] = q[2] = q[3] = 0.f;
return;
}
q[0] = r/2.f;
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
}
#endif

@ -0,0 +1,24 @@
#include <stdarg.h>
#include <stdio.h>
#include "log.h"
void log_message(const char* message, ...)
{
printf("MSG : ");
va_list list;
va_start(list, message);
vprintf(message, list);
va_end(list);
printf("\n");
}
void log_error(const char* context, const char* error, ...)
{
printf("ERR (%s) : ", context);
va_list list;
va_start(list, error);
vprintf(error, list);
va_end(list);
printf("\n");
}

@ -0,0 +1,7 @@
#ifndef log_H
#define log_H
void log_message(const char* message, ...);
void log_error(const char* context, const char* error, ...);
#endif

@ -0,0 +1,54 @@
#define GLEW_STATIC
#include <GL/glew.h>
#include <stdio.h>
#include "log.h"
#include "window_system.h"
#include "game.h"
const int WIN_WIDTH = 800;
const int WIN_HEIGHT = 600;
int init();
void cleanup();
int main(int argc, char** args)
{
//Initialize window system and Glew
if(!init())
log_error("Main:main", "Could not initialize");
else
game_init();
cleanup();
log_message("Program exiting!");
return 0;
}
int init(void)
{
bool success = true;
if(window_init("Symmetry", WIN_WIDTH, WIN_HEIGHT))
{
//Initialize GLEW
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if(glewError != GLEW_OK)
{
log_error("Main:init", "GLEW : %s", glewGetErrorString(glewError));
success = false;
}
}
else
{
success = false;
}
return success;
}
void cleanup()
{
game_cleanup();
window_cleanup();
}

@ -0,0 +1,25 @@
#include "renderer.h"
#include "GLFW/glfw3.h"
void on_framebuffer_size_change(GLFWwindow* window, int width, int height);
void renderer_init(GLFWwindow* window)
{
glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glfwSetFramebufferSizeCallback(window, on_framebuffer_size_change);
}
void renderer_draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void renderer_cleanup(void)
{
}
void on_framebuffer_size_change(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}

@ -0,0 +1,10 @@
#ifndef renderer_H
#define renderer_H
typedef struct GLFWwindow GLFWwindow;
void renderer_init(GLFWwindow* window);
void renderer_draw(void);
void renderer_cleanup(void);
#endif

@ -0,0 +1,107 @@
#include <stdlib.h>
#include <string.h>
#include "string_utils.h"
#include "array.h"
char* str_new(const char* string)
{
size_t length = strlen(string);
char* new_string = malloc(length + 1);
strcpy(new_string, string);
return new_string;
}
char* str_concat(char* string, const char* str_to_concat)
{
size_t length = strlen(str_to_concat);
size_t length_orig = strlen(string);
char* temp = realloc(string, length + length_orig + 1); /* +1 at the end to cope for null byte */
if(temp)
{
string = temp;
strcat(string + length_orig, str_to_concat);
}
return string;
}
char* str_replace(char* string, const char* pattern, const char* replacement)
{
Array* indices = array_new(unsigned int);
size_t string_len = strlen(string);
/* Calculate size of new string and allocate new memory */
size_t pattern_len = strlen(pattern);
size_t replacement_len = strlen(replacement);
bool done = false;
char* remaining_string = string;
while(!done)
{
char* location = strstr(remaining_string, pattern);
if(location)
{
unsigned int index = location - string;
unsigned int* new_index = array_add(indices);
*new_index = index;
remaining_string = location + pattern_len; /* Find the next occurance in the remaining string */
}
else
{
done = true;
}
}
if(indices->length > 0)
{
size_t string_len_without_pattern = string_len - (pattern_len * indices->length);
size_t new_string_len = string_len_without_pattern + (replacement_len * indices->length);
char* new_string = malloc(new_string_len);
if(new_string)
{
done = false;
unsigned int count = 0;
unsigned int index = array_get_val(indices, unsigned int, count);
unsigned int prev_index = 0;
while(!done)
{
char* source_beg = string + prev_index;
char* source_end = string + index;
strncat(new_string, source_beg, (source_end - source_beg));
strcat(new_string, replacement);
count++;
prev_index = index + pattern_len;
if(count == indices->length)
{
done = true;
source_beg = string + prev_index;
strcat(new_string, source_beg);
}
else
{
index = array_get_val(indices, unsigned int, count);
}
}
free(string);
}
array_free(indices);
return new_string;
}
else
{
return NULL;
}
}

@ -0,0 +1,12 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
/*
Convenience methods for handling strings
*/
char* str_new(const char* string);
char* str_concat(char* string, const char* str_to_concat);
char* str_replace(char* string, const char* pattern, const char* replacement);
#endif

@ -0,0 +1,94 @@
#include "window_system.h"
#include "GLFW/glfw3.h"
#include "log.h"
static GLFWwindow* active_window = NULL;
static on_window_close window_close_custom = NULL;
static on_window_resize window_resize_custom = NULL;
void window_error_callback(int error, const char* description);
void window_resize(GLFWwindow* window, int width, int height);
void window_close_callback(GLFWwindow* window);
bool window_init(const char* title, int width, int height)
{
bool success = true;
glfwSetErrorCallback(window_error_callback);
if(!glfwInit())
{
log_error("window_create", "Initializing glfw failed");
success = false;
}
else
{
const char* version = glfwGetVersionString();
log_message("Initialized with %s", version);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
active_window = glfwCreateWindow(width, height, title, NULL, NULL);
if(!active_window)
{
log_error("window_create", "Failed to create window");
success = false;
}
else
{
glfwMakeContextCurrent(active_window);
glfwSwapInterval(1);
glfwSetWindowSizeCallback(active_window, window_resize);
glfwSetWindowCloseCallback(active_window, window_close_callback);
}
}
return success;
}
void window_error_callback(int error, const char* description)
{
log_error("GLFW", "(%d) %s", error, description);
}
void window_close_callback(GLFWwindow* window)
{
if(!window_close_custom)
glfwSetWindowShouldClose(window, GL_TRUE);
else
window_close_custom();
}
void window_cleanup(void)
{
if(active_window) glfwDestroyWindow(active_window);
glfwTerminate();
}
void window_poll_events(void)
{
glfwPollEvents();
}
void window_swap_buffers(void)
{
glfwSwapBuffers(active_window);
}
void window_set_size(int width, int height)
{
glfwSetWindowSize(active_window, width, height);
}
void window_resize(GLFWwindow* window, int width, int height)
{
/* Maybe resize main frame buffer here? */
if(window_resize_custom) window_resize_custom(width, height);
}
GLFWwindow* window_get_active(void)
{
return active_window;
}
bool window_should_close(void)
{
return glfwWindowShouldClose(active_window);
}

@ -0,0 +1,22 @@
#ifndef window_system_H
#define window_system_H
#include <stdbool.h>
struct GLFWwindow;
typedef struct GLFWwindow GLFWwindow;
typedef void (*on_window_close) (void); // Callback for window close
typedef void (*on_window_resize) (int, int); // Callback that recieves window resize event
typedef void (*on_key) (int, int , int, int); // Callback for keyboard events
typedef void (*on_mouse_pos) (double, double); // Callback for mouse position
bool window_init(const char* title, int width, int height);
void window_cleanup(void);
void window_set_size(int width, int height);
void window_poll_events(void);
void window_swap_buffers(void);
bool window_should_close(void);
GLFWwindow* window_get_active(void);
#endif
Loading…
Cancel
Save