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
15namespace 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
for(;yybottom<=yytop;yybottom++)
Definition Grammar.cpp:705
if(!yyvaluep)
Definition Grammar.cpp:645
QColor green()
Definition StyleSheets.h:72
QColor red()
Definition StyleSheets.h:78
__attribute__((target("sse4.1"))) bool update(ElementType const &element)
__attribute__((target("default"))) bool update(ElementType const &element)