diff --git a/include/Engine/Rendering/Model.h b/include/Engine/Rendering/Model.h index 4c63b922..f352ee3e 100644 --- a/include/Engine/Rendering/Model.h +++ b/include/Engine/Rendering/Model.h @@ -18,8 +18,14 @@ public: ~Model(); const std::vector& MaterialGroups() const { return m_RawModel->m_Materials; } const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; } - const RawModel::Vertex* Vertices() const { return m_RawModel->Vertices(); } - unsigned int NumberOfVertices() const { return m_RawModel->NumVertices(); } + + const RawModel::RenderVertex* Vertices() const { return m_RawModel->Vertices(); } + size_t NumberOfVertices() const { return m_RawModel->NumVertices(); } + const std::vector& Indices() const { return m_RawModel->Indices(); } + + const RawModel::Vertex* CollisionVertices() const { return m_RawModel->CollisionVertices(); } + const std::vector& CollisionIndices() const { return m_RawModel->CollisionIndices(); } + const AABB& Box() const { return m_Box; } bool IsSkinned() const { return m_RawModel->IsSkinned(); } GLuint VAO; diff --git a/include/Engine/Rendering/RawModelCustom.h b/include/Engine/Rendering/RawModelCustom.h index ebf8da2b..f38e0570 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -32,9 +32,11 @@ protected: public: ~RawModelCustom(); - - struct Vertex - { + struct Vertex { + glm::vec3 Position; + }; + + struct RenderVertex { glm::vec3 Position; glm::vec3 Normal; glm::vec3 Tangent; @@ -42,7 +44,7 @@ public: glm::vec2 TextureCoords; }; - struct SkinedVertex : public Vertex { + struct SkinedVertex : public RenderVertex { glm::vec4 BoneIndices; glm::vec4 BoneWeights; }; @@ -89,7 +91,7 @@ public: MaterialBasic* material; }; - const Vertex* Vertices() const { + const RenderVertex* Vertices() const { if (hasSkin) { return m_SkinedVertices.data(); } else { @@ -97,16 +99,16 @@ public: } }; - unsigned int VertexSize() const { + unsigned int VertexSize() const { if (hasSkin) { return sizeof(SkinedVertex); } else { - return sizeof(Vertex); + return sizeof(RenderVertex); } }; - unsigned int NumVertices() const { + size_t NumVertices() const { if (hasSkin) { return m_SkinedVertices.size(); } else { @@ -114,17 +116,39 @@ public: } }; + const std::vector& Indices() const { + return m_Indices; + } + bool IsSkinned() const { return hasSkin; }; + const Vertex* CollisionVertices(); + + size_t NumCollisionVertices() const { + return m_CollisionVertices.size(); + }; + + const std::vector& CollisionIndices() const { + if (hasCollisionMesh) { + return m_CollisionIndices; + } else { + return m_Indices; + } + }; + std::vector m_Materials; - std::vector m_Indices; + Skeleton* m_Skeleton = nullptr; glm::mat4 m_Matrix; private: bool hasSkin; - std::vector m_Vertices; + bool hasCollisionMesh = false; + std::vector m_Indices; + std::vector m_CollisionIndices; + std::vector m_CollisionVertices; + std::vector m_Vertices; std::vector m_SkinedVertices; void ReadMeshFile(std::string filePath); @@ -147,7 +171,12 @@ private: void ReadAnimationClips(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfClips); void ReadAnimationClipSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int clipIndex); void ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& animation); - + + + void ReadCollisionFile(std::string filePath); + void ReadCollisionFileData(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + + const Vertex* ConstructCollisionList(); //void CreateSkeleton(std::vector> &boneInfo, std::map &boneNameMapping, aiNode* node, int parentID); }; diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 7a5d2eb4..202cdfb6 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -13,8 +13,7 @@ - - + 5 diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 68d99d92..a8271818 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -150,6 +150,10 @@ bool RayVsModel(const Ray& ray, const std::vector& modelIndices, const glm::mat4& modelMatrix) { + if (!modelVertices) { + return false; + } + for (int i = 0; i < modelIndices.size();) { glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); @@ -201,6 +205,10 @@ bool RayVsModel(const Ray& ray, float& outUCoord, float& outVCoord) { + if (!modelVertices) { + return false; + } + outDistance = INFINITY; bool hit = false; for (int i = 0; i < modelIndices.size();) { @@ -226,6 +234,10 @@ bool RayVsModel(const Ray& ray, const glm::mat4& modelMatrix, glm::vec3& outHitPosition) { + if (!modelVertices) { + return false; + } + float u; float v; float dist; @@ -546,6 +558,10 @@ bool AABBvsTriangles(const AABB& box, glm::vec3& outResolutionVector, bool resolveCollision) { + if (!modelVertices) { + return false; + } + bool hit = false; bool everHitTheGround = false; @@ -705,7 +721,7 @@ boost::optional EntityFirstHitByRay(const Ray& ray, std::vectorVertices(), model->m_RawModel->m_Indices, Transform::ModelMatrix(entityBox.Entity), outDistance, u, v)) { + if (RayVsModel(ray, model->CollisionVertices(), model->CollisionIndices(), Transform::ModelMatrix(entityBox.Entity), outDistance, u, v)) { outIntersectPos = ray.Origin() + outDistance * ray.Direction(); return entityBox; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index fcc3665f..83876efa 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -44,7 +44,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } float u, v; - hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v); + hit = Collision::RayVsModel(ray, model->CollisionVertices(), model->CollisionIndices(), Transform::ModelMatrix(boxB.Entity), dist, u, v); } else { hit = Collision::RayVsAABB(ray, boxB, dist); } @@ -88,7 +88,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; - if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + if (Collision::AABBvsTriangles(boxA, model->CollisionVertices(), model->CollisionIndices(), modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = inOutVelocity; if (isOnGround) { diff --git a/src/Engine/Rendering/Model.cpp b/src/Engine/Rendering/Model.cpp index 3f8e20e1..affd5568 100644 --- a/src/Engine/Rendering/Model.cpp +++ b/src/Engine/Rendering/Model.cpp @@ -50,7 +50,7 @@ Model::Model(std::string fileName) glGenBuffers(1, &ElementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_RawModel->m_Indices.size() * sizeof(unsigned int), &m_RawModel->m_Indices[0], GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_RawModel->Indices().size() * sizeof(unsigned int), m_RawModel->Indices().data(), GL_STATIC_DRAW); glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index dd6a96de..f3b8f9c9 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -11,6 +11,7 @@ RawModelCustom::RawModelCustom(std::string fileName) ReadMeshFile(fileName); ReadMaterialFile(fileName); ReadAnimationFile(fileName); + ReadCollisionFile(fileName); } void RawModelCustom::ReadMeshFile(std::string filePath) @@ -71,11 +72,11 @@ void RawModelCustom::ReadVertices(std::size_t& offset, char* fileData, const uns memcpy(&m_SkinedVertices[0], fileData + offset, m_SkinedVertices.size() * sizeof(SkinedVertex)); offset += m_SkinedVertices.size() * sizeof(SkinedVertex); } else { - if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { + if (offset + m_Vertices.size() * sizeof(RenderVertex) > fileByteSize) { throw Resource::FailedLoadingException("Reading vertices failed"); } - memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); - offset += m_Vertices.size() * sizeof(Vertex); + memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(RenderVertex)); + offset += m_Vertices.size() * sizeof(RenderVertex); } #else #endif @@ -476,6 +477,84 @@ void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, } +void RawModelCustom::ReadCollisionFile(std::string filePath) { + char* fileData; + filePath += ".colli"; + std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate); + + if (!in.is_open()) { + return; + } + unsigned int fileByteSize = static_cast(in.tellg()); + in.seekg(0, std::ios_base::beg); + + fileData = new char[fileByteSize]; + in.read(fileData, fileByteSize); + in.close(); + + std::size_t offset = 0; + if (fileByteSize > 0) { + ReadCollisionFileData(offset, fileData, fileByteSize); + } + hasCollisionMesh = true; + delete[] fileData; +} + +const RawModelCustom::Vertex* RawModelCustom::CollisionVertices() { + if (hasCollisionMesh) { + return m_CollisionVertices.data(); + } + else if (hasSkin) { + return nullptr; + } + else { + return ConstructCollisionList(); + } +}; + +void RawModelCustom::ReadCollisionFileData(std::size_t& offset, char* fileData, const unsigned int& fileByteSize){ + m_CollisionVertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + offset += sizeof(unsigned int); + m_CollisionIndices.resize(static_cast(*(unsigned int*)(fileData + offset))); + offset += sizeof(unsigned int); + + if (offset + m_CollisionVertices.size() * sizeof(Vertex) > fileByteSize) { + throw Resource::FailedLoadingException("Reading collision vertices failed"); + } + memcpy(&m_CollisionVertices[0], fileData + offset, m_CollisionVertices.size() * sizeof(Vertex)); + offset += m_CollisionVertices.size() * sizeof(Vertex); + + if (offset + m_CollisionIndices.size() * sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading collision indices failed"); + } + memcpy(&m_CollisionIndices[0], fileData + offset, m_CollisionIndices.size() * sizeof(unsigned int)); + offset += m_CollisionIndices.size() * sizeof(unsigned int); +} + +const RawModelCustom::Vertex* RawModelCustom::ConstructCollisionList() +{ + if (!hasCollisionMesh && m_CollisionVertices.size() == 0) { + if (hasSkin) + { + m_CollisionVertices.reserve(m_SkinedVertices.size()); + for (auto vertex : m_SkinedVertices) { + Vertex tmp; + tmp.Position = vertex.Position; + m_CollisionVertices.push_back(tmp); + } + } else { + m_CollisionVertices.reserve(m_Vertices.size()); + for (auto vertex : m_Vertices) { + Vertex tmp; + tmp.Position = vertex.Position; + m_CollisionVertices.push_back(tmp); + } + } + } + + return m_CollisionVertices.data(); +} + RawModelCustom::~RawModelCustom() { if (m_Skeleton != nullptr) { diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 90f677fe..7f73d4e2 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -109,8 +109,8 @@ bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, Entity if (model != nullptr && Collision::AABBvsTriangles( spawnedBox, - model->Vertices(), - model->m_Indices, + model->CollisionVertices(), + model->CollisionIndices(), Transform::ModelMatrix(otherEntity))) { return true; }