From 5a4fbe8e517078ac19c65dce38a6e5f1ac3c7a11 Mon Sep 17 00:00:00 2001 From: oculometric Date: Thu, 14 Mar 2024 18:21:15 +0000 Subject: [PATCH] successfully finished implementing 3d wireframe rendering --- src/graphics.cpp | 66 ++++++++++++++++++-------------- src/include/graphics/mesh.h | 3 ++ src/kernel_main.cpp | 76 ++++++++----------------------------- src/panel_graphicsdemos.cpp | 73 ++++++++++++++--------------------- 4 files changed, 86 insertions(+), 132 deletions(-) diff --git a/src/graphics.cpp b/src/graphics.cpp index 903879f..e6d061c 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -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 @@ -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? @@ -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; } @@ -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) diff --git a/src/include/graphics/mesh.h b/src/include/graphics/mesh.h index e19e1bc..07e9657 100644 --- a/src/include/graphics/mesh.h +++ b/src/include/graphics/mesh.h @@ -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); diff --git a/src/kernel_main.cpp b/src/kernel_main.cpp index 5d04c52..0a7ab6d 100644 --- a/src/kernel_main.cpp +++ b/src/kernel_main.cpp @@ -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; @@ -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(); diff --git a/src/panel_graphicsdemos.cpp b/src/panel_graphicsdemos.cpp index 6047e0b..5c758ca 100644 --- a/src/panel_graphicsdemos.cpp +++ b/src/panel_graphicsdemos.cpp @@ -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 @@ -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, @@ -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]];