200 lines
5.7 KiB
C++
200 lines
5.7 KiB
C++
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
|
|
|
#pragma once
|
|
|
|
#include <noggit/AsyncObject.h>
|
|
#include <noggit/ContextObject.hpp>
|
|
#include <noggit/AsyncObjectMultimap.hpp>
|
|
#include <opengl/texture.hpp>
|
|
#include <opengl/context.hpp>
|
|
#include <opengl/context.inl>
|
|
#include <opengl/scoped.hpp>
|
|
#include <opengl/shader.hpp>
|
|
|
|
#include <QtGui/QOffscreenSurface>
|
|
#include <QtGui/QOpenGLFramebufferObjectFormat>
|
|
#include <QPainter>
|
|
#include <QtGui/QPixmap>
|
|
#include <optional>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <array>
|
|
#include <tuple>
|
|
|
|
|
|
struct texture_heightmapping_data
|
|
{
|
|
texture_heightmapping_data(uint32_t scale = 0, float heightscale = 0, float heightoffset = 1.0f)
|
|
{
|
|
uvScale = scale;
|
|
heightScale = heightscale;
|
|
heightOffset = heightoffset;
|
|
}
|
|
uint32_t uvScale = 0;
|
|
float heightScale = 0.0f;
|
|
float heightOffset = 1.0f;
|
|
};
|
|
|
|
struct tuple_hash
|
|
{
|
|
template <class T1, class T2, class T3, class T4>
|
|
std::size_t operator() (const std::tuple<T1,T2,T3,T4> &p) const
|
|
{
|
|
auto h1 = std::hash<T1>{}(std::get<0>(p));
|
|
auto h2 = std::hash<T2>{}(std::get<1>(p));
|
|
auto h3 = std::hash<T3>{}(std::get<2>(p));
|
|
auto h4 = std::hash<T4>{}(std::get<3>(p));
|
|
|
|
return h1 ^ h2 ^ h3 ^ h4; // use hash combine here
|
|
}
|
|
};
|
|
|
|
struct BLPHeader;
|
|
|
|
struct scoped_blp_texture_reference;
|
|
struct blp_texture : public AsyncObject
|
|
{
|
|
blp_texture (BlizzardArchive::Listfile::FileKey const& filename, Noggit::NoggitRenderContext context);
|
|
void finishLoading() override;
|
|
virtual void waitForChildrenLoaded() override {};
|
|
|
|
void loadFromUncompressedData(BLPHeader const* lHeader, char const* lData);
|
|
void loadFromCompressedData(BLPHeader const* lHeader, char const* lData);
|
|
|
|
int width() const { return _width; }
|
|
int height() const { return _height; }
|
|
|
|
void bind();
|
|
void upload();
|
|
void uploadToArray(unsigned layer);
|
|
void unload();
|
|
bool is_uploaded() { return _uploaded; };
|
|
GLuint texture_array() { return _texture_array; };
|
|
int array_index() { return _array_index; };
|
|
bool is_specular() { return _is_specular; };
|
|
unsigned mip_level() { return static_cast<unsigned>(!_compression_format ? _data.size() : _compressed_data.size()); };
|
|
|
|
std::map<int, std::vector<uint32_t>>& data() { return _data;};
|
|
std::map<int, std::vector<uint8_t>>& compressed_data() { return _compressed_data; };
|
|
std::optional<GLint> const& compression_format() { return _compression_format; };
|
|
|
|
Noggit::NoggitRenderContext getContext() { return _context; };
|
|
|
|
[[nodiscard]]
|
|
async_priority loading_priority() const override
|
|
{
|
|
return async_priority::high;
|
|
}
|
|
// Mists HeightMapping
|
|
bool hasHeightMap() {return _has_heightmap; };
|
|
|
|
blp_texture* getHeightMap() { return heightMap.get(); };
|
|
private:
|
|
bool _uploaded = false;
|
|
|
|
int _width;
|
|
int _height;
|
|
|
|
Noggit::NoggitRenderContext _context;
|
|
|
|
bool _is_specular = false;
|
|
bool _is_tileset = false;
|
|
bool _has_heightmap = false;
|
|
|
|
private:
|
|
std::map<int, std::vector<uint32_t>> _data;
|
|
std::map<int, std::vector<uint8_t>> _compressed_data;
|
|
std::optional<GLint> _compression_format;
|
|
int _array_index = -1;
|
|
GLuint _texture_array = 0;
|
|
|
|
std::unique_ptr<blp_texture> heightMap;
|
|
};
|
|
|
|
struct TexArrayParams
|
|
{
|
|
std::vector<GLuint> arrays;
|
|
int n_used = 0;
|
|
};
|
|
|
|
class TextureManager
|
|
{
|
|
public:
|
|
static void report();
|
|
static void unload_all(Noggit::NoggitRenderContext context);
|
|
static TexArrayParams& get_tex_array(int width, int height, int mip_level, Noggit::NoggitRenderContext context);
|
|
static TexArrayParams& get_tex_array(GLint compression, int width, int height, int mip_level, std::map<int, std::vector<uint8_t>>& comp_data, Noggit::NoggitRenderContext context);
|
|
|
|
private:
|
|
friend struct scoped_blp_texture_reference;
|
|
static Noggit::AsyncObjectMultimap<blp_texture> _;
|
|
static std::array<std::unordered_map<std::tuple<GLint, int, int, int>, TexArrayParams, tuple_hash>, Noggit::NoggitRenderContext::count> _tex_arrays;
|
|
|
|
};
|
|
|
|
struct scoped_blp_texture_reference
|
|
{
|
|
scoped_blp_texture_reference() = delete;
|
|
scoped_blp_texture_reference (std::string const& filename, Noggit::NoggitRenderContext context);
|
|
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;
|
|
scoped_blp_texture_reference& operator= (scoped_blp_texture_reference&&) = default;
|
|
~scoped_blp_texture_reference() = default;
|
|
|
|
blp_texture* operator->() const;
|
|
blp_texture* get() const;
|
|
|
|
bool operator== (scoped_blp_texture_reference const& other) const;
|
|
|
|
bool use_cubemap = false;
|
|
private:
|
|
struct Deleter
|
|
{
|
|
void operator() (blp_texture*) const;
|
|
};
|
|
std::unique_ptr<blp_texture, Deleter> _blp_texture;
|
|
Noggit::NoggitRenderContext _context;
|
|
};
|
|
|
|
namespace Noggit
|
|
{
|
|
|
|
class BLPRenderer
|
|
{
|
|
private:
|
|
BLPRenderer() = default;
|
|
|
|
BLPRenderer( const BLPRenderer&) = delete;
|
|
BLPRenderer& operator=( BLPRenderer& ) = delete;
|
|
|
|
std::map<std::tuple<std::string, int, int>, QPixmap> _cache;
|
|
|
|
std::unique_ptr<QOpenGLContext> _context;
|
|
std::unique_ptr<QOpenGLFramebufferObjectFormat> _fmt;
|
|
std::unique_ptr<QOffscreenSurface> _surface;
|
|
std::unique_ptr<OpenGL::program> _program;
|
|
|
|
OpenGL::Scoped::deferred_upload_vertex_arrays<1> _vao;
|
|
OpenGL::Scoped::deferred_upload_buffers<3> _buffers;
|
|
|
|
bool _uploaded = false;
|
|
|
|
public:
|
|
static BLPRenderer& getInstance()
|
|
{
|
|
static BLPRenderer instance;
|
|
return instance;
|
|
}
|
|
|
|
QPixmap* render_blp_to_pixmap ( std::string const& blp_filename, int width = -1, int height = -1);
|
|
void unload();
|
|
void upload();
|
|
|
|
};
|
|
|
|
|
|
}
|