Skip to content

Commit

Permalink
successfully finished implementing 3d wireframe rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
oculometric committed Mar 14, 2024
1 parent d7aa34c commit 5a4fbe8
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 132 deletions.
66 changes: 38 additions & 28 deletions src/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,37 @@ void draw_line(const nov_uvector2& start, const nov_uvector2& end, const nov_col
return;
}

/**
* delete all the buffers (if they actually exist). oh boy you better not do any silly
* stuff after we delete the buffers!
* **/
void nov_mesh::deallocate_buffers()
{
if (vertices) delete[] vertices;
vertices = 0x0;
if (triangles) delete[] triangles;
triangles = 0x0;
if (materials) delete[] materials;
materials = 0x0;
if (material_indices) delete[] material_indices;
material_indices = 0x0;
if (uvs) delete[] uvs;
uvs = 0x0;
if (vertex_normals) delete[] vertex_normals;
vertex_normals = 0x0;
// and the other data
if (normals) delete[] normals;
normals = 0x0;
if (edge_vectors) delete[] edge_vectors;
edge_vectors = 0x0;
if (edge_dots) delete[] edge_dots;
edge_dots = 0x0;
if (inv_denoms) delete[] inv_denoms;
inv_denoms = 0x0;

memory::mconsolidate();
}

