Material ids were not assigned to faces if the

first face with this material was in another thread buffer than where
the usemtl command was
This commit is contained in:
Victor Ripplinger
2018-02-21 11:36:36 +01:00
parent 16f3041c76
commit 72529f02fe

View File

@@ -1492,7 +1492,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
attrib->texcoords.resize(num_vt * 2); attrib->texcoords.resize(num_vt * 2);
attrib->indices.resize(num_f); attrib->indices.resize(num_f);
attrib->face_num_verts.resize(num_indices); attrib->face_num_verts.resize(num_indices);
attrib->material_ids.resize(num_indices); attrib->material_ids.resize(num_indices, -1);
size_t v_offsets[kMaxThreads]; size_t v_offsets[kMaxThreads];
size_t n_offsets[kMaxThreads]; size_t n_offsets[kMaxThreads];
@@ -1523,22 +1523,44 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
size_t t_count = t_offsets[t]; size_t t_count = t_offsets[t];
size_t f_count = f_offsets[t]; size_t f_count = f_offsets[t];
size_t face_count = face_offsets[t]; size_t face_count = face_offsets[t];
int material_id = -1; // -1 = default unknown material. int material_id = -1; // -1 = default unknown material.
for (size_t i = 0; i < commands[t].size(); i++) { for (size_t i = 0; i < commands[t].size(); i++) {
if (commands[t][i].type == COMMAND_EMPTY) { if (commands[t][i].type == COMMAND_EMPTY) {
continue; continue;
} else if (commands[t][i].type == COMMAND_USEMTL) { } else if (commands[t][i].type == COMMAND_USEMTL) {
if (commands[t][i].material_name && if (commands[t][i].material_name &&
commands[t][i].material_name_len > 0) { commands[t][i].material_name_len > 0 &&
std::string material_name(commands[t][i].material_name, // check if there are still faces after this command
commands[t][i].material_name_len); face_count < num_indices) {
// Find next face
if (material_map.find(material_name) != material_map.end()) { bool found = false;
material_id = material_map[material_name]; size_t i_start = i + 1, t_next, i_next;
} else { for (t_next = t; t_next < num_threads; t_next++) {
// Assign invalid material ID for (i_next = i_start; i_next < commands[t_next].size(); i_next++) {
material_id = -1; if (commands[t_next][i_next].type == COMMAND_F) {
found = true;
break;
}
}
if (found)
break;
i_start = 0;
}
// Assign material to this face
if (found) {
std::string material_name(commands[t][i].material_name,
commands[t][i].material_name_len);
for (size_t k = 0; k < commands[t_next][i_next].f_num_verts.size(); k++) {
if (material_map.find(material_name) != material_map.end()) {
attrib->material_ids[face_count + k] = material_map[material_name];
} else {
// Assign invalid material ID
// Set a different value than the default, to
// prevent following faces from being assigned a valid material
attrib->material_ids[face_count + k] = -2;
}
}
} }
} }
} else if (commands[t][i].type == COMMAND_V) { } else if (commands[t][i].type == COMMAND_V) {
@@ -1565,7 +1587,6 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
index_t(vertex_index, texcoord_index, normal_index); index_t(vertex_index, texcoord_index, normal_index);
} }
for (size_t k = 0; k < commands[t][i].f_num_verts.size(); k++) { for (size_t k = 0; k < commands[t][i].f_num_verts.size(); k++) {
attrib->material_ids[face_count + k] = material_id;
attrib->face_num_verts[face_count + k] = attrib->face_num_verts[face_count + k] =
commands[t][i].f_num_verts[k]; commands[t][i].f_num_verts[k];
} }
@@ -1580,19 +1601,13 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
for (size_t t = 0; t < workers->size(); t++) { for (size_t t = 0; t < workers->size(); t++) {
workers[t].join(); workers[t].join();
} }
if(material_map.size()>1&& num_threads>1) {
for (size_t t = 0; t < num_threads; t++) { // To each face with uninitialized material id,
size_t face_count = face_offsets[t]; // assign the material id of the last face preceding it that has one
if (-1 == attrib->material_ids[face_count]) { for (size_t face_count = 1; face_count < num_indices; ++face_count)
int prev_material_id = attrib->material_ids[face_count - 1]; if (attrib->material_ids[face_count] == -1)
size_t max_face_offset = (t == num_threads - 1) ? attrib->material_ids.size() : face_offsets[t + 1]; attrib->material_ids[face_count] = attrib->material_ids[face_count - 1];
for (int i = face_count; i<max_face_offset; ++i) {
if (attrib->material_ids[i] != -1) break;
attrib->material_ids[i] = prev_material_id;
}
}
}
}
auto t_end = std::chrono::high_resolution_clock::now(); auto t_end = std::chrono::high_resolution_clock::now();
ms_merge = t_end - t_start; ms_merge = t_end - t_start;
} }