如何在冻结后获取对象的实际旋转?

huangapple go评论85阅读模式
英文:

How to get object's actual rotation after freeze?

问题

你好,我可以为你翻译以下内容:

你怎么样才能在冻结之后获取物体的实际旋转角度?

例如:

# 创建一个立方体
CudeTransformNode = cmds.polyCube()[0]

# 绕X轴旋转20度
cmds.setAttr(f"{CudeTransformNode}.rotateX", 20)
# * 现在的情况是
#   - 冻结的旋转X:0
#   - 旋转平移X:20
#   - 实际旋转X:20

# 冻结平移
cmds.makeIdentity(CudeTransformNode, a=1, r=1)
# * 然后的情况是
#   - 冻结的旋转X:20
#   - 旋转平移X:0
#   - 实际旋转X:20

# 为了测试,再绕X轴旋转30度。
cmds.setAttr(f"{CudeTransformNode}.rotateX", 30)
# * 现在的情况是
#   - 冻结的旋转X:20
#   - 旋转平移X:30
#   - 实际旋转X:50

# 从这里开始
# 如何获取实际旋转
Foo() == 50
# 或者如何获取冻结的旋转
Boo() == 20

上面的示例中,我的问题是如何获取真正的旋转角度?(如何获取50或20)

因为我找到的每种方法都只告诉你如何获取当前的旋转(旋转平移)。

供参考:

所有这些都告诉你要使用矩阵来获取旋转,但从原生命令返回的矩阵始终只反映了平移值。因此,在上面的示例中,计算出的输出将始终为30(当前旋转)。

例如:

import maya.api.OpenMaya as om

Matrix = cmds.xform(CudeTransformNode, q=1, m=1)
_M = om.MMatrix(Matrix)
_TM = om.MTransformationMatrix(_M)
_rotation_radiants = _TM.rotation()

_rotation_radiants[0]  # 等于30度

# 但我想要获取20或50...

也许更正确的问题是如何获取总体旋转矩阵?

谢谢你的建议!

英文:

Hi, how can I get object's actual rotation after freeze?

For instance :

# create a cube
CudeTransformNode = cmds.polyCube()[ 0 ]


# rotate X 20 degree.
cmds.setAttr( f"{CudeTransformNode}.rotateX" , 20 )
# * now its like 
#   - freezed rotation X : 0
#   - rotation translation X : 20
#   - actual rotation X : 20

# freeze translation.
cmds.makeIdentity( CudeTransformNode , a = 1 , r = 1 )
# * then its like 
#   - freezed rotation X : 20
#   - rotation translation X : 0
#   - actual rotation X : 20


# for test, rotate X 30 more degree.
cmds.setAttr( f"{CudeTransformNode}.rotateX" , 30 )
# * now its like 
#   - freezed rotation X : 20
#   - rotation translation X : 30
#   - actual rotation X : 50

# From here
# how to get actual rotation
Foo() == 50
# or how to get freezed rotation
Boo() == 20

** Above example, my question is how can we get the real rotation??( how to get 50 or 20 )**

Because every method I found is only telling you how to get current rotation( * rotation translation )

For reference :

All these are telling you to use Matrix to get rotation, but the Matrix returned from native commands are always reflecting the translated values only. Therefore, in above example, the calculated output will always be 30( current rotation ).

For instance :

import maya.api.OpenMaya as om

Matrix = cmds.xform( CudeTransformNode, q = 1 , m = 1 ) 
_M = om.MMatrix( Matrix )
_TM = om.MTransformationMatrix( _M )
_rotation_radiants = _TM.rotation()

_rotation_radiants[ 0 ] <-- # equals to 30 degree

# But I want to get 20 or 50...

Maybe the question is more correct to say, how to get overall rotation matrix?

Thank you for your advices!!

答案1

得分: 1

正如haggy krey在评论中指出的,没有直接的方法在冻结变换后检索旋转,因为您将变换应用于组件并将变换节点归零。旋转信息会丢失。

正如您自己提到的,您可以通过使用包围盒来确定冻结后的比例,但这仅在您使用基本形状时有效,其中它们的包围盒等效于应用某种比例。

您究竟想要实现什么?

如果您想要恢复/确定某个原始方向,那么您可以尝试使用向量数学来计算旋转 - 从两个顶点、一个面的法线向量或类似方式。但这需要这些组件与原始旋转对齐。

import maya.cmds as cmds

angle_vector = [0.5, 0.7, 1.0]
up_vector = [0.0, 1.0, 0.0]

euler = cmds.angleBetween(euler=True, vector1=angle_vector, vector2=up_vector)

print(euler)

另一种方法可能是创建一些辅助节点(例如,一个空的组),在这些节点上不冻结旋转。然后,您可以简单地添加或减去立方体和辅助节点的旋转。

最后,您还可以将原始旋转存储在对象的自定义属性中,并从立方体的当前旋转中添加或减去这些值。

import maya.cmds as cmds

cube = cmds.polyCube()[0]
cmds.setAttr(f"{cube}.rx", 30)

cmds.addAttr(cube, ln="originalRotationX", sn="orx", at="double", dv=0)
cmds.setAttr(f"{cube}.originalRotationX", e=True, keyable=True)  # show in Channel Box

rotationX = cmds.getAttr(f"{cube}.rx")
cmds.setAttr(f"{cube}.originalRotationX", rotationX)
英文:

As haggy krey has pointed out in the comments, there is no direct way to retrieve the rotation after freezing the transform, since you are applying the transformation to the components and zero out the transform node. The rotation information is simply lost.

As you mention yourself, you can determine the scale after freezing, by using the bounding box, but this only works as long as you use primitives, where their bounding box would be equivalent to applying some scale.

What exactly are you trying to accomplish?

If you are trying to restore/determine some original orientation, then you can potentially use vector math to calculate a rotation - either from two vertices, the normal vector of a face or similar. But it would require that those components align with the original rotation.

import maya.cmds as cmds

angle_vector = [0.5, 0.7, 1.0]
up_vector = [0.0, 1.0, 0.0]

euler = cmds.angleBetween(euler=True, vector1=angle_vector, vector2=up_vector)

print(euler)

Another approach could be to create some helper node (e.g., an empty group), where you don't freeze rotations. Then you could simply add or subtract the rotation of the cube and the helper node.

Finally, you could also store the original rotation in some custom attributes on the object, and add or subtract those values from the cube's current rotation.

import maya.cmds as cmds

cube = cmds.polyCube()[0]
cmds.setAttr(f"{cube}.rx", 30)

cmds.addAttr(cube, ln="originalRotationX", sn="orx", at="double", dv=0)
cmds.setAttr(f"{cube}.originalRotationX", e=True, keyable=True)  # show in Channel Box

rotationX = cmds.getAttr(f"{cube}.rx")
cmds.setAttr(f"{cube}.originalRotationX", rotationX)

huangapple
  • 本文由 发表于 2023年7月13日 16:12:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76677247.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定