Skip to content

Commit fb004a1

Browse files
committed
AssetPipeline: fix crash with meshes that already have TEXCOORD_4.
Fixes google#1256.
1 parent 0262a38 commit fb004a1

File tree

1 file changed

+44
-11
lines changed

1 file changed

+44
-11
lines changed

libs/gltfio/src/AssetPipeline.cpp

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,12 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
948948
return nullptr;
949949
}
950950

951+
// Check if baked UVs already exist, in which case they are replaced rather than added.
952+
auto skipAttribute = [](const cgltf_attribute& attr) {
953+
const cgltf_int uvindex = gltfio::AssetPipeline::BAKED_UV_ATTRIB_INDEX;
954+
return attr.type == cgltf_attribute_type_texcoord && attr.index == uvindex;
955+
};
956+
951957
// Determine the number of attributes that will be required, which is the same as the old number
952958
// of attributes plus an extra UV set per prim.
953959
size_t numAttributes = 0;
@@ -956,6 +962,12 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
956962
const cgltf_mesh& mesh = sourceAsset->meshes[i];
957963
const cgltf_primitive& sourcePrim = mesh.primitives[0];
958964
numAttributes += sourcePrim.attributes_count + 1;
965+
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
966+
if (skipAttribute(sourcePrim.attributes[ai])) {
967+
numAttributes--;
968+
break;
969+
}
970+
}
959971
}
960972

961973
// The number of required accessors will be the same as the number of vertex attributes, plus
@@ -983,8 +995,11 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
983995
numIndices += atlasMesh.indexCount;
984996
cgltf_size floatsPerVert = 0;
985997
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
986-
cgltf_type attribType = sourcePrim.attributes[ai].data->type;
987-
floatsPerVert += getNumFloats(attribType);
998+
const cgltf_attribute& attr = sourcePrim.attributes[ai];
999+
if (skipAttribute(attr)) {
1000+
continue;
1001+
}
1002+
floatsPerVert += getNumFloats(attr.data->type);
9881003
}
9891004
floatsPerVert += 2;
9901005
numFloats += atlasMesh.vertexCount * floatsPerVert;
@@ -1034,7 +1049,11 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
10341049
const xatlas::Vertex& atlasVertex = atlasMesh.vertexArray[j];
10351050
uint32_t sourceIndex = atlasVertex.xref;
10361051
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
1037-
const cgltf_accessor* accessor = sourcePrim.attributes[ai].data;
1052+
const cgltf_attribute& attr = sourcePrim.attributes[ai];
1053+
if (skipAttribute(attr)) {
1054+
continue;
1055+
}
1056+
const cgltf_accessor* accessor = attr.data;
10381057
cgltf_type attribType = accessor->type;
10391058
cgltf_size elementSize = getNumFloats(attribType);
10401059
cgltf_accessor_read_float(accessor, sourceIndex, vertexWritePtr, elementSize);
@@ -1066,8 +1085,11 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
10661085
// Determine the vertex stride.
10671086
cgltf_size floatsPerVert = 0;
10681087
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
1069-
cgltf_type attribType = sourcePrim.attributes[ai].data->type;
1070-
floatsPerVert += getNumFloats(attribType);
1088+
const cgltf_attribute& attr = sourcePrim.attributes[ai];
1089+
if (skipAttribute(attr)) {
1090+
continue;
1091+
}
1092+
floatsPerVert += getNumFloats(attr.data->type);
10711093
}
10721094
floatsPerVert += 2;
10731095
const cgltf_size stride = floatsPerVert * sizeof(float);
@@ -1106,19 +1128,30 @@ cgltf_data* Pipeline::xatlasToCgltf(const cgltf_data* sourceAsset, const xatlas:
11061128
resultMesh = sourceMesh;
11071129
resultMesh.primitives = &resultPrim;
11081130
resultPrim = sourcePrim;
1131+
11091132
resultPrim.attributes = resultAttribute;
11101133
resultPrim.attributes_count = sourcePrim.attributes_count + 1;
1111-
resultPrim.indices = resultAccessor + sourcePrim.attributes_count + 1;
1134+
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
1135+
if (skipAttribute(sourcePrim.attributes[ai])) {
1136+
resultPrim.attributes_count--;
1137+
break;
1138+
}
1139+
}
1140+
1141+
resultPrim.indices = resultAccessor + resultPrim.attributes_count;
11121142
cgltf_buffer_view* vertexBufferView = views + i * 2 + 0;
11131143
cgltf_buffer_view* indexBufferView = views + i * 2 + 1;
11141144
cgltf_size offset = 0;
11151145
for (size_t ai = 0; ai < sourcePrim.attributes_count; ++ai) {
1116-
const cgltf_attribute& sourceAttrib = sourcePrim.attributes[ai];
1117-
const cgltf_accessor* sourceAccessor = sourceAttrib.data;
1146+
const cgltf_attribute& attr = sourcePrim.attributes[ai];
1147+
if (skipAttribute(attr)) {
1148+
continue;
1149+
}
1150+
const cgltf_accessor* sourceAccessor = attr.data;
11181151
*resultAttribute = {
1119-
.name = sourceAttrib.name,
1120-
.type = sourceAttrib.type,
1121-
.index = sourceAttrib.index,
1152+
.name = attr.name,
1153+
.type = attr.type,
1154+
.index = attr.index,
11221155
.data = resultAccessor
11231156
};
11241157
*resultAccessor = {

0 commit comments

Comments
 (0)