41, m_startColor(QColor(60, 120, 255))
42, m_endColor(QColor(255, 80, 40))
45 createSegmentGeometry();
58 if (vecPoints.size() < 2) {
63 m_vecPoints = vecPoints;
72 m_instanceData.clear();
74 ++m_instanceGeneration;
88 const QColor& endColor)
90 m_startColor = startColor;
91 m_endColor = endColor;
97void PolylineObject::createSegmentGeometry()
99 if (!m_vertexData.isEmpty()) {
106 const int iSegments = 8;
107 const float fHalfHeight = 0.5f;
109 std::vector<VertexData> vertices;
110 std::vector<quint32> indices;
112 for (
int i = 0; i < iSegments; ++i) {
113 const float fAngle = 2.0f *
static_cast<float>(M_PI) *
static_cast<float>(i) /
static_cast<float>(iSegments);
114 const float x = std::cos(fAngle);
115 const float z = std::sin(fAngle);
117 QVector3D normal(x, 0.0f, z);
120 vertices.push_back({x, fHalfHeight, z, normal.x(), normal.y(), normal.z()});
121 vertices.push_back({x, -fHalfHeight, z, normal.x(), normal.y(), normal.z()});
124 for (
int i = 0; i < iSegments; ++i) {
125 const quint32 uTop =
static_cast<quint32
>(i * 2);
126 const quint32 uBottom = uTop + 1;
127 const quint32 uNextTop =
static_cast<quint32
>(((i + 1) % iSegments) * 2);
128 const quint32 uNextBottom = uNextTop + 1;
130 indices.push_back(uTop);
131 indices.push_back(uBottom);
132 indices.push_back(uNextTop);
134 indices.push_back(uNextTop);
135 indices.push_back(uBottom);
136 indices.push_back(uNextBottom);
139 m_vertexData = QByteArray(
reinterpret_cast<const char*
>(vertices.data()),
140 static_cast<qsizetype
>(vertices.size() *
sizeof(VertexData)));
141 m_indexData = QByteArray(
reinterpret_cast<const char*
>(indices.data()),
142 static_cast<qsizetype
>(indices.size() *
sizeof(quint32)));
143 m_iIndexCount =
static_cast<int>(indices.size());
144 ++m_geometryGeneration;
149void PolylineObject::buildInstances()
151 if (m_vecPoints.size() < 2) {
152 m_instanceData.clear();
153 m_iInstanceCount = 0;
157 const int iSegmentCount = m_vecPoints.size() - 1;
158 std::vector<InstanceData> instances;
159 instances.reserve(
static_cast<size_t>(iSegmentCount));
161 const float fLastStep =
static_cast<float>(iSegmentCount - 1);
163 for (
int i = 0; i < iSegmentCount; ++i) {
164 const Eigen::Vector3f& vecStart = m_vecPoints.at(i);
165 const Eigen::Vector3f& vecEnd = m_vecPoints.at(i + 1);
167 const QVector3D start(vecStart.x(), vecStart.y(), vecStart.z());
168 const QVector3D end(vecEnd.x(), vecEnd.y(), vecEnd.z());
170 const QVector3D direction = end - start;
171 const float fLength = direction.length();
183 constexpr float fMinSegmentLength = 1.0e-12f;
184 if (fLength < fMinSegmentLength) {
189 model.translate((start + end) * 0.5f);
190 model.rotate(QQuaternion::rotationTo(QVector3D(0.0f, 1.0f, 0.0f),
191 direction / fLength));
192 model.scale(m_fRadius, fLength, m_fRadius);
194 InstanceData instance{};
195 memcpy(instance.model, model.constData(), 16 *
sizeof(
float));
199 const float fRatio = (fLastStep > 0.0f) ? (
static_cast<float>(i) / fLastStep) : 0.0f;
200 instance.color[0] =
static_cast<float>(m_startColor.redF() + (m_endColor.redF() - m_startColor.redF()) * fRatio);
201 instance.color[1] =
static_cast<float>(m_startColor.greenF() + (m_endColor.greenF() - m_startColor.greenF()) * fRatio);
202 instance.color[2] =
static_cast<float>(m_startColor.blueF() + (m_endColor.blueF() - m_startColor.blueF()) * fRatio);
203 instance.color[3] = 1.0f;
204 instance.isSelected = 0.0f;
206 instances.push_back(instance);
209 m_instanceData = QByteArray(
reinterpret_cast<const char*
>(instances.data()),
210 static_cast<qsizetype
>(instances.size() *
sizeof(InstanceData)));
211 m_iInstanceCount =
static_cast<int>(instances.size());
212 ++m_instanceGeneration;
219 return {{m_vertexData.constData(), quint32(m_vertexData.size()), m_geometryGeneration},
220 {m_indexData.constData(), quint32(m_indexData.size()), m_geometryGeneration},
221 {m_instanceData.constData(), quint32(m_iInstanceCount *
sizeof(InstanceData)), m_instanceGeneration},
PolylineObject class declaration.
3-D brain visualisation using the Qt RHI rendering backend.
CPU streams of an instanced mesh: one shape (vertices, indices) drawn once per instance.
void setRadius(float fRadius)
InstancedStreams streams() const
void setGradient(const QColor &startColor, const QColor &endColor)
void setPoints(const QVector< Eigen::Vector3f > &vecPoints)