Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/dracoenc/src/draco/io/ply_decoder.cc
| Context not available. | |||||
| #include <fstream> | #include <fstream> | ||||
| #include "draco/core/macros.h" | #include "draco/core/macros.h" | ||||
| #include "draco/core/status.h" | |||||
| #include "draco/io/ply_property_reader.h" | #include "draco/io/ply_property_reader.h" | ||||
| namespace draco { | namespace draco { | ||||
| PlyDecoder::PlyDecoder() : out_mesh_(nullptr), out_point_cloud_(nullptr) {} | PlyDecoder::PlyDecoder() : out_mesh_(nullptr), out_point_cloud_(nullptr) {} | ||||
| bool PlyDecoder::DecodeFromFile(const std::string &file_name, Mesh *out_mesh) { | Status PlyDecoder::DecodeFromFile(const std::string &file_name, | ||||
| Mesh *out_mesh) { | |||||
| out_mesh_ = out_mesh; | out_mesh_ = out_mesh; | ||||
| return DecodeFromFile(file_name, static_cast<PointCloud *>(out_mesh)); | return DecodeFromFile(file_name, static_cast<PointCloud *>(out_mesh)); | ||||
| } | } | ||||
| bool PlyDecoder::DecodeFromFile(const std::string &file_name, | Status PlyDecoder::DecodeFromFile(const std::string &file_name, | ||||
| PointCloud *out_point_cloud) { | PointCloud *out_point_cloud) { | ||||
| std::ifstream file(file_name, std::ios::binary); | std::ifstream file(file_name, std::ios::binary); | ||||
| if (!file) | if (!file) | ||||
| return false; | return Status(Status::IO_ERROR, "Couldn't open file"); | ||||
| // Read the whole file into a buffer. | // Read the whole file into a buffer. | ||||
| auto pos0 = file.tellg(); | auto pos0 = file.tellg(); | ||||
| file.seekg(0, std::ios::end); | file.seekg(0, std::ios::end); | ||||
| auto file_size = file.tellg() - pos0; | auto file_size = file.tellg() - pos0; | ||||
| if (file_size == 0) | if (file_size == 0) | ||||
| return false; | return Status(Status::IO_ERROR, "Zero file size"); | ||||
| file.seekg(0, std::ios::beg); | file.seekg(0, std::ios::beg); | ||||
| std::vector<char> data(file_size); | std::vector<char> data(file_size); | ||||
| file.read(&data[0], file_size); | file.read(&data[0], file_size); | ||||
| Context not available. | |||||
| return DecodeFromBuffer(&buffer_, out_point_cloud); | return DecodeFromBuffer(&buffer_, out_point_cloud); | ||||
| } | } | ||||
| bool PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) { | Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) { | ||||
| out_mesh_ = out_mesh; | out_mesh_ = out_mesh; | ||||
| return DecodeFromBuffer(buffer, static_cast<PointCloud *>(out_mesh)); | return DecodeFromBuffer(buffer, static_cast<PointCloud *>(out_mesh)); | ||||
| } | } | ||||
| bool PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, | Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, | ||||
| PointCloud *out_point_cloud) { | PointCloud *out_point_cloud) { | ||||
| out_point_cloud_ = out_point_cloud; | out_point_cloud_ = out_point_cloud; | ||||
| buffer_.Init(buffer->data_head(), buffer->remaining_size()); | buffer_.Init(buffer->data_head(), buffer->remaining_size()); | ||||
| return DecodeInternal(); | return DecodeInternal(); | ||||
| } | } | ||||
| bool PlyDecoder::DecodeInternal() { | Status PlyDecoder::DecodeInternal() { | ||||
| PlyReader ply_reader; | PlyReader ply_reader; | ||||
| if (!ply_reader.Read(buffer())) | DRACO_RETURN_IF_ERROR(ply_reader.Read(buffer())); | ||||
| return false; | |||||
| // First, decode the connectivity data. | // First, decode the connectivity data. | ||||
| if (out_mesh_ && !DecodeFaceData(ply_reader.GetElementByName("face"))) | if (out_mesh_) | ||||
| return false; | DRACO_RETURN_IF_ERROR(DecodeFaceData(ply_reader.GetElementByName("face"))); | ||||
| // Decode all attributes. | // Decode all attributes. | ||||
| if (!DecodeVertexData(ply_reader.GetElementByName("vertex"))) | DRACO_RETURN_IF_ERROR( | ||||
| return false; | DecodeVertexData(ply_reader.GetElementByName("vertex"))); | ||||
| #ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED | |||||
| // In case there are no faces this is just a point cloud which does | // In case there are no faces this is just a point cloud which does | ||||
| // not require deduplication. | // not require deduplication. | ||||
| if (out_mesh_ && out_mesh_->num_faces() != 0) { | if (out_mesh_ && out_mesh_->num_faces() != 0) { | ||||
| #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED | |||||
| if (!out_point_cloud_->DeduplicateAttributeValues()) | if (!out_point_cloud_->DeduplicateAttributeValues()) | ||||
| return false; | return Status(Status::DRACO_ERROR, | ||||
| "Could not deduplicate attribute values"); | |||||
| #endif | |||||
| #ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED | |||||
| out_point_cloud_->DeduplicatePointIds(); | out_point_cloud_->DeduplicatePointIds(); | ||||
| } | |||||
| #endif | #endif | ||||
| return true; | } | ||||
| return OkStatus(); | |||||
| } | } | ||||
| bool PlyDecoder::DecodeFaceData(const PlyElement *face_element) { | Status PlyDecoder::DecodeFaceData(const PlyElement *face_element) { | ||||
| // We accept point clouds now. | // We accept point clouds now. | ||||
| if (face_element == nullptr) { | if (face_element == nullptr) { | ||||
| return true; | return Status(Status::INVALID_PARAMETER, "face_element is null"); | ||||
| } | } | ||||
| const int64_t num_faces = face_element->num_entries(); | const int64_t num_faces = face_element->num_entries(); | ||||
| out_mesh_->SetNumFaces(num_faces); | out_mesh_->SetNumFaces(num_faces); | ||||
| Context not available. | |||||
| vertex_indices = face_element->GetPropertyByName("vertex_index"); | vertex_indices = face_element->GetPropertyByName("vertex_index"); | ||||
| } | } | ||||
| if (vertex_indices == nullptr || !vertex_indices->is_list()) { | if (vertex_indices == nullptr || !vertex_indices->is_list()) { | ||||
| return false; // No faces defined. | return Status(Status::DRACO_ERROR, "No faces defined"); | ||||
| } | } | ||||
| PlyPropertyReader<PointIndex::ValueType> vertex_index_reader(vertex_indices); | PlyPropertyReader<PointIndex::ValueType> vertex_index_reader(vertex_indices); | ||||
| Context not available. | |||||
| face_index++; | face_index++; | ||||
| } | } | ||||
| out_mesh_->SetNumFaces(face_index.value()); | out_mesh_->SetNumFaces(face_index.value()); | ||||
| return true; | return OkStatus(); | ||||
| } | } | ||||
| template <typename DataTypeT> | template <typename DataTypeT> | ||||
| Context not available. | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) { | Status PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) { | ||||
| if (vertex_element == nullptr) | if (vertex_element == nullptr) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, "vertex_element is null"); | ||||
| // TODO(ostava): For now, try to load x,y,z vertices and red,green,blue,alpha | // TODO(ostava): For now, try to load x,y,z vertices and red,green,blue,alpha | ||||
| // colors. We need to add other properties later. | // colors. We need to add other properties later. | ||||
| const PlyProperty *const x_prop = vertex_element->GetPropertyByName("x"); | const PlyProperty *const x_prop = vertex_element->GetPropertyByName("x"); | ||||
| Context not available. | |||||
| if (!x_prop || !y_prop || !z_prop) { | if (!x_prop || !y_prop || !z_prop) { | ||||
| // Currently, we require 3 vertex coordinates (this should be generalized | // Currently, we require 3 vertex coordinates (this should be generalized | ||||
| // later on). | // later on). | ||||
| return false; | return Status(Status::INVALID_PARAMETER, "x, y, or z property is missing"); | ||||
| } | } | ||||
| const PointIndex::ValueType num_vertices = vertex_element->num_entries(); | const PointIndex::ValueType num_vertices = vertex_element->num_entries(); | ||||
| out_point_cloud_->set_num_points(num_vertices); | out_point_cloud_->set_num_points(num_vertices); | ||||
| Context not available. | |||||
| // All properties must have the same type. | // All properties must have the same type. | ||||
| if (x_prop->data_type() != y_prop->data_type() || | if (x_prop->data_type() != y_prop->data_type() || | ||||
| y_prop->data_type() != z_prop->data_type()) { | y_prop->data_type() != z_prop->data_type()) { | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "x, y, and z properties must have the same type"); | |||||
| } | } | ||||
| // TODO(ostava): For now assume the position types are float32 or int32. | // TODO(ostava): For now assume the position types are float32 or int32. | ||||
| const DataType dt = x_prop->data_type(); | const DataType dt = x_prop->data_type(); | ||||
| if (dt != DT_FLOAT32 && dt != DT_INT32) | if (dt != DT_FLOAT32 && dt != DT_INT32) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "x, y, and z properties must be of type float32 or int32"); | |||||
| GeometryAttribute va; | GeometryAttribute va; | ||||
| va.Init(GeometryAttribute::POSITION, nullptr, 3, dt, false, | va.Init(GeometryAttribute::POSITION, nullptr, 3, dt, false, | ||||
| Context not available. | |||||
| // TODO(ostava): For now ensure the data type of all components is uint8. | // TODO(ostava): For now ensure the data type of all components is uint8. | ||||
| DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | ||||
| if (p->data_type() != DT_UINT8) | if (p->data_type() != DT_UINT8) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "Type of 'red' property must be uint8"); | |||||
| color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | ||||
| new PlyPropertyReader<uint8_t>(p))); | new PlyPropertyReader<uint8_t>(p))); | ||||
| } | } | ||||
| Context not available. | |||||
| // TODO(ostava): For now ensure the data type of all components is uint8. | // TODO(ostava): For now ensure the data type of all components is uint8. | ||||
| DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | ||||
| if (p->data_type() != DT_UINT8) | if (p->data_type() != DT_UINT8) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "Type of 'green' property must be uint8"); | |||||
| color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | ||||
| new PlyPropertyReader<uint8_t>(p))); | new PlyPropertyReader<uint8_t>(p))); | ||||
| } | } | ||||
| Context not available. | |||||
| // TODO(ostava): For now ensure the data type of all components is uint8. | // TODO(ostava): For now ensure the data type of all components is uint8. | ||||
| DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | ||||
| if (p->data_type() != DT_UINT8) | if (p->data_type() != DT_UINT8) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "Type of 'blue' property must be uint8"); | |||||
| color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | ||||
| new PlyPropertyReader<uint8_t>(p))); | new PlyPropertyReader<uint8_t>(p))); | ||||
| } | } | ||||
| Context not available. | |||||
| // TODO(ostava): For now ensure the data type of all components is uint8. | // TODO(ostava): For now ensure the data type of all components is uint8. | ||||
| DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); | ||||
| if (p->data_type() != DT_UINT8) | if (p->data_type() != DT_UINT8) | ||||
| return false; | return Status(Status::INVALID_PARAMETER, | ||||
| "Type of 'alpha' property must be uint8"); | |||||
| color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( | ||||
| new PlyPropertyReader<uint8_t>(p))); | new PlyPropertyReader<uint8_t>(p))); | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| return true; | return OkStatus(); | ||||
| } | } | ||||
| } // namespace draco | } // namespace draco | ||||
| Context not available. | |||||