Skip to content

Commit 13cb609

Browse files
committed
PointCloud refactor
The point here is to hide the actual structure of the point cloud data, specifically PointData and the std::vector<PointData>. The data can be accessed with an AttribData API and a raw void* ptr. This allows us to load the raw data directly into an OpenGL buffer, and contains the data we need to create interleaved vertex attributes into that buffer, while still allowing us to iterate over each element, if necessary, using ForEachAttrib(). In the case of PointCloud this is probably overkill, but I want to use this same API for GaussianCloud in the future. Because GaussianCloud can optionally have some or all spherical harmonic coefficients, we don't know the data layout at compile time. This AttribData API gives us the ability to only include what we need at run-time.
1 parent a325912 commit 13cb609

File tree

3 files changed

+101
-53
lines changed

3 files changed

+101
-53
lines changed

src/pointcloud.cpp

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,16 @@
1515
#include "core/util.h"
1616
#include "ply.h"
1717

18+
struct PointData
19+
{
20+
PointData() noexcept {}
21+
float position[4];
22+
float color[4];
23+
};
24+
1825
PointCloud::PointCloud(bool useLinearColorsIn) :
26+
numPoints(0),
27+
pointSize(0),
1928
useLinearColors(useLinearColorsIn)
2029
{
2130
;
@@ -59,55 +68,62 @@ bool PointCloud::ImportPly(const std::string& plyFilename)
5968
Log::E("Error parsing ply file \"%s\", missing color property\n", plyFilename.c_str());
6069
}
6170

62-
pointDataVec.resize(ply.GetVertexCount());
71+
numPoints = ply.GetVertexCount();
72+
pointSize = sizeof(PointData);
73+
PointData* pointDataPtr = new PointData[numPoints];
74+
data.reset(pointDataPtr);
75+
76+
// GL_FLOAT = 0x1406
77+
positionAttrib = {4, 0x1406, (int)pointSize, offsetof(PointData, position)};
78+
colorAttrib = {4, 0x1406, (int)pointSize, offsetof(PointData, color)};
6379

