diff options
author | pryazha <pryadeiniv@mail.ru> | 2025-02-19 22:26:48 +0500 |
---|---|---|
committer | pryazha <pryadeiniv@mail.ru> | 2025-02-19 22:26:48 +0500 |
commit | f9ad6fa902c1167d7622ee7af2617d14b62bee21 (patch) | |
tree | 9d78792cf360ed871616a9ea66c4237018292aa7 /libs/common.h | |
parent | 926cbd0d49890772f911e6a6bedb7835605ced89 (diff) |
quite a lot of changes that I, of course, are not going to describe;)
Diffstat (limited to 'libs/common.h')
-rw-r--r-- | libs/common.h | 1360 |
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 */ |