Rewritten CModelMesh to use separate vertex attributes

dev
Tomasz Kapuściński 2022-11-12 18:52:21 +01:00
parent 3805851255
commit e3ba33a508
18 changed files with 512 additions and 158 deletions

View File

@ -4883,7 +4883,10 @@ int CEngine::AddStaticMesh(const std::string& key, const CModelMesh* mesh, const
{
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;
}

View File

@ -48,7 +48,7 @@ COldModelManager::~COldModelManager()
bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int team)
{
CModel model;
std::unique_ptr<CModel> model;
try
{
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());
ModelInput::Read(model, "models/" + name);
model = ModelInput::Read("models/" + name);
if (model.GetMeshCount() == 0)
if (model->GetMeshCount() == 0)
return false;
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());
ModelInput::Read(model, gltf_path);
model = ModelInput::Read(gltf_path);
if (model.GetMeshCount() > 0)
if (model->GetMeshCount() > 0)
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());
ModelInput::Read(model, mod_path);
model = ModelInput::Read(mod_path);
if (model.GetMeshCount() > 0)
if (model->GetMeshCount() > 0)
goto skip;
}
@ -98,7 +98,7 @@ bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int tea
}
skip:
CModelMesh* mesh = model.GetMesh();
CModelMesh* mesh = model->GetMesh();
assert(mesh != nullptr);
ModelInfo modelInfo;

View File

@ -34,7 +34,7 @@ CModelMesh* CModel::GetMesh()
{
if (m_meshes.size() == 1)
{
return &m_meshes.begin()->second;
return m_meshes.begin()->second.get();
}
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());
return nullptr;
}
return &(it->second);
return it->second.get();
}
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());
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

View File

@ -26,9 +26,10 @@
#include "math/sphere.h"
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include <optional>
namespace Gfx
{
@ -49,7 +50,7 @@ public:
//! Return a mesh with given \a name
const CModelMesh* GetMesh(const std::string& name) const;
//! 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
std::vector<std::string> GetMeshNames() const;
@ -75,7 +76,7 @@ public:
bool HasCameraCollisionSphere() const;
private:
std::map<std::string, CModelMesh> m_meshes;
std::map<std::string, std::unique_ptr<CModelMesh>> m_meshes;
std::vector<ModelCrashSphere> m_crashSpheres;
std::optional<ModelShadowSpot> m_shadowSpot;
std::optional<Math::Sphere> m_cameraCollisionSphere;

View File

@ -71,12 +71,7 @@ struct Sampler
class GLTFLoader
{
public:
void Load(const std::filesystem::path& path);
CModel GetModel()
{
return m_model;
}
std::unique_ptr<CModel> Load(const std::filesystem::path& path);
private:
void ReadBuffers();
@ -94,7 +89,7 @@ private:
std::vector<glm::u8vec4> ReadColors(int index);
std::vector<unsigned> ReadIndices(int index);
CModel m_model;
std::unique_ptr<CModel> m_model;
std::filesystem::path m_directory;
json m_root;
@ -108,16 +103,14 @@ private:
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;
loader.Load(path);
model = loader.GetModel();
return loader.Load(path);
}
void GLTFLoader::Load(const std::filesystem::path& path)
std::unique_ptr<CModel> GLTFLoader::Load(const std::filesystem::path& path)
{
m_directory = path.parent_path();
@ -125,6 +118,8 @@ void GLTFLoader::Load(const std::filesystem::path& path)
stream >> m_root;
m_model = std::make_unique<CModel>();
ReadBuffers();
ReadBufferViews();
ReadAccessors();
@ -133,6 +128,8 @@ void GLTFLoader::Load(const std::filesystem::path& path)
ReadTextures();
ReadMaterials();
ReadMeshes();
return std::move(m_model);
}
void GLTFLoader::ReadBuffers()
@ -470,13 +467,13 @@ void GLTFLoader::ReadMeshes()
{
auto name = node["name"].get<std::string>();
CModelMesh mesh;
auto mesh = std::make_unique<CModelMesh>();
for (const auto& primitive : node["primitives"])
{
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> normals;
@ -565,15 +562,15 @@ void GLTFLoader::ReadMeshes()
}
for (const auto& vertex : vertices)
part.AddVertex(vertex);
part->AddVertex(vertex);
for (const auto& index : indices)
part.AddIndex(index);
part->AddIndex(index);
}
}
if (mesh.GetPartCount() > 0)
m_model.AddMesh(name, std::move(mesh));
if (mesh->GetPartCount() > 0)
m_model->AddMesh(name, std::move(mesh));
}
}

