0

我在 Maya 中遇到了这个表达式的一些问题,基本上只要半径小于 1,计算就会被抛出太多。

float $radius = `getAttr prefix66_calculations_shape.rad`;
float $prevZval = `getAttr -time (frame -1) prefix66_driver.translateZ`;
float $prevXval = `getAttr -time (frame -1) prefix66_driver.translateX`;
float $Zval = prefix66_driver.translateZ - $prevZval;
float $Xval = prefix66_driver.translateX - $prevXval;
float $distance = ($Zval * $Zval) + ($Xval * $Xval);
float $direction;
$distance = sqrt($distance);
if ($prevZval > prefix66_driver.translateZ) {
    $direction = 360;
}
else { 
    $direction = 360;
}
float $rotation = ($distance / (2 * 3.142 * $radius)) * $direction;
print $rotation;
pCube1.rotateX = pCube1.rotateX + $rotation;

也许我的操作顺序是错误的?

4

2 回答 2

1

您的代码的旋转部分看起来不错。getAttr -time但是,您有一个 if/else 块在两种情况下都返回相同的内容,正如@joojaa 所提到的,如果您缓存翻译值,则可以避免。实际上,您应该避免getAttrsetAttr完全在表达式中。

相反,直接引用您想要的属性,Maya 将为您创建连接。当您重命名节点等时,这会更快并且更不容易出错。

要缓存平移值并计算位置变化,您可以向节点添加属性并在表达式中使用它们。

假设您有一个名为 wheel 的圆柱体,它围绕其局部 X 旋转,并且是一个名为 control 的组节点的父级:

添加向量属性:control.lastTranslate
添加向量属性:control.deltaTranslate
添加浮点属性:control.distance

这是一个表达式,它将存储平移的变化,然后根据行进的距离旋转轮子。

// When deltaTranslate is calculated, lastTranslate still has its previous value.
control.deltaTranslateX = control.translateX - control.lastTranslateX;
control.deltaTranslateY = control.translateY - control.lastTranslateY;
control.deltaTranslateZ = control.translateZ - control.lastTranslateZ;
control.lastTranslateX = control.translateX;
control.lastTranslateY = control.translateY;
control.lastTranslateZ = control.translateZ;
control.distance = mag(<<control.deltaTranslateX,control.deltaTranslateY,control.deltaTranslateZ>>);

// Get radius from history node (or somewhere) and move the wheel's hub off the floor.
wheel.translateY = polyCylinder1.radius;

// add rotation to the wheel 
float $tau = 6.283185307179586;
wheel.rotateX = wheel.rotateX + ( control.distance* -360.0) /  (polyCylinder1.radius * $tau );

最好通过动画而不是在视图中拖动节点来测试这种事情。

如果你想让车轮瞄准行驶方向,你可以在 translate + deltaTranslate 处添加一个定位器并连接一个瞄准约束。

例如

aimLocator.translateX = (control.deltaTranslateX / control.distance) + control.translateX;
aimLocator.translateY = (control.deltaTranslateY / control.distance) + control.translateY;
aimLocator.translateZ = (control.deltaTranslateZ / control.distance) + control.translateZ;

除以距离将使偏移正常化。您可能应该检查距离不为零。

于 2013-02-17T22:09:07.713 回答
0

我相信我已经弄清楚了:)

用新的翻译平均值查询旧的翻译平均值会给我一个正确或错误的答案,这是我改变方向所需要的。

还添加了一个 if 语句,如果球是静止的且旋转的,则轮子不会自动转动。

float $oldRotateAverage;
float $oldTransAverage;
float $direction;

nurbsCircle1.DeltaTranslateX = nurbsCircle1.translateX - nurbsCircle1.LastTranslateX;
nurbsCircle1.DeltaTranslateY = nurbsCircle1.translateY - nurbsCircle1.LastTranslateY;
nurbsCircle1.DeltaTranslateZ = nurbsCircle1.translateZ - nurbsCircle1.LastTranslateZ;
nurbsCircle1.LastTranslateX = nurbsCircle1.translateX;
nurbsCircle1.LastTranslateY = nurbsCircle1.translateY;
nurbsCircle1.LastTranslateZ = nurbsCircle1.translateZ;
nurbsCircle1.Distance = mag(<<nurbsCircle1.DeltaTranslateX,nurbsCircle1.DeltaTranslateY,nurbsCircle1.DeltaTranslateZ>>);

if ($oldTransAverage >= (nurbsCircle1.LastTranslateX + nurbsCircle1.LastTranslateY + nurbsCircle1.LastTranslateZ)){
    $direction = -360.00;
} else {
    $direction = 360.00;
};

if (Sh54_anim.auto == 1 )
{
    Sh54_point_grp.rotateZ -= nurbsCircle1.Distance * $direction / 2 / 3.14 / 2;    
};

if ((nurbsCircle1.rotateX + nurbsCircle1.rotateY + nurbsCircle1.rotateZ) != $oldRotateAverage && nurbsCircle1.Distance == $oldTransAverage){
    Sh54_anim.auto = 0;
} else {
    Sh54_anim.auto = 1;
};

Sh54_point_grp.back_up = Sh54_point_grp.translateX;
$oldRotateAverage = nurbsCircle1.rotateX + nurbsCircle1.rotateY + nurbsCircle1.rotateZ;
$oldTransAverage = nurbsCircle1.translateX + nurbsCircle1.translateY + nurbsCircle1.translateZ;
于 2013-02-19T08:33:41.467 回答