implement multi context rendering
This commit is contained in:
13
src/noggit/ContextObject.hpp
Normal file
13
src/noggit/ContextObject.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef NOGGIT_CONTEXTOBJECT_HPP
|
||||
#define NOGGIT_CONTEXTOBJECT_HPP
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
enum NoggitRenderContext
|
||||
{
|
||||
MAP_VIEW,
|
||||
ASSET_BROWSER
|
||||
};
|
||||
}
|
||||
|
||||
#endif //NOGGIT_CONTEXTOBJECT_HPP
|
||||
@@ -16,9 +16,10 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
Model::Model(const std::string& filename)
|
||||
Model::Model(const std::string& filename, noggit::NoggitRenderContext context)
|
||||
: AsyncObject(filename)
|
||||
, _finished_upload(false)
|
||||
, _context(context)
|
||||
{
|
||||
memset(&header, 0, sizeof(ModelHeader));
|
||||
}
|
||||
@@ -1610,7 +1611,7 @@ void Model::lightsOff(opengl::light lbase)
|
||||
void Model::upload()
|
||||
{
|
||||
for (std::string texture : _textureFilenames)
|
||||
_textures.emplace_back(texture);
|
||||
_textures.emplace_back(texture, _context);
|
||||
|
||||
_buffers.upload();
|
||||
_vertex_arrays.upload();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <noggit/Particle.h>
|
||||
#include <noggit/TextureManager.h>
|
||||
#include <noggit/tool_enums.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <opengl/scoped.hpp>
|
||||
#include <opengl/shader.fwd.hpp>
|
||||
|
||||
@@ -211,7 +212,7 @@ public:
|
||||
return std::vector<T>(start, start + count);
|
||||
}
|
||||
|
||||
Model(const std::string& name);
|
||||
Model(const std::string& name, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
void draw( math::matrix_4x4 const& model_view
|
||||
, ModelInstance& instance
|
||||
@@ -297,6 +298,8 @@ private:
|
||||
int _anim_time;
|
||||
int _global_animtime;
|
||||
|
||||
noggit::NoggitRenderContext _context;
|
||||
|
||||
void initCommon(const MPQFile& f);
|
||||
bool isAnimated(const MPQFile& f);
|
||||
void initAnimated(const MPQFile& f);
|
||||
|
||||
@@ -7,17 +7,20 @@
|
||||
#include <noggit/Model.h> // Model, etc.
|
||||
#include <noggit/ModelInstance.h>
|
||||
#include <noggit/WMOInstance.h>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <opengl/primitives.hpp>
|
||||
#include <opengl/scoped.hpp>
|
||||
#include <opengl/shader.hpp>
|
||||
|
||||
ModelInstance::ModelInstance(std::string const& filename)
|
||||
: model (filename)
|
||||
ModelInstance::ModelInstance(std::string const& filename, noggit::NoggitRenderContext context)
|
||||
: model (filename, context)
|
||||
, _context(context)
|
||||
{
|
||||
}
|
||||
|
||||
ModelInstance::ModelInstance(std::string const& filename, ENTRY_MDDF const*d)
|
||||
: model (filename)
|
||||
ModelInstance::ModelInstance(std::string const& filename, ENTRY_MDDF const*d, noggit::NoggitRenderContext context)
|
||||
: model (filename, context)
|
||||
, _context(context)
|
||||
{
|
||||
uid = d->uniqueID;
|
||||
pos = math::vector_3d(d->pos[0], d->pos[1], d->pos[2]);
|
||||
@@ -239,8 +242,9 @@ std::vector<math::vector_3d> const& ModelInstance::extents()
|
||||
}
|
||||
|
||||
|
||||
wmo_doodad_instance::wmo_doodad_instance(std::string const& filename, MPQFile* f)
|
||||
: ModelInstance (filename)
|
||||
wmo_doodad_instance::wmo_doodad_instance(std::string const& filename, MPQFile* f, noggit::NoggitRenderContext context)
|
||||
: ModelInstance(filename, context)
|
||||
, _context(context)
|
||||
{
|
||||
float ff[4];
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <noggit/MapHeaders.h> // ENTRY_MDDF
|
||||
#include <noggit/ModelManager.h>
|
||||
#include <noggit/Selection.h>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <noggit/tile_index.hpp>
|
||||
#include <noggit/tool_enums.hpp>
|
||||
#include <opengl/shader.fwd.hpp>
|
||||
@@ -38,8 +39,12 @@ public:
|
||||
// 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);
|
||||
explicit ModelInstance(std::string const& filename,
|
||||
noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
explicit ModelInstance(std::string const& filename,
|
||||
ENTRY_MDDF const*d,
|
||||
noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
ModelInstance(ModelInstance const& other) = default;
|
||||
ModelInstance& operator= (ModelInstance const& other) = default;
|
||||
@@ -56,8 +61,10 @@ public:
|
||||
, _extents(other._extents)
|
||||
, _transform_mat_transposed(other._transform_mat_transposed)
|
||||
, _transform_mat_inverted(other._transform_mat_inverted)
|
||||
, _context(other._context)
|
||||
{
|
||||
}
|
||||
|
||||
ModelInstance& operator= (ModelInstance&& other)
|
||||
{
|
||||
std::swap (model, other.model);
|
||||
@@ -71,6 +78,7 @@ public:
|
||||
std::swap (_extents, other._extents);
|
||||
std::swap(_transform_mat_transposed, other._transform_mat_transposed);
|
||||
std::swap(_transform_mat_inverted, other._transform_mat_inverted);
|
||||
std::swap(_context, other._context);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -102,6 +110,8 @@ public:
|
||||
|
||||
protected:
|
||||
bool _need_recalc_extents = true;
|
||||
noggit::NoggitRenderContext _context;
|
||||
|
||||
std::vector<math::vector_3d> _extents = std::vector<math::vector_3d>(2);
|
||||
|
||||
virtual void update_transform_matrix();
|
||||
@@ -116,16 +126,19 @@ public:
|
||||
math::quaternion doodad_orientation;
|
||||
math::vector_3d world_pos;
|
||||
|
||||
explicit wmo_doodad_instance(std::string const& filename, MPQFile* f);
|
||||
explicit wmo_doodad_instance(std::string const& filename
|
||||
, MPQFile* f
|
||||
, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
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)
|
||||
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)
|
||||
, _context(other._context)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -135,6 +148,7 @@ public:
|
||||
std::swap (doodad_orientation, other.doodad_orientation);
|
||||
std::swap (world_pos, other.world_pos);
|
||||
std::swap (_need_matrix_update, other._need_matrix_update);
|
||||
std::swap (_context, other._context);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -149,4 +163,5 @@ protected:
|
||||
|
||||
private:
|
||||
bool _need_matrix_update = true;
|
||||
noggit::NoggitRenderContext _context;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <noggit/Model.h>
|
||||
#include <noggit/multimap_with_normalized_key.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -27,37 +28,46 @@ private:
|
||||
|
||||
struct scoped_model_reference
|
||||
{
|
||||
scoped_model_reference (std::string const& filename)
|
||||
: _valid (true)
|
||||
, _filename (filename)
|
||||
, _model (ModelManager::_.emplace (_filename))
|
||||
scoped_model_reference (
|
||||
std::string const& filename
|
||||
, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW)
|
||||
|
||||
: _valid(true)
|
||||
, _filename(filename)
|
||||
, _model(ModelManager::_.emplace (_filename, context))
|
||||
, _context(context)
|
||||
|
||||
{}
|
||||
|
||||
scoped_model_reference (scoped_model_reference const& other)
|
||||
: _valid (other._valid)
|
||||
, _filename (other._filename)
|
||||
, _model (ModelManager::_.emplace (_filename))
|
||||
, _model (ModelManager::_.emplace(_filename, other._context))
|
||||
, _context(other._context)
|
||||
{}
|
||||
scoped_model_reference& operator= (scoped_model_reference const& other)
|
||||
{
|
||||
_valid = other._valid;
|
||||
_filename = other._filename;
|
||||
_model = ModelManager::_.emplace (_filename);
|
||||
_model = ModelManager::_.emplace (_filename, other._context);
|
||||
_context = other._context;
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_model_reference (scoped_model_reference&& other)
|
||||
: _valid (other._valid)
|
||||
, _filename (other._filename)
|
||||
, _model (other._model)
|
||||
: _valid(other._valid)
|
||||
, _filename(other._filename)
|
||||
, _model(other._model)
|
||||
, _context(other._context)
|
||||
{
|
||||
other._valid = false;
|
||||
}
|
||||
scoped_model_reference& operator= (scoped_model_reference&& other)
|
||||
{
|
||||
std::swap (_valid, other._valid);
|
||||
std::swap (_filename, other._filename);
|
||||
std::swap (_model, other._model);
|
||||
std::swap(_valid, other._valid);
|
||||
std::swap(_filename, other._filename);
|
||||
std::swap(_model, other._model);
|
||||
std::swap(_context, other._context);
|
||||
other._valid = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -66,7 +76,7 @@ struct scoped_model_reference
|
||||
{
|
||||
if (_valid)
|
||||
{
|
||||
ModelManager::_.erase (_filename);
|
||||
ModelManager::_.erase(_filename, _context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +93,5 @@ private:
|
||||
bool _valid;
|
||||
std::string _filename;
|
||||
Model* _model;
|
||||
noggit::NoggitRenderContext _context;
|
||||
};
|
||||
|
||||
487
src/noggit/Red/AssetBrowser/ModelView.cpp
Normal file
487
src/noggit/Red/AssetBrowser/ModelView.cpp
Normal file
@@ -0,0 +1,487 @@
|
||||
#include "ModelView.hpp"
|
||||
#include <opengl/scoped.hpp>
|
||||
#include <math/projection.hpp>
|
||||
#include <noggit/Selection.h>
|
||||
#include <noggit/tool_enums.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
using namespace noggit::Red::AssetBrowser;
|
||||
|
||||
static const float XSENS = 15.0f;
|
||||
static const float YSENS = 15.0f;
|
||||
|
||||
ModelViewer::ModelViewer(QWidget *parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, _camera (math::vector_3d(0.0f, 0.0f, 0.0f), math::degrees(0.0f), math::degrees(0.0f))
|
||||
, _settings (new QSettings (this))
|
||||
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMouseTracking (true);
|
||||
|
||||
_startup_time.start();
|
||||
look = false;
|
||||
moving = strafing = updown = lookat = turn = 0.0f;
|
||||
mousedir = -1.0f;
|
||||
|
||||
_update_every_event_loop.start (0);
|
||||
connect (&_update_every_event_loop, &QTimer::timeout, [this] { update(); });
|
||||
}
|
||||
|
||||
void ModelViewer::setModel(std::string const &filename)
|
||||
{
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
makeCurrent();
|
||||
|
||||
// remove old instance
|
||||
if (_model_instance.which() == eEntry_WMO)
|
||||
{
|
||||
delete boost::get<selected_wmo_type>(_model_instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete boost::get<selected_model_type>(_model_instance);
|
||||
}
|
||||
|
||||
// add new model instance
|
||||
QString q_filename = QString(filename.c_str());
|
||||
|
||||
if (q_filename.endsWith(".wmo"))
|
||||
{
|
||||
auto instance = new WMOInstance(filename, noggit::NoggitRenderContext::ASSET_BROWSER);
|
||||
_model_instance = instance;
|
||||
instance->wmo->wait_until_loaded();
|
||||
instance->recalcExtents();
|
||||
|
||||
}
|
||||
else if (q_filename.endsWith(".m2"))
|
||||
{
|
||||
auto instance = new ModelInstance(filename, noggit::NoggitRenderContext::ASSET_BROWSER);
|
||||
_model_instance = instance;
|
||||
instance->model->wait_until_loaded();
|
||||
instance->recalcExtents();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("Asset browser only supports viewing M2 and WMO for now.");
|
||||
}
|
||||
|
||||
resetCamera();
|
||||
}
|
||||
|
||||
|
||||
void ModelViewer::resetCamera()
|
||||
{
|
||||
float radius = 0.f;
|
||||
|
||||
if (_model_instance.which() == eEntry_WMO)
|
||||
{
|
||||
WMOInstance* wmo = boost::get<selected_wmo_type>(_model_instance);
|
||||
auto bb_center = (wmo->extents[0] + wmo->extents[1]) / 2;
|
||||
radius = (bb_center - wmo->extents[0]).length();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelInstance* model = boost::get<selected_model_type>(_model_instance);
|
||||
auto extents = model->extents();
|
||||
|
||||
auto bb_center = (extents[0] + extents[1]) / 2;
|
||||
radius = (bb_center - extents[0]).length();
|
||||
}
|
||||
|
||||
float distance_factor = abs( aspect_ratio() * radius / sin(_camera.fov()) / 2);
|
||||
_camera.position = {0.f, 0.f, 0.f};
|
||||
_camera.move_forward_factor(-1.f, distance_factor);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ModelViewer::initializeGL()
|
||||
{
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
gl.viewport(0.0f, 0.0f, width(), height());
|
||||
gl.clearColor (0.7f, 0.5f, 0.5f, 1.0f);
|
||||
}
|
||||
|
||||
void ModelViewer::paintGL()
|
||||
{
|
||||
const qreal now(_startup_time.elapsed() / 1000.0);
|
||||
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
makeCurrent();
|
||||
|
||||
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
tick(now - _last_update);
|
||||
|
||||
_last_update = now;
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
void ModelViewer::resizeGL(int w, int h)
|
||||
{
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
gl.viewport(0.0f, 0.0f, w, h);
|
||||
}
|
||||
|
||||
void ModelViewer::tick(float dt)
|
||||
{
|
||||
if (turn)
|
||||
{
|
||||
_camera.add_to_yaw(math::degrees(turn));
|
||||
}
|
||||
if (lookat)
|
||||
{
|
||||
_camera.add_to_pitch(math::degrees(lookat));
|
||||
}
|
||||
if (moving)
|
||||
{
|
||||
_camera.move_forward(moving, dt);
|
||||
}
|
||||
if (strafing)
|
||||
{
|
||||
_camera.move_horizontal(strafing, dt);
|
||||
}
|
||||
if (updown)
|
||||
{
|
||||
_camera.move_vertical(updown, dt);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelViewer::draw()
|
||||
{
|
||||
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
makeCurrent();
|
||||
|
||||
float culldistance = 10000000;
|
||||
bool draw_doodads_wmo = true;
|
||||
|
||||
math::matrix_4x4 const mvp(model_view().transposed() * projection().transposed());
|
||||
math::frustum const frustum (mvp);
|
||||
|
||||
if (!_m2_program)
|
||||
{
|
||||
setModel("world/wmo/azeroth/buildings/human_farm/farm.wmo");
|
||||
_m2_program.reset
|
||||
( new opengl::program
|
||||
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("m2_vs") }
|
||||
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("m2_fs") }
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!_m2_instanced_program)
|
||||
{
|
||||
_m2_instanced_program.reset
|
||||
( new opengl::program
|
||||
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("m2_vs", {"instanced"}) }
|
||||
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("m2_fs") }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!_m2_ribbons_program)
|
||||
{
|
||||
_m2_ribbons_program.reset
|
||||
( new opengl::program
|
||||
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("ribbon_vs") }
|
||||
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("ribbon_fs") }
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!_m2_particles_program)
|
||||
{
|
||||
_m2_particles_program.reset
|
||||
( new opengl::program
|
||||
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("particle_vs") }
|
||||
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("particle_fs") }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!_wmo_program)
|
||||
{
|
||||
_wmo_program.reset
|
||||
( new opengl::program
|
||||
{ { GL_VERTEX_SHADER, opengl::shader::src_from_qrc("wmo_vs") }
|
||||
, { GL_FRAGMENT_SHADER, opengl::shader::src_from_qrc("wmo_fs") }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!_liquid_render)
|
||||
{
|
||||
_liquid_render.emplace();
|
||||
}
|
||||
|
||||
gl.enable(GL_DEPTH_TEST);
|
||||
gl.depthFunc(GL_LEQUAL);
|
||||
gl.enable(GL_BLEND);
|
||||
gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// draw WMOs
|
||||
std::unordered_map<std::string, std::vector<ModelInstance*>> _wmo_doodads;
|
||||
|
||||
if (_model_instance.which() == eEntry_WMO)
|
||||
{
|
||||
// set anim time only once per frame
|
||||
{
|
||||
opengl::scoped::use_program water_shader {_liquid_render->shader_program()};
|
||||
water_shader.uniform("animtime", 0 / 2880.f);
|
||||
|
||||
water_shader.uniform("model_view", model_view().transposed());
|
||||
water_shader.uniform("projection", projection().transposed());
|
||||
|
||||
math::vector_4d ocean_color_light(math::vector_3d(1.0f, 1.0f, 1.0f), 1.f);
|
||||
math::vector_4d ocean_color_dark(math::vector_3d(1.0f, 1.0f, 1.0f), 1.f);
|
||||
math::vector_4d river_color_light(math::vector_3d(1.0f, 1.0f, 1.0f), 1.f);
|
||||
math::vector_4d river_color_dark(math::vector_3d(1.0f, 1.0f, 1.0f), 1.f);
|
||||
|
||||
water_shader.uniform("ocean_color_light", ocean_color_light);
|
||||
water_shader.uniform("ocean_color_dark", ocean_color_dark);
|
||||
water_shader.uniform("river_color_light", river_color_light);
|
||||
water_shader.uniform("river_color_dark", river_color_dark);
|
||||
water_shader.uniform("use_transform", 1);
|
||||
}
|
||||
|
||||
{
|
||||
opengl::scoped::use_program wmo_program{*_wmo_program.get()};
|
||||
|
||||
wmo_program.uniform("model_view", model_view().transposed());
|
||||
wmo_program.uniform("projection", projection().transposed());
|
||||
wmo_program.uniform("tex1", 0);
|
||||
wmo_program.uniform("tex2", 1);
|
||||
|
||||
wmo_program.uniform("draw_fog", 0);
|
||||
|
||||
wmo_program.uniform("exterior_light_dir", math::vector_3d(0.0f, 1.0f, 0.0f));
|
||||
wmo_program.uniform("exterior_diffuse_color", math::vector_3d(1.0f, 1.0f, 1.0f));
|
||||
wmo_program.uniform("exterior_ambient_color", math::vector_3d(1.0f, 1.0f, 1.0f));
|
||||
|
||||
auto wmo_instance = boost::get<selected_wmo_type>(_model_instance);
|
||||
|
||||
wmo_instance->draw(
|
||||
wmo_program, model_view().transposed(), projection().transposed(), frustum, culldistance,
|
||||
math::vector_3d(0.0f, 0.0f, 0.0f), false, false // doodads
|
||||
, false, _liquid_render.get(), std::vector<selection_type>(), 0, false, display_mode::in_3D
|
||||
);
|
||||
|
||||
gl.enable(GL_BLEND);
|
||||
gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
gl.enable(GL_CULL_FACE);
|
||||
|
||||
if (draw_doodads_wmo)
|
||||
{
|
||||
for (auto &doodad : wmo_instance->get_visible_doodads(frustum, culldistance, _camera.position, false,
|
||||
display_mode::in_3D))
|
||||
{
|
||||
_wmo_doodads[doodad->model->filename].push_back(doodad);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// draw M2
|
||||
std::unordered_map<Model*, std::size_t> model_with_particles;
|
||||
std::unordered_map<Model*, std::size_t> model_boxes_to_draw;
|
||||
|
||||
{
|
||||
opengl::scoped::use_program m2_shader {*_m2_instanced_program.get()};
|
||||
|
||||
m2_shader.uniform("model_view", model_view().transposed());
|
||||
m2_shader.uniform("projection", projection().transposed());
|
||||
m2_shader.uniform("tex1", 0);
|
||||
m2_shader.uniform("tex2", 1);
|
||||
m2_shader.uniform("draw_fog", 0);
|
||||
|
||||
m2_shader.uniform("light_dir", math::vector_3d(0.0f, 1.0f, 0.0f));
|
||||
m2_shader.uniform("diffuse_color", math::vector_3d(1.0f, 1.0f, 1.0f));
|
||||
m2_shader.uniform("ambient_color", math::vector_3d(1.0f, 1.0f, 1.0f));
|
||||
|
||||
if (_model_instance.which() == eEntry_Model)
|
||||
{
|
||||
auto model_instance = boost::get<selected_model_type>(_model_instance);
|
||||
|
||||
model_instance->model->draw(
|
||||
model_view().transposed()
|
||||
, std::vector<ModelInstance*>{model_instance}
|
||||
, m2_shader
|
||||
, frustum
|
||||
, culldistance
|
||||
, _camera.position
|
||||
, false
|
||||
, 0
|
||||
, false
|
||||
, false
|
||||
, model_with_particles
|
||||
, model_boxes_to_draw
|
||||
, display_mode::in_3D
|
||||
);
|
||||
}
|
||||
|
||||
if (draw_doodads_wmo)
|
||||
{
|
||||
for (auto& it : _wmo_doodads)
|
||||
{
|
||||
it.second[0]->model->draw(
|
||||
model_view().transposed()
|
||||
, it.second
|
||||
, m2_shader
|
||||
, frustum
|
||||
, culldistance
|
||||
, _camera.position
|
||||
, false
|
||||
, 0
|
||||
, false
|
||||
, false
|
||||
, model_with_particles
|
||||
, model_boxes_to_draw
|
||||
, display_mode::in_3D
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gl.bindVertexArray(0);
|
||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
}
|
||||
|
||||
math::matrix_4x4 ModelViewer::model_view() const
|
||||
{
|
||||
return _camera.look_at_matrix();
|
||||
}
|
||||
|
||||
math::matrix_4x4 ModelViewer::projection() const
|
||||
{
|
||||
float far_z = _settings->value("farZ", 2048).toFloat();
|
||||
return math::perspective(_camera.fov(), aspect_ratio(), 1.f, far_z);
|
||||
}
|
||||
|
||||
float ModelViewer::aspect_ratio() const
|
||||
{
|
||||
return float (width()) / float (height());
|
||||
}
|
||||
|
||||
void ModelViewer::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QLineF const relative_movement (_last_mouse_pos, event->pos());
|
||||
|
||||
if (look)
|
||||
{
|
||||
_camera.add_to_yaw(math::degrees(relative_movement.dx() / XSENS));
|
||||
_camera.add_to_pitch(math::degrees(mousedir * relative_movement.dy() / YSENS));
|
||||
}
|
||||
|
||||
_last_mouse_pos = event->pos();
|
||||
}
|
||||
|
||||
void ModelViewer::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
look = true;
|
||||
}
|
||||
|
||||
void ModelViewer::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
look = false;
|
||||
}
|
||||
|
||||
void ModelViewer::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ModelViewer::keyReleaseEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_W || event->key() == Qt::Key_S)
|
||||
{
|
||||
moving = 0.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)
|
||||
{
|
||||
lookat = 0.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Right || event->key() == Qt::Key_Left)
|
||||
{
|
||||
turn = 0.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_D || event->key() == Qt::Key_A)
|
||||
{
|
||||
strafing = 0.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Q || event->key() == Qt::Key_E)
|
||||
{
|
||||
updown = 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ModelViewer::focusOutEvent(QFocusEvent* event)
|
||||
{
|
||||
//moving = 0.0f;
|
||||
//lookat = 0.0f;
|
||||
// turn = 0.0f;
|
||||
//strafing = 0.0f;
|
||||
// updown = 0.0f;
|
||||
}
|
||||
|
||||
void ModelViewer::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_W)
|
||||
{
|
||||
moving = 1.0f;
|
||||
}
|
||||
if (event->key() == Qt::Key_S)
|
||||
{
|
||||
moving = -1.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Up)
|
||||
{
|
||||
lookat = 0.75f;
|
||||
}
|
||||
if (event->key() == Qt::Key_Down)
|
||||
{
|
||||
lookat = -0.75f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Right)
|
||||
{
|
||||
turn = 0.75f;
|
||||
}
|
||||
if (event->key() == Qt::Key_Left)
|
||||
{
|
||||
turn = -0.75f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_D)
|
||||
{
|
||||
strafing = 1.0f;
|
||||
}
|
||||
if (event->key() == Qt::Key_A)
|
||||
{
|
||||
strafing = -1.0f;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Q)
|
||||
{
|
||||
updown = 1.0f;
|
||||
}
|
||||
if (event->key() == Qt::Key_E)
|
||||
{
|
||||
updown = -1.0f;
|
||||
}
|
||||
}
|
||||
89
src/noggit/Red/AssetBrowser/ModelView.hpp
Normal file
89
src/noggit/Red/AssetBrowser/ModelView.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef NOGGIT_ModelView_HPP
|
||||
#define NOGGIT_ModelView_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QSettings>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QFocusEvent>
|
||||
#include <QPointF>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
#include <math/matrix_4x4.hpp>
|
||||
#include <math/vector_3d.hpp>
|
||||
#include <noggit/camera.hpp>
|
||||
#include <noggit/WMOInstance.h>
|
||||
#include <noggit/Selection.h>
|
||||
#include <noggit/WMO.h>
|
||||
#include <noggit/Model.h>
|
||||
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
namespace Red::AssetBrowser
|
||||
{
|
||||
|
||||
class ModelViewer : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModelViewer(QWidget* parent = nullptr);
|
||||
|
||||
void resetCamera();
|
||||
void setModel(std::string const& filename);
|
||||
|
||||
private:
|
||||
|
||||
QTimer _update_every_event_loop;
|
||||
QPointF _last_mouse_pos;
|
||||
float moving, strafing, updown, mousedir, turn, lookat;
|
||||
bool look;
|
||||
|
||||
QElapsedTimer _startup_time;
|
||||
qreal _last_update = 0.f;
|
||||
|
||||
noggit::camera _camera;
|
||||
QSettings* _settings;
|
||||
|
||||
std::unique_ptr<opengl::program> _m2_program;
|
||||
std::unique_ptr<opengl::program> _m2_instanced_program;
|
||||
std::unique_ptr<opengl::program> _m2_particles_program;
|
||||
std::unique_ptr<opengl::program> _m2_ribbons_program;
|
||||
std::unique_ptr<opengl::program> _m2_box_program;
|
||||
std::unique_ptr<opengl::program> _wmo_program;
|
||||
|
||||
boost::optional<liquid_render> _liquid_render = boost::none;
|
||||
|
||||
selection_type _model_instance;
|
||||
|
||||
void tick(float dt);
|
||||
void draw();
|
||||
math::matrix_4x4 model_view() const;
|
||||
math::matrix_4x4 projection() const;
|
||||
float aspect_ratio() const;
|
||||
|
||||
void initializeGL() override;
|
||||
void paintGL() override;
|
||||
void resizeGL (int w, int h) override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void focusOutEvent(QFocusEvent* event) override;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //NOGGIT_ModelView_HPP
|
||||
64
src/noggit/Red/AssetBrowser/Ui/AssetBrowser.cpp
Normal file
64
src/noggit/Red/AssetBrowser/Ui/AssetBrowser.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "AssetBrowser.hpp"
|
||||
#include <ui_AssetBrowser.h>
|
||||
#include <noggit/MPQ.h>
|
||||
#include <noggit/Log.h>
|
||||
#include <noggit/Red/AssetBrowser/Ui/Model/TreeManager.hpp>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
using namespace noggit::Red::AssetBrowser::Ui;
|
||||
|
||||
AssetBrowserWidget::AssetBrowserWidget(QWidget *parent)
|
||||
{
|
||||
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
|
||||
ui = new ::Ui::AssetBrowser;
|
||||
ui->setupUi(this);
|
||||
|
||||
_model = new QStandardItemModel(this);
|
||||
|
||||
ui->listfileTree->setModel(_model);
|
||||
|
||||
connect(ui->listfileTree->selectionModel(), &QItemSelectionModel::selectionChanged
|
||||
,[=] (const QItemSelection& selected, const QItemSelection& deselected)
|
||||
{
|
||||
for (auto index : selected.indexes())
|
||||
{
|
||||
auto path = index.data(Qt::UserRole).toString();
|
||||
if (path.endsWith(".wmo") || path.endsWith(".m2"))
|
||||
{
|
||||
ui->openGLWidget->setModel(path.toStdString());
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
updateModelData();
|
||||
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto duration = duration_cast<std::chrono::seconds>(stop - start);
|
||||
LogDebug << duration.count() << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void AssetBrowserWidget::updateModelData()
|
||||
{
|
||||
Model::TreeManager tree_mgr = Model::TreeManager(_model);
|
||||
for (auto path : gListfile)
|
||||
{
|
||||
QString q_path = QString(path.c_str());
|
||||
|
||||
if (!(q_path.endsWith(".wmo") || q_path.endsWith(".m2")))
|
||||
continue;
|
||||
|
||||
tree_mgr.addItem(path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
AssetBrowserWidget::~AssetBrowserWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
31
src/noggit/Red/AssetBrowser/Ui/AssetBrowser.hpp
Normal file
31
src/noggit/Red/AssetBrowser/Ui/AssetBrowser.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef NOGGIT_ASSETBROWSER_HPP
|
||||
#define NOGGIT_ASSETBROWSER_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <ui_AssetBrowser.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
namespace Red::AssetBrowser::Ui
|
||||
{
|
||||
class AssetBrowserWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
AssetBrowserWidget(QWidget* parent = nullptr);
|
||||
~AssetBrowserWidget();
|
||||
|
||||
private:
|
||||
::Ui::AssetBrowser* ui;
|
||||
QStandardItemModel* _model;
|
||||
|
||||
void updateModelData();
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //NOGGIT_ASSETBROWSER_HPP
|
||||
50
src/noggit/Red/AssetBrowser/Ui/Model/TreeManager.cpp
Normal file
50
src/noggit/Red/AssetBrowser/Ui/Model/TreeManager.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "TreeManager.hpp"
|
||||
|
||||
|
||||
using namespace noggit::Red::AssetBrowser::Ui::Model;
|
||||
|
||||
|
||||
QStandardItem* TreeManager::addItem(QString path)
|
||||
{
|
||||
QStandardItem * item = root;
|
||||
QStringList p(path.split(sep, Qt::SkipEmptyParts));
|
||||
|
||||
if (items.contains(path))
|
||||
return items[path];
|
||||
|
||||
QString path_remainder = QString("");
|
||||
|
||||
while (!p.isEmpty())
|
||||
{
|
||||
QString elt = p.takeFirst();
|
||||
path_remainder = path_remainder + elt;
|
||||
|
||||
QStandardItem* child = find(path_remainder);
|
||||
|
||||
if (!child)
|
||||
{
|
||||
item->appendRow((child = new QStandardItem(elt)));
|
||||
child->setData(QVariant(path_remainder), Qt::UserRole);
|
||||
|
||||
layered_items[path_remainder] = child;
|
||||
}
|
||||
|
||||
item = child;
|
||||
|
||||
path_remainder = path_remainder + "/";
|
||||
}
|
||||
|
||||
items.insert(path, item);
|
||||
return item;
|
||||
}
|
||||
|
||||
QStandardItem* TreeManager::find(QString path)
|
||||
{
|
||||
auto search = layered_items.find(path);
|
||||
if (search != layered_items.end())
|
||||
{
|
||||
return search->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
40
src/noggit/Red/AssetBrowser/Ui/Model/TreeManager.hpp
Normal file
40
src/noggit/Red/AssetBrowser/Ui/Model/TreeManager.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef NOGGIT_TREEMANAGER_HPP
|
||||
#define NOGGIT_TREEMANAGER_HPP
|
||||
|
||||
#include <external/tsl/robin_map.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
namespace Red::AssetBrowser::Ui::Model
|
||||
{
|
||||
class TreeManager
|
||||
{
|
||||
Q_DISABLE_COPY(TreeManager)
|
||||
|
||||
public:
|
||||
explicit TreeManager(QStandardItem* root) : root(root), sep(QLatin1Char('/')) {}
|
||||
explicit TreeManager(QStandardItemModel* model) : root(model->invisibleRootItem()), sep(QLatin1Char('/')) {}
|
||||
|
||||
QStandardItem* addItem(QString path);
|
||||
|
||||
private:
|
||||
|
||||
QChar const sep;
|
||||
QMap<QString, QStandardItem*> items;
|
||||
tsl::robin_map<QString, QStandardItem*> layered_items;
|
||||
QStandardItem* root;
|
||||
|
||||
QStandardItem* find(QString path);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //NOGGIT_TREEMANAGER_HPP
|
||||
@@ -207,8 +207,9 @@ void blp_texture::loadFromCompressedData(BLPHeader const* lHeader, char const* l
|
||||
}
|
||||
}
|
||||
|
||||
blp_texture::blp_texture(const std::string& filenameArg)
|
||||
blp_texture::blp_texture(const std::string& filenameArg, noggit::NoggitRenderContext context)
|
||||
: AsyncObject(filenameArg)
|
||||
, _context(context)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -425,17 +426,19 @@ namespace noggit
|
||||
}
|
||||
}
|
||||
|
||||
scoped_blp_texture_reference::scoped_blp_texture_reference (std::string const& filename)
|
||||
: _blp_texture (TextureManager::_.emplace (filename))
|
||||
scoped_blp_texture_reference::scoped_blp_texture_reference (std::string const& filename, noggit::NoggitRenderContext context)
|
||||
: _blp_texture(TextureManager::_.emplace(filename, context))
|
||||
, _context(context)
|
||||
{}
|
||||
|
||||
scoped_blp_texture_reference::scoped_blp_texture_reference (scoped_blp_texture_reference const& other)
|
||||
: _blp_texture (other._blp_texture ? TextureManager::_.emplace (other._blp_texture->filename) : nullptr)
|
||||
: _blp_texture(other._blp_texture ? TextureManager::_.emplace(other._blp_texture->filename, other._context) : nullptr)
|
||||
, _context(other._context)
|
||||
{}
|
||||
|
||||
void scoped_blp_texture_reference::Deleter::operator() (blp_texture* texture) const
|
||||
{
|
||||
TextureManager::_.erase (texture->filename);
|
||||
TextureManager::_.erase(texture->filename, texture->getContext());
|
||||
}
|
||||
|
||||
blp_texture* scoped_blp_texture_reference::operator->() const
|
||||
@@ -449,5 +452,5 @@ blp_texture* scoped_blp_texture_reference::get() const
|
||||
|
||||
bool scoped_blp_texture_reference::operator== (scoped_blp_texture_reference const& other) const
|
||||
{
|
||||
return std::tie (_blp_texture) == std::tie (other._blp_texture);
|
||||
return std::tie(_blp_texture) == std::tie(other._blp_texture);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <noggit/AsyncObject.h>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <noggit/multimap_with_normalized_key.hpp>
|
||||
#include <opengl/texture.hpp>
|
||||
#include <opengl/context.hpp>
|
||||
@@ -22,9 +23,10 @@
|
||||
|
||||
struct BLPHeader;
|
||||
|
||||
struct scoped_blp_texture_reference;
|
||||
struct blp_texture : public opengl::texture, AsyncObject
|
||||
{
|
||||
blp_texture (std::string const& filename);
|
||||
blp_texture (std::string const& filename, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
void finishLoading();
|
||||
|
||||
void loadFromUncompressedData(BLPHeader const* lHeader, char const* lData);
|
||||
@@ -36,6 +38,8 @@ struct blp_texture : public opengl::texture, AsyncObject
|
||||
void bind();
|
||||
void upload();
|
||||
|
||||
noggit::NoggitRenderContext getContext() { return _context; };
|
||||
|
||||
virtual async_priority loading_priority() const
|
||||
{
|
||||
return async_priority::high;
|
||||
@@ -47,13 +51,14 @@ private:
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
noggit::NoggitRenderContext _context;
|
||||
|
||||
private:
|
||||
std::map<int, std::vector<uint32_t>> _data;
|
||||
std::map<int, std::vector<uint8_t>> _compressed_data;
|
||||
boost::optional<GLint> _compression_format;
|
||||
};
|
||||
|
||||
struct scoped_blp_texture_reference;
|
||||
class TextureManager
|
||||
{
|
||||
public:
|
||||
@@ -67,7 +72,8 @@ private:
|
||||
struct scoped_blp_texture_reference
|
||||
{
|
||||
scoped_blp_texture_reference() = delete;
|
||||
scoped_blp_texture_reference (std::string const& filename);
|
||||
scoped_blp_texture_reference (std::string const& filename,
|
||||
noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
scoped_blp_texture_reference (scoped_blp_texture_reference const& other);
|
||||
scoped_blp_texture_reference (scoped_blp_texture_reference&&) = default;
|
||||
scoped_blp_texture_reference& operator= (scoped_blp_texture_reference const&) = delete;
|
||||
@@ -85,6 +91,7 @@ private:
|
||||
void operator() (blp_texture*) const;
|
||||
};
|
||||
std::unique_ptr<blp_texture, Deleter> _blp_texture;
|
||||
noggit::NoggitRenderContext _context;
|
||||
};
|
||||
|
||||
namespace noggit
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
#include <vector>
|
||||
|
||||
|
||||
WMO::WMO(const std::string& filenameArg)
|
||||
WMO::WMO(const std::string& filenameArg, noggit::NoggitRenderContext context)
|
||||
: AsyncObject(filenameArg)
|
||||
, _finished_upload(false)
|
||||
, _context(context)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -118,7 +119,7 @@ void WMO::finishLoading ()
|
||||
|
||||
if (mapping.second)
|
||||
{
|
||||
textures.emplace_back(texture);
|
||||
textures.emplace_back(texture, _context);
|
||||
}
|
||||
return mapping.first->second;
|
||||
}
|
||||
@@ -176,7 +177,7 @@ void WMO::finishLoading ()
|
||||
{
|
||||
if (MPQFile::exists(path))
|
||||
{
|
||||
skybox = scoped_model_reference(path);
|
||||
skybox = scoped_model_reference(path, _context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,7 +294,7 @@ void WMO::finishLoading ()
|
||||
size_t after_entry (f.getPos() + 0x28);
|
||||
f.read (&x, sizeof (x));
|
||||
|
||||
modelis.emplace_back(ddnames + x.name_offset, &f);
|
||||
modelis.emplace_back(ddnames + x.name_offset, &f, _context);
|
||||
model_nearest_light_vector.emplace_back();
|
||||
|
||||
f.seek (after_entry);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <noggit/TextureManager.h>
|
||||
#include <noggit/tool_enums.hpp>
|
||||
#include <noggit/wmo_liquid.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <opengl/primitives.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
@@ -249,7 +250,7 @@ static_assert ( sizeof (mohd_flags) == sizeof (std::uint16_t)
|
||||
class WMO : public AsyncObject
|
||||
{
|
||||
public:
|
||||
explicit WMO(const std::string& name);
|
||||
explicit WMO(const std::string& name, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
void draw ( opengl::scoped::use_program& wmo_shader
|
||||
, math::matrix_4x4 const& model_view
|
||||
@@ -267,6 +268,7 @@ public:
|
||||
, bool world_has_skies
|
||||
, display_mode display
|
||||
);
|
||||
|
||||
bool draw_skybox( math::matrix_4x4 const& model_view
|
||||
, math::vector_3d const& camera_pos
|
||||
, opengl::scoped::use_program& m2_shader
|
||||
@@ -308,6 +310,8 @@ public:
|
||||
|
||||
boost::optional<scoped_model_reference> skybox;
|
||||
|
||||
noggit::NoggitRenderContext _context;
|
||||
|
||||
bool is_hidden() const { return _hidden; }
|
||||
void toggle_visibility() { _hidden = !_hidden; }
|
||||
void show() { _hidden = false ; }
|
||||
@@ -333,22 +337,26 @@ private:
|
||||
|
||||
struct scoped_wmo_reference
|
||||
{
|
||||
scoped_wmo_reference (std::string const& filename)
|
||||
: _valid (true)
|
||||
, _filename (filename)
|
||||
, _wmo (WMOManager::_.emplace (_filename))
|
||||
scoped_wmo_reference (std::string const& filename
|
||||
, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW)
|
||||
: _valid(true)
|
||||
, _filename(filename)
|
||||
, _context(context)
|
||||
, _wmo (WMOManager::_.emplace(_filename, context))
|
||||
{}
|
||||
|
||||
scoped_wmo_reference (scoped_wmo_reference const& other)
|
||||
: _valid (other._valid)
|
||||
, _filename (other._filename)
|
||||
, _wmo (WMOManager::_.emplace (_filename))
|
||||
: _valid(other._valid)
|
||||
, _filename(other._filename)
|
||||
, _wmo(WMOManager::_.emplace(_filename, other._context))
|
||||
, _context(other._context)
|
||||
{}
|
||||
scoped_wmo_reference& operator= (scoped_wmo_reference const& other)
|
||||
{
|
||||
_valid = other._valid;
|
||||
_filename = other._filename;
|
||||
_wmo = WMOManager::_.emplace (_filename);
|
||||
_wmo = WMOManager::_.emplace(_filename, other._context);
|
||||
_context = other._context;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -356,6 +364,7 @@ struct scoped_wmo_reference
|
||||
: _valid (other._valid)
|
||||
, _filename (other._filename)
|
||||
, _wmo (other._wmo)
|
||||
, _context (other._context)
|
||||
{
|
||||
other._valid = false;
|
||||
}
|
||||
@@ -364,6 +373,7 @@ struct scoped_wmo_reference
|
||||
std::swap(_valid, other._valid);
|
||||
std::swap(_filename, other._filename);
|
||||
std::swap(_wmo, other._wmo);
|
||||
std::swap(_context, other._context);
|
||||
other._valid = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -372,7 +382,7 @@ struct scoped_wmo_reference
|
||||
{
|
||||
if (_valid)
|
||||
{
|
||||
WMOManager::_.erase (_filename);
|
||||
WMOManager::_.erase(_filename, _context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,4 +400,5 @@ private:
|
||||
|
||||
std::string _filename;
|
||||
WMO* _wmo;
|
||||
noggit::NoggitRenderContext _context;
|
||||
};
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
#include <opengl/primitives.hpp>
|
||||
#include <opengl/scoped.hpp>
|
||||
|
||||
WMOInstance::WMOInstance(std::string const& filename, ENTRY_MODF const* d)
|
||||
: wmo(filename)
|
||||
WMOInstance::WMOInstance(std::string const& filename, ENTRY_MODF const* d, noggit::NoggitRenderContext context)
|
||||
: wmo(filename, context)
|
||||
, pos(math::vector_3d(d->pos[0], d->pos[1], d->pos[2]))
|
||||
, dir(math::vector_3d(d->rot[0], d->rot[1], d->rot[2]))
|
||||
, mUniqueID(d->uniqueID), mFlags(d->flags)
|
||||
, mUnknown(d->unknown), mNameset(d->nameSet)
|
||||
, _doodadset(d->doodadSet)
|
||||
, _context(context)
|
||||
{
|
||||
extents[0] = math::vector_3d(d->extents[0][0], d->extents[0][1], d->extents[0][2]);
|
||||
extents[1] = math::vector_3d(d->extents[1][0], d->extents[1][1], d->extents[1][2]);
|
||||
@@ -25,8 +26,8 @@ WMOInstance::WMOInstance(std::string const& filename, ENTRY_MODF const* d)
|
||||
change_doodadset(_doodadset);
|
||||
}
|
||||
|
||||
WMOInstance::WMOInstance(std::string const& filename)
|
||||
: wmo(filename)
|
||||
WMOInstance::WMOInstance(std::string const& filename, noggit::NoggitRenderContext context)
|
||||
: wmo(filename, context)
|
||||
, pos(math::vector_3d(0.0f, 0.0f, 0.0f))
|
||||
, dir(math::vector_3d(0.0f, 0.0f, 0.0f))
|
||||
, mUniqueID(0)
|
||||
@@ -34,6 +35,7 @@ WMOInstance::WMOInstance(std::string const& filename)
|
||||
, mUnknown(0)
|
||||
, mNameset(0)
|
||||
, _doodadset(0)
|
||||
, _context(context)
|
||||
{
|
||||
change_doodadset(_doodadset);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <math/ray.hpp>
|
||||
#include <math/vector_3d.hpp> // math::vector_3d
|
||||
#include <noggit/WMO.h>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
@@ -30,7 +31,8 @@ public:
|
||||
|
||||
private:
|
||||
void update_doodads();
|
||||
|
||||
|
||||
noggit::NoggitRenderContext _context;
|
||||
uint16_t _doodadset;
|
||||
|
||||
std::map<uint32_t, std::vector<wmo_doodad_instance>> _doodads_per_group;
|
||||
@@ -41,8 +43,11 @@ private:
|
||||
math::matrix_4x4 _transform_mat_transposed = math::matrix_4x4::uninitialized;
|
||||
|
||||
public:
|
||||
WMOInstance(std::string const& filename, ENTRY_MODF const* d);
|
||||
explicit WMOInstance(std::string const& filename);
|
||||
WMOInstance(std::string const& filename, ENTRY_MODF const* d
|
||||
, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
explicit WMOInstance(std::string const& filename
|
||||
, noggit::NoggitRenderContext context = noggit::NoggitRenderContext::MAP_VIEW);
|
||||
|
||||
WMOInstance(WMOInstance const& other) = default;
|
||||
WMOInstance& operator=(WMOInstance const& other) = default;
|
||||
@@ -62,6 +67,7 @@ public:
|
||||
, _transform_mat(other._transform_mat)
|
||||
, _transform_mat_inverted(other._transform_mat_inverted)
|
||||
, _transform_mat_transposed(other._transform_mat_transposed)
|
||||
, _context(other._context)
|
||||
{
|
||||
std::swap (extents, other.extents);
|
||||
}
|
||||
@@ -83,6 +89,7 @@ public:
|
||||
std::swap(_transform_mat, other._transform_mat);
|
||||
std::swap(_transform_mat_inverted, other._transform_mat_inverted);
|
||||
std::swap(_transform_mat_transposed, other._transform_mat_transposed);
|
||||
std::swap(_context, other._context);
|
||||
return *this;
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -91,6 +91,11 @@ namespace noggit
|
||||
position += direction() * sign * move_speed * dt;
|
||||
}
|
||||
|
||||
void camera::move_forward_factor (float sign, float factor)
|
||||
{
|
||||
position += direction() * sign * factor;
|
||||
}
|
||||
|
||||
void camera::move_horizontal (float sign, float dt)
|
||||
{
|
||||
math::vector_3d const up (0.0f, 1.0f, 0.0f);
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace noggit
|
||||
void move_horizontal (float sign, float dt);
|
||||
void move_vertical (float sign, float dt);
|
||||
|
||||
void move_forward_factor (float sign, float factor);
|
||||
|
||||
math::vector_3d position;
|
||||
float move_speed;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <noggit/AsyncLoader.h>
|
||||
#include <noggit/AsyncObject.h>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <noggit/Log.h>
|
||||
#include <noggit/MPQ.h>
|
||||
|
||||
@@ -13,11 +14,26 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
struct pair_hash
|
||||
{
|
||||
template <class T1, class T2>
|
||||
std::size_t operator() (const std::pair<T1,T2> &p) const
|
||||
{
|
||||
auto h1 = std::hash<T1>{}(p.first);
|
||||
auto h2 = std::hash<T2>{}(p.second);
|
||||
|
||||
return h1 ^ h2; // use hash combine here
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct async_object_multimap_with_normalized_key
|
||||
struct async_object_multimap_with_normalized_key
|
||||
{
|
||||
async_object_multimap_with_normalized_key (std::function<std::string (std::string)> normalize = &mpq::normalized_filename)
|
||||
: _normalize (std::move (normalize))
|
||||
@@ -25,24 +41,29 @@ namespace noggit
|
||||
|
||||
~async_object_multimap_with_normalized_key()
|
||||
{
|
||||
/*
|
||||
apply ( [&] (std::string const& key, T const&)
|
||||
{
|
||||
LogDebug << key << ": " << _counts.at (key) << std::endl;
|
||||
auto pair = std::make_pair(context, key);
|
||||
LogDebug << key << ": " << _counts.at(pair) << std::endl;
|
||||
}
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
T* emplace (std::string const& filename, Args&&... args)
|
||||
T* emplace (std::string const& filename, noggit::NoggitRenderContext context, Args&&... args)
|
||||
{
|
||||
std::string const normalized (_normalize (filename));
|
||||
auto pair = std::make_pair(context, normalized);
|
||||
//LogDebug << "Emplacing " << normalized << " into context" << context << std::endl;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock const lock(_mutex);
|
||||
|
||||
if ([&] { return _counts[normalized]++; }())
|
||||
if ([&] { return _counts[pair]++; }())
|
||||
{
|
||||
return &_elements.at (normalized);
|
||||
return &_elements.at (pair);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +72,8 @@ namespace noggit
|
||||
{
|
||||
boost::mutex::scoped_lock const lock(_mutex);
|
||||
return &_elements.emplace ( std::piecewise_construct
|
||||
, std::forward_as_tuple (normalized)
|
||||
, std::forward_as_tuple (normalized, args...)
|
||||
, std::forward_as_tuple (pair)
|
||||
, std::forward_as_tuple (normalized, context, args...)
|
||||
).first->second;
|
||||
}()
|
||||
);
|
||||
@@ -61,17 +82,20 @@ namespace noggit
|
||||
|
||||
return obj;
|
||||
}
|
||||
void erase (std::string const& filename)
|
||||
{
|
||||
void erase (std::string const& filename, noggit::NoggitRenderContext context)
|
||||
{
|
||||
std::string const normalized (_normalize (filename));
|
||||
auto pair = std::make_pair(context, normalized);
|
||||
//LogDebug << "Erasing " << normalized << " from context" << context << std::endl;
|
||||
|
||||
AsyncObject* obj = nullptr;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(_mutex);
|
||||
|
||||
if (--_counts.at (normalized) == 0)
|
||||
if (--_counts.at(pair) == 0)
|
||||
{
|
||||
obj = static_cast<AsyncObject*>(&_elements.at(normalized));
|
||||
obj = static_cast<AsyncObject*>(&_elements.at(pair));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,17 +109,18 @@ namespace noggit
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(_mutex);
|
||||
_elements.erase (normalized);
|
||||
_counts.erase (normalized);
|
||||
_elements.erase(pair);
|
||||
_counts.erase(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
void apply (std::function<void (std::string const&, T&)> fun)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(_mutex);
|
||||
|
||||
for (auto& element : _elements)
|
||||
{
|
||||
fun (element.first, element.second);
|
||||
fun (element.first.second, element.second);
|
||||
}
|
||||
}
|
||||
void apply (std::function<void (std::string const&, T const&)> fun) const
|
||||
@@ -103,14 +128,16 @@ namespace noggit
|
||||
boost::mutex::scoped_lock lock(_mutex);
|
||||
for (auto const& element : _elements)
|
||||
{
|
||||
fun (element.first, element.second);
|
||||
fun (element.first.second, element.second);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, T> _elements;
|
||||
std::unordered_map<std::string, std::size_t> _counts;
|
||||
std::map<std::pair<int, std::string>, T> _elements;
|
||||
std::unordered_map<std::pair<int, std::string>, std::size_t, pair_hash> _counts;
|
||||
std::function<std::string (std::string)> _normalize;
|
||||
boost::mutex _mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace opengl
|
||||
{
|
||||
errors += _extra_info();
|
||||
#ifndef NOGGIT_DO_NOT_THROW_ON_OPENGL_ERRORS
|
||||
LogError << _function << ":" + errors << std::endl;
|
||||
LogError << _function << ":" + errors << std::endl;
|
||||
#else
|
||||
throw std::runtime_error (_function + ":" + errors);
|
||||
#endif
|
||||
@@ -751,4 +751,9 @@ namespace opengl
|
||||
scoped::buffer_binder<GL_ELEMENT_ARRAY_BUFFER> const _ (index_buffer);
|
||||
return drawElements (mode, count, type, indices);
|
||||
}
|
||||
|
||||
QOpenGLContext* context::getCurrentContext()
|
||||
{
|
||||
return _current_context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +166,8 @@ namespace opengl
|
||||
void bufferData(GLuint buffer, std::vector<T> const& data, GLenum usage);
|
||||
|
||||
void drawElements (GLenum mode, GLuint index_buffer, GLsizei count, GLenum type, GLvoid const* indices);
|
||||
|
||||
QOpenGLContext* getCurrentContext();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user