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/draco/src/draco/mesh/mesh_attribute_corner_table.cc')
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc211
1 files changed, 211 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc
new file mode 100644
index 00000000000..28b68d5fd40
--- /dev/null
+++ b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc
@@ -0,0 +1,211 @@
+// 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_attribute_corner_table.h"
+
+#include "draco/mesh/corner_table_iterators.h"
+#include "draco/mesh/mesh_misc_functions.h"
+
+namespace draco {
+
+MeshAttributeCornerTable::MeshAttributeCornerTable()
+ : no_interior_seams_(true), corner_table_(nullptr), valence_cache_(*this) {}
+
+bool MeshAttributeCornerTable::InitEmpty(const CornerTable *table) {
+ if (table == nullptr) {
+ return false;
+ }
+ valence_cache_.ClearValenceCache();
+ valence_cache_.ClearValenceCacheInaccurate();
+ is_edge_on_seam_.assign(table->num_corners(), false);
+ is_vertex_on_seam_.assign(table->num_vertices(), false);
+ corner_to_vertex_map_.assign(table->num_corners(), kInvalidVertexIndex);
+ vertex_to_attribute_entry_id_map_.reserve(table->num_vertices());
+ vertex_to_left_most_corner_map_.reserve(table->num_vertices());
+ corner_table_ = table;
+ no_interior_seams_ = true;
+ return true;
+}
+
+bool MeshAttributeCornerTable::InitFromAttribute(const Mesh *mesh,
+ const CornerTable *table,
+ const PointAttribute *att) {
+ if (!InitEmpty(table)) {
+ return false;
+ }
+ valence_cache_.ClearValenceCache();
+ valence_cache_.ClearValenceCacheInaccurate();
+
+ // Find all necessary data for encoding attributes. For now we check which of
+ // the mesh vertices is part of an attribute seam, because seams require
+ // special handling.
+ for (CornerIndex c(0); c < corner_table_->num_corners(); ++c) {
+ const FaceIndex f = corner_table_->Face(c);
+ if (corner_table_->IsDegenerated(f)) {
+ continue; // Ignore corners on degenerated faces.
+ }
+ const CornerIndex opp_corner = corner_table_->Opposite(c);
+ if (opp_corner == kInvalidCornerIndex) {
+ // Boundary. Mark it as seam edge.
+ is_edge_on_seam_[c.value()] = true;
+ // Mark seam vertices.
+ VertexIndex v;
+ v = corner_table_->Vertex(corner_table_->Next(c));
+ is_vertex_on_seam_[v.value()] = true;
+ v = corner_table_->Vertex(corner_table_->Previous(c));
+ is_vertex_on_seam_[v.value()] = true;
+ continue;
+ }
+ if (opp_corner < c) {
+ continue; // Opposite corner was already processed.
+ }
+
+ CornerIndex act_c(c), act_sibling_c(opp_corner);
+ for (int i = 0; i < 2; ++i) {
+ // Get the sibling corners. I.e., the two corners attached to the same
+ // vertex but divided by the seam edge.
+ act_c = corner_table_->Next(act_c);
+ act_sibling_c = corner_table_->Previous(act_sibling_c);
+ const PointIndex point_id = mesh->CornerToPointId(act_c.value());
+ const PointIndex sibling_point_id =
+ mesh->CornerToPointId(act_sibling_c.value());
+ if (att->mapped_index(point_id) != att->mapped_index(sibling_point_id)) {
+ no_interior_seams_ = false;
+ is_edge_on_seam_[c.value()] = true;
+ is_edge_on_seam_[opp_corner.value()] = true;
+ // Mark seam vertices.
+ is_vertex_on_seam_[corner_table_
+ ->Vertex(corner_table_->Next(CornerIndex(c)))
+ .value()] = true;
+ is_vertex_on_seam_[corner_table_
+ ->Vertex(corner_table_->Previous(CornerIndex(c)))
+ .value()] = true;
+ is_vertex_on_seam_
+ [corner_table_->Vertex(corner_table_->Next(opp_corner)).value()] =
+ true;
+ is_vertex_on_seam_[corner_table_
+ ->Vertex(corner_table_->Previous(opp_corner))
+ .value()] = true;
+ break;
+ }
+ }
+ }
+ RecomputeVertices(mesh, att);
+ return true;
+}
+
+void MeshAttributeCornerTable::AddSeamEdge(CornerIndex c) {
+ DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
+ is_edge_on_seam_[c.value()] = true;
+ // Mark seam vertices.
+ is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(c)).value()] =
+ true;
+ is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Previous(c))
+ .value()] = true;
+
+ const CornerIndex opp_corner = corner_table_->Opposite(c);
+ if (opp_corner != kInvalidCornerIndex) {
+ no_interior_seams_ = false;
+ is_edge_on_seam_[opp_corner.value()] = true;
+ is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(opp_corner))
+ .value()] = true;
+ is_vertex_on_seam_
+ [corner_table_->Vertex(corner_table_->Previous(opp_corner)).value()] =
+ true;
+ }
+}
+
+void MeshAttributeCornerTable::RecomputeVertices(const Mesh *mesh,
+ const PointAttribute *att) {
+ DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
+ if (mesh != nullptr && att != nullptr) {
+ RecomputeVerticesInternal<true>(mesh, att);
+ } else {
+ RecomputeVerticesInternal<false>(nullptr, nullptr);
+ }
+}
+
+template <bool init_vertex_to_attribute_entry_map>
+void MeshAttributeCornerTable::RecomputeVerticesInternal(
+ const Mesh *mesh, const PointAttribute *att) {
+ DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
+ vertex_to_attribute_entry_id_map_.clear();
+ vertex_to_left_most_corner_map_.clear();
+ int num_new_vertices = 0;
+ for (VertexIndex v(0); v < corner_table_->num_vertices(); ++v) {
+ const CornerIndex c = corner_table_->LeftMostCorner(v);
+ if (c == kInvalidCornerIndex) {
+ continue; // Isolated vertex?
+ }
+ AttributeValueIndex first_vert_id(num_new_vertices++);
+ if (init_vertex_to_attribute_entry_map) {
+ const PointIndex point_id = mesh->CornerToPointId(c.value());
+ vertex_to_attribute_entry_id_map_.push_back(att->mapped_index(point_id));
+ } else {
+ // Identity mapping
+ vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
+ }
+ CornerIndex first_c = c;
+ CornerIndex act_c;
+ // Check if the vertex is on a seam edge, if it is we need to find the first
+ // attribute entry on the seam edge when traversing in the CCW direction.
+ if (is_vertex_on_seam_[v.value()]) {
+ // Try to swing left on the modified corner table. We need to get the
+ // first corner that defines an attribute seam.
+ act_c = SwingLeft(first_c);
+ while (act_c != kInvalidCornerIndex) {
+ first_c = act_c;
+ act_c = SwingLeft(act_c);
+ }
+ }
+ corner_to_vertex_map_[first_c.value()] = VertexIndex(first_vert_id.value());
+ vertex_to_left_most_corner_map_.push_back(first_c);
+ act_c = corner_table_->SwingRight(first_c);
+ while (act_c != kInvalidCornerIndex && act_c != first_c) {
+ if (IsCornerOppositeToSeamEdge(corner_table_->Next(act_c))) {
+ first_vert_id = AttributeValueIndex(num_new_vertices++);
+ if (init_vertex_to_attribute_entry_map) {
+ const PointIndex point_id = mesh->CornerToPointId(act_c.value());
+ vertex_to_attribute_entry_id_map_.push_back(
+ att->mapped_index(point_id));
+ } else {
+ // Identity mapping.
+ vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
+ }
+ vertex_to_left_most_corner_map_.push_back(act_c);
+ }
+ corner_to_vertex_map_[act_c.value()] = VertexIndex(first_vert_id.value());
+ act_c = corner_table_->SwingRight(act_c);
+ }
+ }
+}
+
+int MeshAttributeCornerTable::Valence(VertexIndex v) const {
+ if (v == kInvalidVertexIndex) {
+ return -1;
+ }
+ return ConfidentValence(v);
+}
+
+int MeshAttributeCornerTable::ConfidentValence(VertexIndex v) const {
+ DRACO_DCHECK_LT(v.value(), num_vertices());
+ draco::VertexRingIterator<MeshAttributeCornerTable> vi(this, v);
+ int valence = 0;
+ for (; !vi.End(); vi.Next()) {
+ ++valence;
+ }
+ return valence;
+}
+
+} // namespace draco