Search Unity

How to make a hinge joint using a Transform and a Vector3 point?

Discussion in 'Scripting' started by createthiscom, Feb 21, 2017.

  1. createthiscom

    createthiscom

    Joined:
    Dec 19, 2016
    Posts:
    67
    I have an object represented by a Transform. A Quaternion rotation and a Vector3 position.

    I have another point in space represented by a Vector3. I want to calculate a Quaternion rotation for that point by imagining a hinge joint between the object and the point. As the object tilts side to side, the calculated rotation should tilt side to side. As the object raises and lowers, the calculated rotation should tilt too, front to back.

    Imagine holding a door hinge in your hands, sort of like this guy:

    Holding a leaf of the door hinge in each hand, lift the hinge up and look directly down the axis of the pivot shaft.

    The "object" is the right leaf of the hinge and the "point" represents the center of the left leaf of the hinge. The point on the left leaf has a fixed position, but can freely rotate. The right leaf gets moved around and I want the orientation of the calculated rotation to be realistic.

    Ok, so, code. Currently, this is how I'm calculating the rotation of the "point":
    Code (CSharp):
    1. Vector3 point;
    2. Quaternion rotation = Quaternion.LookRotation(
    3.     gameObject.transform.position - point,
    4.     gameObject.transform.rotation * Vector3.up);
    5.  
    This almost works perfectly. If the right leaf of the hinge (the gameObject in this case) is at an angle in relation to the line drawn by "gameObject.transform.position - point", it works as expected. However, it seems to fall apart when the angle is shallow, approaching zero degrees. The LookRotation inverts and the left leaf flips from up to down in relation to gameObject.transform.rotation.

    How do I keep that transition flip from happening? I've been thinking about this in my spare time for days and I can't see the forest for the trees at the moment.
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Could you draw a diagram of how you expect your door to be laid out? I'm not sure I follow your logic - I don't know what "point" represents, which object the code is being run from (and therefore what "gameObject" refers to in your code sample, etc), and so on.

    Usually, when making a swinging door, the function needs nothing more than the angle at which the door is open. It uses Quaternion.AngleAxis to rotate it from there. Further, the door is a child of the "doorframe", so you don't have to worry about modifying the rotation at all. Opening the door becomes the equivalent of just changing the Y rotation of the transform in the inspector. Seems like you're drastically overcomplicating it with your approach, and could benefit from taking a step back.
     
  3. createthiscom

    createthiscom

    Joined:
    Dec 19, 2016
    Posts:
    67
    It's not a door. It's just a hinge joint.
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Wel... ok. Whatever it is, all the exact same logic (and questions) apply.
     
  5. createthiscom

    createthiscom

    Joined:
    Dec 19, 2016
    Posts:
    67
    A video demo is worth a thousand words. Sorry for the crappy audio. The mic on the Vive really sucks.
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Okay, so "point" is the initial click position. It appears that you start experiencing issues when controller.z crosses point.z - would that fit with your observations? I think a second key question is, how is this affected if you are facing a different direction initially?

    At a glance (assuming I've interpreted the intended movement correctly), the issue seems to be that your algorithm is not direction-neutral. you ultimately need to get to a few key pieces of information:
    1) point (the center of the disc, so let's call it "disc")
    2) controller position (let's call it "cont")
    3) controller "roll" angle

    From these, you should calculate the disc's rotation in 3 steps, each using Quaternion.AngleAxis:
    1) rotate around Y axis to so that a flattened (disc - cont) faces forward.
    2) rotate around disc's current X axis (pitch forward or backwards) based on the horizontal distance between disc and cont and the vertical difference. (note that "horizontal distance" should contain both X and Z components)
    3) rotate around disc's current Z axis based on controller's roll.

    If it's direction-neutral, then the exact X and Z positions shouldn't matter at all after step 1.

    (depending on how it feels you might wish to store the disc's Z axis between steps 1 & 2 to use during step 3)
     
  7. createthiscom

    createthiscom

    Joined:
    Dec 19, 2016
    Posts:
    67
    It's consistent no matter where I stand. It seems to happen when the controller crosses a 90 degree angle in relation to the disc. This makes sense because I'm using controller.transform.up to orient the disc up or down and when the controller is vertical but the disc is horizontal that direction stops pointing generally up and starts pointing generally down, or vice versa.

    I want the disc to always point up in this case, just like a hinge leaf would always point up even if the second leaf rotated past 90 degrees.
     
  8. createthiscom

    createthiscom

    Joined:
    Dec 19, 2016
    Posts:
    67
    Nevermind, I figured it out. I just needed to calculate a normal. The missing piece was that I forgot I could use controller.right as the third vertex for my triangle.