Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Joshua King · Dec 23, 2009 at 08:17 AM · animationrotation

Using Quaternions and C# script to animate a mesh

I am using a script to animate a mesh character. My values are being fed in realtime through a TCP connection and I am sorting them into their 4x4 quaternion matrices. When I apply these rotations to each bone, I should get the same animation being sent from the live feed, but I'm getting very odd rotations that don't seem to match in any way. I've already tried some changes of coordinate systems and bone structure.

Here is what my code for the rotation looks like:

using UnityEngine; using System.Collections; using System; using System.Text; using System.IO; using System.Net; using System.Net.Sockets;

public class BoneControlTest : MonoBehaviour {

 GameObject hipRight;
 GameObject kneeRight;
 GameObject ankleRight;
 GameObject footRight;
 GameObject toeRight;

 GameObject leftLeg;
 GameObject hipLeft;
 GameObject kneeLeft;
 GameObject ankleLeft;
 GameObject footLeft;
 GameObject toeLeft;

 GameObject spine3;
 GameObject spine2;
 GameObject spine1;
 GameObject spine;
 GameObject head;

 Byte[] sendBytes = new Byte[5000];
 byte[] readBytes = new byte [5050];
 TcpClient socketForOMProxyServer;
 NetworkStream proxyStream;
 GameObject[] boneArray = new GameObject[21];
 string boneData = "";

 //method for parsing rootbone matrix
 static float[,] ParseBoneData(string boneData, int boneNum)
 {
     string forCurrent = "Bone " + boneNum + "/21: ";
     string forNext = "Bone " + (boneNum+1) + "/21: ";
     print(forCurrent + " " + forNext);
     int rootNodePos = boneData.IndexOf(forCurrent);
     int firstNodePos = boneData.IndexOf(forNext);
     string boneMatrix = boneData.Substring(rootNodePos, firstNodePos - rootNodePos);
     char[] separators = new char [] { ' ', '\n', '\r' };
     string[] parts = boneMatrix.Split(separators, StringSplitOptions.RemoveEmptyEntries);
     float[,] rootBoneMat = new float[4,4]
     {
         {float.Parse(parts[ 6]), float.Parse(parts[ 7]), float.Parse(parts[ 8]), float.Parse(parts[ 9])},
         {float.Parse(parts[10]), float.Parse(parts[11]), float.Parse(parts[12]), float.Parse(parts[13])},
         {float.Parse(parts[14]), float.Parse(parts[15]), float.Parse(parts[16]), float.Parse(parts[17])},
         {float.Parse(parts[18]), float.Parse(parts[19]), float.Parse(parts[20]), float.Parse(parts[21])}
     };;

     print("Root bone matrix: " + rootBoneMat[0, 0] + " " + rootBoneMat[0, 1] + " " + rootBoneMat[0, 2] + " " + rootBoneMat[0, 3] + '\n'
     +  rootBoneMat[1, 0] + " " + rootBoneMat[1, 1] + " " + rootBoneMat[1, 2] + " "  + rootBoneMat[1, 3] + '\n'
     + rootBoneMat[2, 0] + " " + rootBoneMat[2, 1] + " " + rootBoneMat[2, 2] + " " + rootBoneMat[2, 3] + '\n'
     + rootBoneMat[3, 0] + " " + rootBoneMat[3, 1] + " " + rootBoneMat[3, 2] + " "+rootBoneMat[3, 3]);

     return rootBoneMat;
 }

 void Start() 
 {
     //socket code from Jack's SLbot

     try
     {
         socketForOMProxyServer = new TcpClient("localHost", 4242);
         print("Connected to OMProxy");
     }
     catch
     {
         print(
         "Failed to connect to server at {0}:4242"+            "localhost");
         return;
     }
     proxyStream = socketForOMProxyServer.GetStream();

     //bind our new GameObjects to the bone structure
     spine3 = GameObject.Find("MidTorso");
     spine2 = GameObject.Find("LowerTorso");
     spine1 = GameObject.Find("UpperChest");
     spine = GameObject.Find("Neck");
     //head = GameObject.Find("Head");

     //spine2.transform.parent = spine3.transform;
     //spine1.transform.parent = spine2.transform;
     //spine.transform.parent = spine1.transform;
     //head.transform.parent = spine.transform;

     boneArray[1] = spine3;
     boneArray[2] = spine2;
     boneArray[3] = spine1;
     boneArray[4] = spine;
     boneArray[5] = head;

     //print(spine3.transform.childCount + " " + spine.transform.childCount + " " + head.transform.root);
 }

