Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 /
This question was closed Feb 17, 2018 at 09:52 AM by pako for the following reason:

The question is answered, right answer was accepted

avatar image
10
Question by numberkruncher · Feb 19, 2013 at 03:12 PM · rotationpositionquaternionscalematrix

How to Decompose a TRS Matrix?

How can the position, rotation and scale components be extracted from a transform matrix?

Comment
Add comment · Show 2
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 Lesliehdez · Feb 16, 2018 at 06:37 PM 0
Share

Hi, i need apply my own $$anonymous$$ATRIX4X4= [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] to my gameobject, how can i do that? I need to apply it to obtain a new transformation to my object.

this is correct? $$anonymous$$atrix4x4 worldToLocal = [15,0,0,0,0,15,0,0,0,0,15,0,0,0,0,1]; gameObj.Transform.localToWorld$$anonymous$$atrix = worldToLocal.inverse;

avatar image pako Lesliehdez · Feb 17, 2018 at 09:51 AM 0
Share

You should post this as a separate question, since the original question has been already answered.

3 Replies

  • Sort: 
avatar image
22
Best Answer

Answer by numberkruncher · Feb 19, 2013 at 03:13 PM

The components of a matrix can be extracted as follows:

 // Extract new local position
 Vector3 position = m.GetColumn(3);
 
 // Extract new local rotation
 Quaternion rotation = Quaternion.LookRotation(
     m.GetColumn(2),
     m.GetColumn(1)
 );
 
 // Extract new local scale
 Vector3 scale = new Vector3(
     m.GetColumn(0).magnitude,
     m.GetColumn(1).magnitude,
     m.GetColumn(2).magnitude
 );

Note: The purpose of this question was to share this knowledge in Q&A style :-)

Comment
Add comment · Show 9 · 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 vagran_zulu · Jan 28, 2014 at 09:05 AM 2
Share

This method is not able to extract negative scale values (flip transforms).

avatar image Kiloblargh · Jan 28, 2014 at 09:10 AM 2
Share

Negative scale values are immoral and carcinogenic.

avatar image vagran_zulu · Jan 28, 2014 at 09:22 AM 0
Share

I agree it's not good but real world is such. In my case, I need to import GoogleEarth $$anonymous$$$$anonymous$$Z models (Collada inside), which often have a number of such flip transforms produced by Google SketchUp. Probably other 3D-editors also can produce such models. Unfortunately my project managers will not agree to drop this feature because of Google immorality.

avatar image numberkruncher · Jan 28, 2014 at 11:03 AM 0
Share

@vagran_zulu Can you not just write a script to generate a new mesh which does not have flipped transforms? i.e. recompose your mesh... just an idea I thought I'd throw in there for you to play with ;)

avatar image vagran_zulu · Jan 28, 2014 at 11:20 AM 0
Share

Yes, it can be done, it will work, and can be used as workaround. The bad think is that mesh data will be duplicated and will waste a lot of resources. Typically a model has nodes graph, each node has some transform and may have some meshes attached to it. The same mesh can be attached to many nodes thus just having different overall transform applied (and different material bound). So in model which has many parts shared in such a way the wasting factor could be significant.

Actually I have found another workaround but it also has problems: the answer can be extended by checking deter$$anonymous$$ant value of the matrix and in case it is negative, one (any) component of scale vector should be negated. It works for vertex coordinates but unfortunately the Unity is unable to apply this transform also to normals - they became inverted. Seems when it calculates matrix for normals it does not account scaling sign (however according to documentation it accounts scaling as such - it makes some workaround for non-uniform scaling). Before that I tried using Graphics.Draw$$anonymous$$esh with matrix but there is also a problem. Seems the provided matrix applied to both positions and normals as is. Usually for normals separate matrix is calculated if necessary (orthonormal matrix, transpose of inverse of 3x3 upper-left submatrix), but Unity does not do it.

Show more comments
avatar image
-2

Answer by frogsbo · Mar 12, 2014 at 07:26 AM

