DracoDecoder.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2018 Uni Osnabrück
2  * This file is part of the LAS VEGAS Reconstruction Toolkit,
3  *
4  * LAS VEGAS is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * LAS VEGAS is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17  */
18 
30 #include "lvr2/io/DracoDecoder.hpp"
31 #include <draco/metadata/geometry_metadata.h>
32 
33 namespace lvr2
34 {
35 
48 template <typename LvrArrType, typename DataType, int numComponents>
49 LvrArrType loadAttributeFromDraco(const draco::PointAttribute* attribute)
50 {
51  if (!attribute)
52  {
53  throw std::invalid_argument("attribute is not existing");
54  }
55 
56  LvrArrType data(new DataType[attribute->size() * numComponents]);
57 
58  std::array<DataType, numComponents> tmp;
59  for (draco::AttributeValueIndex i(0); i < attribute->size(); ++i)
60  {
61  if (!attribute->ConvertValue<DataType, numComponents>(i, &tmp[0]))
62  {
63  throw std::invalid_argument("attribute seems to have an incorrect structur");
64  }
65 
66  for (int j = 0; j < numComponents; j++)
67  {
68  data[i.value() * numComponents + j] = tmp[j];
69  }
70  }
71 
72  return data;
73 }
74 
82 void createTextures(std::vector<int32_t>& drcTextures, std::vector<GlTexture*>& lvrTextures)
83 {
84  unsigned long size = drcTextures.size();
85  unsigned long index = 0;
86 
87  while (index < size)
88  {
89  // set texture attributes
90  int id = drcTextures[index++];
91  int height = drcTextures[index++];
92  int width = drcTextures[index++];
93 
94  int pixelDat = height * width * 3;
95  unsigned char* pixel = new unsigned char[pixelDat];
96 
97  // create pixel array
98  for (int i = 0; i < pixelDat; ++i)
99  {
100  pixel[i] = (unsigned char)drcTextures[index++];
101  }
102 
103  GlTexture* glTexture = new GlTexture(pixel, width, height);
104  glTexture->m_texIndex = (GLuint)id;
105  lvrTextures.push_back(glTexture);
106  }
107 }
108 
116 void createTextures(std::vector<int32_t>& drcTextures, std::vector<Texture>& lvrTextures)
117 {
118  unsigned long size = drcTextures.size();
119  unsigned long index = 0;
120 
121  while (index < size)
122  {
123  // set texture attributes
124  int id = drcTextures[index++];
125  int height = drcTextures[index++];
126  int width = drcTextures[index++];
127 
128  int pixelDat = height * width * 3;
129  unsigned char* pixel = new unsigned char[pixelDat];
130 
131  // create pixel array
132  for (int i = 0; i < pixelDat; ++i)
133  {
134  pixel[i] = (unsigned char)drcTextures[index++];
135  }
136 
137  Texture texture(id, width, height, 3, 1, 1, pixel);
138  lvrTextures.push_back(texture);
139  }
140 }
141 
153 const draco::PointAttribute* getDracoAttributeByAttributeMetadata(draco::PointCloud* geometry,
154  std::string key,
155  std::string value)
156 {
157  if (!geometry->GetMetadata())
158  {
159  return nullptr;
160  }
161 
162  const draco::AttributeMetadata* attributeMeta =
163  geometry->GetMetadata()->GetAttributeMetadataByStringEntry(key, value);
164 
165  if (!attributeMeta)
166  {
167  return nullptr;
168  }
169 
170  return geometry->GetAttributeByUniqueId(attributeMeta->att_unique_id());
171 }
172 
180 ModelPtr readPointCloud(draco::DecoderBuffer& buffer, draco::Decoder& decoder)
181 {
182  auto status = decoder.DecodePointCloudFromBuffer(&buffer);
183 
184  if (!status.ok())
185  {
186  std::cerr << "An error occurred while decoding file:"
187  << " " << status.status() << std::endl;
188  return ModelPtr(new Model());
189  }
190 
191  ModelPtr modelPtr(new Model(PointBufferPtr(new PointBuffer)));
192 
193  std::unique_ptr<draco::PointCloud> dracoPointCloud = std::move(status).value();
194 
195  // get coordinates
196  try
197  {
198  const draco::PointAttribute* attribute =
199  dracoPointCloud->GetNamedAttribute(draco::GeometryAttribute::POSITION);
200  floatArr data = loadAttributeFromDraco<floatArr, float, 3>(attribute);
201  modelPtr->m_pointCloud->setPointArray(data, attribute->size());
202  }
203  catch (const std::invalid_argument& ia)
204  {
205  // no points, no pointcloud
206  std::cerr << "Error loading positions: " << ia.what() << std::endl;
207  return ModelPtr(new Model());
208  }
209 
210  // get normals
211  try
212  {
213  const draco::PointAttribute* attribute =
214  dracoPointCloud->GetNamedAttribute(draco::GeometryAttribute::NORMAL);
215  floatArr data = loadAttributeFromDraco<floatArr, float, 3>(attribute);
216  modelPtr->m_pointCloud->setNormalArray(data, attribute->size());
217  }
218  catch (const std::invalid_argument& ia)
219  {
220  }
221 
222  // get colors
223  try
224  {
225  const draco::PointAttribute* attribute =
226  dracoPointCloud->GetNamedAttribute(draco::GeometryAttribute::COLOR);
227  ucharArr data = loadAttributeFromDraco<ucharArr, unsigned char, 3>(attribute);
228  modelPtr->m_pointCloud->setColorArray(data, attribute->size());
229  }
230  catch (const std::invalid_argument& ia)
231  {
232  }
233 
234  // // get confidences
235  // try
236  // {
237  // const draco::PointAttribute* attribute =
238  // getDracoAttributeByAttributeMetadata(dracoPointCloud.get(), "name", "confidence");
239  // floatArr data = loadAttributeFromDraco<floatArr, float, 1>(attribute);
240  // modelPtr->m_pointCloud->setPointConfidenceArray(data, attribute->size());
241  // }
242  // catch (const std::invalid_argument& ia)
243  // {
244  // }
245 
246  // // get intensities
247  // try
248  // {
249  // const draco::PointAttribute* attribute =
250  // getDracoAttributeByAttributeMetadata(dracoPointCloud.get(), "name", "intensity");
251  // floatArr data = loadAttributeFromDraco<floatArr, float, 1>(attribute);
252  // modelPtr->m_pointCloud->setPointIntensityArray(data, attribute->size());
253  // }
254  // catch (const std::invalid_argument& ia)
255  // {
256  // }
257 
258  return modelPtr;
259 }
260 
268 ModelPtr readMesh(draco::DecoderBuffer& buffer, draco::Decoder& decoder)
269 {
270  auto status = decoder.DecodeMeshFromBuffer(&buffer);
271 
272  if (!status.ok())
273  {
274  std::cerr << "An error occurred while decoding file:"
275  << " " << status.status() << std::endl;
276  return ModelPtr(new Model());
277  }
278 
279  ModelPtr modelPtr(new Model(MeshBufferPtr(new MeshBuffer)));
280 
281  std::unique_ptr<draco::Mesh> dracoMesh = std::move(status).value();
282 
283  auto metadata = dracoMesh->GetMetadata();
284 
285  // get textures
286  if (metadata)
287  {
288  std::vector<int32_t> texture;
289 
290  if (metadata->GetEntryIntArray("texture", &texture))
291  {
292  std::vector<Texture> textures;
293 
294  createTextures(texture, textures);
295 
296  modelPtr->m_mesh->setTextures(textures);
297  }
298  }
299 
300  // get materials
301  if (metadata)
302  {
303  std::vector<int32_t> dat;
304 
305  if (metadata->GetEntryIntArray("material", &dat))
306  {
307  vector<Material> materials;
308  for (int i = 0; i < dat.size() / 4; i++)
309  {
310  Material m;
311  Rgb8Color rgb;
312  rgb[0] = static_cast<unsigned char>(dat[4 * i + 0]);
313  rgb[0] = static_cast<unsigned char>(dat[4 * i + 1]);
314  rgb[0] = static_cast<unsigned char>(dat[4 * i + 2]);
315 
316  TextureHandle h(dat[4 * i + 3]);
317 
318  m.m_texture = h;
319  m.m_color = rgb;
320 
321  materials.push_back(m);
322  }
323 
324  modelPtr->m_mesh->setMaterials(materials);
325  }
326  }
327 
328  // get coordinates
329  try
330  {
331  const draco::PointAttribute* attribute =
332  dracoMesh->GetNamedAttribute(draco::GeometryAttribute::POSITION);
333  floatArr data = loadAttributeFromDraco<floatArr, float, 3>(attribute);
334  modelPtr->m_mesh->setVertices(data, attribute->size());
335  }
336  catch (const std::invalid_argument& ia)
337  {
338  // no vertices, no mesh
339  std::cerr << "Error loading positions: " << ia.what() << std::endl;
340  return ModelPtr(new Model());
341  }
342 
343  // get normals
344  try
345  {
346  const draco::PointAttribute* attribute =
347  dracoMesh->GetNamedAttribute(draco::GeometryAttribute::NORMAL);
348  floatArr data = loadAttributeFromDraco<floatArr, float, 3>(attribute);
349  modelPtr->m_mesh->setVertexNormals(data);
350  }
351  catch (const std::invalid_argument& ia)
352  {
353  }
354 
355  // get colors
356  try
357  {
358  const draco::PointAttribute* attribute =
359  dracoMesh->GetNamedAttribute(draco::GeometryAttribute::COLOR);
360  ucharArr data = loadAttributeFromDraco<ucharArr, unsigned char, 3>(attribute);
361  modelPtr->m_mesh->setVertexColors(data);
362  }
363  catch (const std::invalid_argument& ia)
364  {
365  }
366 
367  // // get confidences
368  // try
369  // {
370  // const draco::PointAttribute* attribute =
371  // getDracoAttributeByAttributeMetadata(dracoMesh.get(), "name", "confidence");
372  // floatArr data = loadAttributeFromDraco<floatArr, float, 1>(attribute);
373  // modelPtr->m_mesh->setVertexConfidenceArray(data, attribute->size());
374  // }
375  // catch (const std::invalid_argument& ia)
376  // {
377  // }
378 
379  // // get intensities
380  // try
381  // {
382  // const draco::PointAttribute* attribute =
383  // getDracoAttributeByAttributeMetadata(dracoMesh.get(), "name", "intensity");
384  // floatArr data = loadAttributeFromDraco<floatArr, float, 1>(attribute);
385  // modelPtr->m_mesh->setVertexIntensityArray(data, attribute->size());
386  // }
387  // catch (const std::invalid_argument& ia)
388  // {
389  // }
390 
391  // get texture coordinates
392  try
393  {
394  const draco::PointAttribute* attribute =
395  dracoMesh->GetNamedAttribute(draco::GeometryAttribute::TEX_COORD);
396  floatArr data = loadAttributeFromDraco<floatArr, float, 3>(attribute);
397  modelPtr->m_mesh->setTextureCoordinates(data);
398  }
399  catch (const std::invalid_argument& ia)
400  {
401  }
402 
403  // get materialindices
404  const draco::PointAttribute* matIndexAttribute =
405  getDracoAttributeByAttributeMetadata(dracoMesh.get(), "name", "materialindex");
406  if (matIndexAttribute)
407  {
408  indexArray data(new uint32_t[dracoMesh->num_faces()]);
409 
410  uint32_t tmp;
411  for (draco::FaceIndex i(0); i < dracoMesh->num_faces(); i++)
412  {
413  if (!matIndexAttribute->ConvertValue<uint32_t, 1>(
414  matIndexAttribute->mapped_index(dracoMesh->face(i)[0]), &tmp))
415  {
416  data = uintArr(new uint32_t[dracoMesh->num_faces()]);
417  break;
418  }
419 
420  data[i.value()] = tmp;
421  }
422 
423  modelPtr->m_mesh->setFaceMaterialIndices(data);
424  }
425 
426  // get faces
427  const draco::PointAttribute* faceAttribute =
428  dracoMesh->GetNamedAttribute(draco::GeometryAttribute::Type::POSITION);
429  uintArr faceArr(new unsigned int[dracoMesh->num_faces() * 3]);
430  for (draco::FaceIndex i(0); i < dracoMesh->num_faces(); ++i)
431  {
432  faceArr[i.value() * 3 + 0] = faceAttribute->mapped_index(dracoMesh->face(i)[0]).value();
433  faceArr[i.value() * 3 + 1] = faceAttribute->mapped_index(dracoMesh->face(i)[1]).value();
434  faceArr[i.value() * 3 + 2] = faceAttribute->mapped_index(dracoMesh->face(i)[2]).value();
435  }
436  modelPtr->m_mesh->setFaceIndices(faceArr, dracoMesh->num_faces());
437 
438  return modelPtr;
439 }
440 
441 ModelPtr decodeDraco(draco::DecoderBuffer& buffer, draco::EncodedGeometryType type)
442 {
443  draco::Decoder decoder;
444 
445  if (type == draco::TRIANGULAR_MESH)
446  {
447  return readMesh(buffer, decoder);
448  }
449  else if (type == draco::POINT_CLOUD)
450  {
451  return readPointCloud(buffer, decoder);
452  }
453 
454  return ModelPtr(new Model());
455 }
456 
457 } // namespace lvr
lvr2::floatArr
boost::shared_array< float > floatArr
Definition: DataStruct.hpp:133
lvr2::GlTexture
Definition: GlTexture.hpp:56
SingleArray
Definition: data_types.h:107
lvr2::indexArray
boost::shared_array< unsigned int > indexArray
Definition: DataStruct.hpp:128
DracoDecoder.hpp
Decodes a draco comptressed file into a lvr model.
lvr2::GlTexture::m_texIndex
GLuint m_texIndex
The texture index of the texture.
Definition: GlTexture.hpp:112
lvr2::loadAttributeFromDraco
LvrArrType loadAttributeFromDraco(const draco::PointAttribute *attribute)
loads any GeometryAttribute from draco pointcloud and returns its values
Definition: DracoDecoder.cpp:49
lvr2::PointBufferPtr
std::shared_ptr< PointBuffer > PointBufferPtr
Definition: PointBuffer.hpp:130
lvr2::createTextures
void createTextures(std::vector< int32_t > &drcTextures, std::vector< GlTexture * > &lvrTextures)
transforms the int32_t vector with texture data into actual GlTextures
Definition: DracoDecoder.cpp:82
lvr2::PointBuffer
A class to handle point information with an arbitrarily large number of attribute channels....
Definition: PointBuffer.hpp:51
lvr2::Model
Definition: Model.hpp:51
lvr2::Rgb8Color
std::array< uint8_t, 3 > Rgb8Color
Definition: ColorAlgorithms.hpp:54
lvr2::MeshBuffer
The MeshBuffer Mesh representation for I/O modules.
Definition: MeshBuffer.hpp:41
lvr2::decodeDraco
ModelPtr decodeDraco(draco::DecoderBuffer &buffer, draco::EncodedGeometryType type)
delivers ModelPtr from draco DecoderBuffer
Definition: DracoDecoder.cpp:441
lvr2::readPointCloud
ModelPtr readPointCloud(draco::DecoderBuffer &buffer, draco::Decoder &decoder)
loads a pointcloud from the decoderBuffer and converts it into the lvr structure
Definition: DracoDecoder.cpp:180
lvr2::Material
A material that stores information about color and texture of a cluster.
Definition: Material.hpp:42
lvr2::ucharArr
boost::shared_array< unsigned char > ucharArr
Definition: DataStruct.hpp:137
lvr2::readMesh
ModelPtr readMesh(draco::DecoderBuffer &buffer, draco::Decoder &decoder)
loads a mesh from the decoderBuffer and converts it into the lvr structure
Definition: DracoDecoder.cpp:268
lvr2
Definition: BaseBufferManipulators.hpp:39
lvr2::ModelPtr
std::shared_ptr< Model > ModelPtr
Definition: Model.hpp:80
lvr2::MeshBufferPtr
std::shared_ptr< MeshBuffer > MeshBufferPtr
Definition: MeshBuffer.hpp:217
lvr2::getDracoAttributeByAttributeMetadata
const draco::PointAttribute * getDracoAttributeByAttributeMetadata(draco::PointCloud *geometry, std::string key, std::string value)
delivers PointAttribute by searching for given Attribute Metadata Entries
Definition: DracoDecoder.cpp:153
lvr2::Texture
This class represents a texture.
Definition: Texture.hpp:54
lvr2::TextureHandle
Handle to access textures of the mesh.
Definition: Handles.hpp:158
lvr2::Material::m_texture
boost::optional< TextureHandle > m_texture
Optional texture handle.
Definition: Material.hpp:45
lvr2::Material::m_color
boost::optional< Rgb8Color > m_color
Optional color.
Definition: Material.hpp:47
lvr2::uintArr
boost::shared_array< unsigned int > uintArr
Definition: DataStruct.hpp:130


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Wed Mar 2 2022 00:37:23