// 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_H_ #define DRACO_MESH_MESH_H_ #include #include "core/hash_utils.h" #include "core/macros.h" #include "mesh/mesh_indices.h" #include "point_cloud/point_cloud.h" namespace draco { // List of different variants of mesh attributes. enum MeshAttributeElementType { // All corners attached to a vertex share the same attribute value. A typical // example are the vertex positions and often vertex colors. MESH_VERTEX_ATTRIBUTE = 0, // The most general attribute where every corner of the mesh can have a // different attribute value. Often used for texture coordinates or normals. MESH_CORNER_ATTRIBUTE, // All corners of a single face share the same value. MESH_FACE_ATTRIBUTE }; // Mesh class can be used to represent general triangular meshes. Internally, // Mesh is just an extended PointCloud with extra connectivity data that defines // what points are connected together in triangles. class Mesh : public PointCloud { public: typedef std::array Face; Mesh(); void AddFace(const Face &face) { faces_.push_back(face); } void SetFace(FaceIndex face_id, const Face &face) { if (face_id >= faces_.size()) { faces_.resize(face_id.value() + 1, Face()); } faces_[face_id] = face; } // Sets the total number of faces. Creates new empty faces or deletes // existing ones if necessary. void SetNumFaces(size_t num_faces) { faces_.resize(num_faces, Face()); } FaceIndex::ValueType num_faces() const { return faces_.size(); } const Face &face(FaceIndex face_id) const { DCHECK_LE(0, face_id.value()); DCHECK_LT(face_id.value(), static_cast(faces_.size())); return faces_[face_id]; } void SetAttribute(int att_id, std::unique_ptr pa) override { PointCloud::SetAttribute(att_id, std::move(pa)); if (static_cast(attribute_data_.size()) <= att_id) { attribute_data_.resize(att_id + 1); } } MeshAttributeElementType GetAttributeElementType(int att_id) const { return attribute_data_[att_id].element_type; } void SetAttributeElementType(int att_id, MeshAttributeElementType et) { attribute_data_[att_id].element_type = et; } struct AttributeData { AttributeData() : element_type(MESH_CORNER_ATTRIBUTE) {} MeshAttributeElementType element_type; }; protected: // Extends the point deduplication to face corners. This method is called from // the PointCloud::DeduplicatePointIds() and it remaps all point ids stored in // |faces_| to the new deduplicated point ids using the map |id_map|. void ApplyPointIdDeduplication( const IndexTypeVector &id_map, const std::vector &unique_point_ids) override; private: // Mesh specific per-attribute data. std::vector attribute_data_; // Vertex indices valid for all attributes. Each attribute has its own map // that converts vertex indices into attribute indices. IndexTypeVector faces_; friend struct MeshHasher; }; // Functor for computing a hash from data stored within a mesh. // Note that this can be quite slow. Two meshes will have the same hash only // when they have exactly the same connectivity and attribute values. struct MeshHasher { size_t operator()(const Mesh &mesh) const { PointCloudHasher pc_hasher; size_t hash = pc_hasher(mesh); // Hash faces. for (FaceIndex i(0); i < mesh.faces_.size(); ++i) { for (int j = 0; j < 3; ++j) { hash = HashCombine(mesh.faces_[i][j].value(), hash); } } return hash; } }; } // namespace draco #endif // DRACO_MESH_MESH_H_