Compare commits
1 Commits
CloudView_
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb0cbdfc54 |
@ -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,A(0-255)
|
// 解析到了颜色 R,G,B,A(0-255),Alpha 存储在高 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;
|
||||||
|
|||||||
@ -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) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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++;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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[])
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user