7th_Continuum

Position Based Dynamics Frictional Constraint

Recommended Posts

I'm trying to implement a frictional constraint using position based dynamics, but it is only half working. I am using the formulation in the paper "Unified Particle Physics for Real-Time Applications".

Here is my implementation:

	Particle *np = particle->nbs[j].neighbour; 

    vec3  r = particle->x - np->x;
    float r_length = glm::length(r);

    float distDiff = r_length - restDistance;

    if(distDiff >= 0 ) continue;

    //Frictional Constraint
    vec3 n   = r/r_length;
    vec3 xxi = particle->x - xi[particle->getIndex()];
    vec3 xxj = np->x - xi[np->getIndex()];

    vec3 tangentialDisplacement = (xxi - xxj) - glm::dot(xxi - xxj, n) * n;

    float td_length = glm::length(tangentialDisplacement);

    float genMass = ( imass / (imass + imass) );


    if(td_length < (staticFriciton * distDiff)){
        particle->x += genMass * tangentialDisplacement;

        np->x += -genMass * tangentialDisplacement; 
    }else{
        float upper = kineticFriction * distDiff;
        particle->x += genMass * tangentialDisplacement * std::min(upper/td_length, 1.f); 

        np->x += -genMass * tangentialDisplacement * std::min(upper/td_length, 1.f); 
    }

 

Share this post


Link to post
Share on other sites

Here is a youtube link to the working penetration constraint:

And a link tot the failed friction constraint (Friction constraint applied after penetration constraint):

And I just realized that only the else statement gets executed in this part of the code:

  if(td_length < (staticFriciton * distDiff)){
        particle->x += genMass * tangentialDisplacement;

        np->x += -genMass * tangentialDisplacement; 
    }else{
        float upper = kineticFriction * distDiff;
        particle->x += genMass * tangentialDisplacement * std::min(upper/td_length, 1.f); 

        np->x += -genMass * tangentialDisplacement * std::min(upper/td_length, 1.f); 
    }

 

Edited by 7th_Continuum

Share this post


Link to post
Share on other sites

distDiff will always be negative, otherwise there's no interpenetration. So the answer is yes. 

I'm thinking the tangentialDisplacement is being calculated wrongly because everything largely depends on it. It is perpendicular to the contact normal, a dot product gives zero.

The other thing I am not sure about is the which interpenetration distance to use, the one from the penetration constraint or the one from the friction. The paper does not make this clear.

Hoping someone has implemented one before, I can't find a reference anywhere.

Edited by 7th_Continuum

Share this post


Link to post
Share on other sites

If (upper/td_length) is always negative then those std::min calls are redundant because they would only take effect if the value is > 1.  Mainly what I was concerned about was:  Often when min or max calls are done, someone is thinking of magnitudes (i.e.  "make sure the magnitude is between 0 and 1") but accidentally misses the fact that the value is not a magnitude, but can be negative (in which case you would either want to get the magnitude using the absolute value or clamp between -1 and +1).

I'm not familiar with the system you're trying to implement; I'm just looking at "suspicious" code based on my own experience with bugs :)

