From c0279758497088bef49905eed18370ff0dcd06fa Mon Sep 17 00:00:00 2001 From: T1ti <40864460+T1ti@users.noreply.github.com> Date: Tue, 1 Oct 2024 06:04:46 +0200 Subject: [PATCH] Enable fake geometry and box rendering for m2 particle emitters without mesh as they currently don't render Make m2 header temporary to save memory, only save useful data --- src/noggit/Model.cpp | 57 ++++++++++++++++++---------- src/noggit/Model.h | 31 ++++++++++++--- src/noggit/ModelHeaders.h | 4 +- src/noggit/ModelInstance.cpp | 28 +++++++------- src/noggit/rendering/ModelRender.cpp | 12 ++++-- src/noggit/rendering/WorldRender.cpp | 18 +++------ 6 files changed, 92 insertions(+), 58 deletions(-) diff --git a/src/noggit/Model.cpp b/src/noggit/Model.cpp index b3694e23..e9642b40 100755 --- a/src/noggit/Model.cpp +++ b/src/noggit/Model.cpp @@ -27,7 +27,7 @@ Model::Model(const std::string& filename, Noggit::NoggitRenderContext context) , _context(context) , _renderer(this) { - memset(&header, 0, sizeof(ModelHeader)); + // memset(&header, 0, sizeof(ModelHeader)); } void Model::finishLoading() @@ -41,6 +41,8 @@ void Model::finishLoading() throw std::runtime_error("Error loading file \"" + _file_key.stringRepr() + "\". Aborting to load model."); } + ModelHeader header; + memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); @@ -84,12 +86,21 @@ void Model::finishLoading() blend_override = M2Array(f, ofs_blend_override, n_blend_override); } - animated = isAnimated(f); // isAnimated will set animGeometry and animTextures + animated = isAnimated(f, header); // isAnimated will set animGeometry and animTextures trans = 1.0f; _current_anim_seq = 0; - rad = header.bounding_box_radius; + bounding_box_min = header.bounding_box_min; + bounding_box_max = header.bounding_box_max; + bounding_box_radius = header.bounding_box_radius; + + collision_box_min = header.collision_box_min; + collision_box_max = header.collision_box_max; + collision_box_radius = header.collision_box_radius; + + Flags = header.Flags; + if (header.nGlobalSequences) { @@ -97,15 +108,21 @@ void Model::finishLoading() } //! \todo This takes a biiiiiit long. Have a look at this. - initCommon(f); + initCommon(f, header); if (animated) { - initAnimated(f); + initAnimated(f, header); } f.close(); + // add fake geometry for selection + if (_renderer.renderPasses().empty() || particles_only() /* || this->file_key().filepath() == "world/generic/passivedoodads/particleemitters/ashenvalewisps.m2"*/) + { + _fake_geometry.emplace(this); + } + finished = true; _state_changed.notify_all(); } @@ -124,7 +141,7 @@ void Model::waitForChildrenLoaded() } -bool Model::isAnimated(const BlizzardArchive::ClientFile& f) +bool Model::isAnimated(const BlizzardArchive::ClientFile& f, ModelHeader& header) { // see if we have any animated bones ModelBoneDef const* bo = reinterpret_cast(f.getBuffer() + header.ofsBones); @@ -226,7 +243,7 @@ namespace } -void Model::initCommon(const BlizzardArchive::ClientFile& f) +void Model::initCommon(const BlizzardArchive::ClientFile& f, ModelHeader& header) { // vertices, normals, texcoords _vertices = M2Array(f, header.ofsVertices, header.nVertices); @@ -237,6 +254,12 @@ void Model::initCommon(const BlizzardArchive::ClientFile& f) v.normal = fixCoordSystem(v.normal); } + nBoundingTriangles = header.nBoundingTriangles; + // Optional, load collision + // collision_indices = M2Array(f, header.ofsBoundingTriangles, header.nBoundingTriangles); + // collision_vertices = M2Array(f, header.ofsBoundingVertices, header.nBoundingVertices); + // collision_normals = M2Array(f, header.ofsBoundingNormals, header.nBoundingNormals); + // textures ModelTextureDef const* texdef = reinterpret_cast(f.getBuffer() + header.ofsTextures); _textureFilenames.resize(header.nTextures); @@ -346,19 +369,13 @@ void Model::initCommon(const BlizzardArchive::ClientFile& f) _renderer.initRenderPasses(view, texture_unit, model_geosets); g.close(); - - // add fake geometry for selection - if (_renderer.renderPasses().empty()) - { - _fake_geometry.emplace(this); - } } } FakeGeometry::FakeGeometry(Model* m) { - glm::vec3 min = m->header.bounding_box_min, max = m->header.bounding_box_max; + glm::vec3 min = m->bounding_box_min, max = m->bounding_box_max; vertices.emplace_back(min.x, max.y, min.z); vertices.emplace_back(min.x, max.y, max.z); @@ -382,7 +399,7 @@ FakeGeometry::FakeGeometry(Model* m) } -void Model::initAnimated(const BlizzardArchive::ClientFile& f) +void Model::initAnimated(const BlizzardArchive::ClientFile& f, ModelHeader& header) { std::vector> animation_files; @@ -480,12 +497,12 @@ void Model::calcBones(glm::mat4x4 const& model_view , int animation_time ) { - for (size_t i = 0; i= 0) { @@ -842,12 +859,12 @@ std::vector>> Model::intersect (glm:: void Model::lightsOn(OpenGL::light lbase) { // setup lights - for (unsigned int i=0, l=lbase; i bones; std::vector bone_matrices; - ModelHeader header; + // ModelHeader header; // we really don't need to store the offsets. std::vector blend_override; - float rad; + glm::vec3 bounding_box_min; + glm::vec3 bounding_box_max; + float bounding_box_radius; + + glm::vec3 collision_box_min; + glm::vec3 collision_box_max; + float collision_box_radius; + + uint32_t Flags; + float trans; bool animcalc; @@ -228,6 +244,11 @@ public: std::optional _fake_geometry; + uint32_t nBoundingTriangles; + // std::vector collision_indices; + // std::vector collision_vertices; + // std::vector collision_normals; + private: bool _per_instance_animation; int _current_anim_seq; @@ -236,9 +257,9 @@ private: Noggit::NoggitRenderContext _context; - void initCommon(const BlizzardArchive::ClientFile& f); - bool isAnimated(const BlizzardArchive::ClientFile& f); - void initAnimated(const BlizzardArchive::ClientFile& f); + void initCommon(const BlizzardArchive::ClientFile& f, ModelHeader& header); + bool isAnimated(const BlizzardArchive::ClientFile& f, ModelHeader& header); + void initAnimated(const BlizzardArchive::ClientFile& f, ModelHeader& header); void animate(glm::mat4x4 const& model_view, int anim_id, int anim_time); void calcBones(glm::mat4x4 const& model_view, int anim, int time, int animation_time); diff --git a/src/noggit/ModelHeaders.h b/src/noggit/ModelHeaders.h index b9507e25..8f2be807 100755 --- a/src/noggit/ModelHeaders.h +++ b/src/noggit/ModelHeaders.h @@ -75,11 +75,11 @@ struct ModelHeader { glm::vec3 collision_box_max; float collision_box_radius; - uint32_t nBoundingTriangles; + uint32_t nBoundingTriangles; // aka collisionIndices or collision_triangles uint32_t ofsBoundingTriangles; uint32_t nBoundingVertices; uint32_t ofsBoundingVertices; - uint32_t nBoundingNormals; + uint32_t nBoundingNormals; // collisionFaceNormals uint32_t ofsBoundingNormals; uint32_t nAttachments; // O diff --git a/src/noggit/ModelInstance.cpp b/src/noggit/ModelInstance.cpp index a3b4c477..ad6a23df 100755 --- a/src/noggit/ModelInstance.cpp +++ b/src/noggit/ModelInstance.cpp @@ -55,8 +55,8 @@ void ModelInstance::draw_box (glm::mat4x4 const& model_view , projection , transformMatrix() , { 1.0f, 1.0f, 0.0f, 1.0f } - , misc::transform_model_box_coords(model->header.collision_box_min) - , misc::transform_model_box_coords(model->header.collision_box_max) + , misc::transform_model_box_coords(model->collision_box_min) + , misc::transform_model_box_coords(model->collision_box_max) ); // draw bounding box @@ -64,8 +64,8 @@ void ModelInstance::draw_box (glm::mat4x4 const& model_view , projection , transformMatrix() , {1.0f, 1.0f, 1.0f, 1.0f} - , misc::transform_model_box_coords(model->header.bounding_box_min) - , misc::transform_model_box_coords(model->header.bounding_box_max) + , misc::transform_model_box_coords(model->bounding_box_min) + , misc::transform_model_box_coords(model->bounding_box_max) ); // draw extents @@ -84,8 +84,8 @@ void ModelInstance::draw_box (glm::mat4x4 const& model_view , projection , transformMatrix() , color - , misc::transform_model_box_coords(model->header.bounding_box_min) - , misc::transform_model_box_coords(model->header.bounding_box_max) + , misc::transform_model_box_coords(model->bounding_box_min) + , misc::transform_model_box_coords(model->bounding_box_max) ); } } @@ -104,8 +104,8 @@ void ModelInstance::intersect (glm::mat4x4 const& model_view std::vector> triangle_indices; math::ray subray (_transform_mat_inverted, ray); - if ( !subray.intersect_bounds ( fixCoordSystem (model->header.bounding_box_min) - , fixCoordSystem (model->header.bounding_box_max) + if ( !subray.intersect_bounds ( fixCoordSystem (model->bounding_box_min) + , fixCoordSystem (model->bounding_box_max) ) ) { @@ -142,11 +142,11 @@ bool ModelInstance::isInRenderDist(const float& cull_distance, const glm::vec3& if (display == display_mode::in_3D) { - dist = glm::distance(camera, pos) - model->rad * scale; + dist = glm::distance(camera, pos) - model->bounding_box_radius * scale; } else { - dist = std::abs(pos.y - camera.y) - model->rad * scale; + dist = std::abs(pos.y - camera.y) - model->bounding_box_radius * scale; } if (dist >= cull_distance) @@ -188,8 +188,8 @@ void ModelInstance::recalcExtents() updateTransformMatrix(); math::aabb const relative_to_model - ( glm::min ( model->header.collision_box_min, model->header.bounding_box_min) - , glm::max ( model->header.collision_box_max, model->header.bounding_box_max) + ( glm::min ( model->collision_box_min, model->bounding_box_min) + , glm::max ( model->collision_box_max, model->bounding_box_max) ); //! \todo If both boxes are {inf, -inf}, or well, if any min.c > max.c, @@ -259,10 +259,10 @@ void ModelInstance::updateDetails(Noggit::Ui::detail_infos* detail_widget) << "
server position X/Y/Z: {" << (ZEROPOINT - pos.z) << ", " << (ZEROPOINT - pos.x) << ", " << pos.y << "}" << "
server orientation: " << fabs(2 * glm::pi() - glm::pi() / 180.0 * (float(dir.y) < 0 ? fabs(float(dir.y)) + 180.0 : fabs(float(dir.y) - 180.0))) - << "
textures Used: " << model->header.nTextures + << "
textures Used: " << model->_textures.size() << "
size category: " << size_cat; - for (unsigned j = 0; j < model->header.nTextures; j++) + for (unsigned j = 0; j < model->_textures.size(); j++) { bool stuck = !model->_textures[j]->finishedLoading(); bool error = model->_textures[j]->finishedLoading() && !model->_textures[j]->is_uploaded(); diff --git a/src/noggit/rendering/ModelRender.cpp b/src/noggit/rendering/ModelRender.cpp index cb97419e..1befaa44 100755 --- a/src/noggit/rendering/ModelRender.cpp +++ b/src/noggit/rendering/ModelRender.cpp @@ -19,8 +19,8 @@ ModelRender::ModelRender(Model* model) void ModelRender::upload() { _vertex_box_points = math::box_points( - misc::transform_model_box_coords(_model->header.bounding_box_min) - , misc::transform_model_box_coords(_model->header.bounding_box_max)); + misc::transform_model_box_coords(_model->bounding_box_min) + , misc::transform_model_box_coords(_model->bounding_box_max)); for (std::string const& texture : _model->_textureFilenames) _model->_textures.emplace_back(texture, _model->_context); @@ -197,10 +197,14 @@ void ModelRender::draw(glm::mat4x4 const& model_view } // store the model count to draw the bounding boxes later - if (all_boxes || _model->_hidden) + if (all_boxes || _model->_hidden ) { model_boxes_to_draw.emplace(_model, instances.size()); } + else if (_model->use_fake_geometry() /*|| _model->particles_only()*/) + { // hackfix for rendering particle only objects bounds as they currently don't render + model_boxes_to_draw.emplace(_model, instances.size()); + } /* if (draw_particles && (!_particles.empty() || !_ribbons.empty())) @@ -317,7 +321,7 @@ void ModelRender::fixShaderIdBlendOverride() } int shader = 0; - bool blend_mode_override = (_model->header.Flags & m2_flag_use_texture_combiner_combos); + bool blend_mode_override = (_model->Flags & m2_flag_use_texture_combiner_combos); // fuckporting check if (pass.texture_coord_combo_index + pass.texture_count - 1 >= _model->_texture_unit_lookup.size()) diff --git a/src/noggit/rendering/WorldRender.cpp b/src/noggit/rendering/WorldRender.cpp index 55eb7cbf..41c41752 100755 --- a/src/noggit/rendering/WorldRender.cpp +++ b/src/noggit/rendering/WorldRender.cpp @@ -858,7 +858,8 @@ void WorldRender::draw (glm::mat4x4 const& model_view models_to_draw.clear(); wmos_to_draw.clear(); - if(draw_models_with_box || (draw_hidden_models && !model_boxes_to_draw.empty())) + // if(draw_models_with_box || (draw_hidden_models && !model_boxes_to_draw.empty())) + if (!model_boxes_to_draw.empty()) { OpenGL::Scoped::use_program m2_box_shader{ *_m2_box_program.get() }; @@ -896,17 +897,8 @@ void WorldRender::draw (glm::mat4x4 const& model_view if (model->_rendered_last_frame) { - bool is_selected = false; - /* - auto id = model->uid; - bool const is_selected = _world->current_selection().size() > 0 && - std::find_if(_world->current_selection().begin(), _world->current_selection().end(), - [id](selection_type type) - { - return var_type(type) == typeid(selected_object_type) - && std::get(type)->which() == SceneObjectTypes::eMODEL - && static_cast(std::get(type))->uid == id; - }) != _world->current_selection().end();*/ + // bool is_selected = false; + bool is_selected = _world->is_selected(model->uid); model->draw_box(model_view, projection, is_selected); // make optional! } @@ -1101,7 +1093,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view } } - if (terrainMode == editing_mode::light) + if (terrainMode == editing_mode::light && alpha_light_sphere > 0.0f) { // Sky* CurrentSky = skies()->findClosestSkyByDistance(camera_pos); Sky* CurrentSky = skies()->findClosestSkyByWeight();