Rewritten CModelMesh to use separate vertex attributes
parent
3805851255
commit
e3ba33a508
|
@ -4883,7 +4883,10 @@ int CEngine::AddStaticMesh(const std::string& key, const CModelMesh* mesh, const
|
||||||
{
|
{
|
||||||
const auto& part = mesh->GetPart(i);
|
const auto& part = mesh->GetPart(i);
|
||||||
|
|
||||||
AddBaseObjTriangles(baseObjRank, part.GetVertices(), part.GetMaterial(), EngineTriangleType::TRIANGLES);
|
std::vector<Gfx::ModelTriangle> triangles;
|
||||||
|
part->GetTriangles(triangles);
|
||||||
|
|
||||||
|
AddBaseObjTriangles(baseObjRank, triangles);
|
||||||
}
|
}
|
||||||
m_staticMeshBaseObjects[key] = baseObjRank;
|
m_staticMeshBaseObjects[key] = baseObjRank;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ COldModelManager::~COldModelManager()
|
||||||
|
|
||||||
bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int team)
|
bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int team)
|
||||||
{
|
{
|
||||||
CModel model;
|
std::unique_ptr<CModel> model;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto extension = std::filesystem::path(name).extension().string();
|
auto extension = std::filesystem::path(name).extension().string();
|
||||||
|
@ -57,9 +57,9 @@ bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int tea
|
||||||
{
|
{
|
||||||
GetLogger()->Debug("Loading model '%s'\n", name.c_str());
|
GetLogger()->Debug("Loading model '%s'\n", name.c_str());
|
||||||
|
|
||||||
ModelInput::Read(model, "models/" + name);
|
model = ModelInput::Read("models/" + name);
|
||||||
|
|
||||||
if (model.GetMeshCount() == 0)
|
if (model->GetMeshCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
goto skip;
|
goto skip;
|
||||||
|
@ -71,9 +71,9 @@ bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int tea
|
||||||
{
|
{
|
||||||
GetLogger()->Debug("Loading model '%s'\n", (name + ".gltf").c_str());
|
GetLogger()->Debug("Loading model '%s'\n", (name + ".gltf").c_str());
|
||||||
|
|
||||||
ModelInput::Read(model, gltf_path);
|
model = ModelInput::Read(gltf_path);
|
||||||
|
|
||||||
if (model.GetMeshCount() > 0)
|
if (model->GetMeshCount() > 0)
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,9 +83,9 @@ bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int tea
|
||||||
{
|
{
|
||||||
GetLogger()->Debug("Loading model '%s'\n", (name + ".mod").c_str());
|
GetLogger()->Debug("Loading model '%s'\n", (name + ".mod").c_str());
|
||||||
|
|
||||||
ModelInput::Read(model, mod_path);
|
model = ModelInput::Read(mod_path);
|
||||||
|
|
||||||
if (model.GetMeshCount() > 0)
|
if (model->GetMeshCount() > 0)
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int tea
|
||||||
}
|
}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
CModelMesh* mesh = model.GetMesh();
|
CModelMesh* mesh = model->GetMesh();
|
||||||
assert(mesh != nullptr);
|
assert(mesh != nullptr);
|
||||||
|
|
||||||
ModelInfo modelInfo;
|
ModelInfo modelInfo;
|
||||||
|
|
|
@ -34,7 +34,7 @@ CModelMesh* CModel::GetMesh()
|
||||||
{
|
{
|
||||||
if (m_meshes.size() == 1)
|
if (m_meshes.size() == 1)
|
||||||
{
|
{
|
||||||
return &m_meshes.begin()->second;
|
return m_meshes.begin()->second.get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ CModelMesh* CModel::GetMesh(const std::string& name)
|
||||||
GetLogger()->Error("Mesh named '%s' not found in model!\n", name.c_str());
|
GetLogger()->Error("Mesh named '%s' not found in model!\n", name.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &(it->second);
|
return it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CModelMesh* CModel::GetMesh(const std::string& name) const
|
const CModelMesh* CModel::GetMesh(const std::string& name) const
|
||||||
|
@ -61,12 +61,12 @@ const CModelMesh* CModel::GetMesh(const std::string& name) const
|
||||||
GetLogger()->Error("Mesh named '%s' not found in model!\n", name.c_str());
|
GetLogger()->Error("Mesh named '%s' not found in model!\n", name.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &(it->second);
|
return it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModel::AddMesh(const std::string& name, CModelMesh&& mesh)
|
void CModel::AddMesh(const std::string& name, std::unique_ptr<CModelMesh> mesh)
|
||||||
{
|
{
|
||||||
m_meshes[name] = mesh;
|
m_meshes[name] = std::move(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> CModel::GetMeshNames() const
|
std::vector<std::string> CModel::GetMeshNames() const
|
||||||
|
|
|
@ -26,9 +26,10 @@
|
||||||
#include "math/sphere.h"
|
#include "math/sphere.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
@ -49,7 +50,7 @@ public:
|
||||||
//! Return a mesh with given \a name
|
//! Return a mesh with given \a name
|
||||||
const CModelMesh* GetMesh(const std::string& name) const;
|
const CModelMesh* GetMesh(const std::string& name) const;
|
||||||
//! Add new \a mesh with given \a name
|
//! Add new \a mesh with given \a name
|
||||||
void AddMesh(const std::string& name, CModelMesh&& mesh);
|
void AddMesh(const std::string& name, std::unique_ptr<CModelMesh> mesh);
|
||||||
//! Returns list of mesh names
|
//! Returns list of mesh names
|
||||||
std::vector<std::string> GetMeshNames() const;
|
std::vector<std::string> GetMeshNames() const;
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ public:
|
||||||
bool HasCameraCollisionSphere() const;
|
bool HasCameraCollisionSphere() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, CModelMesh> m_meshes;
|
std::map<std::string, std::unique_ptr<CModelMesh>> m_meshes;
|
||||||
std::vector<ModelCrashSphere> m_crashSpheres;
|
std::vector<ModelCrashSphere> m_crashSpheres;
|
||||||
std::optional<ModelShadowSpot> m_shadowSpot;
|
std::optional<ModelShadowSpot> m_shadowSpot;
|
||||||
std::optional<Math::Sphere> m_cameraCollisionSphere;
|
std::optional<Math::Sphere> m_cameraCollisionSphere;
|
||||||
|
|
|
@ -71,12 +71,7 @@ struct Sampler
|
||||||
class GLTFLoader
|
class GLTFLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Load(const std::filesystem::path& path);
|
std::unique_ptr<CModel> Load(const std::filesystem::path& path);
|
||||||
|
|
||||||
CModel GetModel()
|
|
||||||
{
|
|
||||||
return m_model;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadBuffers();
|
void ReadBuffers();
|
||||||
|
@ -94,7 +89,7 @@ private:
|
||||||
std::vector<glm::u8vec4> ReadColors(int index);
|
std::vector<glm::u8vec4> ReadColors(int index);
|
||||||
std::vector<unsigned> ReadIndices(int index);
|
std::vector<unsigned> ReadIndices(int index);
|
||||||
|
|
||||||
CModel m_model;
|
std::unique_ptr<CModel> m_model;
|
||||||
|
|
||||||
std::filesystem::path m_directory;
|
std::filesystem::path m_directory;
|
||||||
json m_root;
|
json m_root;
|
||||||
|
@ -108,16 +103,14 @@ private:
|
||||||
std::vector<Sampler> m_samplers;
|
std::vector<Sampler> m_samplers;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ReadGLTFModel(CModel& model, const std::filesystem::path& path)
|
std::unique_ptr<CModel> ReadGLTFModel(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
GLTFLoader loader;
|
GLTFLoader loader;
|
||||||
|
|
||||||
loader.Load(path);
|
return loader.Load(path);
|
||||||
|
|
||||||
model = loader.GetModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTFLoader::Load(const std::filesystem::path& path)
|
std::unique_ptr<CModel> GLTFLoader::Load(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
m_directory = path.parent_path();
|
m_directory = path.parent_path();
|
||||||
|
|
||||||
|
@ -125,6 +118,8 @@ void GLTFLoader::Load(const std::filesystem::path& path)
|
||||||
|
|
||||||
stream >> m_root;
|
stream >> m_root;
|
||||||
|
|
||||||
|
m_model = std::make_unique<CModel>();
|
||||||
|
|
||||||
ReadBuffers();
|
ReadBuffers();
|
||||||
ReadBufferViews();
|
ReadBufferViews();
|
||||||
ReadAccessors();
|
ReadAccessors();
|
||||||
|
@ -133,6 +128,8 @@ void GLTFLoader::Load(const std::filesystem::path& path)
|
||||||
ReadTextures();
|
ReadTextures();
|
||||||
ReadMaterials();
|
ReadMaterials();
|
||||||
ReadMeshes();
|
ReadMeshes();
|
||||||
|
|
||||||
|
return std::move(m_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTFLoader::ReadBuffers()
|
void GLTFLoader::ReadBuffers()
|
||||||
|
@ -470,13 +467,13 @@ void GLTFLoader::ReadMeshes()
|
||||||
{
|
{
|
||||||
auto name = node["name"].get<std::string>();
|
auto name = node["name"].get<std::string>();
|
||||||
|
|
||||||
CModelMesh mesh;
|
auto mesh = std::make_unique<CModelMesh>();
|
||||||
|
|
||||||
for (const auto& primitive : node["primitives"])
|
for (const auto& primitive : node["primitives"])
|
||||||
{
|
{
|
||||||
const auto& material = m_materials[primitive["material"].get<int>()];
|
const auto& material = m_materials[primitive["material"].get<int>()];
|
||||||
|
|
||||||
auto& part = mesh.AddPart(material);
|
auto part = mesh->AddPart(material);
|
||||||
|
|
||||||
std::vector<glm::vec3> positions;
|
std::vector<glm::vec3> positions;
|
||||||
std::vector<glm::vec3> normals;
|
std::vector<glm::vec3> normals;
|
||||||
|
@ -565,15 +562,15 @@ void GLTFLoader::ReadMeshes()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& vertex : vertices)
|
for (const auto& vertex : vertices)
|
||||||
part.AddVertex(vertex);
|
part->AddVertex(vertex);
|
||||||
|
|
||||||
for (const auto& index : indices)
|
for (const auto& index : indices)
|
||||||
part.AddIndex(index);
|
part->AddIndex(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.GetPartCount() > 0)
|
if (mesh->GetPartCount() > 0)
|
||||||
m_model.AddMesh(name, std::move(mesh));
|
m_model->AddMesh(name, std::move(mesh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,6 @@
|
||||||
namespace Gfx::ModelIO
|
namespace Gfx::ModelIO
|
||||||
{
|
{
|
||||||
|
|
||||||
void ReadGLTFModel(CModel& model, const std::filesystem::path& path);
|
std::unique_ptr<CModel> ReadGLTFModel(const std::filesystem::path& path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,21 +28,21 @@
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
void ModelInput::Read(CModel& model, const std::filesystem::path& path)
|
std::unique_ptr<CModel> ModelInput::Read(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
auto extension = path.extension();
|
auto extension = path.extension();
|
||||||
|
|
||||||
if (extension == ".mod")
|
if (extension == ".mod")
|
||||||
{
|
{
|
||||||
ModelIO::ReadOldModel(model, path);
|
return ModelIO::ReadOldModel(path);
|
||||||
}
|
}
|
||||||
else if (extension == ".txt")
|
else if (extension == ".txt")
|
||||||
{
|
{
|
||||||
ModelIO::ReadTextModel(model, path);
|
return ModelIO::ReadTextModel(path);
|
||||||
}
|
}
|
||||||
else if (extension == ".gltf")
|
else if (extension == ".gltf")
|
||||||
{
|
{
|
||||||
ModelIO::ReadGLTFModel(model, path);
|
return ModelIO::ReadGLTFModel(path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Gfx
|
||||||
*/
|
*/
|
||||||
namespace ModelInput
|
namespace ModelInput
|
||||||
{
|
{
|
||||||
void Read(CModel& model, const std::filesystem::path& path);
|
std::unique_ptr<CModel> Read(const std::filesystem::path& path);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Gfx
|
} // namespace Gfx
|
||||||
|
|
|
@ -29,21 +29,19 @@
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
CModel& CModelManager::GetModel(const std::string& modelName)
|
CModel* CModelManager::GetModel(const std::string& modelName)
|
||||||
{
|
{
|
||||||
auto it = m_models.find(modelName);
|
auto it = m_models.find(modelName);
|
||||||
if (it != m_models.end())
|
if (it != m_models.end())
|
||||||
return it->second;
|
return it->second.get();
|
||||||
|
|
||||||
std::filesystem::path modelFile = "models-new/" + modelName + ".txt";
|
std::filesystem::path modelFile = "models-new/" + modelName + ".txt";
|
||||||
|
|
||||||
GetLogger()->Debug("Loading new model: %s\n", modelFile.c_str());
|
GetLogger()->Debug("Loading new model: %s\n", modelFile.c_str());
|
||||||
|
|
||||||
CModel model;
|
m_models[modelName] = ModelInput::Read(modelFile);
|
||||||
ModelInput::Read(model, modelFile);
|
|
||||||
m_models[modelName] = model;
|
|
||||||
|
|
||||||
return m_models[modelName];
|
return m_models[modelName].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelManager::ClearCache()
|
void CModelManager::ClearCache()
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "graphics/model/model.h"
|
#include "graphics/model/model.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
@ -36,13 +37,13 @@ class CModelManager
|
||||||
public:
|
public:
|
||||||
//! Returns a model named \a modelName
|
//! Returns a model named \a modelName
|
||||||
/** @throws CModelIOException on read error */
|
/** @throws CModelIOException on read error */
|
||||||
CModel& GetModel(const std::string& modelName);
|
CModel* GetModel(const std::string& modelName);
|
||||||
|
|
||||||
//! Clears cached models
|
//! Clears cached models
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, CModel> m_models;
|
std::unordered_map<std::string, std::unique_ptr<CModel>> m_models;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Gfx
|
} // namespace Gfx
|
||||||
|
|
|
@ -19,94 +19,350 @@
|
||||||
|
|
||||||
#include "graphics/model/model_mesh.h"
|
#include "graphics/model/model_mesh.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
CModelPart::CModelPart(const Material& material)
|
CVertexProxy::CVertexProxy(CModelPart* part, size_t index)
|
||||||
: m_material(material) {}
|
: m_part(part), m_index(index)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& CVertexProxy::GetPosition() const
|
||||||
|
{
|
||||||
|
return m_part->m_positions.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetPosition(const glm::vec3& position) const
|
||||||
|
{
|
||||||
|
m_part->m_positions.array[m_index] = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::u8vec4& CVertexProxy::GetColor() const
|
||||||
|
{
|
||||||
|
return m_part->m_colors.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetColor(const glm::u8vec4& color) const
|
||||||
|
{
|
||||||
|
m_part->m_colors.array[m_index] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec2& CVertexProxy::GetUV1() const
|
||||||
|
{
|
||||||
|
return m_part->m_uvs1.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetUV1(const glm::vec2& uv) const
|
||||||
|
{
|
||||||
|
m_part->m_uvs1.array[m_index] = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec2& CVertexProxy::GetUV2() const
|
||||||
|
{
|
||||||
|
return m_part->m_uvs2.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetUV2(const glm::vec2& uv) const
|
||||||
|
{
|
||||||
|
m_part->m_uvs2.array[m_index] = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& CVertexProxy::GetNormal() const
|
||||||
|
{
|
||||||
|
return m_part->m_normals.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetNormal(const glm::vec3& normal) const
|
||||||
|
{
|
||||||
|
m_part->m_normals.array[m_index] = normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec4& CVertexProxy::GetTangent() const
|
||||||
|
{
|
||||||
|
return m_part->m_tangents.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetTangent(const glm::vec4& tangent) const
|
||||||
|
{
|
||||||
|
m_part->m_tangents.array[m_index] = tangent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::u8vec4& CVertexProxy::GetBoneIndices() const
|
||||||
|
{
|
||||||
|
return m_part->m_boneIndices.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetBoneIndices(const glm::u8vec4& indices) const
|
||||||
|
{
|
||||||
|
m_part->m_boneIndices.array[m_index] = indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec4& CVertexProxy::GetBoneWeights() const
|
||||||
|
{
|
||||||
|
return m_part->m_boneWeights.array[m_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVertexProxy::SetBoneWeights(const glm::vec4& weights) const
|
||||||
|
{
|
||||||
|
m_part->m_boneWeights.array[m_index] = weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CModelPart::CModelPart(const Material& material, size_t vertices, size_t indices)
|
||||||
|
: m_material(material) {
|
||||||
|
m_positions.array.resize(vertices);
|
||||||
|
m_indices.array.resize(indices);
|
||||||
|
}
|
||||||
|
|
||||||
const Material& CModelPart::GetMaterial() const
|
const Material& CModelPart::GetMaterial() const
|
||||||
{
|
{
|
||||||
return m_material;
|
return m_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CModelPart::SetVertices(size_t count)
|
||||||
|
{
|
||||||
|
m_positions.array.resize(count);
|
||||||
|
|
||||||
|
if (m_colors.enabled) m_colors.array.resize(count);
|
||||||
|
if (m_uvs1.enabled) m_uvs1.array.resize(count);
|
||||||
|
if (m_uvs2.enabled) m_uvs2.array.resize(count);
|
||||||
|
if (m_normals.enabled) m_normals.array.resize(count);
|
||||||
|
if (m_tangents.enabled) m_tangents.array.resize(count);
|
||||||
|
if (m_boneIndices.enabled) m_boneIndices.array.resize(count);
|
||||||
|
if (m_boneWeights.enabled) m_boneWeights.array.resize(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelPart::SetIndices(size_t count)
|
||||||
|
{
|
||||||
|
m_indices.array.resize(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CModelPart::Has(VertexAttribute array) const
|
||||||
|
{
|
||||||
|
switch (array)
|
||||||
|
{
|
||||||
|
case VertexAttribute::POSITION:
|
||||||
|
return true;
|
||||||
|
case VertexAttribute::COLOR:
|
||||||
|
return m_colors.enabled;
|
||||||
|
case VertexAttribute::UV1:
|
||||||
|
return m_uvs1.enabled;
|
||||||
|
case VertexAttribute::UV2:
|
||||||
|
return m_uvs2.enabled;
|
||||||
|
case VertexAttribute::NORMAL:
|
||||||
|
return m_normals.enabled;
|
||||||
|
case VertexAttribute::TANGENT:
|
||||||
|
return m_tangents.enabled;
|
||||||
|
case VertexAttribute::BONE_INDICES:
|
||||||
|
return m_boneIndices.enabled;
|
||||||
|
case VertexAttribute::BONE_WEIGHTS:
|
||||||
|
return m_boneWeights.enabled;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelPart::Add(VertexAttribute attribute)
|
||||||
|
{
|
||||||
|
switch (attribute)
|
||||||
|
{
|
||||||
|
case VertexAttribute::COLOR:
|
||||||
|
m_colors.enabled = true;
|
||||||
|
m_colors.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::UV1:
|
||||||
|
m_uvs1.enabled = true;
|
||||||
|
m_uvs1.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::UV2:
|
||||||
|
m_uvs2.enabled = true;
|
||||||
|
m_uvs2.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::NORMAL:
|
||||||
|
m_normals.enabled = true;
|
||||||
|
m_normals.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::TANGENT:
|
||||||
|
m_tangents.enabled = true;
|
||||||
|
m_tangents.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::BONE_INDICES:
|
||||||
|
m_boneIndices.enabled = true;
|
||||||
|
m_boneIndices.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
case VertexAttribute::BONE_WEIGHTS:
|
||||||
|
m_boneWeights.enabled = true;
|
||||||
|
m_boneWeights.array.resize(m_positions.array.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelPart::Remove(VertexAttribute attribute)
|
||||||
|
{
|
||||||
|
switch (attribute)
|
||||||
|
{
|
||||||
|
case VertexAttribute::COLOR:
|
||||||
|
m_colors.enabled = false;
|
||||||
|
m_colors.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::UV1:
|
||||||
|
m_uvs1.enabled = false;
|
||||||
|
m_uvs1.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::UV2:
|
||||||
|
m_uvs2.enabled = false;
|
||||||
|
m_uvs2.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::NORMAL:
|
||||||
|
m_normals.enabled = false;
|
||||||
|
m_normals.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::TANGENT:
|
||||||
|
m_tangents.enabled = false;
|
||||||
|
m_tangents.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::BONE_INDICES:
|
||||||
|
m_boneIndices.enabled = false;
|
||||||
|
m_boneIndices.array.resize(0);
|
||||||
|
return;
|
||||||
|
case VertexAttribute::BONE_WEIGHTS:
|
||||||
|
m_boneWeights.enabled = false;
|
||||||
|
m_boneWeights.array.resize(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CModelPart::IsIndexed() const
|
bool CModelPart::IsIndexed() const
|
||||||
{
|
{
|
||||||
return !m_indices.empty();
|
return m_indices.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CModelPart::GetVertexCount() const
|
size_t CModelPart::GetVertexCount() const
|
||||||
{
|
{
|
||||||
return m_vertices.size();
|
return m_positions.array.size();
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<Vertex3D>& CModelPart::GetVertices() const
|
|
||||||
{
|
|
||||||
return m_vertices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CModelPart::GetIndexCount() const
|
size_t CModelPart::GetIndexCount() const
|
||||||
{
|
{
|
||||||
return m_indices.size();
|
return m_indices.array.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned int>& CModelPart::GetIndices() const
|
const std::vector<unsigned int>& CModelPart::GetIndices() const
|
||||||
{
|
{
|
||||||
return m_indices;
|
return m_indices.array;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVertexProxy CModelPart::GetVertex(size_t index)
|
||||||
|
{
|
||||||
|
return CVertexProxy(this, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t CModelPart::GetIndex(size_t index)
|
||||||
|
{
|
||||||
|
return m_indices.array[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelPart::AddVertex(const Vertex3D& vertex)
|
void CModelPart::AddVertex(const Vertex3D& vertex)
|
||||||
{
|
{
|
||||||
m_vertices.push_back(vertex);
|
m_positions.array.push_back(vertex.position);
|
||||||
|
|
||||||
|
if (m_colors.enabled) m_colors.array.push_back(vertex.color);
|
||||||
|
if (m_uvs1.enabled) m_uvs1.array.push_back(vertex.uv);
|
||||||
|
if (m_uvs2.enabled) m_uvs2.array.push_back(vertex.uv2);
|
||||||
|
if (m_normals.enabled) m_normals.array.push_back(vertex.normal);
|
||||||
|
if (m_tangents.enabled) m_tangents.array.push_back({ 1.0f, 0.0f, 0.0f, 1.0f });
|
||||||
|
if (m_boneIndices.enabled) m_boneIndices.array.push_back({ 0, 0, 0, 0 });
|
||||||
|
if (m_boneWeights.enabled) m_boneWeights.array.push_back({ 1.0f, 0.0f, 0.0f, 0.0f });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelPart::AddIndex(unsigned int index)
|
void CModelPart::AddIndex(unsigned int index)
|
||||||
{
|
{
|
||||||
m_indices.push_back(index);
|
if (m_indices.enabled) m_indices.array.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModelPart::GetTriangles(std::vector<Gfx::ModelTriangle>& triangles)
|
||||||
|
{
|
||||||
|
size_t n = IsIndexed()
|
||||||
|
? GetIndexCount()
|
||||||
|
: GetVertexCount();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n - 2; i += 3)
|
||||||
|
{
|
||||||
|
std::array<Gfx::Vertex3D, 3> verts;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
size_t index = IsIndexed()
|
||||||
|
? GetIndex(i + j)
|
||||||
|
: i + j;
|
||||||
|
auto vertex = GetVertex(index);
|
||||||
|
|
||||||
|
verts[j].position = vertex.GetPosition();
|
||||||
|
verts[j].color = vertex.GetColor();
|
||||||
|
verts[j].uv = vertex.GetUV1();
|
||||||
|
verts[j].uv2 = vertex.GetUV2();
|
||||||
|
verts[j].normal = vertex.GetNormal();
|
||||||
|
}
|
||||||
|
|
||||||
|
triangles.push_back({ verts[0], verts[1], verts[2], GetMaterial() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelMesh::AddTriangle(const ModelTriangle& triangle)
|
void CModelMesh::AddTriangle(const ModelTriangle& triangle)
|
||||||
{
|
{
|
||||||
for (auto& part : m_parts)
|
for (auto& part : m_parts)
|
||||||
{
|
{
|
||||||
if (part.GetMaterial() == triangle.material)
|
if (part->GetMaterial() == triangle.material)
|
||||||
{
|
{
|
||||||
part.AddVertex(triangle.p1);
|
part->AddVertex(triangle.p1);
|
||||||
part.AddVertex(triangle.p2);
|
part->AddVertex(triangle.p2);
|
||||||
part.AddVertex(triangle.p3);
|
part->AddVertex(triangle.p3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelPart part(triangle.material);
|
auto part = std::make_unique<CModelPart>(triangle.material, 0, 0);
|
||||||
|
|
||||||
part.AddVertex(triangle.p1);
|
part->Add(VertexAttribute::COLOR);
|
||||||
part.AddVertex(triangle.p2);
|
part->Add(VertexAttribute::UV1);
|
||||||
part.AddVertex(triangle.p3);
|
part->Add(VertexAttribute::UV2);
|
||||||
|
part->Add(VertexAttribute::NORMAL);
|
||||||
|
|
||||||
m_parts.emplace_back(part);
|
part->AddVertex(triangle.p1);
|
||||||
|
part->AddVertex(triangle.p2);
|
||||||
|
part->AddVertex(triangle.p3);
|
||||||
|
|
||||||
|
m_parts.push_back(std::move(part));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModelMesh::AddTriangle(const Triangle& triangle, const Material& material)
|
void CModelMesh::AddTriangle(const Triangle& triangle, const Material& material)
|
||||||
{
|
{
|
||||||
for (auto& part : m_parts)
|
for (auto& part : m_parts)
|
||||||
{
|
{
|
||||||
if (part.GetMaterial() == material)
|
if (part->GetMaterial() == material)
|
||||||
{
|
{
|
||||||
part.AddVertex(triangle.p1);
|
part->AddVertex(triangle.p1);
|
||||||
part.AddVertex(triangle.p2);
|
part->AddVertex(triangle.p2);
|
||||||
part.AddVertex(triangle.p3);
|
part->AddVertex(triangle.p3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelPart part(material);
|
auto part = std::make_unique<CModelPart>(material, 0, 0);
|
||||||
|
|
||||||
part.AddVertex(triangle.p1);
|
part->Add(VertexAttribute::COLOR);
|
||||||
part.AddVertex(triangle.p2);
|
part->Add(VertexAttribute::UV1);
|
||||||
part.AddVertex(triangle.p3);
|
part->Add(VertexAttribute::UV2);
|
||||||
|
part->Add(VertexAttribute::NORMAL);
|
||||||
|
|
||||||
m_parts.emplace_back(part);
|
part->AddVertex(triangle.p1);
|
||||||
|
part->AddVertex(triangle.p2);
|
||||||
|
part->AddVertex(triangle.p3);
|
||||||
|
|
||||||
|
m_parts.push_back(std::move(part));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CModelMesh::GetPartCount() const
|
size_t CModelMesh::GetPartCount() const
|
||||||
|
@ -114,24 +370,26 @@ size_t CModelMesh::GetPartCount() const
|
||||||
return m_parts.size();
|
return m_parts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CModelPart& CModelMesh::GetPart(size_t index) const
|
CModelPart* CModelMesh::GetPart(size_t index) const
|
||||||
{
|
{
|
||||||
return m_parts[index];
|
return m_parts[index].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelPart& CModelMesh::AddPart(const Material& material)
|
CModelPart* CModelMesh::AddPart(const Material& material)
|
||||||
{
|
{
|
||||||
for (auto& part : m_parts)
|
for (auto& part : m_parts)
|
||||||
{
|
{
|
||||||
if (part.GetMaterial() == material)
|
if (part->GetMaterial() == material)
|
||||||
{
|
{
|
||||||
return part;
|
return part.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_parts.push_back(CModelPart(material));
|
auto part = std::make_unique<CModelPart>(material, 0, 0);
|
||||||
|
|
||||||
return m_parts.back();
|
m_parts.push_back(std::move(part));
|
||||||
|
|
||||||
|
return m_parts.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::vec3& CModelMesh::GetPosition() const
|
const glm::vec3& CModelMesh::GetPosition() const
|
||||||
|
@ -180,35 +438,7 @@ std::vector<ModelTriangle> CModelMesh::GetTriangles() const
|
||||||
|
|
||||||
for (const auto& part : m_parts)
|
for (const auto& part : m_parts)
|
||||||
{
|
{
|
||||||
if (part.IsIndexed())
|
part->GetTriangles(triangles);
|
||||||
{
|
|
||||||
const auto& vertices = part.GetVertices();
|
|
||||||
const auto& indices = part.GetIndices();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < indices.size() - 2; i += 3)
|
|
||||||
{
|
|
||||||
triangles.push_back({
|
|
||||||
vertices[indices[i]],
|
|
||||||
vertices[indices[i + 1]],
|
|
||||||
vertices[indices[i + 2]],
|
|
||||||
part.GetMaterial()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto& vertices = part.GetVertices();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < vertices.size() - 2; i += 3)
|
|
||||||
{
|
|
||||||
triangles.push_back({
|
|
||||||
vertices[i],
|
|
||||||
vertices[i + 1],
|
|
||||||
vertices[i + 2],
|
|
||||||
part.GetMaterial()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return triangles;
|
return triangles;
|
||||||
|
|
|
@ -21,11 +21,91 @@
|
||||||
|
|
||||||
#include "graphics/model/model_triangle.h"
|
#include "graphics/model/model_triangle.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \enum VertexAttribute
|
||||||
|
* \brief An enum for vertex attributes
|
||||||
|
*/
|
||||||
|
enum class VertexAttribute
|
||||||
|
{
|
||||||
|
POSITION,
|
||||||
|
COLOR,
|
||||||
|
UV1,
|
||||||
|
UV2,
|
||||||
|
NORMAL,
|
||||||
|
TANGENT,
|
||||||
|
BONE_INDICES,
|
||||||
|
BONE_WEIGHTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
class CModelPart;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CVertexProxy
|
||||||
|
* \brief Proxy object for manipulating vertex data
|
||||||
|
*/
|
||||||
|
class CVertexProxy
|
||||||
|
{
|
||||||
|
CModelPart* m_part;
|
||||||
|
size_t m_index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CVertexProxy(CModelPart* part, size_t index);
|
||||||
|
|
||||||
|
//! Returns vertex position
|
||||||
|
const glm::vec3& GetPosition() const;
|
||||||
|
//! Sets vertex position
|
||||||
|
void SetPosition(const glm::vec3& position) const;
|
||||||
|
|
||||||
|
//! Returns vertex color
|
||||||
|
const glm::u8vec4& GetColor() const;
|
||||||
|
//! Sets vertex color
|
||||||
|
void SetColor(const glm::u8vec4& color) const;
|
||||||
|
|
||||||
|
//! Returns 1st UV
|
||||||
|
const glm::vec2& GetUV1() const;
|
||||||
|
//! Sets 1st UV
|
||||||
|
void SetUV1(const glm::vec2& uv) const;
|
||||||
|
|
||||||
|
//! Returns 2nd UV
|
||||||
|
const glm::vec2& GetUV2() const;
|
||||||
|
//! Sets 2nd UV
|
||||||
|
void SetUV2(const glm::vec2& uv) const;
|
||||||
|
|
||||||
|
//! Returns normal
|
||||||
|
const glm::vec3& GetNormal() const;
|
||||||
|
//! Sets normal
|
||||||
|
void SetNormal(const glm::vec3& normal) const;
|
||||||
|
|
||||||
|
//! Returns tangent
|
||||||
|
const glm::vec4& GetTangent() const;
|
||||||
|
//! Sets tangent
|
||||||
|
void SetTangent(const glm::vec4& tangent) const;
|
||||||
|
|
||||||
|
//! Returns bone indices
|
||||||
|
const glm::u8vec4& GetBoneIndices() const;
|
||||||
|
//! Sets bone indices
|
||||||
|
void SetBoneIndices(const glm::u8vec4& indices) const;
|
||||||
|
|
||||||
|
//! Returns bone weights
|
||||||
|
const glm::vec4& GetBoneWeights() const;
|
||||||
|
//! Sets bone weights
|
||||||
|
void SetBoneWeights(const glm::vec4& weights) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct VertexAttributeArray
|
||||||
|
{
|
||||||
|
bool enabled = false;
|
||||||
|
std::vector<T> array = {};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class CModelPart
|
* \class CModelPart
|
||||||
* \brief Part of mesh with a common material
|
* \brief Part of mesh with a common material
|
||||||
|
@ -34,34 +114,70 @@ class CModelPart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! Creates new part for given material
|
//! Creates new part for given material
|
||||||
CModelPart(const Material& material);
|
CModelPart(const Material& material, size_t vertices = 0, size_t indices = 0);
|
||||||
|
|
||||||
//! Returns this part's material
|
//! Returns this part's material
|
||||||
const Material& GetMaterial() const;
|
const Material& GetMaterial() const;
|
||||||
|
|
||||||
|
//! Sets the number of vertices
|
||||||
|
void SetVertices(size_t count);
|
||||||
|
//! Sets the number of indices
|
||||||
|
void SetIndices(size_t count);
|
||||||
|
|
||||||
|
//! Returns whether this mesh part contains specific vertex attribute
|
||||||
|
bool Has(VertexAttribute attribute) const;
|
||||||
|
//! Adds vertex attribute to this mesh part
|
||||||
|
void Add(VertexAttribute attribute);
|
||||||
|
//! Removes vertex attribute from this mesh part
|
||||||
|
void Remove(VertexAttribute attribute);
|
||||||
|
|
||||||
//! Returns true if this part is indexed
|
//! Returns true if this part is indexed
|
||||||
bool IsIndexed() const;
|
bool IsIndexed() const;
|
||||||
//! Returns the number of vertices in this part
|
//! Returns the number of vertices in this part
|
||||||
size_t GetVertexCount() const;
|
size_t GetVertexCount() const;
|
||||||
//! Returns the vertices in this part
|
|
||||||
const std::vector<Vertex3D>& GetVertices() const;
|
|
||||||
//! Returns the number of indices in this part
|
//! Returns the number of indices in this part
|
||||||
size_t GetIndexCount() const;
|
size_t GetIndexCount() const;
|
||||||
//! Returns the indices in this part
|
//! Returns the indices in this part
|
||||||
const std::vector<unsigned int>& GetIndices() const;
|
const std::vector<unsigned int>& GetIndices() const;
|
||||||
|
|
||||||
|
//! Returns vertex proxy object for manipulating vertex data
|
||||||
|
CVertexProxy GetVertex(size_t index);
|
||||||
|
//! Returns vertex index
|
||||||
|
std::uint32_t GetIndex(size_t index);
|
||||||
|
|
||||||
//! Adds a vertex
|
//! Adds a vertex
|
||||||
void AddVertex(const Vertex3D& vertex);
|
void AddVertex(const Vertex3D& vertex);
|
||||||
//! Adds an index
|
//! Adds an index
|
||||||
void AddIndex(unsigned int index);
|
void AddIndex(unsigned int index);
|
||||||
|
|
||||||
|
//! Fills the array with converted model triangles
|
||||||
|
void GetTriangles(std::vector<Gfx::ModelTriangle>& triangles);
|
||||||
|
|
||||||
|
friend class CVertexProxy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Material
|
//! Material
|
||||||
Material m_material;
|
Material m_material;
|
||||||
//! Vertices
|
|
||||||
std::vector<Vertex3D> m_vertices;
|
//! Positions
|
||||||
|
VertexAttributeArray<glm::vec3> m_positions;
|
||||||
|
//! Colors
|
||||||
|
VertexAttributeArray<glm::u8vec4> m_colors;
|
||||||
|
//! UVs 1
|
||||||
|
VertexAttributeArray<glm::vec2> m_uvs1;
|
||||||
|
//! UVs 2
|
||||||
|
VertexAttributeArray<glm::vec2> m_uvs2;
|
||||||
|
//! Normals
|
||||||
|
VertexAttributeArray<glm::vec3> m_normals;
|
||||||
|
//! Tangents
|
||||||
|
VertexAttributeArray<glm::vec4> m_tangents;
|
||||||
|
//! Bone indices
|
||||||
|
VertexAttributeArray<glm::u8vec4> m_boneIndices;
|
||||||
|
//! Bone weights
|
||||||
|
VertexAttributeArray<glm::vec4> m_boneWeights;
|
||||||
|
|
||||||
//! Indices
|
//! Indices
|
||||||
std::vector<unsigned int> m_indices;
|
VertexAttributeArray<std::uint32_t> m_indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,9 +195,9 @@ public:
|
||||||
//! Returns the number of parts
|
//! Returns the number of parts
|
||||||
size_t GetPartCount() const;
|
size_t GetPartCount() const;
|
||||||
//! Returns a part with given index
|
//! Returns a part with given index
|
||||||
const CModelPart& GetPart(size_t index) const;
|
CModelPart* GetPart(size_t index) const;
|
||||||
//! Adds a new part with given material or returns an existing one
|
//! Adds a new part with given material or returns an existing one
|
||||||
CModelPart& AddPart(const Material& material);
|
CModelPart* AddPart(const Material& material);
|
||||||
|
|
||||||
//! Returns the mesh position
|
//! Returns the mesh position
|
||||||
const glm::vec3& GetPosition() const;
|
const glm::vec3& GetPosition() const;
|
||||||
|
@ -107,10 +223,10 @@ public:
|
||||||
std::vector<ModelTriangle> GetTriangles() const;
|
std::vector<ModelTriangle> GetTriangles() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<CModelPart> m_parts;
|
std::vector<std::unique_ptr<CModelPart>> m_parts;
|
||||||
glm::vec3 m_position;
|
glm::vec3 m_position = { 0, 0, 0 };
|
||||||
glm::vec3 m_rotation;
|
glm::vec3 m_rotation = { 0, 0, 0 };
|
||||||
glm::vec3 m_scale;
|
glm::vec3 m_scale = { 1, 1, 1 };
|
||||||
std::string m_parent;
|
std::string m_parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ void ConvertOldTex1Name(ModelTriangle& triangle, const char* tex1Name);
|
||||||
void ConvertFromOldRenderState(ModelTriangle& triangle, int state);
|
void ConvertFromOldRenderState(ModelTriangle& triangle, int state);
|
||||||
ModelLODLevel MinMaxToLodLevel(float min, float max);
|
ModelLODLevel MinMaxToLodLevel(float min, float max);
|
||||||
|
|
||||||
void ReadOldModel(CModel& model, const std::filesystem::path& path)
|
std::unique_ptr<CModel> ReadOldModel(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
CInputStream stream(path);
|
CInputStream stream(path);
|
||||||
|
|
||||||
|
@ -88,12 +88,16 @@ void ReadOldModel(CModel& model, const std::filesystem::path& path)
|
||||||
throw CModelIOException(std::string("Error reading model triangles: ") + e.what());
|
throw CModelIOException(std::string("Error reading model triangles: ") + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelMesh mesh;
|
auto mesh = std::make_unique<CModelMesh>();
|
||||||
|
|
||||||
for (const auto& triangle : triangles)
|
for (const auto& triangle : triangles)
|
||||||
mesh.AddTriangle(triangle);
|
mesh->AddTriangle(triangle);
|
||||||
|
|
||||||
model.AddMesh("main", std::move(mesh));
|
auto model = std::make_unique<CModel>();
|
||||||
|
|
||||||
|
model->AddMesh("main", std::move(mesh));
|
||||||
|
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ModelTriangle> ReadOldModelV1(std::istream& stream, int totalTriangles)
|
std::vector<ModelTriangle> ReadOldModelV1(std::istream& stream, int totalTriangles)
|
||||||
|
|
|
@ -31,6 +31,6 @@
|
||||||
namespace Gfx::ModelIO
|
namespace Gfx::ModelIO
|
||||||
{
|
{
|
||||||
|
|
||||||
void ReadOldModel(CModel& model, const std::filesystem::path& path);
|
std::unique_ptr<CModel> ReadOldModel(const std::filesystem::path& path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Gfx::ModelIO
|
||||||
void ReadTextModelV1AndV2(CModel& model, std::istream& stream);
|
void ReadTextModelV1AndV2(CModel& model, std::istream& stream);
|
||||||
void ReadTextModelV3(CModel& model, std::istream& stream);
|
void ReadTextModelV3(CModel& model, std::istream& stream);
|
||||||
ModelHeaderV3 ReadTextHeader(std::istream& stream);
|
ModelHeaderV3 ReadTextHeader(std::istream& stream);
|
||||||
CModelMesh ReadTextMesh(std::istream& stream);
|
std::unique_ptr<CModelMesh> ReadTextMesh(std::istream& stream);
|
||||||
|
|
||||||
std::string ReadLineString(std::istream& stream, const std::string& expectedPrefix);
|
std::string ReadLineString(std::istream& stream, const std::string& expectedPrefix);
|
||||||
void ReadValuePrefix(std::istream& stream, const std::string& expectedPrefix);
|
void ReadValuePrefix(std::istream& stream, const std::string& expectedPrefix);
|
||||||
|
@ -51,7 +51,7 @@ std::string ParseSpecialMark(const std::string& text);
|
||||||
|
|
||||||
void ConvertFromOldRenderState(ModelTriangle& triangle, int state);
|
void ConvertFromOldRenderState(ModelTriangle& triangle, int state);
|
||||||
|
|
||||||
void ReadTextModel(CModel& model, const std::filesystem::path& path)
|
std::unique_ptr<CModel> ReadTextModel(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
CInputStream stream(path);
|
CInputStream stream(path);
|
||||||
|
|
||||||
|
@ -66,12 +66,16 @@ void ReadTextModel(CModel& model, const std::filesystem::path& path)
|
||||||
throw CModelIOException(std::string("Error reading version number: ") + e.what());
|
throw CModelIOException(std::string("Error reading version number: ") + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto model = std::make_unique<CModel>();
|
||||||
|
|
||||||
if (version == 1 || version == 2)
|
if (version == 1 || version == 2)
|
||||||
ReadTextModelV1AndV2(model, stream);
|
ReadTextModelV1AndV2(*model, stream);
|
||||||
else if (version == 3)
|
else if (version == 3)
|
||||||
ReadTextModelV3(model, stream);
|
ReadTextModelV3(*model, stream);
|
||||||
else
|
else
|
||||||
throw CModelIOException(std::string("Unexpected version number: ") + boost::lexical_cast<std::string>(version));
|
throw CModelIOException(std::string("Unexpected version number: ") + boost::lexical_cast<std::string>(version));
|
||||||
|
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadTextModelV1AndV2(CModel& model, std::istream& stream)
|
void ReadTextModelV1AndV2(CModel& model, std::istream& stream)
|
||||||
|
@ -88,7 +92,7 @@ void ReadTextModelV1AndV2(CModel& model, std::istream& stream)
|
||||||
throw CModelIOException(std::string("Error reading model header: ") + e.what());
|
throw CModelIOException(std::string("Error reading model header: ") + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelMesh mesh;
|
auto mesh = std::make_unique<CModelMesh>();
|
||||||
|
|
||||||
for (int i = 0; i < header.totalTriangles; ++i)
|
for (int i = 0; i < header.totalTriangles; ++i)
|
||||||
{
|
{
|
||||||
|
@ -134,7 +138,7 @@ void ReadTextModelV1AndV2(CModel& model, std::istream& stream)
|
||||||
triangle.material.variableDetail = t.variableTex2;
|
triangle.material.variableDetail = t.variableTex2;
|
||||||
ConvertFromOldRenderState(triangle, t.state);
|
ConvertFromOldRenderState(triangle, t.state);
|
||||||
|
|
||||||
mesh.AddTriangle(triangle);
|
mesh->AddTriangle(triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
model.AddMesh("main", std::move(mesh));
|
model.AddMesh("main", std::move(mesh));
|
||||||
|
@ -174,7 +178,7 @@ void ReadTextModelV3(CModel& model, std::istream& stream)
|
||||||
for (int i = 0; i < header.totalMeshes; ++i)
|
for (int i = 0; i < header.totalMeshes; ++i)
|
||||||
{
|
{
|
||||||
std::string meshName = ReadLineString(stream, "mesh");
|
std::string meshName = ReadLineString(stream, "mesh");
|
||||||
CModelMesh mesh = ReadTextMesh(stream);
|
auto mesh = ReadTextMesh(stream);
|
||||||
model.AddMesh(meshName, std::move(mesh));
|
model.AddMesh(meshName, std::move(mesh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,14 +194,14 @@ ModelHeaderV3 ReadTextHeader(std::istream& stream)
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
CModelMesh ReadTextMesh(std::istream& stream)
|
std::unique_ptr<CModelMesh> ReadTextMesh(std::istream& stream)
|
||||||
{
|
{
|
||||||
CModelMesh mesh;
|
auto mesh = std::make_unique<CModelMesh>();
|
||||||
|
|
||||||
mesh.SetPosition(ParseVector(ReadLineString(stream, "position")));
|
mesh->SetPosition(ParseVector(ReadLineString(stream, "position")));
|
||||||
mesh.SetRotation(ParseVector(ReadLineString(stream, "rotation")));
|
mesh->SetRotation(ParseVector(ReadLineString(stream, "rotation")));
|
||||||
mesh.SetScale(ParseVector(ReadLineString(stream, "scale")));
|
mesh->SetScale(ParseVector(ReadLineString(stream, "scale")));
|
||||||
mesh.SetParent(ReadLineString(stream, "parent"));
|
mesh->SetParent(ReadLineString(stream, "parent"));
|
||||||
|
|
||||||
int totalTriangles = boost::lexical_cast<int>(ReadLineString(stream, "total_triangles"));
|
int totalTriangles = boost::lexical_cast<int>(ReadLineString(stream, "total_triangles"));
|
||||||
|
|
||||||
|
@ -234,7 +238,7 @@ CModelMesh ReadTextMesh(std::istream& stream)
|
||||||
if (t.material.alphaMode != AlphaMode::NONE)
|
if (t.material.alphaMode != AlphaMode::NONE)
|
||||||
t.material.alphaThreshold = 0.5f;
|
t.material.alphaThreshold = 0.5f;
|
||||||
|
|
||||||
mesh.AddTriangle(t);
|
mesh->AddTriangle(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
|
|
|
@ -31,6 +31,6 @@
|
||||||
namespace Gfx::ModelIO
|
namespace Gfx::ModelIO
|
||||||
{
|
{
|
||||||
|
|
||||||
void ReadTextModel(CModel& model, const std::filesystem::path& path);
|
std::unique_ptr<CModel> ReadTextModel(const std::filesystem::path& path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,12 @@ CStaticObject::CStaticObject(int id,
|
||||||
const std::string& key,
|
const std::string& key,
|
||||||
const glm::vec3& position,
|
const glm::vec3& position,
|
||||||
float angleY,
|
float angleY,
|
||||||
const Gfx::CModel& model,
|
const Gfx::CModel* model,
|
||||||
Gfx::CEngine* engine)
|
Gfx::CEngine* engine)
|
||||||
: CObject(id, type)
|
: CObject(id, type)
|
||||||
, m_engine(engine)
|
, m_engine(engine)
|
||||||
{
|
{
|
||||||
const Gfx::CModelMesh* mesh = model.GetMesh("main");
|
const Gfx::CModelMesh* mesh = model->GetMesh("main");
|
||||||
assert(mesh != nullptr);
|
assert(mesh != nullptr);
|
||||||
|
|
||||||
m_position = position;
|
m_position = position;
|
||||||
|
@ -58,13 +58,13 @@ CStaticObject::CStaticObject(int id,
|
||||||
glm::mat4 worldMatrix = ComputeWorldMatrix(position, angleY);
|
glm::mat4 worldMatrix = ComputeWorldMatrix(position, angleY);
|
||||||
m_meshHandle = m_engine->AddStaticMesh(key, mesh, worldMatrix);
|
m_meshHandle = m_engine->AddStaticMesh(key, mesh, worldMatrix);
|
||||||
|
|
||||||
if (model.HasShadowSpot())
|
if (model->HasShadowSpot())
|
||||||
m_engine->AddStaticMeshShadowSpot(m_meshHandle, model.GetShadowSpot());
|
m_engine->AddStaticMeshShadowSpot(m_meshHandle, model->GetShadowSpot());
|
||||||
|
|
||||||
SetCrashSpheres(model.GetCrashSpheres());
|
SetCrashSpheres(model->GetCrashSpheres());
|
||||||
|
|
||||||
if (model.HasCameraCollisionSphere())
|
if (model->HasCameraCollisionSphere())
|
||||||
SetCameraCollisionSphere(model.GetCameraCollisionSphere());
|
SetCameraCollisionSphere(model->GetCameraCollisionSphere());
|
||||||
}
|
}
|
||||||
|
|
||||||
CStaticObject::~CStaticObject()
|
CStaticObject::~CStaticObject()
|
||||||
|
@ -134,9 +134,9 @@ CStaticObjectUPtr CStaticObject::Create(int id,
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Gfx::CModel& model = modelManager->GetModel(modelFile);
|
auto model = modelManager->GetModel(modelFile);
|
||||||
|
|
||||||
if (model.GetMeshCount() != 1 || model.GetMesh("main") == nullptr)
|
if (model->GetMeshCount() != 1 || model->GetMesh("main") == nullptr)
|
||||||
throw CObjectCreateException("Unexpected mesh configuration", type, modelFile);
|
throw CObjectCreateException("Unexpected mesh configuration", type, modelFile);
|
||||||
|
|
||||||
return std::make_unique<CStaticObject>(id, type, modelFile, adjustedPosition, angleY, model, engine);
|
return std::make_unique<CStaticObject>(id, type, modelFile, adjustedPosition, angleY, model, engine);
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
const std::string& key,
|
const std::string& key,
|
||||||
const glm::vec3& position,
|
const glm::vec3& position,
|
||||||
float angleY,
|
float angleY,
|
||||||
const Gfx::CModel& model,
|
const Gfx::CModel* model,
|
||||||
Gfx::CEngine* engine);
|
Gfx::CEngine* engine);
|
||||||
|
|
||||||
virtual ~CStaticObject();
|
virtual ~CStaticObject();
|
||||||
|
|
Loading…
Reference in New Issue