8 #include "../include/DRCFilter.h"
10 #include "../include/SaveDracoFileDlg.h"
23 #include <draco/compression/decode.h>
24 #include <draco/compression/encode.h>
25 #include <draco/mesh/mesh.h>
26 #include <draco/point_cloud/point_cloud.h>
31 QStringList{
"drc"},
"drc",
32 QStringList{
"DRC cloud or mesh (*.drc)"},
33 QStringList{
"DRC cloud or mesh (*.drc)"},
38 bool& exclusive)
const {
50 unsigned pointCount = ccCloud.
size();
51 dracoCloud.set_num_points(pointCount);
53 draco::DataType dt = draco::DT_FLOAT32;
56 dt = draco::DT_FLOAT64;
61 draco::GeometryAttribute ga;
62 ga.Init(draco::GeometryAttribute::POSITION,
nullptr, 3, dt,
false,
63 DataTypeLength(dt) * 3, 0);
64 const int pointAttributeID =
65 dracoCloud.AddAttribute(ga,
true, pointCount);
67 draco::PointAttribute* pointAttribute =
68 dracoCloud.attribute(pointAttributeID);
69 if (
nullptr == pointAttribute) {
73 if (dt == draco::DT_FLOAT32) {
74 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i) {
75 pointAttribute->SetAttributeValue(draco::AttributeValueIndex(i),
80 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i) {
82 pointAttribute->SetAttributeValue(draco::AttributeValueIndex(i),
90 draco::GeometryAttribute ga;
91 ga.Init(draco::GeometryAttribute::NORMAL,
nullptr, 3, draco::DT_FLOAT32,
92 true, DataTypeLength(draco::DT_FLOAT32) * 3, 0);
93 const int normalAttributeID =
94 dracoCloud.AddAttribute(ga,
true, pointCount);
96 draco::PointAttribute* normalAttribute =
97 dracoCloud.attribute(normalAttributeID);
98 if (
nullptr != normalAttribute) {
99 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i) {
100 normalAttribute->SetAttributeValue(
101 draco::AttributeValueIndex(i),
111 draco::GeometryAttribute ga;
112 ga.Init(draco::GeometryAttribute::COLOR,
nullptr, 3, draco::DT_UINT8,
113 false, DataTypeLength(draco::DT_UINT8) * 3, 0);
114 const int colorAttributeID =
115 dracoCloud.AddAttribute(ga,
true, pointCount);
117 draco::PointAttribute* colorAttribute =
118 dracoCloud.attribute(colorAttributeID);
119 if (
nullptr != colorAttribute) {
120 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i) {
121 colorAttribute->SetAttributeValue(draco::AttributeValueIndex(i),
136 "[DRACO] Cloud %1 has multiple scalar fields, however, "
137 "only one can be saved (the active one by default)");
141 draco::GeometryAttribute ga;
142 ga.Init(draco::GeometryAttribute::GENERIC,
nullptr, 1,
143 draco::DT_FLOAT32,
false, DataTypeLength(draco::DT_FLOAT32), 0);
144 const int sfAttributeID = dracoCloud.AddAttribute(ga,
true, pointCount);
146 draco::PointAttribute* sfAttribute =
147 dracoCloud.attribute(sfAttributeID);
148 if (
nullptr != sfAttribute) {
149 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i) {
151 sfAttribute->SetAttributeValue(draco::AttributeValueIndex(i),
168 draco::GeometryAttribute ga;
169 ga.Init(draco::GeometryAttribute::GENERIC,
nullptr, 1, draco::DT_FLOAT32,
false, DataTypeLength(draco::DT_FLOAT32), 0);
170 const int sfAttributeID = dracoCloud.AddAttribute(ga,
true, pointCount);
172 draco::PointAttribute* sfAttribute = dracoCloud.attribute(sfAttributeID);
173 if (
nullptr != sfAttribute)
175 for (draco::PointIndex::ValueType i = 0; i < pointCount; ++i)
177 sfAttribute->SetAttributeValue(draco::AttributeValueIndex(i), &sf->
getValue(i));
193 draco::Mesh& dracoMesh) {
195 dracoMesh.SetNumFaces(faceCount);
198 draco::FaceIndex faceIndex(0);
199 for (
unsigned i = 0; i < faceCount; ++i) {
201 draco::Mesh::Face
face;
207 dracoMesh.SetFace(faceIndex,
face);
219 unsigned vertexCount = vertices->
size();
220 if (texCoords && texCoords->size() ==
ccMesh.
size() * 3) {
222 draco::GeometryAttribute ga;
223 ga.Init(draco::GeometryAttribute::TEX_COORD,
nullptr, 2,
224 draco::DT_FLOAT32,
false, DataTypeLength(draco::DT_FLOAT32) * 2,
226 const int texCoordAttributeID =
227 dracoMesh.AddAttribute(ga,
true, vertexCount);
229 draco::PointAttribute* texCoordAttribute =
230 dracoMesh.attribute(texCoordAttributeID);
231 if (
nullptr != texCoordAttribute) {
232 for (draco::PointIndex::ValueType i = 0; i < vertexCount; ++i) {
233 if (i < texCoords->
size()) {
234 texCoordAttribute->SetAttributeValue(
235 draco::AttributeValueIndex(i), texCoords->at(i).t);
240 texCoordAttribute->SetAttributeValue(
241 draco::AttributeValueIndex(i), coord);
261 if (
nullptr == entity) {
266 draco::Encoder encoder;
267 encoder.SetSpeedOptions(0, 0);
269 int coordQuantization = 11;
270 int texCoordQuantization = 10;
271 int normalQuantization = 8;
272 int sfQuantization = 8;
278 if (drcDialog.exec() == 0) {
283 coordQuantization = drcDialog.coordsQuantSpinBox->value();
286 normalQuantization = drcDialog.normQuantSpinBox->value();
287 sfQuantization = drcDialog.sfQuantSpinBox->value();
289 encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION,
291 encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD,
292 texCoordQuantization);
293 encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL,
295 encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC,
298 draco::EncoderBuffer buffer;
303 draco::Mesh dracoMesh;
309 if (!encoder.EncodeMeshToBuffer(dracoMesh, &buffer).ok()) {
323 if (!encoder.EncodePointCloudToBuffer(dracoCloud, &buffer).ok()) {
331 if (!file.open(QFile::WriteOnly)) {
334 file.write(buffer.data(),
static_cast<qint64
>(buffer.size()));
342 if (dracoCloud.num_points() == 0) {
346 unsigned pointCount = dracoCloud.num_points();
347 if (!ccCloud.
reserve(pointCount)) {
352 const draco::PointAttribute* pointAttribute =
353 dracoCloud.GetNamedAttribute(draco::GeometryAttribute::POSITION);
354 if (
nullptr == pointAttribute) {
357 if (pointCount != pointAttribute->size()) {
360 draco::DataType dt = pointAttribute->data_type();
361 if (dt == draco::DT_FLOAT32) {
362 for (draco::AttributeValueIndex i(0);
363 i < static_cast<uint32_t>(pointAttribute->size()); ++i) {
365 pointAttribute->GetValue(i, p.
u);
368 }
else if (dt == draco::DT_FLOAT64) {
370 bool preserveCoordinateShift =
true;
371 for (draco::AttributeValueIndex i(0);
372 i < static_cast<uint32_t>(pointAttribute->size()); ++i) {
374 pointAttribute->GetValue(i, P.
u);
379 P, Pshift, preserveCoordinateShift, parameters)) {
380 if (preserveCoordinateShift) {
384 "[DRACO] Cloud has been recentered! Translation: "
385 "(%.2f ; %.2f ; %.2f)",
386 Pshift.
x, Pshift.
y, Pshift.
z);
390 ccCloud.
addPoint((P + Pshift).toPC());
395 const draco::PointAttribute* normalAttribute =
396 dracoCloud.GetNamedAttribute(draco::GeometryAttribute::NORMAL);
397 if ((
nullptr != normalAttribute) &&
398 (normalAttribute->data_type() == draco::DataType::DT_FLOAT32) &&
399 (pointCount == normalAttribute->size())) {
401 for (draco::AttributeValueIndex i(0);
402 i < static_cast<uint32_t>(normalAttribute->size()); ++i) {
404 normalAttribute->GetValue(i, &n[0]);
414 const draco::PointAttribute* colorAttribute =
415 dracoCloud.GetNamedAttribute(draco::GeometryAttribute::COLOR);
416 if ((
nullptr != colorAttribute) &&
417 (colorAttribute->data_type() == draco::DataType::DT_UINT8) &&
418 (pointCount == colorAttribute->size())) {
419 bool rgb = (colorAttribute->num_components() == 3);
420 bool rgba = (colorAttribute->num_components() == 4);
424 std::array<uint8_t, 3> col;
425 for (draco::AttributeValueIndex i(0);
426 i < static_cast<uint32_t>(colorAttribute->size());
428 colorAttribute->GetValue(i, &col[0]);
432 std::array<uint8_t, 4> col;
433 for (draco::AttributeValueIndex i(0);
434 i < static_cast<uint32_t>(colorAttribute->size());
436 colorAttribute->GetValue(i, &col[0]);
449 const draco::PointAttribute* sfAttribute =
450 dracoCloud.GetNamedAttribute(draco::GeometryAttribute::GENERIC);
451 if ((
nullptr != sfAttribute) &&
452 (sfAttribute->data_type() == draco::DataType::DT_FLOAT32) &&
453 (sfAttribute->size() == pointCount)) {
456 for (draco::AttributeValueIndex i(0);
457 i < static_cast<uint32_t>(sfAttribute->size()); ++i) {
459 sfAttribute->GetValue(i, &sfValue);
467 CVLog::Warning(
"Failed to load generic field (not enough memory)");
477 draco::DecoderBuffer buffer;
480 if (!file.open(QFile::ReadOnly)) {
484 QByteArray byteArray = file.readAll();
485 buffer.Init(byteArray.data(), byteArray.size());
487 const auto result = draco::Decoder::GetEncodedGeometryType(&buffer);
492 const draco::EncodedGeometryType geomType =
result.value();
493 if (geomType == draco::TRIANGULAR_MESH) {
494 const auto resultMesh = draco::Decoder().DecodeMeshFromBuffer(&buffer);
495 if (!resultMesh.ok()) {
498 const std::unique_ptr<draco::Mesh>& meshDraco = resultMesh.value();
499 const draco::PointAttribute*
const pointAttribute =
500 meshDraco->GetNamedAttribute(
501 draco::GeometryAttribute::POSITION);
502 if (!pointAttribute) {
506 "[DRACO] Mesh size: " +
507 QString::number(meshDraco->num_faces()) +
508 " / vertex count: " + QString::number(meshDraco->num_points()));
512 LoadCloud(*vertices, *meshDraco, parameters);
515 return verticesError;
528 if (!meshCC->
reserve(meshDraco->num_faces())) {
534 for (draco::FaceIndex f(0); f < meshDraco->num_faces(); ++f) {
535 const draco::Mesh::Face&
face = meshDraco->face(f);
536 assert(
face.size() == 3);
537 uint32_t i1 = pointAttribute->mapped_index(
face[0]).value();
538 uint32_t i2 = pointAttribute->mapped_index(
face[1]).value();
539 uint32_t i3 = pointAttribute->mapped_index(
face[2]).value();
544 const draco::PointAttribute*
const coordAttribute =
545 meshDraco->GetNamedAttribute(
546 draco::GeometryAttribute::TEX_COORD);
548 std::size_t coord_size = meshCC->
size() * 3;
549 if (coordAttribute && coordAttribute->size() == vertices->
size()) {
554 "Not enough memory to load texture coordinates (they "
561 for (draco::AttributeValueIndex i(0);
562 i < static_cast<uint32_t>(coord_size); ++i) {
564 if (i < coordAttribute->
size()) {
565 coordAttribute->GetValue(i, T.
t);
578 texCoords->shrink_to_fit();
581 if (meshCC->
size() == 0) {
597 materials->push_back(material);
606 "[DRC] Texture coordinates were defined but no "
607 "material could be loaded!");
613 const auto resultCloud =
614 draco::Decoder().DecodePointCloudFromBuffer(&buffer);
615 if (!resultCloud.ok()) {
618 const std::unique_ptr<draco::PointCloud>& cloudDraco =
621 QString::number(cloudDraco->num_points()));
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
static CC_FILE_ERROR CCMeshToDraco(ccGenericMesh &ccMesh, draco::Mesh &dracoMesh)
static CC_FILE_ERROR LoadCloud(ccPointCloud &ccCloud, const draco::PointCloud &dracoCloud, FileIOFilter::LoadParameters ¶meters)
static CC_FILE_ERROR CCCloudToDraco(const ccGenericPointCloud &ccCloud, draco::PointCloud &dracoCloud)
CC_FILE_ERROR
Typical I/O filter errors.
@ CC_FERR_CANCELED_BY_USER
@ CC_FERR_THIRD_PARTY_LIB_FAILURE
@ CC_FERR_BAD_ENTITY_TYPE
@ CC_FERR_NOT_ENOUGH_MEMORY
virtual void link()
Increase counter.
virtual void release()
Decrease counter and deletes object when 0.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
CC_FILE_ERROR loadFile(const QString &filename, ccHObject &container, LoadParameters ¶meters) override
Loads one or more entities from a file.
CC_FILE_ERROR saveToFile(ccHObject *entity, const QString &filename, const SaveParameters ¶meters) override
Saves an entity (or a group of) to a file.
bool canSave(CV_CLASS_ENUM type, bool &multiple, bool &exclusive) const override
Returns whether this I/O filter can save the specified type of entity.
static bool HandleGlobalShift(const CCVector3d &P, CCVector3d &Pshift, bool &preserveCoordinateShift, LoadParameters &loadParameters, bool useInputCoordinatesShiftIfPossible=false)
Shortcut to the ecvGlobalShiftManager mechanism specific for files.
DRACO file (https://github.com/google/draco) saving dialog.
Array of 2D texture coordinates.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
bool reserveSafe(size_t count)
Reserves memory (no exception thrown)
void addElement(const Type &value)
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual void showNormals(bool state)
Sets normals visibility.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual bool hasScalarFields() const
Returns whether one or more scalar fields are instantiated.
void showNormals(bool state) override
Sets normals visibility.
virtual void showMaterials(bool state)
Sets whether textures should be displayed or not.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual const CCVector3 & getPointNormal(unsigned pointIndex) const =0
Returns normal corresponding to a given point.
virtual const ecvColor::Rgb & getPointColor(unsigned pointIndex) const =0
Returns color corresponding to a given point.
Hierarchical CLOUDVIEWER Object.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
Mesh (triangle) material.
Mesh (triangle) material.
QSharedPointer< ccMaterial > Shared
Shared type.
TextureCoordsContainer * getTexCoordinatesTable() const override
Returns per-triangle texture coordinates array.
cloudViewer::VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex) override
Returns the indexes of the vertices of a given triangle.
void setMaterialSet(ccMaterialSet *materialSet, bool autoReleaseOldMaterialSet=true)
Sets associated material set (may be shared)
bool reserve(std::size_t n)
Reserves the memory to store the vertex indexes (3 per triangle)
ccGenericPointCloud * getAssociatedCloud() const override
Returns the vertices cloud.
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
void setTexCoordinatesTable(TextureCoordsContainer *texCoordsTable, bool autoReleaseOldTable=true)
Sets per-triangle texture coordinates array (may be shared)
virtual unsigned size() const override
Returns the number of triangles.
void shrinkToFit()
Removes unused capacity.
bool isA(CV_CLASS_ENUM type) const
bool isKindOf(CV_CLASS_ENUM type) const
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool hasNormals() const override
Returns whether normals are enabled or not.
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
bool hasColors() const override
Returns whether colors are enabled or not.
void shrinkToFit()
Removes unused capacity.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
A scalar field associated to display-related parameters.
void computeMinAndMax() override
Determines the min and max values.
CCVector3d toGlobal3d(const Vector3Tpl< T > &Plocal) const
Returns the point back-projected into the original coordinates system.
bool isShifted() const
Returns whether the cloud is shifted or not.
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual unsigned size() const =0
Returns the number of points.
virtual ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
A simple scalar field (to be associated to a point cloud)
void addElement(ScalarType value)
ScalarType & getValue(std::size_t index)
const char * getName() const
Returns scalar field name.
bool reserveSafe(std::size_t count)
Reserves memory (no exception thrown)
std::vector< unsigned int > face
static void error(char *msg)
::ccPointCloud PointCloud
constexpr Rgbaf bright(1.00f, 1.00f, 1.00f, 1.00f)
constexpr Rgbaf darker(0.17f, 0.17f, 0.17f, 1.00f)
Generic loading parameters.
Generic saving parameters.
QWidget * parentWidget
Parent widget (if any)
bool alwaysDisplaySaveDialog