 // Update is called once per frame
 void Update () 
 {
     sendBytes = Encoding.ASCII.GetBytes("g");
     proxyStream.Write(sendBytes, 0, sendBytes.Length);
     int count = proxyStream.Read(readBytes, 0, readBytes.Length);

     for (int i = 1; i <= 4; i++)
     {
         string boneData = Encoding.ASCII.GetString(readBytes).Substring(0, count);
         //print(boneData);
         float[,] rootBoneMat = ParseBoneData(boneData, i);

         // Use rootBoneMat to set body rotation
         float T = 1.0f + rootBoneMat[0, 0] + rootBoneMat[1, 1] + rootBoneMat[2, 2];
         float S = (float)Math.Sqrt(T) * 2.0f;
         float X = (rootBoneMat[2, 1] - rootBoneMat[1, 2]) / S;
         float Y = (rootBoneMat[0, 2] - rootBoneMat[2, 0]) / S;
         float Z = (rootBoneMat[1, 0] - rootBoneMat[0, 1]) / S;
         float W = 0.25f * S;
         Quaternion bodyRotation = new Quaternion(X, Y, Z, W);
         print("X: " + X + " Y: " + Y + " Z: " + Z + " W: " + W);

         Vector3  rootPos = new Vector3(rootBoneMat[3, 0], rootBoneMat[3, 2], rootBoneMat[3, 1]);

         //Rotate the bone
         //bodyRotation.eulerAngles =  Vector3(X, Y, Z);
         boneArray[i].transform.rotation = bodyRotation;
         boneArray[i].transform.localPosition = rootPos;
     }
 }

}

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by runevision · Dec 23, 2009 at 11:26 AM

Have you used debugging to determine if the matrices you get are correct before you convert them to quaternions? You can use Debug.DrawLine to draw lines representing the matrices and see if these look correct.

Unity has a build-in format for 4x4 matrices: Matrix4x4 - you can use that one instead of the float[,] to get easy access to some utility functions.

Where did you get the code for converting to quaternions? It doesn't look the same as the code I use, which I know works:

public static Quaternion QuaternionFromMatrix(Matrix4x4 m) {
    // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
    Quaternion q = new Quaternion();
    q.w = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] + m[1,1] + m[2,2] ) ) / 2; 
    q.x = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] - m[1,1] - m[2,2] ) ) / 2; 
    q.y = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] + m[1,1] - m[2,2] ) ) / 2; 
    q.z = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] - m[1,1] + m[2,2] ) ) / 2; 
    q.x *= Mathf.Sign( q.x * ( m[2,1] - m[1,2] ) );
    q.y *= Mathf.Sign( q.y * ( m[0,2] - m[2,0] ) );
    q.z *= Mathf.Sign( q.z * ( m[1,0] - m[0,1] ) );
    return q;
}

Are the rotations in your data local or global? If they are local, you should set the Transform.localRotation rather than the Transform.rotation.

I hope some of these tips can be of help.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Joshua King · Feb 11, 2010 at 06:32 PM 0
Share

I've made these changes and redid my armature to match the data exactly. For some reason the new armature is not reacting to the script commands. Unity is not showing the bones as null, so it is identifying them as a GameObject, but they aren't moving in any way.

Here is my model/armature. I tried to follow a rigging guide but I don't think it was unity specific.

http://www.megaupload.com/?d=G4I96W0F

avatar image runevision ♦♦ · Feb 12, 2010 at 09:51 AM 0
Share

If your new armature is not reacting on script adjustments at all, that should be easy for you to debug. Just test that it's even referenced correctly by using some dummy movement, e.g. hipRight.Rotate(90*Time.deltaTime,0,0) or something. If nothing happens, you probably didn't drag the bone transforms into the slots in the Inspector correctly.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

No one has followed this question yet.

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Rotating An Object On Its Axis Once 3 Answers

How to correct the First Person Controller orientation when parenting to a rotated x.270 degrees model? 2 Answers

Scripting: make thing repeating 3 Answers

Why does animation affect rotation? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges