Skip to content

Commit

Permalink
Added polygon angle constraints feature to QMesh for more stable soft…
Browse files Browse the repository at this point in the history
… body simulations.
  • Loading branch information
erayzesen committed Mar 15, 2024
1 parent dfd5e4e commit 9c7ae4d
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 238 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ file(GLOB SOURCE_FILES
#if(NOT CMAKE_BUILD_TYPE)
# set(CMAKE_BUILD_TYPE Release)
#endif()

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
Expand Down
119 changes: 75 additions & 44 deletions QuarkPhysics/qcollision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,9 @@
#include "qaabb.h"


QObjectPool<QCollision::Contact>* QCollision::contactPool = nullptr;

QObjectPool<QCollision::Contact> *QCollision::GetContactPool()
{
if(QCollision::contactPool==nullptr){
QCollision::contactPool=new QObjectPool<QCollision::Contact>(100);
}
return QCollision::contactPool;
}

QObjectPool<QCollision::Contact> QCollision::contactPool(100,50);



Expand Down Expand Up @@ -112,11 +106,9 @@ void QCollision::PolylineAndPolygon(vector<QParticle*> &polylineParticles, vecto


bisectorList.push_back(bisectorVector );
p->GetOwnerMesh()->GetOwnerBody()->GetWorld()->gizmos.push_back(new QGizmoLine(p->GetGlobalPosition(),p->GetGlobalPosition()+bisectorVector,true) );
//p->GetOwnerMesh()->GetOwnerBody()->GetWorld()->gizmos.push_back(new QGizmoLine(p->GetGlobalPosition(),p->GetGlobalPosition()+bisectorVector,true) );

/*
Notes: Bisector vector is working well now but it doesn't looks true. A different method is followed here.
*/




Expand Down Expand Up @@ -175,9 +167,10 @@ void QCollision::PolylineAndPolygon(vector<QParticle*> &polylineParticles, vecto
float penetration=bridgeVec.Dot(-normal);


auto contact=QCollision::GetContactPool();
/* contact->Configure(p,p->GetGlobalPosition(),normal,penetration,vector<QParticle*>{s1,s2});
contacts.push_back(contact); */

QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(p,p->GetGlobalPosition(),normal,penetration,vector<QParticle*>{s1,s2});
contacts.push_back(contact);

}
}
Expand Down Expand Up @@ -354,9 +347,10 @@ void QCollision::CircleAndPolyline(vector<QParticle *> &circleParticles, vector<

//pA->GetOwnerMesh()->GetOwnerBody()->GetWorld()->gizmos.push_back(new QGizmoCircle(pA->GetGlobalPosition(),5.0f ) );

auto contact=QCollision::GetContactPool();
/* contact->Configure( pA,pA->GetGlobalPosition(),normal,-penetration,vector<QParticle*>{ nearestSides[collidedSideIndex][0],nearestSides[collidedSideIndex][1] } );
contacts.push_back(contact) ; */

QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure( pA,pA->GetGlobalPosition(),normal,-penetration,vector<QParticle*>{ nearestSides[collidedSideIndex][0],nearestSides[collidedSideIndex][1] } );
contacts.push_back(contact) ;


}else{
Expand Down Expand Up @@ -431,9 +425,10 @@ void QCollision::CircleAndPolyline(vector<QParticle *> &circleParticles, vector<
float penetration=abs( (pA->GetRadius()*projSign)-perpProj);
QVector contactPosition=pA->GetGlobalPosition()-(pA->GetRadius()*projSign*normal);

auto contact=QCollision::GetContactPool();
/* contact->Configure(pA,contactPosition,normal,penetration,vector<QParticle*>{s1,s2});
contacts.push_back(contact); */

QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(pA,contactPosition,normal,penetration,vector<QParticle*>{s1,s2});
contacts.push_back(contact);

}
}
Expand All @@ -451,7 +446,7 @@ void QCollision::CircleAndPolyline(vector<QParticle *> &circleParticles, vector<

}

void QCollision::CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle*> &particlesB,vector<QCollision::Contact*> &contacts,float specifiedRadius){
void QCollision::CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle*> &particlesB,QAABB boundingBoxB,vector<QCollision::Contact*> &contacts,float specifiedRadius){

/*
A. Start the loop for all points of particlesA
Expand All @@ -464,20 +459,49 @@ void QCollision::CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle
float totalRadiusPow;
float radiusA;
float radiusB;
QVector bboxSizeA;

QVector distVec;
float positionalPenetrationSq;
float positionalPenetration;
float penetration;
QVector normal;
QVector contactPosition;


if(specifiedRadius!=0.0){
radiusA=specifiedRadius;
radiusB=specifiedRadius;
totalRadius=specifiedRadius+specifiedRadius;
totalRadiusPow=totalRadius*totalRadius;
bboxSizeA=QVector(specifiedRadius,specifiedRadius);
}

//A. Start the loop for all points of circleparticlesA
for(size_t i=0;i<particlesA.size();i++){
QParticle *pA=particlesA[i];

//Optimization phase: aabb test
if(particlesA.size()>1 && particlesB.size()>1 ){
if(specifiedRadius==0.0){
bboxSizeA=QVector(radiusA,radiusA);
}
QAABB boundingBoxA(pA->GetGlobalPosition()-bboxSizeA,pA->GetGlobalPosition()+bboxSizeA );

if(boundingBoxA.isCollidingWith(boundingBoxB)==false ){
continue;
}
}

//Optimization phase: reducing loop count whether the test is self collision
size_t n=0;
if(particlesA==particlesB){
n=i+1;
}


//B. Start the loop for all points of circleparticlesB
for(size_t n=0;n<particlesB.size();n++){
for(;n<particlesB.size();n++){
QParticle *pB=particlesB[n];
if(pA==pB) continue;

Expand All @@ -494,24 +518,25 @@ void QCollision::CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle
//C. Check the distance between both points


QVector distVec=pB->GetGlobalPosition()-pA->GetGlobalPosition();
float positionalPenetrationSq=distVec.LengthSquared();
distVec=pB->GetGlobalPosition()-pA->GetGlobalPosition();
positionalPenetrationSq=distVec.LengthSquared();



//D. If the distance is less than radius of these points, create a new collision data
if(positionalPenetrationSq<totalRadiusPow){
//The penetration is the difference between the existing penetration and the total radius of the objA and the objB.
float positionalPenetration=sqrt(positionalPenetrationSq);
QVector normal=distVec.Normalized();
positionalPenetration=sqrt(positionalPenetrationSq);
normal=distVec.Normalized();

float penetration=totalRadius-positionalPenetration;
penetration=totalRadius-positionalPenetration;

QVector contactPosition=pA->GetGlobalPosition()+radiusA*normal;
contactPosition=pA->GetGlobalPosition()+radiusA*normal;

auto contact=QCollision::GetContactPool();
/* contact->Configure(pB,contactPosition,normal,penetration,vector<QParticle*>{pA});
contacts.push_back(contact); */
//auto contact=QCollision::GetContactPool();
QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(pB,contactPosition,normal,penetration,vector<QParticle*>{pA});
contacts.push_back(contact);


}
Expand Down Expand Up @@ -636,27 +661,31 @@ void QCollision::CircleAndPolygon(vector<QParticle*> &circleParticles,vector<QPa
}
vector<QParticle*> refSegment={ polygonParticles[ refSegmentIndexes[0] ],polygonParticles[ refSegmentIndexes[1] ] };

