Skip to content

Commit 1ef1c4e

Browse files
committed
Merge pull request godotengine#97264 from clayjohn/obj-no-uv-crash
Fix crash when importing a surface with no UVs after another surface in the same OBJ file that had UVs
2 parents 5f5c690 + 0754600 commit 1ef1c4e

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

editor/import/3d/resource_importer_obj.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes,
246246
bool smoothing = true;
247247
const uint32_t no_smoothing_smooth_group = (uint32_t)-1;
248248

249+
bool uses_uvs = false;
250+
249251
while (true) {
250252
String l = f->get_line().strip_edges();
251253
while (l.length() && l[l.length() - 1] == '\\') {
@@ -320,35 +322,37 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes,
320322
idx = 1 ^ idx;
321323
}
322324

325+
// Check UVs before faces as we may need to generate dummy tangents if there are no UVs.
326+
if (face[idx].size() >= 2 && !face[idx][1].is_empty()) {
327+
int uv = face[idx][1].to_int() - 1;
328+
if (uv < 0) {
329+
uv += uvs.size() + 1;
330+
}
331+
ERR_FAIL_INDEX_V(uv, uvs.size(), ERR_FILE_CORRUPT);
332+
surf_tool->set_uv(uvs[uv]);
333+
uses_uvs = true;
334+
}
335+
323336
if (face[idx].size() == 3) {
324337
int norm = face[idx][2].to_int() - 1;
325338
if (norm < 0) {
326339
norm += normals.size() + 1;
327340
}
328341
ERR_FAIL_INDEX_V(norm, normals.size(), ERR_FILE_CORRUPT);
329342
surf_tool->set_normal(normals[norm]);
330-
if (generate_tangents && uvs.is_empty()) {
343+
if (generate_tangents && !uses_uvs) {
331344
// We can't generate tangents without UVs, so create dummy tangents.
332345
Vector3 tan = Vector3(normals[norm].z, -normals[norm].x, normals[norm].y).cross(normals[norm].normalized()).normalized();
333346
surf_tool->set_tangent(Plane(tan.x, tan.y, tan.z, 1.0));
334347
}
335348
} else {
336349
// No normals, use a dummy tangent since normals and tangents will be generated.
337-
if (generate_tangents && uvs.is_empty()) {
350+
if (generate_tangents && !uses_uvs) {
338351
// We can't generate tangents without UVs, so create dummy tangents.
339352
surf_tool->set_tangent(Plane(1.0, 0.0, 0.0, 1.0));
340353
}
341354
}
342355

343-
if (face[idx].size() >= 2 && !face[idx][1].is_empty()) {
344-
int uv = face[idx][1].to_int() - 1;
345-
if (uv < 0) {
346-
uv += uvs.size() + 1;
347-
}
348-
ERR_FAIL_INDEX_V(uv, uvs.size(), ERR_FILE_CORRUPT);
349-
surf_tool->set_uv(uvs[uv]);
350-
}
351-
352356
int vtx = face[idx][0].to_int() - 1;
353357
if (vtx < 0) {
354358
vtx += vertices.size() + 1;
@@ -407,7 +411,7 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes,
407411
surf_tool->generate_normals();
408412
}
409413

410-
if (generate_tangents && uvs.size()) {
414+
if (generate_tangents && uses_uvs) {
411415
surf_tool->generate_tangents();
412416
}
413417

@@ -426,10 +430,11 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes,
426430

427431
Array array = surf_tool->commit_to_arrays();
428432

429-
if (mesh_flags & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES && generate_tangents) {
430-
// Compression is enabled, so let's validate that the normals and tangents are correct.
433+
if (mesh_flags & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES && generate_tangents && uses_uvs) {
434+
// Compression is enabled, so let's validate that the normals and generated tangents are correct.
431435
Vector<Vector3> norms = array[Mesh::ARRAY_NORMAL];
432436
Vector<float> tangents = array[Mesh::ARRAY_TANGENT];
437+
ERR_FAIL_COND_V(tangents.is_empty(), ERR_FILE_CORRUPT);
433438
for (int vert = 0; vert < norms.size(); vert++) {
434439
Vector3 tan = Vector3(tangents[vert * 4 + 0], tangents[vert * 4 + 1], tangents[vert * 4 + 2]);
435440
if (abs(tan.dot(norms[vert])) > 0.0001) {
@@ -454,6 +459,7 @@ static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes,
454459

455460
surf_tool->clear();
456461
surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
462+
uses_uvs = false;
457463
}
458464

459465
if (l.begins_with("o ") || f->eof_reached()) {

0 commit comments

Comments
 (0)