A 3D game engine from scratch.
1// (c) 2020 Vlad-Stefan Harbuz <vlad@vladh.net>
2
3#include "../src_external/glad/glad.h"
4#include "shaders.hpp"
5#include "util.hpp"
6#include "logs.hpp"
7#include "debugdraw.hpp"
8#include "intrinsics.hpp"
9
10
11debugdraw::State *debugdraw::state = nullptr;
12
13
14void
15debugdraw::draw_line(v3 start_pos, v3 end_pos, v4 color)
16{
17 DebugDrawVertex vertices[2];
18 vertices[0] = { start_pos, color };
19 vertices[1] = { end_pos, color };
20 push_vertices(vertices, 2);
21}
22
23
24void
25debugdraw::draw_ray(spatial::Ray *ray, f32 length, v4 color)
26{
27 v3 end_pos = ray->origin + ray->direction * length;
28 v3 x_axis = util::get_orthogonal_vector(&ray->direction);
29 v3 z_axis = cross(ray->direction, x_axis);
30 f32 chevron_size = 0.2f;
31 v3 chevron_1_pos = end_pos + ((-ray->direction + x_axis) * chevron_size);
32 v3 chevron_2_pos = end_pos + ((-ray->direction - x_axis) * chevron_size);
33 v3 chevron_3_pos = end_pos + ((-ray->direction + z_axis) * chevron_size);
34 v3 chevron_4_pos = end_pos + ((-ray->direction - z_axis) * chevron_size);
35 draw_line(ray->origin, end_pos, color);
36 draw_line(chevron_1_pos, end_pos, color);
37 draw_line(chevron_2_pos, end_pos, color);
38 draw_line(chevron_3_pos, end_pos, color);
39 draw_line(chevron_4_pos, end_pos, color);
40}
41
42
43void
44debugdraw::draw_quad(
45 v3 p1, // clockwise: top left
46 v3 p2, // top right
47 v3 p3, // bottom right
48 v3 p4, // bottom left
49 v4 color
50) {
51 draw_line(p1, p2, color);
52 draw_line(p2, p3, color);
53 draw_line(p3, p4, color);
54 draw_line(p4, p1, color);
55}
56
57
58void
59debugdraw::draw_box(
60 v3 p1, // clockwise top face: top left
61 v3 p2, // top right
62 v3 p3, // bottom right
63 v3 p4, // top left
64 v3 p5, // clockwise bottom face: top left
65 v3 p6, // top right
66 v3 p7, // bottom right
67 v3 p8, // top left
68 v4 color
69) {
70 draw_quad(p1, p2, p3, p4, color);
71 draw_quad(p5, p6, p7, p8, color);
72 draw_quad(p1, p2, p6, p5, color);
73 draw_quad(p2, p3, p7, p6, color);
74 draw_quad(p3, p4, p8, p7, color);
75 draw_quad(p4, p1, p5, p8, color);
76}
77
78
79void
80debugdraw::draw_obb(spatial::Obb *obb, v4 color)
81{
82 v3 z_axis = cross(obb->x_axis, obb->y_axis);
83 v3 dir1 = obb->x_axis * obb->extents[0];
84 v3 dir2 = obb->y_axis * obb->extents[1];
85 v3 dir3 = z_axis * obb->extents[2];
86 v3 p1 = obb->center - dir1 + dir2 - dir3;
87 v3 p2 = obb->center + dir1 + dir2 - dir3;
88 v3 p3 = obb->center + dir1 + dir2 + dir3;
89 v3 p4 = obb->center - dir1 + dir2 + dir3;
90 v3 p5 = obb->center - dir1 - dir2 - dir3;
91 v3 p6 = obb->center + dir1 - dir2 - dir3;
92 v3 p7 = obb->center + dir1 - dir2 + dir3;
93 v3 p8 = obb->center - dir1 - dir2 + dir3;
94 draw_quad(p1, p2, p3, p4, color);
95 draw_quad(p5, p6, p7, p8, color);
96 draw_quad(p1, p2, p6, p5, color);
97 draw_quad(p2, p3, p7, p6, color);
98 draw_quad(p3, p4, p8, p7, color);
99 draw_quad(p4, p1, p5, p8, color);
100}
101
102
103void
104debugdraw::draw_point(v3 position, f32 size, v4 color)
105{
106 spatial::Obb obb = {
107 .center=position,
108 .x_axis=v3(1.0f, 0.0f, 0.0f),
109 .y_axis=v3(0.0f, 1.0f, 0.0f),
110 .extents=v3(size),
111 };
112 draw_obb(&obb, color);
113}
114
115
116void
117debugdraw::clear()
118{
119 debugdraw::state->n_vertices_pushed = 0;
120}
121
122
123void
124debugdraw::render()
125{
126 glBindVertexArray(debugdraw::state->vao);
127 glBindBuffer(GL_ARRAY_BUFFER, debugdraw::state->vbo);
128 glBufferData(GL_ARRAY_BUFFER,
129 VERTEX_SIZE * debugdraw::state->n_vertices_pushed,
130 debugdraw::state->vertices, GL_STATIC_DRAW);
131
132 glUseProgram(debugdraw::state->shader_asset.program);
133
134 glDrawArrays(GL_LINES, 0, debugdraw::state->n_vertices_pushed);
135}
136
137
138void
139debugdraw::init(debugdraw::State *debug_draw_state, memory::Pool *memory_pool)
140{
141 debugdraw::state = debug_draw_state;
142
143 memory::Pool temp_memory_pool = {};
144
145 // Shaders
146 {
147 shaders::init_shader_asset(&debugdraw::state->shader_asset,
148 &temp_memory_pool, "debugdraw", shaders::Type::standard,
149 "debugdraw.vert", "debugdraw.frag", "");
150 debugdraw::state->shader_asset.did_set_texture_uniforms = true;
151 }
152
153 // VAO
154 {
155 glGenVertexArrays(1, &debugdraw::state->vao);
156 glGenBuffers(1, &debugdraw::state->vbo);
157 glBindVertexArray(debugdraw::state->vao);
158 glBindBuffer(GL_ARRAY_BUFFER, debugdraw::state->vbo);
159 glBufferData(GL_ARRAY_BUFFER, VERTEX_SIZE * MAX_N_VERTICES, NULL, GL_DYNAMIC_DRAW);
160
161 u32 location;
162
163 // position (vec3)
164 location = 0;
165 glEnableVertexAttribArray(location);
166 glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
167 (void*)(0));
168
169 // color (vec4)
170 location = 1;
171 glEnableVertexAttribArray(location);
172 glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
173 (void*)(3 * sizeof(f32)));
174 }
175
176 memory::destroy_memory_pool(&temp_memory_pool);
177}
178
179
180void
181debugdraw::push_vertices(DebugDrawVertex vertices[], u32 n_vertices)
182{
183 if (debugdraw::state->n_vertices_pushed + n_vertices > MAX_N_VERTICES) {
184 logs::error("Pushed too many DebugDraw vertices, did you forget to call debugdraw::clear()?");
185 return;
186 }
187 range (0, n_vertices) {
188 debugdraw::state->vertices[debugdraw::state->n_vertices_pushed + idx] = vertices[idx];
189 }
190 debugdraw::state->n_vertices_pushed += n_vertices;
191}