auto contact=QCollision::GetContactPool();
/* contact->Configure(circleParticle,contactPosition,normal,penetration,refSegment );
contacts.push_back(contact); */


QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(circleParticle,contactPosition,normal,penetration,refSegment );
contacts.push_back(contact);

continue;


}



//D. If collision doesn't exist, make collision test with this nearest point
if(abs(penetration)<circleParticle->GetRadius()){
penetration=circleParticle->GetRadius()-abs(penetration);
QVector contactPosition=circleParticle->GetGlobalPosition();
if(circleParticle->GetRadius()>0.5f){
contactPosition-=circleParticle->GetRadius()*normal;
}
auto contact=QCollision::GetContactPool();
/* contact->Configure(circleParticle,contactPosition,normal,penetration,vector<QParticle*>{ polygonParticles[npi] } );
contacts.push_back(contact); */


QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(circleParticle,contactPosition,normal,penetration,vector<QParticle*>{ polygonParticles[npi] } );
contacts.push_back(contact);

}
}
Expand All @@ -670,8 +699,10 @@ QCollision::~QCollision()

}



QObjectPool<QCollision::Contact> &QCollision::GetContactPool()
{
return contactPool;
}

void QCollision::PolygonAndPolygon(vector<QParticle *> &particlesA, vector<QParticle *> &particlesB, vector<QCollision::Contact *> &contacts)
{
Expand Down Expand Up @@ -810,9 +841,9 @@ void QCollision::ClipContactParticles(QParticle *referenceParticles[], QParticle
if(dist<=0){
float proj=bv.Dot(unit);
if(proj>=0.0f && proj<=len){
auto contact=QCollision::GetContactPool();
/* contact->Configure(p,p->GetGlobalPosition(),normal,abs(dist), vector<QParticle*>{referenceParticles[0],referenceParticles[1]});
contacts.push_back(contact); */
QCollision::Contact *contact=QCollision::GetContactPool().Create().data;
contact->Configure(p,p->GetGlobalPosition(),normal,abs(dist), vector<QParticle*>{referenceParticles[0],referenceParticles[1]});
contacts.push_back(contact);

}
}
Expand Down
11 changes: 7 additions & 4 deletions QuarkPhysics/qcollision.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ using namespace std;
class QCollision
{
public:
QCollision();
QCollision(){}
~QCollision();


Expand Down Expand Up @@ -90,6 +90,9 @@ class QCollision

};

static QObjectPool<QCollision::Contact> contactPool;

static QObjectPool<QCollision::Contact> &GetContactPool();


struct Project{
Expand All @@ -116,8 +119,7 @@ class QCollision

};

static QObjectPool<QCollision::Contact> *contactPool;
static QObjectPool<QCollision::Contact> *GetContactPool();


//Collision Methods
/** Checks collisions between polygons.
Expand All @@ -137,7 +139,7 @@ class QCollision
* @param particlesB Another collection of particles representing one or more circles, each having a radius.
* @param contacts A collection where collision contact information will be stored.
*/
static void CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle*> &particlesB,vector<QCollision::Contact*> &contacts, float specifiedRadius=0.0f);
static void CircleAndCircle(vector<QParticle*> &particlesA,vector<QParticle*> &particlesB, QAABB boundingBoxB, vector<QCollision::Contact*> &contacts, float specifiedRadius=0.0f);
/** Checks collisions between polyline and polygon.
* @param polylineParticles A collection of particles that make up a polyline.
* @param polygonParticles Another collection of particles that make up a polygon.
Expand Down Expand Up @@ -200,4 +202,5 @@ class QCollision




#endif // QCOLLISION_H
2 changes: 1 addition & 1 deletion QuarkPhysics/qmanifold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void QManifold::Solve()



bodyA->GetWorld()->gizmos.push_back(new QGizmoCircle(contact->position,2.0f));
bodyA->GetWorld()->gizmos.push_back( new QGizmoRect( QAABB(contact->position+QVector(-0.5f,-0.5f) ,contact->position+QVector(0.5f,0.5f) ) ));



Expand Down
Loading

0 comments on commit 9c7ae4d

Please sign in to comment.