Làm cách nào để áp dụng hoạt hình khung xương từ tệp .x (Direct X)?


8

Sử dụng định dạng .x để xuất mô hình từ Blender, tôi có thể tải lưới, phần ứng và hình động. Tôi không có vấn đề gì khi tạo lưới và xem các mô hình trong trò chơi. Ngoài ra, tôi có hình ảnh động và phần ứng được tải đúng vào cấu trúc dữ liệu phù hợp.

Vấn đề của tôi là áp dụng đúng các hình ảnh động cho các mô hình. Tôi có khung để áp dụng các mô hình và mã để chọn hình động và bước qua các khung.

Theo những gì tôi hiểu, các AnimationKeys bên trong AnimationSetcung cấp các phép biến đổi để biến đổi tư thế liên kết thành tư thế trong khung hình động. Ví dụ nhỏ:

Animation {
  {Armature_001_Bone}
  AnimationKey { 
    2; //Position
    121; //number of frames
    0;3;     0.000000, 0.000000, 0.000000;;,
    1;3;     0.000000, 0.000000, 0.005524;;,
    2;3;     0.000000, 0.000000, 0.022217;;,
    ...
  }
  AnimationKey { 
    0; //Quaternion Rotation 
    121;
    0;4;   -0.707107, 0.707107, 0.000000, 0.000000;;,
    1;4;   -0.697332, 0.697332, 0.015710, 0.015710;;,
    2;4;   -0.684805, 0.684805, 0.035442, 0.035442;;,
    ...
  }
  AnimationKey { 
    1; //Scale
    121;
    0;3;     1.000000, 1.000000, 1.000000;;,
    1;3;     1.000000, 1.000000, 1.000000;;,
    2;3;     1.000000, 1.000000, 1.000000;;,
    ...
  }
}

Vì vậy, để áp dụng khung 2, tôi sẽ lấy vị trí, góc quay và tỷ lệ từ khung 2, tạo ma trận biến đổi (gọi nó Transform_A) từ chúng và áp dụng ma trận đó các đỉnh được điều khiển bởi Armature_001_Bonetrọng số của chúng. Vì vậy, tôi sẽ nhét TransformAvào shader của mình và biến đổi đỉnh. Cái gì đó như:

vertexPos = vertexPos * bones[ int(bfs_BoneIndices.x) ] * bfs_BoneWeights.x;

Trong đó bfs_BoneIndicesbfs_BoneWeightslà các giá trị cụ thể cho đỉnh hiện tại.

Khi tải trong các đỉnh lưới, tôi biến đổi chúng theo rootTransformmeshTransform. Điều này đảm bảo chúng được định hướng và thu nhỏ chính xác để xem tư thế liên kết.

Vấn đề là khi tôi tạo ma trận biến đổi đó (sử dụng vị trí, góc quay và tỷ lệ từ hình ảnh động), nó không biến đổi đúng đỉnh. Có nhiều khả năng hơn là chỉ sử dụng dữ liệu hoạt hình. Tôi cũng đã thử áp dụng hệ thống phân cấp biến đổi xương, vẫn không có xúc xắc. Về cơ bản tôi kết thúc với một số mô hình xoắn. Cũng cần lưu ý rằng tôi đang làm việc trong openGL, do đó, bất kỳ ma trận chuyển vị nào có thể cần được áp dụng đều phải được xem xét.

Tôi cần dữ liệu gì và làm cách nào để kết hợp nó để áp dụng hoạt hình .x cho các mô hình?

Tôi đã thực hiện một số mô phỏng về việc này trông như thế nào, trong trường hợp điều đó hữu ích.

Đầu tiên tôi muốn thử nghiệm bản dịch, đây là một cái đầu bồng bềnh, trông giống như trong Blender:

http://i.stack.imgur.com/NAc4B.gif

Và nó trông như thế nào trong trò chơi (đừng bận tâm đến màu sắc):

http://i.stack.imgur.com/nj2du.gif

