7 #include "imstkCellMesh.h" 8 #include "imstkLogger.h" 9 #include "imstkPbdModel.h" 10 #include "imstkPbdModelConfig.h" 11 #include "imstkPbdObject.h" 12 #include "imstkPointSet.h" 16 std::shared_ptr<PbdModel>
27 if (body->bodyType == PbdBody::Type::RIGID)
36 CHECK(pointSet !=
nullptr) <<
"PbdObject " <<
m_name <<
" only supports PointSet geometries";
43 auto functors =
m_pbdModel->getConfig()->getFunctors();
44 for (
auto& functorArray : functors)
46 for (
auto& functor : functorArray.second)
48 if (
auto bodyFunctor = std::dynamic_pointer_cast<PbdBodyConstraintFunctor>(functor))
50 if (bodyFunctor->m_bodyIndex == body->bodyHandle)
53 CHECK(pointSet !=
nullptr) <<
54 "Tried to generate constraints with functor on PbdObject " <<
m_name <<
" but " 55 " object does not have PointSet geometry";
56 bodyFunctor->setGeometry(pointSet);
69 LOG(FATAL) <<
"PbdObject " <<
m_name <<
" was not given a PbdModel. Please PbdObject::setDynamicalModel";
95 "PbdObject has a PbdBody but cannot find associated PbdModel?";
105 <<
"\" expects a physics geometry, none was provided";
109 if (
m_pbdBody->bodyType == PbdBody::Type::RIGID)
129 setOrAllocate(std::shared_ptr<T>& bodyArrPtr,
130 std::shared_ptr<PointSet> pointSet,
const std::string& attributeName,
131 typename T::ValueType initValue)
134 std::shared_ptr<AbstractDataArray> velocities = pointSet->getVertexAttribute(attributeName);
135 if (velocities !=
nullptr 136 && velocities->getNumberOfComponents() == T::NumComponents
137 && velocities->getScalarType() == IMSTK_DOUBLE
138 && std::dynamic_pointer_cast<T>(velocities)->size() == pointSet->getNumVertices())
140 bodyArrPtr = std::dynamic_pointer_cast<T>(velocities);
145 bodyArrPtr = std::make_shared<T>(pointSet->getNumVertices());
146 bodyArrPtr->fill(initValue);
147 pointSet->setVertexAttribute(attributeName, bodyArrPtr);
154 body.vertices = geom->getVertexPositions();
155 body.prevVertices = std::make_shared<VecDataArray<double, 3>>(*body.vertices);
157 const int numParticles = body.vertices->size();
162 std::shared_ptr<AbstractDataArray> masses = geom->getVertexAttribute(
"Mass");
163 if (masses !=
nullptr && masses->getNumberOfComponents() == 1
164 && masses->getScalarType() == IMSTK_DOUBLE && masses->size() == numParticles)
167 body.invMasses->resize(body.masses->size());
168 for (
int i = 0; i < body.masses->size(); i++)
170 (*body.invMasses)[i] = ((*body.masses)[i] == 0.0) ? 0.0 : 1.0 / (*body.masses)[i];
177 body.masses = std::make_shared<DataArray<double>>(numParticles);
178 body.invMasses = std::make_shared<DataArray<double>>(numParticles);
184 geom->setVertexAttribute(
"Mass", body.masses);
186 geom->setVertexAttribute(
"InvMass", body.invMasses);
189 setOrAllocate(body.velocities, geom,
"Velocities", Vec3d::Zero());
196 body.inertias = std::make_shared<StdVectorOfMat3d>(numParticles);
197 body.invInertias = std::make_shared<StdVectorOfMat3d>(numParticles);
199 std::fill(body.inertias->begin(), body.inertias->end(), Mat3d::Identity());
200 std::fill(body.invInertias->begin(), body.invInertias->end(), Mat3d::Identity());
207 auto orientations = std::dynamic_pointer_cast<
VecDataArray<double, 4>>(geom->getVertexAttribute(
"Orientations"));
208 if (orientations !=
nullptr && orientations->size() == numParticles)
210 body.orientations = std::make_shared<StdVectorOfQuatd>(numParticles);
211 for (
int i = 0; i < orientations->size(); i++)
213 (*body.orientations)[i] = Quatd((*orientations)[i][0], (*orientations)[i][1],
214 (*orientations)[i][2], (*orientations)[i][3]);
219 body.orientations = std::make_shared<StdVectorOfQuatd>(numParticles, Quatd::Identity());
222 body.prevOrientations = std::make_shared<StdVectorOfQuatd>(*body.orientations);
224 setOrAllocate(body.angularVelocities, geom,
"AngularVelocities", Vec3d::Zero());
232 CHECK(i < numParticles && i >= 0) <<
"Tried to fix particle " << i
233 <<
" but there only exist " << numParticles <<
" particles";
242 template<
typename ArrPtrType,
typename ValueType>
244 setOrAllocateRigid(ArrPtrType& array,
const ValueType val)
246 using ArrType =
typename ArrPtrType::element_type;
248 if (array !=
nullptr)
251 if (array->size() == 0)
259 array = std::make_shared<ArrType>(1);
268 setOrAllocateRigid(body.vertices, Vec3d::Zero());
269 body.prevVertices = std::make_shared<VecDataArray<double, 3>>(*body.vertices);
272 body.masses = std::make_shared<DataArray<double>>();
273 body.invMasses = std::make_shared<DataArray<double>>();
277 setOrAllocateRigid(body.velocities, Vec3d::Zero());
278 setOrAllocateRigid(body.inertias, Mat3d::Identity());
279 body.invInertias = std::make_shared<StdVectorOfMat3d>();
280 *body.invInertias = { (*body.inertias)[0].inverse() };
282 setOrAllocateRigid(body.orientations, Quatd::Identity());
283 body.prevOrientations = std::make_shared<StdVectorOfQuatd>(*body.orientations);
284 setOrAllocateRigid(body.angularVelocities, Vec3d::Zero());
297 <<
"\" requires physics geometry to compute CellConstraint map";
300 if (
m_pbdBody->cellConstraintMap.empty() ==
false)
303 LOG(INFO) <<
"PbdObject \"" <<
m_name 304 <<
"\" already has a CellConstraintMap. Cleared and recalculated \n";
312 auto cellVerts = std::dynamic_pointer_cast<
DataArray<int>>(cellMesh->getAbstractCells());
316 std::shared_ptr<PbdConstraintContainer> constraintsPtr = this->
getPbdModel()->getConstraints();
317 CHECK(constraintsPtr !=
nullptr) <<
"PbdObject \"" <<
m_name 318 <<
"\" does not have constraints in computeCellConstraintMap";
320 const std::vector<std::shared_ptr<PbdConstraint>>& constraints = constraintsPtr->getConstraints();
323 std::vector<int> cellVertIds(vertsPerCell);
324 for (
int cellId = 0; cellId < cellMesh->getNumCells(); cellId++)
328 for (
int vertId = 0; vertId < vertsPerCell; vertId++)
330 cellVertIds[vertId] = (*cellVerts)[cellId * vertsPerCell + vertId];
334 for (
auto& constraint : constraints)
336 const std::vector<PbdParticleId>& cVertexIds = constraint->getParticles();
337 std::unordered_set<int> constraintVertIds;
341 for (
int cVertId = 0; cVertId < cVertexIds.size(); cVertId++)
343 if (cVertexIds[cVertId].first == bodyId)
345 constraintVertIds.insert(cVertexIds[cVertId].second);
355 for (
int cellVertId = 0; cellVertId < vertsPerCell; cellVertId++)
357 std::unordered_set<int>::const_iterator indx = constraintVertIds.find(cellVertIds[cellVertId]);
359 if (indx != constraintVertIds.end())
363 for (
int j = 0; j <
m_pbdBody->cellConstraintMap[cellId].size(); j++)
365 if (constraint ==
m_pbdBody->cellConstraintMap[cellId][j])
372 std::shared_ptr<PbdConstraint> cpy = constraint;
373 m_pbdBody->cellConstraintMap[cellId].push_back(std::move(cpy));
Represents a pbd body in the model. This is a data only object. It does no function. PbdBody can be of different types. The types effect what properties it has.
This class implements the position based dynamics model. The PbdModel is a constraint based model tha...
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
void setDeformBodyFromGeometry(PbdBody &body, std::shared_ptr< PointSet > geom)
Creates a deformable PbdBody from Geometry.
virtual int getNumberOfComponents() const override
Returns the number of components.
std::shared_ptr< PbdModel > getPbdModel()
std::shared_ptr< PbdBody > m_pbdBody
Handle to this object in the model/system.
std::unordered_map< int, double > fixedNodeInvMass
Map for archiving fixed nodes' mass.
bool initialize() override
Initialize the Pbd scene object.
Simple dynamic array implementation that also supports event posting and viewing/facade.
void setBodyFromGeometry()
Sets the PbdBody representing this object given its geometry.
virtual void updatePhysicsGeometry()
Update only the physics geometry and apply collision map.
std::vector< int > fixedNodeIds
Nodal/vertex IDs of the nodes that are fixed.
bool initialize() override
Initialize the scene object.
std::shared_ptr< AbstractDynamicalModel > m_dynamicalModel
Dynamical model.
std::shared_ptr< PbdModel > m_pbdModel
Pbd mathematical model.
void computeCellConstraintMap()
std::shared_ptr< PbdBody > getPbdBody()
Returns body in the model.
void updateGeometries() final
Update the physics geometry and the apply the maps (if defined)
void setDynamicalModel(std::shared_ptr< AbstractDynamicalModel > dynaModel) override
Sets the model, and creates the body within the model.
std::shared_ptr< Geometry > getPhysicsGeometry() const
Set/Get the geometry used for Physics computations.
void setRigidBody(PbdBody &body)
Creates a rigid PbdBody from values.
void updatePhysicsGeometry() override
Update physics geometry, overrided to set transform should the PbdObject be a rigid body...
double uniformMassValue
Mass properties, not used if per vertex masses are given in geometry attributes.
std::string m_name
Not unique name.
bool getOriented() const
The body should have orientations if its DEFORMABLE_ORIENTED or RIGID.
std::shared_ptr< Geometry > m_physicsGeometry
Geometry used for Physics.
Provides non templated base for cell based meshes.