C语言 这是一个正确的glTF文件吗?存在重复折点

siv3szwd  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(116)

我正在使用blender 3.6,并且我已经以glTF格式导出了一个简单的立方体:

{
    "asset":{
        "generator":"Khronos glTF Blender I/O v3.6.27",
        "version":"2.0"
    },
    "scene":0,
    "scenes":[
        {
            "name":"Scene",
            "nodes":[
                0
            ]
        }
    ],
    "nodes":[
        {
            "mesh":0,
            "name":"Cube"
        }
    ],
    "materials":[
        {
            "doubleSided":true,
            "name":"Material",
            "pbrMetallicRoughness":{
                "baseColorFactor":[
                    0.800000011920929,
                    0.800000011920929,
                    0.800000011920929,
                    1
                ],
                "metallicFactor":0,
                "roughnessFactor":0.5
            }
        }
    ],
    "meshes":[
        {
            "name":"Cube",
            "primitives":[
                {
                    "attributes":{
                        "POSITION":0,
                        "NORMAL":1,
                        "TEXCOORD_0":2
                    },
                    "indices":3,
                    "material":0
                }
            ]
        }
    ],
    "accessors":[
        {
            "bufferView":0,
            "componentType":5126,
            "count":24,
            "max":[
                1,
                1,
                1
            ],
            "min":[
                -1,
                -1,
                -1
            ],
            "type":"VEC3"
        },
        {
            "bufferView":1,
            "componentType":5126,
            "count":24,
            "type":"VEC3"
        },
        {
            "bufferView":2,
            "componentType":5126,
            "count":24,
            "type":"VEC2"
        },
        {
            "bufferView":3,
            "componentType":5123,
            "count":36,
            "type":"SCALAR"
        }
    ],
    "bufferViews":[
        {
            "buffer":0,
            "byteLength":288,
            "byteOffset":0,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":288,
            "byteOffset":288,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":192,
            "byteOffset":576,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":72,
            "byteOffset":768,
            "target":34963
        }
    ],
    "buffers":[
        {
            "byteLength":840,
            "uri":"data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAQAOABQAAQAUAAcACgAGABMACgATABcAFQASAAwAFQAMAA8AEAADAAkAEAAJABYABQACAAgABQAIAAsAEQANAAAAEQAAAAQA"
        }
    ]
}

字符串
网格本身是一个简单的立方体(当你创建一个新项目时Blender给你的第一个对象),它应该有8个顶点,每个顶点对应一个立方体的角,对吗?
我想提请您注意第一个缓冲区视图和第一个访问器,它们引用位置值(顶点)。访问器说有24个元素,组件类型是5126,代表浮点32位,即4字节。假设数据类型是VEC 3,每个元素应该有12个字节(3 * 4),对吗?这意味着缓冲区视图中应该有8 * 12 = 96个字节。那么为什么buffer视图中有288 = 3 * 96字节,以及为什么当我在buffer视图中打印数据时,我会得到三倍相同的输出:

1.000000, 1.000000, -1.000000

1.000000, 1.000000, -1.000000

1.000000, 1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, 1.000000, 1.000000

1.000000, 1.000000, 1.000000

1.000000, 1.000000, 1.000000

1.000000, -1.000000, 1.000000

1.000000, -1.000000, 1.000000

1.000000, -1.000000, 1.000000

-1.000000, 1.000000, -1.000000

-1.000000, 1.000000, -1.000000

-1.000000, 1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, 1.000000, 1.000000

-1.000000, 1.000000, 1.000000

-1.000000, 1.000000, 1.000000

-1.000000, -1.000000, 1.000000

-1.000000, -1.000000, 1.000000

-1.000000, -1.000000, 1.000000


注意总是有三个相同的向量,注意实际上有24个向量。以下是从完全相同的混合器网格导出的.obj文件(即,在两次导出期间未执行任何操作):

# Blender v3.6.0 OBJ File: ''
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6


实际上应该有8个顶点,在启用统计选项的情况下始终显示在blender内。
用于打印向量的代码(C)如下:

vec3* positions = bin + position_view->byte_offset;

for (int i = 0; i < position_accessor->count; i++) {
    printf("%f, %f, %f\n", positions[i][0], positions[i][1], positions[i][2]);
    printf("\n");
}


其中bin是一个void*,包含缓冲区的全部内容,vec 3是一个cglm类型,它实际上是一个float[3],position_view->byte_offset是0,position_accessor->count 24,就像上面的.gltf文件一样。
我的直觉告诉我,第一个访问器中的“count”:24属性应该是8,缓冲区视图的长度应该是96,因此其他访问器和缓冲区也是错误的,因为它们是法线和纹理坐标(索引似乎是正确的)。
最让我困惑的是,如果我上传.gltf文件到在线gltf查看器,网格实际上是正确渲染的,例如在这个网站上https://gltf-viewer.donmccurdy.com/如果文件是正确的,那么为什么每个顶点都是三倍?也许我对位置数组(vec 3 ,即'float[3]')的解释是错误的?

  • 谢谢-谢谢
x4shl7ld

x4shl7ld1#

具有硬边的立方体在GPU就绪的顶点流中不能只有8个顶点-这是glTF格式提供的。每个顶点存储一个法向量,每个面具有不同的法线,因此需要6 * 4 = 24个顶点。如果你在Blender的导出选项中禁用顶点法线(也许还有UV),你可能会看到8个顶点。
来自Blender Stack Exchange的这个响应可能也有帮助-https://blender.stackexchange.com/a/167383/43930

相关问题