25#include "../utils/linux_helpers.h"
40#include "helpers/GPUDisplayColors.inc"
42constexpr hmm_mat4 MY_HMM_IDENTITY = {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};
48 static GPUSettingsDisplay defaultConfig;
50 return *
chain->mConfigDisplay;
60 mCfgL = mConfig.light;
61 mCfgH = mConfig.heavy;
62 mCfgR = mConfig.renderer;
65 throw std::runtime_error(
"Error obtaining display backend");
67 mBackend->mDisplay =
this;
70 mCfgR.openGLCore = mBackend->CoreProfile();
73void GPUDisplay::calcXYZ(
const float* matrix)
75 mXYZ[0] = -(matrix[0] * matrix[12] + matrix[1] * matrix[13] + matrix[2] * matrix[14]);
76 mXYZ[1] = -(matrix[4] * matrix[12] + matrix[5] * matrix[13] + matrix[6] * matrix[14]);
77 mXYZ[2] = -(matrix[8] * matrix[12] + matrix[9] * matrix[13] + matrix[10] * matrix[14]);
79 mAngle[0] = -asinf(matrix[6]);
80 float A = cosf(mAngle[0]);
81 if (fabsf(
A) > 0.005) {
82 mAngle[1] = atan2f(-matrix[2] /
A, matrix[10] /
A);
83 mAngle[2] = atan2f(matrix[4] /
A, matrix[5] /
A);
86 mAngle[2] = atan2f(-matrix[1], -matrix[0]);
89 mRPhiTheta[0] = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[1] * mXYZ[1] + mXYZ[2] * mXYZ[2]);
90 mRPhiTheta[1] = atan2f(mXYZ[0], mXYZ[2]);
91 mRPhiTheta[2] = atan2f(mXYZ[1], sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[2] * mXYZ[2]));
93 createQuaternionFromMatrix(mQuat, matrix);
111 mNCollissions = std::max<uint32_t>(mNCollissions, collision + 1);
112 mOverlayTFClusters.resize(mNCollissions);
113 mOverlayTFClusters[collision][sector] = cluster;
116void GPUDisplay::mAnimationCloseAngle(
float& newangle,
float lastAngle)
118 const float delta = lastAngle > newangle ? (2 * CAMath::Pi()) : (-2 *
CAMath::Pi());
119 while (fabsf(newangle + delta - lastAngle) < fabsf(newangle - lastAngle)) {
123void GPUDisplay::mAnimateCloseQuaternion(
float*
v,
float lastx,
float lasty,
float lastz,
float lastw)
125 float distPos2 = (lastx -
v[0]) * (lastx -
v[0]) + (lasty -
v[1]) * (lasty -
v[1]) + (lastz -
v[2]) * (lastz -
v[2]) + (lastw -
v[3]) * (lastw -
v[3]);
126 float distNeg2 = (lastx +
v[0]) * (lastx +
v[0]) + (lasty +
v[1]) * (lasty +
v[1]) + (lastz +
v[2]) * (lastz +
v[2]) + (lastw +
v[3]) * (lastw +
v[3]);
127 if (distPos2 > distNeg2) {
128 for (int32_t
i = 0;
i < 4;
i++) {
149void GPUDisplay::updateConfig()
151 mBackend->setQuality();
152 mBackend->setDepthBuffer();
157 mNDrawCalls += mBackend->drawVertices(
v, t);
162 int32_t
retVal = initFailure;
165 retVal = InitDisplay_internal();
167 }
catch (
const std::runtime_error& e) {
168 GPUError(
"%s", e.what());
171 mInitResult =
retVal == 0 ? 1 : -1;
175int32_t GPUDisplay::InitDisplay_internal()
177 mThreadBuffers.resize(getNumThreads());
178 mThreadTracks.resize(getNumThreads());
179 if (mBackend->InitBackend()) {
182 mYFactor = mBackend->getYFactor();
183 mDrawTextInCompatMode = !mBackend->mFreetypeInitialized && mFrontend->
mCanDrawText == 1;
196 mBackend->ExitBackend();
202 mSemLockDisplay.
Lock();
207 mCalib = &mChain->
calib();
211 }
else if (!mOverlayTFClusters.size()) {
215 DrawGLScene_internal();
216 }
catch (
const std::runtime_error& e) {
217 GPUError(
"Runtime error %s during display", e.what());
225void GPUDisplay::DrawGLScene_cameraAndAnimation(
float animateTime,
float& mixSlaveImage,
hmm_mat4& nextViewMatrix)
229 bool lookOrigin = mCfgR.camLookOrigin ^ mFrontend->
mKeys[mFrontend->
KEY_ALT];
230 bool yUp = mCfgR.camYUp ^ mFrontend->
mKeys[mFrontend->
KEY_CTRL] ^ lookOrigin;
235 float scalefactor = mFrontend->
mKeys[mFrontend->
KEY_SHIFT] ? 0.2f : 1.0f;
236 float rotatescalefactor = scalefactor * 0.25f;
237 if (mCfgL.drawSector != -1) {
240 float sqrdist = sqrtf(sqrtf(mViewMatrixP[12] * mViewMatrixP[12] + mViewMatrixP[13] * mViewMatrixP[13] + mViewMatrixP[14] * mViewMatrixP[14]) * GL_SCALE_FACTOR) * 0.8f;
241 if (sqrdist < 0.2f) {
247 scalefactor *= sqrdist;
251 if (animateCamera(animateTime, mixSlaveImage, nextViewMatrix)) {
253 }
else if (mResetScene) {
254 const float initialZpos = mCfgH.projectXY ? 16 : (mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR + 8) : 8);
255 nextViewMatrix = nextViewMatrix *
HMM_Translate({{0, 0, -initialZpos}});
259 mCfgL.pointSize = 2.0f;
260 mCfgL.lineWidth = 1.4f;
261 mCfgL.drawSector = -1;
262 mCfgH.xAdd = mCfgH.zAdd = 0;
263 mCfgR.camLookOrigin = mCfgR.camYUp =
false;
264 mAngleRollOrigin = -1e9f;
266 mUpdateDrawCommands = 1;
270 float moveZ = scalefactor * ((
float)mMouseWheelTmp / 150 + (
float)(mFrontend->
mKeys[(
uint8_t)
'W'] - mFrontend->
mKeys[(uint8_t)
'S']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]) * 0.2f * mFPSScale);
273 float rotRoll = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[(
uint8_t)
'E'] - mFrontend->
mKeys[(uint8_t)
'F']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]);
274 float rotYaw = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_RIGHT] - mFrontend->
mKeys[mFrontend->
KEY_LEFT]);
275 float rotPitch = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_DOWN] - mFrontend->
mKeys[mFrontend->
KEY_UP]);
277 float mouseScale = 1920.f / std::max<float>(1920.f, mBackend->mScreenWidth);
290 mAnimationDelay += moveX;
291 if (mAnimationDelay < 0.05f) {
292 mAnimationDelay = 0.05f;
296 SetInfo(
"Animation delay set to %1.2f", mAnimationDelay);
300 mAngleRollOrigin = 0;
301 }
else if (!lookOrigin) {
302 mAngleRollOrigin = -1e6;
306 if (mAngleRollOrigin < -1e6) {
307 mAngleRollOrigin = yUp ? 0.f : -mAngle[2];
309 mAngleRollOrigin += rotRoll;
310 nextViewMatrix = nextViewMatrix *
HMM_Rotate(mAngleRollOrigin, {{0, 0, 1}});
311 float tmpX = moveX, tmpY = moveY;
312 moveX = tmpX * cosf(mAngle[2]) - tmpY * sinf(mAngle[2]);
313 moveY = tmpX * sinf(mAngle[2]) + tmpY * cosf(mAngle[2]);
316 const float x = mXYZ[0],
y = mXYZ[1],
z = mXYZ[2];
317 float r = sqrtf(
x *
x + +
y *
y +
z *
z);
318 float r2 = sqrtf(
x *
x +
z *
z);
319 float phi = atan2f(
z,
x);
321 float theta = atan2f(mXYZ[1], r2);
322 theta -= moveY * 0.1f;
323 const float max_theta = CAMath::Pi() / 2 - 0.01f;
324 if (theta >= max_theta) {
326 }
else if (theta <= -max_theta) {
329 if (moveZ >=
r - 0.1f) {
333 r2 =
r * cosf(theta);
334 mXYZ[0] = r2 * cosf(phi);
335 mXYZ[2] = r2 * sinf(phi);
336 mXYZ[1] =
r * sinf(theta);
341 nextViewMatrix = nextViewMatrix *
HMM_LookAt({{mXYZ[0], mXYZ[1], mXYZ[2]}}, {{0, 0, 0}}, {{0, 1, 0}});
343 nextViewMatrix = nextViewMatrix *
HMM_Translate({{moveX, moveY * mYFactor, moveZ}});
346 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotYaw, {{0, 1, 0}});
348 if (rotPitch != 0.f) {
349 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotPitch * mYFactor, {{1, 0, 0}});
351 if (!yUp && rotRoll != 0.f) {
352 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotRoll * mYFactor, {{0, 0, 1}});
355 nextViewMatrix = nextViewMatrix * mViewMatrix;
357 calcXYZ(&nextViewMatrix.
Elements[0][0]);
358 nextViewMatrix =
HMM_Rotate(mAngle[2] * 180.f / CAMath::Pi(), {{0, 0, 1}}) * nextViewMatrix;
364 if (rotPitch != 0.f) {
367 if (rotRoll != 0.f) {
368 if (rotateModelTPC) {
369 mModelMatrix =
HMM_Rotate(-rotRoll, {{0, 0, 1}}) * mModelMatrix;
378 float minSize = 0.4f / (mCfgR.drawQualityDownsampleFSAA > 1 ? mCfgR.drawQualityDownsampleFSAA : 1);
380 mCfgL.lineWidth += (
float)deltaLine * mFPSScale * 0.02f * mCfgL.lineWidth;
381 if (mCfgL.lineWidth < minSize) {
382 mCfgL.lineWidth = minSize;
385 SetInfo(
"%s line width: %f", deltaLine > 0 ?
"Increasing" :
"Decreasing", mCfgL.lineWidth);
386 mUpdateDrawCommands = 1;
390 mCfgL.pointSize += (
float)deltaPoint * mFPSScale * 0.02f * mCfgL.pointSize;
391 if (mCfgL.pointSize < minSize) {
392 mCfgL.pointSize = minSize;
395 SetInfo(
"%s point size: %f", deltaPoint > 0 ?
"Increasing" :
"Decreasing", mCfgL.pointSize);
396 mUpdateDrawCommands = 1;
401 if (animateTime < 0) {
402 mViewMatrix = nextViewMatrix;
403 calcXYZ(mViewMatrixP);
412void GPUDisplay::DrawGLScene_drawCommands()
414#define LOOP_SECTOR for (int32_t iSector = (mCfgL.drawSector == -1 ? 0 : mCfgL.drawRelatedSectors ? (mCfgL.drawSector % (NSECTORS / 4)) : mCfgL.drawSector); iSector < NSECTORS; iSector += (mCfgL.drawSector == -1 ? 1 : mCfgL.drawRelatedSectors ? (NSECTORS / 4) : NSECTORS))
415#define LOOP_SECTOR2 for (int32_t iSector = (mCfgL.drawSector == -1 ? 0 : mCfgL.drawRelatedSectors ? (mCfgL.drawSector % (NSECTORS / 4)) : mCfgL.drawSector) % (NSECTORS / 2); iSector < NSECTORS / 2; iSector += (mCfgL.drawSector == -1 ? 1 : mCfgL.drawRelatedSectors ? (NSECTORS / 4) : NSECTORS))
416#define LOOP_COLLISION for (int32_t iCol = (mCfgL.showCollision == -1 ? 0 : mCfgL.showCollision); iCol < mNCollissions; iCol += (mCfgL.showCollision == -1 ? 1 : mNCollissions))
417#define LOOP_COLLISION_COL(cmd) \
420 if (mCfgL.colorCollisions) { \
421 SetCollisionColor(iCol); \
426 if (mCfgL.drawGrid) {
436 if (mCfgL.drawClusters) {
439 mBackend->lineWidthFactor(2);
441 if (mCfgL.drawFinal && mCfgL.colorClusters) {
445 mBackend->lineWidthFactor(1);
449 mBackend->pointSizeFactor(2);
451 mBackend->pointSizeFactor(1);
461 if (mCfgL.drawInitLinks) {
462 if (mCfgL.excludeClusters) {
465 if (mCfgL.colorClusters) {
471 if (mCfgL.drawLinks) {
472 if (mCfgL.excludeClusters) {
475 if (mCfgL.colorClusters) {
483 if (mCfgL.drawSeeds) {
484 if (mCfgL.excludeClusters) {
487 if (mCfgL.colorClusters) {
495 if (mCfgL.drawTracklets) {
496 if (mCfgL.excludeClusters) {
499 if (mCfgL.colorClusters) {
505 if (mCfgL.drawTracks) {
506 if (mCfgL.excludeClusters) {
509 if (mCfgL.colorClusters) {
516 if (mCfgL.drawExtrapolatedTracks) {
517 if (mCfgL.excludeClusters) {
520 if (mCfgL.colorClusters) {
521 SetColorExtrapolatedTracks();
529 if (mCfgL.drawFinal && mCfgL.propagateTracks < 2) {
530 if (mCfgL.excludeClusters) {
533 if (mCfgL.colorClusters) {
542 if (!mCfgH.clustersOnly && mCfgL.excludeClusters != 1) {
544 if (mCfgL.drawInitLinks) {
548 if (mCfgL.drawLinks) {
552 if (mCfgL.drawSeeds) {
556 if (mCfgL.drawTracklets) {
560 if (mCfgL.drawTracks) {
564 if (mCfgL.drawExtrapolatedTracks) {
565 SetColorExtrapolatedTracks();
569 if (mCfgL.drawFinal) {
573 if (mCfgL.colorCollisions) {
574 SetCollisionColor(iCol);
576 if (mCfgL.propagateTracks < 2) {
579 if (mCfgL.propagateTracks > 0 && mCfgL.propagateTracks < 3) {
582 if (mCfgL.propagateTracks == 2) {
585 if (mCfgL.propagateTracks == 3) {
589 if (mCfgH.drawTracksAndFilter ? (mCfgH.drawTPCTracks || mCfgH.drawTRDTracks || mCfgH.drawTOFTracks) : mCfgH.drawITSTracks) {
593 if (mCfgH.markClusters || mCfgH.markAdjacentClusters || mCfgH.markFakeClusters) {
594 if (mCfgH.markFakeClusters) {
595 mBackend->pointSizeFactor(3);
599 if (mCfgH.markFakeClusters) {
600 mBackend->pointSizeFactor(1);
606void GPUDisplay::DrawGLScene_internal(
float animateTime,
bool renderToMixBuffer)
608 bool showTimer =
false;
609 bool doScreenshot = (mRequestScreenshot || mAnimateScreenshot) && animateTime < 0;
612 if (animateTime < 0 && (mUpdateEventData || mResetScene || mUpdateVertexLists) && mIOPtrs) {
613 disableUnsupportedOptions();
615 if (mUpdateEventData || mUpdateVertexLists) {
616 mUpdateDrawCommands = 1;
619 if (animateTime < 0 && (mUpdateEventData || mResetScene) && mIOPtrs) {
621 DrawGLScene_updateEventData();
625 mUpdateVertexLists = 1;
626 mUpdateEventData = 0;
630 float mixSlaveImage = 0.f;
631 DrawGLScene_cameraAndAnimation(animateTime, mixSlaveImage, nextViewMatrix);
634 if (mUpdateVertexLists && mIOPtrs) {
635 size_t totalVertizes = DrawGLScene_updateVertexList();
637 printf(
"Event visualization time: %'d us (vertices %'ld / %'ld bytes)\n", (int32_t)(mTimerDraw.
GetCurrentElapsedTime() * 1000000.), (int64_t)totalVertizes, (int64_t)(totalVertizes *
sizeof(mVertexBuffer[0][0])));
642 nextViewMatrix = nextViewMatrix * mModelMatrix;
643 const float zFar = ((mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR) : 8.f) + 50.f) * 2.f;
645 mBackend->prepareDraw(proj, nextViewMatrix, doScreenshot || mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
646 mBackend->pointSizeFactor(1);
647 mBackend->lineWidthFactor(1);
649 if (mUpdateDrawCommands || mBackend->backendNeedRedraw()) {
651 DrawGLScene_drawCommands();
654 if (mCfgL.drawField) {
655 mBackend->drawField();
658 mUpdateDrawCommands = mUpdateRenderPipeline = 0;
659 mBackend->finishDraw(doScreenshot, renderToMixBuffer, mixSlaveImage);
661 if (animateTime < 0) {
666 float fps = (double)mFramesDoneFPS / fpstime;
668 "FPS: %6.2f (Sector: %d, 1:Clusters %d, 2:Prelinks %d, 3:Links %d, 4:Seeds %d, 5:Tracklets %d, 6:Tracks %d, 7:GTracks %d, 8:Merger %d) (%d frames, %d draw calls) "
669 "(X %1.2f Y %1.2f Z %1.2f / R %1.2f Phi %1.1f Theta %1.1f) / Yaw %1.1f Pitch %1.1f Roll %1.1f)",
670 fps, mCfgL.drawSector, mCfgL.drawClusters, mCfgL.drawInitLinks, mCfgL.drawLinks, mCfgL.drawSeeds, mCfgL.drawTracklets, mCfgL.drawTracks, mCfgL.drawExtrapolatedTracks, mCfgL.drawFinal, mFramesDone, mNDrawCalls, mXYZ[0], mXYZ[1], mXYZ[2], mRPhiTheta[0], mRPhiTheta[1] * 180 / CAMath::Pi(),
671 mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi());
673 if (mPrintInfoText & 2) {
676 if (mFPSScaleadjust++) {
677 mFPSScale = 60 / fps;
683 if (mPrintInfoText & 1) {
688 mBackend->finishFrame(mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
690 mRequestScreenshot =
false;
691 std::vector<char>
pixels = mBackend->getPixels();
692 char tmpFileName[48];
693 if (mAnimateScreenshot) {
694 snprintf(tmpFileName, 48,
"mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame);
696 DoScreenshot(mAnimateScreenshot ? tmpFileName : mScreenshotFile.c_str(),
pixels);
705 if (mMaxClusterZ <= 0) {
710 mUpdateEventData =
true;
720 while (mInitResult == 0) {
723 return (mInitResult != 1);
constexpr hmm_mat4 MY_HMM_IDENTITY
#define LOOP_COLLISION_COL(cmd)
HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, float Far)
HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation)
HMM_EXTERN hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up)
HMM_EXTERN hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis)
double GetCurrentElapsedTime(bool reset=false)
GPUTrackingInOutPointers & mIOPtrs
const GPUCalibObjectsConst & calib() const
const GPUParam & GetParam() const
static GPUDisplayBackend * getBackend(const char *type)
static constexpr int32_t KEY_ALT
virtual void getSize(int32_t &width, int32_t &height)
static constexpr int32_t KEY_PAGEDOWN
static constexpr int32_t KEY_RALT
static constexpr int32_t KEY_LEFT
volatile int32_t mNeedUpdate
static constexpr int32_t KEY_CTRL
static constexpr int32_t INIT_WIDTH
static constexpr int32_t KEY_SHIFT
static constexpr int32_t KEY_PAGEUP
virtual int32_t StartDisplay()=0
GPUDisplayBackend * mBackend
static constexpr int32_t KEY_UP
static constexpr int32_t KEY_DOWN
static constexpr int32_t INIT_HEIGHT
static constexpr int32_t KEY_RIGHT
static constexpr int32_t KEY_RCTRL
void SetCollisionFirstCluster(uint32_t collision, int32_t sector, int32_t cluster) override
void WaitForNextEvent() override
int32_t StartDisplay() override
GPUDisplayFrontend * frontend()
GPUDisplay(GPUDisplayFrontend *frontend, GPUChainTracking *chain, GPUQA *qa, const GPUParam *param=nullptr, const GPUCalibObjectsConst *calib=nullptr, const GPUSettingsDisplay *config=nullptr)
int32_t InitDisplay(bool initFailure=false)
void ShowNextEvent(const GPUTrackingInOutPointers *ptrs=nullptr) override
void ResizeScene(int32_t width, int32_t height, bool init=false)
GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar
GLint GLsizei GLsizei height
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t