我正在用c ++(弹簧物理学)进行绳索物理模拟。我成功地实施了基本的绳索运动,它由几个“骨头”组成(只是一些具有位置,重量等的颗粒[质量])。计算每个粒子的位置时,我将它们分配给蒙皮网格骨架的相应骨骼。 我想要的是计算一个粒子的旋转,使它旋转到它的子粒子(圆是骨头[粒子的位置],黑点是尾巴,它应该连接到它的孩子的头部,等......): 我查了一些帖子,然后来到这里:Finding quaternion representing the rotation from one vector to another并试图实现我项目的接受答案,所以我得到了这个:
XMVECTOR q;
XMVECTOR a = XMVector3Cross(head,tail);
XMVECTOR lh=XMVector3Length(head),lt=XMVector3Length(tail),dot=XMVector3Dot(head,tail);
q.m128_f32[0] = a.m128_f32[0]; //assigning the x coordinate
q.m128_f32[1] = a.m128_f32[1]; //assigning the y coordinate
q.m128_f32[2] = a.m128_f32[2]; //assigning the z coordinate
q.m128_f32[3] = sqrt(pow(lh.m128_f32[0],2)*pow(lt.m128_f32[0],2)) + dot.m128_f32[0]; //assigning the w coordinate
return XMQuaternionNormalize(q);
不幸的是,由于某种原因它没有对我有用,所以尝试了另一个也失败了:
XMVECTOR Head = XMVector3Normalize( head );
XMVECTOR Tail = XMVector3Normalize( tail );
float angle = acos(XMVector3Dot(Head,Tail).m128_f32[0]); //acos(dot(Head,Tail))
XMVECTOR axis = XMVector3Normalize(XMVector3Cross(Head,Tail));
XMVECTOR q = XMQuaternionRotationAxis(axis,angle);
如果有人会给我发一个替代解决方案,我会非常感激,并为糟糕的油漆技巧感到抱歉。
答案 0 :(得分:1)
不要直接使用XMVECTOR的成员......出于这个原因,XMStore / XMLoad函数就在那里。最底层的解决方案如下:
XMVECTOR Head = XMVectorNormalize(head);
XMVECTOR Tail = XMVectorNormalize(tail);
float angle = 0.0f;
XMStoreFloat(&angle,XMVector3AngleBetweenVectors(Head,Tail));
XMVECTOR axis = XMVectorCross(Head,Tail);
return XMQuaternionAxisAngle(axis,angle);
通过这种方式,您可以避免直接访问XMVECTOR,这可能有助于解决问题。
您还应该使用第一个解决方案,但同样应该使用XMStore / XMLoad函数而不是直接访问。
XMFLOAT3 a;
XMStoreFloat3(&a,XMVector3Cross(head,tail));
float lh2, lt2, dot;
XMStoreFloat(&lh2,XMVector3Dot(head,head)); //this calculates the length squared.
XMStoreFloat(<2,XMVector3Dot(tail,tail)); //same as above
XMStoreFloat(&dot,XMVector3Dot(head,tail));
XMFLOAT4 q;
q.x = a.x; //assigning the x coordinate
q.y = a.y; //assigning the y coordinate
q.z = a.z; //assigning the z coordinate
q.w = sqrt(lh2*lt2) + dot; //assigning the w coordinate
return XMQuaternionNormalize(XMLoadFloat4(&q));
更新:
如果仔细使用上述解决方案,它们将起作用,但通常情况下,它们会产生最终以原点为中心的结果。这是因为参考的变化。要产生所需的行为,您需要执行以下操作(假设点由结构/类Point表示):
XMMATRIX CalculateTransform(Point p)
{
XMVECTOR pos=XMLoadFloat3(&p.GetPosition());
//Get your new rotation quaternion using the methods above
XMMATRIX r=XMMatrixRotationQuaternion(CalculateRotation(p.GetHead(),p.GetTail()));
XMMATRIX t=XMMatrixTranslationFromVector(pos);
if(p.HasParent())
return CalculateTransform(p.GetParent())*r*t;
else
return r*t;
}
这将组成层次结构中每个先前骨骼的运动,以形成传递给函数的点的最终变换矩阵。
上述解决方案适用于小型模型(&lt; 10-20骨骼左右),但对于更大的模型,您还需要memoization algorithm来加速计算,如递归现在,它将多次计算根骨的变换矩阵。