2013-08-13 1 views
0

로프 물리 시뮬레이션을 C++ (스프링 물리학)으로 만드는 중입니다. 나는 몇 개의 "뼈"(위치, 무게 등이있는 일부 입자 [질량])로 구성된 기본 로프 이동을 성공적으로 구현했습니다. 각 파티클의 위치가 계산 될 때, 나는 스킨 된 메쉬 뼈대의 해당 뼈에 각각을 할당합니다. 내가 원하는 것은 그것의 자 입자로 회전되도록 입자의 회전을 계산하는 것이다 (원 뼈 [입자의 위치]의 머리, 검은 점은, 그 아이의 머리에 연결해야 꼬리입니다 등등 ...) : 그것을 불행하게도머리에서 꼬리까지 회전을 만드는 방법은 무엇입니까?

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); 

: the problem visualized 은 좀 스레드를 보았다이 온 : Finding quaternion representing the rotation from one vector to another 내 프로젝트에 허용 대답을 구현하기 위해 노력했다, 그래서 나는이있어 어떤 이유로 든 나를 위해 일하지 않았으므로 실패한 다른 시도를했습니다.

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); 

누군가가 나에게 대안을 게시하고 가난한 페인트 기술에 대해 사과한다면 매우 감사 할 것입니다.

답변

1

합니다 ... XMStore/XMLoad 기능이 그 이유가 바로 XMVECTOR의 구성원을 사용하지 마십시오.

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(&lt2,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)); 

UPDATE : 그들은 신중하게 사용되지만,보다 더 자주는 아니지만, 그들은 기원을 중심으로 끝낼 결과를 얻을 경우

위의 솔루션이 작동합니다. 이는 참조 변경으로 인한 것입니다. 원하는 동작을 생산하려면 (가정 지점이 구조체/클래스 포인트로 표현됩니다) 다음을 수행해야합니다

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; 
} 

이 최종 변환을 형성하기 위해 함께 계층 구조의 모든 이전 뼈의 움직임을 구성합니다 함수에 전달 된 점의 행렬입니다.

위의 솔루션은 작은 모델 (그래서 < 10 ~ 20 뼈나)에 대한 작동하지만 지금의 약자로 훨씬 더 큰 모델, 당신은 재귀로, 계산 속도를 높일뿐만 아니라 거기에 memoization algorithm를 원할 것입니다 루트 뼈에 대한 변환 행렬을 여러 번 계산합니다. ,

+0

내가 그것을 밖으로 시도, 답변 주셔서 감사하지만, 출력은 여전히 ​​수정되지 않고 (동일, 실제로되면서), 뼈는 주위 회전 보인다 무작위로하지만 알고 좋은, 문제는 다른 곳에 있음 그때. 또한 XMVECTOR에 직접 액세스하면 어떤 문제가 발생할 수 있는지 이해하지 못합니다. :) –

+1

XMVECTOR 구성원의 내용은 XMFLOAT4 구조의 구조를 알고 예상 한대로 정렬되지 않습니다. 또한, XMVECTOR 구현의 세부 사항은 버전마다, 그리고 플랫폼마다 다를 수 있습니다. 마지막으로, 직접 액세스가 가장 자주 수행되면 성능이 저하됩니다. 자세한 내용은 [이 링크] (http://msdn.microsoft.com/en-us/library/windows/desktop/ee420742(v=vs.85) .aspx)를 참조하십시오. – Alex

+0

시뮬레이션이 완료된 후에 모든 뼈/입자/질량에 대한 절대 좌표가 있기 때문에 상위에주의하지 않고 두 지점 사이에서 회전을 설정하면됩니다.물론 첫 번째 뼈조차도 올바르지 않은 회전을합니다 (유휴 상태에서 X 축을 중심으로 약간 회전하고, 이상하게도 모든 다른 뼈와 함께합니다). 나는 그 문제가 여전히 다른 곳에 있다고 생각한다. –