1

when we want to draw Bones into XNA (using KnectSDK and C#), you have to calculate differences between two joints and draw bones between them. this is the function for drawing Bones:

private void DrawBone(JointCollection joints, JointType startJoint, JointType endJoint)
    {
        Vector2 start = this.mapMethod(joints[startJoint].Position);
        Vector2 end = this.mapMethod(joints[endJoint].Position);
        Vector2 diff = end - start;
        Vector2 scale = new Vector2(1.0f, diff.Length() / this.boneTexture.Height);

        float angle = (float)Math.Atan2(diff.Y, diff.X) - MathHelper.PiOver2;

        Color color = Color.LightGreen;
        if (joints[startJoint].TrackingState != JointTrackingState.Tracked ||
            joints[endJoint].TrackingState != JointTrackingState.Tracked)
        {
            color = Color.Gray;
        }

        this.SharedSpriteBatch.Draw(this.boneTexture, start, null, color, angle, this.boneOrigin, scale, SpriteEffects.None, 1.0f);
    }

I just want to understand the way of calculating angle and how the angle formula works

Thanks

Nathan Drake
  • 301
  • 3
  • 14

1 Answers1

2

Here is the code to calculate the angle between two vectors (Explanation below code):

    public class Angles
    {
    public double AngleBetweenTwoVectors(Vector3D vectorA, Vector3D vectorB)
        {
            double dotProduct = 0.0;
            dotProduct = Vector3D.DotProduct(vectorA, vectorB);

            return (double)Math.Acos(dotProduct)/Math.PI*180;
        }

        public double[] GetVector(Skeleton skeleton)
        {
            Vector3D ShoulderCenter = new Vector3D(skeleton.Joints[JointType.ShoulderCenter].Position.X, skeleton.Joints[JointType.ShoulderCenter].Position.Y, skeleton.Joints[JointType.ShoulderCenter].Position.Z);
            Vector3D RightShoulder = new Vector3D(skeleton.Joints[JointType.ShoulderRight].Position.X, skeleton.Joints[JointType.ShoulderRight].Position.Y, skeleton.Joints[JointType.ShoulderRight].Position.Z);
            Vector3D LeftShoulder = new Vector3D(skeleton.Joints[JointType.ShoulderLeft].Position.X, skeleton.Joints[JointType.ShoulderLeft].Position.Y, skeleton.Joints[JointType.ShoulderLeft].Position.Z);
            Vector3D RightElbow = new Vector3D(skeleton.Joints[JointType.ElbowRight].Position.X, skeleton.Joints[JointType.ElbowRight].Position.Y, skeleton.Joints[JointType.ElbowRight].Position.Z);
            Vector3D LeftElbow = new Vector3D(skeleton.Joints[JointType.ElbowLeft].Position.X, skeleton.Joints[JointType.ElbowLeft].Position.Y, skeleton.Joints[JointType.ElbowLeft].Position.Z);
            Vector3D RightWrist = new Vector3D(skeleton.Joints[JointType.WristRight].Position.X, skeleton.Joints[JointType.WristRight].Position.Y, skeleton.Joints[JointType.WristRight].Position.Z);
            Vector3D LeftWrist = new Vector3D(skeleton.Joints[JointType.WristLeft].Position.X, skeleton.Joints[JointType.WristLeft].Position.Y, skeleton.Joints[JointType.WristLeft].Position.Z);

           /* ShoulderCenter.Normalize();
            RightShoulder.Normalize();
            LeftShoulder.Normalize();
            RightElbow.Normalize();
            LeftElbow.Normalize();
            RightWrist.Normalize();
            LeftWrist.Normalize();

            if (skeleton.Joints[JointType.ShoulderCenter].TrackingState == JointTrackingState.Tracked) { 

            }
            */

            double AngleRightElbow = AngleBetweenTwoVectors(RightElbow - RightShoulder, RightElbow - RightWrist);
            double AngleRightShoulder = AngleBetweenTwoVectors(RightShoulder - ShoulderCenter, RightShoulder - RightElbow);
            double AngleLeftElbow = AngleBetweenTwoVectors(LeftElbow - LeftShoulder, LeftElbow - LeftWrist);
            double AngleLeftShoulder = AngleBetweenTwoVectors(LeftShoulder - ShoulderCenter, LeftShoulder - LeftElbow);

            double[] Angles = {AngleRightElbow, AngleRightShoulder, AngleLeftElbow, AngleLeftShoulder};
            return Angles;
        }
}

First of all we'll have a look at the method GetVector(Skeleton skeleton). In this method we first define our Vector3D(for the joints you choose). We then call the method AngleBetweenTwoVectors and give it two parameters.

But attention. If we would just give it the Vector of the Joints, we would not get the correct angle. We first have to substract the surrounding Vectors from the Vector (Vector we want to get the angle from). We then pass the two Vectors to the method AngleBetweenTwoVectors.

In this method we first have to calculate the dot-product. For more information on the dot-product click here. With the dot-product we can calculate the angle. To do that we just need to use the arcos() method.

Another thing I struggled with: The assemblies. You need to import:

using System.Windows.Media;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit.Fusion;
using System.Windows.Media.Media3D;

To get the [...].Toolkit.Fusion assembly go to "Add Reference" and hit "Browse". You will then guide to the assembly directory from the MicrosoftSDK's/Kinect/Developer Toolkit v1.8.0/Assemblies. Import the assembly and add it to your project.

jbuchel
  • 703
  • 5
  • 21