gltf,是否要转置矩阵?

gltf, are matrices ever to be transposed?

在学习 gltf 时,我已经有 2 个可用的皮肤模型,现在我正在尝试 RiggedFigure。

其他 2 个模型工作得很好,我使用的是相同的代码。我正在使用 vscode gltf 扩展来验证我的输出。

文档指出:

Accessors of matrix type have data stored in column-major order; start of each column must be aligned to 4-byte boundaries.

特征矩阵也是主要的列,因此将原始字节复制到 Eigen::Matrix4f 类型的 stl 向量中应该会产生正确的数据,事实上,我拥有的 3 个模型中的 2 个就是这种情况到目前为止尝试过。

但是对于装配图,vs 代码说矩阵应该是(请原谅屏幕截图,但出于某种原因我无法复制粘贴矩阵):

我的代码打印:

     0.999983 0.000442018  0.00581419 -0.00398856
          0    0.997123  -0.0758045   0.0520021
  -0.005831   0.0758032    0.997106   -0.684015
          0           0           0           1

         1          0          0          0
         0   -0.01376   0.999905   -0.85674
         0  -0.999905 -0.0137601   0.024791
         0          0          0          1

        1         0         0         0
        0  0.979842  0.199774 -0.224555
        0 -0.199774  0.979842  -1.05133
        0         0         0         1

          1           0           0           0
          0 -0.00751853    0.999972    -1.12647
          0   -0.999972 -0.00751847  0.00796944
          0           0           0           1

          -1 -1.50995e-07            0            0
           0   0.00364935     0.999993     -1.19299
-1.51869e-07     0.999993  -0.00364941   0.00535393
           0            0            0            1

 -0.0623881    0.998036 -0.00569177  0.00162297
   0.891518   0.0531644   -0.449853    0.404156
  -0.448667  -0.0331397   -0.893084    0.998987
          0           0           0           1

 0.109672  0.988876 -0.100484  0.107683
-0.891521 0.0531632 -0.449849  0.404152
-0.439503   0.13892  0.887434 -0.993169
        0         0         0         1

 0.530194  0.847874  0.001751 -0.183428
 0.760039 -0.474352 -0.444218  0.206564
-0.375811  0.236853 -0.895917  0.973213
        0         0         0         1

-0.0705104  -0.619322   0.781965  -0.761146
 -0.760038  -0.474352  -0.444223   0.206569
  0.646043  -0.625645  -0.437261   0.633599
         0          0          0          1

   0.631434    0.775418 -0.00419003   -0.228155
   0.649284    -0.53166   -0.543845    0.154659
  -0.423935    0.340682   -0.839175    0.951451
          0           0           0           1

 0.111378 -0.773831  0.623523 -0.550204
-0.649284 -0.531661 -0.543845   0.15466
 0.752347 -0.344271 -0.561651  0.809067
        0         0         0         1

  -0.830471   -0.549474    0.091635 -0.00030848
  0.0339727   -0.214148    -0.97621    0.596867
   0.556025   -0.807601    0.196511   -0.159297
          0           0           0           1

 -0.994689   0.102198  0.0121981 -0.0750653
-0.0339737  -0.214147   -0.97621   0.596867
-0.0971548   -0.97144   0.216482  -0.140501
         0          0          0          1

    -0.99973    0.0232223 -7.82996e-05    0.0784336
   0.0051282     0.217484     -0.97605     0.357951
  -0.0226493    -0.975788    -0.217544    0.0222206
           0            0            0            1

  -0.998171  -0.0599068 -0.00810355  -0.0775425
-0.00512856    0.217484    -0.97605    0.357951
  0.0602345   -0.974224   -0.217393   0.0251548
          0           0           0           1

 -0.999327  0.0366897          0  0.0783684
 0.0287104   0.781987   0.622632 -0.0567413
 0.0228442   0.622213  -0.782514  0.0634761
         0          0          0          1

 -0.999326 0.00828946  0.0357652 -0.0814984
 0.0287402   0.782804   0.621604 -0.0521458
-0.0228444   0.622213  -0.782514  0.0634761
         0          0          0          1

   0.994013    0.109264 0.000418345  -0.0755577
   0.109252   -0.993835  -0.0188101  -0.0405796
-0.00164008   0.0187438   -0.999822   0.0227357
          0           0           0           1

   0.994011   -0.109281 0.000483894   0.0755372
  -0.109253   -0.993836   -0.018811  -0.0405797
 0.00253636   0.0186453   -0.999823   0.0228038
          0           0           0           1

哪些是 vs 代码所说的转置版本。

我的加载代码是这样的(用错别字实例化Eigen::Matrix4f):

    void CopySparseBuffer(
        void* dest,
        const void* src,
        const size_t element_count,
        const size_t stride,
        const size_t type_size)
    {
        assert(stride >= type_size);
        // Typecast src and dest addresses to (char *)
        unsigned char* csrc = (unsigned char*)src;
        unsigned char* cdest = (unsigned char*)dest;
        // Iterate over the total number of elements to copy
        for(int i = 0; i < element_count; i++)
            // Copy each byte of the element. Since the stride could be different from the
            // type size (in the case of padding bytes for example) the right access
            // should skip over any interleaved data, that's why we use the stride.
            for(int j = 0; j < type_size; j++)
                *(cdest + i * type_size + j) = *(csrc + i * stride + j);
    }
    
    template<typename T>
    std::vector<T> ExtractDataFromAccessor(
        const tinygltf::Model& model, const int accessor_index, bool print = false)
    {
        const int buffer_view_index = model.accessors[accessor_index].bufferView;
        const int array_type = model.accessors[accessor_index].type;
        const int component_type = model.accessors[accessor_index].componentType;
        const int accessor_offset = model.accessors[accessor_index].byteOffset;
        const int element_num = model.accessors[accessor_index].count;
    
        const int buffer_index = model.bufferViews[buffer_view_index].buffer;
        const int buffer_length = model.bufferViews[buffer_view_index].byteLength;
        const int buffer_offset = model.bufferViews[buffer_view_index].byteOffset;
        const int buffer_stride = model.bufferViews[buffer_view_index].byteStride;
    
        const std::vector<unsigned char> data = model.buffers[buffer_index].data;
    
        assert(
            component_type == ComponentCode<T>() &&
            "The component type found here should match that of the type (e.g. float and "
            "float).");
        assert(array_type == TypeCode<T>());
        // Size in bytes of a single element (e.g. 12 for a vec3 of floats)
        const int type_size = sizeof(T);
        assert(
            buffer_stride == 0 || buffer_stride >= sizeof(T) &&
            "It doesn't make sense for a positive buffer "
            "stride to be less than the type size");
        assert(element_num * type_size <= buffer_length);
        const size_t stride = std::max(buffer_stride, type_size);
    
        std::vector<T> holder(element_num);
        CopySparseBuffer(
            holder.data(),
            data.data() + buffer_offset + accessor_offset,
            element_num,
            stride,
            type_size);
    
        return holder;
    }

我刚刚弄明白了,所以我会把它留在这里,以防将来有人遇到同样的情况。

VS 代码向量是列,而不是行,所以我的代码和 VS 代码实际上是一致的,只是 VS 代码输出令人困惑。

简而言之,一切正常,输出只是令人困惑。