VisualizationPointCloud.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cfloat>
4 
5 #include <RobotAPI/interface/ArViz/Elements.h>
6 
7 #include "ElementVisualizer.h"
8 #include <Inventor/nodes/SoCoordinate3.h>
9 #include <Inventor/nodes/SoDrawStyle.h>
10 #include <Inventor/nodes/SoMaterial.h>
11 #include <Inventor/nodes/SoMaterialBinding.h>
12 #include <Inventor/nodes/SoPointSet.h>
13 #include <x86intrin.h>
14 
15 namespace armarx::viz::coin
16 {
18  {
19  using ElementType = data::ElementPointCloud;
20 
22  {
23  pclMat = new SoMaterial;
24 
25  SoMaterialBinding* pclMatBind = new SoMaterialBinding;
26  pclMatBind->value = SoMaterialBinding::PER_PART;
27 
28  pclCoords = new SoCoordinate3;
29  pclStyle = new SoDrawStyle;
30 
31  node->addChild(pclMat);
32  node->addChild(pclMatBind);
33  node->addChild(pclCoords);
34  node->addChild(pclStyle);
35  node->addChild(new SoPointSet);
36  }
37 
38  __attribute__((target("default"))) bool
39  update(ElementType const& element)
40  {
41  data::ColoredPoint const* pclData = (data::ColoredPoint const*)element.points.data();
42  int pclSize = element.points.size() / sizeof(data::ColoredPoint);
43 
44  int singleBufferSize = pclSize * 3;
45  buffer.resize(singleBufferSize * 2);
46 
47  const float conv = 1.0f / 255.0f;
48  float* coordsData = buffer.data();
49  float* colorsData = buffer.data() + singleBufferSize;
50 
51  for (int i = 0; i < pclSize; ++i)
52  {
53  data::ColoredPoint point = pclData[i];
54  colorsData[i * 3 + 0] = point.color.r * conv;
55  colorsData[i * 3 + 1] = point.color.g * conv;
56  colorsData[i * 3 + 2] = point.color.b * conv;
57 
58  coordsData[i * 3 + 0] = point.x;
59  coordsData[i * 3 + 1] = point.y;
60  coordsData[i * 3 + 2] = point.z;
61  }
62 
63  pclMat->diffuseColor.setValuesPointer(pclSize, colorsData);
64  pclMat->ambientColor.setValuesPointer(pclSize, colorsData);
65  pclMat->transparency = element.transparency;
66 
67  pclCoords->point.setValuesPointer(pclSize, coordsData);
68 
69  pclStyle->pointSize = element.pointSizeInPixels;
70 
71  return true;
72  }
73 
74  __attribute__((target("sse4.1"))) bool
75  update(ElementType const& element)
76  {
77  float* pclIn = (float*)element.points.data();
78  int pclSize = element.points.size() / sizeof(data::ColoredPoint);
79 
80  // Enlarge and align the buffers
81  int singleBufferSize = (pclSize + 3) * 3;
82  if (singleBufferSize % 16 != 0)
83  {
84  singleBufferSize += 16 - singleBufferSize % 16;
85  }
86  buffer.resize(singleBufferSize * 2);
87 
88  float* positionsData = buffer.data();
89  float* colorsData = buffer.data() + singleBufferSize;
90 
91  float* colorsOut = colorsData;
92  float* positionsOut = positionsData;
93 
94  __m128 convColor = _mm_set1_ps(1.0f / 255.0f);
95  __m128i offsetBase = _mm_set_epi32(12, 8, 4, 0);
96  __m128i offsetIncrement = _mm_set1_epi32(16);
97  __m128i maxOffset = _mm_set1_epi32(4 * (pclSize - 1));
98  __m128 floatMax = _mm_set1_ps(FLT_MAX);
99 
100 
101  // std::uint64_t timerStart = __rdtsc();
102  // Work on four points at a time
103  for (int i = 0; i < pclSize; i += 4)
104  {
105  // Ensure that the offsets do not exceed the input size
106  __m128i offsets = _mm_min_epi32(offsetBase, maxOffset);
107 
108  // Load four colored point
109  // Memory layout of a colored point: c z y x
110  __m128 cp0 = _mm_loadu_ps(pclIn + _mm_extract_epi32(offsets, 0));
111  __m128 cp1 = _mm_loadu_ps(pclIn + _mm_extract_epi32(offsets, 1));
112  __m128 cp2 = _mm_loadu_ps(pclIn + _mm_extract_epi32(offsets, 2));
113  __m128 cp3 = _mm_loadu_ps(pclIn + _mm_extract_epi32(offsets, 3));
114 
115  // Shift the colored point data, so that we can blend them together
116  // 0 -> x, 1 -> y, 2 -> z, 3 -> c
117  // shiftedP0: c z y x
118  //__m128i shiftedP0 = _mm_shuffle_epi32((__m128i)cp0, _MM_SHUFFLE(3, 2, 1, 0));
119  __m128i shiftedP0 = (__m128i)cp0;
120  // shiftedP1: x c z y
121  __m128i shiftedP1 = _mm_shuffle_epi32((__m128i)cp1, _MM_SHUFFLE(0, 3, 2, 1));
122  // shiftedP2: y x c z
123  __m128i shiftedP2 = _mm_shuffle_epi32((__m128i)cp2, _MM_SHUFFLE(1, 0, 3, 2));
124  // shiftedP3: z y x c
125  __m128i shiftedP3 = _mm_shuffle_epi32((__m128i)cp3, _MM_SHUFFLE(2, 1, 0, 3));
126 
127  // Blend together entries from two colored points to gather the packed position data
128  // [x] (P1) [z y x] (P0) ==> 1000 = 8
129  __m128 p0 = _mm_blend_ps((__m128)shiftedP0, (__m128)shiftedP1, 8);
130  // [y x] (P2) [z y] (P1) ==> 1100 = 12
131  __m128 p1 = _mm_blend_ps((__m128)shiftedP1, (__m128)shiftedP2, 12);
132  // [z y x] (P3) [z] (P2) ==> 1110 = 14
133  __m128 p2 = _mm_blend_ps((__m128)shiftedP2, (__m128)shiftedP3, 14);
134 
135  // Replace NaNs with zeros
136  p0 = _mm_and_ps(p0, _mm_cmplt_ps(p0, floatMax));
137  p1 = _mm_and_ps(p1, _mm_cmplt_ps(p1, floatMax));
138  p2 = _mm_and_ps(p2, _mm_cmplt_ps(p2, floatMax));
139 
140  // Store the position data (3 registers, 4 position values)
141  _mm_storeu_ps(positionsOut + 0, p0);
142  _mm_storeu_ps(positionsOut + 4, p1);
143  _mm_storeu_ps(positionsOut + 8, p2);
144 
145  // Blend together the entries from all four colored points to gather packed color data
146  // [c] (P0) [c z y] (P1) ==> 0111 ==> 7
147  __m128 c01 = _mm_blend_ps((__m128)shiftedP0, (__m128)shiftedP1, 7);
148  // [y x c] (P2) [c] (P3) ==> 0001 ==> 1
149  __m128 c23 = _mm_blend_ps((__m128)shiftedP2, (__m128)shiftedP3, 1);
150  // [c c] (c01) [c c] (c23) ==> 0011 ==> 3
151  __m128i c0123 = _mm_castps_si128(_mm_blend_ps(c01, c23, 3));
152 
153  // Extract the color channels from the packed color data
154  // c = b g r a (8-bit each)
155  // Range [0, 255]
156  __m128i redI = _mm_and_si128(_mm_bsrli_si128(c0123, 1), _mm_set1_epi32(0xFF));
157  __m128i greenI = _mm_and_si128(_mm_bsrli_si128(c0123, 2), _mm_set1_epi32(0xFF));
158  __m128i blueI = _mm_and_si128(_mm_bsrli_si128(c0123, 3), _mm_set1_epi32(0xFF));
159 
160  // Convert the integer color channels to float channels
161  // Range [0.0, 1.0]
162  __m128 red = _mm_mul_ps(_mm_cvtepi32_ps(redI), convColor);
163  __m128 green = _mm_mul_ps(_mm_cvtepi32_ps(greenI), convColor);
164  __m128 blue = _mm_mul_ps(_mm_cvtepi32_ps(blueI), convColor);
165 
166  // Construct the output memory order (4 color values in 3 registers)
167  // [r g b] [r
168  // g b] [r g
169  // b] [r g b]
170  __m128 c0 = _mm_setr_ps(red[3], green[3], blue[3], red[2]);
171  __m128 c1 = _mm_setr_ps(green[2], blue[2], red[1], green[1]);
172  __m128 c2 = _mm_setr_ps(blue[1], red[0], green[0], blue[0]);
173 
174  // Store the color data (3 registers, 4 color values)
175  _mm_storeu_ps(colorsOut + 0, c0);
176  _mm_storeu_ps(colorsOut + 4, c1);
177  _mm_storeu_ps(colorsOut + 8, c2);
178 
179  // Advance the output pointers by 4 values (3 floats per position/color)
180  colorsOut += 12;
181  positionsOut += 12;
182 
183  // Move the input offsets to the next 4 colored points
184  offsetBase = _mm_add_epi32(offsetBase, offsetIncrement);
185  }
186  // std::uint64_t timerEnd = __rdtsc();
187  // int timerDiff = (int)(timerEnd - timerStart);
188  // float ticksPerPoint = (float)timerDiff / pclSize;
189  // printf("%c[2KUpdate Time %d\tT/Point %g\n", 27, timerDiff, ticksPerPoint);
190 
191  pclMat->diffuseColor.setValuesPointer(pclSize, colorsData);
192  pclMat->ambientColor.setValuesPointer(pclSize, colorsData);
193  pclMat->transparency = element.transparency;
194 
195  pclCoords->point.setValuesPointer(pclSize, positionsData);
196 
197  pclStyle->pointSize = element.pointSizeInPixels;
198 
199  return true;
200  }
201 
202  SoMaterial* pclMat;
203  SoCoordinate3* pclCoords;
204  SoDrawStyle* pclStyle;
205 
206  std::vector<SbColor> colors;
207  std::vector<SbVec3f> coords;
208 
209  std::vector<float> buffer;
210  };
211 } // namespace armarx::viz::coin
ElementVisualizer.h
armarx::viz::coin::TypedElementVisualization
Definition: ElementVisualizer.h:52
armarx::viz::coin::VisualizationPointCloud
Definition: VisualizationPointCloud.h:17
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
armarx::viz::coin::VisualizationPointCloud::colors
std::vector< SbColor > colors
Definition: VisualizationPointCloud.h:206
armarx::viz::coin::VisualizationPointCloud::pclMat
SoMaterial * pclMat
Definition: VisualizationPointCloud.h:202
armarx::viz::coin::VisualizationPointCloud::__attribute__
__attribute__((target("sse4.1"))) bool update(ElementType const &element)
Definition: VisualizationPointCloud.h:74
armarx::viz::coin::VisualizationPointCloud::pclStyle
SoDrawStyle * pclStyle
Definition: VisualizationPointCloud.h:204
armarx::viz::coin::VisualizationPointCloud::ElementType
data::ElementPointCloud ElementType
Definition: VisualizationPointCloud.h:19
armarx::viz::coin::TypedElementVisualization< SoSeparator >::node
NodeType * node
Definition: ElementVisualizer.h:67
armarx::viz::coin::VisualizationPointCloud::buffer
std::vector< float > buffer
Definition: VisualizationPointCloud.h:209
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
armarx::red
QColor red()
Definition: StyleSheets.h:78
armarx::viz::coin::VisualizationPointCloud::pclCoords
SoCoordinate3 * pclCoords
Definition: VisualizationPointCloud.h:203
armarx::viz::coin
Definition: ElementVisualizer.cpp:11
armarx::viz::coin::VisualizationPointCloud::VisualizationPointCloud
VisualizationPointCloud()
Definition: VisualizationPointCloud.h:21
armarx::viz::coin::VisualizationPointCloud::coords
std::vector< SbVec3f > coords
Definition: VisualizationPointCloud.h:207
armarx::viz::coin::VisualizationPointCloud::__attribute__
__attribute__((target("default"))) bool update(ElementType const &element)
Definition: VisualizationPointCloud.h:38
armarx::green
QColor green()
Definition: StyleSheets.h:72