16#include "frontend/GPUDisplayInfo.inc"
26#include "../utils/linux_helpers.h"
41#include "helpers/GPUDisplayColors.inc"
43constexpr hmm_mat4 MY_HMM_IDENTITY = {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};
49 static GPUSettingsDisplay defaultConfig;
51 return *
chain->mConfigDisplay;
61 mCfgL = mConfig.light;
62 mCfgH = mConfig.heavy;
63 mCfgR = mConfig.renderer;
66 throw std::runtime_error(
"Error obtaining display backend");
68 mBackend->mDisplay =
this;
71 mCfgR.openGLCore = mBackend->CoreProfile();
74void GPUDisplay::calcXYZ(
const float* matrix)
76 mXYZ[0] = -(matrix[0] * matrix[12] + matrix[1] * matrix[13] + matrix[2] * matrix[14]);
77 mXYZ[1] = -(matrix[4] * matrix[12] + matrix[5] * matrix[13] + matrix[6] * matrix[14]);
78 mXYZ[2] = -(matrix[8] * matrix[12] + matrix[9] * matrix[13] + matrix[10] * matrix[14]);
80 mAngle[0] = -asinf(matrix[6]);
81 float A = cosf(mAngle[0]);
82 if (fabsf(
A) > 0.005) {
83 mAngle[1] = atan2f(-matrix[2] /
A, matrix[10] /
A);
84 mAngle[2] = atan2f(matrix[4] /
A, matrix[5] /
A);
87 mAngle[2] = atan2f(-matrix[1], -matrix[0]);
90 mRPhiTheta[0] = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[1] * mXYZ[1] + mXYZ[2] * mXYZ[2]);
91 mRPhiTheta[1] = atan2f(mXYZ[0], mXYZ[2]);
92 mRPhiTheta[2] = atan2f(mXYZ[1], sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[2] * mXYZ[2]));
94 createQuaternionFromMatrix(mQuat, matrix);
112 mNCollissions = std::max<uint32_t>(mNCollissions, collision + 1);
113 mOverlayTFClusters.resize(mNCollissions);
114 mOverlayTFClusters[collision][sector] = cluster;
117void GPUDisplay::mAnimationCloseAngle(
float& newangle,
float lastAngle)
119 const float delta = lastAngle > newangle ? (2 * CAMath::Pi()) : (-2 *
CAMath::Pi());
120 while (fabsf(newangle + delta - lastAngle) < fabsf(newangle - lastAngle)) {
124void GPUDisplay::mAnimateCloseQuaternion(
float*
v,
float lastx,
float lasty,
float lastz,
float lastw)
126 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]);
127 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]);
128 if (distPos2 > distNeg2) {
129 for (int32_t
i = 0;
i < 4;
i++) {
150void GPUDisplay::updateConfig()
152 mBackend->setQuality();
153 mBackend->setDepthBuffer();
158 mNDrawCalls += mBackend->drawVertices(
v, t);
163 int32_t
retVal = initFailure;
166 retVal = InitDisplay_internal();
168 }
catch (
const std::runtime_error& e) {
169 GPUError(
"%s", e.what());
172 mInitResult =
retVal == 0 ? 1 : -1;
176int32_t GPUDisplay::InitDisplay_internal()
178 mThreadBuffers.resize(getNumThreads());
179 mThreadTracks.resize(getNumThreads());
180 if (mBackend->InitBackend()) {
183 mYFactor = mBackend->getYFactor();
184 mDrawTextInCompatMode = !mBackend->mFreetypeInitialized && mFrontend->
mCanDrawText == 1;
197 mBackend->ExitBackend();
203 mSemLockDisplay.
Lock();
212 }
else if (!mOverlayTFClusters.size()) {
216 DrawGLScene_internal();
217 }
catch (
const std::runtime_error& e) {
218 GPUError(
"Runtime error %s during display", e.what());
226void GPUDisplay::DrawGLScene_cameraAndAnimation(
float animateTime,
float& mixSlaveImage,
hmm_mat4& nextViewMatrix)
230 bool lookOrigin = mCfgR.camLookOrigin ^ mFrontend->
mKeys[mFrontend->
KEY_ALT];
231 bool yUp = mCfgR.camYUp ^ mFrontend->
mKeys[mFrontend->
KEY_CTRL] ^ lookOrigin;
236 float scalefactor = mFrontend->
mKeys[mFrontend->
KEY_SHIFT] ? 0.2f : 1.0f;
237 float rotatescalefactor = scalefactor * 0.25f;
238 if (mCfgL.drawSector != -1) {
241 float sqrdist = sqrtf(sqrtf(mViewMatrixP[12] * mViewMatrixP[12] + mViewMatrixP[13] * mViewMatrixP[13] + mViewMatrixP[14] * mViewMatrixP[14]) * GL_SCALE_FACTOR) * 0.8f;
242 if (sqrdist < 0.2f) {
248 scalefactor *= sqrdist;
252 if (animateCamera(animateTime, mixSlaveImage, nextViewMatrix)) {
254 }
else if (mResetScene) {
255 const float initialZpos = mCfgH.projectXY ? 16 : (mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR + 8) : 8);
256 nextViewMatrix = nextViewMatrix *
HMM_Translate({{0, 0, -initialZpos}});
260 mCfgL.pointSize = 2.0f;
261 mCfgL.lineWidth = 1.4f;
262 mCfgL.drawSector = -1;
263 mCfgH.xAdd = mCfgH.zAdd = 0;
264 mCfgR.camLookOrigin = mCfgR.camYUp =
false;
265 mAngleRollOrigin = -1e9f;
267 mUpdateDrawCommands = 1;
271 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);
274 float rotRoll = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[(
uint8_t)
'E'] - mFrontend->
mKeys[(uint8_t)
'F']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]);
275 float rotYaw = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_RIGHT] - mFrontend->
mKeys[mFrontend->
KEY_LEFT]);
276 float rotPitch = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_DOWN] - mFrontend->
mKeys[mFrontend->
KEY_UP]);
278 float mouseScale = 1920.f / std::max<float>(1920.f, mBackend->mScreenWidth);
291 mAnimationDelay += moveX;
292 if (mAnimationDelay < 0.05f) {
293 mAnimationDelay = 0.05f;
297 SetInfo(
"Animation delay set to %1.2f", mAnimationDelay);
301 mAngleRollOrigin = 0;
302 }
else if (!lookOrigin) {
303 mAngleRollOrigin = -1e6;
307 if (mAngleRollOrigin < -1e6) {
308 mAngleRollOrigin = yUp ? 0.f : -mAngle[2];
310 mAngleRollOrigin += rotRoll;
311 nextViewMatrix = nextViewMatrix *
HMM_Rotate(mAngleRollOrigin, {{0, 0, 1}});
312 float tmpX = moveX, tmpY = moveY;
313 moveX = tmpX * cosf(mAngle[2]) - tmpY * sinf(mAngle[2]);
314 moveY = tmpX * sinf(mAngle[2]) + tmpY * cosf(mAngle[2]);
317 const float x = mXYZ[0],
y = mXYZ[1],
z = mXYZ[2];
318 float r = sqrtf(
x *
x + +
y *
y +
z *
z);
319 float r2 = sqrtf(
x *
x +
z *
z);
320 float phi = atan2f(
z,
x);
322 float theta = atan2f(mXYZ[1], r2);
323 theta -= moveY * 0.1f;
324 const float max_theta = CAMath::Pi() / 2 - 0.01f;
325 if (theta >= max_theta) {
327 }
else if (theta <= -max_theta) {
330 if (moveZ >=
r - 0.1f) {
334 r2 =
r * cosf(theta);
335 mXYZ[0] = r2 * cosf(phi);
336 mXYZ[2] = r2 * sinf(phi);
337 mXYZ[1] =
r * sinf(theta);
342 nextViewMatrix = nextViewMatrix *
HMM_LookAt({{mXYZ[0], mXYZ[1], mXYZ[2]}}, {{0, 0, 0}}, {{0, 1, 0}});
344 nextViewMatrix = nextViewMatrix *
HMM_Translate({{moveX, moveY * mYFactor, moveZ}});
347 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotYaw, {{0, 1, 0}});
349 if (rotPitch != 0.f) {
350 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotPitch * mYFactor, {{1, 0, 0}});
352 if (!yUp && rotRoll != 0.f) {
353 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotRoll * mYFactor, {{0, 0, 1}});
356 nextViewMatrix = nextViewMatrix * mViewMatrix;
358 calcXYZ(&nextViewMatrix.
Elements[0][0]);
359 nextViewMatrix =
HMM_Rotate(mAngle[2] * 180.f / CAMath::Pi(), {{0, 0, 1}}) * nextViewMatrix;
365 if (rotPitch != 0.f) {
368 if (rotRoll != 0.f) {
369 if (rotateModelTPC) {
370 mModelMatrix =
HMM_Rotate(-rotRoll, {{0, 0, 1}}) * mModelMatrix;
379 float minSize = 0.4f / (mCfgR.drawQualityDownsampleFSAA > 1 ? mCfgR.drawQualityDownsampleFSAA : 1);
381 mCfgL.lineWidth += (
float)deltaLine * mFPSScale * 0.02f * mCfgL.lineWidth;
382 if (mCfgL.lineWidth < minSize) {
383 mCfgL.lineWidth = minSize;
386 SetInfo(
"%s line width: %f", deltaLine > 0 ?
"Increasing" :
"Decreasing", mCfgL.lineWidth);
387 mUpdateDrawCommands = 1;
391 mCfgL.pointSize += (
float)deltaPoint * mFPSScale * 0.02f * mCfgL.pointSize;
392 if (mCfgL.pointSize < minSize) {
393 mCfgL.pointSize = minSize;
396 SetInfo(
"%s point size: %f", deltaPoint > 0 ?
"Increasing" :
"Decreasing", mCfgL.pointSize);
397 mUpdateDrawCommands = 1;
402 if (animateTime < 0) {
403 mViewMatrix = nextViewMatrix;
404 calcXYZ(mViewMatrixP);
413void GPUDisplay::DrawGLScene_drawCommands()
415#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))
416#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))
417#define LOOP_COLLISION for (int32_t iCol = (mCfgL.showCollision == -1 ? 0 : mCfgL.showCollision); iCol < mNCollissions; iCol += (mCfgL.showCollision == -1 ? 1 : mNCollissions))
418#define LOOP_COLLISION_COL(cmd) \
421 if (mCfgL.colorCollisions) { \
422 SetCollisionColor(iCol); \
427 if (mCfgL.drawGrid) {
437 if (mCfgL.drawClusters) {
440 mBackend->lineWidthFactor(2);
442 if (mCfgL.drawFinal && mCfgL.colorClusters) {
446 mBackend->lineWidthFactor(1);
450 mBackend->pointSizeFactor(2);
452 mBackend->pointSizeFactor(1);
462 if (mCfgL.drawInitLinks) {
463 if (mCfgL.excludeClusters) {
466 if (mCfgL.colorClusters) {
472 if (mCfgL.drawLinks) {
473 if (mCfgL.excludeClusters) {
476 if (mCfgL.colorClusters) {
484 if (mCfgL.drawSeeds) {
485 if (mCfgL.excludeClusters) {
488 if (mCfgL.colorClusters) {
496 if (mCfgL.drawTracklets) {
497 if (mCfgL.excludeClusters) {
500 if (mCfgL.colorClusters) {
506 if (mCfgL.drawTracks) {
507 if (mCfgL.excludeClusters) {
510 if (mCfgL.colorClusters) {
517 if (mCfgL.drawExtrapolatedTracks) {
518 if (mCfgL.excludeClusters) {
521 if (mCfgL.colorClusters) {
522 SetColorExtrapolatedTracks();
530 if (mCfgL.drawFinal && mCfgL.propagateTracks < 2) {
531 if (mCfgL.excludeClusters) {
534 if (mCfgL.colorClusters) {
543 if (!mCfgH.clustersOnly && mCfgL.excludeClusters != 1) {
545 if (mCfgL.drawInitLinks) {
549 if (mCfgL.drawLinks) {
553 if (mCfgL.drawSeeds) {
557 if (mCfgL.drawTracklets) {
561 if (mCfgL.drawTracks) {
565 if (mCfgL.drawExtrapolatedTracks) {
566 SetColorExtrapolatedTracks();
570 if (mCfgL.drawFinal) {
574 if (mCfgL.colorCollisions) {
575 SetCollisionColor(iCol);
577 if (mCfgL.propagateTracks < 2) {
580 if (mCfgL.propagateTracks > 0 && mCfgL.propagateTracks < 3) {
583 if (mCfgL.propagateTracks == 2) {
586 if (mCfgL.propagateTracks == 3) {
590 if (mCfgH.drawTracksAndFilter ? (mCfgH.drawTPCTracks || mCfgH.drawTRDTracks || mCfgH.drawTOFTracks) : mCfgH.drawITSTracks) {
594 if (mCfgH.markClusters || mCfgH.markAdjacentClusters || mCfgH.markFakeClusters) {
595 if (mCfgH.markFakeClusters) {
596 mBackend->pointSizeFactor(3);
600 if (mCfgH.markFakeClusters) {
601 mBackend->pointSizeFactor(1);
607void GPUDisplay::DrawGLScene_internal(
float animateTime,
bool renderToMixBuffer)
609 bool showTimer =
false;
610 bool doScreenshot = (mRequestScreenshot || mAnimateScreenshot) && animateTime < 0;
613 if (animateTime < 0 && (mUpdateEventData || mResetScene || mUpdateVertexLists) && mIOPtrs) {
614 disableUnsupportedOptions();
616 if (mUpdateEventData || mUpdateVertexLists) {
617 mUpdateDrawCommands = 1;
620 if (animateTime < 0 && (mUpdateEventData || mResetScene) && mIOPtrs) {
622 DrawGLScene_updateEventData();
626 mUpdateVertexLists = 1;
627 mUpdateEventData = 0;
631 float mixSlaveImage = 0.f;
632 DrawGLScene_cameraAndAnimation(animateTime, mixSlaveImage, nextViewMatrix);
635 if (mUpdateVertexLists && mIOPtrs) {
636 size_t totalVertizes = DrawGLScene_updateVertexList();
638 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])));
643 nextViewMatrix = nextViewMatrix * mModelMatrix;
644 const float zFar = ((mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR) : 8.f) + 50.f) * 2.f;
646 mBackend->prepareDraw(proj, nextViewMatrix, doScreenshot || mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
647 mBackend->pointSizeFactor(1);
648 mBackend->lineWidthFactor(1);
650 if (mUpdateDrawCommands || mBackend->backendNeedRedraw()) {
652 DrawGLScene_drawCommands();
655 if (mCfgL.drawField) {
656 mBackend->drawField();
659 mUpdateDrawCommands = mUpdateRenderPipeline = 0;
660 mBackend->finishDraw(doScreenshot, renderToMixBuffer, mixSlaveImage);
662 if (animateTime < 0) {
667 float fps = (double)mFramesDoneFPS / fpstime;
669 "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) "
670 "(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)",
671 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(),
672 mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi());
674 if (mPrintInfoText & 2) {
677 if (mFPSScaleadjust++) {
678 mFPSScale = 60 / fps;
684 if (mPrintInfoText & 1) {
689 mBackend->finishFrame(mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
691 mRequestScreenshot =
false;
692 std::vector<char>
pixels = mBackend->getPixels();
693 char tmpFileName[48];
694 if (mAnimateScreenshot) {
695 snprintf(tmpFileName, 48,
"mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame);
697 DoScreenshot(mAnimateScreenshot ? tmpFileName : mScreenshotFile.c_str(),
pixels);
706 if (mMaxClusterZ <= 0) {
711 mUpdateEventData =
true;
721 while (mInitResult == 0) {
724 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 & GetCalib() 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