6480
if (useDoubles)
6581
{
6682
int i = 0;
67-
ply.ForEachVertex([this, &i, &props](const uint8_t* data, size_t size)
83+
ply.ForEachVertex([this, pointDataPtr, &i, &props](const uint8_t* data, size_t size)
6884
{
6985
if (useLinearColors)
7086
{
71-
pointDataVec[i].position[0] = SRGBToLinear((float)props.x.Get<double>(data));
72-
pointDataVec[i].position[1] = SRGBToLinear((float)props.y.Get<double>(data));
73-
pointDataVec[i].position[2] = SRGBToLinear((float)props.z.Get<double>(data));
87+
pointDataPtr[i].position[0] = SRGBToLinear((float)props.x.Get<double>(data));
88+
pointDataPtr[i].position[1] = SRGBToLinear((float)props.y.Get<double>(data));
89+
pointDataPtr[i].position[2] = SRGBToLinear((float)props.z.Get<double>(data));
7490
}
7591
else
7692
{
77-
pointDataVec[i].position[0] = (float)props.x.Get<double>(data);
78-
pointDataVec[i].position[1] = (float)props.y.Get<double>(data);
79-
pointDataVec[i].position[2] = (float)props.z.Get<double>(data);
93+
pointDataPtr[i].position[0] = (float)props.x.Get<double>(data);
94+
pointDataPtr[i].position[1] = (float)props.y.Get<double>(data);
95+
pointDataPtr[i].position[2] = (float)props.z.Get<double>(data);
8096
}
81-
pointDataVec[i].position[3] = 1.0f;
82-
pointDataVec[i].color[0] = (float)props.red.Get<uint8_t>(data) / 255.0f;
83-
pointDataVec[i].color[1] = (float)props.green.Get<uint8_t>(data) / 255.0f;
84-
pointDataVec[i].color[2] = (float)props.blue.Get<uint8_t>(data) / 255.0f;
85-
pointDataVec[i].color[3] = 1.0f;
97+
pointDataPtr[i].position[3] = 1.0f;
98+
pointDataPtr[i].color[0] = (float)props.red.Get<uint8_t>(data) / 255.0f;
99+
pointDataPtr[i].color[1] = (float)props.green.Get<uint8_t>(data) / 255.0f;
100+
pointDataPtr[i].color[2] = (float)props.blue.Get<uint8_t>(data) / 255.0f;
101+
pointDataPtr[i].color[3] = 1.0f;
86102
i++;
87103
});
88104
}
89105
else
90106
{
91107
int i = 0;
92-
ply.ForEachVertex([this, &i, &props](const uint8_t* data, size_t size)
108+
ply.ForEachVertex([this, pointDataPtr, &i, &props](const uint8_t* data, size_t size)
93109
{
94110
if (useLinearColors)
95111
{
96-
pointDataVec[i].position[0] = SRGBToLinear(props.x.Get<float>(data));
97-
pointDataVec[i].position[1] = SRGBToLinear(props.y.Get<float>(data));
98-
pointDataVec[i].position[2] = SRGBToLinear(props.z.Get<float>(data));
112+
pointDataPtr[i].position[0] = SRGBToLinear(props.x.Get<float>(data));
113+
pointDataPtr[i].position[1] = SRGBToLinear(props.y.Get<float>(data));
114+
pointDataPtr[i].position[2] = SRGBToLinear(props.z.Get<float>(data));
99115
}
100116
else
101117
{
102-
pointDataVec[i].position[0] = props.x.Get<float>(data);
103-
pointDataVec[i].position[1] = props.y.Get<float>(data);
104-
pointDataVec[i].position[2] = props.z.Get<float>(data);
118+
pointDataPtr[i].position[0] = props.x.Get<float>(data);
119+
pointDataPtr[i].position[1] = props.y.Get<float>(data);
120+
pointDataPtr[i].position[2] = props.z.Get<float>(data);
105121
}
106-
pointDataVec[i].position[3] = 1.0f;
107-
pointDataVec[i].color[0] = (float)props.red.Get<uint8_t>(data) / 255.0f;
108-
pointDataVec[i].color[1] = (float)props.green.Get<uint8_t>(data) / 255.0f;
109-
pointDataVec[i].color[2] = (float)props.blue.Get<uint8_t>(data) / 255.0f;
110-
pointDataVec[i].color[2] = 1.0f;
122+
pointDataPtr[i].position[3] = 1.0f;
123+
pointDataPtr[i].color[0] = (float)props.red.Get<uint8_t>(data) / 255.0f;
124+
pointDataPtr[i].color[1] = (float)props.green.Get<uint8_t>(data) / 255.0f;
125+
pointDataPtr[i].color[2] = (float)props.blue.Get<uint8_t>(data) / 255.0f;
126+
pointDataPtr[i].color[3] = 1.0f;
111127
i++;
112128
});
113129
}
@@ -130,7 +146,7 @@ bool PointCloud::ExportPly(const std::string& plyFilename) const
130146
// ply files have unix line endings.
131147
plyFile << "ply\n";
132148
plyFile << "format binary_little_endian 1.0\n";
133-
plyFile << "element vertex " << pointDataVec.size() << "\n";
149+
plyFile << "element vertex " << numPoints << "\n";
134150
plyFile << "property float x\n";
135151
plyFile << "property float y\n";
136152
plyFile << "property float z\n";
@@ -155,19 +171,22 @@ bool PointCloud::ExportPly(const std::string& plyFilename) const
155171

156172
void PointCloud::InitDebugCloud()
157173
{
158-
pointDataVec.clear();
174+
const int NUM_POINTS = 5;
175+
176+
numPoints = NUM_POINTS * 3;
177+
pointSize = sizeof(PointData);
178+
PointData* pointDataPtr = new PointData[numPoints];
179+
data.reset(pointDataPtr);
159180

160181
//
161182
// make an debug pointVec, that contains three lines one for each axis.
162183
//
163184
const float AXIS_LENGTH = 1.0f;
164-
const int NUM_POINTS = 5;
165185
const float DELTA = (AXIS_LENGTH / (float)NUM_POINTS);
166-
pointDataVec.resize(NUM_POINTS * 3);
167186
// x axis
168187
for (int i = 0; i < NUM_POINTS; i++)
169188
{
170-
PointCloud::PointData& p = pointDataVec[i];
189+
PointData& p = pointDataPtr[i];
171190
p.position[0] = i * DELTA;
172191
p.position[1] = 0.0f;
173192
p.position[2] = 0.0f;
@@ -180,7 +199,7 @@ void PointCloud::InitDebugCloud()
180199
// y axis
181200
for (int i = 0; i < NUM_POINTS; i++)
182201
{
183-
PointCloud::PointData& p = pointDataVec[i + NUM_POINTS];
202+
PointData& p = pointDataPtr[i + NUM_POINTS];
184203
p.position[0] = 0.0f;
185204
p.position[1] = i * DELTA;
186205
p.position[2] = 0.0f;
@@ -193,14 +212,25 @@ void PointCloud::InitDebugCloud()
193212
// z axis
194213
for (int i = 0; i < NUM_POINTS; i++)
195214
{
196-
PointCloud::PointData& p = pointDataVec[i + 2 * NUM_POINTS];
215+
PointData& p = pointDataPtr[i + 2 * NUM_POINTS];
197216
p.position[0] = 0.0f;
198217
p.position[1] = 0.0f;
199218
p.position[2] = i * DELTA;
200219
p.position[3] = 1.0f;
201-
p.color[0] = 0;
202-
p.color[1] = 0;
220+
p.color[0] = 0.0f;
221+
p.color[1] = 0.0f;
203222
p.color[2] = 1.0f;
204223
p.color[3] = 0.0f;
205224
}
206225
}
226+
227+
void PointCloud::ForEachAttrib(const AttribData& attribData, const AttribCallback& cb) const
228+
{
229+
const uint8_t* bytePtr = (uint8_t*)data.get();
230+
bytePtr += attribData.offset;
231+
for (size_t i = 0; i < GetNumPoints(); i++)
232+
{
233+
cb((const void*)bytePtr);
234+
bytePtr += attribData.stride;
235+
}
236+
}

src/pointcloud.h

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
#pragma once
77

8-
#include <string>
9-
#include <vector>
108
#include <cstdint>
9+
#include <functional>
10+
#include <memory>
11+
#include <string>
1112

1213
class PointCloud
1314
{
@@ -19,18 +20,30 @@ class PointCloud
1920

2021
void InitDebugCloud();
2122

22-
struct PointData
23+
struct AttribData
2324
{
24-
PointData() noexcept {}
25-
float position[4];
26-
float color[4];
25+
int32_t size;
26+
int32_t type;
27+
int32_t stride;
28+
size_t offset;
2729
};
2830

29-
size_t GetNumPoints() const { return pointDataVec.size(); }
30-
const std::vector<PointData>& GetPointDataVec() const { return pointDataVec; }
31-
std::vector<PointData>& GetPointDataVec() { return pointDataVec; }
31+
size_t GetNumPoints() const { return numPoints; }
32+
size_t GetTotalSize() const { return GetNumPoints() * pointSize; }
33+
void* GetRawDataPtr() { return data.get(); }
34+
35+
const AttribData& GetPositionAttrib() const { return positionAttrib; }
36+
const AttribData& GetColorAttrib() const { return colorAttrib; }
37+
38+
using AttribCallback = std::function<void(const void*)>;
39+
void ForEachAttrib(const AttribData& attribData, const AttribCallback& cb) const;
3240

3341
protected:
34-
std::vector<PointData> pointDataVec;
42+
std::shared_ptr<void> data;
43+
AttribData positionAttrib;
44+
AttribData colorAttrib;
45+
46+
size_t numPoints;
47+
size_t pointSize;
3548
bool useLinearColors;
3649
};

src/pointrenderer.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,14 @@ bool PointRenderer::Init(std::shared_ptr<PointCloud> pointCloud, bool isFramebuf
7070
}
7171

7272
const size_t numPoints = pointCloud->GetNumPoints();
73+
7374
// build posVec
7475
posVec.reserve(numPoints);
75-
for (auto&& p : pointCloud->GetPointDataVec())
76+
pointCloud->ForEachAttrib(pointCloud->GetPositionAttrib(), [this](const void* ptr)
7677
{
77-
posVec.emplace_back(glm::vec4(p.position[0], p.position[1], p.position[2], p.position[3]));
78-
}
78+
const float* p = (const float*)ptr;
79+
posVec.emplace_back(glm::vec4(p[0], p[1], p[2], p[3]));
80+
});
7981

8082
BuildVertexArrayObject(pointCloud);
8183

@@ -194,9 +196,8 @@ void PointRenderer::BuildVertexArrayObject(std::shared_ptr<PointCloud> pointClou
194196
const size_t numPoints = pointCloud->GetNumPoints();
195197

196198
// allocate large buffer to hold interleaved vertex data
197-
void* pointDataPtr = (void*)pointCloud->GetPointDataVec().data();
198-
size_t pointDataSize = (size_t)(numPoints * sizeof(PointCloud::PointData));
199-
pointDataBuffer = std::make_shared<BufferObject>(GL_ARRAY_BUFFER, pointDataPtr, pointDataSize, 0);
199+
pointDataBuffer = std::make_shared<BufferObject>(GL_ARRAY_BUFFER, pointCloud->GetRawDataPtr(),
200+
pointCloud->GetTotalSize(), 0);
200201

201202
// build element array
202203
indexVec.reserve(numPoints);
@@ -211,12 +212,16 @@ void PointRenderer::BuildVertexArrayObject(std::shared_ptr<PointCloud> pointClou
211212
pointDataBuffer->Bind();
212213

213214
int positionLoc = pointProg->GetAttribLoc("position");
214-
glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(PointCloud::PointData), (void*)0);
215+
PointCloud::AttribData positionAttrib = pointCloud->GetPositionAttrib();
216+
glVertexAttribPointer(positionLoc, positionAttrib.size, positionAttrib.type, GL_FALSE,
217+
positionAttrib.stride, (void*)positionAttrib.offset);
215218
glEnableVertexAttribArray(positionLoc);
216219

217220
int colorLoc = pointProg->GetAttribLoc("color");
218-
glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(PointCloud::PointData), (void*)(sizeof(float) * 4));
219-
glEnableVertexAttribArray(positionLoc);
221+
PointCloud::AttribData colorAttrib = pointCloud->GetColorAttrib();
222+
glVertexAttribPointer(colorLoc, colorAttrib.size, colorAttrib.type, GL_FALSE,
223+
colorAttrib.stride, (void*)colorAttrib.offset);
224+
glEnableVertexAttribArray(colorLoc);
220225

221226
pointVao->SetElementBuffer(indexBuffer);
222227
}

0 commit comments

Comments
 (0)