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