50 : m_bbMin(std::numeric_limits<float>::max(),
51 std::numeric_limits<float>::max(),
52 std::numeric_limits<float>::max())
53 , m_bbMax(std::numeric_limits<float>::lowest(),
54 std::numeric_limits<float>::lowest(),
55 std::numeric_limits<float>::lowest())
94 const QColor& minColor,
95 const QColor& maxColor)
101 float minVal = std::numeric_limits<float>::max();
102 float maxVal = std::numeric_limits<float>::lowest();
103 for (
auto it = values.cbegin(); it != values.cend(); ++it) {
104 if (it.value() < minVal) minVal = it.value();
105 if (it.value() > maxVal) maxVal = it.value();
109 for (
auto& shaft : m_arrays) {
110 for (
auto& contact : shaft.contacts) {
111 auto it = values.find(contact.name);
112 if (it != values.end()) {
113 contact.value = it.value();
114 contact.color = interpolateColor(it.value(), minVal, maxVal,
167 QVector<unsigned int>& indices,
168 int cylinderSides)
const
173 if (cylinderSides < 3)
176 for (
const auto& shaft : m_arrays) {
181 if (shaft.contacts.size() < 2)
184 const QVector3D& tipPos = shaft.contacts.first().position;
185 const QVector3D& tailPos = shaft.contacts.last().position;
186 const QVector3D axis = tailPos - tipPos;
187 const float length = axis.length();
191 const QVector3D axisNorm = axis.normalized();
195 if (qAbs(QVector3D::dotProduct(axisNorm, QVector3D(0, 1, 0))) < 0.99f)
196 perp = QVector3D::crossProduct(axisNorm, QVector3D(0, 1, 0)).normalized();
198 perp = QVector3D::crossProduct(axisNorm, QVector3D(1, 0, 0)).normalized();
200 const QVector3D biperp = QVector3D::crossProduct(axisNorm, perp).normalized();
202 const float r = shaft.shaftRadius;
203 const unsigned int baseIdx =
static_cast<unsigned int>(vertices.size() / 6);
206 for (
int ring = 0; ring < 2; ++ring) {
207 const QVector3D center = (ring == 0) ? tipPos : tailPos;
208 for (
int i = 0; i < cylinderSides; ++i) {
209 const float angle = 2.0f * float(
M_PI) * float(i) / float(cylinderSides);
210 const float cs = cosf(angle);
211 const float sn = sinf(angle);
213 const QVector3D normal = (perp * cs + biperp * sn).normalized();
214 const QVector3D pos = center + normal * r;
217 vertices.append(pos.x());
218 vertices.append(pos.y());
219 vertices.append(pos.z());
221 vertices.append(normal.x());
222 vertices.append(normal.y());
223 vertices.append(normal.z());
228 for (
int i = 0; i < cylinderSides; ++i) {
229 const unsigned int i0 = baseIdx +
static_cast<unsigned int>(i);
230 const unsigned int i1 = baseIdx +
static_cast<unsigned int>((i + 1) % cylinderSides);
231 const unsigned int i2 = i0 +
static_cast<unsigned int>(cylinderSides);
232 const unsigned int i3 = i1 +
static_cast<unsigned int>(cylinderSides);
235 indices.append(i0); indices.append(i2); indices.append(i1);
236 indices.append(i1); indices.append(i2); indices.append(i3);
241 const QVector3D normal = -axisNorm;
242 const unsigned int centerIdx =
static_cast<unsigned int>(vertices.size() / 6);
243 vertices.append(tipPos.x());
244 vertices.append(tipPos.y());
245 vertices.append(tipPos.z());
246 vertices.append(normal.x());
247 vertices.append(normal.y());
248 vertices.append(normal.z());
250 for (
int i = 0; i < cylinderSides; ++i) {
251 const unsigned int i0 = baseIdx +
static_cast<unsigned int>(i);
252 const unsigned int i1 = baseIdx +
static_cast<unsigned int>((i + 1) % cylinderSides);
253 indices.append(centerIdx); indices.append(i1); indices.append(i0);
259 const QVector3D normal = axisNorm;
260 const unsigned int centerIdx =
static_cast<unsigned int>(vertices.size() / 6);
261 vertices.append(tailPos.x());
262 vertices.append(tailPos.y());
263 vertices.append(tailPos.z());
264 vertices.append(normal.x());
265 vertices.append(normal.y());
266 vertices.append(normal.z());
268 const unsigned int ring1Base = baseIdx +
static_cast<unsigned int>(cylinderSides);
269 for (
int i = 0; i < cylinderSides; ++i) {
270 const unsigned int i0 = ring1Base +
static_cast<unsigned int>(i);
271 const unsigned int i1 = ring1Base +
static_cast<unsigned int>((i + 1) % cylinderSides);
272 indices.append(centerIdx); indices.append(i0); indices.append(i1);
282 instanceData.clear();
283 const int floatsPerInstance = 9;
286 for (
const auto& shaft : m_arrays) {
287 for (
const auto& contact : shaft.contacts) {
289 instanceData.append(contact.position.x());
290 instanceData.append(contact.position.y());
291 instanceData.append(contact.position.z());
293 instanceData.append(contact.radius);
295 instanceData.append(
static_cast<float>(contact.color.redF()));
296 instanceData.append(
static_cast<float>(contact.color.greenF()));
297 instanceData.append(
static_cast<float>(contact.color.blueF()));
298 instanceData.append(
static_cast<float>(contact.color.alphaF()));
300 instanceData.append(contact.selected ? 1.0f : 0.0f);
374 const bool needsCreate = !m_gpu->vertexBuffer || !m_gpu->indexBuffer || !m_gpu->instanceBuffer;
377 if (!needsCreate && !m_gpu->dirty) {
379 if (m_gpu->shaftIndexCount > 0) {
380 QVector<float> verts;
381 QVector<unsigned int> idx;
383 u->uploadStaticBuffer(m_gpu->vertexBuffer.get(), verts.constData());
384 u->uploadStaticBuffer(m_gpu->indexBuffer.get(), idx.constData());
386 if (m_gpu->instanceCount > 0) {
389 u->uploadStaticBuffer(m_gpu->instanceBuffer.get(), inst.constData());
394 if (!m_gpu->dirty && !needsCreate)
return;
398 QVector<float> shaftVerts;
399 QVector<unsigned int> shaftIdx;
402 QVector<float> instData;
405 m_gpu->shaftIndexCount =
static_cast<uint32_t
>(shaftIdx.size());
406 m_gpu->instanceCount =
static_cast<uint32_t
>(instData.size() / 9);
409 const quint32 vbufSize =
static_cast<quint32
>(shaftVerts.size() *
sizeof(
float));
411 if (!m_gpu->vertexBuffer) {
412 m_gpu->vertexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, vbufSize));
413 m_gpu->vertexBuffer->create();
415 u->uploadStaticBuffer(m_gpu->vertexBuffer.get(), shaftVerts.constData());
419 const quint32 ibufSize =
static_cast<quint32
>(shaftIdx.size() *
sizeof(
unsigned int));
421 if (!m_gpu->indexBuffer) {
422 m_gpu->indexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, ibufSize));
423 m_gpu->indexBuffer->create();
425 u->uploadStaticBuffer(m_gpu->indexBuffer.get(), shaftIdx.constData());
429 const quint32 instBufSize =
static_cast<quint32
>(instData.size() *
sizeof(
float));
430 if (instBufSize > 0) {
431 if (!m_gpu->instanceBuffer) {
432 m_gpu->instanceBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, instBufSize));
433 m_gpu->instanceBuffer->create();
435 u->uploadStaticBuffer(m_gpu->instanceBuffer.get(), instData.constData());
438 m_gpu->dirty =
false;