diff --git a/samples/02_Demo2D/Demo2D.cpp b/samples/02_Demo2D/Demo2D.cpp index adbf3ceba..6def43d0f 100644 --- a/samples/02_Demo2D/Demo2D.cpp +++ b/samples/02_Demo2D/Demo2D.cpp @@ -101,6 +101,10 @@ class Demo2DApp : public App::AppBase { mCanvasRenderer->drawRect(100, 600, 110, 124, true); + mCanvasRenderer->drawRect(100, 700, 110, 124, true); + + mCanvasRenderer->drawRect(100, 1000, 110, 124, true); + return true; } diff --git a/src/Editor/src/main.cpp b/src/Editor/src/main.cpp index 4700eacdc..8d0959e90 100644 --- a/src/Editor/src/main.cpp +++ b/src/Editor/src/main.cpp @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { std::cout << "Editor version 0.1\n"; OsreEdApp osreApp(argc, argv); - if (!osreApp.initWindow(100, 100, 1024, 768, "test", WindowMode::Windowed, WindowType::Root, App::RenderBackendType::OpenGLRenderBackend)) { + if (!osreApp.initWindow(100, 100, 1024, 768, "test", false, true, RenderBackendType::OpenGLRenderBackend)) { return -1; } @@ -60,7 +60,12 @@ int main(int argc, char *argv[]) { // Main loop bool done = false; while (!done) { - done = !osreApp.handleEvents(); + static int counter = 0; + done = osreApp.handleEvents(); + App::Stage *stage = osreApp.getStage(); + if (stage != nullptr) { + World *world = stage->getActiveWorld(0); + } osreApp.update(); osreApp.requestNextFrame(); } diff --git a/src/Engine/Animation/AnimatorBase.h b/src/Engine/Animation/AnimatorBase.h index 13917fb39..29bcd48bc 100644 --- a/src/Engine/Animation/AnimatorBase.h +++ b/src/Engine/Animation/AnimatorBase.h @@ -82,31 +82,38 @@ struct OSRE_EXPORT Skeleton { }; struct VectorKey { - glm::vec3 mVector; - d32 mTime; + f32 Time; + glm::vec3 Value; + + VectorKey() : Time(1.0f), Value(1) { + // empty + } + + ~VectorKey() = default; }; +using VectorKeyArray = ::cppcore::TArray; + struct RotationKey { glm::vec4 mQuad; d32 mTime; }; -using VectorKeyArray = ::cppcore::TArray; using RotationKeyArray = ::cppcore::TArray; -struct NodeAnimation { - VectorKeyArray mPositions; - VectorKeyArray mScalings; - RotationKeyArray mRotations; -}; +struct VectorChannel { + size_t NumVectorKeys; + VectorKeyArray VectorKeys; -struct AnimationTrack { - String mName; - double mDuration; - double mTicksPerSecond; - cppcore::TArray mNodeAnimations; + VectorChannel() : NumVectorKeys(0), VectorKeys() { + // empty + } + + ~VectorChannel() = default; }; +using VectorChannelArray = ::cppcore::TArray; + template struct AnimatorBase { void operator () ( T &out, const T &a, const T &b, f32 d ) const { @@ -128,7 +135,6 @@ enum class TransformCommandType { Count }; - //------------------------------------------------------------------------------------------------- /// @ingroup Engine /// @@ -139,7 +145,7 @@ class OSRE_EXPORT AnimationControllerBase { public: /// @brief The class destructor, virtual. virtual ~AnimationControllerBase() = default; - + /// @brief Will update the mouse input state. /// @param mis The mouse input. virtual void getMouseUpdate(const App::MouseInputState &mis) = 0; diff --git a/src/Engine/Animation/AnimatorComponent.cpp b/src/Engine/Animation/AnimatorComponent.cpp new file mode 100644 index 000000000..1e69f69e9 --- /dev/null +++ b/src/Engine/Animation/AnimatorComponent.cpp @@ -0,0 +1,82 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2015-2024 OSRE ( Open Source Render Engine ) by Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include "Animation/AnimatorComponent.h" + +namespace OSRE{ +namespace Animation { + +using namespace OSRE::App; + +AnimatorComponent::AnimatorComponent(Entity *owner, ComponentType type) : + Component(owner, type), + mAnimationTrackArray(), + mActiveTrack() { + // empty +} + +AnimatorComponent::~AnimatorComponent() { + // empty +} + +void AnimatorComponent::addTrack(AnimationTrack *track) { + if (track == nullptr) { + return; + } + + mAnimationTrackArray.add(track); +} + +AnimationTrack *AnimatorComponent::getTrackAt(size_t index) const { + if (index >= mAnimationTrackArray.size()) { + return nullptr; + } + + return mAnimationTrackArray[index]; +} + +bool AnimatorComponent::selectTrack(size_t index) { + if (index >= mAnimationTrackArray.size()) { + return false; + } + + mActiveTrack = index; + + return true; +} + +size_t AnimatorComponent::getActiveTrack() const { + return mActiveTrack; +} + +bool AnimatorComponent::onUpdate(Time dt) { + return true; +} + +bool AnimatorComponent::onRender(RenderBackend::RenderBackendService *renderBackendSrv) { + osre_assert(renderBackendSrv != nullptr); + + return true; +} + +} // namespace Animation +} // namespace OSRE diff --git a/src/Engine/Animation/AnimatorComponent.h b/src/Engine/Animation/AnimatorComponent.h new file mode 100644 index 000000000..eeaf84525 --- /dev/null +++ b/src/Engine/Animation/AnimatorComponent.h @@ -0,0 +1,74 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2015-2024 OSRE ( Open Source Render Engine ) by Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#pragma once + +#include "Common/osre_common.h" +#include "Animation/AnimatorBase.h" +#include "App/Component.h" + +namespace OSRE { +namespace Animation { + +struct AnimationTrack { + f32 Duration; + f32 mTicksPerSecond; + size_t NumVectorChannels; + VectorChannel *VectorChannels; + + AnimationTrack() : + Duration(1.0f), mTicksPerSecond(1.0f), NumVectorChannels(0l), VectorChannels(nullptr) { + // empty + } + + ~AnimationTrack() { + delete [] VectorChannels; + VectorChannels = nullptr; + } +}; + +//------------------------------------------------------------------------------------------------- +/// @ingroup Engine +/// +/// @brief Describes the base class for all components. +//------------------------------------------------------------------------------------------------- +class AnimatorComponent : public App::Component { +public: + AnimatorComponent(App::Entity *owner, App::ComponentType type); + ~AnimatorComponent(); + void addTrack(AnimationTrack *track); + AnimationTrack *getTrackAt(size_t index) const; + bool selectTrack(size_t index); + size_t getActiveTrack() const; + +protected: + bool onUpdate(Time dt) override; + bool onRender(RenderBackend::RenderBackendService *renderBackendSrv) override; + +private: + using AnimationTrackArray = cppcore::TArray; + AnimationTrackArray mAnimationTrackArray; + size_t mActiveTrack; +}; + +} // namespace Animation +} // namespace OSRE diff --git a/src/Engine/App/AssimpWrapper.cpp b/src/Engine/App/AssimpWrapper.cpp index 8b1dbd017..688e831aa 100644 --- a/src/Engine/App/AssimpWrapper.cpp +++ b/src/Engine/App/AssimpWrapper.cpp @@ -216,24 +216,14 @@ Entity *AssimpWrapper::convertScene() { if (nullptr != mAssetContext.mScene->mRootNode) { importNode(mAssetContext.mScene->mRootNode, nullptr); } - AnimationMap animLookup; - if (nullptr != mAssetContext.mScene->mAnimations) { - cppcore::TArray animationTracks; - animationTracks.resize(mAssetContext.mScene->mNumAnimations); - for (ui32 i = 0; i < mAssetContext.mScene->mNumAnimations; ++i) { - importAnimation(mAssetContext.mScene->mAnimations[i], animationTracks[i], animLookup); - } - } + importAnimations(mAssetContext.mScene); + if (!mAssetContext.mMeshArray.isEmpty()) { RenderComponent *rc = (RenderComponent*) mAssetContext.mEntity->getComponent(ComponentType::RenderComponentType); rc->addStaticMeshArray(mAssetContext.mMeshArray); } - if (mAssetContext.mScene->hasSkeletons()) { - importSkeletons(*mAssetContext.mScene->mSkeletons, mAssetContext.mScene->mNumSkeletons); - } - return mAssetContext.mEntity; } @@ -535,35 +525,19 @@ void AssimpWrapper::importMaterial(aiMaterial *material) { using Bone2NodeMap = cppcore::THashMap; -void AssimpWrapper::importSkeletons( aiSkeleton *skeletons, size_t numSkeletons) { - if (numSkeletons == 0 || skeletons == nullptr) { +void AssimpWrapper::importAnimations(const aiScene *scene) { + if (scene == nullptr) { return; } - - Bone2NodeMap bone2NodeMap; - for (size_t skeletonIdx = 0; skeletonIdx < numSkeletons; ++skeletonIdx) { - aiSkeleton ¤tSkeleton = skeletons[skeletonIdx]; - for (size_t boneIdx = 0; boneIdx < currentSkeleton.mNumBones; ++boneIdx) { - aiSkeletonBone *bone = currentSkeleton.mBones[boneIdx]; - if (bone == nullptr) { - continue; - } - - aiMesh *mesh = bone->mMeshId; - if (mesh == nullptr) { - continue; - } + + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { + const aiMesh *mesh = scene->mMeshes[i]; + for (unsigned int n = 0; n < mesh->mNumBones; ++n) { + const aiBone *bone = mesh->mBones[n]; + mAssetContext.mBone2NodeMap[bone->mName.data] = scene->mRootNode->FindNode(bone->mName); } } } -void AssimpWrapper::importAnimation(aiAnimation *animation, AnimationTrack ¤tAnimationTrack, AnimationMap &animLookup) { - if (nullptr == animation) { - return; - } - - currentAnimationTrack.mName = animation->mName.C_Str(); -} - } // namespace App } // namespace OSRE diff --git a/src/Engine/App/AssimpWrapper.h b/src/Engine/App/AssimpWrapper.h index 3210fde60..23ee6fe3f 100644 --- a/src/Engine/App/AssimpWrapper.h +++ b/src/Engine/App/AssimpWrapper.h @@ -79,9 +79,6 @@ class OSRE_EXPORT AssimpWrapper { /// @brief Alias for bone to node relations. using Bone2NodeMap = std::map; - /// @brief Name to animation track relation alias. - using AnimationMap = std::map; - /// @brief The class constructor. /// @param ids The id container. /// @param world The world to put the imported entity in. @@ -112,11 +109,9 @@ class OSRE_EXPORT AssimpWrapper { protected: Entity *convertScene(); void importMeshes( aiMesh **meshes, ui32 numMeshes ); - //void importBones(aiMesh* mesh); void importNode( aiNode *node, TransformComponent *parent ); void importMaterial( aiMaterial *material ); - void importSkeletons(aiSkeleton *skeletons, size_t numSkeletons); - void importAnimation(aiAnimation *animation, Animation::AnimationTrack ¤tAnimationTrack, AnimationMap &animLookup); + void importAnimations(const aiScene *scene); void optimizeVertexBuffer(); private: diff --git a/src/Engine/App/Component.cpp b/src/Engine/App/Component.cpp index df7e80acc..7530638d6 100644 --- a/src/Engine/App/Component.cpp +++ b/src/Engine/App/Component.cpp @@ -109,7 +109,6 @@ bool LightComponent::onUpdate(Time) { return true; } - return true; } diff --git a/src/Engine/App/Component.h b/src/Engine/App/Component.h index c9d23a193..4353ea9ad 100644 --- a/src/Engine/App/Component.h +++ b/src/Engine/App/Component.h @@ -49,6 +49,7 @@ enum class ComponentType { TransformComponentType, ///< For all transformation types. LightComponentType, ///< For light types. CameraComponentType, ///< For camera components. + AnimationComponentType, ///< Count ///< The number of components. }; @@ -65,15 +66,15 @@ class OSRE_EXPORT Component { /// @brief The update callback /// @param[in] timeSlice The time slice virtual void update(Time timeSlice); - + /// @brief The render callback. /// @param[in] renderBackendSrv The render backend service. virtual void render(RenderBackend::RenderBackendService *renderBackendSrv); - + /// @brief Will return the owning entity. /// @return Pointer showing to the entity instance, nullptr in none. virtual Entity *getOwner() const; - + /// @brief Will return the component type. /// @return The component type. virtual ComponentType getType() const; @@ -88,12 +89,12 @@ class OSRE_EXPORT Component { /// @param[in] owner The component type. /// @param[in] type The owning entity. Component(Entity *owner, ComponentType type); - + /// @brief The update callback. /// @param[in] dt The time diff. /// @return true if successful. virtual bool onUpdate(Time dt) = 0; - + /// @brief The render callback. /// @param renderBackendSrv The render backend server. /// @return true if successful. diff --git a/src/Engine/App/Entity.cpp b/src/Engine/App/Entity.cpp index d91205d03..0f8b0f424 100644 --- a/src/Engine/App/Entity.cpp +++ b/src/Engine/App/Entity.cpp @@ -73,6 +73,7 @@ bool Entity::update(Time dt) { if (nullptr != mBehavior) { mBehavior->update(dt); } + for (auto &it : mComponentArray) { if (it != nullptr) { it->update(dt); @@ -146,6 +147,5 @@ void Entity::deserialize( IO::Stream *stream ) { osre_assert(stream != nullptr); } - } // Namespace App } // Namespace OSRE diff --git a/src/Engine/App/TransformComponent.cpp b/src/Engine/App/TransformComponent.cpp index 05d9189f1..0ca0f50e4 100644 --- a/src/Engine/App/TransformComponent.cpp +++ b/src/Engine/App/TransformComponent.cpp @@ -164,10 +164,6 @@ void TransformComponent::releaseChildren() { } } -void TransformComponent::update(Time dt) { - onUpdate(dt); -} - void TransformComponent::render(RenderBackendService *renderBackendSrv) { if (nullptr == renderBackendSrv) { return; diff --git a/src/Engine/App/TransformComponent.h b/src/Engine/App/TransformComponent.h index f885a4fc0..53a06a991 100644 --- a/src/Engine/App/TransformComponent.h +++ b/src/Engine/App/TransformComponent.h @@ -86,7 +86,6 @@ class OSRE_EXPORT TransformComponent : public Common::Object, public Component { virtual size_t getNumChildren() const; virtual TransformComponent *getChildAt(size_t idx) const; virtual void releaseChildren(); - virtual void update(Time dt); virtual void render(RenderBackend::RenderBackendService *renderBackendSrv); virtual void setActive(bool isActive); virtual bool isActive() const; diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index 3ed3dc0ea..9b9708c8b 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -31,6 +31,15 @@ ELSE( WIN32 ) cppcore) ENDIF( WIN32 ) +#============================================================================== +# Animation +#============================================================================== +SET(animation_src + Animation/AnimatorBase.h + Animation/AnimatorComponent.h + Animation/AnimatorComponent.cpp +) + #============================================================================== # App #============================================================================== @@ -273,13 +282,6 @@ SET ( properties_src Properties/Property.cpp ) -#============================================================================== -# Animation -#============================================================================== -SET( animation_src - Animation/AnimatorBase.h -) - #============================================================================== # RenderBackend #============================================================================== diff --git a/src/Engine/Common/osre_common.h b/src/Engine/Common/osre_common.h index dcd6339e9..29c7f8386 100644 --- a/src/Engine/Common/osre_common.h +++ b/src/Engine/Common/osre_common.h @@ -152,32 +152,41 @@ struct OsreString { ~OsreString() = default; }; -/// @brief A handle struct. +/// @brief A struct to manage a handle. struct Handle { static constexpr i32 Invalid = -1; - + i32 m_idx; + /// @brief The default class constructor. Handle() : m_idx(Invalid) { // empty } + /// @brief The class constructor with the index. + /// @param[in] idx The index. explicit Handle(i32 idx) { init(idx); } + /// @brief Inits the handle with a new index. + /// @param[in] idx The new index. void init(i32 idx) { m_idx = idx; } + /// @brief Will validate the index. + /// @return true if valid, false if not. bool isValid() const { return m_idx != Invalid; } + /// @brief Equal operator. bool operator == (const Handle &rhs) const { return m_idx == rhs.m_idx; } + /// @brief Not-equal operator. bool operator != (const Handle &rhs) const { return !(*this == rhs); }