Here is an example of Matrix TRS from extrusion demo in .js:

 for (var i=0;i<sections.length;i++)//for every vertex as edges of 2 pairs 
 {
     if (autoCalculateOrientation)
     {
         if (i == 0)
         {
             var direction = sections[0].point - sections[1].point;
             var rotation = Quaternion.LookRotation(direction, Vector3.up);
             previousRotation = rotation;
             finalSections[i] = worldToLocal * Matrix4x4.TRS(position, rotation, Vector3.one);    
         }
         // all elements get the direction by looking up the next section
         else if (i != sections.length - 1)
         {    
             direction = sections[i].point - sections[i+1].point;
             rotation = Quaternion.LookRotation(direction, Vector3.up);
             
             // When the angle of the rotation compared to the last segment is too high
             // smooth the rotation a little bit. Optimally we would smooth the entire sections array.
             if (Quaternion.Angle (previousRotation, rotation) > 20)
                 rotation = Quaternion.Slerp(previousRotation, rotation, 0.5);
                 
             previousRotation = rotation;
             finalSections[i] = worldToLocal * Matrix4x4.TRS(sections[i].point, rotation, Vector3.one);
         }
         // except the last one, which just copies the previous one
         else
         {
             finalSections[i] = finalSections[i-1];
         }
     }
     else
     {
         if (i == 0)
         {
             finalSections[i] = Matrix4x4.identity;
         }
         else
         {
             finalSections[i] = worldToLocal * sections[i].matrix;
         }
     }
 }
 
Comment
Add comment · Show 1 · 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 numberkruncher · Mar 12, 2014 at 02:28 PM 0
Share

Your answer shows how to Compose a TRS matrix whereas the purpose of this question/topic is to Decompose a TRS matrix.

avatar image
0

Answer by ETdoFresh · Jan 02, 2016 at 05:59 PM

