Skip to content

Commit

Permalink
partially working draco point cloud reader
Browse files Browse the repository at this point in the history
  • Loading branch information
hobu committed Nov 17, 2020
1 parent 51c9511 commit 0101c08
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 86 deletions.
284 changes: 206 additions & 78 deletions plugins/draco/io/DracoReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@
****************************************************************************/

#include <algorithm>
#include <pdal/util/FileUtils.hpp>

#include "DracoReader.hpp"

#include <draco/io/point_cloud_io.h>
#include <draco/compression/decode.h>

namespace pdal {

static PluginInfo const s_info
Expand All @@ -48,6 +52,46 @@ static PluginInfo const s_info
CREATE_SHARED_STAGE(DracoReader, s_info)
std::string DracoReader::getName() const { return s_info.name; }

// CopyAttributeData<double>(m_count, attr, m_position);
// Returns the attribute data in |attr| as an array of type T.
template <typename T>
bool CopyAttributeData(int num_points,
const draco::PointAttribute *attr,
std::vector<T>& data)
{
const int num_components = attr->num_components();
data.resize(num_points * num_components, T(0));

for (draco::PointIndex i(0); i < num_points; ++i) {
const draco::AttributeValueIndex val_index = attr->mapped_index(i);
bool got_data = false;
switch (num_components) {
case 1:
got_data = attr->ConvertValue<T, 1>(val_index,
data.data() + i.value() * num_components);
break;
case 2:
got_data = attr->ConvertValue<T, 2>(val_index,
data.data() + i.value() * num_components);
break;
case 3:
got_data = attr->ConvertValue<T, 3>(val_index,
data.data() + i.value() * num_components);
break;
case 4:
got_data = attr->ConvertValue<T, 4>(val_index,
data.data() + i.value() * num_components);
break;
default:
break;
}
if (!got_data)
throw pdal_error("CopyAttributeData unable to read data for point ");
}

return true;
}

Dimension::Type getPdalType(draco::DataType t)
{
using namespace draco;
Expand Down Expand Up @@ -82,14 +126,6 @@ Dimension::Type getPdalType(draco::DataType t)

void DracoReader::addArgs(ProgramArgs& args)
{
// args.addSynonym("filename", "array_name");
// args.add("config_file", "Draco configuration file location",
// m_cfgFileName);
// args.add("chunk_size", "Draco read chunk size", m_chunkSize,
// point_count_t(1000000));
// args.add("stats", "Dump Draco query stats to stdout", m_stats, false);
// args.add("bbox3d", "Bounding box subarray to read from Draco in format "
// "([minx, maxx], [miny, maxy], [minz, maxz])", m_bbox);
}

void DracoReader::prepared(PointTableRef table)
Expand All @@ -102,97 +138,190 @@ void DracoReader::prepared(PointTableRef table)

void DracoReader::initialize()
{
if (!FileUtils::fileExists(m_filename))
throwError("File '" + m_filename + "' does not exist");

m_istreamPtr = Utils::openFile(m_filename, true);
if (!m_istreamPtr)
throwError("Unable to open file '" + m_filename + "' ");

m_data.assign(std::istreambuf_iterator<char>(*m_istreamPtr),
std::istreambuf_iterator<char>());
Utils::closeFile(m_istreamPtr);

m_draco_buffer.Init(m_data.data(), m_data.size());

draco::Decoder decoder;
auto geom_status = draco::Decoder::GetEncodedGeometryType(&m_draco_buffer);
if (!geom_status.ok())
{
return throwError(geom_status.status().error_msg());
}

const draco::EncodedGeometryType geom_type = geom_status.value();

draco::Decoder::GetEncodedGeometryType(&m_draco_buffer);

draco::StatusOr<std::unique_ptr<draco::PointCloud>> pc_status = decoder.DecodePointCloudFromBuffer(&m_draco_buffer);
if (!pc_status.ok())
{
return throwError(pc_status.status().error_msg());
}

m_pc = std::move(pc_status).value();

m_count = m_pc->num_points();


}


void DracoReader::addDimensions(PointLayoutPtr layout)
{
using namespace draco;

}
log()->get(LogLevel::Debug) << "draco pc num_attributes: "
<< m_pc->num_attributes() << std::endl;;

void DracoReader::ready(PointTableRef)
{
m_istreamPtr = Utils::openFile(m_filename, true);
m_data.assign(std::istreambuf_iterator<char>(*m_istreamPtr),
std::istreambuf_iterator<char>());
Utils::closeFile(m_istreamPtr);
const GeometryMetadata *metadata = m_pc->GetMetadata();
for (int i=0; i < m_pc->num_attributes(); ++i)
{
const PointAttribute* attr = m_pc->GetAttributeByUniqueId(i);
const AttributeMetadata* attr_metatata = m_pc->GetAttributeMetadataByAttributeId(i);
DataType dt = attr->data_type();
GeometryAttribute::Type at = attr->attribute_type();

std::cerr << "size: " << m_data.size() << std::endl;
int8_t nc = attr->num_components();
log()->get(LogLevel::Debug) << "named component: "
<< GeometryAttribute::TypeToString(at)
<< " subcomponents: " << (int)nc << std::endl;;
std::string name;
if (attr_metatata)
{
log()->get(LogLevel::Debug) << "number of metadata: "
<< attr_metatata->num_entries()
<< std::endl;;
attr_metatata->GetEntryString("name", &name);
}
switch (at)
{
case GeometryAttribute::POSITION:
layout->registerDim(Dimension::Id::X);
layout->registerDim(Dimension::Id::Y);
layout->registerDim(Dimension::Id::Z);
break;
case GeometryAttribute::NORMAL:
layout->registerDim(Dimension::Id::NormalX);
layout->registerDim(Dimension::Id::NormalY);
layout->registerDim(Dimension::Id::NormalZ);
break;
case GeometryAttribute::COLOR:
layout->registerDim(Dimension::Id::Red);
layout->registerDim(Dimension::Id::Green);
layout->registerDim(Dimension::Id::Blue);
case GeometryAttribute::TEX_COORD:
layout->registerDim(Dimension::Id::TextureU);
layout->registerDim(Dimension::Id::TextureV);
layout->registerDim(Dimension::Id::TextureW);
break;

m_draco_buffer.Init(m_data.data(), m_data.size());
case GeometryAttribute::GENERIC:
layout->registerOrAssignDim(name, getPdalType(dt));
break;

default:
// Not supported draco domain types
throw pdal_error("Unknown Geometry Attribute Type");
}

// for (draco::PointIndex pi(0); pi < m_count; ++pi) {
// std::vector<float> results = CopyAttributeData<float>(m_count, attr);
// for (std::vector<float>::size_type t = 0; t < results.size();)
// {
// std::cout << "t: " << t << "xyz: " << results[t] << "," << results[t+1] << "," << results[t+2] << std::endl;
// t = t + nc;
// }
// m_pc->attribute(i)->GetMappedValue(pi, results.data());
// std::cout << "xyz: " << results[0] << "," << results[1] << "," << results[2] << std::endl;
// }

draco::Decoder decoder;
auto statusor = decoder.DecodePointCloudFromBuffer(&m_draco_buffer);
auto type_statusor = draco::Decoder::GetEncodedGeometryType(&m_draco_buffer);
if (!type_statusor.ok())
{
return throwError(type_statusor.status().error_msg());
}
const draco::EncodedGeometryType geom_type = type_statusor.value();

}

void DracoReader::ready(PointTableRef)
{
using namespace draco;
for (int at_id=0; at_id < m_pc->num_attributes(); ++at_id)
{
const PointAttribute* attr = m_pc->GetAttributeByUniqueId(at_id);
DataType dt = attr->data_type();
GeometryAttribute::Type at = attr->attribute_type();

switch (at)
{
case GeometryAttribute::POSITION:
CopyAttributeData<double>(m_count, attr, m_positions);
break;
case GeometryAttribute::NORMAL:
CopyAttributeData<double>(m_count, attr, m_normals);
break;
case GeometryAttribute::COLOR:
CopyAttributeData<uint16_t>(m_count, attr, m_colors);
case GeometryAttribute::TEX_COORD:
CopyAttributeData<double>(m_count, attr, m_textures);
break;

case GeometryAttribute::GENERIC:
break;

// namespace
// {
//
// template<typename DracoEngine>
// size_t addFields(DracoEngine& engine, const DimTypeList& dims)
// {
// using namespace Dimension;
// using namespace draco;
//
// size_t pointSize = 0;
// for (auto di = dims.begin(); di != dims.end(); ++di)
default:
// Not supported draco domain types
throw pdal_error("Unknown Geometry Attribute Type");
}
}

// for (int i=0; i < m_count; ++i)
// {
// switch (di->m_type)
// {
// case Type::Double:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_FLOAT64);
// break;
// case Type::Float:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_FLOAT32);
// break;
// case Type::Signed64:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT64);
// break;
// case Type::Signed32:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT32);
// break;
// case Type::Signed16:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16);
// break;
// case Type::Signed8:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT8);
// break;
// case Type::Unsigned64:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT64);
// break;
// case Type::Unsigned32:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT32);
// break;
// case Type::Unsigned16:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT16);
// break;
// case Type::Unsigned8:
// engine.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT8);
// break;
// default:
// return 0;
// }
// pointSize += Dimension::size(di->m_type);
// std::cout << m_positions[i*3] << "," << m_positions[i*3+1] << ", " << m_positions[i*3+2] << std::endl;
// }
// return pointSize;
// }
//
// } // anonymous namespace
//

}


bool DracoReader::processOne(PointRef& point)
{
return false;

point_count_t pid = point.pointId();

if (m_positions.size())
{
point.setField(Dimension::Id::X, m_positions[pid*3]);
point.setField(Dimension::Id::Y, m_positions[pid*3+1]);
point.setField(Dimension::Id::Z, m_positions[pid*3+2]);
}

if (m_normals.size())
{
point.setField(Dimension::Id::NormalX, m_normals[pid*3]);
point.setField(Dimension::Id::NormalY, m_normals[pid*3+1]);
point.setField(Dimension::Id::NormalZ, m_normals[pid*3+2]);
}

if (m_textures.size())
{
point.setField(Dimension::Id::TextureU, m_textures[pid*3]);
point.setField(Dimension::Id::TextureV, m_textures[pid*3+1]);
point.setField(Dimension::Id::TextureW, m_textures[pid*3+2]);
}

if (m_colors.size())
{
point.setField(Dimension::Id::Red, m_colors[pid*3]);
point.setField(Dimension::Id::Green, m_colors[pid*3+1]);
point.setField(Dimension::Id::Blue, m_colors[pid*3+2]);
}
return true;
}


Expand All @@ -211,7 +340,6 @@ point_count_t DracoReader::read(PointViewPtr view, point_count_t count)

void DracoReader::done(pdal::BasePointTable &table)
{
// m_array->close();
}

} // namespace pdal
7 changes: 5 additions & 2 deletions plugins/draco/io/DracoReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,13 @@
#include <iostream>

#include <pdal/Reader.hpp>
#include <pdal/Streamable.hpp>
#include <draco/point_cloud/point_cloud.h>
#include <draco/compression/decode.h>

namespace pdal
{

class PDAL_DLL DracoReader : public Reader, public Streamable
class PDAL_DLL DracoReader : public Reader
{
public:

Expand All @@ -69,6 +68,10 @@ class PDAL_DLL DracoReader : public Reader, public Streamable
std::vector<char> m_data;
draco::DecoderBuffer m_draco_buffer;
std::unique_ptr<draco::PointCloud> m_pc;
std::vector<double> m_positions;
std::vector<uint16_t> m_colors;
std::vector<double> m_normals;
std::vector<double> m_textures;

};

Expand Down
7 changes: 1 addition & 6 deletions plugins/draco/test/DracoReaderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ TEST(DracoReaderTest, test_sequential)

Options ops1;
ops1.add("filename", Support::datapath("draco/1.2-with-color.drc"));
ops1.add("count", 103);
DracoReader reader;
reader.setOptions(ops1);

Expand All @@ -86,11 +85,7 @@ TEST(DracoReaderTest, test_sequential)
EXPECT_EQ(viewSet.size(), 1u);
PointViewPtr view = *viewSet.begin();
Support::check_p0_p1_p2(*view);
PointViewPtr view2 = view->makeNew();
view2->appendPoint(*view, 100);
view2->appendPoint(*view, 101);
view2->appendPoint(*view, 102);
Support::check_p100_p101_p102(*view2);

}


Expand Down
Binary file added test/data/draco/1.2-with-color.drc
Binary file not shown.

0 comments on commit 0101c08

Please sign in to comment.