Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Calculating rotation for object

Discussion in 'Scripting' started by PreeHooZheng, Nov 30, 2023.

  1. PreeHooZheng

    PreeHooZheng

    Joined:
    Oct 5, 2023
    Posts:
    19
    Hi Folks.

    I use some deep learning solution. This solution create on a scene some face mesh (478 feature points of face), it’s look like on the picture




    Issue I had:

    I don’t understand how to calculate the rotation of a mesh face with good performance.

    I used to use a very bad algorithm for calculating angle whith sin, cos, etc… It works, but only in the range from -90° to +90°, but I would like to get full 360° on each axis. How can I get this result?

    Each point on the face looks like a Transform with a changing position, the rotation is always 0.
     
    Last edited: Nov 30, 2023
  2. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,638
    This suggestion may or may not help you immediately, but: Use Quaternions!
    They may be trickier to grasp than classic (Euler) angles, but they avoid certain problems and usually the library (e.g. Unity) provides many helpful methods.

    Finally if optimization is your goal, evaluate whether you can do your computations in "burst compiled jobs". That is a somewhat restrictive (e.g. allows no managed datatypes) but highly performant (natively compiled and inherently parallelized) subsystem in Unity for processing data.

    By the way, just in case: Make sure you set the positions of the points from some singular external script and do not have one instance of some updating script in each of the points because that can be a bottleneck as well.
    There are some assets for pointcloud rendering in the asset store or you can misuse the particle system (have particles with infinite life and no actual simulation/velocity).

    Edit: First of all make sure you do identify the performance bottleneck! It's often unexpected. Pure math is reasonably fast even with SIN and COS etc.
    Unity has multiple Profilers for finding performance issues.
     
    Last edited: Nov 30, 2023
  3. PreeHooZheng

    PreeHooZheng

    Joined:
    Oct 5, 2023
    Posts:
    19

    Thank you @DragonCoder. I understand what I should use quaternions. Right now I find any solve how calculate rotations with quaternions.

    But I haven't found a solution yet.
    Anyway thank you for your message.

    UPD:


    The main problem is that the rotation range only works correctly from -90 degrees to 90.

    And when I turn the camera on its side, the facial points (as in the picture) visually flip to the left (or right, depending on the rotation). Therefore, the current solution begins to produce bugs.
     
    Last edited: Nov 30, 2023
  4. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,638
    Well you haven't even described what exactly you need to calculate. What's the input and the desired output?

    On quaternions, there are many tutorials out there. Best to look at a few and then make yourself a sample project where you play around with them. Learning by doing.
     
  5. PreeHooZheng

    PreeHooZheng

    Joined:
    Oct 5, 2023
    Posts:
    19

    Okay. I you show an example.

    As you can see in the image, the dots follow the face. In fact, the points simply change their positions.

    When I turn the camera I get errors that (see second GIF).


    Why is this happening? Because I'm using a triangle solution that looks like this:


    Code (CSharp):
    1.     public float GetDegreeOfRotation(Vector2 pointFirst, Vector2 pointSecond, PointOrder pointsOrder)
    2.     {
    3.       if (pointFirst.y.Equals(pointSecond.y))
    4.         return 0;
    5.  
    6.       (pointFirst, pointSecond) = GetCorrectOrderOfPlace(pointFirst, pointSecond, pointsOrder);
    7.       _circleRadius = Vector2.Distance(pointFirst, pointSecond) / 2;
    8.       CalculateTrianglePoints(pointFirst, pointSecond);
    9.       CalculateTriangleSides();
    10.       _signCoefficientOfRotation = _vectorUnknownAnglePoint == pointFirst ? -1 : 1;
    11.       // α(rad) = arcos(b^2 + c^2 - a^2) / 2bc
    12.       // α(deg) = α(rad) * 180 / PI
    13.       float alphaRadiansNumerator =
    14.         Mathf.Pow(_triangleSideB, 2) + Mathf.Pow(_triangleSideC, 2) - Mathf.Pow(_triangleSideA, 2);
    15.       float alphaRadiansDenominator = 2 * _triangleSideB * _triangleSideC;
    16.       float alphaRadians = Mathf.Acos(alphaRadiansNumerator / alphaRadiansDenominator);
    17.       float alphaDegrees = alphaRadians * _StraightAngle / Mathf.PI;
    18.       float alphaDegreesSigned = alphaDegrees * _signCoefficientOfRotation;
    19.       return alphaDegreesSigned;
    20.     }
    This solution wotks good only for half-circle (from -90° to °90).

    UPD:
    Add used methods

    CalculateTrianglePoints
    Code (CSharp):
    1.     private void CalculateTrianglePoints(Vector2 pointFirst, Vector2 pointSecond)
    2.     {
    3.       // Calculate the center of the segment between the points
    4.       _circleCenterPoint = new Vector2((pointFirst.x + pointSecond.x) / 2, (pointFirst.y + pointSecond.y) / 2);
    5.       // Depending on the difference in the Y coordinate, we determine a point on a circle with an unknown angle
    6.       _vectorUnknownAnglePoint = pointFirst.y < pointSecond.y ? pointFirst : pointSecond;
    7.       // Defining a point on a circle with a zero angle
    8.       _vectorZeroAnglePoint = _circleCenterPoint;
    9.       _vectorZeroAnglePoint.x = _vectorUnknownAnglePoint != pointFirst
    10.         ? _vectorZeroAnglePoint.x + _circleRadius
    11.         : _vectorZeroAnglePoint.x - _circleRadius;
    12.     }

    CalculateTrianglesSides
    Code (CSharp):
    1.     /// <summary>
    2.     /// Calculates the length of each side of the triangle. The sides of the length of sides C and B are always equal,
    3.     /// The length of the third side of the triangle is calculated as the point of the vector 0 degrees lying on the
    4.     /// circle <b>minus</b> the point of the vector of an unknown angle lying on the circle
    5.     /// </summary>
    6.     private void CalculateTriangleSides()
    7.     {
    8.       _triangleSideC = _circleRadius;
    9.       _triangleSideB = _circleRadius;
    10.       _triangleSideA = Mathf.Sqrt(Mathf.Pow(_vectorZeroAnglePoint.x - _vectorUnknownAnglePoint.x, 2) +
    11.                                   Mathf.Pow(_vectorZeroAnglePoint.y - _vectorUnknownAnglePoint.y, 2));
    12.     }
     

    Attached Files:

    Last edited: Nov 30, 2023
  6. PreeHooZheng

    PreeHooZheng

    Joined:
    Oct 5, 2023
    Posts:
    19