diff --git a/src/QuarkPhysics/qbody.cpp b/src/QuarkPhysics/qbody.cpp index 15fdf12..fc02cc5 100644 --- a/src/QuarkPhysics/qbody.cpp +++ b/src/QuarkPhysics/qbody.cpp @@ -246,7 +246,17 @@ void QBody::UpdateMeshTransforms(){ } - +void QBody::Update() +{ + for (auto mesh: _meshes){ + for(size_t i=0;iGetParticleCount();++i ){ + QParticle *particle=mesh->GetParticleAt(i); + if (particle->GetOneTimeCollisionEnabled()==true ){ + particle->ResetOneTimeCollisions(); + } + } + } +} bool QBody::CanGiveCollisionResponseTo(QBody *otherBody) { diff --git a/src/QuarkPhysics/qbody.h b/src/QuarkPhysics/qbody.h index 213d15e..eaaaacd 100644 --- a/src/QuarkPhysics/qbody.h +++ b/src/QuarkPhysics/qbody.h @@ -128,7 +128,7 @@ class QBody{ void UpdateAABB(); void UpdateMeshTransforms(); /** Updates properties of the soft body and applies needed physical dynamics. */ - virtual void Update(){}; + virtual void Update(); /** Called after all bodies have completed their Update step to perform post-update operations. */ virtual void PostUpdate(){}; virtual bool CanGiveCollisionResponseTo(QBody *otherBody); diff --git a/src/QuarkPhysics/qmanifold.cpp b/src/QuarkPhysics/qmanifold.cpp index 840c2f5..841f41d 100644 --- a/src/QuarkPhysics/qmanifold.cpp +++ b/src/QuarkPhysics/qmanifold.cpp @@ -127,6 +127,8 @@ void QManifold::Solve() for(int i=0;ipenetration*=0.75f; }else if(betweenPressuredSoftbodies){ @@ -152,6 +154,12 @@ void QManifold::Solve() QBody *incidentBody=contact->particle->GetOwnerMesh()->GetOwnerBody(); + + + + + + QRigidBody *refRigidBody=nullptr; QRigidBody *incRigidBody=nullptr; @@ -211,15 +219,67 @@ void QManifold::Solve() } - + //Exceptions of Returns of Events. if(collisionEnabledByRef==false || collisionEnabledByInc==false){ cancelSolving=true; } + + if(cancelSolving==true) + continue; + + + //Exceptions of Disabled Particles + if(contact->particle->GetEnabled()==false ) + continue; + + for (size_t n=0;nreferenceParticles.size();++n ){ + if (contact->referenceParticles[n]->GetEnabled()==false ){ + cancelSolving=true; + break; + } + + } + + if(cancelSolving==true) + continue; + + + + + + + + //Exceptions of the One Time Collisions of Particles + if (contact->particle->GetOneTimeCollisionEnabled() ) + contact->particle->previousCollidedBodies.insert(referenceBody); + + for (size_t n=0;nreferenceParticles.size();++n ){ + if (contact->referenceParticles[n]->GetOneTimeCollisionEnabled() ) + contact->referenceParticles[n]->previousCollidedBodies.insert(incidentBody); + } + + if (contact->particle->GetOneTimeCollisionEnabled() ){ + if( contact->particle->oneTimeCollidedBodies.find(referenceBody)!=contact->particle->oneTimeCollidedBodies.end() ){ + continue; + } + } + + for (size_t n=0;nreferenceParticles.size();++n ){ + if (contact->referenceParticles[n]->GetOneTimeCollisionEnabled() ){ + if( contact->referenceParticles[n]->oneTimeCollidedBodies.find(incidentBody)!=contact->referenceParticles[n]->oneTimeCollidedBodies.end() ) + cancelSolving=true; + break; + } + + } + if(cancelSolving==true) continue; + + //APPLYING FORCES TO BODIES diff --git a/src/QuarkPhysics/qparticle.cpp b/src/QuarkPhysics/qparticle.cpp index 12c2532..644cd74 100644 --- a/src/QuarkPhysics/qparticle.cpp +++ b/src/QuarkPhysics/qparticle.cpp @@ -30,6 +30,17 @@ #include "qbody.h" #include "qvector.h" +void QParticle::ClearOneTimeCollisions() +{ + oneTimeCollidedBodies.clear(); + previousCollidedBodies.clear(); +} + +void QParticle::ResetOneTimeCollisions() +{ + oneTimeCollidedBodies=previousCollidedBodies; + previousCollidedBodies.clear(); +} QParticle::QParticle() { @@ -123,6 +134,18 @@ QParticle *QParticle::SetIsInternal(bool value) return this; } +QParticle *QParticle::SetEnabled(bool value) +{ + enabled=value; + return this; +} + +QParticle *QParticle::SetOneTimeCollisionEnabled(bool value) +{ + enableOneTimeCollision=value; + ClearOneTimeCollisions(); + return this; +} QParticle *QParticle::ApplyForce(QVector value) { diff --git a/src/QuarkPhysics/qparticle.h b/src/QuarkPhysics/qparticle.h index 0333e64..43eb6e5 100644 --- a/src/QuarkPhysics/qparticle.h +++ b/src/QuarkPhysics/qparticle.h @@ -53,8 +53,21 @@ class QParticle std::vector accumulatedForces; + bool enabled=true; + + bool enableOneTimeCollision=false; + + void ClearOneTimeCollisions(); + protected: std::unordered_set springConnectedParticles; + + unordered_set oneTimeCollidedBodies; + unordered_set previousCollidedBodies; + + void ResetOneTimeCollisions(); + + public: QParticle(); QParticle(float posX,float posY,float radius=0.5f); @@ -97,6 +110,19 @@ class QParticle QVector GetForce(){ return force; } + /** Returns whether the particle is enabled. Disabled particles are not exempt from the collision tests that involve the meshes they belong to, but the solutions of their manifolds are not applied. Additionally, in body types where particles can move freely individually (e.g., QSoftBody), force and velocity integrations are not applied. + * @note Disabled particles in QRigidBody objects may appear to move because they are transformed based on the position and rotation of the rigid body. + */ + bool GetEnabled(){ + return enabled; + } + /** + * Returns whether the particle's one-time collision feature is enabled. When the one-time collision feature is active, an interaction occurs once at the beginning of the collision with objects. For subsequent collision interactions, the object must exit the collision and re-enter to trigger another interaction. + */ + + bool GetOneTimeCollisionEnabled(){ + return enableOneTimeCollision; + } //Set Methods /** Sets the local position of the particle. @@ -147,6 +173,22 @@ class QParticle */ QParticle *SetIsInternal(bool value); + /** Sets whether the particle is enabled. Disabled particles are not exempt from the collision tests that involve the meshes they belong to, but the solutions of their manifolds are not applied. Additionally, in body types where particles can move freely individually (e.g., QSoftBody), force and velocity integrations are not applied. + * @note Disabled particles in QRigidBody objects may appear to move because they are transformed based on the position and rotation of the rigid body. + * @param value A value to set. + * @return A pointer to the particle itself. + */ + + QParticle *SetEnabled(bool value); + + /** + * Sets whether the particle's one-time collision feature is enabled. When the one-time collision feature is active, an interaction occurs once at the beginning of the collision with objects. For subsequent collision interactions, the object must exit the collision and re-enter to trigger another interaction. + * @param value A value to set. + * @return A pointer to the particle itself. + */ + + QParticle *SetOneTimeCollisionEnabled(bool value); + // /** Applies a force immediately to the particle. You can use the method safely before the physics step (e.g. at the OnPreStep event of QBody objects). If you want to use this method after physics step, it can break the simulation.(Collisions and constraints may not be applied properly.) if you want to apply force at the next physic step safely, use SetForce() and AddForce() methods. * @param value A force value to apply. @@ -193,7 +235,10 @@ class QParticle */ static void ApplyForceToParticleSegment(QParticle *pA,QParticle *pB,QVector force,QVector fromPosition); + friend class QMesh; + friend class QBody; + friend class QManifold; }; diff --git a/src/QuarkPhysics/qrigidbody.cpp b/src/QuarkPhysics/qrigidbody.cpp index f3f4cbd..c727996 100644 --- a/src/QuarkPhysics/qrigidbody.cpp +++ b/src/QuarkPhysics/qrigidbody.cpp @@ -101,6 +101,9 @@ QRigidBody *QRigidBody::AddAngularForce(float value) void QRigidBody::Update() { + QBody::Update(); + + if(mode==QBody::STATIC){ return; } diff --git a/src/QuarkPhysics/qsoftbody.cpp b/src/QuarkPhysics/qsoftbody.cpp index 48894a6..231d10e 100644 --- a/src/QuarkPhysics/qsoftbody.cpp +++ b/src/QuarkPhysics/qsoftbody.cpp @@ -78,10 +78,13 @@ QSoftBody::QSoftBody() void QSoftBody::Update() { + QBody::Update(); + if (mode==QBody::STATIC){ return; } + //Sleep Feature if(isSleeping){ @@ -107,6 +110,8 @@ void QSoftBody::Update() QMesh *mesh=_meshes[i]; for(int n=0;nGetParticleCount();n++){ QParticle *particle=mesh->GetParticleAt(n); + + /* if(GetPassivationOfInternalSpringsEnabled() && particle->GetIsInternal()) continue; */ auto vel=particle->GetGlobalPosition()-particle->GetPreviousGlobalPosition(); diff --git a/src/QuarkPhysics/qsoftbody.h b/src/QuarkPhysics/qsoftbody.h index 0c5b4cb..acac1ed 100644 --- a/src/QuarkPhysics/qsoftbody.h +++ b/src/QuarkPhysics/qsoftbody.h @@ -306,6 +306,7 @@ class QSoftBody : public QBody void PreserveAreas(); /** Applies the shape matching operation to the body. */ void ApplyShapeMatching(); + }; diff --git a/src/qparticle_object.cpp b/src/qparticle_object.cpp index 0d9f164..eac2075 100644 --- a/src/qparticle_object.cpp +++ b/src/qparticle_object.cpp @@ -13,6 +13,9 @@ void QParticleObject::_bind_methods() { ClassDB::bind_method(D_METHOD( "get_radius" ),&QParticleObject::get_radius ); ClassDB::bind_method(D_METHOD( "get_is_internal" ),&QParticleObject::get_is_internal ); ClassDB::bind_method(D_METHOD( "get_force" ),&QParticleObject::get_force ); + ClassDB::bind_method(D_METHOD( "get_enabled" ),&QParticleObject::get_enabled ); + ClassDB::bind_method(D_METHOD( "get_one_time_collision_enabled" ),&QParticleObject::get_one_time_collision_enabled ); + //Set ClassDB::bind_method(D_METHOD( "set_global_position","value" ),&QParticleObject::set_global_position ); ClassDB::bind_method(D_METHOD( "add_global_position","value" ),&QParticleObject::add_global_position ); @@ -26,6 +29,8 @@ void QParticleObject::_bind_methods() { ClassDB::bind_method(D_METHOD( "apply_force","value" ),&QParticleObject::apply_force ); ClassDB::bind_method(D_METHOD( "set_force","value" ),&QParticleObject::set_force ); ClassDB::bind_method(D_METHOD( "add_force","value" ),&QParticleObject::add_force ); + ClassDB::bind_method(D_METHOD( "set_enabled","value" ),&QParticleObject::set_enabled ); + ClassDB::bind_method(D_METHOD( "set_one_time_collision_enabled","value" ),&QParticleObject::set_one_time_collision_enabled ); } @@ -67,6 +72,16 @@ Vector2 QParticleObject::get_force() { return Vector2(value.x,value.y); } +bool QParticleObject::get_enabled() +{ + return particleObject->GetEnabled(); +} + +bool QParticleObject::get_one_time_collision_enabled() +{ + return particleObject->GetOneTimeCollisionEnabled(); +} + //SET METHODS Ref QParticleObject::set_global_position(Vector2 value) { particleObject->SetGlobalPosition(QVector(value.x,value.y) ); @@ -127,3 +142,15 @@ Ref QParticleObject::add_force(Vector2 value) { particleObject->AddForce(QVector(value.x,value.y) ); return Ref(this); } + +Ref QParticleObject::set_enabled(bool value) +{ + particleObject->SetEnabled(value); + return Ref(this); +} + +Ref QParticleObject::set_one_time_collision_enabled(bool value) +{ + particleObject->SetOneTimeCollisionEnabled(value); + return Ref(this); +} diff --git a/src/qparticle_object.h b/src/qparticle_object.h index 609c855..c075ca0 100644 --- a/src/qparticle_object.h +++ b/src/qparticle_object.h @@ -77,6 +77,8 @@ class QParticleObject: public RefCounted{ float get_radius(); bool get_is_internal(); Vector2 get_force(); + bool get_enabled(); + bool get_one_time_collision_enabled(); //Set Methods Ref set_global_position(Vector2 value); @@ -91,6 +93,10 @@ class QParticleObject: public RefCounted{ Ref apply_force(Vector2 value); Ref set_force(Vector2 value); Ref add_force(Vector2 value); + Ref set_enabled(bool value); + Ref set_one_time_collision_enabled(bool value); + + friend class QSpringObject; friend class QMeshNode;