我在这里遇到了一些问题,我想要一些帮助。我正试图找到一个旋转,允许我让一个物体跟随玩家(始终面对它)。 我首先尝试做十字产品,点和旋转,但这只是无法正常工作。 然后我继续将它分解为两个旋转(偏航和俯仰)和锁定滚动。它现在有效,但仅限于某些方向(我相信四分之一圆,但可能更少)。 这是我目前的代码:
XMVECTOR newDir = Vec3DtoDX((Player->Position - InternalEntity->Position).getNormalized());
XMVECTOR orig = XMVectorSet(0,0,1,0);
XMVECTOR xNewDir,xOrigDir,yNewDir,yOrigDir;
xOrigDir = XMVectorSet(0,1,0,0); // (y,z)
yOrigDir = XMVectorSet(0,1,0,0); // (x,z)
xNewDir = XMVectorSet(newDir.m128_f32[1],newDir.m128_f32[2],0,0);
yNewDir = XMVectorSet(newDir.m128_f32[0],newDir.m128_f32[2],0,0);
float xAngle = XMVector2AngleBetweenVectors(xNewDir,xOrigDir).m128_f32[0];
float yAngle = XMVector2AngleBetweenVectors(yNewDir,yOrigDir).m128_f32[0];
XMVECTOR rotDX = XMQuaternionRotationRollPitchYaw(xAngle,yAngle,0);
PxQuat rot = VecDXto4D<PxQuat>(rotDX);
如果我面向靠近Z轴的物体,这里工作正常 http://imgur.com/oNNNRXo
如果我移动更多,它就会变成这样: http://imgur.com/xFIEzdg
任何帮助将不胜感激。
编辑: 我已经尝试从十字架和点的acos角度创建四元数。事实上,这是我的第一次。问题是它无法正常工作。以下是我的表现:
PxVec3 newDir = (Player->Position - InternalEntity->Position).getNormalized();
PxVec3 orig(0,0,1);
PxVec3 axis = newDir.cross(orig);
float angle = XMVector3AngleBetweenVectors(Vec3DtoDX(newDir),Vec3DtoDX(orig)).m128_f32[0];
PxQuat rot(angle,axis);
其中XMVector3AngleBetweenVectors是:
XMVECTOR L1 = XMVector3ReciprocalLength(V1);
XMVECTOR L2 = XMVector3ReciprocalLength(V2);
XMVECTOR Dot = XMVector3Dot(V1, V2);
L1 = XMVectorMultiply(L1, L2);
XMVECTOR CosAngle = XMVectorMultiply(Dot, L1);
CosAngle = XMVectorClamp(CosAngle, g_XMNegativeOne.v, g_XMOne.v);
return XMVectorACos(CosAngle);
这导致以下屏幕: http://imgur.com/vlMPAwG 并且:http://imgur.com/PEz1aMc
任何帮助?
答案 0 :(得分:0)
首先,您必须知道定义要面向查看器的对象平面的矢量。让我们说这个向量是'向前'。通常,此向量可以是转换为世界空间的对象空间中的局部z轴向量。
一旦你有这个矢量,你必须找到旋转轴:
axis = CrossProduct(newDir,forward)
和旋转角度:
angle = acos(DotProduct(newDir,forward))
所有向量必须是单一的。
获得角度和轴后,只需计算定义此旋转的四元数。您可以使用以下API函数来执行此操作:RotationAxis或从头开始构建四元数。
最后,一旦你有四元数,只需用它旋转你的对象。
答案 1 :(得分:0)
好的,所以经过很多麻烦后,这是一个有效的代码:
// Using PxExtendedVec3 to use double
// For ground enemies, just flatten the positions across the Up vector ( set y to 0 in this case )
PxExtendedVec3 newDir = Vec3Dto3D<PxExtendedVec3>(Vec3Dto3D<PxExtendedVec3>(Player->Position) - Vec3Dto3D<PxExtendedVec3>(InternalEntity->Position));
newDir.y = 0;
newDir.normalize();
PxExtendedVec3 orig(0,0,1);
PxExtendedVec3 axis = newDir.cross(orig);
double angle = -asin(_Core::Clamp<double>(axis.magnitude(),-1.0,1.0));
axis.normalize();
// Compensate the [-pi/2,pi/2] range of asin
if(newDir.dot(Vec3Dto3D<PxVec3>(orig)) < 0.0)
angle = XM_PIDIV2 - angle + XM_PIDIV2;//angle += XM_PI/2.0;
PxQuat rot(angle,Vec3Dto3D<PxVec3>(axis));
其中PxExtendedVec3是双精度矢量,XM_PIDIV2是pi / 2: 希望这对某些人有所帮助,我已经使用了很长时间了。
编辑:一点评论。在这种情况下,我将Y设置为0,因为这会删除一些不需要的滚动,但请考虑该行是可选的,因此如果您愿意,请使用它。此外,这给出ABSOLUTE旋转,而不是相对于最后一次旋转。