Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc')
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc185
1 files changed, 185 insertions, 0 deletions
diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc b/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc
new file mode 100644
index 00000000000..8e2d393b8f3
--- /dev/null
+++ b/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 The Draco Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "draco/mesh/mesh_cleanup.h"
+
+namespace draco {
+
+bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) {
+ if (!options.remove_degenerated_faces && !options.remove_unused_attributes)
+ return true; // Nothing to cleanup.
+ const PointAttribute *const pos_att =
+ mesh->GetNamedAttribute(GeometryAttribute::POSITION);
+ if (pos_att == nullptr)
+ return false;
+ // Array that is going to store whether a corresponding point is used.
+ std::vector<bool> is_point_used;
+ if (options.remove_unused_attributes) {
+ is_point_used.resize(mesh->num_points(), false);
+ }
+
+ FaceIndex::ValueType num_degenerated_faces = 0;
+ PointIndex::ValueType num_new_points = 0;
+ // Array for storing position indices on a face.
+ std::array<AttributeValueIndex, 3> pos_indices;
+ for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
+ const Mesh::Face &face = mesh->face(f);
+ for (int p = 0; p < 3; ++p) {
+ pos_indices[p] = pos_att->mapped_index(face[p]);
+ }
+ bool is_face_valid = true;
+ if (options.remove_degenerated_faces) {
+ if (pos_indices[0] == pos_indices[1] ||
+ pos_indices[0] == pos_indices[2] ||
+ pos_indices[1] == pos_indices[2]) {
+ ++num_degenerated_faces;
+ is_face_valid = false;
+ } else if (num_degenerated_faces > 0) {
+ // Copy the face to its new location.
+ mesh->SetFace(f - num_degenerated_faces, face);
+ }
+ }
+ if (options.remove_unused_attributes && is_face_valid) {
+ for (int p = 0; p < 3; ++p) {
+ if (!is_point_used[face[p].value()]) {
+ is_point_used[face[p].value()] = true;
+ ++num_new_points;
+ }
+ }
+ }
+ }
+ if (num_degenerated_faces > 0) {
+ mesh->SetNumFaces(mesh->num_faces() - num_degenerated_faces);
+ }
+ if (options.remove_unused_attributes) {
+ bool points_changed = false;
+ const PointIndex::ValueType num_original_points = mesh->num_points();
+ // Map from old points to the new ones.
+ IndexTypeVector<PointIndex, PointIndex> point_map(num_original_points);
+ if (num_new_points < static_cast<int>(mesh->num_points())) {
+ // Some of the points were removed. We need to remap the old points to the
+ // new ones.
+ num_new_points = 0;
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ if (is_point_used[i.value()]) {
+ point_map[i] = num_new_points++;
+ } else {
+ point_map[i] = kInvalidPointIndex;
+ }
+ }
+ // Go over faces and update their points.
+ for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
+ Mesh::Face face = mesh->face(f);
+ for (int p = 0; p < 3; ++p) {
+ face[p] = point_map[face[p]];
+ }
+ mesh->SetFace(f, face);
+ }
+ // Set the new number of points.
+ mesh->set_num_points(num_new_points);
+ points_changed = true;
+ } else {
+ // No points were removed. Initialize identity map between the old and new
+ // points.
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ point_map[i] = i;
+ }
+ }
+
+ // Update index mapping for attributes.
+ IndexTypeVector<AttributeValueIndex, uint8_t> is_att_index_used;
+ IndexTypeVector<AttributeValueIndex, AttributeValueIndex> att_index_map;
+ for (int a = 0; a < mesh->num_attributes(); ++a) {
+ PointAttribute *const att = mesh->attribute(a);
+ // First detect which attribute entries are used (included in a point).
+ is_att_index_used.assign(att->size(), 0);
+ att_index_map.clear();
+ AttributeValueIndex::ValueType num_used_entries = 0;
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ if (point_map[i] != kInvalidPointIndex) {
+ const AttributeValueIndex entry_id = att->mapped_index(i);
+ if (!is_att_index_used[entry_id]) {
+ is_att_index_used[entry_id] = 1;
+ ++num_used_entries;
+ }
+ }
+ }
+ bool att_indices_changed = false;
+ // If there are some unused attribute entries, remap the attribute values
+ // in the attribute buffer.
+ if (num_used_entries < static_cast<int>(att->size())) {
+ att_index_map.resize(att->size());
+ num_used_entries = 0;
+ for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size());
+ ++i) {
+ if (is_att_index_used[i]) {
+ att_index_map[i] = num_used_entries;
+ if (i > num_used_entries) {
+ const uint8_t *const src_add = att->GetAddress(i);
+ att->buffer()->Write(
+ att->GetBytePos(AttributeValueIndex(num_used_entries)),
+ src_add, att->byte_stride());
+ }
+ ++num_used_entries;
+ }
+ }
+ // Update the number of unique entries in the vertex buffer.
+ att->Resize(num_used_entries);
+ att_indices_changed = true;
+ }
+ // If either the points or attribute indices have changed, we need to
+ // update the attribute index mapping.
+ if (points_changed || att_indices_changed) {
+ if (att->is_mapping_identity()) {
+ // The mapping was identity. It'll remain identity only if the
+ // number of point and attribute indices is still the same.
+ if (num_used_entries != static_cast<int>(mesh->num_points())) {
+ // We need to create an explicit mapping.
+ // First we need to initialize the explicit map to the original
+ // number of points to recreate the original identity map.
+ att->SetExplicitMapping(num_original_points);
+ // Set the entries of the explicit map to identity.
+ for (PointIndex::ValueType i = 0; i < num_original_points; ++i) {
+ att->SetPointMapEntry(PointIndex(i), AttributeValueIndex(i));
+ }
+ }
+ }
+ if (!att->is_mapping_identity()) {
+ // Explicit mapping between points and local attribute indices.
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ // The new point id that maps to the currently processed attribute
+ // entry.
+ const PointIndex new_point_id = point_map[i];
+ if (new_point_id == kInvalidPointIndex)
+ continue;
+ // Index of the currently processed attribute entry in the original
+ // mesh.
+ const AttributeValueIndex original_entry_index =
+ att->mapped_index(i);
+ // New index of the same entry after unused entries were removed.
+ const AttributeValueIndex new_entry_index =
+ att_index_map[original_entry_index];
+ att->SetPointMapEntry(new_point_id, new_entry_index);
+ }
+ // If the number of points changed, we need to set a new explicit map
+ // size.
+ att->SetExplicitMapping(mesh->num_points());
+ }
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace draco