Skip to content
Snippets Groups Projects
Commit 3f133a06 authored by Andrew Wilson's avatar Andrew Wilson :elephant:
Browse files

ENH: Osteo example

parent f3bfa90e
No related branches found
No related tags found
No related merge requests found
###########################################################################
#
# 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.
#
###########################################################################
project(Example-OsteoTemp)
#-----------------------------------------------------------------------------
# Create executable
#-----------------------------------------------------------------------------
imstk_add_executable(${PROJECT_NAME} OsteoTempExample.cpp CutObject.h CutObject.cpp)
#-----------------------------------------------------------------------------
# Add the target to Examples folder
#-----------------------------------------------------------------------------
SET_TARGET_PROPERTIES (${PROJECT_NAME} PROPERTIES FOLDER Examples/Osteo)
#-----------------------------------------------------------------------------
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME} SimulationManager Filtering)
///*=========================================================================
//
// 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 "CutObject.h"
#include "imstkImageData.h"
#include "imstkLevelSetModel.h"
#include "imstkLocalMarchingCubes.h"
#include "imstkMeshIO.h"
#include "imstkNew.h"
#include "imstkRenderMaterial.h"
#include "imstkSurfaceMesh.h"
#include "imstkTaskGraph.h"
#include "imstkVisualModel.h"
CutObject::CutObject() : LevelSetDeformableObject("Femur"),
m_isoExtract(std::make_shared<LocalMarchingCubes>())
{
std::shared_ptr<ImageData> initLvlSetImage = MeshIO::read<ImageData>("C:/Users/Andx_/Desktop/NewScenarioData/Final/mandible/mandibleReducedSmoothenedCut_SDF.mhd")->cast(IMSTK_DOUBLE);
// Setup the Parameters
imstkNew<LevelSetModelConfig> lvlSetConfig;
lvlSetConfig->m_sparseUpdate = true;
lvlSetConfig->m_substeps = 10;
// Too many chunks and you'll hit memory constraints quickly
// Too little chunks and the updates for a chunk will take too long
// The chunks must divide the image dimensions-1 (image dim-1 must be divisible by # chunks)
m_isoExtract->setInputImage(initLvlSetImage);
m_isoExtract->setIsoValue(0.0);
m_isoExtract->setNumberOfChunks(Vec3i(10, 15, 15));
m_isoExtract->update();
srand(static_cast<unsigned int>(time(NULL)));
createVisualModels();
// Setup the Object
imstkNew<SignedDistanceField> sdf(initLvlSetImage);
// Setup the Model
imstkNew<LevelSetModel> model;
model->setModelGeometry(sdf);
model->configure(lvlSetConfig);
setPhysicsGeometry(sdf);
setCollidingGeometry(sdf);
setDynamicalModel(model);
// Setup a custom task to forward the modified voxels of the level set model
// to the marching cubes before they're cleared
m_forwardModifiedVoxels = std::make_shared<TaskNode>(
std::bind(&CutObject::updateModifiedVoxels, this), "Isosurface: SetModifiedVoxels");
m_taskGraph->addNode(m_forwardModifiedVoxels);
}
void
CutObject::visualUpdate()
{
// Update any chunks that contain a voxel which was set modified
m_isoExtract->update();
// Create meshes for chunks if they now contain vertices (and weren't already generated)
// You could just create all the chunks, but this saves some memory for internal/empty ones
createVisualModels();
}
void
CutObject::createVisualModels()
{
const Vec3i& numChunks = m_isoExtract->getNumberOfChunks();
for (int i = 0; i < numChunks[0] * numChunks[1] * numChunks[2]; i++)
{
auto surfMesh = std::dynamic_pointer_cast<SurfaceMesh>(m_isoExtract->getOutput(i));
if (surfMesh->getNumVertices() > 0 && m_chunksGenerated.count(i) == 0)
{
imstkNew<VisualModel> surfMeshModel(m_isoExtract->getOutput(i));
imstkNew<RenderMaterial> material;
material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
material->setLineWidth(4.0);
if (m_useRandomChunkColors)
{
const double r = (rand() % 10000) / 10000.0;
const double g = (rand() % 10000) / 10000.0;
const double b = (rand() % 10000) / 10000.0;
material->setColor(Color(r, g, b));
}
else
{
material->setColor(Color::Bone);
}
//material->setOpacity(0.7);
surfMeshModel->setRenderMaterial(material);
addVisualModel(surfMeshModel);
m_chunksGenerated.insert(i);
}
}
}
void
CutObject::updateModifiedVoxels()
{
// Forward the level set's modified nodes to the isosurface extraction
for (auto i : getLevelSetModel()->getNodesToUpdate())
{
m_isoExtract->setModified(std::get<0>(i.second));
}
}
void
CutObject::initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink)
{
// Copy, sum, and connect the model graph to nest within this graph
m_taskGraph->addEdge(source, getUpdateNode());
m_dynamicalModel->initGraphEdges();
m_taskGraph->nestGraph(m_dynamicalModel->getTaskGraph(), getUpdateNode(), getUpdateGeometryNode());
// The levelsetmodel produces a list of modified voxels, we forward that to the isosurface extraction
// filter to update only the modified chunks
m_taskGraph->addEdge(getLevelSetModel()->getGenerateVelocitiesEndNode(), m_forwardModifiedVoxels);
m_taskGraph->addEdge(m_forwardModifiedVoxels, getLevelSetModel()->getQuantityEvolveNode(0));
m_taskGraph->addEdge(getUpdateGeometryNode(), sink);
}
\ 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.
//
//=========================================================================*/
#pragma once
#include "imstkLevelSetDeformableObject.h"
#include <unordered_set>
namespace imstk
{
class LocalMarchingCubes;
class TaskNode;
}
using namespace imstk;
///
/// \class FemurObject
///
/// \brief The FemurObject implements a localized marching cubes. That is we've split
/// up an image into a bunch of chunks. Our model reports on which voxels of the image
/// were modified, we supply this to the local marching cubes and it will update
/// only the respective chunks.
///
class CutObject : public LevelSetDeformableObject
{
public:
CutObject();
~CutObject() override = default;
public:
///
/// \brief Update the isosurface before rendering, the isosurface
/// is not used for simulation so we can afford to update it
/// less frequently
///
void visualUpdate() override;
///
/// \brief Creates visual models for any chunk that has non-zero vertices
/// and is not already generated
///
void createVisualModels();
void setUseRandomChunkColors(const bool useRandom) { m_useRandomChunkColors = useRandom; }
bool getUseRandomChunkColors() const { return m_useRandomChunkColors; }
protected:
///
/// \brief Forwards/copies the levelsets list of modified voxels to the isosurface
/// extraction filters list of modified voxels
///
void updateModifiedVoxels();
///
/// \brief Setup connectivity of task graph
///
virtual void initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink) override;
protected:
std::shared_ptr<LocalMarchingCubes> m_isoExtract;
std::unordered_set<int> m_chunksGenerated; // Lazy generation of chunks
std::shared_ptr<TaskNode> m_forwardModifiedVoxels;
bool m_useRandomChunkColors = false;
};
\ 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 "imstkCamera.h"
#include "imstkCollisionGraph.h"
#include "imstkVecDataArray.h"
#ifdef iMSTK_USE_OPENHAPTICS
#include "imstkHapticDeviceClient.h"
#include "imstkHapticDeviceManager.h"
#endif
#include "imstkImageData.h"
#include "imstkKeyboardDeviceClient.h"
#include "imstkLevelSetCH.h"
#include "imstkLevelSetDeformableObject.h"
#include "imstkLevelSetModel.h"
#include "imstkLight.h"
#include "imstkLocalMarchingCubes.h"
#include "imstkLogger.h"
#include "imstkMeshIO.h"
#include "imstkMouseSceneControl.h"
#include "imstkNew.h"
#include "imstkOpenVRDeviceClient.h"
#include "imstkPlane.h"
#include "imstkRbdConstraint.h"
#include "imstkRigidBodyCH.h"
#include "imstkRigidBodyModel2.h"
#include "imstkRigidObject2.h"
#include "imstkRigidObjectController.h"
#include "imstkRigidObjectLevelSetCollisionPair.h"
#include "imstkScene.h"
#include "imstkSceneManager.h"
#include "imstkSimulationManager.h"
#include "imstkSurfaceMesh.h"
#include "imstkTaskGraph.h"
#include "imstkVisualModel.h"
#include "imstkVisualObjectImporter.h"
#include "imstkVolumeRenderMaterial.h"
#include "imstkVTKOpenVRViewer.h"
#include "imstkVTKViewer.h"
#include "imstkViewer.h"
#include "imstkKeyboardSceneControl.h"
#include "CutObject.h"
using namespace imstk;
using namespace imstk::expiremental;
/// Note: Transform 200 degrees around the X axes to get back to source image space
std::unordered_set<int> lvlSetChunkCreated;
std::shared_ptr<RigidObject2>
makeSawObj(const std::string& name)
{
imstkNew<RigidBodyModel2> rbdModel;
rbdModel->getConfig()->m_maxNumIterations = 8;
rbdModel->getConfig()->m_velocityDamping = 1.0;
rbdModel->getConfig()->m_angularVelocityDamping = 1.0;
rbdModel->getConfig()->m_maxNumConstraints = 40;
// Create the saw
imstkNew<RigidObject2> rigidObj("Saw");
{
auto toolMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scalpel/Scalpel_Hull_Subdivided_Shifted.stl");
toolMesh->rotate(Vec3d(0.0, 1.0, 0.0), 3.14, Geometry::TransformType::ApplyToData);
toolMesh->rotate(Vec3d(1.0, 0.0, 0.0), -1.57, Geometry::TransformType::ApplyToData);
toolMesh->scale(Vec3d(10.0, 10.0, 10.0), Geometry::TransformType::ApplyToData);
imstkNew<VisualModel> visualModel(toolMesh);
imstkNew<RenderMaterial> mat;
mat->setDisplayMode(RenderMaterial::DisplayMode::Surface);
mat->setShadingModel(RenderMaterial::ShadingModel::PBR);
mat->setMetalness(0.9f);
mat->setRoughness(0.4f);
//mat->setDisplayMode(RenderMaterial::DisplayMode::Points);
//mat->setPointSize(15.0);
mat->setDiffuseColor(Color(0.7, 0.7, 0.7));
visualModel->setRenderMaterial(mat);
// Create the object
rigidObj->addVisualModel(visualModel);
rigidObj->setPhysicsGeometry(toolMesh);
rigidObj->setCollidingGeometry(toolMesh);
rigidObj->setDynamicalModel(rbdModel);
/*rigidObj->getRigidBody()->m_mass = 1000.0;
rigidObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 20.0;
rigidObj->getRigidBody()->m_initPos = Vec3d(0.0, 1.0, 2.0);*/
rigidObj->getRigidBody()->m_mass = 1.0 * 100.0;
rigidObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 10000.0 * 100.0;
rigidObj->getRigidBody()->m_initPos = Vec3d(0.0, 1.0, 2.0);
}
return rigidObj;
}
int
main()
{
// If the user requested haptics but imstk was not built with it, turn it off
#ifndef iMSTK_USE_OPENHAPTICS
if (m_config.controllerType == ControllerType::USEHAPTICS)
{
m_config.controllerType = ControllerType::USEMOUSE;
m_config.renderType = RenderType::USEWINDOW;
}
#endif
LOG(INFO) << "----------------------------------------";
LOG(INFO) << " Virtual Osteotomy Trainer \n";
LOG(INFO) << " Kitware Inc., UNC School of Dentistry ";
LOG(INFO) << "----------------------------------------\n";
// Setup logger (write to file and stdout)
Logger::startLogger();
imstkNew<Scene> scene("Osteotomy Trainer");
imstkNew<CutObject> cutObject;
scene->addSceneObject(cutObject);
Vec3d lvlSetCenter;
{
Vec3d min, max;
cutObject->getPhysicsGeometry()->computeBoundingBox(min, max);
lvlSetCenter = (min + max) * 0.5;
}
std::shared_ptr<RigidObject2> rbdObj = makeSawObj("RigidObj");
scene->addSceneObject(rbdObj);
imstkNew<SceneObject> rbdGhostObj("RigidObjGhost");
imstkNew<SurfaceMesh> ghostMesh;
ghostMesh->deepCopy(std::dynamic_pointer_cast<SurfaceMesh>(rbdObj->getPhysicsGeometry()));
rbdGhostObj->setVisualGeometry(ghostMesh);
std::shared_ptr<RenderMaterial> ghostMat = std::make_shared<RenderMaterial>(*rbdObj->getVisualModel(0)->getRenderMaterial());
ghostMat->setOpacity(0.4);
rbdGhostObj->getVisualModel(0)->setRenderMaterial(ghostMat);
scene->addSceneObject(rbdGhostObj);
imstkNew<RigidObjectLevelSetCollisionPair> interaction(rbdObj, cutObject);
auto colHandlerA = std::dynamic_pointer_cast<RigidBodyCH>(interaction->getCollisionHandlingA());
colHandlerA->setUseFriction(false);
colHandlerA->setStiffness(0.0); // inelastic collision
auto colHandlerB = std::dynamic_pointer_cast<LevelSetCH>(interaction->getCollisionHandlingB());
colHandlerB->setLevelSetVelocityScaling(10.0);
colHandlerB->setKernel(3, 1.0);
//colHandlerB->setLevelSetVelocityScaling(0.0); // Can't push the levelset
colHandlerB->setUseProportionalVelocity(false);
scene->getCollisionGraph()->addInteraction(interaction);
// Light (white)
imstkNew<DirectionalLight> whiteLight("whiteLight");
whiteLight->setDirection(Vec3d(0.0, -8.0, 5.0));
whiteLight->setIntensity(1.0);
scene->addLight(whiteLight);
// Adjust camera
scene->getActiveCamera()->setFocalPoint(16.75, 21.20, 49.44);
scene->getActiveCamera()->setPosition(15.0, 118.71, 32.15);
scene->getActiveCamera()->setViewUp(-0.03, -0.18, -0.98);
{
imstkNew<VTKViewer> viewer("Viewer");
viewer->setActiveScene(scene);
// Add a module to run the scene
imstkNew<SceneManager> sceneManager("Scene Manager");
sceneManager->setActiveScene(scene);
sceneManager->setExecutionType(Module::ExecutionType::ADAPTIVE);
imstkNew<HapticDeviceManager> hapticManager;
hapticManager->setSleepDelay(0.5); // Delay for 1/2ms (haptics thread is limited to max 2000hz)
std::shared_ptr<HapticDeviceClient> hapticDeviceClient = hapticManager->makeDeviceClient();
imstkNew<RigidObjectController> controller(rbdObj, hapticDeviceClient);
// Note: These decrease as world space increases
controller->setLinearKd(1000.0 * 100.0);
controller->setLinearKs(100000.0 * 100.0);
controller->setAngularKs(300000000.0 * 100.0);
controller->setAngularKd(400000.0 * 100.0);
controller->setForceScaling(0.0000001);
controller->setComputeVelocity(true); // The device we are using doesn't produce this quantity, with this flag its computed
controller->setComputeAngularVelocity(true); // The device we are using doesn't produce this quantity, with this flag its computed
controller->setTranslationScaling(0.5);
controller->setTranslationOffset(lvlSetCenter);
//controller->setRotationOffset(Quatd(Rotd(3.14159, Vec3d(1.0, 0.0, 0.0))));
scene->addController(controller);
connect<Event>(sceneManager, &SceneManager::postUpdate, [&](Event*)
{
rbdObj->getRigidBodyModel2()->getConfig()->m_dt = sceneManager->getDt();
cutObject->getLevelSetModel()->getConfig()->m_dt = sceneManager->getDt();
// Also apply controller transform to ghost geometry
ghostMesh->setTranslation(controller->getPosition());
ghostMesh->setRotation(controller->getRotation());
ghostMesh->updatePostTransformData();
ghostMesh->postModified();
});
imstkNew<SimulationManager> driver;
driver->addModule(viewer);
driver->addModule(sceneManager);
driver->addModule(hapticManager);
driver->setDesiredDt(0.001);
{
imstkNew<MouseSceneControl> mouseControl(viewer->getMouseDevice());
mouseControl->setSceneManager(sceneManager);
viewer->addControl(mouseControl);
imstkNew<KeyboardSceneControl> keyControl(viewer->getKeyboardDevice());
keyControl->setSceneManager(sceneManager);
keyControl->setModuleDriver(driver);
viewer->addControl(keyControl);
}
driver->start();
}
}
###########################################################################
#
# 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_OpenHaptics)
project(Example-RigidBodyRibsExample)
#-----------------------------------------------------------------------------
# Create executable
#-----------------------------------------------------------------------------
imstk_add_executable(${PROJECT_NAME} RigidBodyRibsExample.cpp)
#-----------------------------------------------------------------------------
# Add the target to Examples folder
#-----------------------------------------------------------------------------
SET_TARGET_PROPERTIES (${PROJECT_NAME} PROPERTIES FOLDER Examples/Haptics)
#-----------------------------------------------------------------------------
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME} SimulationManager Filtering)
endif()
/*=========================================================================
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 "imstkCamera.h"
#include "imstkCollisionGraph.h"
#include "imstkHapticDeviceClient.h"
#include "imstkHapticDeviceManager.h"
#include "imstkKeyboardSceneControl.h"
#include "imstkLevelSetCH.h"
#include "imstkLevelSetModel.h"
#include "imstkLight.h"
#include "imstkLogger.h"
#include "imstkMeshIO.h"
#include "imstkMouseSceneControl.h"
#include "imstkNew.h"
#include "imstkRbdConstraint.h"
#include "imstkRigidBodyCH.h"
#include "imstkRigidBodyModel2.h"
#include "imstkRigidObject2.h"
#include "imstkRigidObjectController.h"
#include "imstkRigidObjectCollidingCollisionPair.h"
#include "imstkScene.h"
#include "imstkSceneManager.h"
#include "imstkSimulationManager.h"
#include "imstkSurfaceMesh.h"
#include "imstkVisualModel.h"
#include "imstkVolumeRenderMaterial.h"
#include "imstkVTKViewer.h"
#include "imstkKeyboardDeviceClient.h"
#include "imstkIsometricMap.h"
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include "imstkVolumeRenderMaterial.h"
#include <vtkVolumeProperty.h>
using namespace imstk;
using namespace imstk::expiremental;
std::shared_ptr<CollidingObject>
makeRibObj(const std::string& name)
{
imstkNew<CollidingObject> colObj(name);
auto sdfImage = MeshIO::read<ImageData>("C:/Users/Andx_/Desktop/ribs_SDF.mhd")->cast(IMSTK_DOUBLE);
sdfImage->setOrigin(sdfImage->getOrigin() + Vec3d(-200.0, -200.0, -200.0));
auto visualMesh = MeshIO::read<SurfaceMesh>("C:/Users/Andx_/Desktop/ribs.stl");
visualMesh->translate(Vec3d(-200.0, -200.0, -200.0), Geometry::TransformType::ApplyToData);
colObj->setVisualGeometry(visualMesh);
colObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Bone);
//colObj->setVisualGeometry(sdfImage);
auto sdf = std::make_shared<SignedDistanceField>(sdfImage);
colObj->setCollidingGeometry(sdf);
//imstkNew<VolumeRenderMaterial> volumeMaterial;
//vtkNew<vtkColorTransferFunction> colorFunc;
//colorFunc->AddRGBPoint(0.0, 1.0, 0.0, 0.0);
//colorFunc->AddRGBPoint(8.0, 0.0, 0.0, 1.0);
//volumeMaterial->getVolumeProperty()->SetColor(colorFunc);
//vtkNew<vtkPiecewiseFunction> opacityFunc;
//opacityFunc->AddPoint(0.0, 0.0);
//opacityFunc->AddPoint(1.0, 1.0);
//volumeMaterial->getVolumeProperty()->SetScalarOpacity(opacityFunc);
//// Apply the preset to the visual object
//colObj->getVisualModel(0)->setRenderMaterial(volumeMaterial);
return colObj;
}
std::shared_ptr<RigidObject2>
makeRigidObj(const std::string& name)
{
imstkNew<RigidBodyModel2> rbdModel;
rbdModel->getConfig()->m_maxNumIterations = 20;
rbdModel->getConfig()->m_velocityDamping = 1.0;
rbdModel->getConfig()->m_angularVelocityDamping = 1.0;
rbdModel->getConfig()->m_maxNumConstraints = 60;
// Create the first rbd, plane floor
imstkNew<RigidObject2> rigidObj(name);
{
auto toolMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scalpel/Scalpel_Hull_Subdivided.stl");
toolMesh->rotate(Vec3d(0.0, 1.0, 0.0), 3.14, Geometry::TransformType::ApplyToData);
toolMesh->rotate(Vec3d(1.0, 0.0, 0.0), -1.57, Geometry::TransformType::ApplyToData);
toolMesh->scale(Vec3d(15.0, 15.0, 15.0), Geometry::TransformType::ApplyToData);
auto toolTipMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scalpel/Scalpel_Handle.dae");
toolTipMesh->rotate(Vec3d(0.0, 1.0, 0.0), 3.14, Geometry::TransformType::ApplyToData);
toolTipMesh->rotate(Vec3d(1.0, 0.0, 0.0), -1.57, Geometry::TransformType::ApplyToData);
toolTipMesh->scale(Vec3d(15.0, 15.0, 15.0), Geometry::TransformType::ApplyToData);
auto toolHandleMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scalpel/Scalpel_Blade15.dae");
toolHandleMesh->rotate(Vec3d(0.0, 1.0, 0.0), 3.14, Geometry::TransformType::ApplyToData);
toolHandleMesh->rotate(Vec3d(1.0, 0.0, 0.0), -1.57, Geometry::TransformType::ApplyToData);
toolHandleMesh->scale(Vec3d(15.0, 15.0, 15.0), Geometry::TransformType::ApplyToData);
imstkNew<RenderMaterial> toolMaterial;
toolMaterial->setDisplayMode(RenderMaterial::DisplayMode::Surface);
toolMaterial->setShadingModel(RenderMaterial::ShadingModel::PBR);
toolMaterial->setMetalness(0.9f);
toolMaterial->setRoughness(0.4f);
toolMaterial->setDiffuseColor(Color(0.7, 0.7, 0.7));
imstkNew<VisualModel> toolTip;
toolTip->setGeometry(toolTipMesh);
toolTip->setRenderMaterial(toolMaterial);
imstkNew<VisualModel> toolHandle;
toolHandle->setGeometry(toolHandleMesh);
toolHandle->setRenderMaterial(toolMaterial);
// Create the object
//rigidObj->setVisualGeometry(toolMesh);
rigidObj->addVisualModel(toolTip);
rigidObj->addVisualModel(toolHandle);
rigidObj->setPhysicsGeometry(toolMesh);
rigidObj->setCollidingGeometry(toolMesh);
rigidObj->setCollidingToVisualMap(std::make_shared<IsometricMap>(toolMesh, toolTipMesh));
rigidObj->setPhysicsToCollidingMap(std::make_shared<IsometricMap>(toolMesh, toolHandleMesh));
rigidObj->setDynamicalModel(rbdModel);
rigidObj->getRigidBody()->m_mass = 1.0;
rigidObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 10000.0;
rigidObj->getRigidBody()->m_initPos = Vec3d(0.0, 1.0, 2.0);
}
return rigidObj;
}
///
/// \brief This example demonstrates cutting a femur bone with a tool
/// Some of the example parameters may need to be tweaked for differing
/// systems
///
int
main()
{
// Setup logger (write to file and stdout)
Logger::startLogger();
imstkNew<Scene> scene("Ribsssss");
scene->getConfig()->taskParallelizationEnabled = false;
std::shared_ptr<CollidingObject> ribObj = makeRibObj("Ribs");
scene->addSceneObject(ribObj);
std::shared_ptr<RigidObject2> rbdObj = makeRigidObj("ToolObject");
scene->addSceneObject(rbdObj);
imstkNew<SceneObject> rbdGhostObj("ToolObjectGhost");
imstkNew<SurfaceMesh> ghostMesh;
ghostMesh->deepCopy(std::dynamic_pointer_cast<SurfaceMesh>(rbdObj->getPhysicsGeometry()));
rbdGhostObj->setVisualGeometry(ghostMesh);
std::shared_ptr<RenderMaterial> ghostMat = std::make_shared<RenderMaterial>(*rbdObj->getVisualModel(0)->getRenderMaterial());
ghostMat->setOpacity(0.4);
rbdGhostObj->getVisualModel(0)->setRenderMaterial(ghostMat);
scene->addSceneObject(rbdGhostObj);
imstkNew<RigidObjectCollidingCollisionPair> interaction(rbdObj, ribObj, CollisionDetection::Type::PointSetToImplicit);
{
auto colHandlerA = std::dynamic_pointer_cast<RigidBodyCH>(interaction->getCollisionHandlingA());
colHandlerA->setUseFriction(false);
colHandlerA->setStiffness(0.01); // inelastic collision
}
scene->getCollisionGraph()->addInteraction(interaction);
// Light (white)
imstkNew<DirectionalLight> whiteLight1("whiteLight1");
whiteLight1->setDirection(Vec3d(0.0, -8.0, 8.0));
whiteLight1->setIntensity(0.5);
scene->addLight(whiteLight1);
// Light (white)
imstkNew<DirectionalLight> whiteLight2("whiteLight2");
whiteLight2->setDirection(Vec3d(0.0, -8.0, -8.0));
whiteLight2->setIntensity(0.5);
scene->addLight(whiteLight2);
// Adjust camera
scene->getActiveCamera()->setFocalPoint(21.98, 34.49, -20.82);
scene->getActiveCamera()->setPosition(-215.76, 190.62, 97.96);
scene->getActiveCamera()->setViewUp(0.44, 0.86, -0.26);
{
imstkNew<VTKViewer> viewer("Viewer");
viewer->setVtkLoggerMode(VTKViewer::VTKLoggerMode::MUTE);
viewer->setActiveScene(scene);
// Add a module to run the scene
imstkNew<SceneManager> sceneManager("Scene Manager");
sceneManager->setActiveScene(scene);
sceneManager->setExecutionType(Module::ExecutionType::ADAPTIVE);
imstkNew<HapticDeviceManager> hapticManager;
hapticManager->setSleepDelay(0.5); // Delay for 1/2ms (haptics thread is limited to max 2000hz)
std::shared_ptr<HapticDeviceClient> hapticDeviceClient = hapticManager->makeDeviceClient();
imstkNew<RigidObjectController> controller(rbdObj, hapticDeviceClient);
{
controller->setLinearKd(100.0);
controller->setLinearKs(1000.0);
controller->setAngularKs(1000000.0);
controller->setAngularKd(100000.0);
controller->setForceScaling(0.0);
// The particular device we are using doesn't produce this quantity
// with this flag its computed
// in code
controller->setComputeVelocity(true);
controller->setComputeAngularVelocity(true);
controller->setTranslationScaling(1.0);
controller->setTranslationOffset(Vec3d(0.1, 0.9, 1.6));
controller->setSmoothingKernelSize(10);
scene->addController(controller);
}
connect<Event>(sceneManager, &SceneManager::postUpdate, [&](Event*)
{
rbdObj->getRigidBodyModel2()->getConfig()->m_dt = sceneManager->getDt();
// Also apply controller transform to ghost geometry
ghostMesh->setTranslation(controller->getPosition());
ghostMesh->setRotation(controller->getRotation());
ghostMesh->updatePostTransformData();
ghostMesh->postModified();
rbdObj->getCollidingToVisualMap()->apply();
rbdObj->getPhysicsToCollidingMap()->apply();
rbdObj->getVisualModel(0)->getGeometry()->postModified();
rbdObj->getVisualModel(1)->getGeometry()->postModified();
});
connect<KeyEvent>(viewer->getKeyboardDevice(), &KeyboardDeviceClient::keyPress, [&](KeyEvent* e)
{
scene->getActiveCamera()->print();
});
imstkNew<SimulationManager> driver;
driver->addModule(viewer);
driver->addModule(sceneManager);
driver->addModule(hapticManager);
driver->setDesiredDt(0.001); // Exactly 1000ups
{
imstkNew<MouseSceneControl> mouseControl(viewer->getMouseDevice());
mouseControl->setSceneManager(sceneManager);
viewer->addControl(mouseControl);
imstkNew<KeyboardSceneControl> keyControl(viewer->getKeyboardDevice());
keyControl->setSceneManager(sceneManager);
keyControl->setModuleDriver(driver);
viewer->addControl(keyControl);
}
driver->start();
}
return 0;
}
\ No newline at end of file
......@@ -45,14 +45,17 @@ public:
///
/// \brief Constructor
///
explicit VisualModel(std::shared_ptr<Geometry> geometry);
explicit VisualModel(std::shared_ptr<Geometry> geometry,
std::shared_ptr<RenderMaterial> renderMaterial);
explicit VisualModel(std::shared_ptr<DebugRenderGeometry> geometry);
explicit VisualModel(std::shared_ptr<DebugRenderGeometry> geometry,
std::shared_ptr<RenderMaterial> renderMaterial);
VisualModel() = delete;
VisualModel(std::shared_ptr<Geometry> geometry);
VisualModel(std::shared_ptr<Geometry> geometry,
std::shared_ptr<RenderMaterial> renderMaterial);
VisualModel(std::shared_ptr<DebugRenderGeometry> geometry);
VisualModel(std::shared_ptr<DebugRenderGeometry> geometry,
std::shared_ptr<RenderMaterial> renderMaterial);
VisualModel() = default;
public:
SIGNAL(VisualModel,modified);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment