draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
2016-12-12 16:39:06 -08:00

186 lines
7.8 KiB
C++

// 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_COMPRESSION_MESH_MESH_EDGEBREAKER_ENCODER_IMPL_H_
#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_ENCODER_IMPL_H_
#include <unordered_map>
#include "compression/attributes/mesh_attribute_indices_encoding_data.h"
#include "compression/mesh/mesh_edgebreaker_encoder_impl_interface.h"
#include "compression/mesh/mesh_edgebreaker_shared.h"
#include "core/encoder_buffer.h"
#include "mesh/mesh_attribute_corner_table.h"
namespace draco {
// Class implementing the edgebreaker encoding as described in "3D Compression
// Made Simple: Edgebreaker on a Corner-Table" by Rossignac at al.'01.
// http://www.cc.gatech.edu/~jarek/papers/CornerTableSMI.pdf
template <class TraversalEncoderT>
class MeshEdgeBreakerEncoderImpl : public MeshEdgeBreakerEncoderImplInterface {
public:
MeshEdgeBreakerEncoderImpl();
bool Init(MeshEdgeBreakerEncoder *encoder) override;
const MeshAttributeCornerTable *GetAttributeCornerTable(
int att_id) const override;
const MeshAttributeIndicesEncodingData *GetAttributeEncodingData(
int att_id) const override;
bool GenerateAttributesEncoder(int32_t att_id) override;
bool EncodeAttributesEncoderIdentifier(int32_t att_encoder_id) override;
bool EncodeConnectivity() override;
const CornerTable *GetCornerTable() const override {
return corner_table_.get();
}
MeshEdgeBreakerEncoder *GetEncoder() const override { return encoder_; }
private:
// Initializes data needed for encoding non-position attributes.
// Returns false on error.
bool InitAttributeData();
// Finds the configuration of the initial face that starts the traversal.
// Configurations are determined by location of holes around the init face
// and they are described in mesh_edgebreaker_shared.h.
// Returns true if the face configuration is interior and false if it is
// exterior.
bool FindInitFaceConfiguration(FaceIndex face_id,
CornerIndex *out_corner_id) const;
// Encodes the connectivity between vertices.
bool EncodeConnectivityFromCorner(CornerIndex corner_id);
// Encodes all vertices of a hole starting at start_corner_id.
// The vertex associated with the first corner is encoded only if
// |encode_first_vertex| is true.
// Returns the number of encoded hole vertices.
int EncodeHole(CornerIndex start_corner_id, bool encode_first_vertex);
CornerIndex GetRightCorner(CornerIndex corner_id) const;
CornerIndex GetLeftCorner(CornerIndex corner_id) const;
bool IsRightFaceVisited(CornerIndex corner_id) const;
bool IsLeftFaceVisited(CornerIndex corner_id) const;
bool IsVertexVisited(VertexIndex vert_id) const {
return visited_vertex_ids_[vert_id.value()];
}
// Finds and stores data about all holes in the input mesh.
bool FindHoles();
// For faces encoded with symbol TOPOLOGY_S (split), this method returns
// the encoded symbol id or -1 if the face wasn't encoded by a split symbol.
int GetSplitSymbolIdOnFace(int face_id) const;
// Checks whether there is a topology split event on a neighboring face and
// stores the event data if necessary. For more info about topology split
// events, see description of TopologySplitEventData in
// mesh_edgebreaker_shared.h.
void CheckAndStoreTopologySplitEvent(int src_symbol_id, int src_face_id,
EdgeFaceName src_edge,
int neighbor_face_id);
// Encodes connectivity of all attributes on a newly traversed face.
bool EncodeAttributeConnectivitiesOnFace(CornerIndex corner);
// This function is used to to assign correct encoding order of attributes
// to unprocessed corners. The encoding order is equal to the order in which
// the attributes are going to be processed by the decoder and it is necessary
// for proper prediction of attribute values.
bool AssignPositionEncodingOrderToAllCorners();
// This function is used to generate encoding order for all non-position
// attributes.
// Returns false when one or more attributes failed to be processed.
bool GenerateEncodingOrderForAttributes();
// The main encoder that own's this class.
MeshEdgeBreakerEncoder *encoder_;
// Mesh that's being encoded.
const Mesh *mesh_;
// Corner table stores the mesh face connectivity data.
std::unique_ptr<CornerTable> corner_table_;
// Stack used for storing corners that need to be traversed when encoding
// the connectivity. New corner is added for each initial face and a split
// symbol, and one corner is removed when the end symbol is reached.
// Stored as member variable to prevent frequent memory reallocations when
// handling meshes with lots of disjoint components. Originally, we used
// recursive functions to handle this behavior, but that can cause stack
// memory overflow when compressing huge meshes.
std::vector<CornerIndex> corner_traversal_stack_;
// Array for marking visited faces.
std::vector<bool> visited_faces_;
// Attribute data for position encoding.
MeshAttributeIndicesEncodingData pos_encoding_data_;
// Array storing corners in the order they were visited during the
// connectivity encoding (always storing the tip corner of each newly visited
// face).
std::vector<CornerIndex> processed_connectivity_corners_;
// Array for storing visited vertex ids of all input vertices.
std::vector<bool> visited_vertex_ids_;
// For each traversal, this array stores the number of visited vertices.
std::vector<int> vertex_traversal_length_;
// Array for storing all topology split events encountered during the mesh
// traversal.
std::vector<TopologySplitEventData> topology_split_event_data_;
// Map between face_id and symbol_id. Contains entries only for faces that
// were encoded with TOPOLOGY_S symbol.
std::unordered_map<int, int> face_to_split_symbol_map_;
// Array for marking holes that has been reached during the traversal.
std::vector<bool> visited_holes_;
// Array for mapping vertices to hole ids. If a vertex is not on a hole, the
// stored value is -1.
std::vector<int> vertex_hole_id_;
// Array of hole events encountered during the traversal. There will be always
// exactly one hole event for each hole in the input mesh.
std::vector<HoleEventData> hole_event_data_;
// Id of the last encoded symbol.
int last_encoded_symbol_id_;
// The number of encoded split symbols.
uint32_t num_split_symbols_;
// Struct holding data used for encoding each non-position attribute.
// TODO(ostava): This should be probably renamed to something better.
struct AttributeData {
AttributeData() : attribute_index(-1), is_connectivity_used(true) {}
int attribute_index;
MeshAttributeCornerTable connectivity_data;
// Flag that can mark the connectivity_data invalid. In such case the base
// corner table of the mesh should be used instead.
bool is_connectivity_used;
// Data about attribute encoding order.
MeshAttributeIndicesEncodingData encoding_data;
};
std::vector<AttributeData> attribute_data_;
// Array storing mapping between attribute encoder id and attribute data id.
std::vector<int32_t> attribute_encoder_to_data_id_map_;
TraversalEncoderT traversal_encoder_;
};
} // namespace draco
#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_ENCODER_IMPL_H_