summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/common.h1360
1 files changed, 663 insertions, 697 deletions
diff --git a/libs/common.h b/libs/common.h
index c7513a2..b12e4a1 100644
--- a/libs/common.h
+++ b/libs/common.h
@@ -12,535 +12,520 @@
#include <sys/stat.h>
#include <fcntl.h>
-U8 *
-read_entire_file(const char *filename) {
- U8 *result;
- FILE *f;
- long file_size;
-
- result = 0;
-
- if (!filename) {
- return(result);
- }
-
- f = fopen(filename, "rb");
- if (!f) {
- return(result);
- }
-
- fseek(f, 0, SEEK_END);
- file_size = ftell(f);
- fseek(f, 0, SEEK_SET);
-
- result = malloc(file_size + 1);
- fread(result, file_size, 1, f);
- fclose(f);
-
- result[file_size] = 0;
-
- return(result);
-}
-
-void *
-mmap_file(size_t *len, const char *filename)
-{
- struct stat sb;
- char* p;
- int fd;
-
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- perror("open");
- return NULL;
- }
-
- if (fstat(fd, &sb) == -1) {
- perror("fstat");
- return NULL;
- }
-
- if (!S_ISREG(sb.st_mode)) {
- fprintf(stderr, "%s is not a file\n", filename);
- return NULL;
- }
-
- p = (char*)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
-
- if (p == MAP_FAILED) {
- perror("mmap");
- return NULL;
- }
-
- if (close(fd) == -1) {
- perror("close");
- return NULL;
- }
-
- (*len) = sb.st_size;
-
- return p;
-}
-
-void
-read_entire_file_mmap(void* ctx, const char* filename, const int is_mtl,
- const char* obj_filename, char** data, size_t* len)
-{
- if (!filename)
- {
- fprintf(stderr, "[ERROR]: Filename not provided (null)\n");
- *data = 0;
- *len = 0;
- return;
- }
-
- size_t data_len = 0;
-
- *data = mmap_file(&data_len, filename);
- *len = data_len;
-}
-
-Mesh *
-mesh_load_obj(Arena *arena, const char *filename)
-{
- tinyobj_attrib_t attrib;
- tinyobj_shape_t *shapes = 0;
- tinyobj_material_t *materials = 0;
- size_t num_shapes, num_materials, num_triangles;
- size_t i, j, face_offset;
- U32 flags;
- Mesh *mesh = 0;
-
- flags = TINYOBJ_FLAG_TRIANGULATE;
-
- S32 status = tinyobj_parse_obj(&attrib, &shapes, &num_shapes,
- &materials, &num_materials, filename,
- read_entire_file_mmap, 0, flags);
- if (status != TINYOBJ_SUCCESS)
- {
- fprintf(stderr, "[ERROR]: Failed to parse \"%s\"\n", filename);
- if (status == TINYOBJ_ERROR_INVALID_PARAMETER)
- fprintf(stderr, "[ERROR]: TINYOBJ_ERROR_INVALID_PARAMETER\n");
- return(mesh);
- }
-
- num_triangles = attrib.num_face_num_verts;
- face_offset = 0;
-
- Vertex *vertices = arena_push_size(arena, sizeof(Vertex)*num_triangles*3);
- U32 *indices = arena_push_size(arena, num_triangles*3*sizeof(U32));
- U32 vertex_count = 0;
- U32 index_count = 0, index_index = 0;
- for (i = 0; i < attrib.num_face_num_verts; ++i)
- {
- tinyobj_vertex_index_t idx;
- V3F pos, normal;
- V2F tex_coords;
-
- Assert(attrib.face_num_verts[i]%3 == 0);
-
- Assert(attrib.face_num_verts[i]/3 > 3);
-
- Assert(attrib.num_texcoords);
-
- for (j = 0; j < 3; ++j)
- {
- idx = attrib.faces[face_offset+j];
- Assert(idx.v_idx >= 0);
- pos = v3f(attrib.vertices[3*idx.v_idx+0],
- attrib.vertices[3*idx.v_idx+1],
- attrib.vertices[3*idx.v_idx+2]);
-
- Assert(idx.vn_idx < (S32)attrib.num_normals);
- normal = v3f(attrib.normals[3*idx.vn_idx+0],
- attrib.normals[3*idx.vn_idx+1],
- attrib.normals[3*idx.vn_idx+2]);
-
- Assert(idx.vt_idx < (S32)attrib.num_texcoords);
- tex_coords = v2f(attrib.texcoords[2*idx.vt_idx+0],
- attrib.texcoords[2*idx.vt_idx+1]);
-
- vertices[vertex_count++] = vertex(pos, normal, tex_coords);
- Assert(index_count < attrib.num_faclibe_num_verts);
- indices[index_index++] = index_count++;
- }
-
- face_offset += 3;
- }
-
- mesh = mesh_init(arena, vertices, vertex_count,
- indices, num_triangles*3);
-
- tinyobj_attrib_free(&attrib);
- tinyobj_shapes_free(shapes, num_shapes);
- tinyobj_materials_free(materials, num_materials);
-
- return(mesh);
-}
-
-U32
-compile_shader(GLenum type, const char *filename)
-{
- U32 shader;
- S32 status;
- char logs[512];
-
- const char *source = (const char *)read_entire_file(filename);
- if (!source) {
- fprintf(stderr, "[ERROR]: Failed to read the file \"%s\"\n", filename);
- return(0);
- }
-
- shader = glCreateShader(type);
- glShaderSource(shader, 1, &source, 0);
- free((void *)source);
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- glGetShaderInfoLog(shader, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to compile: \"%s\"\n%s", filename, logs);
- } else {
- fprintf(stdout, "[INFO]: \"%s\" compiled successfuly.\n", filename);
- }
- return(shader);
-}
-
-U32
-create_shader_program(char *vertex_shader_filename,
- char *fragment_shader_filename)
-{
- S32 success;
- char logs[512];
-
- U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
- U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
-
- U32 shader_program;
- shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glLinkProgram(shader_program);
- glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
- if (success == GL_FALSE) {
- glGetProgramInfoLog(shader_program, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s",
- logs);
- } else {
- fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
- }
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
-
- return(shader_program);
-}
-
-U32
-create_shader_program_geom(char *vertex_shader_filename,
- char *fragment_shader_filename,
- char *geometry_shader_filename)
-{
- S32 success;
- char logs[512];
-
- U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
- U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
- U32 geometry_shader = compile_shader(GL_GEOMETRY_SHADER, geometry_shader_filename);
-
- U32 shader_program;
- shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glAttachShader(shader_program, geometry_shader);
- glLinkProgram(shader_program);
- glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
- if (success == GL_FALSE) {
- glGetProgramInfoLog(shader_program, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s",
- logs);
- } else {
- fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
- }
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
- glDeleteShader(geometry_shader);
-
- return(shader_program);
-}
-
-void
-shader_set_3f(U32 shader_program, char *uniform_name, F32 x, F32 y, F32 z)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniform3f(uniform_location, x, y, z);
-}
-
-void
-shader_set_1f(U32 shader_program, char *uniform_name, F32 value)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniform1f(uniform_location, value);
-}
-
-void
-shader_set_3fv(U32 shader_program, char *uniform_name, V3F value)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniform3fv(uniform_location, 1, (const GLfloat *)&value);
-}
-
-void
-shader_set_2fv(U32 shader_program, char *uniform_name, V2F value)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniform2fv(uniform_location, 1, (const GLfloat *)&value);
-}
-
-void
-shader_set_mat4fv(U32 shader_program, char *uniform_name, MAT4 value)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (F32 *)&value);
-}
-
-void
-shader_set_1i(U32 shader_program, char *uniform_name, S32 value)
-{
- U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
- glUniform1i(uniform_location, value);
-}
-
-U32
-load_texture(char *texture_filename)
-{
- S32 width, height, number_channels;
- U32 texture_id;
-
- glGenTextures(1, &texture_id);
-
- stbi_set_flip_vertically_on_load(1);
- U8 *data = stbi_load(texture_filename, &width, &height, &number_channels, 0);
- if (data) {
- GLenum format = 0;
- if (number_channels == 1)
- format = GL_RED;
- else if (number_channels == 3)
- format = GL_RGB;
- else if (number_channels == 4)
- format = GL_RGBA;
-
- glBindTexture(GL_TEXTURE_2D, texture_id);
- glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
- glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n",
- texture_filename);
- } else {
- fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n",
- texture_filename);
- }
- stbi_image_free(data);
-
- return(texture_id);
-}
-
-U32
-load_texture_gamma(char *filename, B32 gamma_correction)
-{
- S32 width, height, number_channels;
- U32 texture_id;
-
- glGenTextures(1, &texture_id);
-
- stbi_set_flip_vertically_on_load(1);
- U8 *data = stbi_load(filename, &width, &height, &number_channels, 0);
- if (data) {
- GLenum internal_format, data_format;
- if (number_channels == 1)
- {
- internal_format = data_format = GL_RED;
- }
- else if (number_channels == 3)
- {
- internal_format = gamma_correction ? GL_SRGB : GL_RGB;
- data_format = GL_RGB;
- }
- else if (number_channels == 4)
- {
- internal_format = gamma_correction ? GL_SRGB_ALPHA : GL_RGBA;
- data_format = GL_RGBA;
- }
-
- glBindTexture(GL_TEXTURE_2D, texture_id);
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height,
- 0, data_format, GL_UNSIGNED_BYTE, data);
- glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n", filename);
- } else {
- fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n", filename);
- }
- stbi_image_free(data);
-
- return(texture_id);
-}
-
-U32
-load_cubemap(const char *texture_filenames[6])
-{
- U32 texture_id;
- glGenTextures(1, &texture_id);
- glBindTexture(GL_TEXTURE_CUBE_MAP, texture_id);
- S32 width, height, number_channels;
- U8 *data = 0;
- stbi_set_flip_vertically_on_load(0);
- for (U32 texture_index = 0;
- texture_index < 6;
- ++texture_index)
- {
- data = stbi_load(texture_filenames[texture_index], &width, &height,
- &number_channels, 0);
- if (data) {
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+texture_index, 0, GL_RGB,
- width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
- fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n",
- texture_filenames[texture_index]);
- } else {
- fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n",
- texture_filenames[texture_index]);
- }
- stbi_image_free(data);
- }
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- return(texture_id);
+U8 * read_entire_file(const char *filename)
+{
+ U8 *result;
+ FILE *f;
+ long file_size;
+
+ result = 0;
+
+ if (!filename)
+ return(result);
+
+ f = fopen(filename, "rb");
+ if (!f)
+ return(result);
+
+ fseek(f, 0, SEEK_END);
+ file_size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ result = malloc(file_size + 1);
+ fread(result, file_size, 1, f);
+ fclose(f);
+
+ result[file_size] = 0;
+
+ return(result);
+}
+
+void * mmap_file(size_t *len, const char *filename)
+{
+ struct stat sb;
+ char* p;
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ perror("open");
+ return NULL;
+ }
+
+ if (fstat(fd, &sb) == -1) {
+ perror("fstat");
+ return NULL;
+ }
+
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "%s is not a file\n", filename);
+ return NULL;
+ }
+
+ p = (char*)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (p == MAP_FAILED) {
+ perror("mmap");
+ return NULL;
+ }
+
+ if (close(fd) == -1) {
+ perror("close");
+ return NULL;
+ }
+
+ (*len) = sb.st_size;
+
+ return p;
+}
+
+void read_entire_file_mmap(void* ctx, const char* filename, const int is_mtl,
+ const char* obj_filename, char** data, size_t* len)
+{
+ if (!filename) {
+ fprintf(stderr, "[ERROR]: Filename not provided (null)\n");
+ *data = 0;
+ *len = 0;
+ return;
+ }
+
+ size_t data_len = 0;
+
+ *data = mmap_file(&data_len, filename);
+ *len = data_len;
+}
+
+Mesh * mesh_load_obj(Arena *arena, const char *filename)
+{
+ tinyobj_attrib_t attrib;
+ tinyobj_shape_t *shapes = 0;
+ tinyobj_material_t *materials = 0;
+ size_t num_shapes, num_materials, num_triangles;
+ size_t i, j, face_offset;
+ U32 flags;
+ Mesh *mesh = 0;
+
+ flags = TINYOBJ_FLAG_TRIANGULATE;
+
+ S32 status = tinyobj_parse_obj(&attrib, &shapes, &num_shapes,
+ &materials, &num_materials, filename,
+ read_entire_file_mmap, 0, flags);
+
+ if (status != TINYOBJ_SUCCESS) {
+ fprintf(stderr, "[ERROR]: Failed to parse \"%s\"\n", filename);
+ if (status == TINYOBJ_ERROR_INVALID_PARAMETER)
+ fprintf(stderr, "[ERROR]: TINYOBJ_ERROR_INVALID_PARAMETER\n");
+ return(mesh);
+ }
+
+ num_triangles = attrib.num_face_num_verts;
+ face_offset = 0;
+
+ Vertex *vertices = arena_push_size(arena, sizeof(Vertex)*num_triangles*3);
+ U32 *indices = arena_push_size(arena, num_triangles*3*sizeof(U32));
+ U32 vertex_count = 0;
+ U32 index_count = 0, index_index = 0;
+ for (i = 0; i < attrib.num_face_num_verts; ++i) {
+ tinyobj_vertex_index_t idx;
+ V3F pos, normal;
+ V2F tex_coords;
+
+ Assert(attrib.face_num_verts[i]%3 == 0);
+
+ Assert(attrib.face_num_verts[i]/3 > 3);
+
+ Assert(attrib.num_texcoords);
+
+ for (j = 0; j < 3; ++j) {
+ idx = attrib.faces[face_offset+j];
+ Assert(idx.v_idx >= 0);
+ pos = v3f(attrib.vertices[3*idx.v_idx+0],
+ attrib.vertices[3*idx.v_idx+1],
+ attrib.vertices[3*idx.v_idx+2]);
+
+ Assert(idx.vn_idx < (S32)attrib.num_normals);
+ normal = v3f(attrib.normals[3*idx.vn_idx+0],
+ attrib.normals[3*idx.vn_idx+1],
+ attrib.normals[3*idx.vn_idx+2]);
+
+ Assert(idx.vt_idx < (S32)attrib.num_texcoords);
+ tex_coords = v2f(attrib.texcoords[2*idx.vt_idx+0],
+ attrib.texcoords[2*idx.vt_idx+1]);
+
+ vertices[vertex_count++] = vertex(pos, normal, tex_coords);
+ Assert(index_count < attrib.num_faclibe_num_verts);
+ indices[index_index++] = index_count++;
+ }
+
+ face_offset += 3;
+ }
+
+ mesh = mesh_init(arena, vertices, vertex_count,
+ indices, num_triangles*3);
+
+ tinyobj_attrib_free(&attrib);
+ tinyobj_shapes_free(shapes, num_shapes);
+ tinyobj_materials_free(materials, num_materials);
+
+ return(mesh);
+}
+
+U32 compile_shader(GLenum type, const char *filename)
+{
+ U32 shader;
+ S32 status;
+ char logs[512];
+
+ const char *source = (const char *)read_entire_file(filename);
+ if (!source) {
+ fprintf(stderr, "[ERROR]: Failed to read the file \"%s\"\n", filename);
+ return(0);
+ }
+
+ shader = glCreateShader(type);
+ glShaderSource(shader, 1, &source, 0);
+ free((void *)source);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ glGetShaderInfoLog(shader, 512, 0, logs);
+ fprintf(stderr, "[ERROR]: Failed to compile: \"%s\"\n%s", filename, logs);
+ } else {
+ fprintf(stdout, "[INFO]: \"%s\" compiled successfuly.\n", filename);
+ }
+ return(shader);
+}
+
+U32 create_shader_program(char *vertex_shader_filename,
+ char *fragment_shader_filename)
+{
+ S32 success;
+ char logs[512];
+
+ U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
+ U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
+
+ U32 shader_program;
+ shader_program = glCreateProgram();
+ glAttachShader(shader_program, vertex_shader);
+ glAttachShader(shader_program, fragment_shader);
+ glLinkProgram(shader_program);
+ glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
+ if (success == GL_FALSE) {
+ glGetProgramInfoLog(shader_program, 512, 0, logs);
+ fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s", logs);
+ } else {
+ fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
+ }
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+
+ return(shader_program);
+}
+
+U32 create_shader_program_geom(char *vertex_shader_filename,
+ char *fragment_shader_filename,
+ char *geometry_shader_filename)
+{
+ S32 success;
+ char logs[512];
+
+ U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
+ U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
+ U32 geometry_shader = compile_shader(GL_GEOMETRY_SHADER, geometry_shader_filename);
+
+ U32 shader_program;
+ shader_program = glCreateProgram();
+ glAttachShader(shader_program, vertex_shader);
+ glAttachShader(shader_program, fragment_shader);
+ glAttachShader(shader_program, geometry_shader);
+ glLinkProgram(shader_program);
+ glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
+ if (success == GL_FALSE) {
+ glGetProgramInfoLog(shader_program, 512, 0, logs);
+ fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s",
+ logs);
+ } else {
+ fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
+ }
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+ glDeleteShader(geometry_shader);
+
+ return(shader_program);
+}
+
+void shader_set_3f(U32 shader_program, char *uniform_name, F32 x, F32 y, F32 z)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniform3f(uniform_location, x, y, z);
+}
+
+void shader_set_1f(U32 shader_program, char *uniform_name, F32 value)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniform1f(uniform_location, value);
+}
+
+void shader_set_3fv(U32 shader_program, char *uniform_name, V3F value)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniform3fv(uniform_location, 1, (const GLfloat *)&value);
+}
+
+void shader_set_2fv(U32 shader_program, char *uniform_name, V2F value)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniform2fv(uniform_location, 1, (const GLfloat *)&value);
+}
+
+void shader_set_mat4fv(U32 shader_program, char *uniform_name, MAT4 value)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (F32 *)&value);
+}
+
+void shader_set_1i(U32 shader_program, char *uniform_name, S32 value)
+{
+ U32 uniform_location = glGetUniformLocation(shader_program, uniform_name);
+ glUniform1i(uniform_location, value);
+}
+
+U32 load_texture(char *texture_filename)
+{
+ S32 width, height, number_channels;
+ U32 texture_id;
+
+ glGenTextures(1, &texture_id);
+
+ stbi_set_flip_vertically_on_load(1);
+ U8 *data = stbi_load(texture_filename, &width, &height, &number_channels, 0);
+ if (data) {
+ GLenum format = 0;
+ if (number_channels == 1)
+ format = GL_RED;
+ else if (number_channels == 3)
+ format = GL_RGB;
+ else if (number_channels == 4)
+ format = GL_RGBA;
+
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n",
+ texture_filename);
+ } else {
+ fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n",
+ texture_filename);
+ }
+ stbi_image_free(data);
+
+ return(texture_id);
+}
+
+U32 load_texture_gamma(char *filename, B32 gamma_correction)
+{
+ S32 width, height, number_channels;
+ U32 texture_id;
+
+ glGenTextures(1, &texture_id);
+
+ stbi_set_flip_vertically_on_load(1);
+ U8 *data = stbi_load(filename, &width, &height, &number_channels, 0);
+ if (data) {
+ GLenum internal_format, data_format;
+ if (number_channels == 1) {
+ internal_format = data_format = GL_RED;
+ } else if (number_channels == 3) {
+ internal_format = gamma_correction ? GL_SRGB : GL_RGB;
+ data_format = GL_RGB;
+ } else if (number_channels == 4) {
+ internal_format = gamma_correction ? GL_SRGB_ALPHA : GL_RGBA;
+ data_format = GL_RGBA;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height,
+ 0, data_format, GL_UNSIGNED_BYTE, data);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n", filename);
+ } else {
+ fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n", filename);
+ }
+ stbi_image_free(data);
+
+ return(texture_id);
+}
+
+U32 load_cubemap(const char *texture_filenames[6])
+{
+ U32 texture_id;
+ glGenTextures(1, &texture_id);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, texture_id);
+ S32 width, height, number_channels;
+ U8 *data = 0;
+ stbi_set_flip_vertically_on_load(0);
+ for (U32 i = 0; i < 6; ++i) {
+ data = stbi_load(texture_filenames[i], &width, &height,
+ &number_channels, 0);
+ if (data) {
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGB,
+ width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
+ fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n",
+ texture_filenames[i]);
+ } else {
+ fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n",
+ texture_filenames[i]);
+ }
+ stbi_image_free(data);
+ }
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ return(texture_id);
}
typedef struct {
- V3F translate;
- V3F scale;
- V3F rotate;
+ V3F translate;
+ V3F scale;
+ V3F rotate;
} Transform;
enum KeyState_Enum {
- KeyState_RELEASE = 0,
- KeyState_PRESS = 1
+ KeyState_RELEASE = 0,
+ KeyState_PRESS = 1
};
typedef struct {
- enum KeyState_Enum last;
- enum KeyState_Enum state;
+ enum KeyState_Enum last;
+ enum KeyState_Enum state;
} Key;
typedef struct {
- Key move_right;
- Key move_forward;
- Key move_left;
- Key move_backward;
- Key move_up;
- Key move_down;
- Key jump;
- Key action_right;
- Key action_up;
- Key action_left;
- Key action_down;
- Key exit;
- V2F last_mouse_pos;
- V2F mouse_offset;
+ Key move_right;
+ Key move_forward;
+ Key move_left;
+ Key move_backward;
+ Key move_up;
+ Key move_down;
+ Key jump;
+ Key action_right;
+ Key action_up;
+ Key action_left;
+ Key action_down;
+ Key exit;
+ V2F last_mouse_pos;
+ V2F mouse_offset;
+ B32 first_mouse;
} Input;
-void
-input_update_last_state(Input *input)
+Input input_init()
{
- input->move_right.last = input->move_right.state;
- input->move_forward.last = input->move_forward.state;
- input->move_left.last = input->move_left.state;
- input->move_backward.last = input->move_backward.state;
- input->move_up.last = input->move_up.state;
- input->move_down.last = input->move_down.state;
- input->jump.last = input->jump.state;
- input->action_right.last = input->action_right.state;
- input->action_up.last = input->action_up.state;
- input->action_left.last = input->action_left.state;
- input->action_down.last = input->action_down.state;
- input->exit.last = input->exit.state;
+ Input r = {0};
+ r.first_mouse = 1;
+ return(r);
}
-void
-process_glfw_key(GLFWwindow *window, S32 glfw_keycode, Key *key)
+void input_update_last_state(Input *input)
{
- if (glfwGetKey(window, glfw_keycode) == GLFW_PRESS)
- key->state = KeyState_PRESS;
- else
- key->state = KeyState_RELEASE;
+ input->move_right.last = input->move_right.state;
+ input->move_forward.last = input->move_forward.state;
+ input->move_left.last = input->move_left.state;
+ input->move_backward.last = input->move_backward.state;
+ input->move_up.last = input->move_up.state;
+ input->move_down.last = input->move_down.state;
+ input->jump.last = input->jump.state;
+ input->action_right.last = input->action_right.state;
+ input->action_up.last = input->action_up.state;
+ input->action_left.last = input->action_left.state;
+ input->action_down.last = input->action_down.state;
+ input->exit.last = input->exit.state;
}
-void
-process_glfw_keyboard(GLFWwindow *window, Input *input)
+void process_glfw_key(GLFWwindow *window, S32 glfw_keycode, Key *key)
{
- process_glfw_key(window, GLFW_KEY_D, &input->move_right);
- process_glfw_key(window, GLFW_KEY_W, &input->move_forward);
- process_glfw_key(window, GLFW_KEY_A, &input->move_left);
- process_glfw_key(window, GLFW_KEY_S, &input->move_backward);
- process_glfw_key(window, GLFW_KEY_E, &input->move_up);
- process_glfw_key(window, GLFW_KEY_Q, &input->move_down);
- process_glfw_key(window, GLFW_KEY_SPACE, &input->jump);
- process_glfw_key(window, GLFW_KEY_RIGHT, &input->action_right);
- process_glfw_key(window, GLFW_KEY_UP, &input->action_up);
- process_glfw_key(window, GLFW_KEY_LEFT, &input->action_left);
- process_glfw_key(window, GLFW_KEY_DOWN, &input->action_down);
- process_glfw_key(window, GLFW_KEY_ESCAPE, &input->exit);
+ if (glfwGetKey(window, glfw_keycode) == GLFW_PRESS)
+ key->state = KeyState_PRESS;
+ else
+ key->state = KeyState_RELEASE;
}
-void
-error_callback(int error, const char *desc)
+void process_glfw_keyboard(GLFWwindow *window, Input *input)
{
- fprintf(stderr, "[ERROR] GLFW: %s\n", desc);
+ process_glfw_key(window, GLFW_KEY_D, &input->move_right);
+ process_glfw_key(window, GLFW_KEY_W, &input->move_forward);
+ process_glfw_key(window, GLFW_KEY_A, &input->move_left);
+ process_glfw_key(window, GLFW_KEY_S, &input->move_backward);
+ process_glfw_key(window, GLFW_KEY_E, &input->move_up);
+ process_glfw_key(window, GLFW_KEY_Q, &input->move_down);
+ process_glfw_key(window, GLFW_KEY_SPACE, &input->jump);
+ process_glfw_key(window, GLFW_KEY_RIGHT, &input->action_right);
+ process_glfw_key(window, GLFW_KEY_UP, &input->action_up);
+ process_glfw_key(window, GLFW_KEY_LEFT, &input->action_left);
+ process_glfw_key(window, GLFW_KEY_DOWN, &input->action_down);
+ process_glfw_key(window, GLFW_KEY_ESCAPE, &input->exit);
}
-B32
-key_is_pressed(Key key)
+void process_glfw_mouse_pos(GLFWwindow *window, Input *input)
+{
+ F64 xpos, ypos;
+ glfwGetCursorPos(window, &xpos, &ypos);
+ if (input->first_mouse) {
+ input->last_mouse_pos = v2f((F32)xpos, (F32)ypos);
+ input->first_mouse = 0;
+ }
+ input->mouse_offset = v2f(input->mouse_offset.x+((F32)xpos-input->last_mouse_pos.x),
+ input->mouse_offset.y+((F32)ypos-input->last_mouse_pos.y));
+ input->last_mouse_pos = v2f((F32)xpos, (F32)ypos);
+}
+
+
+void error_callback(int error, const char *desc)
{
- B32 result = (key.state == KeyState_PRESS);
- return(result);
+ fprintf(stderr, "[ERROR] GLFW: %s\n", desc);
}
-B32
-key_first_press(Key key)
+B32 key_is_pressed(Key key)
{
- B32 result = ((key.last == KeyState_RELEASE) &&
- (key.state == KeyState_PRESS));
- return(result);
+ B32 result = (key.state == KeyState_PRESS);
+ return(result);
}
-B32
-key_was_pressed(Key key)
+B32 key_first_press(Key key)
{
- B32 result = ((key.last == KeyState_PRESS) &&
- (key.state == KeyState_RELEASE));
- return(result);
+ B32 result = ((key.last == KeyState_RELEASE) &&
+ (key.state == KeyState_PRESS));
+ return(result);
}
-MAT4
-mat4_change_basis(V3F x, V3F y, V3F z)
+B32 key_was_pressed(Key key)
{
- MAT4 result = mat4_identity();
- result.m0 = v4f(x.x, x.y, x.z, 0.0f);
- result.m1 = v4f(y.x, y.y, y.z, 0.0f);
- result.m2 = v4f(z.x, z.y, z.z, 0.0f);
- return(result);
+ B32 result = ((key.last == KeyState_PRESS) &&
+ (key.state == KeyState_RELEASE));
+ return(result);
+}
+
+MAT4 mat4_change_basis(V3F x, V3F y, V3F z)
+{
+ MAT4 result = mat4_identity();
+ result.m0 = v4f(x.x, x.y, x.z, 0.0f);
+ result.m1 = v4f(y.x, y.y, y.z, 0.0f);
+ result.m2 = v4f(z.x, z.y, z.z, 0.0f);
+ return(result);
}
/*
@@ -549,261 +534,242 @@ mat4_change_basis(V3F x, V3F y, V3F z)
* | 0 cx -sx |*| 0 1 0 |*| sz cz 0 |=| sx*sy*cz+cx*sz -sx*sy*sz+cx*cz -sx*cy |
* | 0 sx cx | | -sy 0 cy | | 0 0 1 | | -cx*sy*cz+sx*sz cx*sy*sz+sx*cz cx*cy |
*/
-MAT4
-mat4_make_rotate(V3F angles)
+MAT4 mat4_make_rotate(V3F angles)
{
- F32 angle, cx, sx, cy, sy, cz, sz;
- MAT4 result;
- V3F newx, newy, newz;
-
- angle = DEG2RAD*angles.x;
- cx = f32_cos(angle);
- sx = f32_sin(angle);
- angle = DEG2RAD*angles.y;
- cy = f32_cos(angle);
- sy = f32_sin(angle);
- angle = DEG2RAD*angles.z;
- cz = f32_cos(angle);
- sz = f32_sin(angle);
-
- newx = v3f(cy*cz, sx*sy*cz+cx*sz, -cx*sy*cz+sx*sz);
- newy = v3f(-cy*sz, -sx*sy*sz+cx*cz, cx*sy*sz+sx*cz);
- newz = v3f(sy, -sx*cy, cx*cy);
- result = mat4_change_basis(newx, newy, newz);
-
- return(result);
+ F32 angle, cx, sx, cy, sy, cz, sz;
+ MAT4 result;
+ V3F newx, newy, newz;
+
+ angle = DEG2RAD*angles.x;
+ cx = f32_cos(angle);
+ sx = f32_sin(angle);
+ angle = DEG2RAD*angles.y;
+ cy = f32_cos(angle);
+ sy = f32_sin(angle);
+ angle = DEG2RAD*angles.z;
+ cz = f32_cos(angle);
+ sz = f32_sin(angle);
+
+ newx = v3f(cy*cz, sx*sy*cz+cx*sz, -cx*sy*cz+sx*sz);
+ newy = v3f(-cy*sz, -sx*sy*sz+cx*cz, cx*sy*sz+sx*cz);
+ newz = v3f(sy, -sx*cy, cx*cy);
+ result = mat4_change_basis(newx, newy, newz);
+
+ return(result);
}
-MAT4
-mat4_rotate_angles(MAT4 source, V3F angles)
+MAT4 mat4_rotate_angles(MAT4 source, V3F angles)
{
- MAT4 rotate = mat4_make_rotate(angles);
- MAT4 result = mat4_mul(rotate, source);
- return(result);
+ MAT4 rotate = mat4_make_rotate(angles);
+ MAT4 result = mat4_mul(rotate, source);
+ return(result);
}
-Transform
-transform_make(V3F translate, V3F scale, V3F rotate)
+Transform transform_make(V3F translate, V3F scale, V3F rotate)
{
- Transform result;
- result.translate = translate;
- result.scale = scale;
- result.rotate = rotate;
- return(result);
+ Transform result;
+ result.translate = translate;
+ result.scale = scale;
+ result.rotate = rotate;
+ return(result);
}
-Transform
-transform_default()
+Transform transform_default()
{
- Transform result = transform_make(v3f_zero(), v3f_one(), v3f_zero());
- return(result);
+ Transform result = transform_make(v3f_zero(), v3f_one(), v3f_zero());
+ return(result);
}
-Transform
-transform_make_translate(V3F translate)
+Transform transform_make_translate(V3F translate)
{
- Transform result = transform_default();
- result.translate = translate;
- return(result);
+ Transform result = transform_default();
+ result.translate = translate;
+ return(result);
}
-Transform
-transform_make_scale(V3F scale)
+Transform transform_make_scale(V3F scale)
{
- Transform result = transform_default();
- result.scale = scale;
- return(result);
+ Transform result = transform_default();
+ result.scale = scale;
+ return(result);
}
-Transform
-transform_make_rotate(V3F angles)
+Transform transform_make_rotate(V3F angles)
{
- Transform result = transform_default();
- result.rotate = angles;
- return(result);
+ Transform result = transform_default();
+ result.rotate = angles;
+ return(result);
}
-Transform
-transform_translate(Transform source, V3F translate)
+Transform transform_translate(Transform source, V3F translate)
{
- Transform result = source;
- result.translate = v3f_add(source.translate, translate);
- return(result);
+ Transform result = source;
+ result.translate = v3f_add(source.translate, translate);
+ return(result);
}
-Transform
-transform_scale(Transform source, V3F scale)
+Transform transform_scale(Transform source, V3F scale)
{
- Transform result = source;
- result.scale = v3f_dot(source.scale, scale);
- return(result);
+ Transform result = source;
+ result.scale = v3f_dot(source.scale, scale);
+ return(result);
}
-Transform
-transform_rotate(Transform source, V3F angles)
+Transform transform_rotate(Transform source, V3F angles)
{
- Transform result;
- result.translate = source.translate;
- result.scale = source.scale;
- result.rotate = v3f_add(source.rotate, angles);
- return(result);
+ Transform result;
+ result.translate = source.translate;
+ result.scale = source.scale;
+ result.rotate = v3f_add(source.rotate, angles);
+ return(result);
}
-Transform
-transform_make_scale_translate(V3F scale, V3F translate)
+Transform transform_make_scale_translate(V3F scale, V3F translate)
{
- Transform result = transform_default();
- result.translate = translate;
- result.scale = scale;
- return(result);
+ Transform result = transform_default();
+ result.translate = translate;
+ result.scale = scale;
+ return(result);
}
-MAT4
-transform_apply(Transform transform)
+MAT4 transform_apply(Transform transform)
{
- MAT4 result = mat4_identity();
- MAT4 translate = mat4_make_translate(transform.translate);
- MAT4 scale = mat4_make_scale(transform.scale);
- MAT4 rotate = mat4_make_rotate(transform.rotate);
- result = mat4_mul(mat4_mul(translate, scale), rotate);
- return(result);
+ MAT4 result = mat4_identity();
+ MAT4 translate = mat4_make_translate(transform.translate);
+ MAT4 scale = mat4_make_scale(transform.scale);
+ MAT4 rotate = mat4_make_rotate(transform.rotate);
+ result = mat4_mul(mat4_mul(translate, scale), rotate);
+ return(result);
}
-MAT4
-ortho(F32 l, F32 r, F32 b, F32 t, F32 n, F32 f)
+MAT4 ortho(F32 l, F32 r, F32 b, F32 t, F32 n, F32 f)
{
- MAT4 result = mat4_identity();
- result.m0.x = 2.0f/(r-l);
- result.m1.y = 2.0f/(t-b);
- result.m2.z = -2.0f/(f-n);
- result.m3.x = -(r+l)/(r-l);
- result.m3.y = -(t+b)/(t-b);
- result.m3.z = -(f+n)/(f-n);
- return(result);
+ MAT4 result = mat4_identity();
+ result.m0.x = 2.0f/(r-l);
+ result.m1.y = 2.0f/(t-b);
+ result.m2.z = -2.0f/(f-n);
+ result.m3.x = -(r+l)/(r-l);
+ result.m3.y = -(t+b)/(t-b);
+ result.m3.z = -(f+n)/(f-n);
+ return(result);
}
-MAT4
-perspective(F32 fovx, F32 ar, F32 n, F32 f)
+MAT4 perspective(F32 fovx, F32 ar, F32 n, F32 f)
{
- F32 r = n*f32_tan(fovx/2.0f*DEG2RAD);
- F32 t = r/ar;
- MAT4 result = mat4_identity();
- result.m0.x = n/r;
- result.m1.y = n/t;
- result.m2.z = -(f+n)/(f-n);
- result.m2.w = -1.0f;
- result.m3.z = (-2.0f*f*n)/(f-n);
- result.m3.w = 0.0f;
- return(result);
+ F32 r = n*f32_tan(fovx/2.0f*DEG2RAD);
+ F32 t = r/ar;
+ MAT4 result = mat4_identity();
+ result.m0.x = n/r;
+ result.m1.y = n/t;
+ result.m2.z = -(f+n)/(f-n);
+ result.m2.w = -1.0f;
+ result.m3.z = (-2.0f*f*n)/(f-n);
+ result.m3.w = 0.0f;
+ return(result);
}
-MAT4
-look_at(V3F eye, V3F target, V3F up)
+MAT4 look_at(V3F eye, V3F target, V3F up)
{
- V3F f = v3f_norm(v3f_sub(eye, target));
- V3F l = v3f_norm(v3f_cross(up, f));
- V3F u = v3f_cross(f, l);
- MAT4 translate = mat4_make_translate(v3f_negate(eye));
- MAT4 rotate = mat4_change_basis(l, u, f);
- MAT4 result = mat4_mul(mat4_transpose(rotate), translate);
- return(result);
+ V3F f = v3f_norm(v3f_sub(eye, target));
+ V3F l = v3f_norm(v3f_cross(up, f));
+ V3F u = v3f_cross(f, l);
+ MAT4 translate = mat4_make_translate(v3f_negate(eye));
+ MAT4 rotate = mat4_change_basis(l, u, f);
+ MAT4 result = mat4_mul(mat4_transpose(rotate), translate);
+ return(result);
}
typedef struct {
- V3F pos;
- F32 fovx;
- F32 near;
- F32 far;
-
- /* NOTE(pryazha): In degrees */
- F32 yaw;
- F32 pitch;
+ V3F pos;
+ F32 fovx;
+ F32 near;
+ F32 far;
+
+ /* NOTE(pryazha): In degrees */
+ F32 yaw;
+ F32 pitch;
} Camera;
-MAT4
-get_view_matrix(Camera *camera)
-{
- MAT4 view;
- view = mat4_make_translate(v3f_negate(camera->pos));
- view = mat4_rotate_angles(view, v3f(camera->pitch, camera->yaw, 0.0f));
- return(view);
-}
-
-V3F
-get_dv_camera_orbital(Input *input, V3F pos, V3F target,
- F32 dt, F32 acceleration)
-{
- V3F up, f, l, u, dv;
-
- up = v3f(0.0f, 1.0f, 0.0f);
- f = v3f_norm(v3f_sub(target, pos));
- l = v3f_norm(v3f_cross(up, f));
- u = v3f_cross(f, l);
-
- dv = v3f_zero();
-
- if (key_is_pressed(input->move_right))
- dv = v3f_sub(dv, l);
- if (key_is_pressed(input->move_forward))
- dv = v3f_add(dv, f);
- if (key_is_pressed(input->move_left))
- dv = v3f_add(dv, l);
- if (key_is_pressed(input->move_backward))
- dv = v3f_sub(dv, f);
- if (key_is_pressed(input->move_up))
- dv = v3f_add(dv, u);
- if (key_is_pressed(input->move_down))
- dv = v3f_sub(dv, u);
-
- dv = v3f_norm(dv);
-
- dv = v3f_scalef(dv, acceleration*dt);
-
- return(dv);
-}
-
-void
-get_camera_vectors(Camera *camera, V3F *l, V3F *u, V3F *f)
-{
- MAT4 view;
- view = get_view_matrix(camera);
- *l = v3f(-view.m0.x, -view.m1.x, -view.m2.x);
- *u = v3f(view.m0.y, view.m1.y, view.m2.y);
- *f = v3f(-view.m0.z, -view.m1.z, -view.m2.z);
-}
-
-V3F
-get_dv_camera_first_person(Input *input, Camera *camera,
- F32 acceleration, F32 dt)
-{
- V3F f, l, u, dv;
- get_camera_vectors(camera, &l, &u, &f);
-
- dv = v3f_zero();
-
- if (key_is_pressed(input->move_right))
- dv = v3f_sub(dv, l);
- if (key_is_pressed(input->move_forward))
- dv = v3f_add(dv, f);
- if (key_is_pressed(input->move_left))
- dv = v3f_add(dv, l);
- if (key_is_pressed(input->move_backward))
- dv = v3f_sub(dv, f);
- if (key_is_pressed(input->move_up))
- dv = v3f_add(dv, u);
- if (key_is_pressed(input->move_down))
- dv = v3f_sub(dv, u);
-
- dv = v3f_norm(dv);
-
- dv = v3f_scalef(dv, acceleration*dt);
-
- return(dv);
+MAT4 get_view_matrix(Camera *camera)
+{
+ MAT4 view;
+ view = mat4_make_translate(v3f_negate(camera->pos));
+ view = mat4_rotate_angles(view, v3f(camera->pitch, camera->yaw, 0.0f));
+ return(view);
+}
+
+V3F get_dv_camera_orbital(Input *input, V3F pos, V3F target,
+ F32 dt, F32 acceleration)
+{
+ V3F up, f, l, u, dv;
+
+ up = v3f(0.0f, 1.0f, 0.0f);
+ f = v3f_norm(v3f_sub(target, pos));
+ l = v3f_norm(v3f_cross(up, f));
+ u = v3f_cross(f, l);
+
+ dv = v3f_zero();
+
+ if (key_is_pressed(input->move_right))
+ dv = v3f_sub(dv, l);
+ if (key_is_pressed(input->move_forward))
+ dv = v3f_add(dv, f);
+ if (key_is_pressed(input->move_left))
+ dv = v3f_add(dv, l);
+ if (key_is_pressed(input->move_backward))
+ dv = v3f_sub(dv, f);
+ if (key_is_pressed(input->move_up))
+ dv = v3f_add(dv, u);
+ if (key_is_pressed(input->move_down))
+ dv = v3f_sub(dv, u);
+
+ dv = v3f_norm(dv);
+
+ dv = v3f_scalef(dv, acceleration*dt);
+
+ return(dv);
+}
+
+void get_camera_vectors(Camera *camera, V3F *l, V3F *u, V3F *f)
+{
+ MAT4 view;
+ view = get_view_matrix(camera);
+ *l = v3f(-view.m0.x, -view.m1.x, -view.m2.x);
+ *u = v3f(view.m0.y, view.m1.y, view.m2.y);
+ *f = v3f(-view.m0.z, -view.m1.z, -view.m2.z);
+}
+
+V3F get_dv_camera_first_person(Input *input, Camera *camera,
+ F32 acceleration, F32 dt)
+{
+ V3F f, l, u, dv;
+ get_camera_vectors(camera, &l, &u, &f);
+
+ dv = v3f_zero();
+
+ if (key_is_pressed(input->move_right))
+ dv = v3f_sub(dv, l);
+ if (key_is_pressed(input->move_forward))
+ dv = v3f_add(dv, f);
+ if (key_is_pressed(input->move_left))
+ dv = v3f_add(dv, l);
+ if (key_is_pressed(input->move_backward))
+ dv = v3f_sub(dv, f);
+ if (key_is_pressed(input->move_up))
+ dv = v3f_add(dv, u);
+ if (key_is_pressed(input->move_down))
+ dv = v3f_sub(dv, u);
+
+ dv = v3f_norm(dv);
+
+ dv = v3f_scalef(dv, acceleration*dt);
+
+ return(dv);
}
typedef struct {
- Camera camera;
- F32 dt;
+ Camera camera;
+ F32 dt;
} State;
#endif /* COMMON_H */