draw cube with silhouette

This commit is contained in:
Zack Buhman 2025-02-09 12:56:07 -06:00
parent b918082340
commit e053b9646f
3 changed files with 224 additions and 24 deletions

View File

@ -2,10 +2,10 @@
#include <stddef.h>
#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,
};

178
main.cpp
View File

@ -13,11 +13,20 @@
#include <SDL3/SDL.h>
#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;
}

51
model.hpp Normal file
View File

@ -0,0 +1,51 @@
#pragma once
#include <stdint.h>
#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;