Commit fe4fdef0 authored by Sreekanth Arikatla's avatar Sreekanth Arikatla

Merge branch 'particleSystem' into 'master'

ENH: Render Particle System

See merge request !279
parents 226892e9 d79f3c70
Pipeline #129801 passed with stage
in 0 seconds
......@@ -19,6 +19,8 @@ function(CopyAndCompileShaders)
compileShaders(Mesh/mesh_frag.frag Mesh/mesh_frag.spv)
compileShaders(Mesh/decal_vert.vert Mesh/decal_vert.spv)
compileShaders(Mesh/decal_frag.frag Mesh/decal_frag.spv)
compileShaders(Mesh/particle_vert.vert Mesh/particle_vert.spv)
compileShaders(Mesh/particle_frag.frag Mesh/particle_frag.spv)
compileShaders(Mesh/shadow_vert.vert Mesh/shadow_vert.spv)
compileShaders(Mesh/shadow_frag.frag Mesh/shadow_frag.spv)
compileShaders(Mesh/depth_frag.frag Mesh/depth_frag.spv)
......
......@@ -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
......
02b526d12222a723a9dba86fbeeabf7aa66e06f5730b043f48c1ca9b96ec509b50c89aab4c458fbd198c96d5f2cef210b207ac071f180f95cc6ae2566f5af018
eb6f17318fba433631f53429a6b0b4281d577026a2ea44365fc78b10ff5487b969022b77e02ea35e1c85d9dec8cf4aadbcf555322aa924115137f10e71e4b15c
b8219a7352a2ab446b41389484153aed669ef12a0a82e2231d9ea51f42acb5d6ec1c880a5708a8be1b4386da69fc69f511e1c347a454dd430f8dfde226c5d6fe
###########################################################################
#
# Copyright (c) Kitware, Inc.
#
# 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.
#
###########################################################################
if(iMSTK_USE_Vulkan)
project(Example-VulkanParticles)
#-----------------------------------------------------------------------------
# Create executable
#-----------------------------------------------------------------------------
add_executable(${PROJECT_NAME} VulkanParticlesExample.cpp)
#-----------------------------------------------------------------------------
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME} SimulationManager)
#-----------------------------------------------------------------------------
# Add shaders
#-----------------------------------------------------------------------------
include(imstkCopyAndCompileShaders)
CopyAndCompileShaders()
#-----------------------------------------------------------------------------
# Associate external data
#-----------------------------------------------------------------------------
list(APPEND FILE_LIST
particles/,REGEX:.*)
imstk_add_data(${PROJECT_NAME} ${FILE_LIST})
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.
=========================================================================*/
#include "imstkSimulationManager.h"
#include "imstkAnimationObject.h"
#include "imstkRenderParticles.h"
#include "imstkRenderParticleEmitter.h"
#include "imstkAPIUtilities.h"
using namespace imstk;
///
/// \brief This example demonstrates particle rendering feature.
/// NOTE: Requires enabling Vulkan rendering backend
///
int main()
{
// SDK and Scene
auto sdk = std::make_shared<SimulationManager>();
auto scene = sdk->createNewScene("RenderParticles");
// Position camera
auto cam = scene->getCamera();
cam->setPosition(0, 3, 6);
cam->setFocalPoint(0, 0, 0);
// 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);
// 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);
// 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;
midFrame1.m_color.a = 0.7f;
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;
// 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);
// 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->setInitialVelocityRange(Vec3f(-1, 5, -1), Vec3f(1, 5, 1),
4.0, 5.0,
-1.0, 1.0);
particleEmitter->setEmitterSize(0.1f);
// 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;
// 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);
}
// Plane
auto plane = apiutils::createVisualAnalyticalSceneObject(Geometry::Type::Plane, scene, "plane", 10);
plane->getVisualModel(0)->getRenderMaterial()->setColor(Color::Black);
// Light
auto light = std::make_shared<DirectionalLight>("Light");
light->setIntensity(7);
light->setColor(Color(1.0, 0.95, 0.8));
light->setFocalPoint(Vec3d(-1, -1, 0));
scene->addLight(light);
auto viewer = sdk->getViewer();
// Create a call back on key press of 'b' to trigger the sparks emitter
viewer->setOnCharFunction('b', [&](InteractorStyle* c) -> bool
{
auto sparks = std::static_pointer_cast<AnimationObject>(
scene->getSceneObject("Sparks"));
sparks->getAnimationModel()->reset();
return false;
});
// Run
sdk->setActiveScene(scene);
sdk->startSimulation(SimulationStatus::PAUSED);
return 0;
}
#-----------------------------------------------------------------------------
# Create target
#-----------------------------------------------------------------------------
include(imstkAddLibrary)
imstk_add_library( Animation
DEPENDS
Core
Geometry
SceneElements
)
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if( iMSTK_BUILD_TESTING )
add_subdirectory( Testing )
endif()
This diff is collapsed.
/*=========================================================================
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
......@@ -33,7 +33,7 @@ DecalPool::DecalPool(unsigned int maxNumDecals /*= 128*/)
else
{
m_maxNumDecals = 128;
LOG(WARNING) << "The maximum number of decals is 256";
LOG(WARNING) << "The maximum number of decals is 128";
}
m_vertexPositions[0] = glm::vec3(0.5, 0.5, 0.5);
......
/*=========================================================================
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
/*=========================================================================
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;