Warning, file /education/step/stepcore/collisionsolver.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /** \file collisionsolver.h 0008 * \brief CollisionSolver interface 0009 */ 0010 0011 #ifndef STEPCORE_COLLISIONSOLVER_H 0012 #define STEPCORE_COLLISIONSOLVER_H 0013 0014 #include "object.h" 0015 #include "world.h" 0016 #include "vector.h" 0017 #include "solver.h" 0018 0019 #define EIGEN_USE_NEW_STDVECTOR 0020 #include <Eigen/StdVector> 0021 0022 namespace StepCore 0023 { 0024 0025 class BasePolygon; 0026 class Body; 0027 0028 /** \ingroup contacts 0029 * \brief Description of contact between two bodies 0030 */ 0031 struct Contact { 0032 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 0033 0034 enum { 0035 Unknown = 0, /**< Contact state was not (can not) be determined 0036 (if state == Unknown all other fields are not used) */ 0037 Separated, /**< Bodies are far away */ 0038 Separating, /**< Bodies are contacted but moving apart */ 0039 Contacted, /**< Bodies are contacted but resting */ 0040 Colliding, /**< Bodies are colliding */ 0041 Intersected /**< Bodies are interpenetrating */ 0042 }; 0043 enum { 0044 UnknownType, 0045 PolygonPolygonType, 0046 PolygonDiskType, 0047 PolygonParticleType, 0048 DiskDiskType, 0049 DiskParticleType 0050 }; 0051 int type; /**< Contact type (used internally) */ 0052 Body* body0; /**< Body0 */ 0053 Body* body1; /**< Body1 */ 0054 int state; /**< Contact state (maximum of pointsState if pointsCount > 0) */ 0055 double distance; /**< Distance between bodies */ 0056 Vector2d normal; /**< Contact normal (pointing from body0 to body1) */ 0057 Vector2d normalDerivative; /**< Time derivative of contact normal (only if state == Contacted) */ 0058 int pointsCount; /**< Count of contact points (either one or two) */ 0059 int pointsState[2];/**< Contact point states */ 0060 Vector2d points[2]; /**< Contact point coordinated */ 0061 double vrel[2]; /**< Relative velocities at contact points */ 0062 0063 // Cached values from previous run 0064 // TODO: move it to GJK-specific derived struct 0065 int _w1[2]; 0066 }; 0067 0068 /** \ingroup contacts 0069 * \brief Collision solver interface 0070 * 0071 * Provides generic interface for collision solvers. 0072 */ 0073 class CollisionSolver : public Object 0074 { 0075 STEPCORE_OBJECT(CollisionSolver) 0076 0077 public: 0078 CollisionSolver(): _toleranceAbs(0.001), _localError(0) {} 0079 virtual ~CollisionSolver() {} 0080 0081 /** Get absolute allowed tolerance */ 0082 double toleranceAbs() const { return _toleranceAbs; } 0083 /** Set absolute allowed tolerance */ 0084 virtual void setToleranceAbs(double toleranceAbs) { _toleranceAbs = toleranceAbs; } 0085 /** Get error estimation from last step */ 0086 double localError() const { return _localError; } 0087 0088 /** <!--Check (and update) state of the contact 0089 * \param contact contact to check (only body0 and body1 fields must be set) 0090 * \return state of the contact (equals to contact->state)--> 0091 */ 0092 //virtual int checkContact(Contact* contact) = 0; 0093 0094 /** Check and count contacts between several bodies 0095 * \param bodies list of bodies to check 0096 * \param collisions defines whether body collisions are taken into account 0097 * \param count number of contacts 0098 * \return maximum contact state (i.e. maximum value of Contact::state) 0099 */ 0100 virtual int checkContacts(BodyList& bodies, bool collisions = false, int* count = nullptr) = 0; 0101 0102 /** Fill the constraint info structure with the contacts computed by checkContacts() 0103 * \param info ConstraintsInfo structure to fill 0104 * \param collisions defines whether body collisions are taken into account 0105 */ 0106 virtual void getContactsInfo(ConstraintsInfo& info, bool collisions = false) = 0; 0107 0108 // TODO: add errors 0109 /** Solve the collisions between bodies 0110 */ 0111 virtual int solveCollisions(BodyList& bodies) = 0; 0112 0113 /** Reset internal caches of collision information 0114 * @todo do it automatically by checking the cache 0115 */ 0116 virtual void resetCaches() {} 0117 0118 virtual void bodyAdded(BodyList&, Body*) {} 0119 virtual void bodyRemoved(BodyList&, Body*) {} 0120 0121 public: 0122 enum { 0123 InternalError = Solver::CollisionError 0124 }; 0125 0126 protected: 0127 double _toleranceAbs; 0128 //double _toleranceRel; 0129 double _localError; 0130 }; 0131 0132 typedef std::vector<Contact, Eigen::aligned_allocator<Contact> > 0133 ContactValueList; 0134 0135 /** \ingroup contacts 0136 * \brief Discrete collision solver using Gilbert-Johnson-Keerthi distance algorithm 0137 * 0138 * Objects are treated as colliding if distance between them is greater than zero 0139 * but smaller than certain small value. If distance is less than zero objects are 0140 * always treated as interpenetrating - this signals World::doEvolve to invalidate 0141 * current time step and try with smaller stepSize until objects are colliding but 0142 * not interpenetrating. 0143 */ 0144 class GJKCollisionSolver : public CollisionSolver 0145 { 0146 STEPCORE_OBJECT(GJKCollisionSolver) 0147 0148 public: 0149 GJKCollisionSolver() : _contactsIsValid(false) {} 0150 0151 // TODO: proper copying of the cache ! 0152 GJKCollisionSolver(const GJKCollisionSolver& solver) 0153 : CollisionSolver(solver), _contactsIsValid(false) {} 0154 GJKCollisionSolver& operator=(const GJKCollisionSolver&) { 0155 _contactsIsValid = false; return *this; } 0156 0157 /* 0158 enum { 0159 OK = 0, 0160 CollisionDetected = 4096, 0161 PenetrationDetected = 4097 0162 };*/ 0163 0164 /** 0165 * \param bodies list of bodies to check 0166 * \param collisions defines whether body collisions are taken into account 0167 * \param count number of contacts 0168 */ 0169 int checkContacts(BodyList& bodies, bool collisions = false, int* count = nullptr) override; 0170 /** 0171 * \param info ConstraintsInfo structure to fill 0172 * \param collisions defines whether body collisions are taken into account 0173 */ 0174 void getContactsInfo(ConstraintsInfo& info, bool collisions = false) override; 0175 //int findClosestPoints(const BasePolygon* polygon1, const BasePolygon* polygon2); 0176 0177 int solveCollisions(BodyList& bodies) override; 0178 //int solveConstraints(BodyList& bodies); 0179 0180 void resetCaches() override; 0181 void bodyAdded(BodyList& bodies, Body* body) override; 0182 void bodyRemoved(BodyList& bodies, Body* body) override; 0183 0184 protected: 0185 int checkContact(Contact* contact); 0186 0187 int checkPolygonPolygon(Contact* contact); 0188 int solvePolygonPolygon(Contact* contact); 0189 0190 int checkPolygonParticle(Contact* contact); 0191 int solvePolygonParticle(Contact* contact); 0192 0193 int checkPolygonDisk(Contact* contact); 0194 int solvePolygonDisk(Contact* contact); 0195 0196 int checkDiskDisk(Contact* contact); 0197 int solveDiskDisk(Contact* contact); 0198 0199 int checkDiskParticle(Contact* contact); 0200 int solveDiskParticle(Contact* contact); 0201 0202 void addContact(Body* body0, Body* body1); 0203 void checkCache(BodyList& bodies); 0204 0205 protected: 0206 ContactValueList _contacts; 0207 bool _contactsIsValid; 0208 }; 0209 0210 } // namespace StepCore 0211 0212 #endif 0213