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)
106 if (it.value() > maxVal)
111 for (
auto& shaft : m_arrays) {
112 for (
auto& contact : shaft.contacts) {
113 auto it = values.find(contact.name);
114 if (it != values.end()) {
115 contact.value = it.value();
116 contact.color = interpolateColor(it.value(), minVal, maxVal,
169 QVector<unsigned int>& indices,
170 int cylinderSides)
const
175 if (cylinderSides < 3)
178 for (
const auto& shaft : m_arrays) {
183 if (shaft.contacts.size() < 2)
186 const QVector3D& tipPos = shaft.contacts.first().position;
187 const QVector3D& tailPos = shaft.contacts.last().position;
188 const QVector3D axis = tailPos - tipPos;
189 const float length = axis.length();
193 const QVector3D axisNorm = axis.normalized();
197 if (qAbs(QVector3D::dotProduct(axisNorm, QVector3D(0, 1, 0))) < 0.99f)
198 perp = QVector3D::crossProduct(axisNorm, QVector3D(0, 1, 0)).normalized();
200 perp = QVector3D::crossProduct(axisNorm, QVector3D(1, 0, 0)).normalized();
202 const QVector3D biperp = QVector3D::crossProduct(axisNorm, perp).normalized();
204 const float r = shaft.shaftRadius;
205 const unsigned int baseIdx =
static_cast<unsigned int>(vertices.size() / 6);
208 for (
int ring = 0; ring < 2; ++ring) {
209 const QVector3D center = (ring == 0) ? tipPos : tailPos;
210 for (
int i = 0; i < cylinderSides; ++i) {
211 const float angle = 2.0f * float(
M_PI) * float(i) / float(cylinderSides);
212 const float cs = cosf(angle);
213 const float sn = sinf(angle);
215 const QVector3D normal = (perp * cs + biperp * sn).normalized();
216 const QVector3D pos = center + normal * r;
219 vertices.append(pos.x());
220 vertices.append(pos.y());
221 vertices.append(pos.z());
223 vertices.append(normal.x());
224 vertices.append(normal.y());
225 vertices.append(normal.z());
230 for (
int i = 0; i < cylinderSides; ++i) {
231 const unsigned int i0 = baseIdx +
static_cast<unsigned int>(i);
232 const unsigned int i1 = baseIdx +
static_cast<unsigned int>((i + 1) % cylinderSides);
233 const unsigned int i2 = i0 +
static_cast<unsigned int>(cylinderSides);
234 const unsigned int i3 = i1 +
static_cast<unsigned int>(cylinderSides);
247 const QVector3D normal = -axisNorm;
248 const unsigned int centerIdx =
static_cast<unsigned int>(vertices.size() / 6);
249 vertices.append(tipPos.x());
250 vertices.append(tipPos.y());
251 vertices.append(tipPos.z());
252 vertices.append(normal.x());
253 vertices.append(normal.y());
254 vertices.append(normal.z());
256 for (
int i = 0; i < cylinderSides; ++i) {
257 const unsigned int i0 = baseIdx +
static_cast<unsigned int>(i);
258 const unsigned int i1 = baseIdx +
static_cast<unsigned int>((i + 1) % cylinderSides);
259 indices.append(centerIdx);
267 const QVector3D normal = axisNorm;
268 const unsigned int centerIdx =
static_cast<unsigned int>(vertices.size() / 6);
269 vertices.append(tailPos.x());
270 vertices.append(tailPos.y());
271 vertices.append(tailPos.z());
272 vertices.append(normal.x());
273 vertices.append(normal.y());
274 vertices.append(normal.z());
276 const unsigned int ring1Base = baseIdx +
static_cast<unsigned int>(cylinderSides);
277 for (
int i = 0; i < cylinderSides; ++i) {
278 const unsigned int i0 = ring1Base +
static_cast<unsigned int>(i);
279 const unsigned int i1 = ring1Base +
static_cast<unsigned int>((i + 1) % cylinderSides);
280 indices.append(centerIdx);
292 instanceData.clear();
293 const int floatsPerInstance = 9;
296 for (
const auto& shaft : m_arrays) {
297 for (
const auto& contact : shaft.contacts) {
299 instanceData.append(contact.position.x());
300 instanceData.append(contact.position.y());
301 instanceData.append(contact.position.z());
303 instanceData.append(contact.radius);
305 instanceData.append(
static_cast<float>(contact.color.redF()));
306 instanceData.append(
static_cast<float>(contact.color.greenF()));
307 instanceData.append(
static_cast<float>(contact.color.blueF()));
308 instanceData.append(
static_cast<float>(contact.color.alphaF()));
310 instanceData.append(contact.selected ? 1.0f : 0.0f);
390 const bool needsCreate = !m_gpu->vertexBuffer || !m_gpu->indexBuffer || !m_gpu->instanceBuffer;
393 if (!needsCreate && !m_gpu->dirty) {
395 if (m_gpu->shaftIndexCount > 0) {
396 QVector<float> verts;
397 QVector<unsigned int> idx;
399 u->uploadStaticBuffer(m_gpu->vertexBuffer.get(), verts.constData());
400 u->uploadStaticBuffer(m_gpu->indexBuffer.get(), idx.constData());
402 if (m_gpu->instanceCount > 0) {
405 u->uploadStaticBuffer(m_gpu->instanceBuffer.get(), inst.constData());
410 if (!m_gpu->dirty && !needsCreate)
415 QVector<float> shaftVerts;
416 QVector<unsigned int> shaftIdx;
419 QVector<float> instData;
422 m_gpu->shaftIndexCount =
static_cast<uint32_t
>(shaftIdx.size());
423 m_gpu->instanceCount =
static_cast<uint32_t
>(instData.size() / 9);
426 const quint32 vbufSize =
static_cast<quint32
>(shaftVerts.size() *
sizeof(
float));
428 if (!m_gpu->vertexBuffer) {
429 m_gpu->vertexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, vbufSize));
430 m_gpu->vertexBuffer->create();
432 u->uploadStaticBuffer(m_gpu->vertexBuffer.get(), shaftVerts.constData());
436 const quint32 ibufSize =
static_cast<quint32
>(shaftIdx.size() *
sizeof(
unsigned int));
438 if (!m_gpu->indexBuffer) {
439 m_gpu->indexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, ibufSize));
440 m_gpu->indexBuffer->create();
442 u->uploadStaticBuffer(m_gpu->indexBuffer.get(), shaftIdx.constData());
446 const quint32 instBufSize =
static_cast<quint32
>(instData.size() *
sizeof(
float));
447 if (instBufSize > 0) {
448 if (!m_gpu->instanceBuffer) {
449 m_gpu->instanceBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, instBufSize));
450 m_gpu->instanceBuffer->create();
452 u->uploadStaticBuffer(m_gpu->instanceBuffer.get(), instData.constData());
455 m_gpu->dirty =
false;