diff --git a/.gitignore b/.gitignore index 3e0be42..ffd0c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ data.txt *.sublime* *.bin *.4c -asset.log.txt \ No newline at end of file +asset.log.txt +perfclocks.txt \ No newline at end of file diff --git a/assets.cpp b/assets.cpp index df87afc..0d63332 100644 --- a/assets.cpp +++ b/assets.cpp @@ -1,438 +1,12 @@ -#include "multimedia.cpp" -#include "obj.cpp" - -#define STBI_ASSERT assert -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -enum class Obj_Token_Type { - none, word, number, whitespace, end -}; - -struct Obj_Token { - Obj_Token_Type type; - double number; - union { - struct { - char* s; - int len; - }; - String s8; - }; -}; - -function Bitmap -load_image(String path) { - Scratch scratch; - String file = os_read_file(scratch, path); - - int x, y, n; - unsigned char* data = stbi_load_from_memory(file.str, file.len, &x, &y, &n, 4); - Bitmap result = { (U32*)data, x, y }; - if(data) { - U32 *p = result.pixels; - for (int Y = 0; Y < y; Y++) { - for (int X = 0; X < x; X++) { - Vec4 color = vec4abgr(*p); - color.r *= color.a; - color.g *= color.a; - color.b *= color.a; - *p++ = vec4_to_u32abgr(color); - } - } - } - return result; -} - -function Obj_Token next_token_raw(char** data) { - Obj_Token result = {}; - result.s = *data; - *data += 1; - - if (is_alphabetic(*result.s)) { - result.type = Obj_Token_Type::word; - while (!is_whitespace(**data)) { - *data += 1; - } - result.len = (int)(*data - result.s); - } - else if (is_number(*result.s) || *result.s == '-') { - result.type = Obj_Token_Type::number; - while (is_number(**data) || **data == '.' || **data == 'e' || **data == '-') { - *data += 1; - } - result.number = atof(result.s); - result.len = (int)(*data - result.s); - } - else if (*result.s == '#') { - while (**data != '\n') *data += 1; - result = next_token_raw(data); - } - else if (is_whitespace(*result.s)) { - result.type = Obj_Token_Type::whitespace; - while (is_whitespace(**data)) *data += 1; - result.len = (int)(*data - result.s); - } - else if (*result.s == 0) { - result.type = Obj_Token_Type::end; - } - else if (*result.s >= '!') { - result.type = (Obj_Token_Type)*result.s; - } - - return result; -} - -function Obj_Token next_token(char** data) { - Obj_Token result; - do { - result = next_token_raw(data); - } while (result.type == Obj_Token_Type::whitespace); - return result; -} - -function double expect_number(char** data) { - Obj_Token t = next_token(data); - assert(t.type == Obj_Token_Type::number); // @Todo: Error handling, error flag - return t.number; -} - -function void expect_token(char** data, char token) { - Obj_Token t = next_token(data); - assert(t.type == (Obj_Token_Type)token); // @Todo: Error handling, error flag -} - -function void debug_expect_raw(char** data, Obj_Token_Type type) { - char* data_temp = *data; - Obj_Token t = next_token_raw(&data_temp); - assert(t.type == type); -} - -function void -parse_mtl(Obj* obj, String path_obj_folder, String mtl_file) { - Scratch scratch; - char *data = (char *)mtl_file.str; - Obj_Material *m = 0; - - for (;;) { - Obj_Token token = next_token(&data); - if (token.type == Obj_Token_Type::end) break; - else if (token.type == Obj_Token_Type::word) { - if (string_compare(token.s8, "newmtl"_s)) { - token = next_token(&data); - m = obj->materials.push_empty_zero(); - m->name_len = clamp_top(token.len, 64); - memory_copy(m->name, token.s8.str, m->name_len); - } - - else if (string_compare(token.s8, "Ns"_s)) { - m->shininess = expect_number(&data); - } - - else if (string_compare(token.s8, "Ka"_s)) { - m->ambient_color.x = expect_number(&data); - m->ambient_color.y = expect_number(&data); - m->ambient_color.z = expect_number(&data); - } - else if (string_compare(token.s8, "Kd"_s)) { - m->diffuse_color.x = expect_number(&data); - m->diffuse_color.y = expect_number(&data); - m->diffuse_color.z = expect_number(&data); - } - - else if (string_compare(token.s8, "Ks"_s)) { - m->specular_color.x = expect_number(&data); - m->specular_color.y = expect_number(&data); - m->specular_color.z = expect_number(&data); - } - else if (string_compare(token.s8, "Ni"_s)) { - m->optical_density = expect_number(&data); - } - - else if (string_compare(token.s8, "d"_s)) { - m->non_transparency = expect_number(&data); - } - else if (string_compare(token.s8, "illum"_s)) { - m->illumination_model = (S32)expect_number(&data); - } - - else if (string_compare(token.s8, "map_Kd"_s)) { - Obj_Token t = next_token(&data); - String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); - m->texture_diffuse = load_image(path); - } - - else if (string_compare(token.s8, "map_Ka"_s)) { - Obj_Token t = next_token(&data); - String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); - m->texture_ambient = load_image(path); - } - - else if (string_compare(token.s8, "map_d"_s)) { - Obj_Token t = next_token(&data); - String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); - m->texture_dissolve = load_image(path); - } - - else if (string_compare(token.s8, "map_Disp"_s)) { - Obj_Token t = next_token(&data); - String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); - m->texture_displacement = load_image(path); - } - } - } -} - -function Obj -parse(Allocator *allocator, char* data, String path_obj_folder) { - Set_Allocator(allocator); - Scratch mtl_scratch; - Obj result = {}; - //result.vertices.init(allocator, 160000); - //result.texture_coordinates.init(allocator, 160000); - //result.normals.init(allocator, 160000); - //result.mesh.init(allocator, 64); - //result.materials.init(allocator, 64); - int smoothing = 0; - - Obj_Mesh *mesh = result.mesh.push_empty_zero(); - //mesh->indices.init(allocator); - int material_id = -1; - - S64 debug_i = 0; - for (;;debug_i++){ - Obj_Token token = next_token(&data); - if (token.type == Obj_Token_Type::end) break; - else if (token.type == Obj_Token_Type::word) { - if (string_compare(token.s8, "v"_s)) { - Vec3 *vertex = result.vertices.push_empty_zero(); - vertex->x = (float)expect_number(&data); - vertex->y = (float)expect_number(&data); - vertex->z = (float)expect_number(&data); - debug_expect_raw(&data, Obj_Token_Type::whitespace); - } - - else if (string_compare(token.s8, "vt"_s)) { - Vec2 *tex = result.texture_coordinates.push_empty_zero(); - tex->x = (float)expect_number(&data); - tex->y = (float)expect_number(&data); - debug_expect_raw(&data, Obj_Token_Type::whitespace); - } - - else if (string_compare(token.s8, "vn"_s)) { - Vec3 *norm = result.normals.push_empty_zero(); - norm->x = (float)expect_number(&data); - norm->y = (float)expect_number(&data); - norm->z = (float)expect_number(&data); - debug_expect_raw(&data, Obj_Token_Type::whitespace); - } - - else if (string_compare(token.s8, "mtllib"_s)) { - Obj_Token t = next_token(&data); - String path = string_fmt(mtl_scratch, "%Q/%Q", path_obj_folder, t.s8); - String mtl_file = os_read_file(mtl_scratch, path); - if(mtl_file.str) { - parse_mtl(&result, path_obj_folder, mtl_file); - } - } - - else if (string_compare(token.s8, "usemtl"_s)) { - Obj_Token t = next_token(&data); - assert(t.type == Obj_Token_Type::word); - for(U64 i = 0; i < result.materials.len; i++) { - Obj_Material *m = result.materials.data + i; - if(string_compare({(U8 *)m->name, m->name_len}, t.s8)) { - material_id = i; - break; - } - } - } - - else if (string_compare(token.s8, "o"_s)) { - Obj_Token t = next_token(&data); - assert(t.type == Obj_Token_Type::word); - if (mesh->indices.len != 0) { - mesh = result.mesh.push_empty_zero(); - } - else { - U64 len = clamp_top(t.len, 64); - memory_copy(mesh->name, t.s, len); - } - } - - else if (string_compare(token.s8, "s"_s)) { - Obj_Token t = next_token(&data); - if (t.type == Obj_Token_Type::number) { - smoothing = (int)t.number; - } - else { - assert(t.type == Obj_Token_Type::word); - if (string_compare(t.s8, "on"_s)) { - smoothing = 1; - } - else if (string_compare(t.s8, "off"_s)) { - smoothing = 0; - } - else invalid_codepath; - } - - } - - else if (string_compare(token.s8, "g"_s)) { - Obj_Token t = next_token(&data); - assert(t.type == Obj_Token_Type::word); - } - - else if (string_compare(token.s8, "f"_s)) { - Obj_Index *i = mesh->indices.push_empty_zero(); - i->smoothing_group_id = smoothing; - i->material_id = material_id; - i->vertex[0] = (int)expect_number(&data); - expect_token(&data, '/'); - i->tex[0] = (int)expect_number(&data); - expect_token(&data, '/'); - i->normal[0] = (int)expect_number(&data); - - i->vertex[1] = (int)expect_number(&data); - expect_token(&data, '/'); - i->tex[1] = (int)expect_number(&data); - expect_token(&data, '/'); - i->normal[1] = (int)expect_number(&data); - - i->vertex[2] = (int)expect_number(&data); - expect_token(&data, '/'); - i->tex[2] = (int)expect_number(&data); - expect_token(&data, '/'); - i->normal[2] = (int)expect_number(&data); - //debug_expect_raw(&data, Obj_Token_Type::whitespace); - } - } - } - return result; -} - -function Obj -load_obj(Allocator *arena, String file) { - Scratch scratch; - String data = os_read_file(scratch, file); - assert(data.str); - - String path = string_chop_last_slash(file); - Obj result = parse(arena, (char *)data.str, path); - result.name = file; - return result; -} - -template void -dump_array(String_Builder *sb, Array *arr){ - sb->append_data(arr, sizeof(*arr)); - sb->append_data(arr->data, sizeof(T)*arr->len); -} - -function void -dump_bitmap_image(String_Builder *sb, Bitmap *bm){ - sb->append_data(bm->pixels, sizeof(U32)*bm->x*bm->y); -} - - -function B32 -_os_write_file(String file, String data, B32 append = false) { - B32 result = false; - DWORD access = GENERIC_WRITE; - DWORD creation_disposition = CREATE_ALWAYS; - if (append) { - access = FILE_APPEND_DATA; - creation_disposition = OPEN_ALWAYS; - } - - // @Todo(Krzosa): Unicode - HANDLE handle = CreateFileA((const char *)file.str, access, 0, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if (handle != INVALID_HANDLE_VALUE) { - DWORD bytes_written = 0; - // @Todo: can only read 32 byte size files? - assert_msg(data.len == (U32)data.len, "Max data size os_write can handle is 32 bytes, data to write is larger then 32 bytes!"); - B32 error = WriteFile(handle, data.str, (U32)data.len, &bytes_written, NULL); - if (error == false) log_error("Failed to write to file: %Q", file); - else { - if (bytes_written != data.len) log_error("Failed to write to file: %Q, mismatch between length requested to write and length written", file); - else result = true; - } - CloseHandle(handle); - } - else { - log_error("File not found when trying to write: %Q", file); - } - - return result; -} - -function B32 -os_write_file2(String file, String data) { - return _os_write_file(file, data, false); -} -function B32 -os_append_file(String file, String data) { - return _os_write_file(file, data, true); -} - -function void -dump_obj_to_file(Obj *obj, String out_name){ - obj->vertices.allocator = 0; - obj->vertices.cap = obj->vertices.len; - - obj->texture_coordinates.allocator = 0; - obj->texture_coordinates.cap = obj->texture_coordinates.len; - - obj->normals.allocator = 0; - obj->normals.cap = obj->normals.len; - - obj->mesh.allocator = 0; - obj->mesh.cap = obj->mesh.len; - - obj->materials.allocator = 0; - obj->materials.cap = obj->materials.len; - - For(obj->mesh){ - it.indices.allocator = 0; - it.indices.cap = it.indices.len; - } - - Scratch arena; - String_Builder sb = string_builder_make(arena, mib(4)); - sb.append_data(obj, sizeof(Obj)); - sb.append_data(obj->name.str, obj->name.len); - sb.append_data(obj->vertices.data, obj->vertices.len*sizeof(Vec3)); - sb.append_data(obj->texture_coordinates.data, obj->texture_coordinates.len*sizeof(Vec2)); - sb.append_data(obj->normals.data, obj->normals.len*sizeof(Vec3)); - sb.append_data(obj->mesh.data, obj->mesh.len*sizeof(Obj_Mesh)); - sb.append_data(obj->materials.data, obj->materials.len*sizeof(Obj_Material)); - - For(obj->mesh){ - sb.append_data(it.indices.data, sizeof(Obj_Index)*it.indices.len); - } - - For(obj->materials){ - sb.append_data(&it, sizeof(Obj_Material)); - dump_bitmap_image(&sb, &it.texture_ambient); - dump_bitmap_image(&sb, &it.texture_diffuse); - dump_bitmap_image(&sb, &it.texture_dissolve); - dump_bitmap_image(&sb, &it.texture_displacement); - } - - String result = string_flatten(arena, &sb); - os_write_file2(out_name, result); -} - -global FILE *output_file; +#include "obj_dump.cpp" function void asset_log(Log_Kind kind, String string, char *file, int line){ - fprintf(output_file, "%.*s", string_expand(string)); + printf("%.*s", string_expand(string)); } int main(int argc, char **argv){ - output_file = fopen("asset.log.txt", "a"); thread_ctx.log_proc = asset_log; Obj sponza_obj = load_obj(&os_process_heap, "assets/sponza/sponza.obj"_s); @@ -453,5 +27,4 @@ main(int argc, char **argv){ } dump_obj_to_file(&plane_obj, "plane.bin"_s); - fclose(output_file); } \ No newline at end of file diff --git a/build.bat b/build.bat index 54f9900..1b95a77 100644 --- a/build.bat +++ b/build.bat @@ -6,4 +6,4 @@ rem assets.exe rem tracy/TracyClient.cpp -DTRACY_ENABLE -clang main.cpp -O2 -Wall -Wno-unused-function -Wno-missing-braces -fno-exceptions -fdiagnostics-absolute-paths -g -I".." -o main.exe -Wl,user32.lib -Wl,optick\lib\x64\release\OptickCore.lib \ No newline at end of file +clang main.cpp -mavx2 -Wall -Wno-unused-function -Wno-missing-braces -fno-exceptions -fdiagnostics-absolute-paths -g -I".." -o main.exe -Wl,user32.lib -Wl,optick\lib\x64\release\OptickCore.lib \ No newline at end of file diff --git a/main.cpp b/main.cpp index bb21285..146e45f 100644 --- a/main.cpp +++ b/main.cpp @@ -89,11 +89,11 @@ #undef assert #endif + #include "multimedia.cpp" #include "profile.cpp" #include "obj.cpp" - - +#include "vec.cpp" struct Vertex { Vec3 pos; @@ -294,6 +294,7 @@ void draw_triangle_nearest(Bitmap* dst, F32 *depth_buffer, Bitmap *src, Vec3 lig Vec4 p0, Vec4 p1, Vec4 p2, Vec2 tex0, Vec2 tex1, Vec2 tex2, Vec3 norm0, Vec3 norm1, Vec3 norm2) { + if(src->pixels == 0) return; PROFILE_SCOPE(draw_triangle); F32 min_x1 = (F32)(min(p0.x, min(p1.x, p2.x))); F32 min_y1 = (F32)(min(p0.y, min(p1.y, p2.y))); @@ -429,6 +430,7 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * image = &material->texture_ambient; } } + Vertex vert[] = { { vertices[index->vertex[0] - 1], @@ -518,13 +520,16 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * F32 t = prev_dot / (prev_dot - curr_dot); in[in_count].pos = vec4(lerp(prev->pos, curr->pos, t), 1); in[in_count].tex = lerp(prev->tex, curr->tex, t); - in[in_count++].norm = lerp(prev->norm, curr->norm, t); + in[in_count].norm = lerp(prev->norm, curr->norm, t); + in_count += 1; } + if (curr_dot > 0) { in[in_count].pos = vec4(vert[j].pos, 1); in[in_count].tex = vert[j].tex; in[in_count++].norm = vert[j].norm; } + prev = curr++; prev_dot = curr_dot; } @@ -610,6 +615,8 @@ main(int argc, char **argv) { f22 = load_obj_dump(os.perm_arena, "plane.bin"_s); sponza = load_obj_dump(os.perm_arena, "sponza.bin"_s); + // Obj sponza_obj = load_obj(&os_process_heap, "assets/sponza/sponza.obj"_s); + // sponza = &sponza_obj; scene_callback(); int screen_x = 1280; @@ -654,12 +661,15 @@ main(int argc, char **argv) { } if (os.key[Key_R].down) r.camera_pos.y += speed * (F32)os.delta_time; if (os.key[Key_F].down) r.camera_pos.y -= speed * (F32)os.delta_time; + + // Clear screen and depth buffer U32* p = r.screen320.pixels; for (int y = 0; y < r.screen320.y; y++) { for (int x = 0; x < r.screen320.x; x++) { *p++ = 0x33333333; } } + F32* dp = r.depth320; for (int y = 0; y < r.screen320.y; y++) { for (int x = 0; x < r.screen320.x; x++) { @@ -667,7 +677,6 @@ main(int argc, char **argv) { } } - Mat4 camera_rotation = mat4_rotation_y(r.camera_yaw.x) * mat4_rotation_x(r.camera_yaw.y); r.camera_direction = (camera_rotation * vec4(0,0,1,1)).xyz; Vec3 target = r.camera_pos + r.camera_direction; @@ -696,6 +705,7 @@ main(int argc, char **argv) { *ptr++ = r.screen320.pixels[tx + ty * (r.screen320.x)]; } } + ui_end_frame(os.screen, &ui, &font); frame_data = string_fmt(os.frame_arena, "FPS:%f dt:%f frame:%u camera_pos: %f %f %f camera_yaw: %f %f", os.fps, os.delta_time, os.frame, r.camera_pos.x, r.camera_pos.y, r.camera_pos.z, r.camera_yaw.x, r.camera_yaw.y); diff --git a/obj.cpp b/obj.cpp index ca1d47b..f6320c3 100644 --- a/obj.cpp +++ b/obj.cpp @@ -64,8 +64,8 @@ load_obj_dump(Allocator *allocator, String filename){ Stream stream = {string.str, string.str + string.len}; Obj *obj = stream_read_struct(&stream, Obj); obj->name.str = stream_read_array(&stream, U8, obj->name.len); - obj->vertices.data = stream_read_array(&stream, Vec3, obj->vertices.len); obj->texture_coordinates.data = stream_read_array(&stream, Vec2, obj->texture_coordinates.len); + obj->vertices.data = stream_read_array(&stream, Vec3, obj->vertices.len); obj->normals.data = stream_read_array(&stream, Vec3, obj->normals.len); obj->mesh.data = stream_read_array(&stream, Obj_Mesh, obj->mesh.len); obj->materials.data = stream_read_array(&stream, Obj_Material, obj->materials.len); diff --git a/obj_dump.cpp b/obj_dump.cpp new file mode 100644 index 0000000..d983383 --- /dev/null +++ b/obj_dump.cpp @@ -0,0 +1,432 @@ +#include "multimedia.cpp" +#include "obj.cpp" + +#define STBI_ASSERT assert +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +enum class Obj_Token_Type { + none, word, number, whitespace, end +}; + +struct Obj_Token { + Obj_Token_Type type; + double number; + union { + struct { + char* s; + int len; + }; + String s8; + }; +}; + +function Bitmap +load_image(String path) { + Scratch scratch; + String file = os_read_file(scratch, path); + + int x, y, n; + unsigned char* data = stbi_load_from_memory(file.str, file.len, &x, &y, &n, 4); + Bitmap result = { (U32*)data, x, y }; + if(data) { + U32 *p = result.pixels; + for (int Y = 0; Y < y; Y++) { + for (int X = 0; X < x; X++) { + Vec4 color = vec4abgr(*p); + color.r *= color.a; + color.g *= color.a; + color.b *= color.a; + *p++ = vec4_to_u32abgr(color); + } + } + } + return result; +} + +function Obj_Token next_token_raw(char** data) { + Obj_Token result = {}; + result.s = *data; + *data += 1; + + if (is_alphabetic(*result.s)) { + result.type = Obj_Token_Type::word; + while (!is_whitespace(**data)) { + *data += 1; + } + result.len = (int)(*data - result.s); + } + else if (is_number(*result.s) || *result.s == '-') { + result.type = Obj_Token_Type::number; + while (is_number(**data) || **data == '.' || **data == 'e' || **data == '-') { + *data += 1; + } + result.number = atof(result.s); + result.len = (int)(*data - result.s); + } + else if (*result.s == '#') { + while (**data != '\n') *data += 1; + result = next_token_raw(data); + } + else if (is_whitespace(*result.s)) { + result.type = Obj_Token_Type::whitespace; + while (is_whitespace(**data)) *data += 1; + result.len = (int)(*data - result.s); + } + else if (*result.s == 0) { + result.type = Obj_Token_Type::end; + } + else if (*result.s >= '!') { + result.type = (Obj_Token_Type)*result.s; + } + + return result; +} + +function Obj_Token next_token(char** data) { + Obj_Token result; + do { + result = next_token_raw(data); + } while (result.type == Obj_Token_Type::whitespace); + return result; +} + +function double expect_number(char** data) { + Obj_Token t = next_token(data); + assert(t.type == Obj_Token_Type::number); // @Todo: Error handling, error flag + return t.number; +} + +function void expect_token(char** data, char token) { + Obj_Token t = next_token(data); + assert(t.type == (Obj_Token_Type)token); // @Todo: Error handling, error flag +} + +function B32 match_token(char **data, char token){ + char *save = *data; + Obj_Token t = next_token(&save); + if(t.type == (Obj_Token_Type)token){ + *data = save; + return true; + } + return false; +} + +function void debug_expect_raw(char** data, Obj_Token_Type type) { + char* data_temp = *data; + Obj_Token t = next_token_raw(&data_temp); + assert(t.type == type); +} + +function void +parse_mtl(Obj* obj, String path_obj_folder, String mtl_file) { + Scratch scratch; + char *data = (char *)mtl_file.str; + Obj_Material *m = 0; + + for (;;) { + Obj_Token token = next_token(&data); + if (token.type == Obj_Token_Type::end) break; + else if (token.type == Obj_Token_Type::word) { + if (string_compare(token.s8, "newmtl"_s)) { + token = next_token(&data); + m = obj->materials.push_empty_zero(); + m->name_len = clamp_top(token.len, 64); + memory_copy(m->name, token.s8.str, m->name_len); + } + + else if (string_compare(token.s8, "Ns"_s)) { + m->shininess = expect_number(&data); + } + + else if (string_compare(token.s8, "Ka"_s)) { + m->ambient_color.x = expect_number(&data); + m->ambient_color.y = expect_number(&data); + m->ambient_color.z = expect_number(&data); + } + else if (string_compare(token.s8, "Kd"_s)) { + m->diffuse_color.x = expect_number(&data); + m->diffuse_color.y = expect_number(&data); + m->diffuse_color.z = expect_number(&data); + } + + else if (string_compare(token.s8, "Ks"_s)) { + m->specular_color.x = expect_number(&data); + m->specular_color.y = expect_number(&data); + m->specular_color.z = expect_number(&data); + } + else if (string_compare(token.s8, "Ni"_s)) { + m->optical_density = expect_number(&data); + } + + else if (string_compare(token.s8, "d"_s)) { + m->non_transparency = expect_number(&data); + } + else if (string_compare(token.s8, "illum"_s)) { + m->illumination_model = (S32)expect_number(&data); + } + + else if (string_compare(token.s8, "map_Kd"_s)) { + Obj_Token t = next_token(&data); + String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); + m->texture_diffuse = load_image(path); + } + + else if (string_compare(token.s8, "map_Ka"_s)) { + Obj_Token t = next_token(&data); + String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); + m->texture_ambient = load_image(path); + } + + else if (string_compare(token.s8, "map_d"_s)) { + Obj_Token t = next_token(&data); + String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); + m->texture_dissolve = load_image(path); + } + + else if (string_compare(token.s8, "map_Disp"_s)) { + Obj_Token t = next_token(&data); + String path = string_fmt(scratch, "%Q/%Q\0", path_obj_folder, t.s8); + m->texture_displacement = load_image(path); + } + } + } +} + +function Obj +parse(Allocator *allocator, char* data, String path_obj_folder) { + Set_Allocator(allocator); + Scratch mtl_scratch; + Obj result = {}; + //result.vertices.init(allocator, 160000); + //result.texture_coordinates.init(allocator, 160000); + //result.normals.init(allocator, 160000); + //result.mesh.init(allocator, 64); + //result.materials.init(allocator, 64); + int smoothing = 0; + + Obj_Mesh *mesh = result.mesh.push_empty_zero(); + //mesh->indices.init(allocator); + int material_id = -1; + + S64 debug_i = 0; + for (;;debug_i++){ + Obj_Token token = next_token(&data); + if (token.type == Obj_Token_Type::end) break; + else if (token.type == Obj_Token_Type::word) { + if (string_compare(token.s8, "v"_s)) { + Vec3 *vertex = result.vertices.push_empty_zero(); + vertex->x = (float)expect_number(&data); + vertex->y = (float)expect_number(&data); + vertex->z = (float)expect_number(&data); + debug_expect_raw(&data, Obj_Token_Type::whitespace); + } + + else if (string_compare(token.s8, "vt"_s)) { + Vec2 *tex = result.texture_coordinates.push_empty_zero(); + tex->x = (float)expect_number(&data); + tex->y = (float)expect_number(&data); + debug_expect_raw(&data, Obj_Token_Type::whitespace); + } + + else if (string_compare(token.s8, "vn"_s)) { + Vec3 *norm = result.normals.push_empty_zero(); + norm->x = (float)expect_number(&data); + norm->y = (float)expect_number(&data); + norm->z = (float)expect_number(&data); + debug_expect_raw(&data, Obj_Token_Type::whitespace); + } + + else if (string_compare(token.s8, "mtllib"_s)) { + Obj_Token t = next_token(&data); + String path = string_fmt(mtl_scratch, "%Q/%Q", path_obj_folder, t.s8); + String mtl_file = os_read_file(mtl_scratch, path); + if(mtl_file.str) { + parse_mtl(&result, path_obj_folder, mtl_file); + } + } + + else if (string_compare(token.s8, "usemtl"_s)) { + Obj_Token t = next_token(&data); + assert(t.type == Obj_Token_Type::word); + for(U64 i = 0; i < result.materials.len; i++) { + Obj_Material *m = result.materials.data + i; + if(string_compare({(U8 *)m->name, m->name_len}, t.s8)) { + material_id = i; + break; + } + } + } + + else if (string_compare(token.s8, "o"_s)) { + Obj_Token t = next_token(&data); + assert(t.type == Obj_Token_Type::word); + if (mesh->indices.len != 0) { + mesh = result.mesh.push_empty_zero(); + } + else { + U64 len = clamp_top(t.len, 64); + memory_copy(mesh->name, t.s, len); + } + } + + else if (string_compare(token.s8, "s"_s)) { + Obj_Token t = next_token(&data); + if (t.type == Obj_Token_Type::number) { + smoothing = (int)t.number; + } + else { + assert(t.type == Obj_Token_Type::word); + if (string_compare(t.s8, "on"_s)) { + smoothing = 1; + } + else if (string_compare(t.s8, "off"_s)) { + smoothing = 0; + } + else invalid_codepath; + } + + } + + else if (string_compare(token.s8, "g"_s)) { + Obj_Token t = next_token(&data); + assert(t.type == Obj_Token_Type::word); + } + + else if (string_compare(token.s8, "f"_s)) { + Obj_Index *i = mesh->indices.push_empty_zero(); + i->smoothing_group_id = smoothing; + i->material_id = material_id; + i->vertex[0] = (int)expect_number(&data); + expect_token(&data, '/'); + i->tex[0] = (int)expect_number(&data); + if(match_token(&data, '/')) i->normal[0] = (int)expect_number(&data); + + + i->vertex[1] = (int)expect_number(&data); + expect_token(&data, '/'); + i->tex[1] = (int)expect_number(&data); + if(match_token(&data, '/')) i->normal[1] = (int)expect_number(&data); + + i->vertex[2] = (int)expect_number(&data); + expect_token(&data, '/'); + i->tex[2] = (int)expect_number(&data); + if(match_token(&data, '/')) i->normal[2] = (int)expect_number(&data); + //debug_expect_raw(&data, Obj_Token_Type::whitespace); + } + } + } + return result; +} + +function Obj +load_obj(Allocator *arena, String file) { + Scratch scratch; + String data = os_read_file(scratch, file); + assert(data.str); + + String path = string_chop_last_slash(file); + Obj result = parse(arena, (char *)data.str, path); + result.name = file; + return result; +} + +template void +dump_array(String_Builder *sb, Array *arr){ + sb->append_data(arr, sizeof(*arr)); + sb->append_data(arr->data, sizeof(T)*arr->len); +} + +function void +dump_bitmap_image(String_Builder *sb, Bitmap *bm){ + sb->append_data(bm->pixels, sizeof(U32)*bm->x*bm->y); +} + + +function B32 +_os_write_file(String file, String data, B32 append = false) { + B32 result = false; + DWORD access = GENERIC_WRITE; + DWORD creation_disposition = CREATE_ALWAYS; + if (append) { + access = FILE_APPEND_DATA; + creation_disposition = OPEN_ALWAYS; + } + + // @Todo(Krzosa): Unicode + HANDLE handle = CreateFileA((const char *)file.str, access, 0, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle != INVALID_HANDLE_VALUE) { + DWORD bytes_written = 0; + // @Todo: can only read 32 byte size files? + assert_msg(data.len == (U32)data.len, "Max data size os_write can handle is 32 bytes, data to write is larger then 32 bytes!"); + B32 error = WriteFile(handle, data.str, (U32)data.len, &bytes_written, NULL); + if (error == false) log_error("Failed to write to file: %Q", file); + else { + if (bytes_written != data.len) log_error("Failed to write to file: %Q, mismatch between length requested to write and length written", file); + else result = true; + } + CloseHandle(handle); + } + else { + log_error("File not found when trying to write: %Q", file); + } + + return result; +} + +function B32 +os_write_file2(String file, String data) { + return _os_write_file(file, data, false); +} +function B32 +os_append_file(String file, String data) { + return _os_write_file(file, data, true); +} + +function void +dump_obj_to_file(Obj *obj, String out_name){ + obj->vertices.allocator = 0; + obj->vertices.cap = obj->vertices.len; + + obj->texture_coordinates.allocator = 0; + obj->texture_coordinates.cap = obj->texture_coordinates.len; + + obj->normals.allocator = 0; + obj->normals.cap = obj->normals.len; + + obj->mesh.allocator = 0; + obj->mesh.cap = obj->mesh.len; + + obj->materials.allocator = 0; + obj->materials.cap = obj->materials.len; + + For(obj->mesh){ + it.indices.allocator = 0; + it.indices.cap = it.indices.len; + } + + Scratch arena; + String_Builder sb = string_builder_make(arena, mib(4)); + sb.append_data(obj, sizeof(Obj)); + sb.append_data(obj->name.str, obj->name.len); + sb.append_data(obj->texture_coordinates.data, obj->texture_coordinates.len*sizeof(Vec2)); + sb.append_data(obj->vertices.data, obj->vertices.len*sizeof(Vec3)); + sb.append_data(obj->normals.data, obj->normals.len*sizeof(Vec3)); + sb.append_data(obj->mesh.data, obj->mesh.len*sizeof(Obj_Mesh)); + sb.append_data(obj->materials.data, obj->materials.len*sizeof(Obj_Material)); + + For(obj->mesh){ + sb.append_data(it.indices.data, sizeof(Obj_Index)*it.indices.len); + } + + For(obj->materials){ + sb.append_data(&it, sizeof(Obj_Material)); + dump_bitmap_image(&sb, &it.texture_ambient); + dump_bitmap_image(&sb, &it.texture_diffuse); + dump_bitmap_image(&sb, &it.texture_dissolve); + dump_bitmap_image(&sb, &it.texture_displacement); + } + + String result = string_flatten(arena, &sb); + os_write_file2(out_name, result); +} diff --git a/profile.cpp b/profile.cpp index 6f966dd..3ba0a4e 100644 --- a/profile.cpp +++ b/profile.cpp @@ -5,6 +5,7 @@ enum ProfileScopeName { ProfileScopeName_draw_mesh, ProfileScopeName_draw_set_of_mesh_indices, ProfileScopeName_main_loop, + ProfileScopeName_fill_triangle_after_depth_test, ProfileScopeName_Count, }; @@ -15,6 +16,7 @@ const char *profile_scope_names[] = { "draw_mesh", "draw_set_of_mesh_indices", "main_loop", + "fill_triangle_after_depth_test", }; struct ProfileState { diff --git a/vec.cpp b/vec.cpp new file mode 100644 index 0000000..28c962b --- /dev/null +++ b/vec.cpp @@ -0,0 +1,16 @@ +#include + +union Vec8{ + __m256 simd; + F32 e[8]; + Vec4 v4[2]; +}; + + +Vec8 vec8(F32 x){return {_mm256_set1_ps(x)}; } +Vec8 vec8(F32 a, F32 b, F32 c, F32 d, F32 e, F32 f, F32 g, F32 h){ return {_mm256_set_ps(a,b,c,d,e,f,g,h)}; } +Vec8 operator+(Vec8 a, Vec8 b){ return {_mm256_add_ps(a.simd, b.simd)}; } +Vec8 operator-(Vec8 a, Vec8 b){ return {_mm256_sub_ps(a.simd, b.simd)}; } +Vec8 operator*(Vec8 a, Vec8 b){ return {_mm256_mul_ps(a.simd, b.simd)}; } +Vec8 operator/(Vec8 a, Vec8 b){ return {_mm256_div_ps(a.simd, b.simd)}; } +Vec8 operator+=(Vec8 &a, Vec8 b){ return a + b; } \ No newline at end of file