Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Actionscript 3 用四元数旋转_Actionscript 3_3d_Rotation_Quaternions - Fatal编程技术网

Actionscript 3 用四元数旋转

Actionscript 3 用四元数旋转,actionscript-3,3d,rotation,quaternions,Actionscript 3,3d,Rotation,Quaternions,在ActionScript3中,我有一个3D对象,它围绕x、y和z轴随机旋转。我想让它停在适当的位置,然后在它的旋转之间,以尽可能短的路线旋转到指定的旋转。四元数似乎是这项工作的合适工具,但我不知道如何正确地处理它。我试着做两个轴的角度旋转,然后把它转换成四元数。这是到目前为止我的测试代码 var startV3DV:Vector.<Vector3D> = new <Vector3D>[positionV3D, new Vector3D(0,1,0,0), scaleV3

在ActionScript3中,我有一个3D对象,它围绕x、y和z轴随机旋转。我想让它停在适当的位置,然后在它的旋转之间,以尽可能短的路线旋转到指定的旋转。四元数似乎是这项工作的合适工具,但我不知道如何正确地处理它。我试着做两个轴的角度旋转,然后把它转换成四元数。这是到目前为止我的测试代码

var startV3DV:Vector.<Vector3D> = new <Vector3D>[positionV3D, new Vector3D(0,1,0,0), scaleV3D];
var endV3DV:Vector.<Vector3D> = new <Vector3D>[positionV3D, new Vector3D(0,1,0,Math.PI), scaleV3D];
var recomposeV3DV:Vector.<Vector3D> = new <Vector3D>[positionV3D, new Vector3D(0,0,0,0), scaleV3D];

TweenMax.to(startV3DV[1], 2, {x:endV3DV[1].x, y:endV3D[1].y, z:endV3D[1].z, w:endV3D[1].w, onUpdate:quat});

var quatV3D:Vector3D = new Vector3D();
function quat():void {
    quatV3D.x = currentV3D[1].x * Math.sin(currentV3D[1].w * .5);
    quatV3D.y = currentV3D[1].y * Math.sin(currentV3D[1].w * .5);
    quatV3D.z = currentV3D[1].z * Math.sin(currentV3D[1].w * .5);
    quatV3D.w = Math.cos(currentV3D[1].w * .5);
    recomposeV3DV[1] = quatV3D;
    myMatrix3D.recompose(recomposeV3DV,"quaternion");
}
var startV3DV:Vector.=新的[positionV3D,新的Vector3D(0,1,0,0),scaleV3D];
var endV3DV:向量=新的[positionV3D,新的Vector3D(0,1,0,Math.PI),scaleV3D];
var recomposeV3DV:向量=新的[positionV3D,新的Vector3D(0,0,0,0),scaleV3D];
TweenMax.to(startV3DV[1],2,{x:endV3DV[1].x,y:endV3D[1].y,z:endV3D[1].z,w:endV3D[1].w,onUpdate:quat});
var quatV3D:Vector3D=新的Vector3D();
函数quat():void{
quatV3D.x=currentV3D[1].x*Math.sin(currentV3D[1].w*.5);
quatV3D.y=currentV3D[1].y*Math.sin(currentV3D[1].w*.5);
quatV3D.z=currentV3D[1].z*Math.sin(currentV3D[1].w*.5);
quatV3D.w=Math.cos(currentV3D[1].w*.5);
recoposev3dv[1]=quatV3D;
myMatrix3D.重新组合(重新组合3DV,“四元数”);
}

它实际上会使对象围绕其y轴的旋转缩短一段时间,但当它达到PI/2时,它会出错,我在重新组合行上得到“ArgumentError:Error#2004:其中一个参数无效”,我认为这意味着其中一个quatV3D属性不符合四元数公式。有没有关于如何正确执行此操作的想法?

我无法用您提供的数据重现它。但在使用currentV3D向量时,您似乎正在使用startV3DV,这在示例代码中没有提到。它可能包含无效数据,如0轴或0刻度

此外,这不是四元数用于粗花间的方式。这里您似乎要做的是在两个轴/角度表示之间切换,然后在每次更新时从中生成一个四元数。您还可以使用内置的“axisAngle”旋转模式直接重建。这可能不会达到您预期的效果,因为1)不能保证采用最短的角度,2)当轴不同时-所有关于插值的赌注都被取消;)

