diff --git a/.gitignore b/.gitignore index 0df2db42..23056510 100755 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ tools/MayaExporter/x64/Debug/ tools/MayaExporter/MayaExporter/Debug/ tools/MayaExporter/MayaExporter/GeneratedFiles/ + +tools/MayaExporter/MayaExporter/x64/* +tools/MayaExporter/x64/* diff --git a/assets b/assets index c4898d82..7531e441 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c4898d8281b5584d89b1caf14dab8e5fac120321 +Subproject commit 7531e441fea639076d69c6cf05e3ae8ff7170cf9 diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 8137ceef..86f397f7 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -64,7 +64,7 @@ bool RayVsModel(const Ray& ray, float& outVCoord); bool AABBvsTriangles(const AABB& box, - const std::vector& modelVertices, + const RawModel::Vertex* modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 2bbd768d..f3b0a17a 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -4,6 +4,7 @@ #include "../GLM.h" #include "../Core/InputController.h" #include "../Core/ELockMouse.h" +#include "../Game/Events/EDashAbility.h" #include "InputHandler.h" template @@ -230,6 +231,9 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; + + Events::DashAbility e; + m_EventBroker->Publish(e); } #endif \ No newline at end of file diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index fcdcbc92..15dbe39d 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -9,6 +9,7 @@ #include "Rendering/Model.h" #include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" +#include class AnimationSystem : public PureSystem { @@ -22,8 +23,9 @@ public: ~AnimationSystem() { } virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override; private: - - + float angle = 0.f; + bool b_forward = false; + char bone[100]; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/BoneAttachmentSystem.h b/include/Engine/Rendering/BoneAttachmentSystem.h new file mode 100644 index 00000000..93ce5119 --- /dev/null +++ b/include/Engine/Rendering/BoneAttachmentSystem.h @@ -0,0 +1,29 @@ +#ifndef BoneAttachmentSystem_h__ +#define BoneAttachmentSystem_h__ + +#include "GLM.h" + +#include "Common.h" +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Rendering/Model.h" +#include "Rendering/Skeleton.h" + +//Needs to be a higher orderlevel than AnimationSystem +class BoneAttachmentSystem : public PureSystem +{ +public: + BoneAttachmentSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) + , PureSystem("BoneAttachment") + { + + } + ~BoneAttachmentSystem() { } + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) override; +private: + + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 28ac958c..7d5e2a7a 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -43,8 +43,8 @@ private: void BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); void BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); - void BindExplosionTextures(std::shared_ptr& job); - void BindModelTextures(std::shared_ptr& job); + void BindExplosionTextures(GLuint shaderHandle, std::shared_ptr& job); + void BindModelTextures(GLuint shaderHandle, std::shared_ptr& job); Texture* m_WhiteTexture; Texture* m_BlackTexture; @@ -68,8 +68,18 @@ private: ShaderProgram* m_ForwardPlusProgram; ShaderProgram* m_ExplosionEffectProgram; + ShaderProgram* m_ExplosionEffectSplatMapProgram; + ShaderProgram* m_ForwardPlusSplatMapProgram; ShaderProgram* m_ShieldToStencilProgram; ShaderProgram* m_FillDepthBufferProgram; + + + ShaderProgram* m_ForwardPlusSkinnedProgram; + ShaderProgram* m_ExplosionEffectSkinnedProgram; + ShaderProgram* m_ExplosionEffectSplatMapSkinnedProgram; + ShaderProgram* m_ForwardPlusSplatMapSkinnedProgram; + ShaderProgram* m_ShieldToStencilSkinnedProgram; + ShaderProgram* m_FillDepthBufferSkinnedProgram; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h index 89b1342b..8f339526 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -15,7 +15,7 @@ struct ExplosionEffectJob : ModelJob { - ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage) + ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage) : ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage) { ExplosionOrigin = (glm::vec3)explosionEffectComponent["ExplosionOrigin"]; diff --git a/include/Engine/Rendering/Model.h b/include/Engine/Rendering/Model.h index 1f5231e2..4d21f724 100644 --- a/include/Engine/Rendering/Model.h +++ b/include/Engine/Rendering/Model.h @@ -15,11 +15,12 @@ private: public: ~Model(); - const std::vector& MaterialGroups() const { return m_RawModel->MaterialGroups; } + const std::vector& MaterialGroups() const { return m_RawModel->m_Materials; } const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; } - const std::vector& Vertices() const { return m_RawModel->m_Vertices; } + const RawModel::Vertex* Vertices() const { return m_RawModel->Vertices(); } + unsigned int NumberOfVertices() const { return m_RawModel->NumVertices(); } const AABB& Box() const { return m_Box; } - + bool IsSkinned() const { return m_RawModel->IsSkinned(); } GLuint VAO; GLuint ElementBuffer; RawModel* m_RawModel; diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 2cb2169c..bc2b8b6e 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -14,39 +14,98 @@ #include "../Core/World.h" #include "../Core/Transform.h" #include "Skeleton.h" +#include "ShaderProgram.h" struct ModelJob : RenderJob { - ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) + ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matProp, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) : RenderJob() { Model = model; - TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0; - if (modelComponent["DiffuseTexture"]) { - DiffuseTexture = matGroup.Texture.get(); - } else { - DiffuseTexture = nullptr; - } - if (modelComponent["NormalMap"]) { - NormalTexture = matGroup.NormalMap.get(); - } else { - NormalTexture = nullptr; - } - if (modelComponent["SpecularMap"]) { - SpecularTexture = matGroup.SpecularMap.get(); - } else { - SpecularTexture = nullptr; - } - if (modelComponent["GlowMap"]) { - IncandescenceTexture = matGroup.IncandescenceMap.get(); - } else { - IncandescenceTexture = nullptr; - } - DiffuseColor = matGroup.DiffuseColor; - SpecularColor = matGroup.SpecularColor; - IncandescenceColor = matGroup.IncandescenceColor; - StartIndex = matGroup.StartIndex; - EndIndex = matGroup.EndIndex; + ModelID = model->ResourceID; + Type = matProp.type; + ::RawModel::MaterialBasic* matGroup = matProp.material; + switch(matProp.type){ + case ::RawModel::MaterialType::Basic: + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } + TextureID = 0; + break; + case ::RawModel::MaterialType::SingleTextures: + { + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } + ::RawModel::MaterialSingleTextures* singleTextures = static_cast<::RawModel::MaterialSingleTextures*>(matProp.material); + TextureID = (singleTextures->ColorMap.Texture) ? singleTextures->ColorMap.Texture->ResourceID : 0; + if (modelComponent["DiffuseTexture"]) { + DiffuseTexture.push_back(&singleTextures->ColorMap); + } + + if (modelComponent["NormalMap"]) { + NormalTexture.push_back(&singleTextures->NormalMap); + } + + if (modelComponent["SpecularMap"]) { + SpecularTexture.push_back(&singleTextures->SpecularMap); + } + + if (modelComponent["GlowMap"]) { + IncandescenceTexture.push_back(&singleTextures->IncandescenceMap); + } + } + break; + case ::RawModel::MaterialType::SplatMapping: + { + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusSplatMapProgram")->ResourceID; + } + ::RawModel::MaterialSplatMapping* SplatTextures = static_cast<::RawModel::MaterialSplatMapping*>(matProp.material); + + SplatMap = &SplatTextures->SplatMap; + + TextureID = (SplatTextures->ColorMaps[0].Texture) ? SplatTextures->ColorMaps[0].Texture->ResourceID : 0; + if (modelComponent["DiffuseTexture"]) { + for (auto& texture : SplatTextures->ColorMaps) { + DiffuseTexture.push_back(&texture); + } + } + + if (modelComponent["NormalMap"]) { + for (auto& texture : SplatTextures->NormalMaps) { + NormalTexture.push_back(&texture); + } + } + + if (modelComponent["SpecularMap"]) { + for (auto& texture : SplatTextures->SpecularMaps) { + SpecularTexture.push_back(&texture); + } + } + + if (modelComponent["GlowMap"]) { + for (auto& texture : SplatTextures->IncandescenceMaps) { + IncandescenceTexture.push_back(&texture); + } + } + } + break; + } + DiffuseColor = matGroup->DiffuseColor; + SpecularColor = matGroup->SpecularColor; + IncandescenceColor = matGroup->IncandescenceColor; + StartIndex = matGroup->StartIndex; + EndIndex = matGroup->EndIndex; Matrix = matrix; Color = modelComponent["Color"]; Entity = modelComponent.EntityID; @@ -57,29 +116,56 @@ struct ModelJob : RenderJob FillColor = fillColor; FillPercentage = fillPercentage; + Skeleton = Model->m_RawModel->m_Skeleton; - if (world->HasComponent(Entity, "Animation") && Skeleton != nullptr) { - auto animationComponent = world->GetComponent(Entity, "Animation"); - Animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["Name"]); - AnimationTime = (double)animationComponent["Time"]; + if (Skeleton != nullptr) { + if (world->HasComponent(Entity, "Animation")) { + auto animationComponent = world->GetComponent(Entity, "Animation"); + + for (int i = 1; i <= 3; i++) { + ::Skeleton::AnimationData animationData; + animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + if (animationData.animation == nullptr) { + continue; + } + animationData.time = (double)animationComponent["Time" + std::to_string(i)]; + animationData.weight = (double)animationComponent["Weight" + std::to_string(i)]; + + Animations.push_back(animationData); + } + } + + if (world->HasComponent(Entity, "AnimationOffset")) { + auto animationOffsetComponent = world->GetComponent(Entity, "AnimationOffset"); + AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(animationOffsetComponent["AnimationName"]); + AnimationOffset.time = (double)animationOffsetComponent["Time"]; + } else { + AnimationOffset.animation = nullptr; + } } }; unsigned int TextureID; unsigned int ShaderID; + unsigned int ModelID; + ::RawModel::MaterialType Type; EntityID Entity; glm::mat4 Matrix; - const Texture* DiffuseTexture; - const Texture* NormalTexture; - const Texture* SpecularTexture; - const Texture* IncandescenceTexture; + const ::RawModel::TextureProperties* SplatMap; + std::vector DiffuseTexture; + std::vector NormalTexture; + std::vector SpecularTexture; + std::vector IncandescenceTexture; float Shininess = 0.f; glm::vec4 Color; const ::Model* Model = nullptr; ::Skeleton* Skeleton = nullptr; - const ::Skeleton::Animation* Animation = nullptr; + // const ::Skeleton::Animation* Animation = nullptr; + + std::vector<::Skeleton::AnimationData> Animations; + ::Skeleton::AnimationOffset AnimationOffset; float AnimationTime = 0.f; @@ -95,7 +181,7 @@ struct ModelJob : RenderJob void CalculateHash() override { - Hash = TextureID; + Hash = TextureID + ModelID << 10 + ShaderID << 20; } }; diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index da3ed31b..2ce2e78d 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -40,6 +40,7 @@ private: const IRenderer* m_Renderer; ShaderProgram* m_PickingProgram; + ShaderProgram* m_PickingSkinnedProgram; Camera* m_Camera; struct PickingInfo diff --git a/include/Engine/Rendering/RawModelCustom.h b/include/Engine/Rendering/RawModelCustom.h index e903f49f..cf21fb6d 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -33,18 +33,27 @@ protected: public: ~RawModelCustom(); - struct Vertex - { - glm::vec3 Position; - glm::vec3 Normal; - glm::vec3 Tangent; - glm::vec3 BiNormal; - glm::vec2 TextureCoords; + struct Vertex + { + glm::vec3 Position; + glm::vec3 Normal; + glm::vec3 Tangent; + glm::vec3 BiNormal; + glm::vec2 TextureCoords; + }; + + struct SkinedVertex : public Vertex { glm::vec4 BoneIndices; glm::vec4 BoneWeights; }; - struct MaterialGroup + struct TextureProperties { + std::string TexturePath; + glm::vec2 UVRepeat; + std::shared_ptr<::Texture> Texture; + }; + + struct MaterialBasic { float SpecularExponent; float ReflectionFactor; @@ -54,25 +63,69 @@ public: unsigned int StartIndex; unsigned int EndIndex; //float Transparency; - std::string TexturePath; - std::shared_ptr<::Texture> Texture; - std::string NormalMapPath; - std::shared_ptr<::Texture> NormalMap; - std::string SpecularMapPath; - std::shared_ptr<::Texture> SpecularMap; - std::string IncandescenceMapPath; - std::shared_ptr<::Texture> IncandescenceMap; }; - std::vector MaterialGroups; + struct MaterialSplatMapping : public MaterialBasic + { + TextureProperties SplatMap; + std::vector ColorMaps; + std::vector NormalMaps; + std::vector SpecularMaps; + std::vector IncandescenceMaps; + }; + + struct MaterialSingleTextures : public MaterialBasic + { + TextureProperties ColorMap; + TextureProperties NormalMap; + TextureProperties SpecularMap; + TextureProperties IncandescenceMap; + }; + + enum class MaterialType { Basic = 1, SplatMapping, SingleTextures }; + + struct MaterialProperties { + MaterialType type; + MaterialBasic* material; + }; + + const Vertex* Vertices() const { + if (hasSkin) { + return m_SkinedVertices.data(); + } else { + return m_Vertices.data(); + } + }; + + unsigned int VertexSize() const { + if (hasSkin) { + return sizeof(SkinedVertex); + } + else { + return sizeof(Vertex); + } + }; + + unsigned int NumVertices() const { + if (hasSkin) { + return m_SkinedVertices.size(); + } else { + return m_Vertices.size(); + } + }; + + bool IsSkinned() const { return hasSkin; }; + + std::vector m_Materials; - std::vector m_Vertices; std::vector m_Indices; Skeleton* m_Skeleton = nullptr; glm::mat4 m_Matrix; private: - + bool hasSkin; + std::vector m_Vertices; + std::vector m_SkinedVertices; void ReadMeshFile(std::string filePath); void ReadMeshFileHeader(std::size_t& offset, char* fileData); @@ -83,13 +136,17 @@ private: void ReadMaterialFile(std::string filePath); void ReadMaterials(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialBasic(MaterialBasic* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialSingleTexture(MaterialSingleTextures* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialSplatMapping(MaterialSplatMapping* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialTextureProperties(TextureProperties& texture, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadAnimationFile(std::string filePath); void ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadAnimationJoint(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); 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, unsigned int numberOfJoints, Skeleton::Animation& animation); + void ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& animation); //void CreateSkeleton(std::vector> &boneInfo, std::map &boneNameMapping, aiNode* node, int parentID); }; diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index d8e07c3a..4a313087 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -50,7 +50,6 @@ private: void fillLight(std::list>& jobs); bool isChildOfACamera(EntityWrapper entity); bool isChildOfCurrentCamera(EntityWrapper entity); - }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 3b89b89b..124d618b 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -5,6 +5,7 @@ #include "Common.h" #include "../GLM.h" #include +#include //struct Bone //{ @@ -53,22 +54,39 @@ public: { struct BoneProperty { - int ID; - glm::vec3 Position; - glm::quat Rotation; + glm::vec3 Position; + glm::quat Rotation; glm::vec3 Scale = glm::vec3(1); }; - int Index = 0; - double Time = 0.0; - std::map BoneProperties; + int Index = 0; + double Time = 0.0; + BoneProperty BoneProperties; }; - - std::string Name; - double Duration; - std::vector Keyframes; + std::string Name; + double Duration; + std::map> JointAnimations; }; + struct AnimationData + { + const Animation* animation; + float time; + float weight; + }; + + struct JointFrameTransform { + glm::vec3 PositionInterp = glm::vec3(0); + glm::quat RotationInterp = glm::quat(); + glm::vec3 ScaleInterp = glm::vec3(0); + float Weight; + }; + + struct AnimationOffset { + const Animation* animation; + float time; + }; + Skeleton() { } ~Skeleton(); @@ -82,17 +100,27 @@ public: int GetBoneID(std::string name); - const Animation* GetAnimation(std::string name); - std::vector GetFrameBones(const Animation& animation, double time, bool noRootMotion = false); - void AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); - void PrintSkeleton(); + const Animation* GetAnimation(std::string name); + std::vector GetFrameBones(std::vector animations, bool noRootMotion = false); + std::vector GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion = false); + + //void AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, float time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); + + void PrintSkeleton(); void PrintSkeleton(const Bone* parent, int depthCount); std::map Animations; -private: - std::map m_BonesByName; + glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); + int GetKeyframe(const Animation& animation, double time); - int GetKeyframe(const Animation& animation, double time); +private: + + glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + + std::map m_BonesByName; + float aim = 0.f; }; #endif diff --git a/include/Engine/Sound/EPlayQueueOnEntity.h b/include/Engine/Sound/EPlayQueueOnEntity.h new file mode 100644 index 00000000..e880819a --- /dev/null +++ b/include/Engine/Sound/EPlayQueueOnEntity.h @@ -0,0 +1,18 @@ +#ifndef Events_PlayQueueOnEntity_h__ +#define Events_PlayQueueOnEntity_h__ + +#include "../Core/Event.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct PlayQueueOnEntity : public Event +{ + EntityWrapper Emitter; + std::vector FilePaths; +}; + +} + +#endif diff --git a/include/Engine/Sound/Sound.h b/include/Engine/Sound/Sound.h index 6b2aac04..cccbdf07 100644 --- a/include/Engine/Sound/Sound.h +++ b/include/Engine/Sound/Sound.h @@ -1,6 +1,9 @@ #ifndef Sound_h__ #define Sound_h__ +#include +#include + #include "Core/ResourceManager.h" class Sound : public Resource diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundManager.h similarity index 57% rename from include/Engine/Sound/SoundSystem.h rename to include/Engine/Sound/SoundManager.h index b9cc2589..5b027c62 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundManager.h @@ -1,17 +1,23 @@ -#ifndef SoundSystem_h__ -#define SoundSystem_h__ +#ifndef SoundManager_h__ +#define SoundManager_h__ #include +#include #include "glm/common.hpp" #include "glm/gtx/rotate_vector.hpp" // Calculate Up vector #include "OpenAL/al.h" #include "OpenAL/alc.h" +#include "imgui/imgui.h" + #include "Core/World.h" #include "Core/EventBroker.h" +#include "../Engine/Core/ResourceManager.h" +#include "../Engine/Core/ConfigFile.h" #include "Core/Transform.h" // Absolute transform #include "Sound/Sound.h" +#include "../Engine/Sound/EPlayQueueOnEntity.h" #include "Sound/EPlaySoundOnEntity.h" #include "Sound/EPlaySoundOnPosition.h" #include "Sound/EPlayBackgroundMusic.h" @@ -20,6 +26,11 @@ #include "Sound/EStopSound.h" #include "Sound/ESetBGMGain.h" #include "Sound/ESetSFXGain.h" +#include "Core/EPause.h" +#include "Core/EComponentAttached.h" +#include "../Core/EPlayerSpawned.h" + +typedef std::pair> QueuedBuffers; enum class SoundType { SFX, @@ -34,14 +45,15 @@ struct Source SoundType Type; }; -class SoundSystem +class SoundManager { public: - SoundSystem() { } - SoundSystem(World* world, EventBroker* eventBroker, bool editorMode); - ~SoundSystem(); + SoundManager() { } + SoundManager(World* world, EventBroker* eventBroker); + ~SoundManager(); // Update emitters / listener void Update(double dt); + private: // Help functions for working with OpenaAL void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; @@ -56,46 +68,62 @@ private: // Logic void initOpenAL(); void updateEmitters(double dt); - void updateListener(double dt); void deleteInactiveEmitters(); - void addNewEmitters(double dt); - Source* createSource(std::string filePath); - void playSound(Source* source); - void stopSound(Source* source); void stopEmitters(); + void updateListener(double dt); ALenum getSourceState(ALuint source); void setGain(Source* source, float gain); - void setSoundProperties(ALuint source, ComponentWrapper* soundComponent); + void setSoundProperties(Source* source, ComponentWrapper* soundComponent); + + // Specific logic + void playSound(Source* source); + // Need to be the same format (sample rate etc) + void playQueue(QueuedBuffers qb); + void stopSound(Source* source); + Source* createSource(std::string filePath); + std::unordered_map m_Sources; + + // Logic + World* m_World = nullptr; + EventBroker* m_EventBroker = nullptr; // OpenAL system variables ALCdevice* m_ALCdevice = nullptr; ALCcontext* m_ALCcontext = nullptr; - // Logic - World* m_World = nullptr; - EventBroker* m_EventBroker = nullptr; - std::unordered_map m_Sources; float m_BGMVolumeChannel = 1.0f; - float m_SFXVolumeChannel = 1.f; - bool m_EditorEnabled = false; - + float m_SFXVolumeChannel = 1.0f; + EntityWrapper m_LocalPlayer = EntityWrapper(); + // Events - EventRelay m_EPlaySoundOnEntity; + EventRelay m_EPlaySoundOnEntity; bool OnPlaySoundOnEntity(const Events::PlaySoundOnEntity &e); - EventRelay m_EPlaySoundOnPosition; + EventRelay m_EPlaySoundOnPosition; bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e); - EventRelay m_EPlayBackgroundMusic; + EventRelay m_EPlayBackgroundMusic; bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e); - EventRelay m_EPauseSound; + EventRelay m_EPauseSound; bool OnPauseSound(const Events::PauseSound &e); - EventRelay m_EStopSound; + EventRelay m_EStopSound; bool OnStopSound(const Events::StopSound &e); - EventRelay m_EContinueSound; + EventRelay m_EContinueSound; bool OnContinueSound(const Events::ContinueSound &e); - EventRelay m_ESetBGMGain; - bool OnSetBGMGain(const Events::SetBGMGain &e); // Not tested - EventRelay m_ESetSFXGain; - bool OnSetSFXGain(const Events::SetSFXGain &e); // Not tested + EventRelay m_ESetBGMGain; + bool OnSetBGMGain(const Events::SetBGMGain &e); + EventRelay m_ESetSFXGain; + bool OnSetSFXGain(const Events::SetSFXGain &e); + EventRelay m_EComponentAttached; + bool OnComponentAttached(const Events::ComponentAttached &e); + EventRelay m_EPause; + bool OnPause(const Events::Pause &e); + EventRelay m_EResume; + bool OnResume(const Events::Resume &e); + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(const Events::PlayerSpawned &e); + EventRelay m_EPlayQueueOnEntity; + bool OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e); + + }; #endif \ No newline at end of file diff --git a/include/Game/Events/EDashAbility.h b/include/Game/Events/EDashAbility.h new file mode 100644 index 00000000..62a2b935 --- /dev/null +++ b/include/Game/Events/EDashAbility.h @@ -0,0 +1,13 @@ +#ifndef Events_DashAbility_h__ +#define Events_DashAbility_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct DashAbility : public Event { }; + +} + +#endif \ No newline at end of file diff --git a/include/Game/Events/EDoubleJump.h b/include/Game/Events/EDoubleJump.h new file mode 100644 index 00000000..767d5b39 --- /dev/null +++ b/include/Game/Events/EDoubleJump.h @@ -0,0 +1,16 @@ +#ifndef Events_DoubleJump_h__ +#define Events_DoubleJump_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct DoubleJump : public Event +{ + +}; + +} + +#endif diff --git a/include/Game/Game.h b/include/Game/Game.h index 37267a68..6177a818 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -30,7 +30,8 @@ #include "Network/Client.h" // Sound -#include "Sound/SoundSystem.h" +#include "Sound/SoundManager.h" +#include "Systems/SoundSystem.h" class Game { @@ -64,7 +65,7 @@ private: bool m_IsClientOrServer = false; // Sound - SoundSystem* m_SoundSystem; + SoundManager* m_SoundManager; //EventRelay m_EInputCommand; //bool debugOnInputCommand(const Events::InputCommand& e); diff --git a/include/Game/Systems/LifetimeSystem.h b/include/Game/Systems/LifetimeSystem.h index da88cfa2..99cafd89 100644 --- a/include/Game/Systems/LifetimeSystem.h +++ b/include/Game/Systems/LifetimeSystem.h @@ -9,7 +9,9 @@ public: LifetimeSystem(World* world, EventBroker* eventBroker) : System(world, eventBroker) , PureSystem("Lifetime") - { } + { + LOG_INFO("ASDASDASSA"); + } virtual void Update(double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt) override; diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 34862e90..defaa8ae 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -4,6 +4,8 @@ #include "Core/EPlayerSpawned.h" #include "Input/FirstPersonInputController.h" #include +#include "Events/EDoubleJump.h" +#include "../Engine/Sound/EPlaySoundOnEntity.h" class PlayerMovementSystem : public ImpureSystem, PureSystem { @@ -18,6 +20,19 @@ private: // State std::unordered_map*> m_PlayerInputControllers; + EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; + // Walking logic + // Keeps track of how far the player has walked within this "key press session". + float m_DistanceMoved = 0.0f; + // How far a step is (How often the step sound will be played). + const float m_PlayerStepLength = 1.75f; + // Determine what sound file to play. + bool m_LeftFoot = false; + // To get a difference when calculating the walking state. + glm::vec3 m_LastPosition = glm::vec3(); + // The logic for making the sound play when player is moving + void playerStep(double dt); + EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(Events::PlayerSpawned& e); diff --git a/include/Game/Systems/SoundSystem.h b/include/Game/Systems/SoundSystem.h new file mode 100644 index 00000000..09582826 --- /dev/null +++ b/include/Game/Systems/SoundSystem.h @@ -0,0 +1,71 @@ +#ifndef Systems_SoundSystem_h__ +#define Systems_SoundSystem_h__ + +#include + +#include "../Engine/Core/System.h" +#include "../Engine/Core/ResourceManager.h" +#include "../Engine/Core/ConfigFile.h" +#include "../Engine/Sound/Sound.h" +#include "../Engine/Sound/EPlayQueueOnEntity.h" +#include "../Engine/Core/EPlayerSpawned.h" +#include "../Engine/Input/EInputCommand.h" +#include "../Engine/Core/EShoot.h" +#include "../Engine/Core/EPlayerSpawned.h" +#include "../Engine/Input/EInputCommand.h" +#include "../Engine/Core/ECaptured.h" +#include "../Engine/Core/EPlayerDamage.h" +#include "../Engine/Core/EPlayerDeath.h" +#include "../Engine/Core/EPlayerHealthPickup.h" +#include "../Engine/Collision/ETrigger.h" +#include "../Engine/Sound/EPlaySoundOnEntity.h" +#include "../Engine/Sound/EPlayBackgroundMusic.h" +#include "../Game/Events/EDoubleJump.h" +#include "../Game/Events/EDashAbility.h" + + +class SoundSystem : public PureSystem, ImpureSystem +{ +public: + SoundSystem(World* world, EventBroker* eventbroker); + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) override; + virtual void Update(double dt) override; +private: + EntityWrapper m_LocalPlayer = EntityWrapper(); + + World* m_World = nullptr; + EventBroker* m_EventBroker = nullptr; + std::string m_Announcer = ""; + // Logic for playing a sound when a player jumps + void playerJumps(); + + // Temporary solution for play test. + bool m_DrumsIsPlaying = false; + double m_DrumTimer = 0.0; + bool drumTimer(double dt); + + std::default_random_engine generator; + + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(const Events::PlayerSpawned &e); + EventRelay m_InputCommand; + bool OnInputCommand(const Events::InputCommand &e); + EventRelay m_EDoubleJump; + bool OnDoubleJump(const Events::DoubleJump &e); + EventRelay m_EDashAbility; + bool OnDashAbility(const Events::DashAbility &e); + EventRelay m_ETriggerTouch; + bool OnTriggerTouch(const Events::TriggerTouch &e); + EventRelay m_EShoot; + bool OnShoot(const Events::Shoot &e); + EventRelay m_ECaptured; + bool OnCaptured(const Events::Captured &e); + EventRelay m_EPlayerDamage; + bool OnPlayerDamage(const Events::PlayerDamage &e); + EventRelay m_EPlayerDeath; + bool OnPlayerDeath(const Events::PlayerDeath &e); + EventRelay m_EPlayerHealthPickup; + bool OnPlayerHealthPickup(const Events::PlayerHealthPickup &e); +}; + +#endif diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 86dc735c..12ec06c8 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -29,3 +29,8 @@ TimeoutMs=15000 [Multithreading] ResourceLoading=true + +[Sound] +BGMVolume=1.0 +SFXVolume=1.0 +Announcer=female \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index e2c40d48..1aa98f17 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -28,9 +28,11 @@ + + diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index 66d2865d..ae42009d 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,7 +1,18 @@ - - - 0 - true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index 0dd21f29..fd4a4c46 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -6,10 +6,21 @@ - - - - + + + + + + + + + + + + + + + diff --git a/resources/Schema/Components/AnimationOffset.xml b/resources/Schema/Components/AnimationOffset.xml new file mode 100644 index 00000000..4aef8219 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xsd b/resources/Schema/Components/AnimationOffset.xsd new file mode 100644 index 00000000..c3430cc2 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xsd @@ -0,0 +1,17 @@ + + + + + + + + Aim animation offset for the skeleton + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/BoneAttachment.xml b/resources/Schema/Components/BoneAttachment.xml new file mode 100644 index 00000000..47df9e40 --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xml @@ -0,0 +1,10 @@ + + + + + + + true + true + false + \ No newline at end of file diff --git a/resources/Schema/Components/BoneAttachment.xsd b/resources/Schema/Components/BoneAttachment.xsd new file mode 100644 index 00000000..aee1868f --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AnimatedArmy.xml b/resources/Schema/Entities/AnimatedArmy.xml index b711a0fe..67accc40 100644 --- a/resources/Schema/Entities/AnimatedArmy.xml +++ b/resources/Schema/Entities/AnimatedArmy.xml @@ -20,7 +20,7 @@ - models/dummyscene.mesh + Models/Test/DummyScene.mesh @@ -31,7 +31,7 @@ - models/animtest. + Models/Test/AnimTest.mesh @@ -42,7 +42,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -53,7 +53,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -64,7 +64,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -91,7 +91,7 @@ - + @@ -154,7 +154,7 @@ - + diff --git a/resources/Schema/Entities/AnimationTests.xml b/resources/Schema/Entities/AnimationTests.xml new file mode 100644 index 00000000..77c87e64 --- /dev/null +++ b/resources/Schema/Entities/AnimationTests.xml @@ -0,0 +1,377 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + + Models/DirectionalLightWidget.mesh + + + + + + + + + + + + Crouch + + 1 + + + Models/Asstest.mesh + + + + + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml new file mode 100644 index 00000000..96a439a4 --- /dev/null +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + Run + 0.5 + 0.23980116887997371 + 1 + 1 + StrafeRight + 0.5 + 0.42593105566437428 + ReloadSwitch + 0.68855715986371058 + 1 + + + AimRifle + + + Models/Characters/Assault/AssaultAnimations.mesh + + + + + + + + + + + + 10 + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AssetPedistal.xml b/resources/Schema/Entities/AssetPedistal.xml index 728a3028..3c816149 100644 --- a/resources/Schema/Entities/AssetPedistal.xml +++ b/resources/Schema/Entities/AssetPedistal.xml @@ -35,7 +35,7 @@ - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh diff --git a/resources/Schema/Entities/BoneMarker b/resources/Schema/Entities/BoneMarker new file mode 100644 index 00000000..eda56d56 --- /dev/null +++ b/resources/Schema/Entities/BoneMarker @@ -0,0 +1,22 @@ + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CaptureTest.xml b/resources/Schema/Entities/CaptureTest.xml index 5f657e51..3d678bd7 100644 --- a/resources/Schema/Entities/CaptureTest.xml +++ b/resources/Schema/Entities/CaptureTest.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -81,7 +81,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -102,7 +102,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -120,7 +120,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -138,7 +138,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState1.xml b/resources/Schema/Entities/CaptureTestState1.xml index ffabd5c2..64999074 100644 --- a/resources/Schema/Entities/CaptureTestState1.xml +++ b/resources/Schema/Entities/CaptureTestState1.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -42,7 +42,7 @@ 6.9158446328696002 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -63,7 +63,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -83,7 +83,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -104,7 +104,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -122,7 +122,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -140,7 +140,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState2.xml b/resources/Schema/Entities/CaptureTestState2.xml index 29abdfbd..6ddb306f 100644 --- a/resources/Schema/Entities/CaptureTestState2.xml +++ b/resources/Schema/Entities/CaptureTestState2.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -98,7 +98,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -116,7 +116,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -134,7 +134,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState3.xml b/resources/Schema/Entities/CaptureTestState3.xml index ff875dc4..3bed3624 100644 --- a/resources/Schema/Entities/CaptureTestState3.xml +++ b/resources/Schema/Entities/CaptureTestState3.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -81,7 +81,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -101,7 +101,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -122,7 +122,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -140,7 +140,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -158,7 +158,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -176,7 +176,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -194,7 +194,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState4.xml b/resources/Schema/Entities/CaptureTestState4.xml index 740d7e7b..30db23aa 100644 --- a/resources/Schema/Entities/CaptureTestState4.xml +++ b/resources/Schema/Entities/CaptureTestState4.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -96,7 +96,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -115,7 +115,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -133,7 +133,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -151,7 +151,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -169,7 +169,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -187,7 +187,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState5.xml b/resources/Schema/Entities/CaptureTestState5.xml index f1b07a7b..8fe85068 100644 --- a/resources/Schema/Entities/CaptureTestState5.xml +++ b/resources/Schema/Entities/CaptureTestState5.xml @@ -17,7 +17,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -39,7 +39,7 @@ 1 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -57,7 +57,7 @@ 2 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 3 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -104,7 +104,7 @@ 4 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -124,7 +124,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + Models/Core/UnitCube.mesh @@ -143,7 +143,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + Models/Core/UnitCube.mesh @@ -160,7 +160,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\DummyScene.mesh + Models/Test/DummyScene.mesh diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 4727c777..46e6d54d 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -37,7 +37,7 @@ 0.80000001192092896 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh 1 @@ -62,7 +62,7 @@ 3 - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -73,7 +73,7 @@ - Models/AssaultWeaponRed.mesh + Models/Weapons/Red/AssaultWeaponRed.mesh true @@ -86,7 +86,7 @@ - Models/DefenderGunRed.mesh + Models/Weapons/Red/DefenderGunRed.mesh true false @@ -115,7 +115,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -131,7 +131,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -157,7 +157,7 @@ - Models/Log.mesh + Models/Props/TreeLog.mesh @@ -176,7 +176,7 @@ - models/NormSpecIncdMapSphere.mesh + Models/Test/NormSpecIncdMapSphere.mesh @@ -260,7 +260,7 @@ - Models/NormalMapSphere.mesh + Models/Test/NormalMapSphere.mesh @@ -271,7 +271,7 @@ - Models/SpecularMapSphere.mesh + Models/Test/SpecularMapSphere.mesh @@ -313,7 +313,7 @@ - Models/IncandescenceMapSphere.mesh + Models/Test/IncandescenceMapSphere.mesh diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 88452aac..1276f3e4 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -18,7 +18,7 @@ - Models/RotationWidgetX.mesh + Models/Widgets/Rotate/RotationWidgetX.mesh @@ -33,7 +33,7 @@ - Models/RotationWidgetY.mesh + Models/Widgets/Rotate/RotationWidgetY.mesh @@ -48,7 +48,7 @@ - Models/RotationWidgetZ.mesh + Models/Widgets/Rotate/RotationWidgetZ.mesh diff --git a/resources/Schema/Entities/EditorWidgetScale.xml b/resources/Schema/Entities/EditorWidgetScale.xml index 786b079e..65cb2b86 100644 --- a/resources/Schema/Entities/EditorWidgetScale.xml +++ b/resources/Schema/Entities/EditorWidgetScale.xml @@ -3,7 +3,7 @@ - Models/ScaleWidgetOrigin.mesh + Models/Widgets/Scale/ScalingWidgetOrigin.mesh @@ -20,7 +20,7 @@ - Models/ScaleWidgetX.mesh + Models/Widgets/Scale/ScalingWidgetX.mesh @@ -34,7 +34,7 @@ - Models/ScaleWidgetY.mesh + Models/Widgets/Scale/ScalingWidgetY.mesh @@ -48,7 +48,7 @@ - Models/ScaleWidgetZ.mesh + Models/Widgets/Scale/ScalingWidgetZ.mesh diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index c6dba4d9..e177b7e9 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -3,7 +3,7 @@ - Models/TranslationWidgetOrigin.mesh + Models/Widgets/Translate/TranslationWidgetOrigin.mesh @@ -18,7 +18,7 @@ - Models/TranslationWidgetX.mesh + Models/Widgets/Translate/TranslationWidgetX.mesh @@ -30,7 +30,7 @@ - Models/TranslationWidgetY.mesh + Models/Widgets/Translate/TranslationWidgetY.mesh @@ -42,7 +42,7 @@ - Models/TranslationWidgetZ.mesh + Models/Widgets/Translate/TranslationWidgetZ.mesh @@ -54,7 +54,7 @@ - Models/WidgetPlaneX.mesh + Models/Widgets/Translate/TranslationWidgetPlaneX.mesh @@ -66,7 +66,7 @@ - Models/WidgetPlaneY.mesh + Models/Widgets/Translate/TranslationWidgetPlaneY.mesh @@ -78,7 +78,7 @@ - Models/WidgetPlaneZ.mesh + Models/Widgets/Translate/TranslationWidgetPlaneZ.mesh diff --git a/resources/Schema/Entities/FastWorld.xml b/resources/Schema/Entities/FastWorld.xml index 1289d9d1..94df077d 100644 --- a/resources/Schema/Entities/FastWorld.xml +++ b/resources/Schema/Entities/FastWorld.xml @@ -3,7 +3,7 @@ - + @@ -18,23 +18,17 @@ - + - Run - - 1 + Crouch Walk + + 8 - - - - 0.95625903442123672 - - Models/AssaultAnimated.mesh diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 5c1fbacc..84a1e363 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -14,7 +14,7 @@ - Models\MapVersion1.mesh + Models/LevelBase/MapVersion1.mesh @@ -26,7 +26,7 @@ 2 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh false diff --git a/resources/Schema/Entities/Model.xml b/resources/Schema/Entities/Model.xml index 57856cbd..bee6b7e1 100644 --- a/resources/Schema/Entities/Model.xml +++ b/resources/Schema/Entities/Model.xml @@ -19,7 +19,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index f5197830..b8b68ef1 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -26,7 +26,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -39,7 +39,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -54,7 +54,7 @@ - Models/DirectionalLightWidget.mesh + sModels/Widgets/Lights/DirectionalLightWidget.mesh @@ -96,7 +96,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -109,7 +109,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -171,7 +171,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh @@ -186,7 +186,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -199,7 +199,7 @@ - Models/AssaultHeadless.mesh + Models/Characters/Assault/AssaultHeadless.mesh diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 384ffb80..7c081e4c 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -6,9 +6,6 @@ - - 2.0 - @@ -53,7 +50,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -92,7 +89,7 @@ - Models/CrosshairQuad.mesh + Models/Weapons/CrosshairQuad.mesh @@ -105,7 +102,7 @@ - Models/AssaultWeaponRed.mesh + Models/Weapons/Red/AssaultWeaponRed.mesh @@ -130,7 +127,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -149,7 +146,7 @@ - Models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 980cb39c..aef0fa87 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -97,7 +97,7 @@ 0.80000001192092896 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh 1 @@ -126,7 +126,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -142,7 +142,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -200,7 +200,7 @@ 1 - Models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -224,7 +224,7 @@ - models/NormSpecIncdMapSphere.mesh + Models/Test/NormSpecIncdMapSphere.mesh @@ -308,7 +308,7 @@ - Models/NormalMapSphere.mesh + Models/Test/NormalMapSphere.mesh @@ -319,7 +319,7 @@ - Models/SpecularMapSphere.mesh + Models/Test/SpecularMapSphere.mesh @@ -361,7 +361,7 @@ - Models/IncandescenceMapSphere.mesh + Models/Test/IncandescenceMapSphere.mesh @@ -422,7 +422,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -435,7 +435,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -448,7 +448,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -461,7 +461,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -493,7 +493,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -506,7 +506,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -519,7 +519,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -532,7 +532,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -608,7 +608,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh true @@ -690,7 +690,7 @@ - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh @@ -737,7 +737,7 @@ - Models/AssaultWeaponRed.mesh + Models/Weapons/Red/AssaultWeaponRed.mesh @@ -797,7 +797,7 @@ - Models/SecondaryWeapon.mesh + Models/Weapons/SecondaryWeapon.mesh @@ -844,7 +844,7 @@ - Models/AssualtSoft.mesh + Models/Test/AssaultTPoseSoftEdge.mesh @@ -890,7 +890,7 @@ - Models/DefenderGunBlue.mesh + Models/Weapons/Blue/DefenderGunBlue.mesh @@ -937,7 +937,7 @@ - Models/DefenderGunRed.mesh + Models/Weapons/Red/DefenderGunRed.mesh @@ -984,7 +984,7 @@ - Models/Assualt.mesh + Models/Test/AssaultTPoseHardEdge.mesh @@ -1021,7 +1021,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1073,7 +1073,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1119,7 +1119,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1163,7 +1163,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1210,7 +1210,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1405,7 +1405,7 @@ true - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh true @@ -1458,7 +1458,7 @@ 0.31711568080172703 - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh true @@ -1518,7 +1518,7 @@ true - Models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh true diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 4a0bb9d4..8d8e6e1e 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -6,7 +6,7 @@ 0.25 - Models/CylinderBullet.mesh + Models/Weapons/CylinderBullet.mesh true diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml index e69df489..11a9b077 100644 --- a/resources/Schema/Entities/RayRed.xml +++ b/resources/Schema/Entities/RayRed.xml @@ -6,7 +6,7 @@ 0.25 - Models/CylinderBullet.mesh + Models/Weapons/CylinderBullet.mesh true diff --git a/resources/Schema/Entities/RenderingWorld.xml b/resources/Schema/Entities/RenderingWorld.xml index 20301d5f..d3e9695f 100644 --- a/resources/Schema/Entities/RenderingWorld.xml +++ b/resources/Schema/Entities/RenderingWorld.xml @@ -20,7 +20,7 @@ - Models/Assault.obj + Models/Characters/Assault/AssaultTPose.mesh @@ -35,7 +35,7 @@ 80 - Models/Camera.mesh + Models/Widgets/Camera.mesh @@ -52,14 +52,15 @@ - 0.65990006923675537 + Models/Core/UnitHexagon.mesh + true @@ -132,7 +133,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -161,7 +162,7 @@ - + @@ -308,7 +309,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -324,7 +325,7 @@ 0.10000000149011612 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh @@ -346,6 +347,20 @@ + + + + Run + + 0.004999999888241291 + + + Models/SuperTest.mesh + + + + + diff --git a/resources/Schema/Entities/ShootEventTest.xml b/resources/Schema/Entities/ShootEventTest.xml index 9e9adf50..80dd2f35 100644 --- a/resources/Schema/Entities/ShootEventTest.xml +++ b/resources/Schema/Entities/ShootEventTest.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -96,7 +96,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -115,7 +115,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -133,7 +133,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -151,7 +151,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -171,7 +171,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -191,7 +191,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/Skeleton.xml b/resources/Schema/Entities/Skeleton.xml new file mode 100644 index 00000000..b8deb2eb --- /dev/null +++ b/resources/Schema/Entities/Skeleton.xml @@ -0,0 +1,497 @@ + + + + + + + + + + + + R_Arm_Weapon_Joint + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + R_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + L_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Head + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Perietal + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/SpawnPointClusterWithModels.xml b/resources/Schema/Entities/SpawnPointClusterWithModels.xml index 9c42d0e4..ea8e09d4 100644 --- a/resources/Schema/Entities/SpawnPointClusterWithModels.xml +++ b/resources/Schema/Entities/SpawnPointClusterWithModels.xml @@ -19,7 +19,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -31,7 +31,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -43,7 +43,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -55,7 +55,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh diff --git a/resources/Schema/Entities/SpawnerWithPlayerModel.xml b/resources/Schema/Entities/SpawnerWithPlayerModel.xml index 1274eefa..dbd93ed4 100644 --- a/resources/Schema/Entities/SpawnerWithPlayerModel.xml +++ b/resources/Schema/Entities/SpawnerWithPlayerModel.xml @@ -4,7 +4,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh diff --git a/resources/Schema/Entities/SplatMapTesWorld.xml b/resources/Schema/Entities/SplatMapTesWorld.xml new file mode 100644 index 00000000..11660a63 --- /dev/null +++ b/resources/Schema/Entities/SplatMapTesWorld.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + Models/Test/SplatMapTest.mesh + + + + + + + + diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 2cdf4e17..7f40e6de 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -6,7 +6,7 @@ - Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -36,7 +36,7 @@ 0 - Models/Camera.mesh + Models/Widgets/Camera.mesh diff --git a/resources/Schema/Entities/Testingu b/resources/Schema/Entities/Testingu new file mode 100644 index 00000000..145550f4 --- /dev/null +++ b/resources/Schema/Entities/Testingu @@ -0,0 +1,45 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/aim_rays.xml b/resources/Schema/Entities/aim_rays.xml new file mode 100644 index 00000000..c8dac9a3 --- /dev/null +++ b/resources/Schema/Entities/aim_rays.xml @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + 1 + + + Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/awdawd b/resources/Schema/Entities/awdawd new file mode 100644 index 00000000..d8dacb54 --- /dev/null +++ b/resources/Schema/Entities/awdawd @@ -0,0 +1,23 @@ + + + + + + + L_Foot + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/joint.xml b/resources/Schema/Entities/joint.xml new file mode 100644 index 00000000..912693f3 --- /dev/null +++ b/resources/Schema/Entities/joint.xml @@ -0,0 +1,22 @@ + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 972a45e1..16366a67 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -38,6 +38,7 @@ + diff --git a/resources/Shaders/FillDepthBufferSkinned.vert.glsl b/resources/Shaders/FillDepthBufferSkinned.vert.glsl new file mode 100644 index 00000000..ce2a142d --- /dev/null +++ b/resources/Shaders/FillDepthBufferSkinned.vert.glsl @@ -0,0 +1,33 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + + +layout(location = 0) in vec3 Position; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + mat4 boneTransform = mat4(1); + + if(BoneWeights[0] > 0.0f){ + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = vec3(0.0); +} \ No newline at end of file diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index c09e0438..471ee20b 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -9,6 +9,11 @@ uniform vec2 ScreenDimensions; uniform vec4 FillColor; uniform vec4 AmbientColor; uniform float FillPercentage; + +uniform vec2 DiffuseUVRepeat; +uniform vec2 NormalUVRepeat; +uniform vec2 SpecularUVRepeat; +uniform vec2 GlowUVRepeat; layout (binding = 0) uniform sampler2D DiffuseTexture; layout (binding = 1) uniform sampler2D NormalMapTexture; layout (binding = 2) uniform sampler2D SpecularMapTexture; @@ -114,11 +119,11 @@ vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textu void main() { - vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); - vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); - vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate); + vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate * DiffuseUVRepeat); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate * GlowUVRepeat); + vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate * SpecularUVRepeat); vec4 position = V * M * vec4(Input.Position, 1.0); - vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, NormalMapTexture); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture); normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); vec4 viewVec = normalize(-position); diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 3b3e931c..d475d825 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -3,15 +3,12 @@ uniform mat4 M; uniform mat4 V; uniform mat4 P; -uniform mat4 Bones[100]; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; layout(location = 2) in vec3 Tangent; layout(location = 3) in vec3 BiTangent; layout(location = 4) in vec2 TextureCoords; -layout(location = 5) in vec4 BoneIndices; -layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; @@ -25,19 +22,9 @@ out VertexData{ void main() { - - - mat4 boneTransform = mat4(1); - if(BoneWeights[0] > 0.0f){ - boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] - + BoneWeights[1] * Bones[int(BoneIndices[1])] - + BoneWeights[2] * Bones[int(BoneIndices[2])] - + BoneWeights[3] * Bones[int(BoneIndices[3])]; - } - - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + gl_Position = P*V*M * vec4(Position, 1.0); - Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + Output.Position = Position; Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(M * vec4(Normal, 0.0)); Output.Tangent = vec3(M * vec4(Tangent, 0.0)); diff --git a/resources/Shaders/ForwardPlusSkinned.vert.glsl b/resources/Shaders/ForwardPlusSkinned.vert.glsl new file mode 100644 index 00000000..5fd55a8c --- /dev/null +++ b/resources/Shaders/ForwardPlusSkinned.vert.glsl @@ -0,0 +1,46 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; +}Output; + +void main() +{ + mat4 boneTransform = mat4(1); + + if(BoneWeights[0] > 0.0f){ + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + Output.TextureCoordinate = TextureCoords; + Output.Normal = vec3(M * boneTransform * vec4(Normal, 0.0)); + Output.Tangent = vec3(M * vec4(Tangent, 0.0)); + Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); + Output.ExplosionColor = vec4(1.0); + Output.ExplosionPercentageElapsed = 0.0; +} \ No newline at end of file diff --git a/resources/Shaders/ForwardPlusSplatMap.frag.glsl b/resources/Shaders/ForwardPlusSplatMap.frag.glsl new file mode 100644 index 00000000..c4908534 --- /dev/null +++ b/resources/Shaders/ForwardPlusSplatMap.frag.glsl @@ -0,0 +1,277 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec2 ScreenDimensions; +uniform float FillPercentage; +uniform vec4 DiffuseColor; +uniform vec4 FillColor; +uniform vec4 Color; +uniform vec4 AmbientColor; + +//Get bineded at the same time as the textures +uniform vec2 DiffuseUVRepeat1; +uniform vec2 DiffuseUVRepeat2; +uniform vec2 DiffuseUVRepeat3; +uniform vec2 DiffuseUVRepeat4; +uniform vec2 DiffuseUVRepeat5; +uniform vec2 NormalUVRepeat1; +uniform vec2 NormalUVRepeat2; +uniform vec2 NormalUVRepeat3; +uniform vec2 NormalUVRepeat4; +uniform vec2 NormalUVRepeat5; +uniform vec2 SpecularUVRepeat1; +uniform vec2 SpecularUVRepeat2; +uniform vec2 SpecularUVRepeat3; +uniform vec2 SpecularUVRepeat4; +uniform vec2 SpecularUVRepeat5; +uniform vec2 GlowUVRepeat1; +uniform vec2 GlowUVRepeat2; +uniform vec2 GlowUVRepeat3; +uniform vec2 GlowUVRepeat4; +uniform vec2 GlowUVRepeat5; +layout (binding = 0) uniform sampler2D SplatMapTexture; +layout (binding = 1) uniform sampler2D DiffuseTexture1; +layout (binding = 2) uniform sampler2D DiffuseTexture2; +layout (binding = 3) uniform sampler2D DiffuseTexture3; +layout (binding = 4) uniform sampler2D DiffuseTexture4; +layout (binding = 5) uniform sampler2D DiffuseTexture5; +layout (binding = 6) uniform sampler2D NormalMapTexture1; +layout (binding = 7) uniform sampler2D NormalMapTexture2; +layout (binding = 8) uniform sampler2D NormalMapTexture3; +layout (binding = 9) uniform sampler2D NormalMapTexture4; +layout (binding = 10) uniform sampler2D NormalMapTexture5; +layout (binding = 11) uniform sampler2D SpecularMapTexture1; +layout (binding = 12) uniform sampler2D SpecularMapTexture2; +layout (binding = 13) uniform sampler2D SpecularMapTexture3; +layout (binding = 14) uniform sampler2D SpecularMapTexture4; +layout (binding = 15) uniform sampler2D SpecularMapTexture5; +layout (binding = 16) uniform sampler2D GlowMapTexture1; +layout (binding = 17) uniform sampler2D GlowMapTexture2; +layout (binding = 18) uniform sampler2D GlowMapTexture3; +layout (binding = 19) uniform sampler2D GlowMapTexture4; +layout (binding = 20) uniform sampler2D GlowMapTexture5; + +#define TILE_SIZE 16 + +struct LightSource { + vec4 Position; + vec4 Direction; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + int Type; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + LightSource List[]; +} LightSources; + +struct LightGrid { + float Start; + float Amount; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + float LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; +}Input; + +out vec4 sceneColor; +out vec4 bloomColor; + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist, float falloff) { + return 1.0 - smoothstep(radius * 0.3, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist, falloff); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + +LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal) +{ + vec4 L = normalize( -vec4(direction.xyz, 0) ); + + LightResult result; + result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity; + result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity; + return result; +} + +vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textureCoordinate, sampler2D normalMap) +{ + mat3 TBN = mat3(tangent, bitangent, normal); + vec3 NormalMap = texture(normalMap, textureCoordinate).xyz * 2.0 - vec3(1.0); + return vec4(TBN * normalize(NormalMap), 0.0); +} + +#define TEXTURE_TILE 5.0 + +vec4 CalcBlendedTexel(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, sampler2D A, sampler2D D, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, vec2 A_TileValues, vec2 D_TileValues){ + vec4 R_Channel = texture2D(R, Input.TextureCoordinate * R_TileValues); + vec4 G_Channel = texture2D(G, Input.TextureCoordinate * G_TileValues); + vec4 B_Channel = texture2D(B, Input.TextureCoordinate * B_TileValues); + vec4 A_Channel = texture2D(A, Input.TextureCoordinate * A_TileValues); + vec4 D_Channel = texture2D(D, Input.TextureCoordinate * D_TileValues); + + float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; + if(total > 1.0f){ + blendValue.r / total; + blendValue.g / total; + blendValue.b / total; + blendValue.a / total; + } + float D_percent = clamp( 1.0f - total, 0.0f, 1.0f); + + return blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel + + blendValue.a * A_Channel + + D_percent * D_Channel; +} + +vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, sampler2D A, sampler2D D, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, vec2 A_TileValues, vec2 D_TileValues){ + mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal); + vec3 R_Channel = texture(R, Input.TextureCoordinate * R_TileValues).xyz * 2.0 - vec3(1.0); + vec3 G_Channel = texture(G, Input.TextureCoordinate * G_TileValues).xyz * 2.0 - vec3(1.0); + vec3 B_Channel = texture(B, Input.TextureCoordinate * B_TileValues).xyz * 2.0 - vec3(1.0); + vec3 A_Channel = texture(A, Input.TextureCoordinate * A_TileValues).xyz * 2.0 - vec3(1.0); + vec3 D_Channel = texture(D, Input.TextureCoordinate * D_TileValues).xyz * 2.0 - vec3(1.0); + + float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; + if(total > 1.0f){ + blendValue.r / total; + blendValue.g / total; + blendValue.b / total; + blendValue.a / total; + } + float D_percent = clamp( 1.0f - total, 0.0f, 1.0f); + + vec3 Normal_result = blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel + + blendValue.a * A_Channel + + D_percent * D_Channel; + + return vec4(TBN * normalize(Normal_result), 0.0); +} + +void main() +{ + vec4 splatTexel = texture2D(SplatMapTexture, Input.TextureCoordinate); + + vec4 diffuseTexel = CalcBlendedTexel(splatTexel, DiffuseTexture1, DiffuseTexture2, DiffuseTexture3, DiffuseTexture4, DiffuseTexture5, + DiffuseUVRepeat1, DiffuseUVRepeat2, DiffuseUVRepeat3, DiffuseUVRepeat4, DiffuseUVRepeat5); + vec4 glowTexel = CalcBlendedTexel(splatTexel, GlowMapTexture1, GlowMapTexture2, GlowMapTexture3, GlowMapTexture4, GlowMapTexture5, + GlowUVRepeat1, GlowUVRepeat2, GlowUVRepeat3, GlowUVRepeat4, GlowUVRepeat5); + vec4 specularTexel = CalcBlendedTexel(splatTexel, SpecularMapTexture1, SpecularMapTexture2, SpecularMapTexture3, SpecularMapTexture4, SpecularMapTexture5, + SpecularUVRepeat1, SpecularUVRepeat2, SpecularUVRepeat3, SpecularUVRepeat4, SpecularUVRepeat5); + vec4 position = V * M * vec4(Input.Position, 1.0); + //vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, SplatMapTexture); + vec4 normal = V * CalcBlendedNormal(splatTexel, NormalMapTexture1, NormalMapTexture2, NormalMapTexture3, NormalMapTexture4, NormalMapTexture5, + NormalUVRepeat1, NormalUVRepeat2, NormalUVRepeat3, NormalUVRepeat4, NormalUVRepeat5); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-position); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/TILE_SIZE); + tilePos.y = int(gl_FragCoord.y/TILE_SIZE); + + LightResult totalLighting; + totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); + int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); + + int start = int(LightGrids.Data[currentTile].Start); + int amount = int(LightGrids.Data[currentTile].Amount); + + for(int i = start; i < start + amount; i++) { + + int l = int(LightIndex[i]); + LightSource light = LightSources.List[l]; + + LightResult light_result; + //These if statements should be removed. + if(light.Type == 1) { // point + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff); + } else if (light.Type == 2) { //Directional + light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + } + totalLighting.Diffuse += light_result.Diffuse; + totalLighting.Specular += light_result.Specular; + } + + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); + color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + + if(pos <= FillPercentage) { + color_result += FillColor; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + color_result += glowTexel*3; + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); + + //Tiled Debug Code + /* + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { + sceneColor += vec4(0.5, 0, 0, 0); + } else { + sceneColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1); + } + */ +} + + diff --git a/resources/Shaders/Picking.vert.glsl b/resources/Shaders/Picking.vert.glsl index 205a8fdd..f888cd16 100644 --- a/resources/Shaders/Picking.vert.glsl +++ b/resources/Shaders/Picking.vert.glsl @@ -3,15 +3,12 @@ uniform mat4 M; uniform mat4 V; uniform mat4 P; -uniform mat4 Bones[100]; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; layout(location = 2) in vec3 Tangent; layout(location = 3) in vec3 BiTangent; layout(location = 4) in vec2 TextureCoords; -layout(location = 5) in vec4 BoneIndices; -layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; @@ -19,14 +16,6 @@ out VertexData{ void main() { - mat4 boneTransform = mat4(1); - if(BoneWeights[0] > 0.0f){ - boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] - + BoneWeights[1] * Bones[int(BoneIndices[1])] - + BoneWeights[2] * Bones[int(BoneIndices[2])] - + BoneWeights[3] * Bones[int(BoneIndices[3])]; - } - - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); - Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + gl_Position = P*V*M * vec4(Position, 1.0); + Output.Position = Position, 1.0; } \ No newline at end of file diff --git a/resources/Shaders/PickingSkinned.vert.glsl b/resources/Shaders/PickingSkinned.vert.glsl new file mode 100644 index 00000000..205a8fdd --- /dev/null +++ b/resources/Shaders/PickingSkinned.vert.glsl @@ -0,0 +1,32 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + mat4 boneTransform = mat4(1); + if(BoneWeights[0] > 0.0f){ + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; +} \ No newline at end of file diff --git a/resources/Shaders/ShieldStencilSkinned.vert.glsl b/resources/Shaders/ShieldStencilSkinned.vert.glsl new file mode 100644 index 00000000..ce2a142d --- /dev/null +++ b/resources/Shaders/ShieldStencilSkinned.vert.glsl @@ -0,0 +1,33 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + + +layout(location = 0) in vec3 Position; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + mat4 boneTransform = mat4(1); + + if(BoneWeights[0] > 0.0f){ + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = vec3(0.0); +} \ No newline at end of file diff --git a/resources/Shaders/Sprite.frag.glsl b/resources/Shaders/Sprite.frag.glsl new file mode 100644 index 00000000..c391322d --- /dev/null +++ b/resources/Shaders/Sprite.frag.glsl @@ -0,0 +1,41 @@ +#version 430 + +uniform vec4 Color; +uniform vec4 FillColor; +uniform float FillPercentage; +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout (binding = 0) uniform sampler2D DiffuseTexture; +layout (binding = 1) uniform sampler2D GlowMapTexture; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; +}Input; + + +out vec4 sceneColor; +out vec4 bloomColor; + +void main() +{ + vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); + + vec4 color_result = Color * diffuseTexel; + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + if(pos <= FillPercentage) { + color_result += FillColor; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + color_result += glowTexel*3; + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); +} + + diff --git a/resources/Shaders/Sprite.vert.glsl b/resources/Shaders/Sprite.vert.glsl new file mode 100644 index 00000000..e910a26a --- /dev/null +++ b/resources/Shaders/Sprite.vert.glsl @@ -0,0 +1,24 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 4) in vec2 TextureCoords; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = P * M * vec4(Position, 1.0); + + Output.Position = Position; + Output.TextureCoordinate = TextureCoords; + Output.Normal = Normal; +} \ No newline at end of file diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d82ec3fb..07080caf 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -184,7 +184,7 @@ bool RayVsTriangle(const Ray& ray, } outDistance = dist; outUCoord = glm::dot(m, DxE2) * DetInv; - outVCoord = glm::dot(ray.Direction(), MxE1) * DetInv; + outVCoord = glm::dot(ray.Direction(), MxE1) * DetInv; //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem //If u and v are positive, u+v <= 1, dist is positive, and less than closest. @@ -331,7 +331,7 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, float push = rightRes < -leftRes ? rightRes : leftRes; float absPushSq = abs(push); absPushSq *= absPushSq; - + if (absPushSq < resolutionDistanceSq) { resolutionDistanceSq = absPushSq; resolutionDirection = push * normal; @@ -356,8 +356,8 @@ constexpr bool FaceIsGround(float faceNormalY) //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); -bool AABBvsTriangle(const AABB& box, - const std::array& triPos, +bool AABBvsTriangle(const AABB& box, + const std::array& triPos, const glm::vec3& originalBoxVelocity, float verticalStepHeight, bool& isOnGround, @@ -386,7 +386,7 @@ bool AABBvsTriangle(const AABB& box, Resolution() : DistanceSq(INFINITY) , Vector(0.f) - {} + { } BoxTriResolveCase Case; float DistanceSq; glm::vec3 Vector; @@ -526,9 +526,9 @@ bool AABBvsTriangle(const AABB& box, return true; } -bool AABBvsTriangles(const AABB& box, - const std::vector& modelVertices, - const std::vector& modelIndices, +bool AABBvsTriangles(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, float verticalStepHeight, @@ -638,4 +638,4 @@ boost::optional AbsoluteAABBExplosionEffect(EntityWrapper& entity) return aabb; } -} +} \ No newline at end of file diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 7d8905a8..afd09022 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -41,7 +41,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->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = inOutVelocity; if (isOnGround) { diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp index 2126362f..4566410f 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -15,33 +15,39 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a Skeleton* skeleton = model->m_RawModel->m_Skeleton; - const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["Name"]); - if(animation != nullptr) { - double animationSpeed = (double)animationComponent["Speed"]; + if(skeleton == nullptr) { + return; + } + + for (int i = 1; i <= 3; i++) { + const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + + if (animation == nullptr) { + return; + } + + double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; if (animationSpeed != 0.0) { - double nextTime = (double)animationComponent["Time"] + animationSpeed * dt; + double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; - if (!(bool)animationComponent["Loop"] && glm::abs(nextTime) > animation->Duration) { - (double&)animationComponent["Time"] = glm::sign(nextTime) * animation->Duration; - (double&)animationComponent["Speed"] = 0.0; + if (!(bool)animationComponent["Loop" + std::to_string(i)] && glm::abs(nextTime) > animation->Duration) { + (double&)animationComponent["Time" + std::to_string(i)] = glm::sign(nextTime) * animation->Duration; + (double&)animationComponent["Speed" + std::to_string(i)] = 0.0; Events::AnimationComplete e; e.Entity = entity; - e.Name = (std::string)animationComponent["Name"]; + e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; m_EventBroker->Publish(e); } else { if (glm::abs(nextTime) > animation->Duration) { - (double&)animationComponent["Time"] = glm::abs(nextTime) - animation->Duration; + (double&)animationComponent["Time" + std::to_string(i)] = glm::abs(nextTime) - animation->Duration; } else { - (double&)animationComponent["Time"] = nextTime; + (double&)animationComponent["Time" + std::to_string(i)] = nextTime; } } } - } - - - + } } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp new file mode 100644 index 00000000..bdc45fa6 --- /dev/null +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -0,0 +1,70 @@ +#include "Rendering/BoneAttachmentSystem.h" + +void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) +{ + + + if(!entity.HasComponent("Transform")) { + return; + } + + auto parent = entity.FirstParentWithComponent("Animation"); + if (!parent.HasComponent("Model")) { + return; + } + Model* model; + try { + model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + + if(skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation(parent["Animation"]["AnimationName1"]); + + if (!animation) { + return; + } + + int id = skeleton->GetBoneID(entity["BoneAttachment"]["BoneName"]); + + if(id == -1) { + return; + } + + + glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time1"], glm::mat4(1)); + + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); + + glm::vec3 angles; + angles.y = asin(-boneTransform[0][2]); + if (cos(angles.y) != 0) { + angles.x = atan2(boneTransform[1][2], boneTransform[2][2]); + angles.z = atan2(boneTransform[0][1], boneTransform[0][0]); + } else { + angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]); + angles.z = 0; + } + + if ((bool)entity["BoneAttachment"]["InheritPosition"]) { + (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { + (glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritScale"]) { + (glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; + } +} diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 5d8b2359..6cf3a2cc 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -77,8 +77,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //Iterate some times to make it more gaussian. for (int i = 1; i < m_iterations; i++) { @@ -90,8 +90,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //horizontal pass @@ -102,8 +102,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } //final vertical gaussian after the iterations are done @@ -115,8 +115,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); GLERROR("DrawBloomPass::Draw: END"); } diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index 37153800..c82d614f 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -40,6 +40,6 @@ void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLu glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 72a65e80..0d08b98f 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -79,6 +79,62 @@ void DrawFinalPass::InitializeShaderPrograms() m_ExplosionEffectProgram->Link(); GLERROR("Creating explosion program"); + m_ForwardPlusSplatMapProgram = ResourceManager::Load("#ForwardPlusSplatMapProgram"); + m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ForwardPlusSplatMapProgram->Compile(); + m_ForwardPlusSplatMapProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapProgram->Link(); + GLERROR("Creating Forward SplatMap program"); + + m_ExplosionEffectSplatMapProgram = ResourceManager::Load("#ExplosionEffectSplatMapProgram"); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ExplosionEffectSplatMapProgram->Compile(); + m_ExplosionEffectSplatMapProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapProgram->Link(); + GLERROR("Creating explosion SplatMap program"); + + m_ForwardPlusSkinnedProgram = ResourceManager::Load("#ForwardPlusSkinnedProgram"); + m_ForwardPlusSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ForwardPlusSkinnedProgram->Compile(); + m_ForwardPlusSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSkinnedProgram->Link(); + GLERROR("Creating forward+ Skinned program"); + + m_ExplosionEffectSkinnedProgram = ResourceManager::Load("#ExplosionEffectSkinnedProgram"); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ExplosionEffectSkinnedProgram->Compile(); + m_ExplosionEffectSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSkinnedProgram->Link(); + GLERROR("Creating explosion Skinned program"); + + m_ExplosionEffectSplatMapSkinnedProgram = ResourceManager::Load("#ExplosionEffectSplatMapSkinnedProgram"); + m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ExplosionEffectSplatMapSkinnedProgram->Compile(); + m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapSkinnedProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); + + m_ForwardPlusSplatMapSkinnedProgram = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram"); + m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ForwardPlusSplatMapSkinnedProgram->Compile(); + m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapSkinnedProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); + m_ShieldToStencilProgram = ResourceManager::Load("#ShieldToStencilProgram"); m_ShieldToStencilProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencil.vert.glsl"))); m_ShieldToStencilProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); @@ -86,12 +142,26 @@ void DrawFinalPass::InitializeShaderPrograms() m_ShieldToStencilProgram->Link(); GLERROR("Creating Shield program"); + m_ShieldToStencilSkinnedProgram = ResourceManager::Load("#ShieldToStencilProgramSkinned"); + m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencilSkinned.vert.glsl"))); + m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); + m_ShieldToStencilSkinnedProgram->Compile(); + m_ShieldToStencilSkinnedProgram->Link(); + GLERROR("Creating Shield Skinned program"); + m_FillDepthBufferProgram = ResourceManager::Load("#FillDepthBufferProgram"); m_FillDepthBufferProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBuffer.vert.glsl"))); m_FillDepthBufferProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); m_FillDepthBufferProgram->Compile(); m_FillDepthBufferProgram->Link(); GLERROR("Creating DepthFill program"); + + m_FillDepthBufferSkinnedProgram = ResourceManager::Load("#FillDepthBufferProgramSkinned"); + m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBufferSkinned.vert.glsl"))); + m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); + m_FillDepthBufferSkinnedProgram->Compile(); + m_FillDepthBufferSkinnedProgram->Link(); + GLERROR("Creating DepthFill program"); } void DrawFinalPass::Draw(RenderScene& scene) @@ -125,11 +195,11 @@ void DrawFinalPass::Draw(RenderScene& scene) //Draw Opaque shielded objects state->StencilFunc(GL_NOTEQUAL, 1, 0xFF); state->StencilMask(0x00); - DrawShieldedModelRenderQueue(scene.Jobs.OpaqueShieldedObjects, scene); + DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing GLERROR("Shielded Opaque object"); //Draw Transparen Shielded objects - DrawShieldedModelRenderQueue(scene.Jobs.TransparentShieldedObjects, scene); + DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene); //might need changing GLERROR("Shielded Transparent objects"); GLERROR("END"); @@ -223,107 +293,205 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); GLERROR("forwardHandle"); - GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); + GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); GLERROR("explosionHandle"); + GLuint explosionSplatMapHandle = m_ExplosionEffectSplatMapProgram->GetHandle(); + GLERROR("explosionSplatMapHandle"); + GLuint forwardSplatHandle = m_ForwardPlusSplatMapProgram->GetHandle(); + GLERROR("forwardSplatHandle"); + GLuint forwardSkinnedHandle = m_ForwardPlusSkinnedProgram->GetHandle(); + GLERROR("forwardSkinnedHandle"); + GLuint explosionSkinnedHandle = m_ExplosionEffectSkinnedProgram->GetHandle(); + GLERROR("explosionSkinnedHandle"); + GLuint explosionSplatMapSkinnedHandle = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); + GLERROR("explosionSplatMapSkinnedHandle"); + GLuint forwardSplatMapSkinnedHandle = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); + GLERROR("forwardSplatSkinnedHandle"); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); - for(auto &job : jobs) - { - auto explosionEffectJob = std::dynamic_pointer_cast(job); - if(explosionEffectJob) { - //Bind program - if(GLERROR("Prebind")) { - continue; - } - m_ExplosionEffectProgram->Bind(); - if(GLERROR("BindProgram")) { - continue; - } + for (auto &job : jobs) { + auto explosionEffectJob = std::dynamic_pointer_cast(job); + if (explosionEffectJob) { + switch (explosionEffectJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (explosionEffectJob->Model->IsSkinned()) { + m_ExplosionEffectSkinnedProgram->Bind(); + GLERROR("Bind ExplosionEffectSkinned program"); + //bind uniforms + BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); + std::vector frameBones; + if (explosionEffectJob->AnimationOffset.animation != nullptr) { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); + } else { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_ExplosionEffectProgram->Bind(); + GLERROR("Bind ExplosionEffect program"); + //bind uniforms + BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionHandle, explosionEffectJob); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (explosionEffectJob->Model->IsSkinned()) { + m_ExplosionEffectSplatMapSkinnedProgram->Bind(); + GLERROR("Bind ExplosionEffectSplatMapSkinned program"); + //bind uniforms + BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); + GLERROR("asdasd"); + std::vector frameBones; + if (explosionEffectJob->AnimationOffset.animation != nullptr) { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); + } else { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_ExplosionEffectSplatMapProgram->Bind(); + GLERROR("Bind ExplosionEffectSplatMap program"); + //bind uniforms + //bind uniforms + BindExplosionUniforms(explosionSplatMapHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapHandle, explosionEffectJob); + GLERROR("asdasd"); + } + break; + } + } glDisable(GL_CULL_FACE); - //Bind uniforms - BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); - if(GLERROR("BindExplosionUniforms")) { - continue; - } - - if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { - - if (explosionEffectJob->Animation != nullptr) { - std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } - } - if(GLERROR("Animation")) { - continue; - } - - //bind textures - BindExplosionTextures(explosionEffectJob); - if(GLERROR("BindExplosionTextures")) { - continue; - } //draw glBindVertexArray(explosionEffectJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); glEnable(GL_CULL_FACE); - if(GLERROR("explosion effect end")) { - continue; - } + GLERROR("explosion effect end"); + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + //bind forward program + //TODO: JOHAN/TOBIAS: Bind shader based on ModelJob->ShaderID; + switch (modelJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (modelJob->Model->IsSkinned()) { + m_ForwardPlusSkinnedProgram->Bind(); + GLERROR("Bind ForwardPlusSkinnedProgram"); + //bind uniforms + BindModelUniforms(forwardSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSkinnedHandle, modelJob); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } else { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - //bind forward program - m_ForwardPlusProgram->Bind(); - glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - - //bind uniforms - BindModelUniforms(forwardHandle, modelJob, scene); - - //bind textures - BindModelTextures(modelJob); - - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_ForwardPlusProgram->Bind(); + GLERROR("Bind ForwardPlusProgram"); + //bind uniforms + BindModelUniforms(forwardHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardHandle, modelJob); + } + break; } - } + case RawModel::MaterialType::SplatMapping: + { + if (modelJob->Model->IsSkinned()) { + m_ForwardPlusSplatMapSkinnedProgram->Bind(); + GLERROR("Bind SplatMap program"); + //bind uniforms + BindModelUniforms(forwardSplatMapSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); + GLERROR("asdasd"); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - //draw - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); - if(GLERROR("models end")) { - continue; + } else { + m_ForwardPlusSplatMapProgram->Bind(); + GLERROR("Bind SplatMap program"); + //bind uniforms + BindModelUniforms(forwardSplatHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatHandle, modelJob); + GLERROR("asdasd"); + } + break; + } + } + //draw + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); + if (GLERROR("models end")) { + continue; + } } } } - } - } void DrawFinalPass::DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene) { - m_ShieldToStencilProgram->Bind(); - GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); for (auto &job : jobs) { auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + if(modelJob->Model->IsSkinned()) { + m_ShieldToStencilSkinnedProgram->Bind(); + GLuint shaderHandle = m_ShieldToStencilSkinnedProgram->GetHandle(); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_ShieldToStencilProgram->Bind(); + GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle(); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + + } glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); @@ -366,19 +534,20 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::listModel->m_RawModel->m_Skeleton != nullptr) { - - if (explosionEffectJob->Animation != nullptr) { - std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } + std::vector frameBones; + if (explosionEffectJob->AnimationOffset.animation != nullptr) { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset); + } else { + frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations); } + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + if (GLERROR("Animation")) { continue; } //bind textures - BindExplosionTextures(explosionEffectJob); + BindExplosionTextures(explosionHandle, explosionEffectJob); if (GLERROR("BindExplosionTextures")) { continue; } @@ -402,15 +571,16 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::listModel->m_RawModel->m_Skeleton != nullptr) { - - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); } + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + //draw glBindVertexArray(modelJob->Model->VAO); @@ -427,25 +597,35 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene) { - m_FillDepthBufferProgram->Bind(); - GLuint shaderHandle = m_FillDepthBufferProgram->GetHandle(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - + + for (auto &job : jobs) { auto modelJob = std::dynamic_pointer_cast(job); - //bind uniforms - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + if(modelJob->Model->IsSkinned()) { + m_FillDepthBufferSkinnedProgram->Bind(); + GLuint shaderHandle = m_FillDepthBufferSkinnedProgram->GetHandle(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_FillDepthBufferProgram->Bind(); + GLuint shaderHandle = m_FillDepthBufferProgram->GetHandle(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); } + //draw glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); @@ -459,108 +639,314 @@ void DrawFinalPass::DrawToDepthBuffer(std::list>& job void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { + GLERROR("Bind 1 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + GLERROR("Bind 2 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + GLERROR("Bind 3 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + GLERROR("Bind 4 uniform"); glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLERROR("Bind 5 uniform"); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); + GLERROR("Bind 6 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + GLERROR("Bind 7 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); + GLERROR("Bind 8 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor)); + GLERROR("Bind 9 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness); + GLERROR("Bind 10 uniform"); glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); + GLERROR("Bind 11 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar); + GLERROR("Bind 12 uniform"); glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity)); + GLERROR("Bind 13 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance); + GLERROR("Bind 14 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration); + GLERROR("Bind 15 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); + GLERROR("Bind 16 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); + GLERROR("Bind 17 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); + GLERROR("Bind 18 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); + GLERROR("Bind 19 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); GLERROR("END"); } void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + GLERROR("Bind 1 uniform"); + GLint Location_M = glGetUniformLocation(shaderHandle, "M"); + glUniformMatrix4fv(Location_M, 1, GL_FALSE, glm::value_ptr(job->Matrix)); + GLERROR("Bind 2 uniform"); + GLint Location_V = glGetUniformLocation(shaderHandle, "V"); + glUniformMatrix4fv(Location_V, 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + GLERROR("Bind 3 uniform"); + GLint Location_P = glGetUniformLocation(shaderHandle, "P"); + glUniformMatrix4fv(Location_P, 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + GLERROR("Bind 4 uniform"); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLint Location_ScreenDimensions = glGetUniformLocation(shaderHandle, "ScreenDimensions"); + glUniform2f(Location_ScreenDimensions, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLERROR("Bind 5 uniform"); - glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); - glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); - glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); - glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); - glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLint Location_FillPercentage = glGetUniformLocation(shaderHandle, "FillPercentage"); + glUniform1f(Location_FillPercentage, job->FillPercentage); + GLERROR("Bind 6 uniform"); + GLint Location_DiffuseColor = glGetUniformLocation(shaderHandle, "DiffuseColor"); + glUniform4fv(Location_DiffuseColor, 1, glm::value_ptr(job->DiffuseColor)); + GLERROR("Bind 7 uniform"); + GLint Location_FillColor = glGetUniformLocation(shaderHandle, "FillColor"); + glUniform4fv(Location_FillColor, 1, glm::value_ptr(job->FillColor)); + GLERROR("Bind 8 uniform"); + GLint Location_Color = glGetUniformLocation(shaderHandle, "Color"); + glUniform4fv(Location_Color, 1, glm::value_ptr(job->Color)); + GLERROR("Bind 9 uniform"); + GLint Location_AmbientColor = glGetUniformLocation(shaderHandle, "AmbientColor"); + glUniform4fv(Location_AmbientColor, 1, glm::value_ptr(scene.AmbientColor)); - GLERROR("END"); + GLERROR("END"); } - -void DrawFinalPass::BindExplosionTextures(std::shared_ptr& job) +void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptr& job) { - glActiveTexture(GL_TEXTURE0); - if (job->DiffuseTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } + switch (job->Type) { + case RawModel::MaterialType::SingleTextures: + case RawModel::MaterialType::Basic: + { + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE1); - if (job->NormalTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE1); + if (job->NormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE2); - if (job->SpecularTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE2); + if (job->SpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE3); - if (job->IncandescenceTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE3); + if (job->IncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, job->SplatMap->Texture->m_Texture); + + int texturePosition = GL_TEXTURE1; + + //Bind 5 diffuse textures + std::string UniformName = "DiffuseUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->DiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Normal textures + UniformName = "NormalUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Specular textures + UniformName = "SpecularUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Incandescence textures + UniformName = "GlowUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + break; + } + } } -void DrawFinalPass::BindModelTextures(std::shared_ptr& job) +void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptr& job) { - glActiveTexture(GL_TEXTURE0); - if (job->DiffuseTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } + switch (job->Type) { + case RawModel::MaterialType::SingleTextures: + case RawModel::MaterialType::Basic: + { + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE1); - if (job->NormalTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE1); + if (job->NormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE2); - if (job->SpecularTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE2); + if (job->SpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE3); - if (job->IncandescenceTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE3); + if (job->IncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, job->SplatMap->Texture->m_Texture); + + int texturePosition = GL_TEXTURE1; + + //Bind 5 diffuse textures + std::string UniformName = "DiffuseUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->DiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Normal textures + UniformName = "NormalUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Specular textures + UniformName = "SpecularUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Incandescence textures + UniformName = "GlowUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + break; + } + } } diff --git a/src/Engine/Rendering/DrawScreenQuadPass.cpp b/src/Engine/Rendering/DrawScreenQuadPass.cpp index b17f5e29..7a522b72 100644 --- a/src/Engine/Rendering/DrawScreenQuadPass.cpp +++ b/src/Engine/Rendering/DrawScreenQuadPass.cpp @@ -32,6 +32,6 @@ void DrawScreenQuadPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } diff --git a/src/Engine/Rendering/Model.cpp b/src/Engine/Rendering/Model.cpp index a61cf8e3..6457c980 100644 --- a/src/Engine/Rendering/Model.cpp +++ b/src/Engine/Rendering/Model.cpp @@ -5,26 +5,77 @@ Model::Model(std::string fileName) //Try loading the model asyncronously, if it throws any exceptions then let it propagate back to caller. m_RawModel = ResourceManager::Load(fileName); - for (auto& group : m_RawModel->MaterialGroups) { - if (!group.TexturePath.empty()) { - group.Texture = std::shared_ptr(ResourceManager::Load(group.TexturePath)); - } - if (!group.NormalMapPath.empty()) { - group.NormalMap = std::shared_ptr(ResourceManager::Load(group.NormalMapPath)); - } - if (!group.SpecularMapPath.empty()) { - group.SpecularMap = std::shared_ptr(ResourceManager::Load(group.SpecularMapPath)); - } - if (!group.IncandescenceMapPath.empty()) { - group.IncandescenceMap = std::shared_ptr(ResourceManager::Load(group.IncandescenceMapPath)); - } + for (auto& materialProperty : m_RawModel->m_Materials) { + switch (materialProperty.type) { + case RawModel::MaterialType::SingleTextures: + { + RawModel::MaterialSingleTextures* materialSingleTexture = static_cast(materialProperty.material); + if (!materialSingleTexture->ColorMap.TexturePath.empty()) { + materialSingleTexture->ColorMap.Texture = std::shared_ptr(ResourceManager::Load(materialSingleTexture->ColorMap.TexturePath)); + } + if (!materialSingleTexture->NormalMap.TexturePath.empty()) { + materialSingleTexture->NormalMap.Texture = std::shared_ptr(ResourceManager::Load(materialSingleTexture->NormalMap.TexturePath)); + } + if (!materialSingleTexture->SpecularMap.TexturePath.empty()) { + materialSingleTexture->SpecularMap.Texture = std::shared_ptr(ResourceManager::Load(materialSingleTexture->SpecularMap.TexturePath)); + } + if (!materialSingleTexture->IncandescenceMap.TexturePath.empty()) { + materialSingleTexture->IncandescenceMap.Texture = std::shared_ptr(ResourceManager::Load(materialSingleTexture->IncandescenceMap.TexturePath)); + } + } + break; + case RawModel::MaterialType::SplatMapping: + { + RawModel::MaterialSplatMapping* materialSplatMapping = static_cast(materialProperty.material); + if (!materialSplatMapping->SplatMap.TexturePath.empty()) { + materialSplatMapping->SplatMap.Texture = std::shared_ptr(ResourceManager::Load(materialSplatMapping->SplatMap.TexturePath)); + } + for (auto& texture : materialSplatMapping->ColorMaps) + { + if (!texture.TexturePath.empty()) { + texture.Texture = std::shared_ptr(ResourceManager::Load(texture.TexturePath)); + } + else { + texture.Texture = nullptr; + } + } + for (auto& texture : materialSplatMapping->NormalMaps) + { + if (!texture.TexturePath.empty()) { + texture.Texture = std::shared_ptr(ResourceManager::Load(texture.TexturePath)); + } else { + texture.Texture = nullptr; + } + } + for (auto& texture : materialSplatMapping->SpecularMaps) + { + if (!texture.TexturePath.empty()) { + texture.Texture = std::shared_ptr(ResourceManager::Load(texture.TexturePath)); + } + else { + texture.Texture = nullptr; + } + } + for (auto& texture : materialSplatMapping->IncandescenceMaps) + { + if (!texture.TexturePath.empty()) { + texture.Texture = std::shared_ptr(ResourceManager::Load(texture.TexturePath)); + } + else { + texture.Texture = nullptr; + } + } + } + break; + } } // Generate GL buffers GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, m_RawModel->m_Vertices.size() * sizeof(RawModel::Vertex), &m_RawModel->m_Vertices[0], GL_STATIC_DRAW); + + glBufferData(GL_ARRAY_BUFFER, m_RawModel->NumVertices() * m_RawModel->VertexSize(), m_RawModel->Vertices(), GL_STATIC_DRAW); glGenBuffers(1, &ElementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer); @@ -35,7 +86,13 @@ Model::Model(std::string fileName) GLERROR("GLEW: BufferFail4"); glBindBuffer(GL_ARRAY_BUFFER, buffer); - std::vector structSizes = { 3, 3, 3, 3, 2, 4, 4 }; + std::vector structSizes; + if (m_RawModel->IsSkinned()) { + structSizes = { 3, 3, 3, 3, 2, 4, 4 }; + } else { + structSizes = { 3, 3, 3, 3, 2 }; + } + int stride = 0; for (int size : structSizes) { stride += size; @@ -49,8 +106,10 @@ Model::Model(std::string fileName) glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; - glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; - glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + if (m_RawModel->IsSkinned()) { + glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + } } GLERROR("GLEW: BufferFail5"); @@ -59,15 +118,19 @@ Model::Model(std::string fileName) glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); - glEnableVertexAttribArray(5); - glEnableVertexAttribArray(6); + if (m_RawModel->IsSkinned()) { + glEnableVertexAttribArray(5); + glEnableVertexAttribArray(6); + } GLERROR("GLEW: BufferFail5"); //CreateBuffers(); glm::vec3 mini(INFINITY); glm::vec3 maxi(-INFINITY); - for (const auto& v : m_RawModel->m_Vertices) { + + for (unsigned int i = 0; i < m_RawModel->NumVertices(); i++) { + const auto& v = m_RawModel->Vertices()[i]; mini = glm::min(mini, v.Position); maxi = glm::max(maxi, v.Position); } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index b0733ae2..fa1b3ca3 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -41,6 +41,14 @@ void PickingPass::InitializeShaderPrograms() m_PickingProgram->Compile(); m_PickingProgram->BindFragDataLocation(0, "TextureFragment"); m_PickingProgram->Link(); + + m_PickingSkinnedProgram = ResourceManager::Load("#PickingSkinnedProgram"); + + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/PickingSkinned.vert.glsl"))); + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); + m_PickingSkinnedProgram->Compile(); + m_PickingSkinnedProgram->BindFragDataLocation(0, "TextureFragment"); + m_PickingSkinnedProgram->Link(); } void PickingPass::Draw(RenderScene& scene) @@ -49,6 +57,7 @@ void PickingPass::Draw(RenderScene& scene) //TODO: Render: Add code for more jobs than modeljobs. GLuint shaderHandle = m_PickingProgram->GetHandle(); + GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle(); m_PickingProgram->Bind(); if (scene.ClearDepth) { @@ -83,18 +92,32 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + if (modelJob->Model->IsSkinned()) + { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } - } + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + } else { + m_PickingProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + } glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); @@ -105,41 +128,50 @@ void PickingPass::Draw(RenderScene& scene) for (auto &job : scene.Jobs.TransparentObjects) { auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; + int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; - PickingInfo pickInfo; - pickInfo.Entity = modelJob->Entity; - pickInfo.World = modelJob->World; - pickInfo.Camera = scene.Camera; + PickingInfo pickInfo; + pickInfo.Entity = modelJob->Entity; + pickInfo.World = modelJob->World; + pickInfo.Camera = scene.Camera; - auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)); - if (color != m_EntityColors.end()) { - pickColor[0] = color->second[0]; - pickColor[1] = color->second[1]; + auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)); + if (color != m_EntityColors.end()) { + pickColor[0] = color->second[0]; + pickColor[1] = color->second[1]; + } else { + m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); + if (m_ColorCounter[0] > 255) { + m_ColorCounter[0] = 0; + m_ColorCounter[1] += 1; } else { - m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); - if (m_ColorCounter[0] > 255) { - m_ColorCounter[0] = 0; - m_ColorCounter[1] += 1; - } else { - m_ColorCounter[0] += 1; - } + m_ColorCounter[0] += 1; } + } - m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; + m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + if (modelJob) { + if (modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_PickingProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } glBindVertexArray(modelJob->Model->VAO); @@ -175,17 +207,27 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + if(modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_PickingProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } glBindVertexArray(modelJob->Model->VAO); @@ -198,6 +240,7 @@ void PickingPass::Draw(RenderScene& scene) auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { + int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; PickingInfo pickInfo; @@ -221,19 +264,38 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + if (modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + + std::vector frameBones; + if (modelJob->AnimationOffset.animation != nullptr) { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset); + } else { + frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations); + } + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } + } else { + m_PickingProgram->Bind(); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } + + + glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); @@ -252,8 +314,8 @@ void PickingPass::ClearPicking() { m_PickingColorsToEntity.clear(); m_EntityColors.clear(); - m_ColorCounter[0] = 1; - m_ColorCounter[1] = 0; + m_ColorCounter[0] = 0; + m_ColorCounter[1] = 1; m_PickingBuffer.Bind(); glClearColor(0.f, 0.f, 0.f, 0.f); diff --git a/src/Engine/Rendering/RawModelAssimp.cpp b/src/Engine/Rendering/RawModelAssimp.cpp index 7bf72a22..6b970f70 100644 --- a/src/Engine/Rendering/RawModelAssimp.cpp +++ b/src/Engine/Rendering/RawModelAssimp.cpp @@ -271,7 +271,7 @@ RawModelAssimp::RawModelAssimp(std::string fileName) skelAnim.Keyframes.push_back(animationFrame); } - m_Skeleton->Animations[animationName] = skelAnim; + m_Skeleton->Animations[animationName1] = skelAnim; } } diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index 59634625..4ebf80b6 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -34,13 +34,20 @@ void RawModelCustom::ReadMeshFile(std::string filePath) ReadMeshFileHeader(offset, fileData); ReadMesh(offset, fileData, fileByteSize); } - delete fileData; + delete[] fileData; } void RawModelCustom::ReadMeshFileHeader(std::size_t& offset, char* fileData) { #ifdef BOOST_LITTLE_ENDIAN - m_Vertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + hasSkin = *(bool*)(fileData + offset); + offset += sizeof(bool); + if (hasSkin) { + m_SkinedVertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + } + else { + m_Vertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + } offset += sizeof(unsigned int); m_Indices.resize(static_cast(*(unsigned int*)(fileData + offset))); offset += sizeof(unsigned int); @@ -57,12 +64,19 @@ void RawModelCustom::ReadMesh(std::size_t& offset, char* fileData, const unsigne void RawModelCustom::ReadVertices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN - if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { - throw Resource::FailedLoadingException("Reading vertices failed"); - } - - memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); - offset += m_Vertices.size() * sizeof(Vertex); + if (hasSkin) { + if (offset + m_SkinedVertices.size() * sizeof(SkinedVertex) > fileByteSize) { + throw Resource::FailedLoadingException("Reading skined vertices failed"); + } + 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) { + throw Resource::FailedLoadingException("Reading vertices failed"); + } + memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); + offset += m_Vertices.size() * sizeof(Vertex); + } #else #endif } @@ -102,14 +116,14 @@ void RawModelCustom::ReadMaterialFile(std::string filePath) if (fileByteSize > 0) { ReadMaterials(offset, fileData, fileByteSize); } - delete fileData; + delete[] fileData; } void RawModelCustom::ReadMaterials(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN unsigned int* numMaterials = (unsigned int*)(fileData); - MaterialGroups.reserve(*numMaterials); + m_Materials.reserve(*numMaterials); offset += sizeof(unsigned int); for (unsigned int i = 0; i < *numMaterials; i++) { @@ -121,83 +135,150 @@ void RawModelCustom::ReadMaterials(std::size_t& offset, char* fileData, const un void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { - MaterialGroup newMaterial; - + MaterialProperties newMaterialProperty; #ifdef BOOST_LITTLE_ENDIAN - if (offset + sizeof(unsigned int) * 4 > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material texture names length failed"); - } + if (offset + sizeof(MaterialType) > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material Type failed"); + } + MaterialType type = *(MaterialType*)(fileData + offset); + offset += sizeof(MaterialType); - unsigned int* nameLengths = (unsigned int*)(fileData + offset); - offset += sizeof(unsigned int) * 4; + switch (type) { + case MaterialType::Basic: + newMaterialProperty.material = new MaterialBasic(); + ReadMaterialBasic(newMaterialProperty.material, offset, fileData, fileByteSize); + break; + case MaterialType::SplatMapping: + newMaterialProperty.material = new MaterialSplatMapping(); + ReadMaterialSplatMapping(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + break; + case MaterialType::SingleTextures: + newMaterialProperty.material = new MaterialSingleTextures(); + ReadMaterialSingleTexture(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + break; + default: + throw Resource::FailedLoadingException("Material contains an unknown MaterialType"); + }; - if (offset + sizeof(float) * 11 + sizeof(unsigned int) * 2 > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material specular, reflection, color and start and end index values failed"); - } - - newMaterial.SpecularExponent = *(float*)(fileData + offset); - offset += sizeof(float); - newMaterial.ReflectionFactor = *(float*)(fileData + offset); - offset += sizeof(float); - - memcpy(&newMaterial.DiffuseColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - memcpy(&newMaterial.SpecularColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - memcpy(&newMaterial.IncandescenceColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - - newMaterial.StartIndex = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); - newMaterial.EndIndex = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); - - if (nameLengths[0] > 0) { - if (offset + nameLengths[0] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material texture path failed"); - } - - newMaterial.TexturePath = "Textures/"; - newMaterial.TexturePath += (fileData + offset); - newMaterial.TexturePath += ".png"; - offset += nameLengths[0]; - } - - if (nameLengths[1] > 0) { - if (offset + nameLengths[1] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material NormalMap path failed"); - } - newMaterial.NormalMapPath = "Textures/"; - newMaterial.NormalMapPath += (fileData + offset); - newMaterial.NormalMapPath += ".png"; - offset += nameLengths[1]; - } - - if (nameLengths[2] > 0) { - if (offset + nameLengths[2] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material SpecularMap path failed"); - } - newMaterial.SpecularMapPath = "Textures/"; - newMaterial.SpecularMapPath += (fileData + offset); - newMaterial.SpecularMapPath += ".png"; - offset += nameLengths[2]; - } - - if (nameLengths[3] > 0) { - if (offset + nameLengths[3] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material IncandescenceMap path failed"); - } - newMaterial.IncandescenceMapPath = "Textures/"; - newMaterial.IncandescenceMapPath += (fileData + offset); - newMaterial.IncandescenceMapPath += ".png"; - offset += nameLengths[3]; - } + newMaterialProperty.type = type; #else #endif - MaterialGroups.push_back(newMaterial); + m_Materials.push_back(newMaterialProperty); +} + +void RawModelCustom::ReadMaterialBasic(RawModelCustom::MaterialBasic* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + if (offset + sizeof(float) * 11 + sizeof(unsigned int) * 2 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material specular, reflection, color and start and end index values failed"); + } + + newMaterial->SpecularExponent = *(float*)(fileData + offset); + offset += sizeof(float); + newMaterial->ReflectionFactor = *(float*)(fileData + offset); + offset += sizeof(float); + + memcpy(&newMaterial->DiffuseColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + memcpy(&newMaterial->SpecularColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + memcpy(&newMaterial->IncandescenceColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + + newMaterial->StartIndex = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + newMaterial->EndIndex = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); +} + +void RawModelCustom::ReadMaterialSingleTexture(RawModelCustom::MaterialSingleTextures* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + ReadMaterialBasic(newMaterial, offset, fileData, fileByteSize); + if (offset + sizeof(unsigned char) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material NumOfMaps failed"); + } + unsigned char numberOfMaps[4]; + memcpy(numberOfMaps, fileData + offset, sizeof(unsigned char) * 4); + offset += sizeof(unsigned char) * 4; + + if (numberOfMaps[0] > 0) + { + ReadMaterialTextureProperties(newMaterial->ColorMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[1] > 0) + { + ReadMaterialTextureProperties(newMaterial->SpecularMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[2] > 0) + { + ReadMaterialTextureProperties(newMaterial->NormalMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[3] > 0) + { + ReadMaterialTextureProperties(newMaterial->IncandescenceMap, offset, fileData, fileByteSize); + } +} + +void RawModelCustom::ReadMaterialSplatMapping(RawModelCustom::MaterialSplatMapping* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + ReadMaterialBasic(newMaterial, offset, fileData, fileByteSize); + ReadMaterialTextureProperties(newMaterial->SplatMap, offset, fileData, fileByteSize); + if (offset + sizeof(unsigned char) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material NumOfMaps failed"); + } + + unsigned char numberOfMaps[4]; + memcpy(numberOfMaps, fileData + offset, sizeof(unsigned char) * 4); + offset += sizeof(unsigned char) * 4; + + newMaterial->ColorMaps.resize(numberOfMaps[0]); + for (unsigned char i = 0; i < numberOfMaps[0]; i++) + { + ReadMaterialTextureProperties(newMaterial->ColorMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->SpecularMaps.resize(numberOfMaps[1]); + for (unsigned char i = 0; i < numberOfMaps[1]; i++) + { + ReadMaterialTextureProperties(newMaterial->SpecularMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->NormalMaps.resize(numberOfMaps[2]); + for (unsigned char i = 0; i < numberOfMaps[2]; i++) + { + ReadMaterialTextureProperties(newMaterial->NormalMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->IncandescenceMaps.resize(numberOfMaps[3]); + for (unsigned char i = 0; i < numberOfMaps[3]; i++) + { + ReadMaterialTextureProperties(newMaterial->IncandescenceMaps[i], offset, fileData, fileByteSize); + } +} + +void RawModelCustom::ReadMaterialTextureProperties(RawModelCustom::TextureProperties& texture, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { + unsigned int nameLength = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + + if (nameLength > 0) { + if (offset + nameLength > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material texture path failed"); + } + texture.TexturePath = "Textures/"; + texture.TexturePath += (fileData + offset); + texture.TexturePath += ".png"; + offset += nameLength; + if (offset + sizeof(glm::vec2) > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material texture UVTiling failed"); + } + memcpy(&texture.UVRepeat[0], fileData + offset, sizeof(glm::vec2)); + offset += sizeof(glm::vec2); + } } void RawModelCustom::ReadAnimationFile(std::string filePath) @@ -207,7 +288,9 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate); if (!in.is_open()) { - //throw Resource::FailedLoadingException("Open animation file failed"); + if (hasSkin) { + throw Resource::FailedLoadingException("Open animation file for a skinned mesh failed, unknown stuff will happen"); + } return; } @@ -233,7 +316,7 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) ReadAnimationBindPoses(offset, fileData, fileByteSize); ReadAnimationClips(offset, fileData, fileByteSize, numAnimations); } - delete fileData; + delete[] fileData; } void RawModelCustom::ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) @@ -318,32 +401,43 @@ void RawModelCustom::ReadAnimationClipSingle(std::size_t& offset, char* fileData if (offset + sizeof(float) > fileByteSize) { throw Resource::FailedLoadingException("Reading AnimationClip duration failed"); } - newAnimation.Duration = *(float*)(fileData + offset); offset += sizeof(float); if (offset + sizeof(unsigned int) > fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationClip NrOfKeyframes failed"); + throw Resource::FailedLoadingException("Reading AnimationClip numberOfJointFrames failed"); } - unsigned int nrOfKeyframes = *(unsigned int*)(fileData + offset); + unsigned int numberOfJointFrames = *(unsigned int*)(fileData + offset); offset += sizeof(unsigned int); - if (offset + sizeof(unsigned int) > fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationClip NrOfJoints failed"); - } - unsigned int nrOfJoints = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); + for (unsigned int i = 0; i < numberOfJointFrames; i++) { + if (offset + sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationClip JointID failed"); + } + int jointID = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); - newAnimation.Keyframes.reserve(nrOfKeyframes); - for (unsigned int i = 0; i < nrOfKeyframes; i++) { - ReadAnimationKeyFrame(offset, fileData, fileByteSize, nrOfJoints, newAnimation); + if (offset + sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationClip numberOFKeyFrames failed"); + } + unsigned int numberOFKeyFrames = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + + if (numberOFKeyFrames > 0) { + newAnimation.JointAnimations[jointID].reserve(numberOFKeyFrames); + + for (unsigned int j = 0; j < numberOFKeyFrames; j++) { + ReadAnimationKeyFrame(offset, fileData, fileByteSize, newAnimation.JointAnimations[jointID]); + } + } } m_Skeleton->Animations[newAnimation.Name] = newAnimation; + //m_Skeleton->Animations[newAnimation.Name].KeyFrameAmount = nrOfKeyframes; #else #endif } -void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation) +void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& animation) { Skeleton::Animation::Keyframe newKeyFrame; @@ -359,17 +453,27 @@ void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, newKeyFrame.Time = *(float*)(fileData + offset); offset += sizeof(float); - if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * numberOfJoints> fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationKeyFrame joints failed"); + if (offset + sizeof(float) * 3 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Position failed"); } + memcpy(&newKeyFrame.BoneProperties.Position[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; - Skeleton::Animation::Keyframe::BoneProperty newBone; - for (unsigned int i = 0; i < numberOfJoints; i++) { - memcpy(&newBone, (fileData + offset), sizeof(Skeleton::Animation::Keyframe::BoneProperty)); - offset += sizeof(Skeleton::Animation::Keyframe::BoneProperty); - newKeyFrame.BoneProperties[newBone.ID] = newBone; + if (offset + sizeof(float) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Rotation failed"); } - animation.Keyframes.push_back(newKeyFrame); + memcpy(&newKeyFrame.BoneProperties.Rotation[0], fileData + offset, sizeof(float) * 4); + offset += sizeof(float) * 4; + + if (offset + sizeof(float) * 3 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Scale failed"); + } + memcpy(&newKeyFrame.BoneProperties.Scale[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + + + animation.push_back(newKeyFrame); + } RawModelCustom::~RawModelCustom() @@ -377,6 +481,9 @@ RawModelCustom::~RawModelCustom() if (m_Skeleton != nullptr) { delete m_Skeleton; } + for (auto material : m_Materials) { + delete material.material; + } } #endif \ No newline at end of file diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 07e65c44..ab9a3c27 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -62,14 +62,14 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) } // Only render children of a camera if that camera is currently active - if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) { - continue; - } + if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) { + continue; + } // Hide things parented to local player if they have the HiddenFromLocalPlayer component - if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) { - continue; - } + if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) { + continue; + } Model* model; try { @@ -111,6 +111,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) fillPercentage )); if (m_World->HasComponent(cModel.EntityID, "Shield")){ + explosionEffectJob->CalculateHash(); Jobs.ShieldObjects.push_back(explosionEffectJob); } else if (m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player")) { @@ -122,6 +123,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) if (cModel["Transparent"]) { Jobs.TransparentShieldedObjects.push_back(explosionEffectJob); } else { + explosionEffectJob->CalculateHash(); Jobs.OpaqueShieldedObjects.push_back(explosionEffectJob); } } else { @@ -132,6 +134,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) if (cModel["Transparent"]) { Jobs.TransparentObjects.push_back(explosionEffectJob); } else { + explosionEffectJob->CalculateHash(); Jobs.OpaqueObjects.push_back(explosionEffectJob); } } @@ -147,6 +150,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) fillPercentage )); if (m_World->HasComponent(cModel.EntityID, "Shield")) { + modelJob->CalculateHash(); Jobs.ShieldObjects.push_back(modelJob); } else if (m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player")) { @@ -158,6 +162,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) if (cModel["Transparent"]) { Jobs.TransparentShieldedObjects.push_back(modelJob); } else { + modelJob->CalculateHash(); Jobs.OpaqueShieldedObjects.push_back(modelJob); } } else { @@ -168,6 +173,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs) if (cModel["Transparent"]) { Jobs.TransparentObjects.push_back(modelJob); } else { + modelJob->CalculateHash(); Jobs.OpaqueObjects.push_back(modelJob); } } @@ -233,7 +239,7 @@ void RenderSystem::fillText(std::list>& jobs, World* if (texts == nullptr) { return; } - + for (auto& textComponent : *texts) { bool visible = textComponent["Visible"]; if (!visible) { @@ -290,6 +296,8 @@ void RenderSystem::Update(double dt) fillModels(scene.Jobs); fillPointLights(scene.Jobs.PointLight, m_World); + //TODO: Make sure all objects needed are also sorted. + scene.Jobs.OpaqueObjects.sort(); fillDirectionalLights(scene.Jobs.DirectionalLight, m_World); fillText(scene.Jobs.Text, m_World); m_RenderFrame->Add(scene); diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 851408a4..f272f14d 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -39,66 +39,494 @@ const Skeleton::Animation* Skeleton::GetAnimation(std::string name) } } -std::vector Skeleton::GetFrameBones(const Animation& animation, double time, bool noRootMotion /*= false*/) +std::vector Skeleton::GetFrameBones(std::vector animations, bool noRootMotion /*= false*/) { - // HACK: Animation wrap-around - while (time < 0) { - time += animation.Duration; - } - while (time > animation.Duration) { - time -= animation.Duration; - } + if (animations.size() <= 0) { + std::vector finalMatrices; + for (auto& b : Bones) { + finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); + } + return finalMatrices; + } - int currentKeyframeIndex = GetKeyframe(animation, time); + std::map frameBones; + AccumulateBoneTransforms(true, animations, frameBones, RootBone, glm::mat4(1)); - const Animation::Keyframe& currentFrame = animation.Keyframes[currentKeyframeIndex]; - const Animation::Keyframe& nextFrame = animation.Keyframes[(currentKeyframeIndex + 1) % animation.Keyframes.size()]; - double alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - //auto animationFrame = Animations[""].Keyframes[frame]; - std::map frameBones; - AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, static_cast(alpha), frameBones, RootBone, glm::mat4(1)); - - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); - } - return finalMatrices; + std::vector finalMatrices; + for (auto &kv : frameBones) { + finalMatrices.push_back(kv.second); + } + return finalMatrices; } -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe ¤tFrame, const Animation::Keyframe &nextFrame, float progress, std::map &boneMatrices, const Bone* bone, glm::mat4 parentMatrix) + +std::vector Skeleton::GetFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/) +{ + if (animations.size() <= 0 || animationOffset.animation == nullptr) { + std::vector finalMatrices; + for (auto& b : Bones) { + finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix); + } + return finalMatrices; + } + + + std::map frameBones; + AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1)); + + std::vector finalMatrices; + for (auto &kv : frameBones) { + finalMatrices.push_back(kv.second); + } + return finalMatrices; +} +/* + +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, float time, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - if (currentFrame.BoneProperties.find(bone->ID) != currentFrame.BoneProperties.end() || nextFrame.BoneProperties.find(bone->ID) != nextFrame.BoneProperties.end()) { - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties.at(bone->ID); - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties.at(bone->ID); + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; - glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + if(animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - positionInterp.x = 0; - positionInterp.z = 0; - } + if(boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if(nextFrame.Index == 0) { + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } - boneMatrix = parentMatrix * (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - if (bone->Parent) { - boneMatrix = parentMatrix; // * glm::inverse(bone->OffsetMatrix); + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress: %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + positionInterp.x = 0; + positionInterp.z = 0; + } + + boneMatrix = parentMatrix *(glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + boneMatrix = parentMatrix *(glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)); + + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; } - boneMatrices[bone->ID] = boneMatrix; // * bone->OffsetMatrix; - } + } else { // 0 keyframes for the current bone - for (auto &child : bone->Children) { - std::string name = child->Name; - AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, progress, boneMatrices, child, boneMatrix); - } + // LOG_INFO("%s Has no keyframe", bone->Name.c_str()); + if (bone->Parent) { + boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix; + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; + } + + } + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child, boneMatrix); + } +} +*/ + +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +{ + glm::mat4 boneMatrix; + + + + std::vector JointTransforms; + + for (const AnimationData animationData : animations) { + const Animation* animation = animationData.animation; + const float time = animationData.time; + + JointFrameTransform jointTransform; + jointTransform.Weight = animationData.weight;; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } + + + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress: %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.z = 0; + } + + JointTransforms.push_back(jointTransform); + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + jointTransform.PositionInterp = currentFrame.BoneProperties.Position; + jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; + jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + + } + + } + + if(JointTransforms.size() <= 0) { + if (bone->Parent) { + boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix; + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; + } + } else if (JointTransforms.size() == 1) { + boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + + glm::vec3 finalPosInterp; + glm::quat finalRotInterp; + glm::vec3 finalScaleInterp; + float totalWeight = 0; + + for (JointFrameTransform jointTransform : JointTransforms) { + totalWeight += jointTransform.Weight; + } + + + for (JointFrameTransform jointTransform : JointTransforms) + { + if(jointTransform.Weight == 1.0f) { + finalPosInterp = jointTransform.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } + + + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix); + } +} + + +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +{ + glm::mat4 boneMatrix; + + + + std::vector JointTransforms; + + for (const AnimationData animationData : animations) { + const Animation* animation = animationData.animation; + const float time = animationData.time; + + JointFrameTransform jointTransform; + jointTransform.Weight = animationData.weight;; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } + + + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress: %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.z = 0; + } + + JointTransforms.push_back(jointTransform); + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + jointTransform.PositionInterp = currentFrame.BoneProperties.Position; + jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; + jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + + } + + } + + + glm::mat4 offset = GetOffsetTransform(bone, animationOffset); + + if (JointTransforms.size() == 0) { + if (bone->Parent) { + if (offset != glm::mat4(1)) { + boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); + } else { + boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); + + } + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } else { + boneMatrix = offset * glm::inverse(bone->OffsetMatrix); + boneMatrices[bone->ID] = parentMatrix; + } + } else { + + glm::vec3 finalPosInterp; + glm::quat finalRotInterp; + glm::vec3 finalScaleInterp; + float totalWeight = 0; + + for (JointFrameTransform jointTransform : JointTransforms) { + totalWeight += jointTransform.Weight; + } + + + for (JointFrameTransform jointTransform : JointTransforms) { + if (jointTransform.Weight == 1.0f) { + finalPosInterp = jointTransform.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + + + if (offset != glm::mat4(1)) { + boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset); + } else { + boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + } + + boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; + } + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix); + } +} + + +glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) +{ + const Animation* animation = animationOffset.animation; + float time = animationOffset.time; + + glm::vec3 position = glm::vec3(0); + glm::quat rotation = glm::quat(); + glm::vec3 scale = glm::vec3(1); + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } + + + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress: %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + position = currentFrame.BoneProperties.Position; + rotation = currentFrame.BoneProperties.Rotation; + scale = currentFrame.BoneProperties.Scale; + } + } + + return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); +} + + +glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) +{ + glm::mat4 boneMatrix; + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + } + + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix; + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix; + + } + } else { // 0 keyframes for the current bone + if (bone->Parent) { + boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; + } + } + + if (bone->Parent) { + return GetBoneTransform(bone->Parent, animation, time, boneMatrix); + } else { + return boneMatrix; + } } int Skeleton::GetBoneID(std::string name) @@ -134,11 +562,13 @@ void Skeleton::PrintSkeleton(const Bone* bone, int depthCount) int Skeleton::GetKeyframe(const Animation& animation, double time) { + +/* if (time < 0) { time = 0; } if (time >= animation.Duration) { - return animation.Keyframes.size() - 1; + return animation..size() - 1; } for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) { @@ -146,6 +576,8 @@ int Skeleton::GetKeyframe(const Animation& animation, double time) return (keyframe - 1) % animation.Keyframes.size(); } } +*/ + return 0; } diff --git a/src/Engine/Sound/SoundManager.cpp b/src/Engine/Sound/SoundManager.cpp new file mode 100644 index 00000000..8e103d5c --- /dev/null +++ b/src/Engine/Sound/SoundManager.cpp @@ -0,0 +1,374 @@ +#include "Sound/SoundManager.h" + +SoundManager::SoundManager(World* world, EventBroker* eventBroker) +{ + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_EventBroker = eventBroker; + m_World = world; + m_BGMVolumeChannel = config->Get("Sound.BGMVolume", 1.f); + m_SFXVolumeChannel = config->Get("Sound.SFXVolume", 1.f); + + initOpenAL(); + alSpeedOfSound(340.29f); + alDistanceModel(AL_LINEAR_DISTANCE); + alDopplerFactor(1); + + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundManager::OnPlaySoundOnEntity); + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundManager::OnPlaySoundOnPosition); + EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundManager::OnPlayBackgroundMusic); + EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundManager::OnStopSound); + EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundManager::OnPauseSound); + EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundManager::OnContinueSound); + EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundManager::OnSetBGMGain); + EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundManager::OnSetSFXGain); + EVENT_SUBSCRIBE_MEMBER(m_EPause, &SoundManager::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EResume, &SoundManager::OnResume); + EVENT_SUBSCRIBE_MEMBER(m_EComponentAttached, &SoundManager::OnComponentAttached); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundManager::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_EPlayQueueOnEntity, &SoundManager::OnPlayQueueOnEntity); +} + +SoundManager::~SoundManager() +{ + stopEmitters(); // Stopps emitters + deleteInactiveEmitters(); // Deletes stopped emitters + // Delete entities + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + m_World->DeleteEntity((*it).first); + } + m_Sources.clear(); + + alcDestroyContext(m_ALCcontext); + alcCloseDevice(m_ALCdevice); +} + +void SoundManager::stopEmitters() +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + if (getSourceState(it->second->ALsource) == AL_PLAYING) { + stopSound(it->second); + } + } +} + +void SoundManager::Update(double dt) +{ + m_EventBroker->Process(); + deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" + updateEmitters(dt); + updateListener(dt); + + // Editor debug info + ImGui::SliderFloat("BGM", &m_BGMVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); + ImGui::SliderFloat("SFX", &m_SFXVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); +} + +void SoundManager::deleteInactiveEmitters() +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end();) { + if (m_World->ValidEntity(it->first) + && m_World->HasComponent(it->first, "SoundEmitter")) { + if (getSourceState(it->second->ALsource) != AL_STOPPED) { + // Nothing to see here, move along + it++; + continue; + } else { + // Sound has been stopped / finished playing. + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + m_World->DeleteEntity(it->first); + delete it->second; + it = m_Sources.erase(it); + } + } else { + // Entity / Component has been removed + stopSound(it->second); + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + delete it->second; + it = m_Sources.erase(it); + } + } +} + +void SoundManager::updateEmitters(double dt) +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + // Get previous pos + if (!m_World->ValidEntity(it->first)) { + return; + } + if (!m_World->HasComponent(it->first, "SoundEmitter")) + return; + + glm::vec3 previousPos; + alGetSource3f(it->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); + // Get next pos + if (!m_World->HasComponent(it->first, "Transform")) + return; + if (!m_World->ValidEntity(m_World->GetParent(it->first))) { + return; + } + glm::vec3 nextPos = Transform::AbsolutePosition(m_World, it->first); + // Calculate velocity + glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; + setSourcePos(it->second->ALsource, nextPos); + setSourceVel(it->second->ALsource, velocity); + + auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); + setSoundProperties(it->second, &emitter); + + // Path changed + if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { + it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); + if (it->second->SoundResource->Buffer() != 0) { + playSound(it->second); + } + } + } +} + +void SoundManager::updateListener(double dt) +{ + // Should only be one listener. + auto listenerComponents = m_World->GetComponents("Listener"); + if (listenerComponents == nullptr || !m_LocalPlayer.Valid()) { + return; + } + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + EntityWrapper listener(m_World, (*it).EntityID); + if (!listener.Valid()) { + break; + } + if (listener.IsChildOf(m_LocalPlayer) || listener == m_LocalPlayer) { + glm::vec3 previousPos; + alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos + glm::vec3 nextPos = Transform::AbsolutePosition(listener); // Get next (current) pos + glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; // Calculate velocity + setListenerPos(nextPos); + setListenerVel(velocity); + setListenerOri(glm::eulerAngles(Transform::AbsoluteOrientation(listener))); + break; + } + } +} + +Source* SoundManager::createSource(std::string filePath) +{ + ALuint alSource; + alGenSources((ALuint)1, &alSource); + alSourcef(alSource, AL_REFERENCE_DISTANCE, 1.0); + alSourcef(alSource, AL_MAX_DISTANCE, FLT_MAX); + Source* source = new Source(); + source->ALsource = alSource; + source->SoundResource = ResourceManager::Load(filePath); + return source; +} + +void SoundManager::playSound(Source* source) +{ + alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); + alSourcePlay(source->ALsource); +} + +void SoundManager::playQueue(QueuedBuffers qb) +{ + for (int i = 0; i < qb.second.size(); i++) { + alSourceQueueBuffers(qb.first, 1, &qb.second[i]); + } + alSourcePlay(qb.first); +} + +void SoundManager::stopSound(Source* source) +{ + alSourceStop(source->ALsource); +} + +bool SoundManager::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) +{ + Source* source = createSource(e.FilePath); + source->Type = SoundType::SFX; + EntityID child = m_World->CreateEntity(e.EmitterID); + m_World->AttachComponent(child, "Transform"); + m_World->AttachComponent(child, "SoundEmitter"); + m_Sources[child] = source; + playSound(source); + return false; +} + +bool SoundManager::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) +{ + Source* source = createSource(e.FilePath); + auto emitterID = m_World->CreateEntity(); + auto transform = m_World->AttachComponent(emitterID, "Transform"); + (glm::vec3&)transform["Position"] = e.Position; + auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); + (float&)(double)emitter["Gain"] = e.Gain; + (float&)(double)emitter["Pitch"] = e.Pitch; + (bool&)emitter["Loop"] = e.Loop; + (float&)(double)emitter["MaxDistance"] = e.MaxDistance; + (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; + (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; + source->Type = SoundType::SFX; + m_Sources[emitterID] = source; + playSound(source); + return true; +} + +bool SoundManager::OnPauseSound(const Events::PauseSound & e) +{ + alSourcePause(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnStopSound(const Events::StopSound & e) +{ + alSourceStop(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnContinueSound(const Events::ContinueSound & e) +{ + alSourcePlay(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) +{ + auto listenerComponents = m_World->GetComponents("Listener"); + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + if ((*it).EntityID != m_LocalPlayer.ID) { + break; + } + auto emitterChild = m_World->CreateEntity((*it).EntityID); + auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); + (bool&)emitter["Loop"] = true; + (std::string&)emitter["FilePath"] = e.FilePath; + m_World->AttachComponent(emitterChild, "Transform"); + Source* source = createSource(e.FilePath); + source->Type = SoundType::BGM; + setSoundProperties(source, &emitter); + m_Sources[emitterChild] = source; + playSound(source); + } + return true; +} + +bool SoundManager::OnSetBGMGain(const Events::SetBGMGain & e) +{ + m_BGMVolumeChannel = e.Gain; + return true; +} + +bool SoundManager::OnSetSFXGain(const Events::SetSFXGain & e) +{ + m_SFXVolumeChannel = e.Gain; + return true; +} + +bool SoundManager::OnComponentAttached(const Events::ComponentAttached & e) +{ + if (e.Component.Info.Name == "SoundEmitter") { + auto component = m_World->GetComponent(e.Entity.ID, "SoundEmitter"); + Source* source = createSource(component["FilePath"]); + m_Sources[e.Entity.ID] = source; + } + return false; +} + +bool SoundManager::OnPause(const Events::Pause & e) +{ + for (auto it = m_Sources.begin(); it != m_Sources.end(); it++) { + alSourcePause(it->second->ALsource); + } + return false; +} + +bool SoundManager::OnResume(const Events::Resume &e) +{ + for (auto it = m_Sources.begin(); it != m_Sources.end(); it++) { + alSourcePlay(it->second->ALsource); + } + return false; +} + + +bool SoundManager::OnPlayerSpawned(const Events::PlayerSpawned &e) +{ + if (e.PlayerID == -1) { // Local player + m_LocalPlayer = e.Player; + return true; + } + return false; +} + + +bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) +{ + Source* source = createSource(*e.FilePaths.begin()); + std::vector buffers; + buffers.push_back(source->SoundResource->Buffer()); + source->Type = SoundType::BGM; + std::vector::const_iterator it; + for (it = e.FilePaths.begin() + 1; it != e.FilePaths.end(); it++) { + buffers.push_back(ResourceManager::Load(*it)->Buffer()); + } + playQueue(QueuedBuffers(source->ALsource, buffers)); + return true; +} + +ALenum SoundManager::getSourceState(ALuint source) +{ + ALenum state; + alGetSourcei(source, AL_SOURCE_STATE, &state); + return state; +} + +void SoundManager::setGain(Source * source, float gain) +{ + alSourcef(source->ALsource, AL_GAIN, gain); +} + +void SoundManager::setSoundProperties(Source* source, ComponentWrapper* soundComponent) +{ + float gain = (source->Type == SoundType::SFX) ? m_SFXVolumeChannel : m_BGMVolumeChannel; + alSourcef(source->ALsource, AL_GAIN, (float)(double)(*soundComponent)["Gain"] * gain); + alSourcef(source->ALsource, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); + alSourcei(source->ALsource, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO + alSourcef(source->ALsource, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); + alSourcef(source->ALsource, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); + alSourcef(source->ALsource, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); +} + +void SoundManager::initOpenAL() +{ + // Initialize OpenAL + m_ALCdevice = alcOpenDevice(nullptr); + if (m_ALCdevice != nullptr) { + m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); + alcMakeContextCurrent(m_ALCcontext); + } else { + LOG_ERROR("OpenAL failed to initialize."); + } +} + +void SoundManager::setListenerOri(glm::vec3 ori) +{ + // Calculate forward and up vector. + glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); + forward = glm::rotateX(forward, ori.x); + forward = glm::rotateY(forward, ori.y); + forward = glm::rotateZ(forward, ori.z); + glm::normalize(forward); + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); + up = glm::rotateX(up, ori.x); + up = glm::rotateY(up, ori.y); + up = glm::rotateZ(up, ori.z); + glm::normalize(up); + ALfloat lOri[6] = { forward.x, forward.y, forward.z, up.x, up.y, up.z }; + alListenerfv(AL_ORIENTATION, lOri); +} \ No newline at end of file diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp deleted file mode 100644 index cd83d9c6..00000000 --- a/src/Engine/Sound/SoundSystem.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include "Sound/SoundSystem.h" - -SoundSystem::SoundSystem(World* world, EventBroker* eventBroker, bool editorMode) -{ - m_EventBroker = eventBroker; - m_World = world; - m_EditorEnabled = editorMode; - - initOpenAL(); - - alSpeedOfSound(340.29f); - alDistanceModel(AL_LINEAR_DISTANCE); - alDopplerFactor(1); - - EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundSystem::OnPlaySoundOnEntity); - EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundSystem::OnPlaySoundOnPosition); - EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundSystem::OnPlayBackgroundMusic); - EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundSystem::OnStopSound); - EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundSystem::OnPauseSound); - EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundSystem::OnContinueSound); - EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundSystem::OnSetBGMGain); - EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundSystem::OnSetSFXGain); -} - -SoundSystem::~SoundSystem() -{ - stopEmitters(); // Stopps emitters - deleteInactiveEmitters(); // Deletes stopped emitters - // Delete entities - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - m_World->DeleteEntity((*it).first); - } - m_Sources.clear(); - - alcDestroyContext(m_ALCcontext); - alcCloseDevice(m_ALCdevice); -} - -void SoundSystem::stopEmitters() -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - if (getSourceState(it->second->ALsource) == AL_PLAYING) { - stopSound(it->second); - } - } -} - -void SoundSystem::Update(double dt) -{ - m_EventBroker->Process(); - addNewEmitters(dt); // can be optimized with "EEntityCreated" - deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" - updateEmitters( dt); - updateListener( dt); -} - -void SoundSystem::deleteInactiveEmitters() -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end();) { - if (m_World->ValidEntity(it->first) - && m_World->HasComponent(it->first, "SoundEmitter")) { - if (getSourceState(it->second->ALsource) != AL_STOPPED) { - // Nothing to see here, move along - it++; - continue; - } else { - // Sound has been stopped / finished playing. - alDeleteBuffers(1, &it->second->ALsource); - alDeleteSources(1, &it->second->ALsource); - m_World->DeleteEntity(it->first); - delete it->second; - it = m_Sources.erase(it); - } - } else { - // Entity / Component has been removed - stopSound((*it).second); - alDeleteBuffers(1, &it->second->ALsource); - alDeleteSources(1, &it->second->ALsource); - delete it->second; - it = m_Sources.erase(it); - } - } -} - -void SoundSystem::addNewEmitters(double dt) -{ - auto emitterComponents = m_World->GetComponents("SoundEmitter"); - if (emitterComponents == nullptr) { - return; - } - for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { - EntityID emitter = (*it).EntityID; - std::unordered_map::iterator source; - source = m_Sources.find(emitter); - if (source == m_Sources.end()) { // Did not exist, add it - Source* source = createSource((std::string)(*it)["FilePath"]); - m_Sources[emitter] = source; - } - } -} - -void SoundSystem::updateEmitters(double dt) -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - // Get previous pos - glm::vec3 previousPos; - alGetSource3f(it->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); - // Get next pos - glm::vec3 nextPos = Transform::AbsolutePosition(m_World, it->first); - // Calculate velocity - glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; - setSourcePos(it->second->ALsource, nextPos); - setSourceVel(it->second->ALsource, velocity); - float gain; - if (it->second->Type == SoundType::SFX) { - gain = m_SFXVolumeChannel; - } else if (it->second->Type == SoundType::BGM) { - gain = m_BGMVolumeChannel; - } - auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); - setSoundProperties(it->second->ALsource, &emitter); - - // To make an emitter play when spawned in editor mode - if (m_EditorEnabled) { - // Path changed - if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { - it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); - if (it->second->SoundResource->Buffer() != 0) { - playSound(it->second); - } - } - } - } -} - -void SoundSystem::updateListener(double dt) -{ - // Should only be one listener. - auto listenerComponents = m_World->GetComponents("Listener"); - if (listenerComponents == nullptr) { - return; - } - for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { - EntityID listener = (*it).EntityID; - glm::vec3 previousPos; - alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos - glm::vec3 nextPos = Transform::AbsolutePosition(m_World, listener); // Get next (current) pos - glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; // Calculate velocity - setListenerPos(nextPos); - setListenerVel(velocity); - setListenerOri(glm::eulerAngles(Transform::AbsoluteOrientation(m_World, listener))); - } -} - -Source* SoundSystem::createSource(std::string filePath) -{ - ALuint alSource; - alGenSources((ALuint)1, &alSource); - alSourcef(alSource, AL_REFERENCE_DISTANCE, 1.0); - alSourcef(alSource, AL_MAX_DISTANCE, FLT_MAX); - Source* source = new Source(); - source->ALsource = alSource; - source->SoundResource = ResourceManager::Load(filePath); - return source; -} - -void SoundSystem::playSound(Source* source) -{ - alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); - alSourcePlay(source->ALsource); -} - -void SoundSystem::stopSound(Source* source) -{ - alSourceStop(source->ALsource); -} - -bool SoundSystem::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) -{ - Source* source = createSource(e.FilePath); - source->Type = SoundType::SFX; - m_Sources[e.EmitterID] = source; - playSound(source); - return false; -} - -bool SoundSystem::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) -{ - Source* source = createSource(e.FilePath); - auto emitterID = m_World->CreateEntity(); - auto transform = m_World->AttachComponent(emitterID, "Transform"); - (glm::vec3&)transform["Position"] = e.Position; - auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); - (float&)(double)emitter["Gain"] = e.Gain; - (float&)(double)emitter["Pitch"] = e.Pitch; - (bool&)emitter["Loop"] = e.Loop; - (float&)(double)emitter["MaxDistance"] = e.MaxDistance; - (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; - (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; - auto model = m_World->AttachComponent(emitterID, "Model"); - (std::string&)model["Resource"] = "Models/Core/UnitCube.mesh"; // 360NoScope UnitCube - source->Type = SoundType::SFX; - m_Sources[emitterID] = source; - playSound(source); - return true; -} - -bool SoundSystem::OnPauseSound(const Events::PauseSound & e) -{ - alSourcePause(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnStopSound(const Events::StopSound & e) -{ - alSourceStop(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnContinueSound(const Events::ContinueSound & e) -{ - alSourcePlay(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) -{ - auto listenerComponents = m_World->GetComponents("Listener"); - for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { - auto emitterChild = m_World->CreateEntity((*it).EntityID); - auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); - (bool&)emitter["Loop"] = true; - (std::string&)emitter["FilePath"] = e.FilePath; - m_World->AttachComponent(emitterChild, "Transform"); - Source* source = createSource(e.FilePath); - source->Type = SoundType::BGM; - m_Sources[emitterChild] = source; - playSound(source); - } - return true; -} - -bool SoundSystem::OnSetBGMGain(const Events::SetBGMGain & e) -{ - m_BGMVolumeChannel = e.Gain; - return true; -} - -bool SoundSystem::OnSetSFXGain(const Events::SetSFXGain & e) -{ - m_SFXVolumeChannel = e.Gain; - return true; -} - -void SoundSystem::setListenerOri(glm::vec3 ori) -{ - // Calculate forward and up vector. - glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); - forward = glm::rotateX(forward, ori.x); - forward = glm::rotateY(forward, ori.y); - forward = glm::rotateZ(forward, ori.z); - glm::normalize(forward); - glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); - up = glm::rotateX(up, ori.x); - up = glm::rotateY(up, ori.y); - up = glm::rotateZ(up, ori.z); - glm::normalize(up); - ALfloat lOri[6] = { forward.x, forward.y, forward.z, up.x, up.y, up.z }; - alListenerfv(AL_ORIENTATION, lOri); -} - -ALenum SoundSystem::getSourceState(ALuint source) -{ - ALenum state; - alGetSourcei(source, AL_SOURCE_STATE, &state); - return state; -} - -void SoundSystem::setGain(Source * source, float gain) -{ - alSourcef(source->ALsource, AL_GAIN, gain); -} - -void SoundSystem::setSoundProperties(ALuint source, ComponentWrapper* soundComponent) -{ - alSourcef(source, AL_GAIN, (float)(double)(*soundComponent)["Gain"]); - alSourcef(source, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); - alSourcei(source, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO - alSourcef(source, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); - alSourcef(source, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); - alSourcef(source, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); -} - -void SoundSystem::initOpenAL() -{ - // Initialize OpenAL - m_ALCdevice = alcOpenDevice(nullptr); - if (m_ALCdevice != nullptr) { - m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); - alcMakeContextCurrent(m_ALCcontext); - } else { - LOG_ERROR("OpenAL failed to initialize."); - } -} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 0f836c6f..95310952 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -14,9 +14,10 @@ #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/WeaponSystem.h" +#include "Rendering/AnimationSystem.h" +#include "Rendering/BoneAttachmentSystem.h" #include "Game/Systems/PlayerHUD.h" #include "Game/Systems/LifetimeSystem.h" -#include "../Engine/Rendering/AnimationSystem.h" Game::Game(int argc, char* argv[]) { @@ -74,6 +75,8 @@ Game::Game(int argc, char* argv[]) fp.MergeEntities(m_World); } + // Create the sound manager + m_SoundManager = new SoundManager(m_World, m_EventBroker); // Create Octrees // TODO: Perhaps the world bounds should be set in some non-arbitrary way instead of this. @@ -86,6 +89,7 @@ Game::Game(int argc, char* argv[]) // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); @@ -108,6 +112,7 @@ Game::Game(int argc, char* argv[]) // Collision and TriggerSystem should update after player. ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger); ++updateOrderLevel; @@ -121,19 +126,16 @@ Game::Game(int argc, char* argv[]) networkFunction(); } - // Invoke sound system - m_SoundSystem = new SoundSystem(m_World, m_EventBroker, m_Config->Get("Debug.EditorEnabled", false)); - m_LastTime = glfwGetTime(); } Game::~Game() { delete m_SystemPipeline; - delete m_SoundSystem; delete m_OctreeFrustrumCulling; delete m_OctreeCollision; delete m_OctreeTrigger; + delete m_SoundManager; delete m_World; delete m_FrameStack; delete m_InputProxy; @@ -161,16 +163,19 @@ void Game::Tick() m_InputProxy->Process(); m_EventBroker->Swap(); + m_SoundManager->Update(dt); + // Update network if (m_IsClientOrServer) { m_ClientOrServer->Update(); } + //m_SoundManager->Update(dt); + // Iterate through systems and update world! m_EventBroker->Process(); m_SystemPipeline->Update(dt); debugTick(dt); m_Renderer->Update(dt); - m_SoundSystem->Update(dt); GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(*m_RenderFrame); m_RenderFrame->Clear(); diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 52890c3a..e9391c95 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -56,6 +56,12 @@ void PlayerMovementSystem::Update(double dt) } else { wishSpeed = playerMovementSpeed; } + if (player.ID == m_LocalPlayer.ID) { + if (glm::length(wishDirection) == 0) { + // If no key is pressed, reset the distance moved since last step. + m_DistanceMoved = 0; + } + } glm::vec3& velocity = cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; ImGui::Text(isOnGround ? "On ground" : "In air"); @@ -94,6 +100,8 @@ void PlayerMovementSystem::Update(double dt) controller->SetDoubleJumping(false); } else { controller->SetDoubleJumping(true); + Events::DoubleJump e; + m_EventBroker->Publish(e); } velocity.y = 4.f; } @@ -116,19 +124,19 @@ void PlayerMovementSystem::Update(double dt) //TODO: add assault dash animation here if (glm::length(controller->Movement()) > 0.f) { if (controller->Crouching()) { - cAnimation["Name"] = "Crouch Walk"; - (double&)cAnimation["Speed"] = 1.f * -glm::sign(controller->Movement().z); + cAnimation["AnimationName1"] = "Crouch Walk"; + (double&)cAnimation["Speed1"] = 1.f * -glm::sign(controller->Movement().z); } else { - cAnimation["Name"] = "Run"; - (double&)cAnimation["Speed"] = 2.f * -glm::sign(controller->Movement().z); + cAnimation["AnimationName1"] = "Run"; + (double&)cAnimation["Speed1"] = 2.f * -glm::sign(controller->Movement().z); } } else { if (controller->Crouching()) { - cAnimation["Name"] = "Crouch"; + cAnimation["AnimationName1"] = "Crouch"; (double&)cAnimation["Speed"] = 1.f; } else { - cAnimation["Name"] = "Hold Pos"; - (double&)cAnimation["Speed"] = 1.f; + cAnimation["AnimationName1"] = "Hold Pos"; + (double&)cAnimation["Speed1"] = 1.f; } } } @@ -136,6 +144,7 @@ void PlayerMovementSystem::Update(double dt) controller->Reset(); } + playerStep(dt); } void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) @@ -171,10 +180,37 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp position += velocity * (float)dt; } +void PlayerMovementSystem::playerStep(double dt) +{ + if (!m_LocalPlayer.Valid()) { + return; + } + // Position of the local player, used see how far a player has moved. + glm::vec3 pos = (glm::vec3)m_World->GetComponent(m_LocalPlayer.ID, "Transform")["Position"]; + // Used to see if a player is airborne. + bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"]; + m_DistanceMoved += glm::length(pos - m_LastPosition); + // Set the last position for next iteration + m_LastPosition = pos; + if (m_DistanceMoved > m_PlayerStepLength && grounded) { + // Player moved a step's distance + // Create footstep sound + Events::PlaySoundOnEntity e; + e.EmitterID = m_LocalPlayer.ID; + e.FilePath = m_LeftFoot ? "Audio/footstep/footstep2.wav" : "Audio/footstep/footstep3.wav"; + m_LeftFoot = !m_LeftFoot; + m_EventBroker->Publish(e); + m_DistanceMoved = 0.f; + } +} + bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) { // When a player spawns, create an input controller for them m_PlayerInputControllers[e.Player] = new FirstPersonInputController(m_EventBroker, e.PlayerID); - + if (e.PlayerID == -1) { + // Keep track of the local player + m_LocalPlayer = e.Player; + } return true; } diff --git a/src/Game/Systems/SoundSystem.cpp b/src/Game/Systems/SoundSystem.cpp new file mode 100644 index 00000000..acb7501c --- /dev/null +++ b/src/Game/Systems/SoundSystem.cpp @@ -0,0 +1,190 @@ +#include "Game/Systems/SoundSystem.h" + +SoundSystem::SoundSystem(World* world, EventBroker* eventbroker) + : System(world, eventbroker) + , PureSystem("SoundEmitter") + //, ImpureSystem() +{ + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_Announcer = ResourceManager::Load("Config.ini")->Get("Sound.Announcer", "female"); + m_World = world; + m_EventBroker = eventbroker; + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump); + EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &SoundSystem::OnDashAbility); + EVENT_SUBSCRIBE_MEMBER(m_EShoot, &SoundSystem::OnShoot); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage); + EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured); + EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &SoundSystem::OnTriggerTouch); +} + +void SoundSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) +{ } + +void SoundSystem::Update(double dt) +{ + // Temp for play test. + if(m_DrumsIsPlaying) { + m_DrumsIsPlaying = !drumTimer(dt); + } +} + +bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e) +{ + if (e.PlayerID == -1) { // Local player + m_World->AttachComponent(e.Player.ID, "Listener"); + m_LocalPlayer = e.Player; + Events::PlaySoundOnEntity go; + go.EmitterID = m_LocalPlayer.ID; + go.FilePath = "Audio/announcer/" + m_Announcer + "/go.wav"; + m_EventBroker->Publish(go); + // TEMP: starts bgm + { + Events::PlayBackgroundMusic ev; + ev.FilePath = "Audio/bgm/ambient.wav"; + m_EventBroker->Publish(ev); + } + } + return true; +} + +bool SoundSystem::OnInputCommand(const Events::InputCommand & e) +{ + if (e.Command == "Jump" && e.Value > 0) { + if (e.PlayerID == -1) { // local player + playerJumps(); + return true; + } + } + if (e.Command == "TakeDamage" && e.Value > 0) { + Events::PlayerDamage ev; + ev.Player = m_LocalPlayer; + ev.Damage = 1.0; + m_EventBroker->Publish(ev); + } + + return false; +} + +void SoundSystem::playerJumps() +{ + bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"]; + if (grounded) { + Events::PlaySoundOnEntity e; + e.EmitterID = m_LocalPlayer.ID; + e.FilePath = "Audio/jump/jump1.wav"; + m_EventBroker->Publish(e); + } +} + +bool SoundSystem::drumTimer(double dt) +{ + m_DrumTimer += dt; + if (m_DrumTimer > 15) { + m_DrumTimer = 0.0; + return true; + } else { + return false; + } +} + +bool SoundSystem::OnShoot(const Events::Shoot & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/laser/laser1.wav"; + m_EventBroker->Publish(ev); + return true; +} + +bool SoundSystem::OnCaptured(const Events::Captured & e) +{ + int homeTeam = (int)m_World->GetComponent(e.CapturePointID, "Team")["Team"]; + int team = (int)m_World->GetComponent(m_LocalPlayer.ID, "Team")["Team"]; + Events::PlaySoundOnEntity ev; + if (team == homeTeam) { + ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_achieved.wav"; + } else { + ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_failed.wav"; // have not been tested + } + ev.EmitterID = m_LocalPlayer.ID; + m_EventBroker->Publish(ev); + // Temp for play test. + m_DrumsIsPlaying = false; + return false; +} + +// Testing purposes atm... +bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e) +{ + // Should check for only local players here... + std::uniform_int_distribution dist(1, 12); + int rand = dist(generator); + std::vector paths; + paths.push_back("Audio/hurt/hurt" + std::to_string(rand) + ".wav"); + +// // Breathe +// int ammountOfbreaths = (static_cast(e.Damage) / 10) + 2; // TEMP: Idk something stupid like this shit +// for (int i = 0; i < ammountOfbreaths; i++) { +// paths.push_back("Audio/exhausted/breath.wav"); +// } + Events::PlayQueueOnEntity ev; + ev.Emitter = m_LocalPlayer; + ev.FilePaths = paths; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/die/die2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/pickup/pickup2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e) +{ + // Temp for play test. + if (m_DrumsIsPlaying) { + return false; + } + if (m_World->HasComponent(e.Trigger.ID, "CapturePoint")) { + Events::PlaySoundOnEntity ev; // should be BGM + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/bgm/drumstest.wav"; + m_EventBroker->Publish(ev); + // Temp for play test. + m_DrumsIsPlaying = true; + } + return false; +} + +bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/jump/jump2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnDashAbility(const Events::DashAbility &e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = m_LocalPlayer.ID; + ev.FilePath = "Audio/jump/dash1.wav"; + m_EventBroker->Publish(ev); + return false; +} \ No newline at end of file diff --git a/tools/MayaExporter/MayaExporter/Export.cpp b/tools/MayaExporter/MayaExporter/Export.cpp index d8f1abd4..3497fd04 100644 --- a/tools/MayaExporter/MayaExporter/Export.cpp +++ b/tools/MayaExporter/MayaExporter/Export.cpp @@ -47,13 +47,24 @@ bool Export::Meshes(std::string pathName, bool selectedOnly) for (unsigned int i = 0; i < connections.length(); i++) { if (connections[i].node().apiType() == MFn::kSkinClusterFilter) { - MGlobal::select(shape.parent(i), MGlobal::kReplaceList); - MGlobal::displayInfo(MString() + "Moving " + thisNode.name() + " to bindPose."); + shape.parent(0, &status); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + "shape.parent(0, &status) failed with: " + status.errorString()); + } + status = MGlobal::select(shape.parent(0), MGlobal::kReplaceList); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + "Parent to " + thisNode.name() + " failed"); + } + + MFnDependencyNode tmp(shape.parent(0)); + MGlobal::displayInfo(MString() + "Moving " + tmp.name() + " to bindPose."); + status = MGlobal::executeCommand("GoToBindPose;"); if (status != MS::kSuccess) { MGlobal::displayError(MString() + "GoToBindPose: " + status.errorString()); } - MGlobal::displayInfo(MString() + "Has moved " + thisNode.name() + " to bindPose."); + + MGlobal::displayInfo(MString() + "Has moved " + tmp.name() + " to bindPose."); } } } @@ -109,6 +120,8 @@ bool Export::Materials(std::string pathName) bool Export::Animations(std::string pathName, std::vector animInfo) { + allAnimations.clear(); + allBindPoses.clear(); if (MAnimControl::currentTime().unit() != MTime::kNTSCField) { MGlobal::displayError(MString() + "Please change to 60 FPS under Preferences/Settings!"); diff --git a/tools/MayaExporter/MayaExporter/Material.cpp b/tools/MayaExporter/MayaExporter/Material.cpp index 03521231..a5717aa6 100644 --- a/tools/MayaExporter/MayaExporter/Material.cpp +++ b/tools/MayaExporter/MayaExporter/Material.cpp @@ -82,16 +82,36 @@ bool Material::findColorTexture(MaterialNode& material_node, MFnDependencyNode& workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.ColorMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.ColorMapFileLength = material_node.ColorMapFile.length() + 1; - // Test - MGlobal::displayInfo(MString() + "getAbsolutePathToResources: " + workspace); - MGlobal::displayInfo(MString() + "Texture file: " + FullPath.c_str()); + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.ColorMaps.push_back(newTexture); + if(material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.ColorMaps, MFnDependencyNode(AllConnections[i].node())); } } - return false; } @@ -120,9 +140,31 @@ bool Material::findNormalTexture(MaterialNode& material_node, MFnDependencyNode& workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.NormalMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.NormalMapFileLength = material_node.NormalMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.NormalMaps.push_back(newTexture); return true; + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.NormalMaps, MFnDependencyNode(AllConnections[i].node())); } } } @@ -150,9 +192,34 @@ bool Material::findSpecularTexture(MaterialNode& material_node, MFnDependencyNod workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.SpecularMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.SpecularMapFileLength = material_node.SpecularMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + //C:\Users\kamisama\Desktop\TacticalZ\assets\test + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.SpecularMaps.push_back(newTexture); + if (material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.SpecularMaps, MFnDependencyNode(AllConnections[i].node())); } } return false; @@ -168,7 +235,7 @@ bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependen for (int i = 0; i < AllConnections.length(); i++) { if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { MFnDependencyNode TextureNode(AllConnections[i].node()); - + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); m_TexturePaths.push_back(FullPath); @@ -177,14 +244,141 @@ bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependen workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.IncandescenceMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.IncandescenceMapFileLength = material_node.IncandescenceMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.IncandescenceMaps.push_back(newTexture); + if (material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.IncandescenceMaps, MFnDependencyNode(AllConnections[i].node())); } } return false; } +//C:\Users\kamisama\Desktop\TacticalZ\assets\test + +bool Material::findSplatTextures(MaterialNode& material_node, std::vector& textureVector, MFnDependencyNode& node) { + //Get all Inputs in LayeredTexture + MPlug inputs = node.findPlug("inputs"); + MGlobal::displayInfo(MString() + "inputs.numElements(): " + inputs.numElements()); + + MPlugArray AllConnections; + MStatus test; + //Try to find splat texture if using custom splatmap build up. + inputs[0].child(1).connectedTo(AllConnections, true, false); + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kMultiplyDivide)) { + MGlobal::displayInfo(MString() + "found kMultiplyDivide"); + MFnDependencyNode multiplyDivide(AllConnections[i].node()); + multiplyDivide.findPlug("input1", &test).child(0).connectedTo(AllConnections, true, false);; + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { + MFnDependencyNode TextureNode(AllConnections[i].node()); + + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); + m_TexturePaths.push_back(FullPath); + + MString workspace; + MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"), + workspace); + FullPath = FullPath.substr(workspace.length()); + FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + material_node.SplatMap = newTexture; + material_node.type = MaterialNode::MaterialType::SplatMapping; + } + } + } + } + + for (unsigned int i = 0; i < inputs.numElements(); i++) { + //Get connections to color in input[i] + inputs[i].child(0).connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { + MFnDependencyNode TextureNode(AllConnections[i].node()); + + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); + m_TexturePaths.push_back(FullPath); + + MString workspace; + MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"), + workspace); + FullPath = FullPath.substr(workspace.length()); + FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + textureVector.push_back(newTexture); + break; + } + } + if (AllConnections.length() == 0) { + MaterialNode::Texture newTexture; + newTexture.FileNameLength = 0; + textureVector.push_back(newTexture); + } + } + return true; +} + // Returns the absolute path for all textures. Use for copying texture files. std::vector* Material::TexturePaths() { @@ -209,7 +403,6 @@ std::vector* Material::DoIt(Mesh mesh) meshHasMaterial = true; MaterialStorage.IndexStart = totalIndices; MaterialStorage.IndexEnd = totalIndices + aMeshMaterial.second.size() - 1; - break; } totalIndices += aMeshMaterial.second.size(); } @@ -226,7 +419,10 @@ std::vector* Material::DoIt(Mesh mesh) MaterialStorage.ReflectionFactor = 0.0f; MaterialStorage.SpecularExponent = 0.0f; } - + MaterialStorage.NumColorMaps = MaterialStorage.ColorMaps.size(); + MaterialStorage.NumNormalMaps = MaterialStorage.NormalMaps.size(); + MaterialStorage.NumSpecularMaps = MaterialStorage.SpecularMaps.size(); + MaterialStorage.NumIncandescenceMaps = MaterialStorage.IncandescenceMaps.size(); m_AllMaterials.push_back(MaterialStorage); } matIt.next(); diff --git a/tools/MayaExporter/MayaExporter/Material.h b/tools/MayaExporter/MayaExporter/Material.h index e405dd07..d70a6399 100644 --- a/tools/MayaExporter/MayaExporter/Material.h +++ b/tools/MayaExporter/MayaExporter/Material.h @@ -11,62 +11,123 @@ #include "OutputData.h" #include "Mesh.h" + +//#define ColorMapSplat 1 +//#define SpecularMapSplat 1 << 1 +//#define NormalMapSplat 1 << 2 +//#define IncandescenceMapSplat 1 << 3 + + + class MaterialNode : public OutputData { public: + class Texture : public OutputData { + public: + unsigned int FileNameLength = 0; + std::string FileName; + float UVTiling[2]{ 1.0f, 1.0f }; + + virtual void WriteBinary(std::ostream& out) + { + out.write((char*)&FileNameLength, sizeof(unsigned int)); + out.write(FileName.c_str(), FileNameLength); + out.write((char*)&UVTiling, sizeof(float) * 2); + } + + virtual void WriteASCII(std::ostream& out) const + { + out << "FileNameLength: " << FileNameLength << endl; + out << "FileName: " << FileName << endl; + out << "UV tiling: " << UVTiling[0] << " " << UVTiling[1] << endl; + } + }; + + enum class MaterialType { Basic = 1, SplatMapping, SingleTextures }; + + MaterialType type = MaterialType::Basic; + std::string Name; float ReflectionFactor; float SpecularExponent; - float DiffuseColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int ColorMapFileLength = 0; - std::string ColorMapFile; + float DiffuseColor[3]{ 1.0f, 1.0f, 1.0f }; + float SpecularColor[3]{ 1.0f, 1.0f, 1.0f }; + float IncandescenceColor[3]{ 1.0f, 1.0f, 1.0f }; - float SpecularColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int SpecularMapFileLength = 0; - std::string SpecularMapFile; + unsigned int IndexStart; + unsigned int IndexEnd; - unsigned int NormalMapFileLength = 0; - std::string NormalMapFile; - - float IncandescenceColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int IncandescenceMapFileLength = 0; - std::string IncandescenceMapFile; - - unsigned int IndexStart; - unsigned int IndexEnd; + unsigned char NumColorMaps = 0; + unsigned char NumSpecularMaps = 0; + unsigned char NumNormalMaps = 0; + unsigned char NumIncandescenceMaps = 0; + Texture SplatMap; + std::vector ColorMaps; + std::vector SpecularMaps; + std::vector NormalMaps; + std::vector IncandescenceMaps; virtual void WriteBinary(std::ostream& out) { - out.write((char*)&ColorMapFileLength, sizeof(unsigned int)); - out.write((char*)&NormalMapFileLength, sizeof(unsigned int)); - out.write((char*)&SpecularMapFileLength, sizeof(unsigned int)); - out.write((char*)&IncandescenceMapFileLength, sizeof(unsigned int)); - + + out.write((char*)&type, sizeof(MaterialType)); out.write((char*)&SpecularExponent, sizeof(float)); out.write((char*)&ReflectionFactor, sizeof(float)); + out.write((char*)&DiffuseColor, sizeof(float) * 3); out.write((char*)&SpecularColor, sizeof(float) * 3); out.write((char*)&IncandescenceColor, sizeof(float) * 3); + out.write((char*)&IndexStart, sizeof(unsigned int)); out.write((char*)&IndexEnd, sizeof(unsigned int)); + if (type != MaterialType::Basic) { + if (type == MaterialType::SplatMapping) { + SplatMap.WriteBinary(out); + } + out.write((char*)&NumColorMaps, sizeof(unsigned char)); + out.write((char*)&NumSpecularMaps, sizeof(unsigned char)); + out.write((char*)&NumNormalMaps, sizeof(unsigned char)); + out.write((char*)&NumIncandescenceMaps, sizeof(unsigned char)); + } - out.write(ColorMapFile.c_str(), ColorMapFileLength); - out.write(NormalMapFile.c_str(), NormalMapFileLength); - out.write(SpecularMapFile.c_str(), SpecularMapFileLength); - out.write(IncandescenceMapFile.c_str(), IncandescenceMapFileLength); + if (type != MaterialType::Basic) { + for (auto aTexture : ColorMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : SpecularMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : NormalMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : IncandescenceMaps) { + aTexture.WriteBinary(out); + } + } } virtual void WriteASCII(std::ostream& out) const { out << "New Material _ not in binary" << endl; - out << "number of indices: " << Name << " _ not in binary" << endl; - out << "ColorMapFile length: " << ColorMapFileLength << endl; - out << "NormalMapFile length: " << NormalMapFileLength << endl; - out << "SpecularMapFile length: " << SpecularMapFileLength << endl; - out << "IncandescenceMapFile length: " << IncandescenceMapFileLength << endl; + out << "MaterialType(enum): "; + switch (type) { + case MaterialType::Basic: + out << "Basic"; + break; + case MaterialType::SplatMapping: + out << "SplatMapping"; + break; + case MaterialType::SingleTextures: + out << "SingleTextures"; + break; + }; + + out << endl; + + out << "Material Name: " << Name << " _ not in binary" << endl; out << "SpecularExponent: " << SpecularExponent << endl; out << "ReflectionFactor: " << ReflectionFactor << endl; @@ -76,17 +137,38 @@ public: out << "IndexStart: " << IndexStart << endl; out << "IndexEnd: " << IndexEnd << endl; - if (ColorMapFileLength > 0) - out << "ColorMapFile: " << ColorMapFile << endl; + switch (type) { + case MaterialType::SplatMapping: + out << "SplatMap _ not in binary " << endl; + SplatMap.WriteASCII(out); + //Intended fall trought + case MaterialType::SingleTextures: + out << "NumColormaps (is unsigned char in Binary): " << ((unsigned int)NumColorMaps) << endl; + out << "NumSpecularMap (is unsigned char in Binary): " << ((unsigned int)NumSpecularMaps) << endl; + out << "NumNormalMap (is unsigned char in Binary): " << ((unsigned int)NumNormalMaps) << endl; + out << "NumIncandescenceMap (is unsigned char in Binary): " << ((unsigned int)NumIncandescenceMaps )<< endl; - if (NormalMapFileLength > 0) - out << "NormalMapFile: " << NormalMapFile << endl; - - if (SpecularMapFileLength > 0) - out << "SpecularMapFile: " << SpecularMapFile << endl; - - if (IncandescenceMapFileLength > 0) - out << "IncandescenceMapFile: " << IncandescenceMapFile << endl; + out << "ColorMaps _ not in binary " << endl; + for (auto aTexture : ColorMaps) { + aTexture.WriteASCII(out); + } + + out << "SpecularMaps _ not in binary " << endl; + for (auto aTexture : SpecularMaps) { + aTexture.WriteASCII(out); + } + + out << "NormalMaps _ not in binary " << endl; + for (auto aTexture : NormalMaps) { + aTexture.WriteASCII(out); + } + + out << "IncandescenceMaps _ not in binary " << endl; + for (auto aTexture : IncandescenceMaps) { + aTexture.WriteASCII(out); + } + break; + }; } }; @@ -107,6 +189,7 @@ private: bool findNormalTexture(MaterialNode& material_node, MFnDependencyNode& node); bool findSpecularTexture(MaterialNode& material_node, MFnDependencyNode& node); bool findIncandescenceTexture(MaterialNode& material_node, MFnDependencyNode& node); + bool findSplatTextures(MaterialNode& material_node, std::vector& textureVector, MFnDependencyNode& node); void grabLambertProperties(MaterialNode& material_node, MFnDependencyNode& node); void grabBlinnProperties(MaterialNode& material_node, MFnDependencyNode& node); void grabPhongProperties(MaterialNode& material_node, MFnDependencyNode& node); diff --git a/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj b/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj index 4a7ac07e..b9384a45 100644 --- a/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj +++ b/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj @@ -40,8 +40,9 @@ v140 - Application + DynamicLibrary v140 + Unicode @@ -77,6 +78,7 @@ $(SolutionDir)$(Platform)\$(Configuration)\ + .mll @@ -135,7 +137,7 @@ NDEBUG;QT_DLL;QT_NO_DEBUG;QT_NO_IMPORT_QT47_QML;UNICODE;WIN32;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories) + C:\Program Files\Autodesk\Maya2016\include;.\GeneratedFiles;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories) MultiThreadedDLL @@ -144,7 +146,7 @@ Windows - $(OutDir)\$(ProjectName).exe + $(OutDir)$(TargetName)$(TargetExt) $(QTDIR)\lib;%(AdditionalLibraryDirectories) false qtmain.lib;%(AdditionalDependencies) diff --git a/tools/MayaExporter/MayaExporter/Menu.cpp b/tools/MayaExporter/MayaExporter/Menu.cpp index 9cc6de91..02810018 100644 --- a/tools/MayaExporter/MayaExporter/Menu.cpp +++ b/tools/MayaExporter/MayaExporter/Menu.cpp @@ -60,8 +60,6 @@ Menu::Menu(QDialog* dialog) m_ExportPath = new QLineEdit; m_FileDialog = new QFileDialog; - QString tmpPath("C:/Users/Nickelodion/Desktop/workspace/tacticalZ/assets/models/"); - m_ExportPath->setText(tmpPath); QLabel* exportLabel = new QLabel; exportLabel->setText("Export Path:"); QLabel* nameLabel = new QLabel; diff --git a/tools/MayaExporter/MayaExporter/Mesh.cpp b/tools/MayaExporter/MayaExporter/Mesh.cpp index 6af8a557..ee5a6022 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.cpp +++ b/tools/MayaExporter/MayaExporter/Mesh.cpp @@ -8,95 +8,91 @@ MeshClass::MeshClass() } -std::map MeshClass::GetWeightData() -{ - MS status; - map weightMap; - - MItDependencyNodes it(MFn::kSkinClusterFilter); - - while (!it.isDone()) { - - MObject object = it.thisNode(&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + " it.thisNode() ERROR: " + status.errorString()); - break; - } - MFnSkinCluster skinCluster(object, &status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster() ERROR: " + status.errorString()); - break; - } - MDagPathArray influences; - - unsigned int nrOfInfluences = skinCluster.influenceObjects(influences,&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.influenceObjects() ERROR: " + status.errorString()); - break; - } - - unsigned int index; - index = skinCluster.indexForOutputConnection(0,&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.indexForOutputConnection() ERROR: " + status.errorString()); - break; - } - MDagPath skinPath; - status = skinCluster.getPathAtIndex(index, skinPath); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.getPathAtIndex() ERROR: " + status.errorString()); - break; - } - - MItGeometry geomIter(skinPath); - //for (unsigned int i = 0; i < nrOfInfluences; i++) { - // MGlobal::displayInfo(MString() + " Influence object name: " + influences[i].partialPathName().asChar()); - //} - WeightInfo weightInfo; - - while (!geomIter.isDone()) { - MObject comp = geomIter.component(&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "geomIter.component() ERROR: " + status.errorString()); - break; - } - MFloatArray weights; - unsigned int influenceCount; - status = skinCluster.getWeights(skinPath, comp, weights, influenceCount); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.getWeights() ERROR: " + status.errorString()); - break; - } - MFnDependencyNode test(comp); - unsigned int nrOfWeights = 0; - - for (unsigned int j = 0; j < weights.length() && nrOfWeights != 4; j++) { - if (weights[j] > 0.00001) { - weightInfo.BoneWeights[nrOfWeights] = weights[j]; - weightInfo.BoneIndices[nrOfWeights] = j; - nrOfWeights++; - } - } - - float totalWeight = 0.0f; - for (unsigned int i = 0; i < 4; i++) { - totalWeight += weightInfo.BoneWeights[i]; - } - for (unsigned int i = 0; i < 4; i++) { - weightInfo.BoneWeights[i] /= totalWeight; - } - weightMap[geomIter.index()] = weightInfo; - - - for (unsigned int k = 0; k!=nrOfWeights; k++) { - MGlobal::displayInfo(MString() + "influence: " + weightInfo.BoneIndices[k] + " weight: " + weightInfo.BoneWeights[k]); - } - geomIter.next(); - } - it.next(); - } - return weightMap; -} +//std::map MeshClass::GetWeightData() +//{ +// MS status; +// map weightMap; +// +// MItDependencyNodes it(MFn::kSkinClusterFilter); +// +// while (!it.isDone()) { +// +// MObject object = it.thisNode(&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + " it.thisNode() ERROR: " + status.errorString()); +// break; +// } +// MFnSkinCluster skinCluster(object, &status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster() ERROR: " + status.errorString()); +// break; +// } +// MDagPathArray influences; +// +// unsigned int nrOfInfluences = skinCluster.influenceObjects(influences,&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.influenceObjects() ERROR: " + status.errorString()); +// break; +// } +// +// unsigned int index; +// index = skinCluster.indexForOutputConnection(0,&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.indexForOutputConnection() ERROR: " + status.errorString()); +// break; +// } +// MDagPath skinPath; +// status = skinCluster.getPathAtIndex(index, skinPath); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.getPathAtIndex() ERROR: " + status.errorString()); +// break; +// } +// +// MItGeometry geomIter(skinPath); +// //for (unsigned int i = 0; i < nrOfInfluences; i++) { +// // MGlobal::displayInfo(MString() + " Influence object name: " + influences[i].partialPathName().asChar()); +// //} +// WeightInfo weightInfo; +// +// while (!geomIter.isDone()) { +// MObject comp = geomIter.component(&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "geomIter.component() ERROR: " + status.errorString()); +// break; +// } +// MFloatArray weights; +// unsigned int influenceCount; +// status = skinCluster.getWeights(skinPath, comp, weights, influenceCount); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.getWeights() ERROR: " + status.errorString()); +// break; +// } +// MFnDependencyNode test(comp); +// unsigned int nrOfWeights = 0; +// +// for (unsigned int j = 0; j < weights.length() && nrOfWeights != 4; j++) { +// if (weights[j] > 0.00001) { +// weightInfo.BoneWeights[nrOfWeights] = weights[j]; +// weightInfo.BoneIndices[nrOfWeights] = j; +// nrOfWeights++; +// } +// } +// +// float totalWeight = 0.0f; +// for (unsigned int i = 0; i < 4; i++) { +// totalWeight += weightInfo.BoneWeights[i]; +// } +// for (unsigned int i = 0; i < 4; i++) { +// weightInfo.BoneWeights[i] /= totalWeight; +// } +// weightMap[geomIter.index()] = weightInfo; +// +// geomIter.next(); +// } +// it.next(); +// } +// return weightMap; +//} Mesh MeshClass::GetMeshData(MObjectArray object) { @@ -112,8 +108,6 @@ Mesh MeshClass::GetMeshData(MObjectArray object) MFnDependencyNode thisNode(node); MPlugArray connections; thisNode.findPlug("inMesh").connectedTo(connections, true, true); - MGlobal::displayInfo(MString() + "inMesh"); - bool hasSkin = false; MPlug weightList, weights; MObject weightListObject; for (unsigned int i = 0; i < connections.length(); i++) { @@ -122,7 +116,7 @@ Mesh MeshClass::GetMeshData(MObjectArray object) weightList = skinCluster.findPlug("weightList", &status); weightListObject = weightList.attribute(); weights = skinCluster.findPlug("weights"); - hasSkin = true; + newMesh.hasSkin = true; break; } } @@ -138,7 +132,6 @@ Mesh MeshClass::GetMeshData(MObjectArray object) } for (int pathID = 0; pathID < dagPaths.length(); pathID++) { - MGlobal::displayInfo(dagPaths[pathID].fullPathName()); MDagPath thisMeshPath(dagPaths[pathID]); MMatrix transformMatrix = thisMeshPath.inclusiveMatrix(&status); @@ -173,8 +166,7 @@ Mesh MeshClass::GetMeshData(MObjectArray object) break; } map> materialFaceIDs; - MGlobal::displayInfo(MString() + "shaderIndexList: " + shaderIndexList.length()); - MGlobal::displayInfo(MString() + "shaderList: " + shaderList.length()); + MPlugArray plugArray; for (int i = 0; i < shaderIndexList.length(); i++) { MFnDependencyNode shader(shaderList[shaderIndexList[i]]); @@ -261,43 +253,33 @@ Mesh MeshClass::GetMeshData(MObjectArray object) //mesh.getPoint(vertexIndex, pos, MSpace::kPostTransform); pos = positions[vertexIndex]; pos = pos * transformMatrix; - if (abs(pos.x) > 0.0001) - thisVertex.Pos[0] = pos.x; - if (abs(pos.y) > 0.0001) - thisVertex.Pos[1] = pos.y; - if (abs(pos.z) > 0.0001) - thisVertex.Pos[2] = pos.z; + + thisVertex.Pos[0] = pos.x; + thisVertex.Pos[1] = pos.y; + thisVertex.Pos[2] = pos.z; status = faceVert.getNormal(normal, MSpace::kObject); if (status != MS::kSuccess) { MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); break; } - if (abs(normal[0]) > 0.0001) - thisVertex.Normal[0] = normal[0]; - if (abs(normal[1]) > 0.0001) - thisVertex.Normal[1] = normal[1]; - if (abs(normal[2]) > 0.0001) - thisVertex.Normal[2] = normal[2]; + + thisVertex.Normal[0] = normal[0]; + thisVertex.Normal[1] = normal[1]; + thisVertex.Normal[2] = normal[2]; MFloatVector Tangent = Tangents[faceVert.tangentId()]; //MVector tmp = faceVert.getTangent(MSpace::kObject, NULL); //tmp.get(biTangent); - if (abs(Tangent[0]) > 0.0001) - thisVertex.Tangent[0] = Tangent[0]; - if (abs(Tangent[1]) > 0.0001) - thisVertex.Tangent[1] = Tangent[1]; - if (abs(Tangent[2]) > 0.0001) - thisVertex.Tangent[2] = Tangent[2]; + thisVertex.Tangent[0] = Tangent[0]; + thisVertex.Tangent[1] = Tangent[1]; + thisVertex.Tangent[2] = Tangent[2]; MFloatVector biNormal = biNormals[faceVert.tangentId()]; //faceVert.getBinormal().get(biNormal); - if (abs(biNormal[0]) > 0.0001) - thisVertex.BiNormal[0] = biNormal[0]; - if (abs(biNormal[1]) > 0.0001) - thisVertex.BiNormal[1] = biNormal[1]; - if (abs(biNormal[2]) > 0.0001) - thisVertex.BiNormal[2] = biNormal[2]; + thisVertex.BiNormal[0] = biNormal[0]; + thisVertex.BiNormal[1] = biNormal[1]; + thisVertex.BiNormal[2] = biNormal[2]; status = faceVert.getUV(UV); if (status != MS::kSuccess) { @@ -308,7 +290,8 @@ Mesh MeshClass::GetMeshData(MObjectArray object) thisVertex.Uv[1] = UV[1]; - if (hasSkin) { + if (newMesh.hasSkin) { + thisVertex.useWeights = true; float totalWeight = 0.0f; unsigned int totalBones = 0; MIntArray jointIDs /* ??? */; @@ -324,9 +307,11 @@ Mesh MeshClass::GetMeshData(MObjectArray object) } for (unsigned int i = 0; i < 4; i++) { - thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; + //thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; } - } + } else { + thisVertex.useWeights = false; + } //float totalWeight = thisVertex.BoneWeights[0] + thisVertex.BoneWeights[1] + thisVertex.BoneWeights[2] + thisVertex.BoneWeights[3]; //if (totalWeight > 0.0001f) { diff --git a/tools/MayaExporter/MayaExporter/Mesh.h b/tools/MayaExporter/MayaExporter/Mesh.h index 11f6bcf8..affc4320 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.h +++ b/tools/MayaExporter/MayaExporter/Mesh.h @@ -11,6 +11,7 @@ class VertexLayout : public OutputData { public: + bool useWeights = true; float Pos[3]{ 0 }; float Normal[3]{ 0 }; float Tangent[3]{ 0 }; @@ -26,8 +27,10 @@ public: out.write((char*)&Tangent, sizeof(float) * 3); out.write((char*)&BiNormal, sizeof(float) * 3); out.write((char*)&Uv, sizeof(float) * 2); - out.write((char*)&BoneIndices, sizeof(float) * 4); - out.write((char*)&BoneWeights, sizeof(float) * 4); + if (useWeights) { + out.write((char*)&BoneIndices, sizeof(float) * 4); + out.write((char*)&BoneWeights, sizeof(float) * 4); + } } virtual void WriteASCII(std::ostream& out) const @@ -37,8 +40,10 @@ public: out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl; out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl; out << Uv[0] << " " << Uv[1] << endl; - out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; - out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + if (useWeights) { + out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; + out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + } } bool operator==(const VertexLayout& right) @@ -57,6 +62,7 @@ public: class Mesh : public OutputData { public: + bool hasSkin = false; unsigned int NumVertices; unsigned int NumIndices; std::vector Vertices; @@ -64,6 +70,7 @@ public: virtual void WriteBinary(std::ostream& out) { + out.write((char*)&hasSkin, sizeof(bool)); out.write((char*)&NumVertices, sizeof(int)); out.write((char*)&NumIndices, sizeof(int)); for (auto aVertex : Vertices) { @@ -79,6 +86,11 @@ public: virtual void WriteASCII(std::ostream& out) const { out << "New Mesh _ not in binary" << endl; + out << "hasSkin: "; + if(hasSkin) + out << "true" << endl; + else + out << "false" << endl; out << "Number of vertices: " << NumVertices << endl; out << "number of indices: " << NumIndices << endl; int vertexNumber = 0; diff --git a/tools/MayaExporter/MayaExporter/Skeleton.cpp b/tools/MayaExporter/MayaExporter/Skeleton.cpp index c30311b8..2e432476 100644 --- a/tools/MayaExporter/MayaExporter/Skeleton.cpp +++ b/tools/MayaExporter/MayaExporter/Skeleton.cpp @@ -60,7 +60,7 @@ // // return m_AllSkeletons; //} -std::string attr[9] = { "scaleX", "scaleY", "scaleZ", "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" }; +static std::string attr[9] = { "scaleX", "scaleY", "scaleZ", "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" }; Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int endFrame) { @@ -68,100 +68,294 @@ Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int e std::vector animatedJoints; std::vector m_Hierarchy; - Animation returnData; - double oneDivSixty = 1 / 60.0; - returnData.Name = animationName; + Animation returnData; + double oneDivSixty = 1 / 60.0; + returnData.Name = animationName; returnData.nameLength = animationName.size() + 1; - returnData.Duration = (endFrame - startFrame) * oneDivSixty; + returnData.Duration = (endFrame - startFrame) * oneDivSixty; - MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); - while (!jointIt.isDone()) - { - m_Hierarchy.push_back(jointIt.item()); + std::map, 4>> joinCheckMap; + std::map exportJoint; - MFnDependencyNode depNode(jointIt.item()); - for (int i = 0; i < 9; i++) - { - MStatus tmp; - MPlug plug = depNode.findPlug(attr[i].c_str(), &tmp); + //MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + //for (unsigned int i = startFrame; i <= endFrame; i++) + //{ + // MAnimControl::setCurrentTime(MTime(i, MTime::kNTSCField)); + // while (!jointIt.isDone()) + // { + // m_Hierarchy.push_back(jointIt.item()); - MPlugArray connections; - plug.connectedTo(connections, true, false, 0); - for (int j = 0; j != connections.length(); j++) { - MObject connected = connections[j].node(); + // MFnTransform MayaJoint(jointIt.item()); + // MMatrix transformationMatrix = MayaJoint.transformationMatrix(); - if (connected.hasFn(MFn::kAnimCurve)) { + // if (i == startFrame) + // { + // double doubleMat[4][4]; + // transformationMatrix.get(doubleMat); - MFnAnimCurve jointAnim(connected); + // joinCheckMap[MayaJoint.name().asChar()][0][0] = doubleMat[0][0]; + // joinCheckMap[MayaJoint.name().asChar()][0][1] = doubleMat[0][1]; + // joinCheckMap[MayaJoint.name().asChar()][0][2] = doubleMat[0][2]; + // joinCheckMap[MayaJoint.name().asChar()][0][3] = doubleMat[0][3]; + // joinCheckMap[MayaJoint.name().asChar()][1][0] = doubleMat[1][0]; + // joinCheckMap[MayaJoint.name().asChar()][1][1] = doubleMat[1][1]; + // joinCheckMap[MayaJoint.name().asChar()][1][2] = doubleMat[1][2]; + // joinCheckMap[MayaJoint.name().asChar()][1][3] = doubleMat[1][3]; + // joinCheckMap[MayaJoint.name().asChar()][2][0] = doubleMat[2][0]; + // joinCheckMap[MayaJoint.name().asChar()][2][1] = doubleMat[2][1]; + // joinCheckMap[MayaJoint.name().asChar()][2][2] = doubleMat[2][2]; + // joinCheckMap[MayaJoint.name().asChar()][2][3] = doubleMat[2][3]; + // joinCheckMap[MayaJoint.name().asChar()][3][0] = doubleMat[3][0]; + // joinCheckMap[MayaJoint.name().asChar()][3][1] = doubleMat[3][1]; + // joinCheckMap[MayaJoint.name().asChar()][3][2] = doubleMat[3][2]; + // joinCheckMap[MayaJoint.name().asChar()][3][3] = doubleMat[3][3]; - unsigned int startKeyFrameIndex = jointAnim.findClosest(MTime(startFrame, MTime::kNTSCField), &tmp); + // exportJoint[MayaJoint.name().asChar()] = false; + // } + // else if(!exportJoint[MayaJoint.name().asChar()])//!exportJoint[MayaJoint.name().asChar()]) + // { + // double doubleMat[4][4]; - if (tmp == MStatus::kFailure) - MGlobal::displayInfo(MString() + "Fail :c"); + // doubleMat[0][0] = joinCheckMap[MayaJoint.name().asChar()][0][0]; + // doubleMat[0][1] = joinCheckMap[MayaJoint.name().asChar()][0][1]; + // doubleMat[0][2] = joinCheckMap[MayaJoint.name().asChar()][0][2]; + // doubleMat[0][3] = joinCheckMap[MayaJoint.name().asChar()][0][3]; + // doubleMat[1][0] = joinCheckMap[MayaJoint.name().asChar()][1][0]; + // doubleMat[1][1] = joinCheckMap[MayaJoint.name().asChar()][1][1]; + // doubleMat[1][2] = joinCheckMap[MayaJoint.name().asChar()][1][2]; + // doubleMat[1][3] = joinCheckMap[MayaJoint.name().asChar()][1][3]; + // doubleMat[2][0] = joinCheckMap[MayaJoint.name().asChar()][2][0]; + // doubleMat[2][1] = joinCheckMap[MayaJoint.name().asChar()][2][1]; + // doubleMat[2][2] = joinCheckMap[MayaJoint.name().asChar()][2][2]; + // doubleMat[2][3] = joinCheckMap[MayaJoint.name().asChar()][2][3]; + // doubleMat[3][0] = joinCheckMap[MayaJoint.name().asChar()][3][0]; + // doubleMat[3][1] = joinCheckMap[MayaJoint.name().asChar()][3][1]; + // doubleMat[3][2] = joinCheckMap[MayaJoint.name().asChar()][3][2]; + // doubleMat[3][3] = joinCheckMap[MayaJoint.name().asChar()][3][3]; - if (startFrame * oneDivSixty <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame * oneDivSixty) { - animatedJoints.push_back(jointIt.item()); - i = 9; - break; - } + // MMatrix tmp(doubleMat); + // if (!tmp.isEquivalent(transformationMatrix)) { + // MGlobal::displayInfo(MString() + MayaJoint.name() + " is exported"); + // exportJoint[MayaJoint.name().asChar()] = true; + // animatedJoints.push_back(MayaJoint.object()); + // } + // } - unsigned int endKeyFrameIndex = jointAnim.findClosest(MTime(endFrame, MTime::kNTSCField)); - MGlobal::displayInfo(MString() + startKeyFrameIndex + " " + endKeyFrameIndex); + /*for (int i = 0; i < 9; i++) + { + MStatus tmp; + MPlug plug = depNode.findPlug(attr[i].c_str(), &tmp); - if (startFrame * oneDivSixty <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame * oneDivSixty || endKeyFrameIndex - startKeyFrameIndex > 0) { - animatedJoints.push_back(jointIt.item()); - i = 9; - break; - } + MPlugArray connections; + plug.connectedTo(connections, true, false, 0); + for (int j = 0; j != connections.length(); j++) { + MObject connected = connections[j].node(); - MFnTransform MayaJoint(jointIt.item()); + if (connected.hasFn(MFn::kAnimCurve)) { - MPlug BindPose = MayaJoint.findPlug("bindPose"); - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix BindPoseMatrix = MartixFn.matrix(); + MFnAnimCurve jointAnim(connected); - if (!BindPoseMatrix.isEquivalent(MayaJoint.transformationMatrix())) - { - MGlobal::displayError(MString() + animationName.c_str() + " is using " + MayaJoint.name() + " that is not in bind pose nor is it key framed in the animation, the exported animation will NOT correspond to the animation in Maya"); - } - } - } - } + //MGlobal::displayInfo(MString() + "curve : " + jointAnim.name()); + //MGlobal::displayInfo(MString() + "curve keys : " + jointAnim.numKeys()); + //MGlobal::displayInfo(MString() + "curve keyframes : " + jointAnim.numKeyframes()); + //MGlobal::displayInfo(MString() + "startFrame : " + startFrame); + //MGlobal::displayInfo(MString() + "endFrame : " + endFrame); - jointIt.next(); - } + unsigned int startKeyFrameIndex = jointAnim.findClosest(MTime(startFrame, MTime::kNTSCField), &tmp); - int currentFrame = startFrame; - while (currentFrame != endFrame + 1) { // ANDREAS - Animation::Keyframe thisKeyFrame; - thisKeyFrame.Index = currentFrame - startFrame; - thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; + if (tmp == MStatus::kFailure) + MGlobal::displayInfo(MString() + "Fail :c"); - MAnimControl::setCurrentTime(MTime(currentFrame, MTime::kNTSCField)); - MTime time = MAnimControl::currentTime(); + if (startFrame * oneDivSixty <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame * oneDivSixty) { + //MGlobal::displayInfo(MString() + "Start key time : " + jointAnim.time(startKeyFrameIndex).value()); - for (auto aJoint : animatedJoints){ - MFnTransform thisJoint(aJoint); - Animation::Keyframe::JointProperty joint; - auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), thisJoint.object()); - if (it != m_Hierarchy.end()) { - joint.ID = it - m_Hierarchy.begin(); - } - else { - MGlobal::displayError(MString() + "Could not find joint ID for: " + thisJoint.name()); - } - - MTransformationMatrix Matrix = thisJoint.transformation(); - MPlug BindPose = thisJoint.findPlug("bindPose"); - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix BindPoseMatrix = MartixFn.matrix(); - Matrix = Matrix.asMatrix(); - + if (startFrame <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame ) { + animatedJoints.push_back(jointIt.item()); + i = 9; + break; + } + + unsigned int endKeyFrameIndex = jointAnim.findClosest(MTime(endFrame, MTime::kNTSCField)); + MGlobal::displayInfo(MString() + startKeyFrameIndex + " " + endKeyFrameIndex); + MGlobal::displayInfo(MString() + "Fail!!!!!!!!!!!!!!!!!!!!!!!!!"); + + if (startFrame * oneDivSixty <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame * oneDivSixty || endKeyFrameIndex - startKeyFrameIndex > 0) { + //MGlobal::displayInfo(MString() + "End key index : " + endKeyFrameIndex); + //MGlobal::displayInfo(MString() + "end key time : " + jointAnim.time(endKeyFrameIndex).value()); + + /*MGlobal::displayInfo(MString() + "start keyfram index: " + startKeyFrameIndex + ". End keyfram index: " + endKeyFrameIndex + ".");*/ + + /*if (startFrame <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame || endKeyFrameIndex - startKeyFrameIndex > 0) { + animatedJoints.push_back(jointIt.item()); + i = 9; + break; + } + + MFnTransform MayaJoint(jointIt.item()); + + MPlug BindPose = MayaJoint.findPlug("bindPose"); + MDataHandle DataHandle; + BindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix BindPoseMatrix = MartixFn.matrix(); + + if (!BindPoseMatrix.isEquivalent(MayaJoint.transformationMatrix())) + { + MGlobal::displayError(MString() + animationName.c_str() + " is using " + MayaJoint.name() + " that is not in bind pose nor is it key framed in the animation, the exported animation will NOT correspond to the animation in Maya"); + } + } + } + } + + } // end of int i loop*/ + /* jointIt.next(); + } + jointIt.reset(); + }*/ + + MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + unsigned int jointID = 0; + + while (!jointIt.isDone()) { + int currentFrame = startFrame; + Animation::JointAnimation thisJointAnimation; + bool haxBool = false; + while (currentFrame < endFrame) { + Animation::JointAnimation::KeyFrame thisKeyFrame; + //thisKeyFrame.Index = currentFrame - startFrame; + //thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; + + MAnimControl::setCurrentTime(MTime(currentFrame, MTime::kNTSCField)); + MTime time = MAnimControl::currentTime(); + + MFnTransform thisJoint(jointIt.currentItem()); + MTransformationMatrix transformationMatrix = thisJoint.transformationMatrix(); + + double doubleMat[4][4]; + + if (currentFrame != startFrame) { + //Animation::JointAnimation joint; + + doubleMat[0][0] = joinCheckMap[thisJoint.name().asChar()][0][0]; + doubleMat[0][1] = joinCheckMap[thisJoint.name().asChar()][0][1]; + doubleMat[0][2] = joinCheckMap[thisJoint.name().asChar()][0][2]; + doubleMat[0][3] = joinCheckMap[thisJoint.name().asChar()][0][3]; + doubleMat[1][0] = joinCheckMap[thisJoint.name().asChar()][1][0]; + doubleMat[1][1] = joinCheckMap[thisJoint.name().asChar()][1][1]; + doubleMat[1][2] = joinCheckMap[thisJoint.name().asChar()][1][2]; + doubleMat[1][3] = joinCheckMap[thisJoint.name().asChar()][1][3]; + doubleMat[2][0] = joinCheckMap[thisJoint.name().asChar()][2][0]; + doubleMat[2][1] = joinCheckMap[thisJoint.name().asChar()][2][1]; + doubleMat[2][2] = joinCheckMap[thisJoint.name().asChar()][2][2]; + doubleMat[2][3] = joinCheckMap[thisJoint.name().asChar()][2][3]; + doubleMat[3][0] = joinCheckMap[thisJoint.name().asChar()][3][0]; + doubleMat[3][1] = joinCheckMap[thisJoint.name().asChar()][3][1]; + doubleMat[3][2] = joinCheckMap[thisJoint.name().asChar()][3][2]; + doubleMat[3][3] = joinCheckMap[thisJoint.name().asChar()][3][3]; + + MMatrix LastJointMatrix(doubleMat); + //Is same as last KeyFrame + if (LastJointMatrix.isEquivalent(transformationMatrix.asMatrix())) { + //jointID++; + //jointIt.next(); + currentFrame++; + haxBool = false; + continue; + } else if(!haxBool){ + haxBool = true; + MTransformationMatrix LastJointTransformationMatrix = LastJointMatrix; + MObject jointOrientObj = thisJoint.attribute("jointOrient"); + MFnNumericAttribute jointOrient(jointOrientObj); + double jointOrientDouble[3]; + jointOrient.getDefault(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); + //MGlobal::displayError(MString() + "Joint Matrix: "); + //MGlobal::displayError(MString() + Matrix.asMatrix()[0][0] + " " + Matrix.asMatrix()[0][1] + " " + Matrix.asMatrix()[0][2] + " " + Matrix.asMatrix()[0][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[1][0] + " " + Matrix.asMatrix()[1][1] + " " + Matrix.asMatrix()[1][2] + " " + Matrix.asMatrix()[1][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[2][0] + " " + Matrix.asMatrix()[2][1] + " " + Matrix.asMatrix()[2][2] + " " + Matrix.asMatrix()[2][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[3][0] + " " + Matrix.asMatrix()[3][1] + " " + Matrix.asMatrix()[3][2] + " " + Matrix.asMatrix()[3][3]); + + MEulerRotation joEuler(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); + MQuaternion jo = joEuler.asQuaternion(); + + double tmp[4]; + LastJointTransformationMatrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); + MQuaternion rotation(tmp); + + rotation = rotation * jo; + rotation.get(tmp); + + //Animation::JointAnimation::KeyFrame keyframe; + Animation::JointAnimation::KeyFrame previousKeyFrame; + previousKeyFrame.Index = currentFrame - startFrame - 1; + previousKeyFrame.Time = previousKeyFrame.Index * oneDivSixty; + + previousKeyFrame.Rotation[0] = tmp[0]; + previousKeyFrame.Rotation[1] = tmp[1]; + previousKeyFrame.Rotation[2] = tmp[2]; + previousKeyFrame.Rotation[3] = tmp[3]; + LastJointTransformationMatrix.getTranslation(MSpace::kTransform).get(tmp); + previousKeyFrame.Position[0] = tmp[0]; + previousKeyFrame.Position[1] = tmp[1]; + previousKeyFrame.Position[2] = tmp[2]; + LastJointTransformationMatrix.getScale(tmp, MSpace::kTransform); + previousKeyFrame.Scale[0] = tmp[0]; + previousKeyFrame.Scale[1] = tmp[1]; + previousKeyFrame.Scale[2] = tmp[2]; + + thisJointAnimation.m_KeyFrames.push_back(previousKeyFrame); + } + } + + transformationMatrix.asMatrix().get(doubleMat); + + //Save transformationMatrix to joinCheckMap + joinCheckMap[thisJoint.name().asChar()][0][0] = doubleMat[0][0]; + joinCheckMap[thisJoint.name().asChar()][0][1] = doubleMat[0][1]; + joinCheckMap[thisJoint.name().asChar()][0][2] = doubleMat[0][2]; + joinCheckMap[thisJoint.name().asChar()][0][3] = doubleMat[0][3]; + joinCheckMap[thisJoint.name().asChar()][1][0] = doubleMat[1][0]; + joinCheckMap[thisJoint.name().asChar()][1][1] = doubleMat[1][1]; + joinCheckMap[thisJoint.name().asChar()][1][2] = doubleMat[1][2]; + joinCheckMap[thisJoint.name().asChar()][1][3] = doubleMat[1][3]; + joinCheckMap[thisJoint.name().asChar()][2][0] = doubleMat[2][0]; + joinCheckMap[thisJoint.name().asChar()][2][1] = doubleMat[2][1]; + joinCheckMap[thisJoint.name().asChar()][2][2] = doubleMat[2][2]; + joinCheckMap[thisJoint.name().asChar()][2][3] = doubleMat[2][3]; + joinCheckMap[thisJoint.name().asChar()][3][0] = doubleMat[3][0]; + joinCheckMap[thisJoint.name().asChar()][3][1] = doubleMat[3][1]; + joinCheckMap[thisJoint.name().asChar()][3][2] = doubleMat[3][2]; + joinCheckMap[thisJoint.name().asChar()][3][3] = doubleMat[3][3]; + + if (currentFrame == startFrame) { + MPlug thisJointBindPose = thisJoint.findPlug("bindPose"); + MDataHandle DataHandle; + thisJointBindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix thisJointBindPoseMatrix = MartixFn.matrix(); + + MFnTransform Parent(thisJoint.parent(0), &status); + if (status == MS::kSuccess && thisJoint.parent(0).apiType() == MFn::kJoint) { + MTransformationMatrix Matrix = Parent.transformation(); + MPlug parentBindPose = Parent.findPlug("bindPose"); + MDataHandle DataHandle; + parentBindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix parentBindPoseMatrix = MartixFn.matrix(); + + thisJointBindPoseMatrix = thisJointBindPoseMatrix * parentBindPoseMatrix.inverse(); + } + + if (thisJointBindPoseMatrix.isEquivalent(transformationMatrix.asMatrix())) { + //jointID++; + //jointIt.next(); + currentFrame++; + MGlobal::displayError(MString() + thisJoint.name() + " is in bindPose"); + continue; + } + haxBool = true; + } + MObject jointOrientObj = thisJoint.attribute("jointOrient"); MFnNumericAttribute jointOrient(jointOrientObj); double jointOrientDouble[3]; @@ -175,95 +369,97 @@ Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int e MEulerRotation joEuler(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); MQuaternion jo = joEuler.asQuaternion(); - double tmp[4]; - Matrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); + double tmp[4]; + transformationMatrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); MQuaternion rotation(tmp); rotation = rotation * jo; rotation.get(tmp); - joint.Rotation[0] = tmp[0]; - joint.Rotation[1] = tmp[1]; - joint.Rotation[2] = tmp[2]; - joint.Rotation[3] = tmp[3]; - Matrix.getTranslation(MSpace::kTransform).get(tmp); - joint.Position[0] = tmp[0]; - joint.Position[1] = tmp[1]; - joint.Position[2] = tmp[2]; - Matrix.getScale(tmp, MSpace::kTransform); - joint.Scale[0] = tmp[0]; - joint.Scale[1] = tmp[1]; - joint.Scale[2] = tmp[2]; + //Animation::JointAnimation::KeyFrame keyframe; + thisKeyFrame.Index = currentFrame - startFrame; + thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; - thisKeyFrame.JointProperties.push_back(joint); - } - returnData.Keyframes.push_back(thisKeyFrame); - currentFrame++; - } + thisKeyFrame.Rotation[0] = tmp[0]; + thisKeyFrame.Rotation[1] = tmp[1]; + thisKeyFrame.Rotation[2] = tmp[2]; + thisKeyFrame.Rotation[3] = tmp[3]; + transformationMatrix.getTranslation(MSpace::kTransform).get(tmp); + thisKeyFrame.Position[0] = tmp[0]; + thisKeyFrame.Position[1] = tmp[1]; + thisKeyFrame.Position[2] = tmp[2]; + transformationMatrix.getScale(tmp, MSpace::kTransform); + thisKeyFrame.Scale[0] = tmp[0]; + thisKeyFrame.Scale[1] = tmp[1]; + thisKeyFrame.Scale[2] = tmp[2]; - returnData.NumKeyFrames = returnData.Keyframes.size(); - returnData.NumberOfJoints = animatedJoints.size(); + thisJointAnimation.m_KeyFrames.push_back(thisKeyFrame); - return returnData; + currentFrame++; + } + //thisKeyFrame.NumberOfJoints = thisKeyFrame.JointProperties.size(); + thisJointAnimation.numberOFKeyFrames = thisJointAnimation.m_KeyFrames.size(); + returnData.JointsFrameMap[jointID] = (thisJointAnimation); + + jointID++; + jointIt.next(); + } + returnData.NumOfJointFrames = returnData.JointsFrameMap.size(); + return returnData; } std::vector Skeleton::GetBindPoses() { MStatus status; - std::vector m_AllSkeletons; - std::vector m_Hierarchy; + std::vector m_AllSkeletons; + std::vector m_Hierarchy; - MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); - BindPoseSkeletonNode SkeletonStorage; - while (!jointIt.isDone()) { - MFnTransform MayaJoint(jointIt.currentItem()); - BindPoseSkeletonNode::BindPoseJoint NewJoint; + MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + BindPoseSkeletonNode SkeletonStorage; + while (!jointIt.isDone()) { + MFnTransform MayaJoint(jointIt.currentItem()); + BindPoseSkeletonNode::BindPoseJoint NewJoint; - if (MFnDependencyNode(MayaJoint.parent(0)).name() == "world") { - if (SkeletonStorage.Joints.size() != 0) { - m_AllSkeletons.push_back(SkeletonStorage); + if (MFnDependencyNode(MayaJoint.parent(0)).object().apiType() != MFn::kJoint) { + if (SkeletonStorage.Joints.size() != 0) { + m_AllSkeletons.push_back(SkeletonStorage); - SkeletonStorage.Joints.clear(); - SkeletonStorage.Name.clear(); - } - SkeletonStorage.Name = std::string(MayaJoint.name().asChar()); - NewJoint.ParentID = -1; // This joint is root - } - else { - auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), MayaJoint.parent(0)); - if (it != m_Hierarchy.end()) { - NewJoint.ParentID = it - m_Hierarchy.begin(); - } - else { - MGlobal::displayError(MString() + "Could not find joint parent for: " + MayaJoint.name()); - } - } - m_Hierarchy.push_back(MayaJoint.object()); + SkeletonStorage.Joints.clear(); + SkeletonStorage.Name.clear(); + } + SkeletonStorage.Name = std::string(MayaJoint.name().asChar()); + NewJoint.ParentID = -1; // This joint is root + } else { + auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), MayaJoint.parent(0)); + if (it != m_Hierarchy.end()) { + NewJoint.ParentID = it - m_Hierarchy.begin(); + } else { + MGlobal::displayError(MString() + "Could not find joint parent for: " + MayaJoint.name()); + } + } + m_Hierarchy.push_back(MayaJoint.object()); - MPlug BindPose = MayaJoint.findPlug("bindPose", &status); - if (status != MS::kSuccess) { + MPlug BindPose = MayaJoint.findPlug("bindPose", &status); + if (status != MS::kSuccess) { MGlobal::displayError(MString() + "Could not find bindPose plug: " + status.errorString()); } - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix Matrix = MartixFn.matrix(); + MDataHandle DataHandle; + BindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix Matrix = MartixFn.matrix(); MVector tmp = MayaJoint.transformation().getTranslation(MSpace::kObject); - MGlobal::displayError(MString() + "translation befor: " + tmp[0] + " " + tmp[1] + " " + tmp[2]); //Matrix[3][0] *= -1; //Matrix[3][2] *= -1; //Matrix[3][1] *= -1; double test[3]; MayaJoint.transformation().getScale(test, MSpace::kObject); - MGlobal::displayError(MString() + "scale: " + test[0] + " " + test[1] + " " + test[2]); MTransformationMatrix::RotationOrder order = MTransformationMatrix::RotationOrder::kXYZ; MayaJoint.transformation().getRotation(test, order); - MGlobal::displayError(MString() + "rotation: " + test[0] + " " + test[1] + " " + test[2]); - + //----- test @@ -310,33 +506,33 @@ std::vector Skeleton::GetBindPoses() Matrix = Matrix.inverse(); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j]; - } - } + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j]; + } + } - NewJoint.Name = MayaJoint.name().asChar(); + NewJoint.Name = MayaJoint.name().asChar(); NewJoint.NameLength = MayaJoint.name().length() + 1; NewJoint.ID = SkeletonStorage.Joints.size(); - //double tmp[3]; - //((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp); - //NewJoint.Rotation[0] = tmp[0]; - //NewJoint.Rotation[1] = tmp[1]; - //NewJoint.Rotation[2] = tmp[2]; - //((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform); - //NewJoint.Scale[0] = tmp[0]; - //NewJoint.Scale[1] = tmp[1]; - //NewJoint.Scale[2] = tmp[2]; - //((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp); - //NewJoint.Translation[0] = tmp[0]; - //NewJoint.Translation[1] = tmp[1]; - //NewJoint.Translation[2] = tmp[2]; - SkeletonStorage.Joints.push_back(NewJoint); + //double tmp[3]; + //((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp); + //NewJoint.Rotation[0] = tmp[0]; + //NewJoint.Rotation[1] = tmp[1]; + //NewJoint.Rotation[2] = tmp[2]; + //((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform); + //NewJoint.Scale[0] = tmp[0]; + //NewJoint.Scale[1] = tmp[1]; + //NewJoint.Scale[2] = tmp[2]; + //((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp); + //NewJoint.Translation[0] = tmp[0]; + //NewJoint.Translation[1] = tmp[1]; + //NewJoint.Translation[2] = tmp[2]; + SkeletonStorage.Joints.push_back(NewJoint); SkeletonStorage.numBones++; - jointIt.next(); - } - m_AllSkeletons.push_back(SkeletonStorage); + jointIt.next(); + } + m_AllSkeletons.push_back(SkeletonStorage); - return m_AllSkeletons; + return m_AllSkeletons; } \ No newline at end of file diff --git a/tools/MayaExporter/MayaExporter/Skeleton.h b/tools/MayaExporter/MayaExporter/Skeleton.h index 6a288c8a..3dfbe8a5 100644 --- a/tools/MayaExporter/MayaExporter/Skeleton.h +++ b/tools/MayaExporter/MayaExporter/Skeleton.h @@ -3,50 +3,63 @@ #include #include +#include #include #include "MayaIncludes.h" #include "OutputData.h" class Animation : public OutputData { public: - struct Keyframe - { - struct JointProperty - { - int ID = 0; + //struct Keyframe + //{ + // struct JointProperty + // { + // int ID = 0; + // float Position[3]{ 0 }; + // float Rotation[4]{ 0 }; + // float Scale[3]{ 0 }; + // }; + + // int Index = 0; + // float Time = 0; + // int NumberOfJoints; + // std::vector JointProperties; + //}; + + struct JointAnimation { + struct KeyFrame { + int Index = 0; + float Time = 0; float Position[3]{ 0 }; float Rotation[4]{ 0 }; float Scale[3]{ 0 }; - }; - - int Index = 0; - float Time = 0; - std::vector JointProperties; - }; + }; + unsigned int numberOFKeyFrames = 0; + std::vector m_KeyFrames; + }; std::string Name; int nameLength = 0; float Duration = 0; - int NumKeyFrames = 0; - int NumberOfJoints = 0; - std::vector Keyframes; + int NumOfJointFrames = 0; + std::map JointsFrameMap; virtual void WriteBinary(std::ostream& out) { out.write((char*)&nameLength, sizeof(int)); out.write(Name.c_str(), Name.size() + 1); out.write((char*)&Duration, sizeof(float)); - out.write((char*)&NumKeyFrames, sizeof(int)); - out.write((char*)&NumberOfJoints, sizeof(int)); + out.write((char*)&NumOfJointFrames, sizeof(int)); //Här under loopas alla key frames igenom - for (auto aKeyframe : Keyframes) { - out.write((char*)&aKeyframe.Index, sizeof(int)); - out.write((char*)&aKeyframe.Time, sizeof(float)); - for (auto aJoint : aKeyframe.JointProperties) { - out.write((char*)&aJoint.ID, sizeof(int)); - out.write((char*)aJoint.Position, sizeof(float) * 3); - out.write((char*)aJoint.Rotation, sizeof(float) * 4); - out.write((char*)aJoint.Scale, sizeof(float) * 3); + for (auto aJointAnimation : JointsFrameMap) { + out.write((char*)&aJointAnimation.first, sizeof(int)); + out.write((char*)&aJointAnimation.second.numberOFKeyFrames, sizeof(int)); + for (auto aJointKeyFrame : aJointAnimation.second.m_KeyFrames) { + out.write((char*)&aJointKeyFrame.Index, sizeof(int)); + out.write((char*)&aJointKeyFrame.Time, sizeof(float)); + out.write((char*)&aJointKeyFrame.Position, sizeof(float) * 3); + out.write((char*)&aJointKeyFrame.Rotation, sizeof(float) * 4); + out.write((char*)&aJointKeyFrame.Scale, sizeof(float) * 3); } } } @@ -55,16 +68,17 @@ public: { out << "Animation Name: " << Name << endl; out << "Duration: " << Duration << endl; - out << "Number of KeyFrames: " << NumKeyFrames << endl; - out << "Number of Joints: " << NumberOfJoints << endl; - for (auto aKeyframe : Keyframes) { - out << "Frame: " << aKeyframe.Index << endl; - out << "Time: " << aKeyframe.Time << endl; - for (auto aJoint : aKeyframe.JointProperties) { - out << "Joint ID: " << aJoint.ID << endl; - out << aJoint.Position[0] << " " << aJoint.Position[1] << " " << aJoint.Position[2] << endl; - out << aJoint.Rotation[0] << " " << aJoint.Rotation[1] << " " << aJoint.Rotation[2] << " " << aJoint.Rotation[3] << endl; - out << aJoint.Scale[0] << " " << aJoint.Scale[1] << " " << aJoint.Scale[2] << endl; + out << "Number of KeyFrames: " << NumOfJointFrames << endl; + for (auto aJointAnimation : JointsFrameMap) { + out << "Bone: " << aJointAnimation.first << endl; + //out << "Time: " << aJointAnimation.Time << endl; + //out << "Number of Joints: " << aKeyframe.NumberOfJoints << endl; + for (auto aJointKeyFrame : aJointAnimation.second.m_KeyFrames) { + //out << "Joint ID: " << aJoint.ID << endl; + out << "Time: " << aJointKeyFrame.Time << endl; + out << aJointKeyFrame.Position[0] << " " << aJointKeyFrame.Position[1] << " " << aJointKeyFrame.Position[2] << endl; + out << aJointKeyFrame.Rotation[0] << " " << aJointKeyFrame.Rotation[1] << " " << aJointKeyFrame.Rotation[2] << " " << aJointKeyFrame.Rotation[3] << endl; + out << aJointKeyFrame.Scale[0] << " " << aJointKeyFrame.Scale[1] << " " << aJointKeyFrame.Scale[2] << endl; } }