Sau đó, chỉ để xoay, hình ảnh động là đầu xoay 360 độ quanh trục thẳng đứng. Đây là những gì trông giống như trong trò chơi:

http://i.stack.imgur.com/gVyUW.gif

Lưu ý, không nên có độ nghiêng, chỉ xoay như vòng xoay vui vẻ.

Cập nhật

Tôi có một phần dịch của hoạt hình. Nhưng nó cảm thấy khó chịu và tôi không thấy làm thế nào để áp dụng nó vào vòng quay.

Bản dịch hoạt động bằng cách thực hiện các bước sau:

  1. Lấy vị trí từ khung hình động và trao đổi yzcác giá trị
  2. Dịch ma trận biến đổi theo vị trí thay đổi
  3. Chuyển đổi ma trận biến đổi
  4. Áp dụng ma trận biến đổi cho các đỉnh

Vì vậy, đó là cách nó có thể hoạt động, nhưng làm thế nào để nó hoạt động chung cho vị trí, quy mô và luân chuyển?


2
Bạn đã biến đổi đỉnh với ma trận tư thế liên kết nghịch đảo trước khi áp dụng skinning?
r2d2rigo

Tôi có, nó có tác dụng, nhưng nó không phải là một mong muốn. Nó xuất hiện ảnh hưởng đến biểu diễn trực quan của mô hình (đảo ngược tất cả các quy tắc, trông giống như), nhưng không có ảnh hưởng đến chuyển động / xoay / tỷ lệ.
MichaelHouse

Bạn có thể đăng một ảnh chụp màn hình minh họa vấn đề?
r2d2rigo

@ r2d2rigo Tôi đã cập nhật với gifs hoạt hình.
MichaelHouse

1
Tôi chủ yếu động não ở đây, nhưng nếu thứ tự vectơ (xyz, zxy) khác nhau giữa .x và opengl, bạn sẽ nhận được một số hiệu ứng thú vị. Thực tế là hoán vị giúp có nghĩa là nó sử dụng vectơ cột (hoặc hàng) cho vị trí, thay vì cách khác. vi.wikipedia.org/wiki/ Có một mô tả về các phép quay cho 2D. Tôi hoàn toàn không biết làm thế nào để sửa đổi một quan điểm. Hoặc sự khác biệt giữa các định dạng .x và openGL
Daniel Carlsson

Câu trả lời:


3

Cũng cần lưu ý rằng tôi đang làm việc trong openGL, do đó, bất kỳ ma trận chuyển vị nào có thể cần được áp dụng đều phải được xem xét.

Có lẽ đó là chìa khóa, bạn đã thử phủ định một số tọa độ Z xung quanh để chuyển đổi từ tọa độ tay trái DirectX sang tay phải OpenGL chưa?

Bạn có thể phủ nhận tất cả các Z trước khi áp dụng các phép biến đổi của mình và phủ định lại khi hoàn thành, xem liệu đầu ra có tốt hơn không.

BIÊN TẬP

Hoán đổi tọa độ Y và Z là một cách khác để thay đổi độ thuận tay. Vì vậy, bạn phải điều chỉnh các biến đổi của mình, kiểm tra bài viết này để biết chi tiết .

Thực tế là bạn phải hoán chuyển ma trận của bạn cũng có nghĩa là bạn đi từ hàng chính sang cột chính hoặc ngược lại. Điều này sẽ ít phức tạp hơn để xử lý, có lẽ bạn sẽ chỉ cần tìm đúng "địa điểm" để thực hiện trong đường ống của mình. Tôi chỉ đoán, nhưng thực hiện nó trên các bậc bốn có thể chỉ đơn giản là thay đổi chúng thành ma trận, hoán vị và quay trở lại các phần tử, nếu lib lib của bạn cung cấp tùy chọn này.


Kiểu cho tôi biết những gì tôi đã biết ở đây ...
MichaelHouse

