Files
noggit-red/src/noggit/ModelInstance.h

153 lines
4.6 KiB
C++

// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <math/ray.hpp>
#include <math/vector_3d.hpp> // math::vector_3d
#include <noggit/MPQ.h> // MPQFile
#include <noggit/MapHeaders.h> // ENTRY_MDDF
#include <noggit/ModelManager.h>
#include <noggit/Selection.h>
#include <noggit/tile_index.hpp>
#include <noggit/tool_enums.hpp>
#include <opengl/shader.fwd.hpp>
#include <opengl/primitives.hpp>
namespace math { class frustum; }
class Model;
class WMOInstance;
class ModelInstance
{
public:
constexpr static float min_scale() { return 1.f / 1024.f; };
constexpr static float max_scale() { return static_cast<float>((1 << 16) - 1) / 1024.f; };
scoped_model_reference model;
math::vector_3d pos;
math::vector_3d dir;
math::vector_3d light_color = { 1.f, 1.f, 1.f };
//! \todo Get this out and do somehow else.
unsigned int uid;
float scale = 1.f;
// used when flag 0x8 is set in wdt
// longest side of an AABB transformed model's bounding box from the M2 header
float size_cat;
explicit ModelInstance(std::string const& filename);
explicit ModelInstance(std::string const& filename, ENTRY_MDDF const*d);
ModelInstance(ModelInstance const& other) = default;
ModelInstance& operator= (ModelInstance const& other) = default;
ModelInstance (ModelInstance&& other)
: model (std::move (other.model))
, pos (other.pos)
, dir (other.dir)
, light_color (other.light_color)
, uid (other.uid)
, scale (other.scale)
, size_cat (other.size_cat)
, _need_recalc_extents(other._need_recalc_extents)
, _extents(other._extents)
, _transform_mat_transposed(other._transform_mat_transposed)
, _transform_mat_inverted(other._transform_mat_inverted)
{
}
ModelInstance& operator= (ModelInstance&& other)
{
std::swap (model, other.model);
std::swap (pos, other.pos);
std::swap (dir, other.dir);
std::swap (light_color, other.light_color);
std::swap (uid, other.uid);
std::swap (scale, other.scale);
std::swap (size_cat, other.size_cat);
std::swap (_need_recalc_extents, other._need_recalc_extents);
std::swap (_extents, other._extents);
std::swap(_transform_mat_transposed, other._transform_mat_transposed);
std::swap(_transform_mat_inverted, other._transform_mat_inverted);
return *this;
}
bool is_a_duplicate_of(ModelInstance const& other);
void draw_box ( math::matrix_4x4 const& model_view
, math::matrix_4x4 const& projection
, bool is_current_selection
);
void intersect ( math::matrix_4x4 const& model_view
, math::ray const&
, selection_result*
, int animtime
);
math::matrix_4x4 const& transform_matrix_transposed() const { return _transform_mat_transposed; }
void resetDirection();
bool isInsideRect(math::vector_3d rect[2]) const;
bool is_visible(math::frustum const& frustum, const float& cull_distance, const math::vector_3d& camera, display_mode display);
virtual math::vector_3d get_pos() const { return pos; }
void recalcExtents();
std::vector<math::vector_3d> const& extents();
protected:
bool _need_recalc_extents = true;
std::vector<math::vector_3d> _extents = std::vector<math::vector_3d>(2);
virtual void update_transform_matrix();
math::matrix_4x4 _transform_mat_transposed = math::matrix_4x4::uninitialized;
math::matrix_4x4 _transform_mat_inverted = math::matrix_4x4::uninitialized;
};
class wmo_doodad_instance : public ModelInstance
{
public:
math::quaternion doodad_orientation;
math::vector_3d world_pos;
explicit wmo_doodad_instance(std::string const& filename, MPQFile* f);
wmo_doodad_instance(wmo_doodad_instance const& other) = default;
wmo_doodad_instance& operator= (wmo_doodad_instance const& other) = default;
wmo_doodad_instance (wmo_doodad_instance&& other)
: ModelInstance (other)
, doodad_orientation (other.doodad_orientation)
, world_pos (other.world_pos)
, _need_matrix_update(other._need_matrix_update)
{
}
wmo_doodad_instance& operator= (wmo_doodad_instance&& other)
{
ModelInstance::operator= (other);
std::swap (doodad_orientation, other.doodad_orientation);
std::swap (world_pos, other.world_pos);
std::swap (_need_matrix_update, other._need_matrix_update);
return *this;
}
bool need_matrix_update() const { return _need_matrix_update; }
void update_transform_matrix_wmo(WMOInstance* wmo);
virtual math::vector_3d get_pos() const { return world_pos; }
protected:
// to avoid redefining recalcExtents
virtual void update_transform_matrix() { }
private:
bool _need_matrix_update = true;
};