diff --git a/CMakeLists.txt b/CMakeLists.txt index b9aecc38d0055c66f784bffdfdd730d2c7f03f93..d634a2ed8c749b184316cccc1b6e4e4f73c68d21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,6 +343,7 @@ add_subdirectory(Source/SimulationManager) add_subdirectory(Source/Constraint) add_subdirectory(Source/Materials) add_subdirectory(Source/GUIOverlay) +add_subdirectory(Source/Animation) #-------------------------------------------------------------------------- # Export Targets diff --git a/Examples/VulkanParticles/VulkanParticlesExample.cpp b/Examples/VulkanParticles/VulkanParticlesExample.cpp index 6044f17b1c5b8e97665eee72b3c527beefd3a629..9737ad1fed0cb9b574890fa0b0b21da3e137a332 100644 --- a/Examples/VulkanParticles/VulkanParticlesExample.cpp +++ b/Examples/VulkanParticles/VulkanParticlesExample.cpp @@ -20,6 +20,8 @@ =========================================================================*/ #include "imstkSimulationManager.h" +#include "imstkAnimationObject.h" +#include "imstkRenderParticles.h" #include "imstkRenderParticleEmitter.h" #include "imstkAPIUtilities.h" @@ -42,28 +44,36 @@ int main() // Smoke { + // Create sparks material auto particleMaterial = std::make_shared<RenderMaterial>(); auto particleTexture = std::make_shared<Texture> (iMSTK_DATA_ROOT "/particles/smoke_01.png", Texture::Type::DIFFUSE); particleMaterial->addTexture(particleTexture); particleMaterial->setBlendMode(RenderMaterial::BlendMode::ALPHA); - auto particleEmitter = std::make_shared<RenderParticleEmitter>(128, 2000.0f); + // Create particle geometry (for visual and animation) + auto particles = std::make_shared<RenderParticles>(128); + particles->setParticleSize(0.4f); + + // Create particle animation model + auto particleEmitter = std::make_shared<RenderParticleEmitter>(particles, 2000.0f); particleEmitter->setInitialVelocityRange(Vec3f(-1, 5, -1), Vec3f(1, 5, 1), 0.5, 1.0, -1.0, 1.0); particleEmitter->setEmitterSize(0.3f); - particleEmitter->setParticleSize(0.4f); + // Modify the first keyframe auto startKeyFrame = particleEmitter->getStartKeyFrame(); startKeyFrame->m_color = Color(1.0, 0.7, 0.0, 1.0); + // Add another keyframe RenderParticleKeyFrame midFrame0; midFrame0.m_time = 700.0f; midFrame0.m_color = Color::Red; midFrame0.m_scale = 1.5f; particleEmitter->addKeyFrame(midFrame0); + // Add another keyframe RenderParticleKeyFrame midFrame1; midFrame1.m_time = 1300.0f; midFrame1.m_color = Color::DarkGray; @@ -71,48 +81,58 @@ int main() midFrame1.m_scale = 2.0f; particleEmitter->addKeyFrame(midFrame1); + // Modify the last keyframe auto endKeyFrame = particleEmitter->getEndKeyFrame(); endKeyFrame->m_color = Color::Black; endKeyFrame->m_color.a = 0.0; endKeyFrame->m_scale = 4.0; - auto particleObject = std::make_shared<VisualObject>("Smoke"); - auto particleModel = std::make_shared<VisualModel>(particleEmitter); + // Create and add animation scene object + auto particleObject = std::make_shared<AnimationObject>("Smoke"); + auto particleModel = std::make_shared<VisualModel>(particles); particleModel->setRenderMaterial(particleMaterial); particleObject->addVisualModel(particleModel); - + particleObject->setAnimationModel(particleEmitter); scene->addSceneObject(particleObject); } // Sparks { + // Create sparks material auto particleMaterial = std::make_shared<RenderMaterial>(); auto particleTexture = std::make_shared<Texture> (iMSTK_DATA_ROOT "/particles/flare_01.png", Texture::Type::DIFFUSE); particleMaterial->addTexture(particleTexture); particleMaterial->setBlendMode(RenderMaterial::BlendMode::ALPHA); - auto particleEmitter = std::make_shared<RenderParticleEmitter>(128, + // Create particle geometry (for visual and animation) + auto particles = std::make_shared<RenderParticles>(128); + particles->setTranslation(2, 0.1, 0); + particles->setParticleSize(0.3f); + + // Create animation model + auto particleEmitter = std::make_shared<RenderParticleEmitter>(particles, 850.0f, RenderParticleEmitter::Mode::BURST); - particleEmitter->setTranslation(2, 0.1, 0); particleEmitter->setInitialVelocityRange(Vec3f(-1, 5, -1), Vec3f(1, 5, 1), 4.0, 5.0, -1.0, 1.0); particleEmitter->setEmitterSize(0.1f); - particleEmitter->setParticleSize(0.3f); + // Modifying the first keyframe auto startKeyFrame = particleEmitter->getStartKeyFrame(); startKeyFrame->m_acceleration = Vec3f(0, -9.8, 0); startKeyFrame->m_color = Color::Yellow; + // Modifying the last keyframe auto endKeyFrame = particleEmitter->getEndKeyFrame(); endKeyFrame->m_color = Color::Orange; - auto particleObject = std::make_shared<VisualObject>("Sparks"); - auto particleModel = std::make_shared<VisualModel>(particleEmitter); + // Create and add animation object + auto particleObject = std::make_shared<AnimationObject>("Sparks"); + auto particleModel = std::make_shared<VisualModel>(particles); particleModel->setRenderMaterial(particleMaterial); particleObject->addVisualModel(particleModel); - + particleObject->setAnimationModel(particleEmitter); scene->addSceneObject(particleObject); } @@ -131,9 +151,9 @@ int main() // Create a call back on key press of 'b' to trigger the sparks emitter viewer->setOnCharFunction('b', [&](InteractorStyle* c) -> bool { - auto geometry = scene->getSceneObject("Sparks")->getVisualModel(0)->getGeometry(); - auto sparks = std::static_pointer_cast<RenderParticleEmitter>(geometry); - sparks->reset(); + auto sparks = std::static_pointer_cast<AnimationObject>( + scene->getSceneObject("Sparks")); + sparks->getAnimationModel()->reset(); return false; }); diff --git a/Source/Animation/CMakeLists.txt b/Source/Animation/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b8f764a4a22e2ceeccfde0cae3a6a35b64b436f --- /dev/null +++ b/Source/Animation/CMakeLists.txt @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Create target +#----------------------------------------------------------------------------- +include(imstkAddLibrary) +imstk_add_library( Animation + DEPENDS + Core + Geometry + SceneElements + ) + +#----------------------------------------------------------------------------- +# Testing +#----------------------------------------------------------------------------- +if( iMSTK_BUILD_TESTING ) + add_subdirectory( Testing ) +endif() diff --git a/Source/Geometry/Particles/imstkRenderParticleEmitter.cpp b/Source/Animation/Particles/imstkRenderParticleEmitter.cpp similarity index 75% rename from Source/Geometry/Particles/imstkRenderParticleEmitter.cpp rename to Source/Animation/Particles/imstkRenderParticleEmitter.cpp index e080223bde50cfc0f866c151bee1f87b4484b302..52b852867486849ce1c6f614082d4b8acc587cfd 100644 --- a/Source/Geometry/Particles/imstkRenderParticleEmitter.cpp +++ b/Source/Animation/Particles/imstkRenderParticleEmitter.cpp @@ -23,20 +23,12 @@ namespace imstk { -RenderParticleEmitter::RenderParticleEmitter(unsigned int maxNumParticles /*=128*/, - float time /*= 3000*/, - RenderParticleEmitter::Mode mode /*= Mode::BURST*/) - : Geometry(Geometry::Type::RenderParticleEmitter) +RenderParticleEmitter::RenderParticleEmitter(std::shared_ptr<Geometry> geometry, + const float time /*= 3000*/, + RenderParticleEmitter::Mode mode /*= Mode::CONTINUOUS*/) + : AnimationModel(geometry) { - if (maxNumParticles <= 128) - { - m_maxNumParticles = maxNumParticles; - } - else - { - m_maxNumParticles = 128; - LOG(WARNING) << "The maximum number of decals is 128"; - } + this->setGeometry(geometry); m_time = time; m_emitTime = m_time; @@ -57,25 +49,51 @@ RenderParticleEmitter::RenderParticleEmitter(unsigned int maxNumParticles /*=128 m_keyFrames.push_back(startFrame); m_keyFrames.push_back(endFrame); - m_vertexPositions[0] = glm::vec3(0.5, 0.5, 0); - m_vertexPositions[1] = glm::vec3(0.5, -0.5, 0); - m_vertexPositions[2] = glm::vec3(-0.5, 0.5, 0); - m_vertexPositions[3] = glm::vec3(-0.5, -0.5, 0); + this->initializeParticles(); +} - m_vertexNormals[0] = glm::vec3(0.0, 0.0, 1.0); - m_vertexNormals[1] = glm::vec3(0.0, 0.0, 1.0); - m_vertexNormals[2] = glm::vec3(0.0, 0.0, 1.0); - m_vertexNormals[3] = glm::vec3(0.0, 0.0, 1.0); +void +RenderParticleEmitter::setGeometry( + std::shared_ptr<Geometry> geometry) +{ + if (geometry->getType() != Geometry::Type::RenderParticles) + { + LOG(FATAL) << "Geometry must be RenderParticles"; + return; + } - m_vertexUVs[0] = glm::vec2(1.0, 1.0); - m_vertexUVs[1] = glm::vec2(1.0, 0); - m_vertexUVs[2] = glm::vec2(0, 1.0); - m_vertexUVs[3] = glm::vec2(0, 0); + m_animationGeometry = geometry; + m_particles = &std::static_pointer_cast<RenderParticles>(m_animationGeometry)->getParticles(); +} - m_triangles[0] = glm::ivec3(1, 0, 3); - m_triangles[1] = glm::ivec3(0, 2, 3); +RenderParticleEmitter::Mode +RenderParticleEmitter::getEmitterMode() const +{ + return m_mode; +} - this->initializeParticles(); +void +RenderParticleEmitter::setEmitterSize(const float size) +{ + m_emitterSize = size; +} + +void +RenderParticleEmitter::setInitialVelocityRange(const Vec3f minDirection, + const Vec3f maxDirection, + const float minSpeed, + const float maxSpeed, + const float minRotationSpeed, + const float maxRotationSpeed) +{ + m_minDirection = minDirection; + m_maxDirection = maxDirection; + m_minDirection.normalize(); + m_maxDirection.normalize(); + m_minSpeed = minSpeed; + m_maxSpeed = maxSpeed; + m_minRotationSpeed = minRotationSpeed; + m_maxRotationSpeed = maxRotationSpeed; } bool @@ -90,27 +108,63 @@ RenderParticleEmitter::addKeyFrame(RenderParticleKeyFrame keyFrame) return true; } -RenderParticleEmitter::Mode -RenderParticleEmitter::getEmitterMode() +RenderParticleKeyFrame * +RenderParticleEmitter::getStartKeyFrame() { - return m_mode; + unsigned int index = 0; + + for (unsigned int i = 0; i < m_keyFrames.size(); i++) + { + if (m_keyFrames[i].m_time < m_keyFrames[index].m_time) + { + index = i; + } + } + + return &m_keyFrames[index]; } -void -RenderParticleEmitter::setEmitterSize(float size) +RenderParticleKeyFrame * +RenderParticleEmitter::getEndKeyFrame() { - m_emitterSize = size; + unsigned int index = 0; + + for (unsigned int i = 0; i < m_keyFrames.size(); i++) + { + if (m_keyFrames[i].m_time > m_keyFrames[index].m_time) + { + index = i; + } + } + + return &m_keyFrames[index]; +} + +std::vector<RenderParticleKeyFrame>& +RenderParticleEmitter::getKeyFrames() +{ + return m_keyFrames; } void -RenderParticleEmitter::setParticleSize(float size) +RenderParticleEmitter::reset() { - m_particleSize = size; + if (m_mode != Mode::BURST) + { + return; + } + + auto renderParticles = std::static_pointer_cast<RenderParticles>(m_geometry); + renderParticles->reset(); + + this->initializeParticles(); } void -RenderParticleEmitter::updateParticleEmitter(Vec3d cameraPosition) +RenderParticleEmitter::update() { + auto renderParticles = std::static_pointer_cast<RenderParticles>(m_geometry); + if (!m_started) { m_stopWatch.start(); @@ -121,7 +175,7 @@ RenderParticleEmitter::updateParticleEmitter(Vec3d cameraPosition) float dt = (float)(time - m_lastUpdateTime); m_lastUpdateTime = time; - for (auto&& particle : m_particles) + for (auto&& particle : (*m_particles)) { auto startKeyFrameTemp = *this->getStartKeyFrame(); auto startKeyFrame = &startKeyFrameTemp; @@ -134,7 +188,7 @@ RenderParticleEmitter::updateParticleEmitter(Vec3d cameraPosition) { particle->m_created = true; this->emitParticle(particle); - m_numParticles++; + renderParticles->incrementNumOfParticles(); } else if (particle->m_age < 0) { @@ -179,17 +233,32 @@ RenderParticleEmitter::updateParticleEmitter(Vec3d cameraPosition) particle->m_scale = (alpha * endKeyFrame->m_scale) + ((1.0f - alpha) * startKeyFrame->m_scale); - interpolateColor(particle->m_color, + this->interpolateColor(particle->m_color, endKeyFrame->m_color, startKeyFrame->m_color, alpha); } } +void +RenderParticleEmitter::initializeParticles() +{ + m_particles->clear(); + + auto particles = std::static_pointer_cast<RenderParticles>(m_animationGeometry); + + for (unsigned int i = 0; i < particles->getMaxNumParticles(); i++) + { + m_particles->push_back(std::unique_ptr<RenderParticle>(new RenderParticle())); + (*m_particles)[i]->m_age = -(i / (float)(particles->getMaxNumParticles())) * m_emitTime; + (*m_particles)[i]->m_created = false; + } +} + void RenderParticleEmitter::emitParticle(std::unique_ptr<RenderParticle>& particle) { - auto position = this->getTranslation(); + auto position = m_animationGeometry->getTranslation(); if (m_shape == Shape::CUBE) { @@ -226,9 +295,9 @@ RenderParticleEmitter::emitParticle(std::unique_ptr<RenderParticle>& particle) void RenderParticleEmitter::interpolateColor(Color& destination, - Color& sourceA, - Color& sourceB, - float alpha) + const Color& sourceA, + const Color& sourceB, + const float alpha) { destination.r = (sourceA.r * alpha) + (sourceB.r * (1.0f - alpha)); destination.g = (sourceA.g * alpha) + (sourceB.g * (1.0f - alpha)); @@ -236,103 +305,9 @@ RenderParticleEmitter::interpolateColor(Color& destination, destination.a = (sourceA.a * alpha) + (sourceB.a * (1.0f - alpha)); } -unsigned int -RenderParticleEmitter::getNumParticles() -{ - return m_numParticles; -} - -std::vector<std::unique_ptr<RenderParticle>>& -RenderParticleEmitter::getParticles() -{ - return m_particles; -} - -std::vector<RenderParticleKeyFrame>& -RenderParticleEmitter::getKeyFrames() -{ - return m_keyFrames; -} - -RenderParticleKeyFrame * -RenderParticleEmitter::getStartKeyFrame() -{ - unsigned int index = 0; - - for (unsigned int i = 0; i < m_keyFrames.size(); i++) - { - if (m_keyFrames[i].m_time < m_keyFrames[index].m_time) - { - index = i; - } - } - - return &m_keyFrames[index]; -} - -RenderParticleKeyFrame * -RenderParticleEmitter::getEndKeyFrame() -{ - unsigned int index = 0; - - for (unsigned int i = 0; i < m_keyFrames.size(); i++) - { - if (m_keyFrames[i].m_time > m_keyFrames[index].m_time) - { - index = i; - } - } - - return &m_keyFrames[index]; -} - -void -RenderParticleEmitter::setInitialVelocityRange(Vec3f minDirection, - Vec3f maxDirection, - float minSpeed, - float maxSpeed, - float minRotationSpeed, - float maxRotationSpeed) -{ - m_minDirection = minDirection; - m_maxDirection = maxDirection; - m_minDirection.normalize(); - m_maxDirection.normalize(); - m_minSpeed = minSpeed; - m_maxSpeed = maxSpeed; - m_minRotationSpeed = minRotationSpeed; - m_maxRotationSpeed = maxRotationSpeed; -} - float RenderParticleEmitter::getRandomNormalizedFloat() { return (float)std::rand() / RAND_MAX; } - -void -RenderParticleEmitter::initializeParticles() -{ - m_particles.clear(); - - for (unsigned int i = 0; i < m_maxNumParticles; i++) - { - m_particles.push_back(std::make_unique<RenderParticle>()); - m_particles[i]->m_age = -(i / (float)(m_maxNumParticles)) * m_emitTime; - m_particles[i]->m_created = false; - } -} - -void -RenderParticleEmitter::reset() -{ - if (m_mode != Mode::BURST) - { - return; - } - - m_numParticles = 0; - - this->initializeParticles(); } -} \ No newline at end of file diff --git a/Source/Geometry/Particles/imstkRenderParticleEmitter.h b/Source/Animation/Particles/imstkRenderParticleEmitter.h similarity index 61% rename from Source/Geometry/Particles/imstkRenderParticleEmitter.h rename to Source/Animation/Particles/imstkRenderParticleEmitter.h index d5a3a878f39ddf5095865e1288f366b1e83dab6a..746156b4dddadf726ce5285a5241bd53d83415bd 100644 --- a/Source/Geometry/Particles/imstkRenderParticleEmitter.h +++ b/Source/Animation/Particles/imstkRenderParticleEmitter.h @@ -1,250 +1,213 @@ -/*========================================================================= - - Library: iMSTK - - Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, - & Imaging in Medicine, Rensselaer Polytechnic Institute. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef imstkRenderParticleEmitter_h -#define imstkRenderParticleEmitter_h - -#include <vector> -#include <climits> -#include <memory> - -#include "glm/glm.hpp" - -#include "imstkGeometry.h" -#include "imstkMath.h" -#include "imstkColor.h" -#include "imstkTimer.h" - -namespace imstk -{ -struct RenderParticle -{ - Vec3f m_position = Vec3f(0, 0, 0); - Vec3f m_velocity = Vec3f(0, 0, 0); - Vec3f m_acceleration = Vec3f(0, 0, 0); - Color m_color = Color::White; - float m_age = 0; - bool m_created = false; - float m_scale = 1.0f; - float m_rotation = 0; - float m_rotationalVelocity = 0; - float m_rotationalAcceleration = 0; -}; - -struct RenderParticleKeyFrame -{ - float m_time = 0; - Color m_color = Color::White; - Vec3f m_acceleration = Vec3f(0, 0, 0); - float m_rotationalAcceleration = 0; - float m_scale = 1.0f; -}; - -/// -/// \class RenderParticleEmitter -/// -/// \brief Particle emitter -/// -class RenderParticleEmitter : public Geometry -{ -public: - /// - /// \brief Shape of emitter - /// - enum class Shape - { - CUBE - }; - - /// - /// \brief Mode of emitter - /// - enum class Mode - { - CONTINUOUS, ///< Emitter continuously releases/recycles particles - BURST ///< Emitter releases particles once until manually reset - }; - - /// - /// \brief Constructor - /// \param maxNumParticles Number of particles this emitter can produce - /// \param time Lifespan of each particle (in milliseconds) - /// \param mode Mode for emitter - /// - RenderParticleEmitter(unsigned int maxNumParticles = 128, - float time = 3000.0f, - Mode mode = Mode::CONTINUOUS); - - /// - /// \brief Add keyframe to particle emitter - /// \param keyFrame key frame to add - /// \returns True if key frame added, false if too many key frames - /// - bool addKeyFrame(RenderParticleKeyFrame keyFrame); - - /// - /// \brief Get mode of emitter - /// \returns mode Mode of emitter - /// - RenderParticleEmitter::Mode getEmitterMode(); - - /// - /// \brief Set size of emitter - /// \param size Width of emitter - /// - void setEmitterSize(float size); - - /// - /// \brief Set size of particle - /// \param size Particle size, this determines how much each keyframe - /// scales by - /// - void setParticleSize(float size); - - /// - /// \brief Update function - /// - void updateParticleEmitter(Vec3d cameraPosition); - - /// - /// \brief Emit particle - /// - void emitParticle(std::unique_ptr<RenderParticle>& particle); - - /// - /// \brief Get number of particles - /// - unsigned int getNumParticles(); - - /// - /// \brief Get particles - /// \returns particles - /// - std::vector<std::unique_ptr<RenderParticle>>& getParticles(); - - /// - /// \brief Get start and end frames - /// - RenderParticleKeyFrame * getStartKeyFrame(); - RenderParticleKeyFrame * getEndKeyFrame(); - - /// - /// \brief Get key frames - /// \returns key frames that are unsorted - /// - std::vector<RenderParticleKeyFrame>& getKeyFrames(); - - /// - /// \brief Set velocity range - /// This functions sets minimum and maximum rotation values for determining - /// the initial trajectory of the particles. The values are randomly - /// selected (according to a uniform distribution) between the min and max - /// values. If the values are the same, then the particle direction will - /// not behave randomly. - /// \param minDirection Maximum initial angle of trajectory - /// \param maxDirection Minimum initial angle of trajectory - /// \param minSpeed Minimum initial speed - /// \param maxSpeed Maximum initial speed - /// \param minRotationSpeed Minimum initial rotation speed - /// \param maxRotationSpeed Maximum initial rotation speed - /// - void setInitialVelocityRange(Vec3f minDirection, - Vec3f maxDirection, - float minSpeed, - float maxSpeed, - float minRotationSpeed, - float maxRotationSpeed); - - /// - /// \brief Get uniformly-distributed float - /// \returns float in the range of [0, 1] - /// - float getRandomNormalizedFloat(); - - /// - /// \brief Get volume - /// As these are particles, the volume is 0 - /// - double getVolume() const override { return 0; }; - - /// - /// \brief Reset the emitter - /// Only works for burst particles - /// - void reset(); - -protected: - friend class VulkanParticleRenderDelegate; - - /// - /// \brief Interpolate color - /// - void interpolateColor(Color& destination, - Color& sourceA, - Color& sourceB, - float alpha); - - /// - /// \brief Initialize particles - /// - void initializeParticles(); - - const int c_maxNumKeyFrames = 16; ///< Maximum key frames - unsigned int m_maxNumParticles = 128; ///< Maximum particles - - RenderParticleEmitter::Mode m_mode - = RenderParticleEmitter::Mode::CONTINUOUS; - RenderParticleEmitter::Shape m_shape - = RenderParticleEmitter::Shape::CUBE; - float m_emitterSize = 1.0f; - float m_particleSize = 0.1f; - - std::vector<std::unique_ptr<RenderParticle>> m_particles; ///< Particle objects - std::vector<RenderParticleKeyFrame> m_keyFrames; ///< Particle keyframes - imstk::StopWatch m_stopWatch; - glm::vec3 m_vertexPositions[4]; - glm::vec3 m_vertexNormals[4]; - glm::vec3 m_vertexTangents[4]; - glm::vec2 m_vertexUVs[4]; - glm::ivec3 m_triangles[2]; - - Vec3f m_minDirection; - Vec3f m_maxDirection; - float m_minSpeed; - float m_maxSpeed; - float m_minRotationSpeed; - float m_maxRotationSpeed; - - void applyTranslation(const Vec3d t) override {}; - void applyRotation(const Mat3d r) override {}; - void applyScaling(const double s) override {}; - virtual void updatePostTransformData() override {}; - - float m_time; ///< total time for particle system - float m_emitTime; - - unsigned int m_numParticles = 0; - double m_lastUpdateTime = 0.0; - bool m_started = false; -}; -} - -#endif \ No newline at end of file +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#ifndef imstkRenderParticleEmitter_h +#define imstkRenderParticleEmitter_h + + +#include <memory> +#include <vector> + +#include "g3log/g3log.hpp" + +#include "imstkMath.h" +#include "imstkColor.h" +#include "imstkTimer.h" +#include "imstkAnimationModel.h" +#include "imstkRenderParticles.h" + +namespace imstk +{ +/// +/// \struct RenderParticleKeyFrame +/// +/// \brief Keyframe for particle animation +/// +struct RenderParticleKeyFrame +{ + float m_time = 0; + Color m_color = Color::White; + Vec3f m_acceleration = Vec3f(0, 0, 0); + float m_rotationalAcceleration = 0; + float m_scale = 1.0f; +}; + +/// +/// \class RenderParticleEmitter +/// +/// \brief Animation method for rendering particles +/// Common use cases include smoke and fire. +/// +class RenderParticleEmitter : public AnimationModel +{ +public: + /// + /// \brief Shape of emitter + /// + enum class Shape + { + CUBE + }; + + /// + /// \brief Mode of emitter + /// + enum class Mode + { + CONTINUOUS, ///< Emitter continuously releases/recycles particles + BURST ///< Emitter releases particles once until manually reset + }; + + /// + /// \brief Constructor + /// + RenderParticleEmitter(std::shared_ptr<Geometry> geometry, + const float time = 3000.0f, + Mode mode = Mode::CONTINUOUS); + + /// + /// \brief Set animation geometry + /// \param renderParticles particles for rendering + /// + virtual void setGeometry(std::shared_ptr<Geometry> renderParticles); + + /// + /// \brief Get mode of emitter + /// \returns mode Mode of emitter + /// + RenderParticleEmitter::Mode getEmitterMode() const; + + /// + /// \brief Set size of emitter + /// \param size Width of emitter + /// + void setEmitterSize(const float size); + + /// + /// \brief Set velocity range + /// This functions sets minimum and maximum rotation values for determining + /// the initial trajectory of the particles. The values are randomly + /// selected (according to a uniform distribution) between the min and max + /// values. If the values are the same, then the particle direction will + /// not behave randomly. + /// \param minDirection Maximum initial angle of trajectory + /// \param maxDirection Minimum initial angle of trajectory + /// \param minSpeed Minimum initial speed + /// \param maxSpeed Maximum initial speed + /// \param minRotationSpeed Minimum initial rotation speed + /// \param maxRotationSpeed Maximum initial rotation speed + /// + void setInitialVelocityRange(const Vec3f minDirection, + const Vec3f maxDirection, + const float minSpeed, + const float maxSpeed, + const float minRotationSpeed, + const float maxRotationSpeed); + + /// + /// \brief Add keyframe to particle emitter + /// \param keyFrame key frame to add + /// \returns True if key frame added, false if too many key frames + /// + bool addKeyFrame(RenderParticleKeyFrame keyFrame); + + /// + /// \brief Get start and end frames + /// + RenderParticleKeyFrame * getStartKeyFrame(); + RenderParticleKeyFrame * getEndKeyFrame(); + + /// + /// \brief Get key frames + /// \returns key frames that are unsorted + /// + std::vector<RenderParticleKeyFrame>& getKeyFrames(); + + /// + /// \brief Reset the emitter + /// Only works for burst particles + /// + virtual void reset(); + + /// + /// \brief Update + /// + virtual void update(); + +protected: + friend class VulkanParticleRenderDelegate; + + /// + /// \brief Initialize particles + /// + void initializeParticles(); + + /// + /// \brief Interpolate color + /// + void interpolateColor(Color& destination, + const Color& sourceA, + const Color& sourceB, + const float alpha); + + /// + /// \brief Emit particle + /// + void emitParticle(std::unique_ptr<RenderParticle>& particle); + + /// + /// \brief Get uniformly-distributed float + /// \returns float in the range of [0, 1] + /// + float getRandomNormalizedFloat(); + + std::vector<RenderParticleKeyFrame> m_keyFrames; ///< Particle keyframes + + RenderParticleEmitter::Mode m_mode + = RenderParticleEmitter::Mode::CONTINUOUS; + RenderParticleEmitter::Shape m_shape + = RenderParticleEmitter::Shape::CUBE; + + Vec3f m_minDirection; + Vec3f m_maxDirection; + float m_minSpeed; + float m_maxSpeed; + float m_minRotationSpeed; + float m_maxRotationSpeed; + + float m_time; ///< total time for particle system + float m_emitTime; + + imstk::StopWatch m_stopWatch; + + double m_lastUpdateTime = 0.0; + bool m_started = false; + + float m_emitterSize = 1.0f; + + const int c_maxNumKeyFrames = 16; ///< Maximum key frames + + std::shared_ptr<Geometry> m_animationGeometry = nullptr; + std::vector<std::unique_ptr<RenderParticle>> * m_particles; +}; +} // imstk + +#endif // ifndef imstkRenderParticleEmitter_h diff --git a/Source/Geometry/Particles/imstkRenderParticles.cpp b/Source/Geometry/Particles/imstkRenderParticles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b3c4cede9a18ad718ff8dce0ee80090569cd238 --- /dev/null +++ b/Source/Geometry/Particles/imstkRenderParticles.cpp @@ -0,0 +1,93 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#include "imstkRenderParticles.h" + +namespace imstk +{ +RenderParticles::RenderParticles(const unsigned int maxNumParticles /*=128*/) + : Geometry(Geometry::Type::RenderParticles) +{ + if (maxNumParticles <= 128) + { + m_maxNumParticles = maxNumParticles; + } + else + { + m_maxNumParticles = 128; + LOG(WARNING) << "The maximum number of decals is 128"; + } + + m_vertexPositions[0] = glm::vec3(0.5, 0.5, 0); + m_vertexPositions[1] = glm::vec3(0.5, -0.5, 0); + m_vertexPositions[2] = glm::vec3(-0.5, 0.5, 0); + m_vertexPositions[3] = glm::vec3(-0.5, -0.5, 0); + + m_vertexNormals[0] = glm::vec3(0.0, 0.0, 1.0); + m_vertexNormals[1] = glm::vec3(0.0, 0.0, 1.0); + m_vertexNormals[2] = glm::vec3(0.0, 0.0, 1.0); + m_vertexNormals[3] = glm::vec3(0.0, 0.0, 1.0); + + m_vertexUVs[0] = glm::vec2(1.0, 1.0); + m_vertexUVs[1] = glm::vec2(1.0, 0); + m_vertexUVs[2] = glm::vec2(0, 1.0); + m_vertexUVs[3] = glm::vec2(0, 0); + + m_triangles[0] = glm::ivec3(1, 0, 3); + m_triangles[1] = glm::ivec3(0, 2, 3); +} + +void +RenderParticles::setParticleSize(const float size) +{ + m_particleSize = size; +} + +std::vector<std::unique_ptr<RenderParticle>>& +RenderParticles::getParticles() +{ + return m_particles; +} + +void +RenderParticles::reset() +{ + m_numParticles = 0; +} + +void +RenderParticles::incrementNumOfParticles() +{ + m_numParticles++; +} + +unsigned int +RenderParticles::getNumParticles() +{ + return m_numParticles; +} + +unsigned int +RenderParticles::getMaxNumParticles() +{ + return m_maxNumParticles; +} +} \ No newline at end of file diff --git a/Source/Geometry/Particles/imstkRenderParticles.h b/Source/Geometry/Particles/imstkRenderParticles.h new file mode 100644 index 0000000000000000000000000000000000000000..4cc55443abacbb9148c855ec6f4890e2a58a854b --- /dev/null +++ b/Source/Geometry/Particles/imstkRenderParticles.h @@ -0,0 +1,136 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#ifndef imstkRenderParticles_h +#define imstkRenderParticles_h + +#include <vector> +#include <climits> +#include <memory> + +#include "glm/glm.hpp" + +#include "imstkGeometry.h" +#include "imstkMath.h" +#include "imstkColor.h" +#include "imstkTimer.h" + +namespace imstk +{ +/// +/// \struct RenderParticle +/// +/// \brief Particle data +/// +struct RenderParticle +{ + Vec3f m_position = Vec3f(0, 0, 0); + Vec3f m_velocity = Vec3f(0, 0, 0); + Vec3f m_acceleration = Vec3f(0, 0, 0); + Color m_color = Color::White; + float m_age = 0; + bool m_created = false; + float m_scale = 1.0f; + float m_rotation = 0; + float m_rotationalVelocity = 0; + float m_rotationalAcceleration = 0; +}; + +/// +/// \class RenderParticles +/// +/// \brief Particles for rendering +/// +class RenderParticles : public Geometry +{ +public: + + /// + /// \brief Constructor + /// \param maxNumParticles Number of particles this emitter can produce + /// \param time Lifespan of each particle (in milliseconds) + /// \param mode Mode for emitter + /// + RenderParticles(const unsigned int maxNumParticles = 128); + + /// + /// \brief Set size of particle + /// \param size Particle size, this determines how much each keyframe + /// scales by + /// + void setParticleSize(const float size); + + /// + /// \brief Get particles + /// \returns particles + /// + std::vector<std::unique_ptr<RenderParticle>>& getParticles(); + + /// + /// \brief Reset number of particles + /// + void reset(); + + /// + /// \brief Increment number of particles + /// + void incrementNumOfParticles(); + + /// + /// \brief Get number of particles + /// + unsigned int getNumParticles(); + + /// + /// \brief Get maximum number of particles + /// + unsigned int getMaxNumParticles(); + + /// + /// \brief Get volume + /// As these are particles, the volume is 0 + /// + double getVolume() const override { return 0; }; + +protected: + friend class VulkanParticleRenderDelegate; + friend class RenderParticles; + + unsigned int m_maxNumParticles = 128; ///< Maximum particles + float m_particleSize = 0.1f; + + std::vector<std::unique_ptr<RenderParticle>> m_particles; ///< Particle objects + glm::vec3 m_vertexPositions[4]; + glm::vec3 m_vertexNormals[4]; + glm::vec3 m_vertexTangents[4]; + glm::vec2 m_vertexUVs[4]; + glm::ivec3 m_triangles[2]; + + unsigned int m_numParticles = 0; + + void applyTranslation(const Vec3d t) override {}; + void applyRotation(const Mat3d r) override {}; + void applyScaling(const double s) override {}; + virtual void updatePostTransformData() override {}; +}; +} + +#endif \ No newline at end of file diff --git a/Source/Geometry/imstkGeometry.h b/Source/Geometry/imstkGeometry.h index 32f397f6c6da4bcb635bd37d9277ce000b01da78..978a7ca3b8995c69a99847e9cbafe7529ea0abf1 100644 --- a/Source/Geometry/imstkGeometry.h +++ b/Source/Geometry/imstkGeometry.h @@ -54,7 +54,7 @@ public: Capsule, Decal, DecalPool, - RenderParticleEmitter + RenderParticles }; /// diff --git a/Source/Rendering/CMakeLists.txt b/Source/Rendering/CMakeLists.txt index b45833cb13cc38039c5ccc72692cc3bd7afb3dda..afb083e2e9d3628e7ee4a6ea033edb69ee6099c6 100644 --- a/Source/Rendering/CMakeLists.txt +++ b/Source/Rendering/CMakeLists.txt @@ -123,6 +123,7 @@ imstk_add_library( Rendering ${VTK_LIBRARIES} ${RENDERING_DEPENDENCIES} Scene + Animation glm #VERBOSE ) diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.cpp b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.cpp index 2332acb712d09774ed53572425026c73f928afaa..0ed4c5e8739ad05df2089bea70260022119679b2 100644 --- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.cpp +++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.cpp @@ -29,7 +29,7 @@ VulkanParticleRenderDelegate::VulkanParticleRenderDelegate(std::shared_ptr<Visua { this->initialize(visualModel); - auto geometry = std::static_pointer_cast<RenderParticleEmitter>(visualModel->getGeometry()); + auto geometry = std::static_pointer_cast<RenderParticles>(visualModel->getGeometry()); m_numVertices = 4; m_numTriangles = 2; @@ -49,7 +49,7 @@ void VulkanParticleRenderDelegate::updateVertexBuffer() { auto vertices = (VulkanBasicVertex *)m_vertexBuffer->getVertexMemory(); - auto geometry = std::static_pointer_cast<RenderParticleEmitter>(m_visualModel->getGeometry()); + auto geometry = std::static_pointer_cast<RenderParticles>(m_visualModel->getGeometry()); for (unsigned i = 0; i < m_numVertices; i++) { @@ -87,9 +87,7 @@ VulkanParticleRenderDelegate::update(const uint32_t frameIndex, std::shared_ptr< { unsigned int index = 0; - auto geometry = std::static_pointer_cast<RenderParticleEmitter>(m_visualModel->getGeometry()); - - geometry->updateParticleEmitter(camera->getPosition()); + auto particles = std::static_pointer_cast<RenderParticles>(m_visualModel->getGeometry()); auto mat = this->getVisualModel()->getRenderMaterial(); auto cameraPosition = glm::vec3(camera->getPosition()[0], @@ -101,9 +99,9 @@ VulkanParticleRenderDelegate::update(const uint32_t frameIndex, std::shared_ptr< auto matColor = mat->getColor(); - this->sortParticles(geometry->getParticles(), geometry->getNumParticles(), cameraPosition); + this->sortParticles(particles->getParticles(), particles->getNumParticles(), cameraPosition); - for (unsigned int i = 0; i < geometry->getNumParticles(); i++) + for (unsigned int i = 0; i < particles->getNumParticles(); i++) { auto particlePosition = glm::vec3(m_particles[i]->m_position[0], m_particles[i]->m_position[1], @@ -117,7 +115,7 @@ VulkanParticleRenderDelegate::update(const uint32_t frameIndex, std::shared_ptr< transformation = transformation * billboardTransformation; transformation = glm::rotate(transformation, m_particles[i]->m_rotation, glm::vec3(0, 0, 1.0f)); transformation = glm::scale(transformation, - glm::vec3(geometry->m_particleSize) * m_particles[i]->m_scale); + glm::vec3(particles->m_particleSize) * m_particles[i]->m_scale); m_particleVertexUniforms.transform[i] = transformation; m_particleFragmentUniforms.receivesShadows[i] = mat->getReceivesShadows() ? 1 : 0; diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.h b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.h index 13710c300e1c9e0d76fadfa73e87c885ff6444e8..ed5e7b30b717ce2e0fcd26eb95c1f4b3d714791b 100644 --- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.h +++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanParticleRenderDelegate.h @@ -28,6 +28,11 @@ namespace imstk { +/// +/// \class VulkanParticleRenderDelegate +/// +/// \brief Billboard render delegate for RenderParticles +/// class VulkanParticleRenderDelegate : public VulkanRenderDelegate { public: diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp index 8ecbd70e1f9dd6ba73e40c60b346e308b4796b1a..9c8795eb2b267f3eb2a45f39d19dbd9337c685d0 100644 --- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp +++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp @@ -101,7 +101,7 @@ VulkanRenderDelegate::make_delegate(std::shared_ptr<VisualModel> visualModel, { return std::make_shared<VulkanDecalRenderDelegate>(visualModel, type, memoryManager); } - case Geometry::Type::RenderParticleEmitter: + case Geometry::Type::RenderParticles: { return std::make_shared<VulkanParticleRenderDelegate>(visualModel, type, memoryManager); } diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp index 1901cbb3dea2ee5227f18213f2990543fe14e8ba..6dc7e90662fba3f13b09a1fabcad5448b7f690f2 100644 --- a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp +++ b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp @@ -659,6 +659,15 @@ VulkanRenderer::renderFrame() this->loadAllVisualModels(); + for (auto sceneObject : m_scene->getSceneObjects()) + { + if (sceneObject->getType() == SceneObject::Type::Animation) + { + auto animatedObject = std::static_pointer_cast<AnimationObject>(sceneObject); + animatedObject->getAnimationModel()->update(); + } + } + // Update global uniforms this->updateGlobalUniforms(nextImageIndex); @@ -670,7 +679,7 @@ VulkanRenderer::renderFrame() auto decalPool = std::dynamic_pointer_cast<VulkanDecalRenderDelegate>(m_renderDelegates[renderDelegateIndex]); decalPool->update(nextImageIndex, m_scene->getCamera()); } - else if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticleEmitter) + else if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticles) { auto particleEmitter = std::dynamic_pointer_cast<VulkanParticleRenderDelegate>(m_renderDelegates[renderDelegateIndex]); particleEmitter->update(nextImageIndex, m_scene->getCamera()); @@ -746,7 +755,7 @@ VulkanRenderer::renderFrame() auto material = m_renderDelegates[renderDelegateIndex]->m_shadowMaterial; if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::DecalPool - || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticleEmitter + || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticles || !m_renderDelegates[renderDelegateIndex]->getVisualModel()->getRenderMaterial()->getCastsShadows() || !m_renderDelegates[renderDelegateIndex]->getVisualModel()->isVisible()) { @@ -787,7 +796,7 @@ VulkanRenderer::renderFrame() for (unsigned int renderDelegateIndex = 0; renderDelegateIndex < m_renderDelegates.size(); renderDelegateIndex++) { if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::DecalPool - || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticleEmitter + || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticles || !m_renderDelegates[renderDelegateIndex]->getVisualModel()->isVisible()) { continue; @@ -866,7 +875,7 @@ VulkanRenderer::renderFrame() for (unsigned int renderDelegateIndex = 0; renderDelegateIndex < m_renderDelegates.size(); renderDelegateIndex++) { if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::DecalPool - || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticleEmitter + || m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() == Geometry::Type::RenderParticles || !m_renderDelegates[renderDelegateIndex]->getVisualModel()->isVisible()) { continue; @@ -938,13 +947,13 @@ VulkanRenderer::renderFrame() for (unsigned int renderDelegateIndex = 0; renderDelegateIndex < m_renderDelegates.size(); renderDelegateIndex++) { - if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() != Geometry::Type::RenderParticleEmitter + if (m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()->getType() != Geometry::Type::RenderParticles || !m_renderDelegates[renderDelegateIndex]->getVisualModel()->isVisible()) { continue; } - auto geometry = std::dynamic_pointer_cast<RenderParticleEmitter>(m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()); + auto geometry = std::dynamic_pointer_cast<RenderParticles>(m_renderDelegates[renderDelegateIndex]->getVisualModel()->getGeometry()); auto material = m_renderDelegates[renderDelegateIndex]->m_material; vkCmdBindPipeline(m_renderCommandBuffer[nextImageIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, material->m_pipeline); this->setCommandBufferState(&m_renderCommandBuffer[nextImageIndex], m_width, m_height); diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.h b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.h index 15e2c2d0869adbad2df7b64d2846735de80edc54..b9af56bbac8780bc1f3e6baa7e483bd56d9c3b33 100644 --- a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.h +++ b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.h @@ -41,6 +41,7 @@ #include "imstkDecalPool.h" #include "imstkRenderParticleEmitter.h" #include "imstkTextureManager.h" +#include "imstkAnimationObject.h" #include "imstkVulkanValidation.h" #include "imstkVulkanVertexBuffer.h" diff --git a/Source/SceneElements/Objects/imstkAnimationModel.cpp b/Source/SceneElements/Objects/imstkAnimationModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b61db821ed7fac8c5c447f609daf14ce3125905 --- /dev/null +++ b/Source/SceneElements/Objects/imstkAnimationModel.cpp @@ -0,0 +1,42 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#include "imstkAnimationModel.h" + +namespace imstk +{ +AnimationModel::AnimationModel(std::shared_ptr<Geometry> geometry) +{ + m_geometry = geometry; +} + +std::shared_ptr<Geometry> +AnimationModel::getGeometry() +{ + return m_geometry; +} + +void +AnimationModel::setGeometry(std::shared_ptr<Geometry> geometry) +{ + m_geometry = geometry; +} +} \ No newline at end of file diff --git a/Source/SceneElements/Objects/imstkAnimationModel.h b/Source/SceneElements/Objects/imstkAnimationModel.h new file mode 100644 index 0000000000000000000000000000000000000000..188f4ea4fa3b0474c41817c78e7654dc7cbfbedc --- /dev/null +++ b/Source/SceneElements/Objects/imstkAnimationModel.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#ifndef imstkAnimationModel_h +#define imstkAnimationModel_h + +#include <memory> + +#include "imstkGeometry.h" + +namespace imstk +{ +/// +/// \class AnimationModel +/// +/// \brief Contains geometric and animation render information +/// +class AnimationModel +{ +public: + /// + /// \brief Constructor + /// + AnimationModel(std::shared_ptr<Geometry> geometry); + + AnimationModel() = delete; + + /// + /// \brief Get/set geometry + /// + std::shared_ptr<Geometry> getGeometry(); + virtual void setGeometry(std::shared_ptr<Geometry> geometry); + + /// + /// \brief Update animation + /// + virtual void update() {}; + + /// + /// \brief Reset animation + /// + virtual void reset() {}; + +protected: + friend class VulkanRenderer; + friend class VTKRenderer; + + std::shared_ptr<Geometry> m_geometry = nullptr; +}; +} // imstk + +#endif // ifndef imstkAnimationModel_h \ No newline at end of file diff --git a/Source/SceneElements/Objects/imstkAnimationObject.cpp b/Source/SceneElements/Objects/imstkAnimationObject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6c408129c89a7cdc7b3d6873bb33d7ab4564e72 --- /dev/null +++ b/Source/SceneElements/Objects/imstkAnimationObject.cpp @@ -0,0 +1,37 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#include "imstkAnimationObject.h" + +namespace imstk +{ +std::shared_ptr<AnimationModel> +AnimationObject::getAnimationModel() const +{ + return m_animationModel; +} + +void +AnimationObject::setAnimationModel(std::shared_ptr<AnimationModel> model) +{ + m_animationModel = model; +} +} // imstk diff --git a/Source/SceneElements/Objects/imstkAnimationObject.h b/Source/SceneElements/Objects/imstkAnimationObject.h new file mode 100644 index 0000000000000000000000000000000000000000..ee77ccaddab0f6a3227de4fa6950e972daa69467 --- /dev/null +++ b/Source/SceneElements/Objects/imstkAnimationObject.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#ifndef imstkAnimationObject_h +#define imstkAnimationObject_h + +#include <memory> + +#include "imstkSceneObject.h" +#include "imstkGeometryMap.h" +#include "imstkAnimationModel.h" +#include "imstkMath.h" + +namespace imstk +{ +class Geometry; + +class AnimationObject : public SceneObject +{ +public: + /// + /// \brief Constructor + /// + AnimationObject(const std::string& name) : SceneObject(name) + { + m_type = Type::Animation; + } + + /// + /// \brief Constructor + /// + AnimationObject(std::string&& name) : SceneObject(std::move(name)) + { + m_type = Type::Animation; + } + + /// + /// \brief Default destructor + /// + virtual ~AnimationObject() = default; + + /// + /// \brief Set/get animation model + /// + std::shared_ptr<AnimationModel> getAnimationModel() const; + void setAnimationModel(std::shared_ptr<AnimationModel> model); + + /// + /// \brief Initialize the scene object + /// + virtual bool initialize() + { + if (SceneObject::initialize()) + { + return true; + } + else + { + return false; + } + } + +protected: + std::shared_ptr<AnimationModel> m_animationModel; +}; +} // imstk + +#endif // ifndef imstkAnimationObject_h diff --git a/Source/SceneElements/Objects/imstkSceneObject.h b/Source/SceneElements/Objects/imstkSceneObject.h index 0456eb2f0089412c55b60f48a7c4333e60a1337b..35532d248b318d03000eb030e94345ef217effc3 100644 --- a/Source/SceneElements/Objects/imstkSceneObject.h +++ b/Source/SceneElements/Objects/imstkSceneObject.h @@ -44,6 +44,7 @@ public: enum class Type { Visual, + Animation, Colliding, Rigid, FEMDeformable,