2011-09-29 27 views
11

Tôi đang viết thư cho nhà nhập khẩu COLLADA của riêng tôi. Tôi đã nhận được khá xa, tải mắt lưới và vật liệu và như vậy. Nhưng tôi đã đánh một hình ảnh động, đặc biệt là: xoay vòng.COLLADA: Đảo ngược ràng buộc đặt ra trong không gian sai?

Công thức Tôi đang sử dụng cho skinning mắt lưới của tôi là thẳng về phía trước:

weighted; 
for (i = 0; i < joint_influences; i++) 
{ 
    weighted += 
     joint[joint_index[i]]->parent->local_matrix * 
     joint[joint_index[i]]->local_matrix * 
     skin->inverse_bind_pose[joint_index[i]] * 
     position * 
     skin->weight[j]; 
} 
position = weighted; 

Và như xa như các tài liệu có liên quan, đây là công thức chính xác. Bây giờ, COLLADA chỉ định hai loại phép quay cho các khớp: cục bộ và toàn cục. Bạn phải ghép các vòng xoay với nhau để có được phép biến đổi cục bộ cho khớp.

Tài liệu COLLADA không phân biệt được giữa vòng quay địa phương của khớp và vòng xoay toàn cầu của khớp. Nhưng trong hầu hết các mô hình tôi đã thấy, các phép quay có thể có id là rotate (toàn cầu) hoặc jointOrient (cục bộ).

Khi tôi bỏ qua vòng quay toàn cục và chỉ sử dụng các phép quay cục bộ, tôi có được tư thế liên kết cho mô hình. Nhưng khi tôi thêm phép quay toàn cầu vào sự biến đổi cục bộ của khớp, những điều kỳ lạ bắt đầu xảy ra.

Đây là mà không sử dụng phép quay toàn cầu:

Bind pose

Và đây là với phép quay toàn cầu:

Weird

Trong cả hai ảnh chụp màn hình tôi đang vẽ bộ xương bằng đường nét, nhưng trong đầu tiên nó là vô hình bởi vì các khớp nằm bên trong lưới. Trong ảnh chụp màn hình thứ hai các đỉnh là tất cả các nơi!

Để so sánh, đây là những gì các ảnh chụp màn hình thứ hai nên trông giống như:

Collada viewer

Thật khó để nhìn thấy, nhưng bạn có thể thấy rằng các khớp đang ở vị trí chính xác trong ảnh chụp màn hình thứ hai.

Nhưng bây giờ điều kỳ lạ. Nếu tôi bỏ qua các ràng buộc nghịch pose theo quy định của COLLADA và thay vào đó lấy nghịch đảo của phụ huynh của doanh địa phương chuyển đổi lần của doanh địa phương chuyển đổi, tôi nhận được như sau:

enter image description here

Trong ảnh chụp màn hình này tôi vẽ một dòng từ mỗi đỉnh đến các khớp có ảnh hưởng. Thực tế là tôi nhận được ràng buộc đặt ra không phải là quá xa lạ, bởi vì công thức lúc này là:

world_matrix * inverse_world_matrix * position * weight 

Nhưng nó dẫn tôi để nghi ngờ rằng ràng buộc ngược COLLADA của pose là trong không gian sai.

Vì vậy, câu hỏi của tôi là: trong không gian nào COLLADA xác định tư thế ràng buộc nghịch đảo của nó? Và làm thế nào tôi có thể biến đổi ràng buộc nghịch đảo đặt ra không gian tôi cần?

+0

Bạn đã đọc phần "Skinning a Skeleton in COLLADA" của thông số 1.4.1 chưa? Công thức của bạn trông giống như – jterrace

Trả lời

10

Tôi bắt đầu bằng cách so sánh các giá trị của mình với giá trị tôi đã đọc từ Assimp (trình tải mô hình nguồn mở). Bước qua mã tôi nhìn vào nơi họ xây dựng ma trận liên kết của họ và ma trận ràng buộc nghịch đảo của họ.