您应该做的是将开始和结束旋转转换为四元数,方法与当前在quat()中所做的相同,并在这些旋转之间进行插值。您仍然需要更正最短路径:如果两个四元数之间的四分量点积<0,则需要对其中一个四元数的所有分量求反。最后,您必须重新规范化四元数(同样是四分量,旋转四元数必须是单位长度)

如果您想坚持使用TweenMax,您仍然可以这样做(可能包含一些粗心的错误,但您应该了解要点):

t=0;
TweenMax.to(this,2,{t:1,onUpdate:lerp});
函数lerp():void
{
变量x:编号,y:编号,z:编号,w:编号;
变量w1:Number=start.w,x1:Number=start.x,y1:Number=start.y,z1:Number=start.z;
变量w2:Number=end.w,end:Number=end.x,y2:Number=end.y,z2:Number=end.z;
变量len:数字;
//最短方向
如果(x1*x2+y1*y2+z1*z2+w1*w2<0){
x2=-x2;
y2=-y2;
z2=-z2;
w2=-w2;
}
x=x1+t*(x2-x1);
y=y1+t*(y2-y1);
z=z1+t*(z2-z1);
w=w1+t*(w2-w1);
len=1.0/数学sqrt(x*x+y*y+z*z+w*w);
quatV3D.x=x*len;
quatV3D.y=y*len;
quatV3D.z=z*len;
quatV3D.w=w*len;
recoposev3dv[1]=quatV3D;
myMatrix3D.重新组合(重新组合3DV,“四元数”);
}
您可能还想研究球面线性插值(“slerp”),它们与线性插值不同,具有恒定的角速度。我会很懒,直接带你去几年前我写的Away3D四元数课程:


希望这有帮助

事实证明Matrix3D已经可以使用四元数执行LERP:

var startM3D:Matrix3D = myObject.transform.matrix3D.clone();
var endM3D:Matrix3D = new Matrix3D(new <Number>[-1.2000000476837158,0,1.0490733615142744e-7,0,0,1.2000000476837158,0,0,-1.0490733615142744e-7,0,-1.2000000476837158,0,220,150,0,1]);
var currentM3D:Matrix3D = new Matrix3D();

var t:Number = 0;
TweenMax.to(this, 4, {t:1, onUpdate:lerp});

function lerp():void {
    currentM3D = Matrix3D.interpolate(startM3D, endM3D, t);
    myObject.transform.matrix3D = currentM3D;
}
var startM3D:Matrix3D=myObject.transform.Matrix3D.clone();
var endM3D:Matrix3D=新的Matrix3D(新[-1.2000000476837158,0,1.0490733615142744e-7,0,0,1.2000000476837158,0,0,-1.0490733615142744e-7,0,-1.2000000476837158,020150,0,1]);
var currentM3D:Matrix3D=新的Matrix3D();
变量t:数值=0;
TweenMax.to(this,4,{t:1,onUpdate:lerp});
函数lerp():void{
currentM3D=矩阵3d.插值(开始tM3d,结束m3d,t);
myObject.transform.matrix3D=当前M3d;
}
这孩子看起来不错。不过我也会试试你的SLERP

var startM3D:Matrix3D = myObject.transform.matrix3D.clone();
var endM3D:Matrix3D = new Matrix3D(new <Number>[-1.2000000476837158,0,1.0490733615142744e-7,0,0,1.2000000476837158,0,0,-1.0490733615142744e-7,0,-1.2000000476837158,0,220,150,0,1]);
var currentM3D:Matrix3D = new Matrix3D();

var t:Number = 0;
TweenMax.to(this, 4, {t:1, onUpdate:lerp});

function lerp():void {
    currentM3D = Matrix3D.interpolate(startM3D, endM3D, t);
    myObject.transform.matrix3D = currentM3D;
}