/**
* recalculate stashed mesh data for rendering. this should be called whenever you've finished
* modifying the mesh data and before using it for rendering
Expand Down Expand Up @@ -247,38 +278,22 @@ bool nov_mesh::read_obj(const char* mesh_data)
|| header->vertex_buffer_length == 0
|| header->triangle_buffer_length == 0) return false;

// delete all the existing data
if (vertices) delete[] vertices; vertices = 0x0;
if (triangles) delete[] triangles; triangles = 0x0;
if (materials) delete[] materials; materials = 0x0;
if (material_indices) delete[] material_indices; material_indices = 0x0;
if (uvs) delete[] uvs; uvs = 0x0;
if (vertex_normals) delete[] vertex_normals; vertex_normals = 0x0;
// and the other data
if (normals) delete[] normals; normals = 0x0;
if (edge_vectors) delete[] edge_vectors; edge_vectors = 0x0;
if (edge_dots) delete[] edge_dots; edge_dots = 0x0;
if (inv_denoms) delete[] inv_denoms; inv_denoms = 0x0;
// delete all existing data
deallocate_buffers();

// reallocate all the buffers
vertices_count = header->vertex_buffer_length;
vertices = new nov_fvector3[vertices_count];
com_1 << stream::mode::DEC;
com_1 << "allocated space for " << vertices_count << " verts (" << (vertices_count * sizeof(nov_fvector3)) << ')' << stream::endl;
vertices_capacity = vertices_count;

triangles_count = header->triangle_buffer_length*3;
triangles = new uint16_t[triangles_count];
com_1 << "allocated space for " << triangles_count << " tris (" << (triangles_count * sizeof(uint16_t)) << ')' << stream::endl;
triangles_capacity = triangles_count;

material_indices = new uint16_t[header->triangle_buffer_length];
com_1 << "allocated space for " << header->triangle_buffer_length << " mats (" << (header->triangle_buffer_length * sizeof(uint16_t)) << ')' << stream::endl;

uvs = new nov_fvector2[triangles_count];
com_1 << "allocated space for " << triangles_count << " uvs (" << (triangles_count * sizeof(nov_fvector2)) << ')' << stream::endl;
vertex_normals = new nov_fvector3[triangles_count];
com_1 << "allocated space for " << triangles_count << " norms (" << (triangles_count * sizeof(nov_fvector3)) << ')' << stream::endl;

// TODO: materials?

Expand Down Expand Up @@ -333,6 +348,10 @@ bool nov_mesh::read_obj(const char* mesh_data)
// pump the last bit of backing data, FIXME: disabled for now since most of the data isn't needed
update_mesh_data();

com_1 << "successfully read a mesh with " << stream::mode::DEC
<< count_vertices() << " verts and "
<< count_triangles() << " tris." << stream::endl;

// we're done
return true;
}
Expand All @@ -345,16 +364,7 @@ nov_mesh::nov_mesh(const char* obj_data) { read_obj(obj_data); }

nov_mesh::~nov_mesh()
{
if (vertices) delete[] vertices; vertices = 0x0;
if (triangles) delete[] triangles; triangles = 0x0;
if (materials) delete[] materials; materials = 0x0;
if (material_indices) delete[] material_indices; material_indices = 0x0;
if (uvs) delete[] uvs; uvs = 0x0;
if (vertex_normals) delete[] vertex_normals; vertex_normals = 0x0;
if (normals) delete[] normals; normals = 0x0;
if (edge_vectors) delete[] edge_vectors; edge_vectors = 0x0;
if (edge_dots) delete[] edge_dots; edge_dots = 0x0;
if (inv_denoms) delete[] inv_denoms; inv_denoms = 0x0;
deallocate_buffers();
}

void bounds_mm_from_cr(nov_bounds& bounds)
Expand Down
3 changes: 3 additions & 0 deletions src/include/graphics/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ class nov_mesh
// bounding box of the object. never directly touch this
nov_bounds bounds;

private:
// list length data for vertices and triangles. never directly touch these
uint16_t vertices_count = 0;
uint16_t vertices_capacity = 0;
uint16_t triangles_count = 0;
uint16_t triangles_capacity = 0;

void deallocate_buffers();

public:
void update_mesh_data();
bool read_obj(const char* mesh_data);
Expand Down
76 changes: 16 additions & 60 deletions src/kernel_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ extern "C" void main(boot::nov_os_hint_table* os_hint_table)
pan_cube->camera_up_direction = nov_fvector3{0,0,1};
pan_cube->camera_look_direction = norm(nov_fvector3{ 0,-1,-1 });
pan_cube->camera_position = nov_fvector3{ 1.0f, 5.0f, -5.0f };
pan_cube->mesh = new graphics::nov_mesh(_binary_res_axes_binmesh_start);
pan_cube->mesh = new graphics::nov_mesh(_res_suzanne_binmesh_start);

gui::nov_panel_star* pan_star = new gui::nov_panel_star();
pan_star->background = nov_colour_nearblack;
Expand All @@ -110,76 +110,32 @@ extern "C" void main(boot::nov_os_hint_table* os_hint_table)
root->child_a->child_b->child_b->panel = pan_text;
root->child_a->child_b->child_a->panel = pan_mem;
root->child_b->panel = pan_star;

man.draw_root();
memory::memcpy((uint32_t*)backbuffer, (uint32_t*)real_buffer, 640*120*3);

/*
nov_fvector3 test = {0.1f, 0.7f, -0.8f};
while (true)
{
test.x -= 0.06;
test.y -= 0.04;
test.z += 0.01;
com_1 << test << endl;
com_1 << mag(test) << endl;
com_1 << mag_sq(test) << endl;
com_1 << norm(test) << endl;
com_1 << mag_sq(norm(test)) << endl << endl;
}
*/

pan_cube->camera_up_direction = nov_fvector3{0,0,1};
float z_rot = 0.0f;
bool monkey = true;
while (true)
{
pan_cube->camera_up_direction = nov_fvector3{0,0,1};//norm(nov_fvector3{ sinf(z_rot), cosf(z_rot),0 });
pan_cube->camera_look_direction = norm(nov_fvector3{cosf(z_rot),-sinf(z_rot),0});
pan_cube->camera_position = nov_fvector3{-5,0,0};//pan_cube->camera_look_direction * -8.0f;
pan_cube->camera_look_direction = norm(nov_fvector3{-sinf(z_rot+MATH_PI),cosf(z_rot+MATH_PI),-0.3f});
pan_cube->camera_position = pan_cube->camera_look_direction * -6.0f;

com_1 << z_rot * 10.0f << endl;
com_1 << sqrt(z_rot * 10.0f) << endl;

man.draw_root();
man.draw_specific(root->child_a->child_a);
memory::memcpy((uint32_t*)backbuffer, (uint32_t*)real_buffer, 640*120*3);

z_rot += 0.01f;
if (z_rot > MATH_PI * 2.0f) z_rot = 0.0f;
z_rot += 0.015f;
if (z_rot > MATH_PI * 2.0f)
{
z_rot = 0.0f;
if (monkey) pan_cube->mesh->read_obj(_res_teapot_binmesh_start);
else pan_cube->mesh->read_obj(_res_suzanne_binmesh_start);
monkey = !monkey;
man.draw_root();
}
}