Cuối cùng tôi đã kết thúc trong SceneAnimator::GetBoneMatrices, trong đó có những điều sau đây:

// Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose 
// Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform 
for(size_t a = 0; a < mesh->mNumBones; ++a) 
{ 
    const aiBone* bone = mesh->mBones[a]; 
    const aiMatrix4x4& currentGlobalTransform 
     = GetGlobalTransform(mBoneNodesByName[ bone->mName.data ]); 
    mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix; 
} 

globalInverseMeshTransform luôn là sắc, vì lưới không biến đổi bất cứ điều gì. currentGlobalTransform là ma trận liên kết, ma trận cục bộ của cha mẹ nối với ma trận cục bộ của khớp. Và mOffsetMatrix là ma trận liên kết nghịch đảo, xuất phát trực tiếp từ da.

Tôi đã tự kiểm tra giá trị của các ma trận này (có, tôi đã so sánh chúng trong cửa sổ xem) và chúng giống hệt nhau, có thể là 0,0001% nhưng không đáng kể. Vậy tại sao phiên bản của Assimp hoạt động và tôi không mặc dù công thức giống nhau?

Đây là những gì tôi nhận:

Inversed!

Khi Assimp cuối cùng tải lên các ma trận với shader skinning, họ làm như sau:

helper->piEffect->SetMatrixTransposeArray("gBoneMatrix", (D3DXMATRIX*)matrices, 60); 

Waaaaait một giây. Họ tải chúng lên transposed? Nó không thể dễ dàng như vậy. Không đời nào.

enter image description here

Yup.

Điều gì đó khác tôi đã làm sai: Tôi đã chuyển đổi tọa độ hệ thống phù hợp (cm đến mét) trước khi áp dụng ma trận da. Điều đó dẫn đến các mô hình bị méo hoàn toàn, bởi vì các ma trận được thiết kế cho hệ tọa độ gốc.

Google FUTURE

  • Đọc tất cả các biến đổi nút (xoay, dịch thuật, quy mô, vv) theo thứ tự bạn nhận được chúng.
  • Ghép chúng vào số ma trận cục bộ của doanh.
  • Lấy phụ huynh của khớp và nhân nó với ma trận cục bộ.
  • Lưu trữ dưới dạng ma trận liên kết .
  • Đọc thông tin về da.
  • Lưu trữ số ma trận bắt buộc ràng buộc của mối nối.
  • Lưu trữ khớp trọng số cho mỗi đỉnh.
  • Multiply ma trận bind với nghịch đảo ràng buộc gây ra ma trậntranspose nó, gọi nó là ma trận skinning.
  • Multiply ma trận skinning với vị trí lần so với doanh cân và thêm nó vào vị trí trọng.
  • Sử dụng vị trí có trọng số để hiển thị.

Xong!

+0

Câu hỏi cũ nhưng rất hữu ích! Cảm ơn nhiều! – Jas

1

BTW, nếu bạn chuyển đổi ma trận khi tải chúng thay vì chuyển ma trận ở cuối (có thể có vấn đề khi hoạt ảnh) bạn muốn thực hiện phép nhân khác nhau (phương pháp bạn sử dụng ở trên dường như là sử dụng skinning DirectX khi sử dụng các ma trận thân thiện OpenGL - ergo chuyển vị trí.)

Trong DirectX tôi chuyển đổi ma trận khi chúng được tải từ tệp và sau đó tôi sử dụng (trong ví dụ bên dưới, tôi chỉ áp dụng ràng buộc để đơn giản) :

XMMATRIX l_oWorldMatrix = XMMatrixMultiply (l_oBindPose, in_oParentWorldMatrix);

XMMATRIX l_oMatrixPallette = XMMatrixMultiply (l_oInverseBindPose, l_oWorldMatrix);

XMMATRIX l_oFinalMatrix = XMMatrixMultiply (l_oBindShapeMatrix, l_oMatrixPallette);