diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 254d18bcb255b8cbf9c0f8df8ab59acf59358d67..d8649d55f25aacf52bc2cbc2f68205c8feb0dc87 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -16,6 +16,7 @@ simmedtk_add_library(Core IOStream.cpp Light.cpp Module.cpp + Model.cpp ObjectSimulator.cpp RenderDetail.cpp Scene.cpp @@ -47,6 +48,7 @@ simmedtk_add_library(Core Light.h MemoryBlock.h Module.h + Model.h ObjectSimulator.h Scene.h SceneObject.h diff --git a/Core/Config.h b/Core/Config.h index 43567b1296f96f5c2671e90efa52c6528f3bcbd9..cdca824a8a8c024547b1cb121c345df4391a7b58 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -60,7 +60,6 @@ enum MaxShaderVariableName = 255 }; - /// \brief class types. Each class should have type of itself enum class ClassType { diff --git a/Core/Geometry.h b/Core/Geometry.h index afec193e1ec6d29c211002020a21999b428bf958..429c793205beb09b86d46233a5b4e69f863c9697 100644 --- a/Core/Geometry.h +++ b/Core/Geometry.h @@ -51,6 +51,11 @@ public: this->renderDelegate->draw(); } + /// \brief Get render delegate + std::shared_ptr<RenderDelegate> getRenderDelegate() const + { + return this->renderDelegate; + } RenderDelegate::Ptr renderDelegate; }; @@ -71,8 +76,8 @@ public: Plane() { this->setRenderDelegate( - Factory<RenderDelegate>::createSubclass( - "RenderDelegate", "PlaneRenderDelegate")); + Factory<RenderDelegate>::createSubclassForGroup( + "RenderDelegate", RenderDelegate::RendererType::VTK)); } ~Plane(){} diff --git a/Core/Model.cpp b/Core/Model.cpp index 6531d7971d02a05236d25efc22f3ceeab64e4f7f..4aae9a13b109033c748eec3a5d7034b17c8bccdc 100644 --- a/Core/Model.cpp +++ b/Core/Model.cpp @@ -23,14 +23,28 @@ #include "Core/Model.h" -Model::Model() -{ +Model::Model() {} +Model::~Model() {} +std::shared_ptr< Core::BaseMesh > Model::getMesh() +{ + return nullptr; } - -Model::~Model() +std::shared_ptr< CoreClass > Model::getObject() { + return nullptr; +} +void Model::draw() {} +std::shared_ptr< RenderDelegate > Model::getRenderDelegate() const +{ + return this->renderDelegate; +} +void Model::setRenderDelegate(RenderDelegate::Ptr delegate) +{ + this->renderDelegate = delegate; + if(delegate) + { + this->renderDelegate->setSourceGeometry(this); + } } -Model::Model() {} -Model::~Model() {} diff --git a/Core/Model.h b/Core/Model.h index e682ec8ef7531a5c659dde90233ca9b351fe3fe8..89e21fc37d6e615eff61ccc31ddea5dd834565f6 100644 --- a/Core/Model.h +++ b/Core/Model.h @@ -29,6 +29,7 @@ // SimMedTK includes #include "Core/CoreClass.h" +#include "Core/RenderDelegate.h" namespace Core { class BaseMesh; @@ -38,12 +39,20 @@ class CoreClass; class Model { public: - Model(){} - ~Model(){} + Model(); + ~Model(); - virtual std::shared_ptr<Core::BaseMesh> getMesh(){ return nullptr; } - virtual std::shared_ptr<CoreClass> getObject(){ return nullptr; } - virtual void draw(){} + virtual std::shared_ptr<Core::BaseMesh> getMesh(); + virtual std::shared_ptr<CoreClass> getObject(); + virtual void draw(); + + virtual void setRenderDelegate(RenderDelegate::Ptr delegate); + + /// \brief Get render delegate + RenderDelegate::Ptr getRenderDelegate() const; + +private: + RenderDelegate::Ptr renderDelegate; }; #endif // SMMODEL diff --git a/Core/RenderDelegate.h b/Core/RenderDelegate.h index d1508fb33a7f18c810d285cee20ca3f450983d29..9f43316a323b258c550739a092fc963e59ac9798 100644 --- a/Core/RenderDelegate.h +++ b/Core/RenderDelegate.h @@ -8,12 +8,21 @@ class RenderDelegate { public: + + enum RendererType + { + VTK = 300, + Other = 400 + }; + typedef std::shared_ptr<RenderDelegate> Ptr; virtual void initDraw() { } virtual void draw() const { } + virtual void modified() + { } virtual bool isTargetTextured() const { diff --git a/Core/RenderDetail.h b/Core/RenderDetail.h index 4c584d928a55ef7cae4bd448fe12a868181ab35a..156244840538f83b958345485a34765c5830a612 100644 --- a/Core/RenderDetail.h +++ b/Core/RenderDetail.h @@ -25,12 +25,14 @@ class VisualArtifact; class CoreClass; +class Model; struct UnifiedId; ///\brief Hold a pointer to a source of geometry that render details can use for drawing. struct GeometrySource { CoreClass* sceneObject; VisualArtifact* analyticObject; + Model *model; GeometrySource() : sceneObject(nullptr), analyticObject(nullptr) @@ -39,12 +41,20 @@ struct GeometrySource { { this->sceneObject = src; this->analyticObject = nullptr; + this->model = nullptr; } void setSource(VisualArtifact* src) { this->sceneObject = nullptr; + this->model = nullptr; this->analyticObject = src; } + void setSource(Model* src) + { + this->sceneObject = nullptr; + this->model = src; + this->analyticObject = nullptr; + } template<typename T> T* sourceAs() const { @@ -57,6 +67,10 @@ struct GeometrySource { { return result; } + if ((result = dynamic_cast<T*>(model))) + { + return result; + } return nullptr; } }; diff --git a/Core/SDK.cpp b/Core/SDK.cpp index 91d1e18502f42657dd745d4f2be0c28328c713f5..82f46213e4556c58b598bfee8d9e9f87b332ef6c 100644 --- a/Core/SDK.cpp +++ b/Core/SDK.cpp @@ -23,6 +23,7 @@ #include "Core/SDK.h" #include "Core/Factory.h" +#include "Core/RenderDelegate.h" #include <chrono> #include <thread> @@ -67,12 +68,16 @@ void SDK::releaseScene(std::shared_ptr<Scene> scene) std::shared_ptr<ViewerBase> SDK::createViewer() { - this->viewer = Factory<CoreClass>::createSubclassForGroupAs<ViewerBase>("ViewerBase",300); + this->viewer = Factory<CoreClass>::createSubclassForGroupAs<ViewerBase>("ViewerBase",RenderDelegate::VTK); if (this->viewer) - { - this->viewer->log = this->errorLog; - this->registerModule(this->viewer); - } + { + this->viewer->log = this->errorLog; + this->registerModule(this->viewer); + } + else + { + std::cerr << "Error: Unable to create viewer." << std::endl; + } return this->viewer; } @@ -86,9 +91,9 @@ void SDK::addViewer(std::shared_ptr<ViewerBase> p_viewer) this->registerModule(p_viewer); } +/// /// \brief Returns a pointer to the viewer object /// -/// \return Returns a pointer to the viewer object std::shared_ptr<ViewerBase> SDK::getViewerInstance() { return this->viewer; @@ -173,20 +178,20 @@ void SDK::run() this->viewer->exec(); - // Now wait for other modules to shut down - while (!shutdown) - { - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - // Tell framework threads to shutdown - terminateAll(); - - // Wait for all threads to finish processing - for (auto &module : modules) - { - module.join(); - } +// // Now wait for other modules to shut down +// while (!shutdown) +// { +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } +// +// // Tell framework threads to shutdown +// terminateAll(); +// +// // Wait for all threads to finish processing +// for (auto &module : modules) +// { +// module.join(); +// } } /// \brief diff --git a/Core/StaticSceneObject.cpp b/Core/StaticSceneObject.cpp index 7f2f1dbee9f990e0c03b4543adf9ec60cd4fdaad..7d6bbbbc8996ea3b252306d170bd9c8cabf9f8a0 100644 --- a/Core/StaticSceneObject.cpp +++ b/Core/StaticSceneObject.cpp @@ -23,6 +23,7 @@ #include "Core/StaticSceneObject.h" #include "Core/Factory.h" +#include "RenderDelegate.h" StaticSceneObject::StaticSceneObject(std::shared_ptr<ErrorLog> /*p_log*/) : SceneObject() { @@ -31,8 +32,8 @@ StaticSceneObject::StaticSceneObject(std::shared_ptr<ErrorLog> /*p_log*/) : Scen name = "Static_SceneObject_" + std::to_string(this->getUniqueId()->getId()); this->setRenderDelegate( - Factory<RenderDelegate>::createSubclass( - "RenderDelegate","StaticSceneObjectRenderDelegate")); + Factory<RenderDelegate>::createConcreteClassForGroup( + "StaticSceneObjectRenderDelegate",RenderDelegate::RendererType::VTK)); } StaticSceneObject::~StaticSceneObject() diff --git a/Examples/vegaFem/CMakeLists.txt b/Examples/vegaFem/CMakeLists.txt index 3f1987071c67f9493d2a0dd26c2b252622f5c12c..dbe075df585fa0cccd6619532e3e019408418fca 100644 --- a/Examples/vegaFem/CMakeLists.txt +++ b/Examples/vegaFem/CMakeLists.txt @@ -2,6 +2,7 @@ add_executable(vegaFemExample main.cpp) target_link_libraries(vegaFemExample Core + VtkRendering Rendering RenderDelegates Simulators diff --git a/Examples/vegaFem/main.cpp b/Examples/vegaFem/main.cpp index 37dac84c70226cf7a170e79356db8e0eaec9361b..851c6aa26f068519fad6729ea5bf27538263cfe1 100644 --- a/Examples/vegaFem/main.cpp +++ b/Examples/vegaFem/main.cpp @@ -21,6 +21,8 @@ // Contact: //--------------------------------------------------------------------------- +#include <memory> + // Core SimMedTK includes #include "Core/Config.h" #include "Core/ErrorLog.h" @@ -92,18 +94,14 @@ int main() auto femObjRenderDetail = std::make_shared<RenderDetail>(//SIMMEDTK_RENDER_WIREFRAME //| SIMMEDTK_RENDER_VERTICES - SIMMEDTK_RENDER_FACES + SIMMEDTK_RENDER_FACES | SIMMEDTK_RENDER_NORMALS ); femObjRenderDetail->setPointSize(4.0); Color maroon(165.0f / 255, 42.0f / 255, 42.0f / 255, 1.0); femObjRenderDetail->setVertexColor(maroon); femObjRenderDetail->setNormalLength(0.02); - femObject->getVolumetricMesh()->setRenderDetail(0,femObjRenderDetail); - - /*hapticCtl = std::make_shared<mstk::Examples::Common::hapticController>(); - hapticCtl->setVegaFemSceneObject(femObject); - femSimulator->attachEvent(core::Haptic, hapticCtl);*/ + femObject->getVolumetricMesh()->getRenderingMesh()->setRenderDetail(femObjRenderDetail); sdk->addSceneActor(femObject, femSimulator); diff --git a/Geometry/MeshModel.cpp b/Geometry/MeshModel.cpp index e733a29e4f7ef15081244d00ab384c8077b990db..e1b028b47308aae47b93b1013aa4a6a919fba1d5 100644 --- a/Geometry/MeshModel.cpp +++ b/Geometry/MeshModel.cpp @@ -26,7 +26,12 @@ #include "IO/IOMesh.h" #include "Core/RenderDelegate.h" -MeshModel::MeshModel() {} +MeshModel::MeshModel() +{ + this->setRenderDelegate( + Factory<RenderDelegate>::createConcreteClassForGroup( + "MeshRenderDelegate",RenderDelegate::RendererType::VTK)); +} MeshModel::~MeshModel() {} void MeshModel::load(const std::string& meshName) { diff --git a/Geometry/PlaneModel.cpp b/Geometry/PlaneModel.cpp index 5fa0887de16467129c4674112385fd25d4edbc8f..87309d1c55393ede0e4efe2fc9028c373a2a2caf 100644 --- a/Geometry/PlaneModel.cpp +++ b/Geometry/PlaneModel.cpp @@ -27,6 +27,11 @@ PlaneModel::PlaneModel(const core::Vec3d& p, const core::Vec3d& n) { this->plane = std::make_shared<Plane>(p, n); this->transform = RigidTransformType::Identity(); + + this->setRenderDelegate( + Factory<RenderDelegate>::createConcreteClassForGroup( + "StaticSceneObjectRenderDelegate",RenderDelegate::RendererType::VTK)); + } PlaneModel::~PlaneModel() {} void PlaneModel::draw() diff --git a/Mesh/SurfaceMesh.cpp b/Mesh/SurfaceMesh.cpp index 6b8c20f85e166cc7ae10c20af19466095a43cef8..69d67a41c708195f083a885ac4bed044d3964bce 100644 --- a/Mesh/SurfaceMesh.cpp +++ b/Mesh/SurfaceMesh.cpp @@ -46,7 +46,7 @@ struct SurfaceMesh::TextureAttachment SurfaceMesh::SurfaceMesh() : useThreeDSTexureCoordinates(false), useOBJDSTexureCoordinates(false) { this->setRenderDelegate( - Factory<RenderDelegate>::createConcreteClassForGroup("MeshRenderDelegate",300)); + Factory<RenderDelegate>::createConcreteClassForGroup("MeshRenderDelegate",RenderDelegate::RendererType::VTK)); } SurfaceMesh::~SurfaceMesh() { diff --git a/Mesh/VegaVolumetricMesh.cpp b/Mesh/VegaVolumetricMesh.cpp index 9d526f3d2331bdb5d1b0c6b621e5869ad61047b7..347ccb2c9a8b37f26317fb9b9a824a58562c3a5e 100644 --- a/Mesh/VegaVolumetricMesh.cpp +++ b/Mesh/VegaVolumetricMesh.cpp @@ -25,6 +25,7 @@ // SimMedTK includes #include "Mesh/SurfaceMesh.h" +#include "Core/RenderDelegate.h" // VEGA includes #include "volumetricMesh.h" @@ -74,8 +75,7 @@ void VegaVolumetricMesh::attachSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceM if(element < 0) { - std::cerr <<"Containing element not found for: " << meshVertices[i] <<std::endl; - continue; + element = this->mesh->getClosestElement(vegaPosition); } this->mesh->computeBarycentricWeights(element, vegaPosition, baryCentricWeights.data()); @@ -132,8 +132,9 @@ void VegaVolumetricMesh::setVegaMesh(std::shared_ptr<VolumetricMesh> newMesh) } void VegaVolumetricMesh::updateAttachedMeshes(double *q) { - for(auto surfaceMesh : this->attachedMeshes) - { + auto surfaceMesh = this->getRenderingMesh(); +// for(auto surfaceMesh : this->attachedMeshes) +// { std::vector<core::Vec3d> displacements(surfaceMesh->getNumberOfVertices()); VolumetricMesh::interpolate(q, displacements.data()->data(), @@ -145,10 +146,12 @@ void VegaVolumetricMesh::updateAttachedMeshes(double *q) auto &vertices = surfaceMesh->getVertices(); for(size_t i = 0, end = displacements.size(); i < end; ++i) { - vertices[i] += displacements[i]; + std::cout << displacements[i] << std::endl; + vertices[i] += displacements[i]*100000; } surfaceMesh->computeTriangleNormals(); - } + surfaceMesh->getRenderDelegate()->modified(); +// } } const std::unordered_map<size_t,size_t>& VegaVolumetricMesh::getVertexMap() const { @@ -177,3 +180,43 @@ void VegaVolumetricMesh::setRenderDetail(int i, std::shared_ptr< RenderDetail > { this->attachedMeshes.at(i)->setRenderDetail(newRenderDetail); } +std::shared_ptr< SurfaceMesh > VegaVolumetricMesh::getRenderingMesh() +{ + return attachedMeshes.size() > 0 + ? this->attachedMeshes.at(attachedMeshes.size() - 1) + : nullptr; +} +void VegaVolumetricMesh::attachSurfaceMesh(std::shared_ptr< SurfaceMesh > surfaceMesh, const std::string& fileName) +{ + std::ifstream fileStream(fileName.c_str()); + + if(!fileStream) + { + std::cerr << "Unable to open file: " << fileName << std::endl; + return; + } + + this->attachedMeshes.push_back(surfaceMesh); + std::vector<int> &vertices = this->attachedVertices[surfaceMesh]; + std::vector<double> &weigths = this->attachedWeights[surfaceMesh]; + vertices.clear(); + weigths.clear(); + + int index; + std::array<int, 4> v; + std::array<double, 4> w; + + while(fileStream >> index + >> v[0] >> w[0] + >> v[1] >> w[1] + >> v[2] >> w[2] + >> v[3] >> w[3]) + { + vertices.push_back(v[0]); weigths.push_back(w[0]); + vertices.push_back(v[1]); weigths.push_back(w[1]); + vertices.push_back(v[2]); weigths.push_back(w[2]); + vertices.push_back(v[3]); weigths.push_back(w[3]); + } + + std::cout << "Total # of weights read: " << weigths.size() << std::endl; +} diff --git a/Mesh/VegaVolumetricMesh.h b/Mesh/VegaVolumetricMesh.h index 842a31dd8f2cec1ee42bdf718564410da24abfaf..14ac3602d838823062174e40a635e113288060af 100644 --- a/Mesh/VegaVolumetricMesh.h +++ b/Mesh/VegaVolumetricMesh.h @@ -24,6 +24,9 @@ #ifndef SMVEGAMESH_H #define SMVEGAMESH_H +// STD includes +#include <fstream> + // SimMedTK includes #include "Core/BaseMesh.h" @@ -124,6 +127,16 @@ public: /// void setRenderDetail(int i, std::shared_ptr<RenderDetail> newRenderDetail); + /// + /// \brief Get attached rendering mesh + /// + std::shared_ptr<SurfaceMesh> getRenderingMesh(); + + /// + /// \brief Get attached surface mesh + /// + void attachSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh, const std::string &fileName); + private: // Vega mesh base object std::shared_ptr<VolumetricMesh> mesh; diff --git a/RenderDelegates/AABBRenderDelegate.cpp b/RenderDelegates/AABBRenderDelegate.cpp index b721f0a5cd9d360f5dc8fb6be012bce91b1a860f..fd1ebc40e71046c05257804e75275591b69bf01a 100644 --- a/RenderDelegates/AABBRenderDelegate.cpp +++ b/RenderDelegates/AABBRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/FemSceneRenderDelegate.cpp b/RenderDelegates/FemSceneRenderDelegate.cpp index dbe5474a5a60ac2dbc56a983a4720e14e20d254f..69a4f391e8ef05d5473da3d8f23a4f3be7f66c10 100644 --- a/RenderDelegates/FemSceneRenderDelegate.cpp +++ b/RenderDelegates/FemSceneRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Simulators/FemSceneObject.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/MeshRenderDelegate.cpp b/RenderDelegates/MeshRenderDelegate.cpp index 8d4bfe92ac2c9e44f369572c3db290447a219df5..bb8681f6e491260e938c85456aec527d13476f9c 100644 --- a/RenderDelegates/MeshRenderDelegate.cpp +++ b/RenderDelegates/MeshRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/PBDSurfaceRenderDelegate.cpp b/RenderDelegates/PBDSurfaceRenderDelegate.cpp index ce6ae47dcb094fc253d67e754bd6f54c9e27f7aa..9746ce7c11ab6f17a48b1399b6a41ead912b34b2 100644 --- a/RenderDelegates/PBDSurfaceRenderDelegate.cpp +++ b/RenderDelegates/PBDSurfaceRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Simulators/PBDSceneObject.h" diff --git a/RenderDelegates/PlaneRenderDelegate.cpp b/RenderDelegates/PlaneRenderDelegate.cpp index b03a855b1902b0e71862cff5e6eefe7ac3144b27..b317a44428571c3e9e4be9b6eaf02c62b257eb93 100644 --- a/RenderDelegates/PlaneRenderDelegate.cpp +++ b/RenderDelegates/PlaneRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/SceneObjectDeformableRenderDelegate.cpp b/RenderDelegates/SceneObjectDeformableRenderDelegate.cpp index 258a554d99cf3439245389138576808b9bd05854..e584e8a0b704db80014cb76570453119cc54ae2f 100644 --- a/RenderDelegates/SceneObjectDeformableRenderDelegate.cpp +++ b/RenderDelegates/SceneObjectDeformableRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/StaticSceneObjectRenderDelegate.cpp b/RenderDelegates/StaticSceneObjectRenderDelegate.cpp index ebb4417ef305b40fa13c36c481e3b54ed66946b3..39d0e647c0e4f886d8e3844f72790bca40932880 100644 --- a/RenderDelegates/StaticSceneObjectRenderDelegate.cpp +++ b/RenderDelegates/StaticSceneObjectRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/StaticSceneObject.h" #include "Core/RenderDelegate.h" diff --git a/RenderDelegates/StylusRenderDelegate.cpp b/RenderDelegates/StylusRenderDelegate.cpp index a5499886f75ad9bb4230ce48da3d8ffb467d7e75..7db2bd6d01396e7751af944cba4b2c48f714829e 100644 --- a/RenderDelegates/StylusRenderDelegate.cpp +++ b/RenderDelegates/StylusRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" diff --git a/RenderDelegates/SurfaceTreeRenderDelegate.cpp b/RenderDelegates/SurfaceTreeRenderDelegate.cpp index 8b08bd3c510ea818f090ad6c1a3b16e7ffb503f7..65826a611d8beb189cce586070b853ff2fd05298 100644 --- a/RenderDelegates/SurfaceTreeRenderDelegate.cpp +++ b/RenderDelegates/SurfaceTreeRenderDelegate.cpp @@ -21,6 +21,7 @@ // Contact: //--------------------------------------------------------------------------- +#include "Core/Model.h" #include "Core/RenderDelegate.h" #include "Core/Factory.h" #include "Collision/MeshCollisionModel.h" diff --git a/Simulators/SceneObjectDeformable.cpp b/Simulators/SceneObjectDeformable.cpp index 434b661fdc3859feaa0413dfbaf0cd991e4563e7..93336e2c0992d09c3c2e8c251c8fa16b49cbf5a1 100644 --- a/Simulators/SceneObjectDeformable.cpp +++ b/Simulators/SceneObjectDeformable.cpp @@ -24,6 +24,7 @@ // SimMedTK includes #include "Simulators/SceneObjectDeformable.h" #include "Core/Factory.h" +#include <Core/RenderDelegate.h> SceneObjectDeformable::SceneObjectDeformable() : renderSecondaryMesh(false), @@ -33,8 +34,9 @@ SceneObjectDeformable::SceneObjectDeformable() : subTimestepCounter(0) { this->setRenderDelegate( - Factory<RenderDelegate>::createSubclass( - "RenderDelegate", "SceneObjectDeformableRenderDelegate")); + Factory<RenderDelegate>::createConcreteClassForGroup( + "SceneObjectDeformableRenderDelegate", + RenderDelegate::RendererType::VTK)); } SceneObjectDeformable::~SceneObjectDeformable() diff --git a/Simulators/VegaFemSceneObject.cpp b/Simulators/VegaFemSceneObject.cpp index 301c26260a4e306d241de723b7b87118c3095d61..1fe916bdd4cc91a7c6d388b91741989d6ee4c6dc 100644 --- a/Simulators/VegaFemSceneObject.cpp +++ b/Simulators/VegaFemSceneObject.cpp @@ -196,9 +196,9 @@ void VegaFemSceneObject::loadVolumeMesh() auto ioMesh = std::make_shared<IOMesh>(); ioMesh->read(femConfig->volumetricMeshFilename); - volumetricMesh = std::static_pointer_cast<VegaVolumetricMesh>(ioMesh->getMesh()); + this->volumetricMesh = std::static_pointer_cast<VegaVolumetricMesh>(ioMesh->getMesh()); - if (!volumetricMesh) + if (!this->volumetricMesh) { PRINT_ERROR_LOCATION std::cout << "VEGA: error! unable to load the volumetric mesh from" @@ -206,9 +206,9 @@ void VegaFemSceneObject::loadVolumeMesh() return; } - numNodes = volumetricMesh->getNumberOfVertices(); - std::cout << "VEGA: Num vertices: " << volumetricMesh->getNumberOfVertices() << - ". Num elements: " << volumetricMesh->getNumberOfElements() << std::endl; + numNodes = this->volumetricMesh->getNumberOfVertices(); + std::cout << "VEGA: Num vertices: " << this->volumetricMesh->getNumberOfVertices() << + ". Num elements: " << this->volumetricMesh->getNumberOfElements() << std::endl; // load mass matrix if (strcmp(femConfig->massMatrixFilename, "__none") == 0) @@ -222,7 +222,7 @@ void VegaFemSceneObject::loadVolumeMesh() std::cout << "VEGA: mass matrix file was not specified! Generating mass matrix file. \n"; SparseMatrix *tempMassMatrix; - GenerateMassMatrix::computeMassMatrix(volumetricMesh->getVegaMesh().get(), &tempMassMatrix, false); + GenerateMassMatrix::computeMassMatrix(this->volumetricMesh->getVegaMesh().get(), &tempMassMatrix, false); std::cout << femConfig->massMatrixFilename << std::endl; if (tempMassMatrix->Save(femConfig->massMatrixFilename) != 0) @@ -247,7 +247,7 @@ void VegaFemSceneObject::loadVolumeMesh() { unsigned int loadingFlag = 0; // 0 = use low-memory version, 1 = use high-memory version - auto precomputedIntegrals = StVKElementABCDLoader::load(volumetricMesh->getVegaMesh().get(), loadingFlag); + auto precomputedIntegrals = StVKElementABCDLoader::load(this->volumetricMesh->getVegaMesh().get(), loadingFlag); if (precomputedIntegrals == nullptr) { @@ -261,7 +261,7 @@ void VegaFemSceneObject::loadVolumeMesh() if (femConfig->numInternalForceThreads == 0) { stVKInternalForces = std::make_shared<StVKInternalForces>( - volumetricMesh->getVegaMesh().get(), + this->volumetricMesh->getVegaMesh().get(), precomputedIntegrals, femConfig->addGravity, femConfig->g); @@ -270,7 +270,7 @@ void VegaFemSceneObject::loadVolumeMesh() else { stVKInternalForces = std::make_shared<StVKInternalForcesMT>( - volumetricMesh->getVegaMesh().get(), + this->volumetricMesh->getVegaMesh().get(), precomputedIntegrals, femConfig->addGravity, femConfig->g, @@ -282,7 +282,7 @@ void VegaFemSceneObject::loadVolumeMesh() } } - auto meshGraph = volumetricMesh->getMeshGraph(); + auto meshGraph = this->volumetricMesh->getMeshGraph(); if (meshGraph) { int scaleRows = 1; @@ -314,8 +314,19 @@ void VegaFemSceneObject::loadSurfaceMesh() << ioMesh->getMesh()->getTriangles().size() << " faces\n"; } auto surfaceMesh = std::static_pointer_cast<SurfaceMesh>(ioMesh->getMesh()); - this->volumetricMesh->attachSurfaceMesh(surfaceMesh); + + // load interpolation structure + if (strcmp(femConfig->secondaryRenderingMeshInterpolationFilename, "__none") == 0) + { + std::cerr << "VEGA: error! no secondary rendering mesh interpolation filename specified." << std::endl; + std::cerr << "VEGA: error! weighs will be computed. Slow operation." << std::endl; + this->volumetricMesh->attachSurfaceMesh(surfaceMesh); + } + + this->volumetricMesh->attachSurfaceMesh(surfaceMesh, + femConfig->secondaryRenderingMeshInterpolationFilename); } + } int VegaFemSceneObject::readBcFromFile(const char* filename, const int offset) diff --git a/VtkRendering/CMakeLists.txt b/VtkRendering/CMakeLists.txt index 5a16f82b934e2bc6865c014b390a2452975a211f..a42155ad6c3167ed5b1aa04d118102db128c2ddf 100644 --- a/VtkRendering/CMakeLists.txt +++ b/VtkRendering/CMakeLists.txt @@ -4,12 +4,16 @@ simmedtk_add_library(VtkRendering SOURCES VtkViewer.cpp VtkMeshRenderDelegate.cpp + VtkPlaneRenderDelegate.cpp + VtkSceneObjectDeformableRenderDelegate.cpp + VtkStaticSceneObjectRenderDelegate.cpp PUBLIC_HEADERS VtkViewer.h ) set(PRIVATE_LIBS PRIVATE - Core) + Core + Simulators) if(VTK_LIBRARIES) target_link_libraries(VtkRendering PUBLIC diff --git a/VtkRendering/VtkMeshRenderDelegate.cpp b/VtkRendering/VtkMeshRenderDelegate.cpp index d7b91eb7db934b72367ae170faa0c47104a30399..cd7733f992464a8f758649ff0caefa27b28127dc 100644 --- a/VtkRendering/VtkMeshRenderDelegate.cpp +++ b/VtkRendering/VtkMeshRenderDelegate.cpp @@ -23,9 +23,9 @@ #include <memory> +#include "Core/Model.h" #include "Core/Geometry.h" #include "Core/RenderDelegate.h" -#include "Core/Factory.h" #include "Mesh/SurfaceMesh.h" #include "Mesh/VegaVolumetricMesh.h" @@ -56,22 +56,18 @@ public: vtkActor *getActor() const; void initDraw(); + void modified(); private: - vtkSmartPointer<vtkActor> actor; - vtkSmartPointer<MeshNodalCoordinates<double>> mappedData; + vtkNew<vtkActor> actor; + vtkNew<MeshNodalCoordinates<double>> mappedData; vtkSmartPointer<vtkMapper> mapper; + + vtkSmartPointer<vtkDataSet> dataSet; }; void MeshRenderDelegate::initDraw() { - actor = vtkActor::New(); - mappedData = MeshNodalCoordinates<double>::New(); - - vtkNew<vtkUnstructuredGrid> unstructuredMesh; - vtkNew<vtkPoints> vertices; - vtkNew<vtkCellArray> triangles; - // The geometry can be either a volume or surface. // If its a vega volume then get its attached surface mesh. // This render delegate only draws surface meshes. @@ -95,6 +91,7 @@ void MeshRenderDelegate::initDraw() mappedData->SetVertexArray(mesh->getVertices()); + vtkNew<vtkCellArray> triangles; auto surfaceTriangles = mesh->getTriangles(); for(const auto &t : surfaceTriangles) { @@ -105,8 +102,11 @@ void MeshRenderDelegate::initDraw() triangles->InsertNextCell(3,cell); } + vtkNew<vtkPoints> vertices; vertices->SetNumberOfPoints(mesh->getVertices().size()); vertices->SetData(mappedData.GetPointer()); + + vtkNew<vtkUnstructuredGrid> unstructuredMesh; unstructuredMesh->SetPoints(vertices.GetPointer()); unstructuredMesh->SetCells(VTK_TRIANGLE,triangles.GetPointer()); @@ -132,6 +132,7 @@ void MeshRenderDelegate::initDraw() unstructuredMesh->GetPointData()->SetTCoords(textureCoordinates.GetPointer()); } + dataSet = unstructuredMesh.GetPointer(); if (mesh->getRenderDetail()->renderType & SIMMEDTK_RENDER_NORMALS) { vtkSmartPointer<vtkGeometryFilter> geometry = vtkGeometryFilter::New(); @@ -141,6 +142,7 @@ void MeshRenderDelegate::initDraw() normals->SetInputConnection(geometry->GetOutputPort()); normals->AutoOrientNormalsOn(); + mapper = vtkPolyDataMapper::New(); mapper->SetInputConnection(normals->GetOutputPort()); } @@ -154,7 +156,7 @@ void MeshRenderDelegate::initDraw() { actor->SetTexture(texture); } - actor->SetMapper(mapper); + actor->SetMapper(mapper.GetPointer()); } bool MeshRenderDelegate::isTargetTextured() const @@ -171,8 +173,18 @@ vtkActor *MeshRenderDelegate::getActor() const return this->actor.GetPointer(); } +void MeshRenderDelegate::modified() +{ + dataSet->Modified(); +} + +#include "Core/Config.h" +#include "Core/Factory.h" SIMMEDTK_BEGIN_DYNAMIC_LOADER() -SIMMEDTK_BEGIN_ONLOAD(register_mesh_render_delegate) - SIMMEDTK_REGISTER_CLASS(RenderDelegate,RenderDelegate,MeshRenderDelegate,300); -SIMMEDTK_FINISH_ONLOAD() + SIMMEDTK_BEGIN_ONLOAD(register_MeshRenderDelegate) + SIMMEDTK_REGISTER_CLASS(RenderDelegate, + RenderDelegate, + MeshRenderDelegate, + RenderDelegate::RendererType::VTK); + SIMMEDTK_FINISH_ONLOAD() SIMMEDTK_FINISH_DYNAMIC_LOADER() diff --git a/VtkRendering/VtkPlaneRenderDelegate.cpp b/VtkRendering/VtkPlaneRenderDelegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b971e27ff0270821bc3d745c0fbde81a381bb1 --- /dev/null +++ b/VtkRendering/VtkPlaneRenderDelegate.cpp @@ -0,0 +1,82 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and 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 +// +// 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. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include "Core/Model.h" +#include "Core/Geometry.h" + +// Vtk incudes +#include <vtkActor.h> +#include <vtkNew.h> +#include <vtkSmartPointer.h> +#include <vtkPolyDataMapper.h> +#include <vtkPlaneSource.h> +#include "VtkRendering/VtkRenderDelegate.h" + +class PlaneRenderDelegate : public VtkRenderDelegate +{ +public: + vtkActor *getActor() const override; + virtual void initDraw() override; + +private: + vtkSmartPointer<vtkActor> actor; + vtkSmartPointer<vtkPolyDataMapper> mapper; +}; + +void PlaneRenderDelegate::initDraw() +{ + auto plane = this->getSourceGeometryAs<Plane>(); + if(!plane) + { + return; + } + + vtkNew<vtkPlaneSource> planeSource; + auto center = plane->getPoint(); + auto normal = plane->getUnitNormal(); + + planeSource->SetCenter(center(0),center(1),center(2)); + planeSource->SetNormal(normal(0),normal(1),normal(2)); + + this->mapper = vtkPolyDataMapper::New(); + this->mapper->SetInputConnection(planeSource->GetOutputPort()); + + this->actor = vtkActor::New(); + this->actor->SetMapper(mapper); +} + +vtkActor *PlaneRenderDelegate::getActor() const +{ + return actor; +} + +#include "Core/Config.h" +#include "Core/Factory.h" +SIMMEDTK_BEGIN_DYNAMIC_LOADER() + SIMMEDTK_BEGIN_ONLOAD(register_PlaneRenderDelegate) + SIMMEDTK_REGISTER_CLASS(RenderDelegate, + RenderDelegate, + PlaneRenderDelegate, + RenderDelegate::RendererType::VTK); + SIMMEDTK_FINISH_ONLOAD() +SIMMEDTK_FINISH_DYNAMIC_LOADER() diff --git a/VtkRendering/VtkRenderDelegate.h b/VtkRendering/VtkRenderDelegate.h index 7fad13ba393a2d06b85fbd9ddc405e3a7ea8983d..82634807a5ede3a3ecd4beb17f68b1640a59bba9 100644 --- a/VtkRendering/VtkRenderDelegate.h +++ b/VtkRendering/VtkRenderDelegate.h @@ -9,7 +9,8 @@ class VtkRenderDelegate : public RenderDelegate { public: virtual vtkActor *getActor() const = 0; - virtual void initDraw(){}; + virtual void initDraw(){} + virtual void modified(){} }; #endif // SMRENDERABLE_H diff --git a/VtkRendering/VtkSceneObjectDeformableRenderDelegate.cpp b/VtkRendering/VtkSceneObjectDeformableRenderDelegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1ba5ee6fb1eda7334f49b71367759054c38037b --- /dev/null +++ b/VtkRendering/VtkSceneObjectDeformableRenderDelegate.cpp @@ -0,0 +1,77 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and 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 +// +// 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. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include "Core/Model.h" +#include "Core/Geometry.h" // for VisualArtifact used by geometry sources in RenderDelegate +#include "Simulators/VegaFemSceneObject.h" +#include "Mesh/VegaVolumetricMesh.h" +#include "VtkRendering/VtkRenderDelegate.h" + +// VTK includes +#include <vtkActor.h> + +/// \brief Displays the fem object with primary or secondary mesh, fixed vertices, +/// vertices interacted with, ground plane etc. +class SceneObjectDeformableRenderDelegate : public VtkRenderDelegate +{ +public: + vtkActor *getActor() const override; +}; + +vtkActor *SceneObjectDeformableRenderDelegate::getActor() const +{ + auto geom = this->getSourceGeometryAs<VegaFemSceneObject>(); + + if(!geom) + { + return nullptr; + } + auto mesh = geom->getVolumetricMesh(); + if(!mesh) + { + return nullptr; + } + auto surfaceMesh = mesh->getRenderingMesh(); + if(!surfaceMesh) + { + return nullptr; + } + auto delegate = std::dynamic_pointer_cast<VtkRenderDelegate>(surfaceMesh->getRenderDelegate()); + if(!delegate) + { + return nullptr; + } + delegate->initDraw(); + return delegate->getActor(); +} + +#include "Core/Config.h" +#include "Core/Factory.h" +SIMMEDTK_BEGIN_DYNAMIC_LOADER() + SIMMEDTK_BEGIN_ONLOAD(register_SceneObjectDeformableRenderDelegate) + SIMMEDTK_REGISTER_CLASS(RenderDelegate, + RenderDelegate, + SceneObjectDeformableRenderDelegate, + RenderDelegate::RendererType::VTK); + SIMMEDTK_FINISH_ONLOAD() +SIMMEDTK_FINISH_DYNAMIC_LOADER() diff --git a/VtkRendering/VtkStaticSceneObjectRenderDelegate.cpp b/VtkRendering/VtkStaticSceneObjectRenderDelegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d298e7f45a311c0b378aa4ffd9efa8611609f2d6 --- /dev/null +++ b/VtkRendering/VtkStaticSceneObjectRenderDelegate.cpp @@ -0,0 +1,75 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and 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 +// +// 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. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include "Core/Model.h" +#include "Core/Geometry.h" +#include "Core/StaticSceneObject.h" +#include "VtkRendering/VtkRenderDelegate.h" +#include "Geometry/PlaneModel.h" + +// VTK includes +#include <vtkActor.h> + +class StaticSceneObjectRenderDelegate : public VtkRenderDelegate +{ +public: + vtkActor *getActor() const override; +}; + +vtkActor *StaticSceneObjectRenderDelegate::getActor() const +{ + StaticSceneObject* geom = this->getSourceGeometryAs<StaticSceneObject>(); + if (!geom) + { + return nullptr; + } + + auto planeModel = std::dynamic_pointer_cast<PlaneModel>( + geom->getModel()); + + if(!planeModel) + { + return nullptr; + } + + auto delegate = std::dynamic_pointer_cast<VtkRenderDelegate>( + planeModel->getPlaneModel()->getRenderDelegate()); + + if(!delegate) + { + return nullptr; + } + delegate->initDraw(); + return delegate->getActor(); +} + +#include "Core/Config.h" +#include "Core/Factory.h" +SIMMEDTK_BEGIN_DYNAMIC_LOADER() + SIMMEDTK_BEGIN_ONLOAD(register_StaticSceneObjectRenderDelegate) + SIMMEDTK_REGISTER_CLASS(RenderDelegate, + RenderDelegate, + StaticSceneObjectRenderDelegate, + RenderDelegate::RendererType::VTK); + SIMMEDTK_FINISH_ONLOAD() +SIMMEDTK_FINISH_DYNAMIC_LOADER() diff --git a/VtkRendering/VtkViewer.cpp b/VtkRendering/VtkViewer.cpp index e952e95baa052fad579881180bcd219ea4830927..323309d53e8abdd077ec053fd0c5a196c2aa6586 100644 --- a/VtkRendering/VtkViewer.cpp +++ b/VtkRendering/VtkViewer.cpp @@ -31,18 +31,31 @@ #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> +#include <vtkInteractorStyleSwitch.h> +#include <vtkCommand.h> /// /// \brief Wrapper to the vtkRendering pipeline /// -class VtkViewer::VtkRenderer +class VtkViewer::VtkRenderer : public vtkCommand { + int timerId; public: VtkRenderer(VtkViewer *activeViewer) : viewer(activeViewer), renderWindow(vtkRenderWindow::New()), renderWindowInteractor(vtkRenderWindowInteractor::New()) { + this->timerId = -1; + } + + virtual void Execute(vtkObject *caller, unsigned long eventId, + void *callData) + { + if(timerId == *static_cast<int*>(callData)) + { + this->renderWindow->Render(); + } } /// @@ -60,7 +73,10 @@ public: { this->viewer->adjustFPS(); this->renderWindow->Render(); + this->timerId = renderWindowInteractor->CreateRepeatingTimer(1000.0/60.0); + this->renderWindowInteractor->AddObserver(vtkCommand::TimerEvent,this); this->renderWindowInteractor->Start(); + this->renderWindowInteractor->DestroyTimer(this->timerId); } void removeRenderer(vtkRenderer* renderer) @@ -81,7 +97,10 @@ public: } this->renderWindowInteractor->SetRenderWindow(renderWindow); - + vtkSmartPointer<vtkInteractorStyleSwitch> style = + vtkSmartPointer<vtkInteractorStyleSwitch>::New(); + style->SetCurrentStyleToTrackballCamera(); + renderWindowInteractor->SetInteractorStyle( style ); // The actors are obtained from VtkRenderDelegates std::shared_ptr<VtkRenderDelegate> delegate; for(auto &ro : this->viewer->renderOperations)