diff --git a/obj_parser.cpp b/assets.cpp similarity index 83% rename from obj_parser.cpp rename to assets.cpp index 6cdb9b2..f10afa6 100644 --- a/obj_parser.cpp +++ b/assets.cpp @@ -1,46 +1,10 @@ -/// -/// [ ] - Cache bitmaps -/// [ ] - Fix potential portability issues due to compiler struct alignment differences etc. -/// +#include "multimedia.cpp" +#include "obj.cpp" -struct Obj_Index { - int vertex[3]; - int tex[3]; - int normal[3]; - S32 material_id; - S32 smoothing_group_id; -}; +#define STBI_ASSERT assert +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" -struct Obj_Mesh { - char name[64]; - Array indices; -}; - -struct Obj_Material { - char name[64]; - U32 name_len; - Bitmap texture_ambient; // map_Ka - Bitmap texture_diffuse; // map_Kd - Bitmap texture_dissolve; // map_d - Bitmap texture_displacement; // map_Disp - F32 non_transparency; // d - F32 transparency; // Tr - F32 optical_density; // Ni - F32 shininess; // Ns - S32 illumination_model; // illum - Vec3 ambient_color; // Ka - Vec3 diffuse_color; // Kd - Vec3 specular_color; // Ks -}; - -struct Obj { - String name; - Array vertices; - Array texture_coordinates; - Array normals; - Array mesh; - Array materials; -}; enum class Obj_Token_Type { none, word, number, whitespace, end @@ -413,23 +377,8 @@ os_append_file(String file, String data) { return _os_write_file(file, data, true); } -struct Stream{ - U8 *cursor; - U8 *end; -}; - -#define stream_read_array(s,T,c) (T *)stream_read(s,sizeof(T)*(c)) -#define stream_read_struct(s,T) stream_read_array(s,T,1) -function void * -stream_read(Stream *s, SizeU size){ - U8 *result = s->cursor; - s->cursor += size; - assert(s->end >= s->cursor); - return result; -} - function void -dump_obj_to_file(Obj *obj){ +dump_obj_to_file(Obj *obj, String out_name){ obj->vertices.allocator = 0; obj->vertices.cap = obj->vertices.len; @@ -473,33 +422,27 @@ dump_obj_to_file(Obj *obj){ } String result = string_flatten(arena, &sb); - os_write_file("sponza.bin"_s, result); + os_write_file(out_name, result); } -function Obj * -load_obj_dump(Allocator *allocator, String filename){ - String string = os_read_file(allocator, filename); +int +main(int argc, char **argv){ + Obj sponza_obj = load_obj(&os_process_heap, "assets/sponza/sponza.obj"_s); + dump_obj_to_file(&sponza_obj, "sponza.bin"_s); - Obj *obj = (Obj *)string.str; - Stream stream = {(U8 *)(obj+1), string.str + string.len}; - 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->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); + Obj plane_obj = load_obj(&pernament_arena, "assets/f22.obj"_s); - Iter(obj->mesh){ - it->indices.data = stream_read_array(&stream, Obj_Index, it->indices.len); + // Add brick texture as main texture + Scratch scratch; + Set_Allocator(scratch); + Obj_Material material = {}; + material.texture_ambient = load_image("assets/bricksx64.png"_s); + plane_obj.materials.add(material); + For(plane_obj.mesh){ + IFor(it->indices, jt, j){ + jt->material_id = 0; + } } - Iter(obj->materials){ - it->texture_ambient.pixels = stream_read_array(&stream, U32, it->texture_ambient.x*it->texture_ambient.y); - it->texture_diffuse.pixels = stream_read_array(&stream, U32, it->texture_diffuse.x*it->texture_diffuse.y); - it->texture_dissolve.pixels = stream_read_array(&stream, U32, it->texture_dissolve.x*it->texture_dissolve.y); - it->texture_displacement.pixels = stream_read_array(&stream, U32, it->texture_displacement.x*it->texture_displacement.y); - } - - return obj; -} - + dump_obj_to_file(&plane_obj, "plane.bin"_s); +} \ No newline at end of file diff --git a/build.bat b/build.bat index f3141cf..45ca401 100644 --- a/build.bat +++ b/build.bat @@ -1,4 +1,8 @@ @echo off +rem clang assets.cpp -Wall -Wno-unused-function -Wno-missing-braces -fno-exceptions -fdiagnostics-absolute-paths -g -I".." -o assets.exe -Wl,user32.lib + +rem assets.exe + clang main.cpp -Wall -Wno-unused-function -Wno-missing-braces -fno-exceptions -fdiagnostics-absolute-paths -g -I".." -o main.exe -Wl,user32.lib \ No newline at end of file diff --git a/main.cpp b/main.cpp index 3ab79a0..916cc2e 100644 --- a/main.cpp +++ b/main.cpp @@ -81,13 +81,14 @@ /// ### Urgent: /// /// - [ ] Simplify the code, especially for the 2d routines -/// - [ ] Asset processor as second program +/// - [x] Asset processor as second program /// /// #define PREMULTIPLIED_ALPHA_BLENDING 1 #include "multimedia.cpp" #include "profile.cpp" +#include "obj.cpp" struct Vertex { Vec3 pos; @@ -112,11 +113,6 @@ struct Render { F32 *depth320; }; -#define STBI_ASSERT assert -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#include "obj_parser.cpp" - enum Scene { Scene_F22, Scene_Sponza, @@ -213,13 +209,8 @@ void draw_bitmap(Bitmap* dst, Bitmap* src, Vec2 pos, Vec2 size=vec2(F32MAX, F32M S64 maxy = miny + (S64)(size.y + 0.5f); S64 offsetx = 0; S64 offsety = 0; - - if (maxx > dst->x) { - maxx = dst->x; - } - if (maxy > dst->y) { - maxy = dst->y; - } + maxx = clamp_top(maxx, (S64)dst->x); + maxy = clamp_top(maxy, (S64)dst->y); if (minx < 0) { offsetx = -minx; minx = 0; @@ -228,6 +219,7 @@ void draw_bitmap(Bitmap* dst, Bitmap* src, Vec2 pos, Vec2 size=vec2(F32MAX, F32M offsety = -miny; miny = 0; } + F32 distx = (F32)(maxx - minx); F32 disty = (F32)(maxy - miny); for (S64 y = miny; y < maxy; y++) { @@ -247,7 +239,6 @@ void draw_bitmap(Bitmap* dst, Bitmap* src, Vec2 pos, Vec2 size=vec2(F32MAX, F32M } } } - } function @@ -396,8 +387,6 @@ void draw_triangle_nearest(Bitmap* dst, F32 *depth_buffer, Bitmap *src, Vec3 lig } - - result_color = premultiplied_alpha(dst_color, result_color); result_color = almost_linear_to_srgb(result_color); U32 color32 = vec4_to_u32abgr(result_color); @@ -422,17 +411,19 @@ void draw_triangle_nearest(Bitmap* dst, F32 *depth_buffer, Bitmap *src, Vec3 lig } function -void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, F32 light, +void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, Vec3 light_direction, Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { + Vec2 tex0, Vec2 tex1, Vec2 tex2, + Vec3 norm0, Vec3 norm1, Vec3 norm2) { F32 min_x1 = (F32)(min(p0.x, min(p1.x, p2.x))); F32 min_y1 = (F32)(min(p0.y, min(p1.y, p2.y))); F32 max_x1 = (F32)(max(p0.x, max(p1.x, p2.x))); F32 max_y1 = (F32)(max(p0.y, max(p1.y, p2.y))); - S64 min_x = (S64)max(0.f, floor(min_x1)); - S64 min_y = (S64)max(0.f, floor(min_y1)); - S64 max_x = (S64)min((F32)dst->x, ceil(max_x1)); - S64 max_y = (S64)min((F32)dst->y, ceil(max_y1)); + + S64 min_x = (S64)clamp_bot(0.f, floor(min_x1)); + S64 min_y = (S64)clamp_bot(0.f, floor(min_y1)); + S64 max_x = (S64)clamp_top((F32)dst->x, ceil(max_x1)); + S64 max_y = (S64)clamp_top((F32)dst->y, ceil(max_y1)); F32 area = edge_function(p0, p1, p2); for (S64 y = min_y; y < max_y; y++) { @@ -441,7 +432,6 @@ void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, F32 lig F32 edge1 = edge_function(p1, p2, { (F32)x,(F32)y }); F32 edge2 = edge_function(p2, p0, { (F32)x,(F32)y }); - if (edge0 >= 0 && edge1 >= 0 && edge2 >= 0) { F32 w1 = edge1 / area; F32 w2 = edge2 / area; @@ -450,6 +440,7 @@ void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, F32 lig F32 u = tex0.x * (w1 / p0.w) + tex1.x * (w2 / p1.w) + tex2.x * (w3 / p2.w); F32 v = tex0.y * (w1 / p0.w) + tex1.y * (w2 / p1.w) + tex2.y * (w3 / p2.w); + u /= interpolated_w; v /= interpolated_w; // @Note: We could do: interpolated_w = 1.f / interpolated_w to get proper depth @@ -478,9 +469,12 @@ void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, F32 lig Vec4 blendx1 = lerp(pixelx1y1, pixelx2y1, udiff); Vec4 blendx2 = lerp(pixelx1y2, pixelx2y2, udiff); Vec4 result_color = lerp(blendx1, blendx2, vdiff); + +#if 0 result_color.r *= light; result_color.g *= light; result_color.b *= light; +#endif #if PREMULTIPLIED_ALPHA_BLENDING Vec4 dst_color = vec4abgr(*dst_pixel); dst_color = srgb_to_almost_linear(dst_color); @@ -496,27 +490,6 @@ void draw_triangle_bilinear(Bitmap* dst, F32 *depth_buffer, Bitmap *src, F32 lig } } -function -void scatter_plot(Bitmap *dst, F64 *data, S64 data_len) { - F64 min = F32MAX; - F64 max = F32MIN; - F64 step = dst->x / (F64)data_len; - for (U32 i = 0; i < data_len; i++) { - if (min > data[i]) min = data[i]; - if (max < data[i]) max = data[i]; - } - F64 diff = max - min; - F64 x = 0; - for (U32 i = 0; i < data_len; i++) { - F64 *p = data + i; - *p /= diff; - F64 y = *p * dst->y; - x += step; - draw_rect(dst, (F32)x-2, (F32)y-2, 4, 4, vec4(1,0,0,1)); - //dst->pixels[xi + yi * dst->x] = 0xffff0000; - } -} - function void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh *mesh, Vec3 *vertices, Vec2 *tex_coords, Vec3 *normals) { for (int i = 0; i < mesh->indices.len; i++) { @@ -530,7 +503,6 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * image = &material->texture_ambient; } } - Vertex vert[] = { { vertices[index->vertex[0] - 1], @@ -648,12 +620,12 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * in[j].pos.y += r->screen320.y / 2; } + draw_triangle_nearest(&r->screen320, r->depth320, image, light_direction, in[0].pos, in[1].pos, in[2].pos, in[0].tex, in[1].tex, in[2].tex, in[0].norm, in[1].norm, in[2].norm); if (in_count > 3) { draw_triangle_nearest(&r->screen320, r->depth320, image, light_direction, in[0].pos, in[2].pos, in[3].pos, in[0].tex, in[2].tex, in[3].tex, in[0].norm, in[2].norm, in[3].norm); } - #if 0 ProfileScope *scope = profile_scopes + ProfileScopeName_draw_triangle; LOCAL_PERSIST B32 profile_flag; @@ -662,7 +634,6 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * save_profile_data(scope, scene_name, LIT("draw_triangle")); } #endif - } } } @@ -670,7 +641,7 @@ void draw_mesh(Render *r, String scene_name, Obj_Material *materials, Obj_Mesh * #include "ui.cpp" global F32 speed = 100.f; global F32 rotation = 0; -global Obj f22; +global Obj *f22; global Obj *sponza; global Obj *obj; global Render r = {}; @@ -682,7 +653,7 @@ UI_SIGNAL_CALLBACK(scene_callback) { case Scene_F22: { speed = 1; r.camera_pos = vec3(0,0,-2); - obj = &f22; + obj = f22; } break; case Scene_Sponza: { speed = 100; @@ -706,12 +677,9 @@ int main(int argc, char **argv) { os.window_size.y = 180*2; os.window_resizable = 1; assert(os_init()); - Font font = os_load_font(os.perm_arena, 24, "Arial", 0); + Font font = os_load_font(os.perm_arena, 72, "Arial", 0); - f22 = load_obj(&os_process_heap, "assets/f22.obj"_s); - //Obj sponza_obj = load_obj(&os_process_heap, "assets/sponza/sponza.obj"_s); - //sponza = &sponza_obj; - //dump_obj_to_file(sponza); + f22 = load_obj_dump(os.perm_arena, "plane.bin"_s); sponza = load_obj_dump(os.perm_arena, "sponza.bin"_s); scene_callback(); @@ -722,7 +690,7 @@ int main(int argc, char **argv) { r.screen320 = {(U32 *)arena_push_size(os.perm_arena, screen_x*screen_y*sizeof(U32)), screen_x, screen_y}; r.plot = {(U32 *)arena_push_size(os.perm_arena, 1280*720*sizeof(U32)), 1280, 720}; r.depth320 = (F32 *)arena_push_size(os.perm_arena, sizeof(F32) * screen_x * screen_y); - r.img = load_image("assets/bricksx64.png"_s); + //r.img = load_image(""_s); String frame_data = {}; diff --git a/obj.cpp b/obj.cpp new file mode 100644 index 0000000..8870ff4 --- /dev/null +++ b/obj.cpp @@ -0,0 +1,86 @@ +/// +/// [?] - Cache bitmaps +/// [ ] - Fix potential portability issues due to compiler struct alignment differences etc. +/// + +struct Obj_Index { + int vertex[3]; + int tex[3]; + int normal[3]; + S32 material_id; + S32 smoothing_group_id; +}; + +struct Obj_Mesh { + char name[64]; + Array indices; +}; + +struct Obj_Material { + char name[64]; + U32 name_len; + Bitmap texture_ambient; // map_Ka + Bitmap texture_diffuse; // map_Kd + Bitmap texture_dissolve; // map_d + Bitmap texture_displacement; // map_Disp + F32 non_transparency; // d + F32 transparency; // Tr + F32 optical_density; // Ni + F32 shininess; // Ns + S32 illumination_model; // illum + Vec3 ambient_color; // Ka + Vec3 diffuse_color; // Kd + Vec3 specular_color; // Ks +}; + +struct Obj { + String name; + Array vertices; + Array texture_coordinates; + Array normals; + Array mesh; + Array materials; +}; + +struct Stream{ + U8 *cursor; + U8 *end; +}; + +#define stream_read_array(s,T,c) (T *)stream_read(s,sizeof(T)*(c)) +#define stream_read_struct(s,T) stream_read_array(s,T,1) +function void * +stream_read(Stream *s, SizeU size){ + U8 *result = s->cursor; + s->cursor += size; + assert(s->end >= s->cursor); + return result; +} + +function Obj * +load_obj_dump(Allocator *allocator, String filename){ + String string = os_read_file(allocator, filename); + + Obj *obj = (Obj *)string.str; + Stream stream = {(U8 *)(obj+1), string.str + string.len}; + 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->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); + + Iter(obj->mesh){ + it->indices.data = stream_read_array(&stream, Obj_Index, it->indices.len); + } + + Iter(obj->materials){ + it->texture_ambient.pixels = stream_read_array(&stream, U32, it->texture_ambient.x*it->texture_ambient.y); + it->texture_diffuse.pixels = stream_read_array(&stream, U32, it->texture_diffuse.x*it->texture_diffuse.y); + it->texture_dissolve.pixels = stream_read_array(&stream, U32, it->texture_dissolve.x*it->texture_dissolve.y); + it->texture_displacement.pixels = stream_read_array(&stream, U32, it->texture_displacement.x*it->texture_displacement.y); + } + + return obj; +} +