1
Chà, bạn đã không đề cập đến sự thuận tay trong câu hỏi của bạn và tôi tin rằng ít nhất đó là một phần của vấn đề của bạn. Tôi không thể cho rằng bạn làm hoặc không biết rằng DirectX và OpenGL đang tuân theo các quy ước khác nhau về điểm này (điều này thực sự phức tạp hơn một chút ). Lưu ý rằng điều này có thể giúp những người khác đọc câu hỏi này để xem nó được đề cập, đây là loại điểm của toàn bộ trang web này.
Laurent Couvidou

Đủ công bằng, bạn nói đúng. Tôi chỉ nói bóng gió về thực tế tôi biết về các chuyển đổi cần thực hiện khi tôi đề cập đến bằng cách sử dụng OpenGL và các chuyển đổi cần phải xảy ra.
MichaelHouse

2

OK, tôi dành thêm một chút thời gian cho việc này và khiến nó hoạt động cho nhiều xương, và ít giống như hack hơn (mặc dù vẫn còn một chút). Hệ thống tôi có tại chỗ ban đầu gần như đúng. Tuy nhiên, vấn đề chính là:

  1. Blender lưu Quancyions ở định dạng W, X, Y, Z. Tôi đã tải chúng X, Y, Z, W .
  2. Mã của tôi để chuyển đổi Quancyion thành ma trận là không chính xác. Tôi thực sự vẫn không chắc tại sao điều này không chính xác, nhưng tôi biết đoạn mã sau hoạt động, như là một phần của lớp Đệ tứ của tôi:

    public Matrix4f toMatrix() {
        Matrix4f tmpMatrix = new Matrix4f();
        if (this.length() > 0)
            this.normalise();
    
        float xx = this.x * this.x;
        float xy = this.x * this.y;
        float xz = this.x * this.z;
        float wx = this.x * this.w;
    
        float yy = this.y * this.y;
        float yz = this.y * this.z;
        float wy = this.y * this.w;
    
        float zz = this.z * this.z;
        float wz = this.z * this.w;
        //note the "* -1"s
        //I needed those to make the same matrices Blender was expecting
        tmpMatrix.m00 = (1.0f - 2.0f * (yy + zz)) * -1;
        tmpMatrix.m01 = (       2.0f * (xy - wz)) * -1;
        tmpMatrix.m02 =        2.0f * (xz + wy);
        tmpMatrix.m03 = 0;
    
        tmpMatrix.m10 =        2.0f * (xy + wz);
        tmpMatrix.m11 = 1.0f - 2.0f * (xx + zz);
        tmpMatrix.m12 = (       2.0f * (yz - wx)) * -1;
        tmpMatrix.m13 = 0;
    
        tmpMatrix.m20 =        2.0f * (xz - wy);
        tmpMatrix.m21 =        2.0f * (yz + wx);
        tmpMatrix.m22 = (1.0f - 2.0f * (xx + yy)) * -1;
        tmpMatrix.m23 = 0;
        return tmpMatrix;
    }

Ngoài ra, nó chỉ là:

finalMatrix = boneMatrix * skinMatrix * invertedBindMatrix;

Lưu ý rằng boneMatrixnên sử dụng ma trận hoạt hình cho từng xương thay vì ma trận liên kết. Nó cũng sẽ nhận được tất cả các ma trận cha mẹ như vậy:

private Matrix4f getBoneMatrix() {
        if (parent == null) {
            return Matrix4f.mul(Matrix4f.mul(parentArmature.getBindMatrix(), parentArmature.getArmatureRootMatrix(), null), boneMatrix, null);
        } else {
            return Matrix4f.mul(parent.getBoneMatrix(), boneMatrix, null);
        }
    }

Và nó hoạt động. Để lại một bình luận nếu bạn cần làm rõ.


Tôi đã viết một số thông tin chung khác về việc này hoạt động tại blog của mình: byte56.com/2012/12/the-blender-connection.html
MichaelHouse
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.