View File

@ -31,6 +31,6 @@
namespace Gfx::ModelIO
{
void ReadGLTFModel(CModel& model, const std::filesystem::path& path);
std::unique_ptr<CModel> ReadGLTFModel(const std::filesystem::path& path);
}

View File

@ -28,21 +28,21 @@
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();
if (extension == ".mod")
{
ModelIO::ReadOldModel(model, path);
return ModelIO::ReadOldModel(path);
}
else if (extension == ".txt")
{
ModelIO::ReadTextModel(model, path);
return ModelIO::ReadTextModel(path);
}
else if (extension == ".gltf")
{
ModelIO::ReadGLTFModel(model, path);
return ModelIO::ReadGLTFModel(path);
}
else
{

View File

@ -33,7 +33,7 @@ namespace Gfx
*/
namespace ModelInput
{
void Read(CModel& model, const std::filesystem::path& path);
std::unique_ptr<CModel> Read(const std::filesystem::path& path);
}
} // namespace Gfx

View File

@ -29,21 +29,19 @@
namespace Gfx
{
CModel& CModelManager::GetModel(const std::string& modelName)
CModel* CModelManager::GetModel(const std::string& modelName)
{
auto it = m_models.find(modelName);
if (it != m_models.end())
return it->second;
return it->second.get();
std::filesystem::path modelFile = "models-new/" + modelName + ".txt";
GetLogger()->Debug("Loading new model: %s\n", modelFile.c_str());
CModel model;
ModelInput::Read(model, modelFile);
m_models[modelName] = model;
m_models[modelName] = ModelInput::Read(modelFile);
return m_models[modelName];
return m_models[modelName].get();
}
void CModelManager::ClearCache()

View File

@ -21,6 +21,7 @@
#include "graphics/model/model.h"
#include <memory>
#include <string>
#include <unordered_map>
@ -36,13 +37,13 @@ class CModelManager
public:
//! Returns a model named \a modelName
/** @throws CModelIOException on read error */
CModel& GetModel(const std::string& modelName);
CModel* GetModel(const std::string& modelName);
//! Clears cached models
void ClearCache();
private:
std::unordered_map<std::string, CModel> m_models;
std::unordered_map<std::string, std::unique_ptr<CModel>> m_models;
};
} // namespace Gfx

View File

@ -19,94 +19,350 @@
#include "graphics/model/model_mesh.h"
#include <array>
namespace Gfx
{
CModelPart::CModelPart(const Material& material)
: m_material(material) {}
CVertexProxy::CVertexProxy(CModelPart* part, size_t index)
: 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
{
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
{
return !m_indices.empty();
return m_indices.enabled;
}
size_t CModelPart::GetVertexCount() const
{
return m_vertices.size();
}
const std::vector<Vertex3D>& CModelPart::GetVertices() const
{
return m_vertices;
return m_positions.array.size();
}
size_t CModelPart::GetIndexCount() const
{
return m_indices.size();
return m_indices.array.size();
}
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)
{
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)
{
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)
{
for (auto& part : m_parts)
{
if (part.GetMaterial() == triangle.material)
if (part->GetMaterial() == triangle.material)
{
part.AddVertex(triangle.p1);
part.AddVertex(triangle.p2);
part.AddVertex(triangle.p3);
part->AddVertex(triangle.p1);
part->AddVertex(triangle.p2);
part->AddVertex(triangle.p3);
return;
}
}
CModelPart part(triangle.material);
auto part = std::make_unique<CModelPart>(triangle.material, 0, 0);
part.AddVertex(triangle.p1);
part.AddVertex(triangle.p2);
part.AddVertex(triangle.p3);
part->Add(VertexAttribute::COLOR);
part->Add(VertexAttribute::UV1);
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)
{
for (auto& part : m_parts)
{
if (part.GetMaterial() == material)
if (part->GetMaterial() == material)
{
part.AddVertex(triangle.p1);
part.AddVertex(triangle.p2);
part.AddVertex(triangle.p3);
part->AddVertex(triangle.p1);
part->AddVertex(triangle.p2);
part->AddVertex(triangle.p3);
return;
}
}
CModelPart part(material);
auto part = std::make_unique<CModelPart>(material, 0, 0);
part.AddVertex(triangle.p1);
part.AddVertex(triangle.p2);
part.AddVertex(triangle.p3);
part->Add(VertexAttribute::COLOR);
part->Add(VertexAttribute::UV1);
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
@ -114,24 +370,26 @@ size_t CModelMesh::GetPartCount() const
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)
{
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
@ -180,35 +438,7 @@ std::vector<ModelTriangle> CModelMesh::GetTriangles() const
for (const auto& part : m_parts)
{
if (part.IsIndexed())
{
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()
});
}
}
part->GetTriangles(triangles);
}
return triangles;