// man.draw_root();
// memory::memcpy((uint32_t*)backbuffer, (uint32_t*)real_buffer, 640*120*3);

// pan_cube->line_colour = nov_colour_carmine;
// pan_cube->mesh->read_obj(_binary_res_suzanne_binmesh_start);

// int i = 0;
// bool monkey = true;
// while(true)
// {
// man.draw_root();
// memory::memcpy((uint32_t*)backbuffer, (uint32_t*)real_buffer, 640*120*3);
// // pan_cube->camera_rotation.z += 0.01f;

// i++;
// if (i == 100)
// {
// com_1 << "100 frames drawn" << endl;
// i = 0;
// if (monkey)
// {
// pan_cube->line_colour = nov_colour_indigo;
// pan_cube->mesh->read_obj(_binary_res_axes_binmesh_start);
// }
// else
// {
// pan_cube->line_colour = nov_colour_carmine;
// pan_cube->mesh->read_obj(_binary_res_suzanne_binmesh_start);
// }
// monkey = !monkey;
// }
// }

com_1 << "all done." << endl;
com_1.flush();

Expand Down
73 changes: 29 additions & 44 deletions src/panel_graphicsdemos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,27 @@ void gui::nov_panel_meshrender::_draw draw_function_stub

if (!meshrender_panel->mesh) return;

// TODO: 3D rotation

vector::nov_fvector3 look = norm(meshrender_panel->camera_look_direction);
vector::nov_fvector3 up = norm(meshrender_panel->camera_up_direction);

float tmp = look.x;
look.x = look.y;
look.y = tmp;

tmp = up.x;
up.x = up.y;
up.y = tmp;

// this represents the x-axis vector of the camera
const vector::nov_fvector3 camera_right = norm(norm(meshrender_panel->camera_look_direction) % norm(meshrender_panel->camera_up_direction));
com_1 << "right: " << camera_right << stream::endl;
const vector::nov_fvector3 camera_right = norm(look % up);
// this represents the y-axis vector of the camera
const vector::nov_fvector3 camera_up = camera_right % norm(meshrender_panel->camera_look_direction);
com_1 << "up: " << camera_up << stream::endl;
const vector::nov_fvector3 camera_up = camera_right % look;
// this represents the z-axis vector of the camera
const vector::nov_fvector3 camera_back = -norm(meshrender_panel->camera_look_direction);
com_1 << "back: " << camera_back << stream::endl;
const vector::nov_fvector3 camera_back = -look;

// this represents the offset of the camera from the origin
const vector::nov_fvector3 camera_position = meshrender_panel->camera_position;
com_1 << "position: " << camera_position << stream::endl;
// FIXME: this ugh

// the world to camera transform is the inverse of the transform that takes the camera from its 'origin' state to its world position
// so a matrix which represents the camera's transformation (position, rotation), the inverse needs to be applied to world-space stuff
// to transform it into camera-space stuff
Expand All @@ -35,44 +40,23 @@ void gui::nov_panel_meshrender::_draw draw_function_stub
// therefore their inverses represent the transformation of a point located relative to the camera
// i.e. multiplying by the inverse represents transforming the camera, and everything in the scene, such
// that the camera is located at the origin and is facing along its normal axes (i.e. no rotation or offset)
const matrix::nov_fmatrix4 camera_position_mat{ 1.0f, 0.0f, 0.0f, camera_position.x,
0.0f, 1.0f, 0.0f, -camera_position.y, // negative?
0.0f, 0.0f, 1.0f, camera_position.z,
0.0f, 0.0f, 0.0f, 1.0f, };
const matrix::nov_fmatrix4 camera_position_mat{ 1.0f, 0.0f, 0.0f, camera_position.y,
0.0f, 1.0f, 0.0f, -camera_position.x,
0.0f, 0.0f, 1.0f, camera_position.z,
0.0f, 0.0f, 0.0f, 1.0f, };

