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

mesh_attribute_corner_table.h « mesh « draco « src « draco « draco « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6f02453d2d401acba8d31dd72c10d48255f31239 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// 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.
//
#ifndef DRACO_MESH_MESH_ATTRIBUTE_CORNER_TABLE_H_
#define DRACO_MESH_MESH_ATTRIBUTE_CORNER_TABLE_H_

#include "draco/core/macros.h"
#include "draco/mesh/corner_table.h"
#include "draco/mesh/mesh.h"
#include "draco/mesh/valence_cache.h"

namespace draco {

// Class for storing connectivity of mesh attributes. The connectivity is stored
// as a difference from the base mesh's corner table, where the differences are
// represented by attribute seam edges. This class provides a basic
// functionality for detecting the seam edges for a given attribute and for
// traversing the constrained corner table with the seam edges.
class MeshAttributeCornerTable {
 public:
  MeshAttributeCornerTable();
  bool InitEmpty(const CornerTable *table);
  bool InitFromAttribute(const Mesh *mesh, const CornerTable *table,
                         const PointAttribute *att);

  void AddSeamEdge(CornerIndex opp_corner);

  // Recomputes vertices using the newly added seam edges (needs to be called
  // whenever the seam edges are updated).
  // |mesh| and |att| can be null, in which case mapping between vertices and
  // attribute value ids is set to identity.
  void RecomputeVertices(const Mesh *mesh, const PointAttribute *att);

  inline bool IsCornerOppositeToSeamEdge(CornerIndex corner) const {
    return is_edge_on_seam_[corner.value()];
  }

  inline CornerIndex Opposite(CornerIndex corner) const {
    if (corner == kInvalidCornerIndex || IsCornerOppositeToSeamEdge(corner)) {
      return kInvalidCornerIndex;
    }
    return corner_table_->Opposite(corner);
  }

  inline CornerIndex Next(CornerIndex corner) const {
    return corner_table_->Next(corner);
  }

  inline CornerIndex Previous(CornerIndex corner) const {
    return corner_table_->Previous(corner);
  }

  // Returns true when a corner is attached to any attribute seam.
  inline bool IsCornerOnSeam(CornerIndex corner) const {
    return is_vertex_on_seam_[corner_table_->Vertex(corner).value()];
  }

  // Similar to CornerTable::GetLeftCorner and CornerTable::GetRightCorner, but
  // does not go over seam edges.
  inline CornerIndex GetLeftCorner(CornerIndex corner) const {
    return Opposite(Previous(corner));
  }
  inline CornerIndex GetRightCorner(CornerIndex corner) const {
    return Opposite(Next(corner));
  }

  // Similar to CornerTable::SwingRight, but it does not go over seam edges.
  inline CornerIndex SwingRight(CornerIndex corner) const {
    return Previous(Opposite(Previous(corner)));
  }

  // Similar to CornerTable::SwingLeft, but it does not go over seam edges.
  inline CornerIndex SwingLeft(CornerIndex corner) const {
    return Next(Opposite(Next(corner)));
  }

  int num_vertices() const {
    return static_cast<int>(vertex_to_attribute_entry_id_map_.size());
  }
  int num_faces() const { return static_cast<int>(corner_table_->num_faces()); }
  int num_corners() const { return corner_table_->num_corners(); }

  VertexIndex Vertex(CornerIndex corner) const {
    DRACO_DCHECK_LT(corner.value(), corner_to_vertex_map_.size());
    return ConfidentVertex(corner);
  }
  VertexIndex ConfidentVertex(CornerIndex corner) const {
    return corner_to_vertex_map_[corner.value()];
  }
  // Returns the attribute entry id associated to the given vertex.
  VertexIndex VertexParent(VertexIndex vert) const {
    return VertexIndex(vertex_to_attribute_entry_id_map_[vert.value()].value());
  }

  inline CornerIndex LeftMostCorner(VertexIndex v) const {
    return vertex_to_left_most_corner_map_[v.value()];
  }

  inline FaceIndex Face(CornerIndex corner) const {
    return corner_table_->Face(corner);
  }

  inline CornerIndex FirstCorner(FaceIndex face) const {
    return corner_table_->FirstCorner(face);
  }

  inline std::array<CornerIndex, 3> AllCorners(FaceIndex face) const {
    return corner_table_->AllCorners(face);
  }

  inline bool IsOnBoundary(VertexIndex vert) const {
    const CornerIndex corner = LeftMostCorner(vert);
    if (corner == kInvalidCornerIndex) {
      return true;
    }
    if (SwingLeft(corner) == kInvalidCornerIndex) {
      return true;
    }
    return false;
  }

  bool IsDegenerated(FaceIndex face) const {
    // Introducing seams can't change the degeneracy of the individual faces,
    // therefore we can delegate the check to the original |corner_table_|.
    return corner_table_->IsDegenerated(face);
  }

  bool no_interior_seams() const { return no_interior_seams_; }
  const CornerTable *corner_table() const { return corner_table_; }

  // TODO(draco-eng): extract valence functions into a reusable class/object
  // also from 'corner_table.*'

  // Returns the valence (or degree) of a vertex.
  // Returns -1 if the given vertex index is not valid.
  int Valence(VertexIndex v) const;
  // Same as above but does not check for validity and does not return -1
  int ConfidentValence(VertexIndex v) const;
  // Returns the valence of the vertex at the given corner.
  inline int Valence(CornerIndex c) const {
    DRACO_DCHECK_LT(c.value(), corner_table_->num_corners());
    if (c == kInvalidCornerIndex) {
      return -1;
    }
    return ConfidentValence(c);
  }
  inline int ConfidentValence(CornerIndex c) const {
    DRACO_DCHECK_LT(c.value(), corner_table_->num_corners());
    return ConfidentValence(Vertex(c));
  }

  // Allows access to an internal object for caching valences.  The object can
  // be instructed to cache or uncache all valences and then its interfaces
  // queried directly for valences with differing performance/confidence
  // qualities.  If the mesh or table is modified the cache should be discarded
  // and not relied on as it does not automatically update or invalidate for
  // performance reasons.
  const ValenceCache<MeshAttributeCornerTable> &GetValenceCache() const {
    return valence_cache_;
  }

 private:
  template <bool init_vertex_to_attribute_entry_map>
  void RecomputeVerticesInternal(const Mesh *mesh, const PointAttribute *att);

  std::vector<bool> is_edge_on_seam_;
  std::vector<bool> is_vertex_on_seam_;

  // If this is set to true, it means that there are no attribute seams between
  // two faces. This can be used to speed up some algorithms.
  bool no_interior_seams_;

  std::vector<VertexIndex> corner_to_vertex_map_;

  // Map between vertices and their associated left most corners. A left most
  // corner is a corner that is adjacent to a boundary or an attribute seam from
  // right (i.e., SwingLeft from that corner will return an invalid corner). If
  // no such corner exists for a given vertex, then any corner attached to the
  // vertex can be used.
  std::vector<CornerIndex> vertex_to_left_most_corner_map_;

  // Map between vertex ids and attribute entry ids (i.e. the values stored in
  // the attribute buffer). The attribute entry id can be retrieved using the
  // VertexParent() method.
  std::vector<AttributeValueIndex> vertex_to_attribute_entry_id_map_;
  const CornerTable *corner_table_;
  ValenceCache<MeshAttributeCornerTable> valence_cache_;
};

}  // namespace draco
#endif  // DRACO_MESH_MESH_ATTRIBUTE_CORNER_TABLE_H_