polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit ea6844914790f2c9a00fde33352c62e3fabce4a5
parent d449b59e787ebf0952e59c0855a969b3774aa836
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 25 Apr 2018 21:02:15 -0700

Merge branch 'master' of github.com:jb55/polyadvent

Diffstat:
MMakefile | 3++-
Metc/shaders/test.f.glsl | 2+-
Metc/shaders/test.v.glsl | 5+++--
Msrc/buffer.c | 1+
Msrc/event.c | 8++++++--
Msrc/event.h | 3++-
Msrc/game.c | 19+++++++++++++++----
Msrc/game.h | 5+++++
Msrc/geometry.c | 20++++++++++++++++++++
Msrc/geometry.h | 1+
Msrc/gl.h | 40++++++++++++++++++++++++++++++++++++++++
Msrc/input.c | 6++++--
Msrc/input.h | 3++-
Msrc/main.c | 28++++++++++++++++++++++------
Msrc/mat4/mat4.c | 26++++++++++++++++++++++++--
Msrc/mat4/mat4.h | 1+
Asrc/perlin.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/perlin.h | 7+++++++
Msrc/render.c | 49+++++++++++++++++++++++++++++++------------------
Msrc/render.h | 2+-
Msrc/shader.c | 2+-
Msrc/terrain.c | 67++++++++++++++++++++++++++++++-------------------------------------
Msrc/terrain.h | 10+++++++++-
Msrc/update.c | 119++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/update.h | 2+-
Msrc/vec3/vec3.h | 3+++
Msrc/window.c | 4+++-
Msrc/window.h | 2+-
28 files changed, 382 insertions(+), 121 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ NAME ?= polyadvent BIN ?= $(NAME) PREFIX ?= /usr/local -CFLAGS = -ggdb -I src -Wall -Wextra -std=c99 \ +CFLAGS = -ggdb -I src -Wall -Werror -Wextra -std=c99 \ -Wno-unused-function \ -Wno-unused-parameter \ -Wno-unused-variable \ @@ -17,6 +17,7 @@ OBJS += $(SRC)/buffer.o OBJS += $(SRC)/debug.o OBJS += $(SRC)/event.o OBJS += $(SRC)/file.o +OBJS += $(SRC)/perlin.o OBJS += $(SRC)/game.o OBJS += $(SRC)/mat4/mat4.o OBJS += $(SRC)/vec3/vec3.o diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl @@ -10,6 +10,6 @@ out vec4 fragmentColor; void main() { - vec4 color = vec4(0.4, 0.4, 0.8, 0.5); + vec4 color = vec4(0.4, 0.4, 0.8, 1.0); fragmentColor = vec4(color.xyz * v_dot, 1.0); } diff --git a/etc/shaders/test.v.glsl b/etc/shaders/test.v.glsl @@ -3,6 +3,7 @@ in vec3 position; in vec3 normal; +uniform mat4 local; uniform mat4 mvp; uniform mat4 normal_matrix; @@ -14,7 +15,7 @@ uniform vec3 light_dir; void main() { vec4 trans_normal = normal_matrix * vec4(normal, 1); - gl_Position = mvp * vec4(position.xyz, 1.0); - v_dot = dot(trans_normal.xyz, vec3(1.0,1.0,0.0)); + gl_Position = mvp * local * vec4(position.xyz, 1.0); + v_dot = dot(trans_normal, vec4(light_dir, 0)); v_norm = normal; } diff --git a/src/buffer.c b/src/buffer.c @@ -2,6 +2,7 @@ #include "buffer.h" #include "util.h" #include <assert.h> +#include "gl.h" gpu_addr make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { diff --git a/src/event.c b/src/event.c @@ -4,15 +4,19 @@ #include "input.h" #include "game.h" -void process_events() { +void process_events(float *camera, struct input *input) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + handle_key(input, event.key); + break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: - handle_resize(event.window.data1, event.window.data2); + handle_resize(camera, event.window.data1, event.window.data2); break; } break; diff --git a/src/event.h b/src/event.h @@ -3,7 +3,8 @@ #define PA_EVENT_H #include "gl.h" +#include "input.h" -void process_events(void); +void process_events(float *camera, struct input *input); #endif /* PA_EVENT_H */ diff --git a/src/game.c b/src/game.c @@ -1,25 +1,36 @@ #include "mat4/mat4.h" +#include "vec3/vec3.h" #include "game.h" mat4 *cam_init = (float[16]){ - 0.952107, 0.186872, -0.241083, 0.000000, - -0.302599, 0.688952, -0.656898, 0.000000, - 0.043785, 0.697792, 0.702532, 0.000000, - -26.815081, -19.055046, -8.465672, 1.000000 + 0.955761, 0.228018, -0.185425, 0.000000, + -0.293528, 0.779583, -0.552437, 0.000000, + 0.018780, 0.580299, 0.802257, 0.000000, + -58.746227, -62.404854, -34.097778, 1.000000 }; void game_init(struct game *game) { float *mvp = game->test_resources.test_mvp; float *normal = game->test_resources.normal_matrix; float *camera = game->test_resources.camera; + float *player = game->test_resources.player; + float *light_dir = game->test_resources.light_dir; + mat4_id(mvp); mat4_id(normal); mat4_id(camera); + light_dir[0] = 0.5; + light_dir[1] = 1; + light_dir[2] = 0; + // move the camera a bit /* mat4_translate(camera, 1.0f, 1.0f, 20.0f, camera); */ mat4_copy(cam_init, camera); + mat4_id(player); + mat4_scale(player, V3(0.36,0.36,1.7), player); + input_init(&game->input); } diff --git a/src/game.h b/src/game.h @@ -17,6 +17,7 @@ struct resources { GLint fade_factor; GLint light_dir; GLint mvp; + GLint local; GLint normal_matrix; } uniforms; @@ -27,7 +28,9 @@ struct resources { float normal_matrix[MAT4_ELEMS]; float test_mvp[MAT4_ELEMS]; + float light_dir[3]; float camera[MAT4_ELEMS]; + float player[MAT4_ELEMS]; float camera_persp[MAT4_ELEMS]; GLfloat fade_factor; }; @@ -37,8 +40,10 @@ struct game { int counter; struct resources test_resources; struct input input; + struct terrain *terrain; }; void game_init(struct game *game); +void should_update(struct game *game); #endif /* PA_GAME_H */ diff --git a/src/geometry.c b/src/geometry.c @@ -1,8 +1,28 @@ #include "geometry.h" +#include "util.h" #include <assert.h> void +destroy_buffer_geometry(struct geometry *geom) { + gpu_addr buffers[] = { + geom->buffer.vertex_buffer.handle, + geom->buffer.normal_buffer.handle, + geom->buffer.index_buffer.handle + }; + /* void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); */ + /* glDisableVertexAttribArray(geom->buffer.vertex_buffer.handle); */ + /* check_gl(); */ + /* glDisableVertexAttribArray(geom->buffer.normal_buffer.handle); */ + /* check_gl(); */ + /* glDisableVertexAttribArray(geom->buffer.index_buffer.handle); */ + /* check_gl(); */ + check_gl(); + glDeleteBuffers(ARRAY_SIZE(buffers), buffers); + check_gl(); +} + +void make_buffer_geometry(struct geometry *geom) { // VBOs diff --git a/src/geometry.h b/src/geometry.h @@ -21,5 +21,6 @@ struct geometry { }; void make_buffer_geometry(struct geometry *geom); +void destroy_buffer_geometry(struct geometry *geom); #endif /* GEOMETRY_H */ diff --git a/src/gl.h b/src/gl.h @@ -7,4 +7,44 @@ #include <GL/glx.h> #include <GL/glext.h> +void glGenBuffers(GLsizei n, GLuint * buffers); +void glGetShaderiv(GLuint shader, GLenum pname, GLint *params); +void glGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); +void glBindBuffer(GLenum target, GLuint buffer); +GLuint glCreateShader(GLenum shaderType); +void glCompileShader(GLuint shader); + +void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, + const GLint *length); + +void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); +GLint glGetUniformLocation(GLuint program, const GLchar *name); +GLint glGetAttribLocation(GLuint program, const GLchar *name); +void glEnableVertexAttribArray(GLuint index); +void glDeleteShader(GLuint shader); + +void glDeleteBuffers(GLsizei n, const GLuint * buffers); + +void glVertexAttribPointer(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const GLvoid * pointer); + +void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLuint glCreateProgram(void); +void glAttachShader(GLuint program, GLuint shader); +void glLinkProgram(GLuint program); + +void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +void glUseProgram(GLuint program); +void glUniform1f(GLint location, GLfloat v0); +void glGetProgramiv(GLuint program, GLenum pname, GLint *params); +void glDeleteProgram( GLuint program); + +void glDisableVertexAttribArray(GLuint index); +void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); + +GLboolean glIsBuffer( GLuint buffer); + #endif /* POLYADVENT_GL_H */ diff --git a/src/input.c b/src/input.c @@ -6,7 +6,9 @@ void input_init(struct input *input) { /* memset(input->keys, 0, sizeof(input->keys[0]) * ARRAY_SIZE(input->keys)); */ input->keystates = SDL_GetKeyboardState(NULL); + assert(input->keystates); } -/* void handle_key(struct input *input, SDL_KeyboardEvent *key) { */ -/* } */ +void handle_key(struct input *input, SDL_KeyboardEvent key) { + input->modifiers = SDL_GetModState(); +} diff --git a/src/input.h b/src/input.h @@ -15,10 +15,11 @@ struct input { /* enum key_state keys[0x7F-0x1F]; */ u8 const *keystates; + SDL_Keymod modifiers; }; void input_init(struct input *input); -/* void handle_key(struct input *input, SDL_KeyboardEvent *ke); */ +void handle_key(struct input *input, SDL_KeyboardEvent ke); #endif /* POLYADVENT_INPUT_H */ diff --git a/src/main.c b/src/main.c @@ -25,19 +25,29 @@ int main(void) size_t length; /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ + int width = 640; + int height = 480; SDL_Window *window = SDL_CreateWindow( - "SDL2/OpenGL Demo", 0, 0, 640, 480, + "SDL2/OpenGL Demo", 0, 0, width, height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - srand(42); + srand(time(NULL)); SDL_GL_CreateContext(window); - init_gl(&game.test_resources); + init_gl(&game.test_resources, width, height); game_init(&game); + game.terrain = &terrain; + + struct perlin_settings terrain_settings = { + .depth = 1, + .freq = 0.02, + .amplitude = 1.0, + .exp = 7.3 + }; terrain_init(&terrain); - terrain_create(&terrain); + terrain_create(&terrain, &terrain_settings); /* slab_buffer = file_contents(SLAB("test.slab"), &length); */ /* slab_parse(&slab, slab_buffer); */ @@ -54,9 +64,15 @@ int main(void) /* Loop until the user closes the window */ + + u32 last = SDL_GetTicks(); + while (1) { - process_events(); - update(&game); + process_events(game.test_resources.camera_persp, &game.input); + u32 ticks = SDL_GetTicks(); + update(&game, ticks-last); + + last = ticks; render(&game.test_resources, &terrain.geom); /* Swap front and back buffers */ diff --git a/src/mat4/mat4.c b/src/mat4/mat4.c @@ -291,8 +291,30 @@ mat4 *mat4_rotate(const mat4 *mat, const float angle, return dest; } - -mat4_print(const mat4 *m) { +mat4 *mat4_scale(mat4 *a, float v[3], mat4 *out) { + float x = v[0], y = v[1], z = v[2]; + + out[0] = a[0] * x; + out[1] = a[1] * x; + out[2] = a[2] * x; + out[3] = a[3] * x; + out[4] = a[4] * y; + out[5] = a[5] * y; + out[6] = a[6] * y; + out[7] = a[7] * y; + out[8] = a[8] * z; + out[9] = a[9] * z; + out[10] = a[10] * z; + out[11] = a[11] * z; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; + + +void mat4_print(const mat4 *m) { for (int i = 0; i < 16; ++i) { if (i % 4 == 0) printf("\n"); diff --git a/src/mat4/mat4.h b/src/mat4/mat4.h @@ -1,6 +1,7 @@ typedef float mat4; +mat4 *mat4_scale(mat4 *a, float v[3], mat4 *out); mat4 *mat4_frustum (float left, float right, float bottom, float top, float near, float far, mat4 *dest); diff --git a/src/perlin.c b/src/perlin.c @@ -0,0 +1,65 @@ +#include <stdio.h> + +static int SEED = 0; + +static int hash[] = { + 208,34,231,213,32,248,233,56,161,78,24,140,71,48,140,254,245,255,247,247,40, + 185,248,251,245,28,124,204,204,76,36,1,107,28,234,163,202,224,245,128,167,204, + 9,92,217,54,239,174,173,102,193,189,190,121,100,108,167,44,43,77,180,204,8,81, + 70,223,11,38,24,254,210,210,177,32,81,195,243,125,8,169,112,32,97,53,195,13, + 203,9,47,104,125,117,114,124,165,203,181,235,193,206,70,180,174,0,167,181,41, + 164,30,116,127,198,245,146,87,224,149,206,57,4,192,210,65,210,129,240,178,105, + 228,108,245,148,140,40,35,195,38,58,65,207,215,253,65,85,208,76,62,3,237,55,89, + 232,50,217,64,244,157,199,121,252,90,17,212,203,149,152,140,187,234,177,73,174, + 193,100,192,143,97,53,145,135,19,103,13,90,135,151,199,91,239,247,33,39,145, + 101,120,99,3,186,86,99,41,237,203,111,79,220,135,158,42,30,154,120,67,87,167, + 135,176,183,191,253,115,184,21,233,58,129,233,142,39,128,211,118,137,139,255, + 114,20,218,113,154,27,127,246,250,1,8,198,250,209,92,222,173,21,88,102,219}; + +int noise2(int x, int y) { + int tmp = hash[(y + SEED) % 256]; + return hash[(tmp + x) % 256]; +} + +float lin_inter(float x, float y, float s) { + return x + s * (y-x); +} + +float smooth_inter(float x, float y, float s) { + return lin_inter(x, y, s * s * (3-2*s)); +} + +float noise2d(float x, float y) { + int x_int = x; + int y_int = y; + float x_frac = x - x_int; + float y_frac = y - y_int; + int s = noise2(x_int, y_int); + int t = noise2(x_int+1, y_int); + int u = noise2(x_int, y_int+1); + int v = noise2(x_int+1, y_int+1); + float low = smooth_inter(s, t, x_frac); + float high = smooth_inter(u, v, x_frac); + return smooth_inter(low, high, y_frac); +} + +float perlin2d(float x, float y, float freq, int depth) { + float xa = x*freq; + float ya = y*freq; + float amp = 1.0; + float fin = 0; + float div = 0.0; + + int i; + for(i=0; i<depth; i++) + { + div += 256 * amp; + fin += noise2d(xa, ya) * amp; + amp /= 2; + xa *= 2; + ya *= 2; + } + + return fin/div; +} + diff --git a/src/perlin.h b/src/perlin.h @@ -0,0 +1,7 @@ + +#ifndef POLYADVENT_PERLIN_H +#define POLYADVENT_PERLIN_H + +float perlin2d(float x, float y, float freq, int depth); + +#endif /* POLYADVENT_PERLIN_H */ diff --git a/src/render.c b/src/render.c @@ -6,6 +6,7 @@ #include "gl.h" #include "game.h" #include "mat4/mat4.h" +#include "vec3/vec3.h" #include "buffer.h" #include "buffer_geometry.h" #include "shader.h" @@ -54,7 +55,7 @@ static const GLushort cube_indices[] = { }; void -init_gl(struct resources *resources) { +init_gl(struct resources *resources, int width, int height) { float tmp_matrix[16]; glEnable(GL_DEPTH_TEST); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); @@ -98,7 +99,7 @@ init_gl(struct resources *resources) { assert(resources->fragment_shader != 0); // camera - mat4_perspective(90 /* fov */, 1080 / 720, 1, 1000, resources->camera_persp); + mat4_perspective(90 /* fov */, (float)width / height, 1, 1000, resources->camera_persp); // Shader program resources->program = make_program(resources->vertex_shader, @@ -119,6 +120,9 @@ init_gl(struct resources *resources) { resources->uniforms.mvp = glGetUniformLocation(resources->program, "mvp"); + resources->uniforms.local + = glGetUniformLocation(resources->program, "local"); + resources->attributes.normal = (gpu_addr)glGetAttribLocation(resources->program, "normal"); @@ -141,6 +145,7 @@ static void recalc_normals(GLint norm_uniform, mat4 *mvp, mat4 *normal) { mat4 *calc = calc_normals(mvp, normal); glUniformMatrix4fv(norm_uniform, 1, 0, calc); + check_gl(); } @@ -188,34 +193,42 @@ static void render_geom (struct resources *res, } -void render (struct resources * resources, struct geometry *geom) { - glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); //clear background screen to black +void render (struct resources * res, struct geometry *geom) { + glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); //clear background screen to black glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + check_gl(); static float id[MAT4_ELEMS] = { 0 }; mat4_id(id); - float *mvp = resources->test_mvp; - float *normal = resources->normal_matrix; - float *camera = resources->camera; - float *persp = resources->camera_persp; - float fade_factor = resources->fade_factor; + float *mvp = res->test_mvp; + float *normal = res->normal_matrix; + float *camera = res->camera; + float *persp = res->camera_persp; + float *light = res->light_dir; + float *player = res->player; + + float fade_factor = res->fade_factor; + + glUseProgram(res->program); /* static float v3[] = { 1, 1, 0 }; */ /* v3[1] = fade_factor * 1.4f; */ /* mat4_rotate(mvp, 0.004f, v3, mvp); */ mat4_multiply(persp, camera, tmp_matrix); mat4_multiply(tmp_matrix, mvp, tmp_matrix); - recalc_normals(resources->uniforms.normal_matrix, tmp_matrix, normal); - glUniform3f(resources->uniforms.light_dir, 1.0f, 1.0f, 0.0f); - glUseProgram(resources->program); - glUniform1f(resources->uniforms.fade_factor, fade_factor); - glUniformMatrix4fv(resources->uniforms.mvp, 1, 0, tmp_matrix); + recalc_normals(res->uniforms.normal_matrix, tmp_matrix, normal); + + glUniform3f(res->uniforms.light_dir, light[0], light[1], light[2]); + glUniform1f(res->uniforms.fade_factor, fade_factor); + glUniformMatrix4fv(res->uniforms.mvp, 1, 0, tmp_matrix); + + glUniformMatrix4fv(res->uniforms.local, 1, 0, player); + render_cube(res); + glUniformMatrix4fv(res->uniforms.local, 1, 0, id); - /* render_cube(resources); */ - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - render_geom(resources, geom, GL_TRIANGLES); + render_geom(res, geom, GL_TRIANGLES); /* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */ - /* render_geom(resources, geom, GL_TRIANGLES); */ + /* render_geom(res, geom, GL_TRIANGLES); */ } diff --git a/src/render.h b/src/render.h @@ -3,7 +3,7 @@ #include "geometry.h" -void init_gl(struct resources *resources); +void init_gl(struct resources *resources, int width, int height); void render (struct resources *resources, struct geometry *geom); void wireframe_mode_on(); diff --git a/src/shader.c b/src/shader.c @@ -20,7 +20,7 @@ make_shader(GLenum type, const char *filename) { source[length] = '\0'; shader = glCreateShader(type); - glShaderSource(shader, 1, (const GLchar*const*)&source, (GLint*)&length); + glShaderSource(shader, 1, (const GLchar**)&source, (GLint*)&length); free(source); glCompileShader(shader); diff --git a/src/terrain.c b/src/terrain.c @@ -3,6 +3,7 @@ #include "util.h" #include "delaunay.h" #include "vec3/vec3.h" +#include "perlin.h" static const float plane_verts[] = { -1,-1,0, -1,1,0, 1,1,0, 1,-1,0 @@ -17,13 +18,22 @@ static const u32 plane_indices[] = { }; -double old_noisy_boi(double x, double y, double *dx, double *dy) { - double c = 5.0; - double h = c; - double z = sin(x/c) * cos(y/c) * h; - *dx = (cos(x/c) * cos(y/c) * h)/c; - *dy = (sin(x/c) * sin(y/c) * h)/c; - return z; +double old_noisy_boi(void *data, double x, double y) { + struct perlin_settings *s = (struct perlin_settings*)data; + double e = 1.0 * perlin2d(x, y, s->freq, s->depth) + + 0.5 * perlin2d(2 * x, 2 * y, s->freq, s->depth) + + 0.25 * perlin2d(4 * x, 4 * y, s->freq, s->depth); + return pow(e, s->exp) * s->amplitude; +} + +void deriv(double (*noisefn)(void*, double, double), void* data, double x, + double y, double z1, double *dx, double *dy) +{ + static const double h = 0.01; + double zx = noisefn(data, x + h, y); + double zy = noisefn(data, x, y - h); + *dx = (zx - z1)/h; + *dy = (zy - z1)/h; } void @@ -33,24 +43,24 @@ terrain_init(struct terrain *terrain) { } void -terrain_create(struct terrain *terrain) { +terrain_create(struct terrain *terrain, struct perlin_settings *perlin) { u32 i; - const int num_verts = 5000; - float tmp1[3]; + const double size = 200; + const double hsize = size/2; + const int num_verts = hsize*hsize; float tmp2[3]; - float norm[3]; del_point2d_t *points = calloc(num_verts, sizeof(*points)); float *verts = calloc(num_verts * 3, sizeof(*verts)); float *normals = calloc(num_verts * 3, sizeof(*normals)); - /* int *indices = calloc(num_verts, sizeof(*indices)); */ // 100 random samples from our noise function for (i = 0; i < (u32)num_verts; i++) { int n = i*3; double dx, dy; - double x = rand_0to1() * 100.0; - double y = rand_0to1() * 100.0; - double z = old_noisy_boi(x, y, &dx, &dy); + double x = rand_0to1() * size; + double y = rand_0to1() * size; + double z = old_noisy_boi((void*)perlin, x, y); + deriv(old_noisy_boi, (void*)perlin, x, y, z, &dx, &dy); points[i].x = x; points[i].y = y; @@ -59,16 +69,12 @@ terrain_create(struct terrain *terrain) { verts[n+1] = (float)y; verts[n+2] = (float)z; - // ^i * dx - vec3_scale((float[3]){1,0,0}, dx, tmp1); // ^k - (^i * dx) - vec3_subtract((float[3]){0,0,1}, tmp1, tmp2); - - // ^j * dy - vec3_scale((float[3]){0,1,0}, dy, tmp1); + vec3_subtract(V3(0,0,1), V3(dx,0,0), tmp2); // (^k - (^i * dx)) - ^j * dy - vec3_subtract(tmp2, tmp1, tmp2); + vec3_subtract(tmp2, V3(0,dy,0), tmp2); + vec3_normalize(tmp2, tmp2); normals[n] = tmp2[0]; normals[n+1] = tmp2[1]; @@ -81,18 +87,6 @@ terrain_create(struct terrain *terrain) { printf("faces %d tris %d points %d\n", del->num_faces, tri->num_triangles, tri->num_points); - // TODO: calc normals - for (i = 0; i < tri->num_points; i++) { - int n = i*3; - - verts[n] = (float)tri->points[i].x; - verts[n+1] = (float)tri->points[i].y; - - /* normals[n] = rand_0to1(); */ - /* normals[n+1] = rand_0to1(); */ - /* normals[n+2] = rand_0to1(); */ - } - terrain->geom.num_verts = num_verts; terrain->geom.vertices = (float*)verts; terrain->geom.normals = (float*)normals; @@ -110,7 +104,6 @@ terrain_create(struct terrain *terrain) { } void -terrain_detroy(struct terrain *terrain) { - free(terrain->geom.vertices); - free(terrain->geom.normals); +terrain_destroy(struct terrain *terrain) { + destroy_buffer_geometry(&terrain->geom); } diff --git a/src/terrain.h b/src/terrain.h @@ -5,13 +5,21 @@ #include "geometry.h" +struct perlin_settings { + double freq; + int depth; + double amplitude; + double exp; +}; + struct terrain { struct geometry geom; + struct perlin_settings settings; float width, height; }; void terrain_init(struct terrain *terrain); -void terrain_create(struct terrain *terrain); +void terrain_create(struct terrain *terrain, struct perlin_settings *); void terrain_destroy(struct terrain *terrain); diff --git a/src/update.c b/src/update.c @@ -1,58 +1,101 @@ #include "gl.h" #include "update.h" +#include "terrain.h" +#include "util.h" #include "mat4/mat4.h" -void camera_movement(struct game *game) { - float *camera = game->test_resources.camera; - float amt = 0.1; +void movement(struct game *game, float *obj) { + float amt = 0.25; - if (game->input.keystates[SDL_SCANCODE_A]) { - mat4_translate(camera, -amt, 0, 0, camera); - } + if (game->input.modifiers & KMOD_SHIFT) + amt *= 6; - if (game->input.keystates[SDL_SCANCODE_D]) { - mat4_translate(camera, amt, 0, 0, camera); - } + if (game->input.keystates[SDL_SCANCODE_A]) + mat4_translate(obj, -amt, 0, 0, obj); - if (game->input.keystates[SDL_SCANCODE_W]) { - mat4_translate(camera, 0, amt, 0, camera); - } + if (game->input.keystates[SDL_SCANCODE_E]) + mat4_translate(obj, 0, 0, amt, obj); - if (game->input.keystates[SDL_SCANCODE_S]) { - mat4_translate(camera, 0, -amt, 0, camera); - } + if (game->input.keystates[SDL_SCANCODE_Q]) + mat4_translate(obj, 0, 0, -amt, obj); - if (game->input.keystates[SDL_SCANCODE_UP]) { - /* mat4_translate(camera, 0, 0, 0.1, camera); */ - /* mat4_translate(camera, 0, -amt, 0, camera); */ - mat4_rotate(camera, amt*0.1, (float[]){1,0,0}, camera); - } + if (game->input.keystates[SDL_SCANCODE_D]) + mat4_translate(obj, amt, 0, 0, obj); + + if (game->input.keystates[SDL_SCANCODE_W]) + mat4_translate(obj, 0, amt, 0, obj); - if (game->input.keystates[SDL_SCANCODE_RIGHT]) { - /* mat4_translate(camera, amt, 0, 0, camera); */ - /* mat4_translate(camera, amt, 0, 0, camera); */ - mat4_rotate(camera, amt*0.1, (float[]){0,1,0}, camera); + if (game->input.keystates[SDL_SCANCODE_S]) + mat4_translate(obj, 0, -amt, 0, obj); + + if (obj == game->test_resources.camera) { + if (game->input.keystates[SDL_SCANCODE_UP]) + mat4_rotate(obj, amt*0.1, (float[]){1,0,0}, obj); + + if (game->input.keystates[SDL_SCANCODE_RIGHT]) + mat4_rotate(obj, amt*0.1, (float[]){0,1,0}, obj); + + if (game->input.keystates[SDL_SCANCODE_LEFT]) + mat4_rotate(obj, -(amt*0.1), (float[]){0,1,0}, obj); + + if (game->input.keystates[SDL_SCANCODE_DOWN]) + mat4_rotate(obj, -(amt*0.1), (float[]){1,0,0}, obj); } - if (game->input.keystates[SDL_SCANCODE_LEFT]) { - /* mat4_translate(camera, -amt, 0, 0, camera); */ - /* mat4_translate(camera, -amt, 0, 0, camera); */ - mat4_rotate(camera, -(amt*0.1), (float[]){0,1,0}, camera); + if (game->input.keystates[SDL_SCANCODE_P]) + mat4_print(obj); +} + +void update (struct game *game, u32 dt) { + static int passed = 0; + static int last_gen_time = 50; + static float n = 1; + struct resources *res = &game->test_resources; + static struct perlin_settings terrain_settings = { + .depth = 1, + }; + float *light = res->light_dir; + + if (game->input.modifiers & KMOD_LALT) + movement(game, res->camera); + else { + movement(game, res->player); + /* movement(game, res->camera); */ } - if (game->input.keystates[SDL_SCANCODE_DOWN]) { - /* mat4_translate(camera, -0.1, 0, 0, camera); */ - /* mat4_translate(camera, 0, amt, 0, camera); */ - mat4_rotate(camera, -(amt*0.1), (float[]){1,0,0}, camera); + if (game->input.keystates[SDL_SCANCODE_C]) { + printf("light_dir %f %f %f\n", light[0], light[1], light[2]); } - if (game->input.keystates[SDL_SCANCODE_P]) { - mat4_print(camera); + if (passed < last_gen_time) { + passed += dt; + } else { + passed = 0; + + terrain_settings.depth = 1; + + terrain_settings.amplitude = sin(n); + terrain_settings.exp = fabs(sin(n) * 10.0); + terrain_settings.freq = fabs(cos(n) * 0.04); + + + terrain_destroy(game->terrain); + terrain_init(game->terrain); + + int t1 = SDL_GetTicks(); + terrain_create(game->terrain, &terrain_settings); + int t2 = SDL_GetTicks(); + last_gen_time = t2 - t1; + + printf("terrain amp %f exp %f freq %f (%d ms)\n", + terrain_settings.amplitude, + terrain_settings.exp, + terrain_settings.freq, + last_gen_time); + + /* res->light_dir[0] = cos(n) * 0.8; */ + n += 0.01f; } -} -void update (struct game *game) { - unsigned int ms = SDL_GetTicks(); - camera_movement(game); } diff --git a/src/update.h b/src/update.h @@ -4,6 +4,6 @@ #include "game.h" -void update(struct game * game); +void update(struct game * game, u32 dt); #endif /* PA_UPDATE_H */ diff --git a/src/vec3/vec3.h b/src/vec3/vec3.h @@ -1,7 +1,10 @@ typedef float vec3; +#define V3(x,y,z) ((float[3]){x,y,z}) + vec3 *vec3_subtract(vec3 *vec, vec3 *vec2, vec3 *dest); vec3 *vec3_cross (vec3 *vec, vec3 *vec2, vec3 *dest); vec3 *vec3_multiply(vec3 *vec, vec3 *vec2, vec3 *dest); vec3 *vec3_scale(vec3 *vec, double val, vec3 *dest); +vec3 *vec3_normalize(vec3 *vec, vec3 *dest); diff --git a/src/window.c b/src/window.c @@ -1,13 +1,15 @@ #include "gl.h" +#include "mat4/mat4.h" #include "window.h" void -handle_resize(int width, int height) { +handle_resize(float *camera, int width, int height) { printf("resizing %d %d\n", width, height); glViewport( 0, 0, width, height ); + mat4_perspective(90 /* fov */, (float)width / height, 1, 1000, camera); /* glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective */ /* Set the camera perspective */ diff --git a/src/window.h b/src/window.h @@ -5,7 +5,7 @@ #include "gl.h" void -handle_resize(int width, int height); +handle_resize(float *camera, int width, int height); #endif /* POLYADVENT_WINDOW_H */