View File

@ -21,11 +21,91 @@
#include "graphics/model/model_triangle.h"
#include <memory>
#include <vector>
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
* \brief Part of mesh with a common material
@ -34,34 +114,70 @@ class CModelPart
{
public:
//! 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
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
bool IsIndexed() const;
//! Returns the number of vertices in this part
size_t GetVertexCount() const;
//! Returns the vertices in this part
const std::vector<Vertex3D>& GetVertices() const;
//! Returns the number of indices in this part
size_t GetIndexCount() const;
//! Returns the indices in this part
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
void AddVertex(const Vertex3D& vertex);
//! Adds an index
void AddIndex(unsigned int index);
//! Fills the array with converted model triangles
void GetTriangles(std::vector<Gfx::ModelTriangle>& triangles);
friend class CVertexProxy;
private:
//! 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
std::vector<unsigned int> m_indices;
VertexAttributeArray<std::uint32_t> m_indices;
};
/**
@ -79,9 +195,9 @@ public:
//! Returns the number of parts
size_t GetPartCount() const;
//! 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
CModelPart& AddPart(const Material& material);
CModelPart* AddPart(const Material& material);
//! Returns the mesh position
const glm::vec3& GetPosition() const;
@ -107,10 +223,10 @@ public:
std::vector<ModelTriangle> GetTriangles() const;
private:
std::vector<CModelPart> m_parts;
glm::vec3 m_position;
glm::vec3 m_rotation;
glm::vec3 m_scale;
std::vector<std::unique_ptr<CModelPart>> m_parts;
glm::vec3 m_position = { 0, 0, 0 };
glm::vec3 m_rotation = { 0, 0, 0 };
glm::vec3 m_scale = { 1, 1, 1 };
std::string m_parent;
};

View File

@ -47,7 +47,7 @@ void ConvertOldTex1Name(ModelTriangle& triangle, const char* tex1Name);
void ConvertFromOldRenderState(ModelTriangle& triangle, int state);
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);
@ -88,12 +88,16 @@ void ReadOldModel(CModel& model, const std::filesystem::path& path)
throw CModelIOException(std::string("Error reading model triangles: ") + e.what());
}
CModelMesh mesh;
auto mesh = std::make_unique<CModelMesh>();
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)

View File

@ -31,6 +31,6 @@
namespace Gfx::ModelIO
{
void ReadOldModel(CModel& model, const std::filesystem::path& path);
std::unique_ptr<CModel> ReadOldModel(const std::filesystem::path& path);
}

View File

@ -36,7 +36,7 @@ namespace Gfx::ModelIO
void ReadTextModelV1AndV2(CModel& model, std::istream& stream);
void ReadTextModelV3(CModel& model, 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);
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 ReadTextModel(CModel& model, const std::filesystem::path& path)
std::unique_ptr<CModel> ReadTextModel(const std::filesystem::path& 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());
}
auto model = std::make_unique<CModel>();
if (version == 1 || version == 2)
ReadTextModelV1AndV2(model, stream);
ReadTextModelV1AndV2(*model, stream);
else if (version == 3)
ReadTextModelV3(model, stream);
ReadTextModelV3(*model, stream);
else
throw CModelIOException(std::string("Unexpected version number: ") + boost::lexical_cast<std::string>(version));
return model;
}
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());
}
CModelMesh mesh;
auto mesh = std::make_unique<CModelMesh>();
for (int i = 0; i < header.totalTriangles; ++i)
{
@ -134,7 +138,7 @@ void ReadTextModelV1AndV2(CModel& model, std::istream& stream)
triangle.material.variableDetail = t.variableTex2;
ConvertFromOldRenderState(triangle, t.state);
mesh.AddTriangle(triangle);
mesh->AddTriangle(triangle);
}
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)
{
std::string meshName = ReadLineString(stream, "mesh");
CModelMesh mesh = ReadTextMesh(stream);
auto mesh = ReadTextMesh(stream);
model.AddMesh(meshName, std::move(mesh));
}
}
@ -190,14 +194,14 @@ ModelHeaderV3 ReadTextHeader(std::istream& stream)
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.SetRotation(ParseVector(ReadLineString(stream, "rotation")));
mesh.SetScale(ParseVector(ReadLineString(stream, "scale")));
mesh.SetParent(ReadLineString(stream, "parent"));
mesh->SetPosition(ParseVector(ReadLineString(stream, "position")));
mesh->SetRotation(ParseVector(ReadLineString(stream, "rotation")));
mesh->SetScale(ParseVector(ReadLineString(stream, "scale")));
mesh->SetParent(ReadLineString(stream, "parent"));
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)
t.material.alphaThreshold = 0.5f;
mesh.AddTriangle(t);
mesh->AddTriangle(t);
}
return mesh;

View File

@ -31,6 +31,6 @@
namespace Gfx::ModelIO
{
void ReadTextModel(CModel& model, const std::filesystem::path& path);
std::unique_ptr<CModel> ReadTextModel(const std::filesystem::path& path);
}

View File

@ -44,12 +44,12 @@ CStaticObject::CStaticObject(int id,
const std::string& key,
const glm::vec3& position,
float angleY,
const Gfx::CModel& model,
const Gfx::CModel* model,
Gfx::CEngine* engine)
: CObject(id, type)
, m_engine(engine)
{
const Gfx::CModelMesh* mesh = model.GetMesh("main");
const Gfx::CModelMesh* mesh = model->GetMesh("main");
assert(mesh != nullptr);
m_position = position;
@ -58,13 +58,13 @@ CStaticObject::CStaticObject(int id,
glm::mat4 worldMatrix = ComputeWorldMatrix(position, angleY);
m_meshHandle = m_engine->AddStaticMesh(key, mesh, worldMatrix);
if (model.HasShadowSpot())
m_engine->AddStaticMeshShadowSpot(m_meshHandle, model.GetShadowSpot());
if (model->HasShadowSpot())
m_engine->AddStaticMeshShadowSpot(m_meshHandle, model->GetShadowSpot());
SetCrashSpheres(model.GetCrashSpheres());
SetCrashSpheres(model->GetCrashSpheres());
if (model.HasCameraCollisionSphere())
SetCameraCollisionSphere(model.GetCameraCollisionSphere());
if (model->HasCameraCollisionSphere())
SetCameraCollisionSphere(model->GetCameraCollisionSphere());
}
CStaticObject::~CStaticObject()
@ -134,9 +134,9 @@ CStaticObjectUPtr CStaticObject::Create(int id,
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);
return std::make_unique<CStaticObject>(id, type, modelFile, adjustedPosition, angleY, model, engine);

View File

@ -45,7 +45,7 @@ public:
const std::string& key,
const glm::vec3& position,
float angleY,
const Gfx::CModel& model,
const Gfx::CModel* model,
Gfx::CEngine* engine);
virtual ~CStaticObject();