diff --git a/cube.hpp b/cube.hpp index 0e5005b..47e64b3 100644 --- a/cube.hpp +++ b/cube.hpp @@ -2,10 +2,10 @@ #include -#include "../model.h" +#include "model.hpp" // floating-point -vertex_position cube_position[] = { +const vec3 cube_position[] = { {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, {1.0, 1.0, 1.0}, @@ -17,7 +17,7 @@ vertex_position cube_position[] = { }; // floating-point -vertex_texture cube_texture[] = { +const vec2 cube_texture[] = { {0.625, 0.5}, {0.875, 0.5}, {0.875, 0.75}, @@ -35,7 +35,7 @@ vertex_texture cube_texture[] = { }; // floating-point -vertex_normal cube_normal[] = { +const vec3 cube_normal[] = { {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, @@ -44,7 +44,7 @@ vertex_normal cube_normal[] = { {0.0, 0.0, -1.0}, }; -union quadrilateral cube_Cube_quadrilateral[] = { +const quadrilateral cube_Cube_quadrilateral[] = { { .v = { {0, 0, 0}, {4, 1, 0}, @@ -83,23 +83,22 @@ union quadrilateral cube_Cube_quadrilateral[] = { }}, }; -struct object cube_Cube = { +const object cube_Cube = { .triangle = NULL, .quadrilateral = &cube_Cube_quadrilateral[0], .triangle_count = 0, .quadrilateral_count = 6, - .material = Material, + .material = -1, }; -struct object * cube_object_list[] = { +const object * cube_object_list[] = { &cube_Cube, }; -struct model cube_model = { +model cube_model = { .position = &cube_position[0], .texture = &cube_texture[0], .normal = &cube_normal[0], .object = &cube_object_list[0], .object_count = 1, }; - diff --git a/main.cpp b/main.cpp index 445a2b7..551a12e 100644 --- a/main.cpp +++ b/main.cpp @@ -13,11 +13,20 @@ #include +#include "math/vec2.hpp" #include "math/vec3.hpp" #include "math/vec4.hpp" #include "math/mat3x3.hpp" #include "math/mat4x4.hpp" +using vec2 = vec<2, float>; +using vec3 = vec<3, float>; +using vec4 = vec<4, float>; +using mat3x3 = mat<3, 3, float>; +using mat4x4 = mat<4, 4, float>; + +#include "cube.hpp" + struct glyph { int32_t width; int32_t height; @@ -160,11 +169,6 @@ int32_t render_text(SDL_Renderer * renderer, int32_t x, int32_t y, const char * return x_advance; } -using vec3 = vec<3, float>; -using vec4 = vec<4, float>; -using mat3x3 = mat<3, 3, float>; -using mat4x4 = mat<4, 4, float>; - struct line { vec3 a; vec3 b; @@ -216,6 +220,11 @@ struct edge_normal quad[4] = { static int window_width = 1; static int window_height = 1; +static inline int max(int a, int b) +{ + return (a > b) ? a : b; +} + static inline int min(int a, int b) { return (a > b) ? b : a; @@ -287,6 +296,11 @@ static inline void render_line(SDL_Renderer * renderer, struct line line) assert(SDL_RenderLine(renderer, line.a.x, line.a.y, line.b.x, line.b.y)); } +static inline void render_line_vtx(SDL_Renderer * renderer, vec3 a, vec3 b) +{ + assert(SDL_RenderLine(renderer, a.x, a.y, b.x, b.y)); +} + void render_basis(SDL_Renderer * renderer) { // magenta: Z @@ -310,10 +324,10 @@ void render_basis(SDL_Renderer * renderer) render_text(renderer, ((x.x - 30) * 64), ((x.y + 10) * 64), "+x", 2); } -static float ltheta = 0; - -void render_quad(SDL_Renderer * renderer) +vec3 update_light(SDL_Renderer * renderer) { + static float ltheta = 0; + vec3 light_origin = {0, 0, 0}; vec3 light_pos = {1, 1, 1}; mat3x3 rot = { @@ -325,6 +339,14 @@ void render_quad(SDL_Renderer * renderer) ltheta += deg / 4; vec3 light_vec = light_origin - light_pos; + assert(SDL_SetRenderDrawColorFloat(renderer, 0, 1, 0, 1)); + render_line(renderer, transform_line({light_origin, light_pos}, 0.5f)); + + return light_vec; +} + +void _render_quad(SDL_Renderer * renderer, vec3 light_vec) +{ for (int i = 0; i < 4; i++) { float d = dot(light_vec, quad[i].normal); @@ -338,9 +360,134 @@ void render_quad(SDL_Renderer * renderer) assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 0, 1)); render_line(renderer, transform_line({origin, origin + quad[i].normal}, 0.25f)); } +} - assert(SDL_SetRenderDrawColorFloat(renderer, 0, 1, 0, 1)); - render_line(renderer, transform_line({light_origin, light_pos}, 0.5f)); +void set_edge_coloring(uint8_t * edge_coloring, + const int edge_stride, + float l_dot_n, int a, int b) +{ + bool d = l_dot_n > 0; + + int ma = min(a, b); + int mb = max(a, b); + + int bit = 1 << ((int)d); + + edge_coloring[ma * edge_stride + mb] |= bit; +} + +void render_quad(SDL_Renderer * renderer, + const vec3 * position, + const vec3 * normal, + const quadrilateral * quadrilateral, + const vec3 light_vec, + uint8_t * edge_coloring, + const int edge_stride) +{ + vec3 n = normal[quadrilateral->a.normal]; + float l_dot_n = dot(light_vec, n); + + if (l_dot_n > 0) + assert(SDL_SetRenderDrawColorFloat(renderer, 1, 1, 1, 1)); + else + assert(SDL_SetRenderDrawColorFloat(renderer, 0, 0, 1, 1)); + + float scale = 0.5f; + + set_edge_coloring(edge_coloring, + edge_stride, + l_dot_n, + quadrilateral->a.position, + quadrilateral->b.position); + set_edge_coloring(edge_coloring, + edge_stride, + l_dot_n, + quadrilateral->b.position, + quadrilateral->c.position); + set_edge_coloring(edge_coloring, + edge_stride, + l_dot_n, + quadrilateral->c.position, + quadrilateral->d.position); + set_edge_coloring(edge_coloring, + edge_stride, + l_dot_n, + quadrilateral->d.position, + quadrilateral->a.position); + + vec3 ap = position[quadrilateral->a.position]; + vec3 bp = position[quadrilateral->b.position]; + vec3 cp = position[quadrilateral->c.position]; + vec3 dp = position[quadrilateral->d.position]; + vec3 n10 = n * 0.1f; + + vec3 a = transform_vertex(ap + n10, scale); + vec3 b = transform_vertex(bp + n10, scale); + vec3 c = transform_vertex(cp + n10, scale); + vec3 d = transform_vertex(dp + n10, scale); + + render_line_vtx(renderer, a, b); + render_line_vtx(renderer, b, c); + render_line_vtx(renderer, c, d); + render_line_vtx(renderer, d, a); + + assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0, 0, 1)); + + vec3 origin = (position[quadrilateral->a.position] + + position[quadrilateral->b.position] + + position[quadrilateral->c.position] + + position[quadrilateral->d.position]) / 4.0f; + + vec3 origin_t = transform_vertex(origin, scale); + vec3 origin_n_t = transform_vertex(origin + n, scale); + render_line_vtx(renderer, origin_t, origin_n_t); +} + +void render_silhouette(SDL_Renderer * renderer, + const vec3 * position, + const uint8_t * edge_coloring, + const int edge_stride) +{ + assert(SDL_SetRenderDrawColorFloat(renderer, 1, 0.5, 0, 1)); + + for (int a = 0; a < edge_stride; a++) { + for (int b = 0; b < edge_stride; b++) { + uint8_t coloring = edge_coloring[a * edge_stride + b]; + if (coloring == 0b11) { + vec3 ap = position[a]; + vec3 bp = position[b]; + + float scale = 0.5f; + vec3 av = transform_vertex(ap, scale); + vec3 bv = transform_vertex(bp, scale); + render_line_vtx(renderer, av, bv); + } + } + } +} + +void render_cube(SDL_Renderer * renderer, const vec3 light_vec) +{ + const int edge_stride = 8; + const int edge_coloring_length = edge_stride * edge_stride; + uint8_t edge_coloring[edge_coloring_length]; + for (int i = 0; i < edge_coloring_length; i++) + edge_coloring[i] = 0; + + for (int i = 0; i < 6; i++) { + render_quad(renderer, + cube_position, + cube_normal, + &cube_Cube_quadrilateral[i], + light_vec, + edge_coloring, + edge_stride); + } + + render_silhouette(renderer, + cube_position, + edge_coloring, + edge_stride); } mat3x3 rotate_to(vec3 old_normal, vec3 new_normal) @@ -485,8 +632,8 @@ int main() assert(success == true); window = SDL_CreateWindow("sandbox", - 512, // w - 512, // h + 640, // w + 480, // h SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_MAXIMIZED); int num_drivers = SDL_GetNumRenderDrivers(); @@ -520,9 +667,11 @@ int main() bool success = SDL_GetWindowSizeInPixels(window, &window_width, &window_height); assert(success == true); + vec3 light_vec = update_light(renderer); + render_text_state(renderer); render_basis(renderer); - render_quad(renderer); + render_cube(renderer, light_vec); while (SDL_GetTicks() - ticks < (1000 / 60)) { SDL_Delay(1); } SDL_RenderPresent(renderer); @@ -548,7 +697,8 @@ int main() break; } } - update_mouse_position(); + + //update_mouse_position(); vtheta += deg / 10; } diff --git a/model.hpp b/model.hpp new file mode 100644 index 0000000..9747a94 --- /dev/null +++ b/model.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include "math/vec3.hpp" +#include "math/vec2.hpp" + +typedef struct index_ptn { + uint16_t position; + uint16_t texture; + uint16_t normal; +} index_ptn; + +typedef union triangle { + struct { + struct index_ptn a; + struct index_ptn b; + struct index_ptn c; + }; + struct index_ptn v[3]; +} triangle; + +typedef union quadrilateral { + struct { + struct index_ptn a; + struct index_ptn b; + struct index_ptn c; + struct index_ptn d; + }; + struct index_ptn v[4]; +} quadrilateral; + +using vertex_position = vec<3, float>; +using vertex_normal = vec<3, float>; +using vertex_texture = vec<2, float>; + +typedef struct object { + const union triangle * triangle; + const union quadrilateral * quadrilateral; + const int triangle_count; + const int quadrilateral_count; + const int material; +} object; + +typedef struct model { + const vertex_position * position; + const vertex_texture * texture; + const vertex_normal * normal; + const struct object ** object; + const int object_count; +} model;