Edited by Nypyren

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Forum Statistics

    • Total Topics
      628278
    • Total Posts
      2981785
  • Similar Content

    • By Rannion
      Hi,
      I'm trying to fill a win64 Console with ASCII char.
      At the moment I have 2 solutions: one using std::cout for each line, let's say 30 lines at once using std::endl at the end of each one.
      The second solution is using FillConsoleOutputCharacter. This method seems a lot more robust and with less flickering. But I'm guessing, internally it's using a different table than the one used by std::cout. I'm trying to fill the console with the unsigned char 0xB0 which is a sort of grey square when I use std::cout but when using FillConsoleOutputCharacter it is outputted as the UTF8 char '°'.
      I tried using SetConsoleOutputCP before but could not find a proper way to force it to only use the non-extended ASCII code page...
      Has anyone a hint on this one?
      Cheers!
    • By Vortez
      Hi guys, i know this is stupid but i've been trying to convert this block of asm code in c++ for an hour or two and im stuck
      ////////////////////////////////////////////////////////////////////////////////////////////// /////// This routine write the value returned by GetProcAddress() at the address p /////////// ////////////////////////////////////////////////////////////////////////////////////////////// bool SetProcAddress(HINSTANCE dll, void *p, char *name) { UINT *res = (UINT*)ptr; void *f = GetProcAddress(dll, name); if(!f) return false; _asm { push ebx push edx mov ebx, f mov edx, p mov [ebx], edx // <--- put edx at the address pointed by ebx pop edx pop ebx } return res != 0; } ... // ie: SetProcAddress(hDll, &some_function, "function_name"); I tried:
      memcmp(p, f, sizeof(p)); and UINT *i1 = (*UINT)p; UINT *i2 = (*UINT)f; *f = *p; The first one dosent seem to give the right retult, and the second one won't compile.
      Any idea?
    • By adapelin
      I am a computer engineering student and i have the assignment below. İ only can write the 2D maze array and have no idea about creating car and time as well. Could anyone write and explain hot to do???
      Minimum Criteria: You are expected to design the game by using C ++ . Below are the minimal criteria: • You must create game board with 2 - Dimensional Matrix • Bonuses create with randomly in the game board • All bonuses have got the same value but different effect for car and score . These effects may be positive or negative . • You must use pointer for creating and using car . Some bonuses may be change car type. • When the game finish, you must show high - score. • For moving car , you need to create coordinate s randomly and you need to write proper control statements. • You must use functions for drawing game board and changing car type . If you need extra functions, you can use it. • If you cannot get out the maze when the time is up , the game is over and you need to show high score. In this project, you must do all minimum criteria. In the end, your program must be work without any errors. Bonus: • Save and load high score information to/from disk • Each bonus has got different random values. • You can create cheat codes for the game. • You can create alternative control for car . • Car can jump over the wall but may lose the score . When car exit the maze , game is over and you need to show high score.    
    • By Angelic Ice
      Hey everyone!
      Text is down below, just wanted to provide some C++ish pseudo-code to help me expressing my issue ('...' defines omitted details):
      class Interface_Tree { public: ... } class Tree : public Interface_Tree { public: ... private: std::vector<Interface_Bucket> buckets; } class Interface_Bucket { public: ... add_object(Interface_Object* obj) } class Special_Bucket : public Interface_Bucket { public: add_object(Interface_Bucket_Object* obj) { /* If `Interface_Bucket_Object` cannot be cast to `Special_Bucket_Object_Category`, do nothing. This would require a dynamic_cast which I want to avoid, that probably cannot unless restructuring. Check what enum-type `Special_Bucket_Object_Category` If `VERY_IMPORTANT` use pointer `very_important_obj`. Else add to `objs`. */ } private: std::vector<Interface_Bucket_Object*> objs; Interface_Bucket_Object* very_important_obj; } class Interface_Bucket_Object { public: ... } enum Special_Bucket_Object_Category { IMPORTANT, VERY_IMPORTANT, SPAM }; class Special_Bucket_Object : public Interface { public: ... private: Special_Bucket_Object_Category category; } I wanted to start programming to interfaces (or in C++, virtual classes) instead of actual classes (which are now just derived ones) in order to improve unit-testing etc., hence every class derives a base, that can be easily implemented differently.
      But the issue is, if I have a Hash-Bucket data-structure class owning buckets that collect bucket-objects, how can the bucket differentiate characteristics of an implementation of the implemented bucket-object? Sure, I can do a dynamic-cast, if that fails just abort, but I do not want to do a dynamic-cast, because I would rather restructure my code.
      I want my bucket-objects to have a flag (could also be called tag, category, ...) that notifies a bucket that this object needs the entire bucket, hence the enum in my code expressing the flags an object can raise.
      If I would omit all interface-stuff, it would be fairly easy. My Bucket's add_object() method could easily only be called with that exact object and since the exact bucket-object type is now given, and not just some interface, accessing the enum is trivial via a getter-method.
      And a last reminder: I'm not using virtual-classes to profit from inheritance in a sense of a bucket being able to collect a tons of different implementations, just one implementation that carries an enum. The bucket-tree won't own different types of buckets neither, just one implementation kind of bucket. The only reason I use inheritance is to enable easy unit-testing.
      So, how can I access the object's category without dynamic-casting?
       
       
    • By nedondev
      I 'm learning how to create game by using opengl with c/c++ coding, so here is my fist game. In video description also have game contain in Dropbox. May be I will make it better in future.
      Thanks.
  • Popular Now