const matrix::nov_fmatrix4 camera_rotation_mat{ camera_right.x, -camera_right.y, camera_right.z, 0.0f,
-camera_up.x, camera_up.y, -camera_up.z, 0.0f,
camera_back.x, -camera_back.y, camera_back.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
const matrix::nov_fmatrix4 camera_rotation_mat{ camera_right.x, -camera_up.x, camera_back.x, 0.0f,
-camera_right.y, camera_up.y, -camera_back.y, 0.0f,
camera_right.z, -camera_up.z, camera_back.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };

// apply the position first, then the rotation (flipped since inversing the matrices effectively flips the order of transformations)
const matrix::nov_fmatrix4 world_to_camera = ~(camera_position_mat * camera_rotation_mat);
com_1 << world_to_camera << stream::endl;

com_1 << "camera position in camera space: " << (world_to_camera * nov_fvector4{camera_position}) << stream::endl;
com_1 << "camera forward in camera space: " << (world_to_camera * nov_fvector4{camera_back}) << stream::endl;
// FIXME: AHA!
// const vector::nov_fvector3 euler = meshrender_panel->camera_rotation;
// const matrix::nov_fmatrix4 rotate_camera_x{ 1.0f, 0.0f, 0.0f, 0.0f,
// 0.0f, cosf(euler.x), -sinf(euler.x), 0.0f,
// 0.0f, sinf(euler.x), cosf(euler.x), 0.0f,
// 0.0f, 0.0f, 0.0f, 1.0f };

// const matrix::nov_fmatrix4 rotate_camera_y{ cosf(euler.y), 0.0f, sinf(euler.y), 0.0f,
// 0.0f, 1.0f, 0.0f, 0.0f,
// -sinf(euler.y), 0.0f, cosf(euler.x), 0.0f,
// 0.0f, 0.0f, 0.0f, 1.0f };

// const matrix::nov_fmatrix4 rotate_camera_z{ cosf(euler.z), -sinf(euler.z), 0.0f, 0.0f,
// sinf(euler.z), cosf(euler.z), 0.0f, 0.0f,
// 0.0f, 0.0f, 1.0f, 0.0f,
// 0.0f, 0.0f, 0.0f, 1.0f };

// const matrix::nov_fmatrix4 rotate_camera = rotate_camera_x * rotate_camera_y * rotate_camera_z;

const float far_clip = 100.0f;
const float near_clip = 0.001f;
const float clip_rat = -far_clip / (far_clip - near_clip);
const float fov_deg = 85.0f;
const float fov_deg = 75.0f;
const float s = 1.0f / tanf((fov_deg / 2.0f) * (MATH_PI / 180.0f));

const matrix::nov_fmatrix4 camera_to_view{ s, 0.0f, 0.0f, 0.0f,
Expand All @@ -94,12 +78,13 @@ void gui::nov_panel_meshrender::_draw draw_function_stub
for (uint32_t i = 0; i < meshrender_panel->mesh->count_vertices(); i++)
{
transformed_vertex_buffer[i] = world_to_view * nov_fvector4{ meshrender_panel->mesh->vertices[i] };
transformed_vertex_buffer[i] /= transformed_vertex_buffer[i].w;
float tmp_z = transformed_vertex_buffer[i].w;
transformed_vertex_buffer[i] /= tmp_z;
transformed_vertex_buffer[i].z = tmp_z;
}

for (uint32_t i = 0; i < (meshrender_panel->mesh->count_triangles() * 3) - 2; i++)
for (uint32_t i = 0; i < ((uint32_t)meshrender_panel->mesh->count_triangles() * 3) - 2; i++)
{
if ((meshrender_panel->mesh->normals[i/3] ^ camera_back) < -0.5f) { i += 2; continue; }
if (i % 3 <= 1)
{
v_a_view = transformed_vertex_buffer[meshrender_panel->mesh->triangles[i]];
Expand Down

0 comments on commit 5a4fbe8

Please sign in to comment.