Here's a Monobehaviour Script I've been working on for a few hours for doing it the Hard Way, for those interested...

 public class DisplayTransformMatrix : MonoBehaviour
 {
     [Header("Matrix4x4.localToWorldMatrix")]
     public Vector3 MatrixRow1;
     public Vector3 MatrixRow2;
     public Vector3 MatrixRow3;
     public Vector3 MatrixCol3;
     public string MatrixRow4;
 
     [Header("Local Transform")]
     public Vector3 localPosition;
     public string localRotation;
     public Vector3 localEuler;
     public Vector3 localScale;
 
     [Header("World Transform")]
     public Vector3 worldPosition;
     public string worldRotation;
     public Vector3 worldEuler;
     public Vector3 worldScale;
 
     [Header("UI Element")]
     public Text textToUpdate;
 
     void Update()
     {
         // Update Matrix4x4 Information in Inspector
         Matrix4x4 m = transform.localToWorldMatrix;
         MatrixRow1.x = m[0, 0];
         MatrixRow1.y = m[0, 1];
         MatrixRow1.z = m[0, 2];
         MatrixRow2.x = m[1, 0];
         MatrixRow2.y = m[1, 1];
         MatrixRow2.z = m[1, 2];
         MatrixRow3.x = m[2, 0];
         MatrixRow3.y = m[2, 1];
         MatrixRow3.z = m[2, 2];
         MatrixCol3.x = m[0, 3];
         MatrixCol3.y = m[1, 3];
         MatrixCol3.z = m[2, 3];
         MatrixRow4 = "" + m[3, 0] + " " + m[3, 1] + " " + m[3, 2] + " " + m[3, 3];
 
         // Update Local Transform in Inspector
         localPosition = transform.localPosition;
         localRotation = string.Format("{0} {1} {2} {3}", transform.localRotation.w,
             transform.localRotation.x, transform.localRotation.y, transform.localRotation.z);
         localEuler = QuaternionToEuler(transform.localRotation);
         localScale = transform.localScale;
 
         // Update World Transform in Inspector
         worldPosition = GetPosition(m);
         worldRotation = string.Format("{0} {1} {2} {3}", GetRotation(m).w,
             GetRotation(m).x, GetRotation(m).y, GetRotation(m).z);
         worldEuler = QuaternionToEuler(GetRotation(m));
         worldScale = GetScale(m);
 
         // Update UI Element
         if (textToUpdate)
             textToUpdate.text = m.ToString();
     }
 
     public Vector3 GetPosition(Matrix4x4 m)
     {
         return new Vector3(m[0, 3], m[1, 3], m[2, 3]);
     }
 
     public Vector3 GetScale(Matrix4x4 m)
     {
         return new Vector3
             (m.GetColumn(0).magnitude, m.GetColumn(1).magnitude, m.GetColumn(2).magnitude);
     }
 
     public Quaternion GetRotation(Matrix4x4 m)
     {
         Vector3 s = GetScale(m);
 
         // Normalize Scale from Matrix4x4
         float m00 = m[0, 0] / s.x;
         float m01 = m[0, 1] / s.y;
         float m02 = m[0, 2] / s.z;
         float m10 = m[1, 0] / s.x;
         float m11 = m[1, 1] / s.y;
         float m12 = m[1, 2] / s.z;
         float m20 = m[2, 0] / s.x;
         float m21 = m[2, 1] / s.y;
         float m22 = m[2, 2] / s.z;
 
         Quaternion q = new Quaternion();
         q.w = Mathf.Sqrt(Mathf.Max(0, 1 + m00 + m11 + m22)) / 2;
         q.x = Mathf.Sqrt(Mathf.Max(0, 1 + m00 - m11 - m22)) / 2;
         q.y = Mathf.Sqrt(Mathf.Max(0, 1 - m00 + m11 - m22)) / 2;
         q.z = Mathf.Sqrt(Mathf.Max(0, 1 - m00 - m11 + m22)) / 2;
         q.x *= Mathf.Sign(q.x * (m21 - m12));
         q.y *= Mathf.Sign(q.y * (m02 - m20));
         q.z *= Mathf.Sign(q.z * (m10 - m01));
 
         // q.Normalize()
         float qMagnitude = Mathf.Sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z);
         q.w /= qMagnitude;
         q.x /= qMagnitude;
         q.y /= qMagnitude;
         q.z /= qMagnitude;
 
         return q;
     }
 
     public Vector3 QuaternionToEuler(Quaternion q)
     {
         Vector3 result;
 
         float test = q.x * q.y + q.z * q.w;
         // singularity at north pole
         if (test > 0.499)
         {
             result.x = 0;
             result.y = 2 * Mathf.Atan2(q.x, q.w);
             result.z = Mathf.PI / 2;
         }
         // singularity at south pole
         else if (test < -0.499)
         { 
             result.x = 0;
             result.y = -2 * Mathf.Atan2(q.x, q.w);
             result.z = -Mathf.PI / 2;
         }
         else
         {
             result.x = Mathf.Rad2Deg * Mathf.Atan2(2 * q.x * q.w - 2 * q.y * q.z, 1 - 2 * q.x * q.x - 2 * q.z * q.z);
             result.y = Mathf.Rad2Deg * Mathf.Atan2(2 * q.y * q.w - 2 * q.x * q.z, 1 - 2 * q.y * q.y - 2 * q.z * q.z);
             result.z = Mathf.Rad2Deg * Mathf.Asin(2 * q.x * q.y + 2 * q.z * q.w);
 
             if (result.x < 0) result.x += 360;
             if (result.y < 0) result.y += 360;
             if (result.z < 0) result.z += 360;
         }
         return result;
     }
 }
Comment
Add comment · Show 1 · 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 JASONYJY · Jun 10, 2018 at 02:58 PM 0
Share

If the value of scale is negative,the result of calculation is incorrect

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Quaternion to Matrix Conversion Error - Camera Script 0 Answers

Having trouble instantiating a gameobject with rotation 0 Answers

Creating a Matrix4x4 from an Object's Transform 1 Answer

How to write a script to disable position and rotation tracking for VR 0 Answers

Function similar to Quaternion.Angle for Scale or Position? 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