对于Unity3D中的项目,我试图通过更改框架来转换世界上的所有对象。这意味着旋转,平移和缩放新框架的原点以匹配旧框架的原点,然后将此操作应用于所有其他对象(包括旧的原点)。 为此,我需要一个广义的3维(因此为4x4)转换矩阵。
我已经看过使用Unity内置的Matrix4x4.TRS()方法,但这似乎没有用,因为它仅将平移,旋转和缩放应用于定义的点。 我要寻找的是更改框架,其中新框架相对于原始框架具有不同的原点,旋转和比例。
为显示问题,我制作了一个小的GIF(我目前有3D的工作版本,没有使用Matrix,也没有任何旋转): https://gyazo.com/8a7ab04dfef2c96f53015084eefbdb01
每个球体的值:
Origin1 (Red Sphere)
Before:
Position (-10, 0, 0)
Rotation (0,0,0)
Scale (4,4,4)
After:
Position (10, 0, 0)
Rotation (0,0,0)
Scale (8,8,8)
-
Origin2 (Blue Sphere)
Before:
Position (-20, 0, 0)
Rotation (0,0,0)
Scale (2,2,2)
After:
Position (-10, 0, 0)
Rotation (0,0,0)
Scale (4,4,4)
-
World-Object (White Sphere)
Before:
Position (0, 0, 10)
Rotation (0,0,0)
Scale (2,2,2)
After:
Position (30, 0, 20)
Rotation (0,0,0)
Scale (4,4,4)
当前,我只是简单地将两个原点之间的Vector取下,将其缩放为两个原点之间的差,然后将其应用到原始(第一个)原点的新位置之上。 当将旋转应用于两个原点中的任何一个时,这当然是行不通的。
// Position in original axes
Vector3 positionBefore = testPosition.TestPosition - origin.TestPosition;
// Position in new axes
Vector3 positionAfter = (positionBefore * scaleFactor) + origin.transform.position;
我正在寻找的是一个可以做到这一点的矩阵(包括旋转,这样Origin2旋转到了转换之前Origin1的旋转,所有其他对象都移到了正确的位置)。
有没有一种方法可以在不对每个Vector进行完全计算的情况下进行此操作(即,变换Vector之前的位置)?它需要每帧应用于(非常)大量的对象,因此需要(相当)优化。
编辑:缩放比例总是一致的。
答案 0 :(得分:0)
也许还有其他解决方案,但这就是我要做的
将您的对象包装到以下层次结构中
WorldAnchorObject
|- Red Sphere
|- Blue Sphere
|- White Sphere
确保WorldAnchorObject
拥有
position: 0,0,0
rotation: 0,0,0
localScale: 1,1,1
定位/旋转/缩放球体(相对于WorldAnchorObject
现在会发生)
现在剩下的就是对WorldAnchorObject
->进行变形,它将移动,缩放和旋转其他任何东西,并保持相对转换不变。
您如何精确地移动世界锚点。我想您想一直居中并规范化某些子对象。也许像
public void CenterOnObject(GameObject targetCenter)
{
var targetTransform = targetCenter.transform;
// The localPosition and localRotation are relative to the parent
var targetPos = transform.localPosition;
var targetRot = targetTransform.localRotation;
var targetScale = targetTransform.localScale;
// First reset everything
transform.position = Vector3.zero;
transform.rotation = Quaternion.Idendity;
transform.localScale = Vector3.one;
// set yourself to inverted target position
// After this action the target should be on 0,0,0
transform.position = targetPos * -1;
// Scale yourself relative to 0,0,0
var newScale = Vector3.one * 1/targetScale.x;
ScaleAround(gameObject, Vector3.zero, newScale);
// Now everything should be scaled so that the target
// has scale 1,1,1 and still is on position 0,0,0
// Now rotate around 0,0,0 so that the rotation of the target gets normalized
transform.rotation = Quaternion.Inverse(targetRotation);
}
// This scales an object around a certain pivot and
// takes care of the correct position translation as well
private void ScaleAround(GameObject target, Vector3 pivot, Vector3 newScale)
{
Vector3 A = target.transform.localPosition;
Vector3 B = pivot;
Vector3 C = A - B; // diff from object pivot to desired pivot/origin
float RS = newScale.x / target.transform.localScale.x; // relative scale factor
// calc final position post-scale
Vector3 FP = B + C * RS;
// finally, actually perform the scale/translation
target.transform.localScale = newScale;
target.transform.localPosition = FP;
}
现在,您称它为传递一个孩子,例如,
worldAnchorReference.CenterOnObject(RedSphere);
应该会导致您想要实现的目标。 (在智能手机上安装了此工具,因此没有任何保证,但是如果遇到问题,我可以在再次使用PC时立即对其进行检查。))
答案 1 :(得分:0)
没关系。 在创建TRS之前必须将旋转和缩放应用于平移 D'Oh