Compare commits

..

1 Commits

Author SHA1 Message Date
yiyi
eb0cbdfc54 增加点的大小 2026-02-23 00:43:55 +08:00
7 changed files with 106 additions and 27 deletions

View File

@ -363,8 +363,11 @@ int LaserDataLoader::LoadPolySegments(const std::string& fileName,
pt.y = fy; pt.y = fy;
pt.z = fz; pt.z = fz;
if (cnt >= 7) { if (cnt >= 7) {
// 解析到了颜色 R,G,B,A0-255 // 解析到了颜色 R,G,B,A0-255Alpha 存储在高 8 位
int nRGB = B; nRGB <<= 8; nRGB += G; nRGB <<= 8; nRGB += R; unsigned int nRGB = static_cast<unsigned int>(A) << 24;
nRGB |= static_cast<unsigned int>(B) << 16;
nRGB |= static_cast<unsigned int>(G) << 8;
nRGB |= static_cast<unsigned int>(R);
pt.nRGB = nRGB; pt.nRGB = nRGB;
} }
parsed = true; parsed = true;
@ -650,12 +653,11 @@ int LaserDataLoader::_ParseLaserScanPoint(const std::string& data, SVzNLPointXYZ
sData.y = Y; sData.y = Y;
sData.z = Z; sData.z = Z;
// R,G,B 是 0-255 整数值 // R,G,B,A 是 0-255 整数值Alpha 存储在高 8 位
int nRGB = B; unsigned int nRGB = static_cast<unsigned int>(A) << 24;
nRGB <<= 8; nRGB |= static_cast<unsigned int>(B) << 16;
nRGB += G; nRGB |= static_cast<unsigned int>(G) << 8;
nRGB <<= 8; nRGB |= static_cast<unsigned int>(R);
nRGB += R;
sData.nRGB = nRGB; sData.nRGB = nRGB;
s2DData.sLeft.x = leftX; s2DData.sLeft.x = leftX;

View File

@ -22,9 +22,10 @@ struct Point3DRGB
{ {
float x, y, z; float x, y, z;
uint8_t r, g, b; uint8_t r, g, b;
Point3DRGB() : x(0), y(0), z(0), r(255), g(255), b(255) {} float pointSize; // 自定义点大小0 表示使用全局默认值(来自 RGBA 中 A > 1 的值)
Point3DRGB(float _x, float _y, float _z, uint8_t _r = 255, uint8_t _g = 255, uint8_t _b = 255) Point3DRGB() : x(0), y(0), z(0), r(255), g(255), b(255), pointSize(0) {}
: x(_x), y(_y), z(_z), r(_r), g(_g), b(_b) {} Point3DRGB(float _x, float _y, float _z, uint8_t _r = 255, uint8_t _g = 255, uint8_t _b = 255, float _ps = 0)
: x(_x), y(_y), z(_z), r(_r), g(_g), b(_b), pointSize(_ps) {}
}; };
/** /**

View File

@ -87,10 +87,11 @@ struct LineSegment
float x1, y1, z1; // 起点 float x1, y1, z1; // 起点
float x2, y2, z2; // 终点 float x2, y2, z2; // 终点
float r, g, b; // 颜色 (0-1) float r, g, b; // 颜色 (0-1)
float lineWidth; // 线宽0 表示使用默认值(来自 RGBA 中 A > 1 的值)
LineSegment() : x1(0), y1(0), z1(0), x2(0), y2(0), z2(0), r(1), g(1), b(1) {} LineSegment() : x1(0), y1(0), z1(0), x2(0), y2(0), z2(0), r(1), g(1), b(1), lineWidth(0) {}
LineSegment(float _x1, float _y1, float _z1, float _x2, float _y2, float _z2, float _r = 1.0f, float _g = 1.0f, float _b = 1.0f) LineSegment(float _x1, float _y1, float _z1, float _x2, float _y2, float _z2, float _r = 1.0f, float _g = 1.0f, float _b = 1.0f, float _lw = 0)
: x1(_x1), y1(_y1), z1(_z1), x2(_x2), y2(_y2), z2(_z2), r(_r), g(_g), b(_b) {} : x1(_x1), y1(_y1), z1(_z1), x2(_x2), y2(_y2), z2(_z2), r(_r), g(_g), b(_b), lineWidth(_lw) {}
}; };
/** /**
@ -272,6 +273,14 @@ private:
int totalLines; // 总线数 int totalLines; // 总线数
int pointsPerLine; // 每线点数(网格化点云) int pointsPerLine; // 每线点数(网格化点云)
// 自定义点大小分组RGBA 中 A > 1 的点按大小分组)
struct PointSizeGroup {
float pointSize; // 点大小
std::vector<size_t> indices; // 该大小的点在顶点数组中的索引(顶点索引 = indices[i] * 3
};
std::vector<PointSizeGroup> customPointSizeGroups;
bool hasCustomPointSizes;
// VBO 缓冲区 // VBO 缓冲区
QOpenGLBuffer vertexBuffer; // 顶点 VBO QOpenGLBuffer vertexBuffer; // 顶点 VBO
QOpenGLBuffer colorBuffer; // 颜色 VBO QOpenGLBuffer colorBuffer; // 颜色 VBO
@ -280,6 +289,7 @@ private:
PointCloudData() PointCloudData()
: hasColor(false), hasLineInfo(false), colorIndex(0) : hasColor(false), hasLineInfo(false), colorIndex(0)
, totalLines(0), pointsPerLine(0) , totalLines(0), pointsPerLine(0)
, hasCustomPointSizes(false)
, vertexBuffer(QOpenGLBuffer::VertexBuffer) , vertexBuffer(QOpenGLBuffer::VertexBuffer)
, colorBuffer(QOpenGLBuffer::VertexBuffer) , colorBuffer(QOpenGLBuffer::VertexBuffer)
, vboCreated(false) , vboCreated(false)
@ -297,6 +307,8 @@ private:
, colorIndex(other.colorIndex) , colorIndex(other.colorIndex)
, totalLines(other.totalLines) , totalLines(other.totalLines)
, pointsPerLine(other.pointsPerLine) , pointsPerLine(other.pointsPerLine)
, customPointSizeGroups(std::move(other.customPointSizeGroups))
, hasCustomPointSizes(other.hasCustomPointSizes)
, vertexBuffer(QOpenGLBuffer::VertexBuffer) , vertexBuffer(QOpenGLBuffer::VertexBuffer)
, colorBuffer(QOpenGLBuffer::VertexBuffer) , colorBuffer(QOpenGLBuffer::VertexBuffer)
, vboCreated(false) , vboCreated(false)
@ -324,6 +336,8 @@ private:
colorIndex = other.colorIndex; colorIndex = other.colorIndex;
totalLines = other.totalLines; totalLines = other.totalLines;
pointsPerLine = other.pointsPerLine; pointsPerLine = other.pointsPerLine;
customPointSizeGroups = std::move(other.customPointSizeGroups);
hasCustomPointSizes = other.hasCustomPointSizes;
// VBO 需要重建 // VBO 需要重建
other.vboCreated = false; other.vboCreated = false;
} }

View File

@ -708,14 +708,17 @@ bool CloudViewMainWindow::loadSegmentFile(const QString& fileName)
for (size_t i = 0; i + 1 < polyLine.size(); ++i) { for (size_t i = 0; i + 1 < polyLine.size(); ++i) {
const auto& p1 = polyLine[i]; const auto& p1 = polyLine[i];
const auto& p2 = polyLine[i + 1]; const auto& p2 = polyLine[i + 1];
// 取起点颜色作为线段颜色nRGB 为 BGR 打包格式 // 取起点颜色作为线段颜色nRGB 为 (A<<24)|BGR 打包格式
float r = ((p1.nRGB >> 0) & 0xFF) / 255.0f; float r = ((p1.nRGB >> 0) & 0xFF) / 255.0f;
float g = ((p1.nRGB >> 8) & 0xFF) / 255.0f; float g = ((p1.nRGB >> 8) & 0xFF) / 255.0f;
float b = ((p1.nRGB >> 16) & 0xFF) / 255.0f; float b = ((p1.nRGB >> 16) & 0xFF) / 255.0f;
uint8_t a = static_cast<uint8_t>((p1.nRGB >> 24) & 0xFF);
// A > 1 时作为线宽使用
float lineWidth = (a > 1) ? static_cast<float>(a) : 0.0f;
segments.append(LineSegment( segments.append(LineSegment(
p1.x, p1.y, p1.z, p1.x, p1.y, p1.z,
p2.x, p2.y, p2.z, p2.x, p2.y, p2.z,
r, g, b)); r, g, b, lineWidth));
} }
} }

View File

@ -137,12 +137,15 @@ int PointCloudConverter::loadFromTxt(const std::string& fileName, PointCloudXYZR
for (const auto& line : rgbdData) { for (const auto& line : rgbdData) {
for (int i = 0; i < line.nPointCnt; ++i) { for (int i = 0; i < line.nPointCnt; ++i) {
const SVzNLPointXYZRGBA& pt = line.p3DPoint[i]; const SVzNLPointXYZRGBA& pt = line.p3DPoint[i];
// 解包颜色nRGB 格式为 (B << 16) | (G << 8) | R // 解包颜色nRGB 格式为 (A << 24) | (B << 16) | (G << 8) | R
uint8_t r = static_cast<uint8_t>(pt.nRGB & 0xFF); uint8_t r = static_cast<uint8_t>(pt.nRGB & 0xFF);
uint8_t g = static_cast<uint8_t>((pt.nRGB >> 8) & 0xFF); uint8_t g = static_cast<uint8_t>((pt.nRGB >> 8) & 0xFF);
uint8_t b = static_cast<uint8_t>((pt.nRGB >> 16) & 0xFF); uint8_t b = static_cast<uint8_t>((pt.nRGB >> 16) & 0xFF);
uint8_t a = static_cast<uint8_t>((pt.nRGB >> 24) & 0xFF);
// A > 1 时作为点大小使用
float pointSize = (a > 1) ? static_cast<float>(a) : 0.0f;
Point3DRGB point(pt.x, pt.y, pt.z, r, g, b); Point3DRGB point(pt.x, pt.y, pt.z, r, g, b, pointSize);
cloud.push_back(point, lineIndex); cloud.push_back(point, lineIndex);
totalCount++; totalCount++;
} }

View File

@ -2,6 +2,7 @@
#include <QDebug> #include <QDebug>
#include <QtMath> #include <QtMath>
#include <cfloat> #include <cfloat>
#include <map>
#include "VrLog.h" #include "VrLog.h"
// OpenGL/GLU 头文件 // OpenGL/GLU 头文件
@ -196,6 +197,27 @@ void PointCloudGLWidget::paintGL()
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
// 绘制自定义大小的点RGBA 中 A > 1 的点)
if (cloudData.hasCustomPointSizes) {
glDepthFunc(GL_LEQUAL); // 允许在相同深度覆盖绘制
for (const auto& group : cloudData.customPointSizeGroups) {
glPointSize(group.pointSize);
glBegin(GL_POINTS);
for (size_t idx : group.indices) {
size_t vi = idx * 3;
if (vi + 2 < cloudData.vertices.size()) {
if (cloudData.hasColor && vi + 2 < cloudData.colors.size()) {
glColor3f(cloudData.colors[vi], cloudData.colors[vi + 1], cloudData.colors[vi + 2]);
}
glVertex3f(cloudData.vertices[vi], cloudData.vertices[vi + 1], cloudData.vertices[vi + 2]);
}
}
glEnd();
}
glDepthFunc(GL_LESS); // 恢复默认深度测试
glPointSize(m_pointSize); // 恢复默认点大小
}
} }
drawSelectedPoints(); drawSelectedPoints();
@ -296,12 +318,19 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
data.colors.reserve(cloud.size() * 3); data.colors.reserve(cloud.size() * 3);
data.totalLines = 0; data.totalLines = 0;
data.pointsPerLine = 0; data.pointsPerLine = 0;
data.hasCustomPointSizes = false;
// 用于按点大小分组的临时 map
std::map<float, std::vector<size_t>> sizeGroupMap;
for (size_t i = 0; i < cloud.points.size(); ++i) { for (size_t i = 0; i < cloud.points.size(); ++i) {
const auto& pt = cloud.points[i]; const auto& pt = cloud.points[i];
if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) { if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) {
continue; continue;
} }
size_t pointIndex = data.vertices.size() / 3;
data.vertices.push_back(pt.x); data.vertices.push_back(pt.x);
data.vertices.push_back(pt.y); data.vertices.push_back(pt.y);
data.vertices.push_back(pt.z); data.vertices.push_back(pt.z);
@ -321,6 +350,23 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
data.totalLines = lineIdx + 1; data.totalLines = lineIdx + 1;
} }
} }
// 收集自定义点大小A > 1
if (pt.pointSize > 1.0f) {
sizeGroupMap[pt.pointSize].push_back(pointIndex);
}
}
// 构建自定义点大小分组
if (!sizeGroupMap.empty()) {
data.hasCustomPointSizes = true;
for (auto& pair : sizeGroupMap) {
PointCloudData::PointSizeGroup group;
group.pointSize = pair.first;
group.indices = std::move(pair.second);
data.customPointSizeGroups.push_back(std::move(group));
}
LOG_INFO("[CloudView] Found %zu custom point size groups\n", data.customPointSizeGroups.size());
} }
// 计算每线点数 // 计算每线点数
@ -1187,16 +1233,26 @@ void PointCloudGLWidget::drawLineSegments()
return; return;
} }
glLineWidth(2.0f); // 按线宽分组绘制
glBegin(GL_LINES); // 收集所有不同的线宽值0 表示默认 2.0f
std::map<float, QVector<int>> widthGroups;
for (int i = 0; i < m_lineSegments.size(); ++i) {
float w = m_lineSegments[i].lineWidth > 0 ? m_lineSegments[i].lineWidth : 2.0f;
widthGroups[w].append(i);
}
for (const auto& seg : m_lineSegments) { for (const auto& group : widthGroups) {
glLineWidth(group.first);
glBegin(GL_LINES);
for (int idx : group.second) {
const auto& seg = m_lineSegments[idx];
glColor3f(seg.r, seg.g, seg.b); glColor3f(seg.r, seg.g, seg.b);
glVertex3f(seg.x1, seg.y1, seg.z1); glVertex3f(seg.x1, seg.y1, seg.z1);
glVertex3f(seg.x2, seg.y2, seg.z2); glVertex3f(seg.x2, seg.y2, seg.z2);
} }
glEnd(); glEnd();
}
glLineWidth(1.0f); glLineWidth(1.0f);
} }

View File

@ -3,7 +3,7 @@
#include <QIcon> #include <QIcon>
#include "CloudViewMainWindow.h" #include "CloudViewMainWindow.h"
#define APP_VERSION "1.1.1" #define APP_VERSION "1.1.2"
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {