From 6b866b8833c52ff65bddf20606ce68b8a585d6f2 Mon Sep 17 00:00:00 2001 From: Thien Nguyen <thien.nguyen@kitware.com> Date: Fri, 29 Jul 2016 17:56:58 -0400 Subject: [PATCH] init some work on pbd collision --- Base/Collision/imstkPbdInteractionPair.cpp | 266 ++++++++++++++++++ Base/Collision/imstkPbdInteractionPair.h | 46 +++ .../imstkPbdCollisionConstraint.cpp | 183 ++++++++++++ Base/Constraint/imstkPbdCollisionConstraint.h | 89 ++++++ .../Objects/imstkPbdCollidingObject.cpp | 25 ++ .../Objects/imstkPbdCollidingObject.h | 72 +++++ Base/SceneElements/Objects/imstkPbdModel.cpp | 5 + Base/SceneElements/Objects/imstkPbdObject.cpp | 10 + Base/SceneElements/Objects/imstkPbdObject.h | 3 + Examples/Sandbox/main.cpp | 4 +- 10 files changed, 702 insertions(+), 1 deletion(-) create mode 100644 Base/Collision/imstkPbdInteractionPair.cpp create mode 100644 Base/Collision/imstkPbdInteractionPair.h create mode 100644 Base/Constraint/imstkPbdCollisionConstraint.cpp create mode 100644 Base/Constraint/imstkPbdCollisionConstraint.h create mode 100644 Base/SceneElements/Objects/imstkPbdCollidingObject.cpp create mode 100644 Base/SceneElements/Objects/imstkPbdCollidingObject.h diff --git a/Base/Collision/imstkPbdInteractionPair.cpp b/Base/Collision/imstkPbdInteractionPair.cpp new file mode 100644 index 00000000..c91e7c6d --- /dev/null +++ b/Base/Collision/imstkPbdInteractionPair.cpp @@ -0,0 +1,266 @@ +#include "imstkPbdInteractionPair.h" +#include "imstkSurfaceMesh.h" + +namespace imstk { + +bool isIntersect(const double& a, const double& b, const double& c, const double& d) +{ + if ( (a <= d && a >= c) || (c <= b && c >= a) ) return true; + return false; +} + +bool testAABBvsAABB(const double& min1_x, const double& max1_x, + const double& min1_y, const double& max1_y, + const double& min1_z, const double& max1_z, + const double& min2_x, const double& max2_x, + const double& min2_y, const double& max2_y, + const double& min2_z, const double& max2_z) +{ + return isIntersect(min1_x, max1_x, min2_x, max2_x) && + isIntersect(min1_y, max1_y, min2_y, max2_y) && + isIntersect(min1_z, max1_z, min2_z, max2_z); +} + +bool testLINEvsLINE(const double& x1, const double& y1, const double& z1, + const double& x2, const double& y2, const double& z2, + const double& x3, const double& y3, const double& z3, + const double& x4, const double& y4, const double& z4, + const double& prox1, const double& prox2) +{ + double min1_x, max1_x, min1_y, max1_y, min1_z, max1_z; + if ( x1 < x2 ) { min1_x = x1; max1_x = x2;} + else { min1_x = x2; max1_x = x1;} + if ( y1 < y2 ) { min1_y = y1; max1_y = y2;} + else { min1_y = y2; max1_y = y1;} + if ( z1 < z2 ) { min1_z = z1; max1_z = z2;} + else { min1_z = z2; max1_z = z1;} + double min2_x, max2_x, min2_y, max2_y, min2_z, max2_z; + if ( x3 < x4 ) { min2_x = x3; max2_x = x4;} + else { min2_x = x4; max2_x = x3;} + if ( y3 < y4 ) { min2_y = y3; max2_y = y4;} + else { min2_y = y4; max2_y = y3;} + if ( z3 < z4 ) { min2_z = z3; max2_z = z4;} + else { min2_z = z4; max2_z = z3;} + + return testAABBvsAABB(min1_x - prox1, max1_x + prox1, min1_y - prox1, max1_y + prox1, min1_z - prox1, max1_z + prox1, + min2_x - prox2, max2_x + prox2, min2_y - prox2, max2_y + prox2, min2_z - prox2, max2_z + prox2); + +} + +bool testPOINTvsTRIANGLE(const double& x1, const double& y1, const double& z1, + const double& x2, const double& y2, const double& z2, + const double& x3, const double& y3, const double& z3, + const double& x4, const double& y4, const double& z4, + const double& prox1, const double& prox2) +{ + double min_x, max_x, min_y, max_y, min_z, max_z; + min_x = std::min(x2, std::min(x3,x4)); + max_x = std::max(x2, std::max(x3,x4)); + min_y = std::min(y2, std::min(y3,y4)); + max_y = std::max(y2, std::max(y3,y4)); + min_z = std::min(z2, std::min(z3,z4)); + max_z = std::max(z2, std::max(z3,z4)); + return testAABBvsAABB(x1 - prox1, x1 + prox1, y1 - prox1, y1 + prox1, z1 - prox1, z1 + prox1, + min_x - prox2, max_x + prox2, min_y - prox2, max_y + prox2, min_z - prox2, max_z + prox2); +} + +bool PbdInteractionPair::doBroadPhase() +{ + auto g1 = first->getCollidingGeometry(); + auto g2 = second->getCollidingGeometry(); + auto mesh1 = std::static_pointer_cast<Mesh>(g1); + auto mesh2 = std::static_pointer_cast<Mesh>(g2); + Vec3d min1, max1; + mesh1->computeBoundingBox(min1, max1); + Vec3d min2, max2; + mesh2->computeBoundingBox(min2, max2); + double prox1 = first->getProximity(); + double prox2 = second->getProximity(); + return testAABBvsAABB(min1_x - prox1, max1_x + prox1, min1_y - prox1, max1_y + prox1, min1_z - prox1, max1_z + prox1, + min2_x - prox2, max2_x + prox2, min2_y - prox2, max2_y + prox2, min2_z - prox2, max2_z + prox2); + +} + +void PbdInteractionPair::doNarrowPhase() +{ + auto g1 = first->getCollidingGeometry(); + auto g2 = second->getCollidingGeometry(); + auto mesh1 = std::static_pointer_cast<SurfaceMesh>(g1); + auto mesh2 = std::static_pointer_cast<SurfaceMesh>(g2); + + double prox1 = first->getProximity(); + double prox2 = second->getProximity(); + + // brute force, use BVH or spatial grid woulbe be much better + // point + for (int i = 0; i < mesh1->getNumVertices(); ++i) { + Vec3d& p = mesh1->getVertexPosition(i); + std::vector<SurfaceMesh::TriangleArray> elements = mesh2->getTrianglesVertices(); + for (int j = 0; j < elements.size(); ++j) { + Vec3i& e = elements[j]; + Vec3d& p0 = mesh2->getVertexPosition(e[0]); + Vec3d& p1 = mesh2->getVertexPosition(e[1]); + Vec3d& p2 = mesh2->getVertexPosition(e[2]); + + if (testPOINTvsTRIANGLE(p[0],p[1],p[2], + p0[0],p0[1],p0[2], + p1[0],p1[1],p1[2], + p2[0],p2[1],p2[2], prox1, prox2)) + { + PointTriangleConstraint* c = new PointTriangleConstraint; + c->initConstraint(first, i, second, e[0], e[1], e[2]); + m_collisionConstraints.push_back(c); + } + } + } + // edge + // since we don't have edge structure, the following is not good + int nV = mesh1->getNumVertices(); + std::vector<std::vector<bool>> E(nV, std::vector<bool>(nV, 1)); + std::vector<SurfaceMesh::TriangleArray> elements = mesh1->getTrianglesVertices(); + for (int k = 0; k < elements.size(); ++k) { + Vec3i& tri = elements[k]; + unsigned int i1; + unsigned int i2; + i1 = tri[0]; + i2 = tri[1]; + if (E[i1][i2] && E[i2][i1]) { + Vec3d& P = mesh1->getVertexPosition(i1); + Vec3d& Q = mesh1->getVertexPosition(i2); + std::vector<SurfaceMesh::TriangleArray> elements2 = mesh2->getTrianglesVertices(); + for (int j = 0; j < elements2.size(); ++j) { + Vec3i& e = elements2[j]; + Vec3d& p0 = mesh2->getVertexPosition(e[0]); + Vec3d& p1 = mesh2->getVertexPosition(e[1]); + Vec3d& p2 = mesh2->getVertexPosition(e[2]); + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p0[0],p0[1],p0[2], + p1[0],p1[1],p1[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[0], e[1]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p1[0],p1[1],p1[2], + p2[0],p2[1],p2[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[1], e[2]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p2[0],p2[1],p2[2], + p0[0],p0[1],p0[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[2], e[0]); + m_collisionConstraints.push_back(c); + } + } + E[i1][i2] = 0; + } + + i1 = tri[1]; + i2 = tri[2]; + if (E[i1][i2] && E[i2][i1]) { + Vec3d& P = mesh1->getVertexPosition(i1); + Vec3d& Q = mesh1->getVertexPosition(i2); + std::vector<SurfaceMesh::TriangleArray> elements2 = mesh2->getTrianglesVertices(); + for (int j = 0; j < elements2.size(); ++j) { + Vec3i& e = elements2[j]; + Vec3d& p0 = mesh2->getVertexPosition(e[0]); + Vec3d& p1 = mesh2->getVertexPosition(e[1]); + Vec3d& p2 = mesh2->getVertexPosition(e[2]); + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p0[0],p0[1],p0[2], + p1[0],p1[1],p1[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[0], e[1]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p1[0],p1[1],p1[2], + p2[0],p2[1],p2[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[1], e[2]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p2[0],p2[1],p2[2], + p0[0],p0[1],p0[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[2], e[0]); + m_collisionConstraints.push_back(c); + } + } + E[i1][i2] = 0; + } + i1 = tri[2]; + i2 = tri[0]; + if (E[i1][i2] && E[i2][i1]) { + Vec3d& P = mesh1->getVertexPosition(i1); + Vec3d& Q = mesh1->getVertexPosition(i2); + std::vector<SurfaceMesh::TriangleArray> elements2 = mesh2->getTrianglesVertices(); + for (int j = 0; j < elements2.size(); ++j) { + Vec3i& e = elements2[j]; + Vec3d& p0 = mesh2->getVertexPosition(e[0]); + Vec3d& p1 = mesh2->getVertexPosition(e[1]); + Vec3d& p2 = mesh2->getVertexPosition(e[2]); + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p0[0],p0[1],p0[2], + p1[0],p1[1],p1[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[0], e[1]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p1[0],p1[1],p1[2], + p2[0],p2[1],p2[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[1], e[2]); + m_collisionConstraints.push_back(c); + } + if (testLINEvsLINE(P[0],P[1],P[2], + Q[0],Q[1],Q[2], + p2[0],p2[1],p2[2], + p0[0],p0[1],p0[2], prox1, prox2)) + { + EdgeEdgeConstraint* c = new EdgeEdgeConstraint; + c->initConstraint(first, i1, i2, second, e[2], e[0]); + m_collisionConstraints.push_back(c); + } + } + E[i1][i2] = 0; + } + } +} + +void PbdInteractionPair::doCollision() +{ + if (!m_collisionConstraints.empty()) { + int i = 0; + while (++i < maxIter){ + for (int k = 0; k < m_collisionConstraints.size(); ++k) { + m_collisionConstraints[k]->solvePositionConstraint(); + } + } + } +} + + + +} diff --git a/Base/Collision/imstkPbdInteractionPair.h b/Base/Collision/imstkPbdInteractionPair.h new file mode 100644 index 00000000..dca3ea9f --- /dev/null +++ b/Base/Collision/imstkPbdInteractionPair.h @@ -0,0 +1,46 @@ +#ifndef IMSTKPBDINTERACTIONPAIR_H +#define IMSTKPBDINTERACTIONPAIR_H + +#include "imstkInteractionPair.h" + +#include "imstkPbdCollisionConstraint.h" +#include "imstkPbdCollidingObject.h" + +namespace imstk { + +class PbdInteractionPair : public InteractionPair +{ +private: + std::vector<CollisionConstraint*> m_collisionConstraints; + std::shared_ptr<PbdCollidingObject> first; + std::shared_ptr<PbdCollidingObject> second; + unsigned int maxIter; +public: + PbdInteractionPair(std::shared_ptr<CollidingObject> A, + std::shared_ptr<CollidingObject> B, + CollisionDetection::Type CDType, + CollisionHandling::Type CHAType, + CollisionHandling::Type CHBType) + { + first = std::static_pointer_cast<PbdCollidingObject>(A); + second = std::static_pointer_cast<PbdCollidingObject>(B); + } + + inline void resetConstraints() + { + m_collisionConstraints.clear(); + } + + inline void setNumberOfInterations(const unsigned int& n) { maxIter = n; } + + bool doBroadPhase(); + + void doNarrowPhase(); + + void doCollision(); + +}; + +} + +#endif // IMSTKPBDINTERACTIONPAIR_H diff --git a/Base/Constraint/imstkPbdCollisionConstraint.cpp b/Base/Constraint/imstkPbdCollisionConstraint.cpp new file mode 100644 index 00000000..26f01914 --- /dev/null +++ b/Base/Constraint/imstkPbdCollisionConstraint.cpp @@ -0,0 +1,183 @@ +#include "imstkPbdCollidingObject.h" +#include "imstkPbdCollisionConstraint.h" + +namespace imstk +{ + +void EdgeEdgeConstraint::initConstraint( PbdCollidingObject* model1, const unsigned int &pIdx1, const unsigned int &pIdx2, + PbdCollidingObject* model2, const unsigned int &pIdx3, const unsigned int &pIdx4) +{ + m_model1 = model1; + m_model2 = model2; + m_bodiesFirst[0] = pIdx1; + m_bodiesFirst[1] = pIdx2; + m_bodiesSecond[0] = pIdx3; + m_bodiesSecond[1] = pIdx4; + +} + +bool EdgeEdgeConstraint::solvePositionConstraint() +{ + const unsigned int i0 = m_bodiesFirst[0]; + const unsigned int i1 = m_bodiesFirst[1]; + const unsigned int i2 = m_bodiesSecond[0]; + const unsigned int i3 = m_bodiesSecond[1]; + +// auto state1 = m_model1->getState(); +// auto state2 = m_model2->getState(); + + Vec3d x0 = m_model1->getVertexPosition(i0); + Vec3d x1 = m_model1->getVertexPosition(i1); + Vec3d x2 = m_model2->getVertexPosition(i2); + Vec3d x3 = m_model2->getVertexPosition(i3); + + double a = (x3-x2).dot(x1-x0); + double b = (x1-x0).dot(x1-x0); + double c = (x0-x2).dot(x1-x0); + double d = (x3-x2).dot(x3-x2); + double e = a; + double f = (x0-x2).dot(x3-x2); + + double det = a*e - d*b; + double s = 0.5; + double t = 0.5; + if ( fabs(det) > 1e-12 ) { + s = (c*e - b*f)/det; + t = (c*d - a*f)/det; + if (s < 0 || s > 1.0 || + t < 0 || t > 1.0) { + return false; + } + } + else { + printf("WARNING: det is null \n"); + } + + Vec3d P = x0 + t*(x1-x0); + Vec3d Q = x2 + s*(x3-x2); + + Vec3d n = Q - P; + double l = n.norm(); + n /= l; + + const double dist = m_model1->getProximity() + m_model2->getProximity(); + + if (l > dist ) + return false; + + Vec3d grad0 = -(1-t)*n; + Vec3d grad1 = -(t)*n; + Vec3d grad2 = (1-s)*n; + Vec3d grad3 = (s)*n; + + const double im0 = m_model1->getInvMass(i0); + const double im1 = m_model1->getInvMass(i1); + const double im2 = m_model2->getInvMass(i2); + const double im3 = m_model2->getInvMass(i3); + + double lambda = im0*grad0.squaredNorm() + im1*grad1.squaredNorm() + im2*grad2.squaredNorm() + im3*grad3.squaredNorm(); + + lambda = (l - dist)/lambda; + + if (im0 > 0) + x0 += -im0*lambda*grad0*m_model1->getContactStiffness(); + if (im1 > 0) + x1 += -im1*lambda*grad1*m_model1->getContactStiffness(); + if (im2 > 0) + x2 += -im2*lambda*grad2*m_model2->getContactStiffness(); + if (im3 > 0) + x3 += -im3*lambda*grad3*m_model2->getContactStiffness(); + + m_model1->setVertexPosition(i0,x0); + m_model1->setVertexPosition(i1,x1); + + m_model2->setVertexPosition(i2,x2); + m_model2->setVertexPosition(i3,x3); + + return true; +} + +void PointTriangleConstraint::initConstraint(PbdCollidingObject* model1, const unsigned int &pIdx1, + PbdCollidingObject* model2, const unsigned int &pIdx2, const unsigned int &pIdx3, const unsigned int &pIdx4) +{ + m_model1 = model1; + m_model2 = model2; + m_bodiesFirst[0] = pIdx1; + m_bodiesSecond[0] = pIdx2; + m_bodiesSecond[1] = pIdx3; + m_bodiesSecond[2] = pIdx4; +} + +bool PointTriangleConstraint::solvePositionConstraint() +{ + const unsigned int i0 = m_bodiesFirst[0]; + const unsigned int i1 = m_bodiesSecond[0]; + const unsigned int i2 = m_bodiesSecond[1]; + const unsigned int i3 = m_bodiesSecond[2]; + +// auto state1 = m_model1->getState(); +// auto state2 = m_model2->getState(); + + Vec3d x0 = m_model1->getVertexPosition(i0); + + Vec3d x1 = m_model2->getVertexPosition(i1); + Vec3d x2 = m_model2->getVertexPosition(i2); + Vec3d x3 = m_model2->getVertexPosition(i3); + + Vec3d x12 = x2 - x1; + Vec3d x13 = x3 - x1; + Vec3d n = x12.cross(x13); + Vec3d x01 = x0 - x1; + + double alpha = n.dot(x12.cross(x01))/ (n.dot(n)); + double beta = n.dot(x01.cross(x13))/ (n.dot(n)); + + if (alpha < 0 || beta < 0 || alpha + beta > 1 ) { +// printf("WARNING: barycentric coordinate out of bounds ! \n"); + return false; + } + + const double dist = m_model1->getProximity() + m_model2->getProximity(); + + n.normalize(); + + double l = x01.dot(n); + + if (l > dist) + return false; + + double gamma = 1.0 - alpha - beta; + Vec3d grad0 = n; + Vec3d grad1 = -alpha*n; + Vec3d grad2 = -beta*n; + Vec3d grad3 = -gamma*n; + + const double im0 = m_model1->getInvMass(i0); + + const double im1 = m_model2->getInvMass(i1); + const double im2 = m_model2->getInvMass(i2); + const double im3 = m_model2->getInvMass(i3); + + double lambda = im0*grad0.squaredNorm() + im1*grad1.squaredNorm() + im2*grad2.squaredNorm() + im3*grad3.squaredNorm(); + + lambda = (l - dist)/lambda; + + if (im0 > 0) + x0 += -im0*lambda*grad0*m_model1->getContactStiffness(); + if (im1 > 0) + x1 += -im1*lambda*grad1*m_model2->getContactStiffness(); + if (im2 > 0) + x2 += -im2*lambda*grad2*m_model2->getContactStiffness(); + if (im3 > 0) + x3 += -im3*lambda*grad3*m_model2->getContactStiffness(); + + m_model1->setVertexPosition(i0,x0); + + m_model2->setVertexPosition(i1,x1); + m_model2->setVertexPosition(i2,x2); + m_model2->setVertexPosition(i3,x3); + + return true; +} + +} diff --git a/Base/Constraint/imstkPbdCollisionConstraint.h b/Base/Constraint/imstkPbdCollisionConstraint.h new file mode 100644 index 00000000..fcde00d7 --- /dev/null +++ b/Base/Constraint/imstkPbdCollisionConstraint.h @@ -0,0 +1,89 @@ +#ifndef IMSTKPBDCOLLISIONCONSTRAINT_H +#define IMSTKPBDCOLLISIONCONSTRAINT_H + +#include <vector> + +namespace imstk +{ + +class PbdCollidingObject; + +class CollisionConstraint +{ +public: + enum class Type + { + EdgeEdge, + PointTriangle + }; + std::vector<unsigned int> m_bodiesFirst; // index of points for the first object + std::vector<unsigned int> m_bodiesSecond; // index of points for the second object + PbdCollidingObject* m_model1; + PbdCollidingObject* m_model2; +public: + CollisionConstraint(const unsigned int& n1, const unsigned int& n2) + { + m_bodiesFirst.resize(n1); + m_bodiesSecond.resize(n2); + } + virtual bool solvePositionConstraint() + { + return true; + } +}; + +/// +/// \brief The EdgeEdgeConstraint class for edge-edge collision response +/// + +class EdgeEdgeConstraint : public CollisionConstraint +{ + +public: + EdgeEdgeConstraint() : CollisionConstraint(2,2) {} + + Type getType() const { return Type::EdgeEdge; } + /// + /// \brief initialize constraint + /// \param pIdx1 first point of the edge from object1 + /// \param pIdx2 second point of the edge from object1 + /// \param pIdx3 first point of the edge from object2 + /// \param pIdx4 second point of the edge from object2 + /// \return true if succeeded + /// + void initConstraint( PbdCollidingObject* model1, const unsigned int& pIdx1, const unsigned int& pIdx2, + PbdCollidingObject* model2, const unsigned int& pIdx3, const unsigned int& pIdx4); + + bool solvePositionConstraint(); +}; + +/// +/// \brief The PointTriangleConstraint class for point-triangle collision response +/// + + +class PointTriangleConstraint : public CollisionConstraint +{ + +public: + PointTriangleConstraint() : CollisionConstraint(1,3) {} + + Type getType() const { return Type::PointTriangle; } + /// + /// \brief initialize constraint + /// \param pIdx1 index of the point from object1 + /// \param pIdx2 first point of the triangle from object2 + /// \param pIdx3 second point of the triangle from object2 + /// \param pIdx4 third point of the triangle from object2 + /// \return + /// + void initConstraint( PbdCollidingObject* model1, const unsigned int& pIdx1, + PbdCollidingObject* model2, const unsigned int& pIdx2, const unsigned int& pIdx3, const unsigned int& pIdx4); + + bool solvePositionConstraint(); +}; + +} + + +#endif // IMSTKPBDCOLLISIONCONSTRAINT_H diff --git a/Base/SceneElements/Objects/imstkPbdCollidingObject.cpp b/Base/SceneElements/Objects/imstkPbdCollidingObject.cpp new file mode 100644 index 00000000..53370a36 --- /dev/null +++ b/Base/SceneElements/Objects/imstkPbdCollidingObject.cpp @@ -0,0 +1,25 @@ +#include "imstkPbdCollidingObject.h" +#include "imstkMesh.h" + +namespace imstk { + +void PbdCollidingObject::setCollidingGeometry(std::shared_ptr<Geometry> geometry) +{ + m_collidingGeometry = geometry; + auto mesh = std::static_pointer_cast<Mesh>(m_collidingGeometry); + m_invMass.resize(mesh->getNumVertices()); +} + +Vec3d PbdCollidingObject::getVertexPosition(const unsigned int &idx) +{ + auto mesh = std::static_pointer_cast<Mesh>(m_collidingGeometry); + return mesh->getVertexPosition(idx); +} + +void PbdCollidingObject::setVertexPosition(const unsigned int &idx, const Vec3d &v) +{ + auto mesh = std::static_pointer_cast<Mesh>(m_collidingGeometry); + mesh->setVerticePosition(idx,v); +} + +} diff --git a/Base/SceneElements/Objects/imstkPbdCollidingObject.h b/Base/SceneElements/Objects/imstkPbdCollidingObject.h new file mode 100644 index 00000000..7fd2fe71 --- /dev/null +++ b/Base/SceneElements/Objects/imstkPbdCollidingObject.h @@ -0,0 +1,72 @@ +#ifndef IMSTKPBDCOLLIDINGOBJECT_H +#define IMSTKPBDCOLLIDINGOBJECT_H + +#include "imstkCollidingObject.h" + +namespace imstk { + +class PbdCollidingObject : public CollidingObject +{ +protected: + double m_proximity; + double m_contactStiffness; + std::vector<double> m_invMass; +public: + PbdCollidingObject(std::string name) + : CollidingObject(name) + { + + } + + ~ PbdCollidingObject() = default; + + inline void setProximity(const double& prox) + { + m_proximity = prox; + } + + inline double getProximity() + { + return m_proximity; + } + + inline void setContactStiffness(const double& stiffness) + { + m_contactStiffness = stiffness; + } + + inline double getContactStiffness() + { + return m_contactStiffness; + } + + inline double getInvMass(const unsigned int& idx) + { + // should check bounds, but ignore for now due to bad design! + return m_invMass[idx]; + } + + inline void setUniformMass(const double& val) + { + if (val >= 0) + { + std::fill(m_invMass.begin(), m_invMass.end(), val); + } + } + + inline void setFixedPoint(const unsigned int& idx) + { + // should check bounds, but ignore for now due to bad design! + m_invMass[idx] = 0; + } + + void setCollidingGeometry(std::shared_ptr<Geometry> geometry); + + Vec3d getVertexPosition(const unsigned int& idx); + + void setVertexPosition(const unsigned int& idx, const Vec3d& v); +}; + +} + +#endif // IMSTKPBDCOLLIDINGOBJECT_H diff --git a/Base/SceneElements/Objects/imstkPbdModel.cpp b/Base/SceneElements/Objects/imstkPbdModel.cpp index 1e4b1db8..ab82aab8 100644 --- a/Base/SceneElements/Objects/imstkPbdModel.cpp +++ b/Base/SceneElements/Objects/imstkPbdModel.cpp @@ -17,6 +17,7 @@ bool PositionBasedModel::initConstraints(PbdConstraint::Type type) LOG(WARNING) << "FEM Tetrahedral constraint should come with tetrahedral mesh"; return false; } + LOG(INFO) << "Creating FEM constraints"; // ok, now create constraints auto tetMesh = static_cast<TetrahedralMesh*>(m_mesh); std::vector<TetrahedralMesh::TetraArray> elements = tetMesh->getTetrahedraVertices(); @@ -35,6 +36,7 @@ bool PositionBasedModel::initConstraints(PbdConstraint::Type type) LOG(WARNING) << "Volume constraint should come with volumetric mesh"; return false; } + LOG(INFO) << "Creating Volume constraints"; // ok, now create constraints auto tetMesh = static_cast<TetrahedralMesh*>(m_mesh); std::vector<TetrahedralMesh::TetraArray> elements = tetMesh->getTetrahedraVertices(); @@ -53,6 +55,7 @@ bool PositionBasedModel::initConstraints(PbdConstraint::Type type) LOG(WARNING) << "Area constraint should come with a triangular mesh"; return false; } + LOG(INFO) << "Creating Area constraints"; // ok, now create constraints auto triMesh = static_cast<SurfaceMesh*>(m_mesh); std::vector<SurfaceMesh::TriangleArray> elements = triMesh->getTrianglesVertices(); @@ -71,6 +74,7 @@ bool PositionBasedModel::initConstraints(PbdConstraint::Type type) LOG(WARNING) << "Dihedral constraint should come with a triangular mesh"; return false; } + LOG(INFO) << "Creating Dihedral constraints"; // ok, now create constraints auto triMesh = static_cast<SurfaceMesh*>(m_mesh); std::vector<SurfaceMesh::TriangleArray> elements = triMesh->getTrianglesVertices(); @@ -158,6 +162,7 @@ bool PositionBasedModel::initConstraints(PbdConstraint::Type type) break; } case PbdConstraint::Type::Distance : { + LOG(INFO) << "Creating Distance constraints"; if (m_mesh->getType() == Geometry::Type::TetrahedralMesh) { auto tetMesh = static_cast<TetrahedralMesh*>(m_mesh); int nV = tetMesh->getNumVertices(); diff --git a/Base/SceneElements/Objects/imstkPbdObject.cpp b/Base/SceneElements/Objects/imstkPbdObject.cpp index d35b226b..829d893a 100644 --- a/Base/SceneElements/Objects/imstkPbdObject.cpp +++ b/Base/SceneElements/Objects/imstkPbdObject.cpp @@ -27,6 +27,16 @@ PbdObject::setPhysicsToCollidingMap(std::shared_ptr<GeometryMap> map) m_physicsToCollidingGeomMap = map; } +std::shared_ptr<GeometryMap> PbdObject::getCollidingToPhysicsMap() const +{ + return m_collidingToPhysicsGeomMap; +} + +void PbdObject::setCollidingToPhysicsMap(std::shared_ptr<GeometryMap> map) +{ + m_collidingToPhysicsGeomMap = map; +} + std::shared_ptr<GeometryMap> PbdObject::getPhysicsToVisualMap() const { diff --git a/Base/SceneElements/Objects/imstkPbdObject.h b/Base/SceneElements/Objects/imstkPbdObject.h index 5e5577b9..43f96d1c 100644 --- a/Base/SceneElements/Objects/imstkPbdObject.h +++ b/Base/SceneElements/Objects/imstkPbdObject.h @@ -34,6 +34,8 @@ public: std::shared_ptr<GeometryMap> getPhysicsToCollidingMap() const; void setPhysicsToCollidingMap(std::shared_ptr<GeometryMap> map); + std::shared_ptr<GeometryMap> getCollidingToPhysicsMap() const; + void setCollidingToPhysicsMap(std::shared_ptr<GeometryMap> map); /// /// \brief Set/Get the Physics-to-Visual map /// @@ -65,6 +67,7 @@ protected: //Maps std::shared_ptr<GeometryMap> m_physicsToCollidingGeomMap; ///> Maps from Physics to collision geometry + std::shared_ptr<GeometryMap> m_collidingToPhysicsGeomMap; ///> Maps from Physics to collision geometry std::shared_ptr<GeometryMap> m_physicsToVisualGeomMap; ///> Maps from Physics to visual geometry size_t numDOF; ///> Number of degree of freedom of the body in the discretized model diff --git a/Examples/Sandbox/main.cpp b/Examples/Sandbox/main.cpp index 0d76006d..fbca62db 100644 --- a/Examples/Sandbox/main.cpp +++ b/Examples/Sandbox/main.cpp @@ -72,6 +72,7 @@ void testSurfaceMeshOptimizer(); void testDeformableBody(); void testPbdVolume(); void testPbdCloth(); +void testPbdCollision(); int main() { std::cout << "****************\n" @@ -95,7 +96,8 @@ int main() //testSurfaceMeshOptimizer(); // testDeformableBody(); // testPbdVolume(); - testPbdCloth(); +// testPbdCloth(); + testPbdCollision(); return 0; } -- GitLab