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;
50 return (
chain &&
chain->mConfigDisplay) ? *
chain->mConfigDisplay : defaultConfig;
55 static GPUSettingsProcessing defaultConfig;
59GPUDisplay::GPUDisplay(
GPUDisplayFrontend* frontend,
GPUChainTracking*
chain,
GPUQA* qa,
const GPUParam*
param,
const GPUCalibObjectsConst* calib,
const GPUSettingsDisplay* config,
const GPUSettingsProcessing* proc) :
GPUDisplayInterface(), mFrontend(frontend), mChain(
chain), mConfig(config ? *config : GetConfig(
chain)), mProcessingSettings(proc ? *proc : GetProcessingConfig(
chain)), mQA(qa)
63 mCfgL = mConfig.light;
64 mCfgH = mConfig.heavy;
65 mCfgR = mConfig.renderer;
68 throw std::runtime_error(
"Error obtaining display backend");
70 mBackend->mDisplay =
this;
73 mCfgR.openGLCore = mBackend->CoreProfile();
76void GPUDisplay::calcXYZ(
const float* matrix)
78 mXYZ[0] = -(matrix[0] * matrix[12] + matrix[1] * matrix[13] + matrix[2] * matrix[14]);
79 mXYZ[1] = -(matrix[4] * matrix[12] + matrix[5] * matrix[13] + matrix[6] * matrix[14]);
80 mXYZ[2] = -(matrix[8] * matrix[12] + matrix[9] * matrix[13] + matrix[10] * matrix[14]);
82 mAngle[0] = -asinf(matrix[6]);
83 float A = cosf(mAngle[0]);
84 if (fabsf(
A) > 0.005) {
85 mAngle[1] = atan2f(-matrix[2] /
A, matrix[10] /
A);
86 mAngle[2] = atan2f(matrix[4] /
A, matrix[5] /
A);
89 mAngle[2] = atan2f(-matrix[1], -matrix[0]);
92 mRPhiTheta[0] = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[1] * mXYZ[1] + mXYZ[2] * mXYZ[2]);
93 mRPhiTheta[1] = atan2f(mXYZ[0], mXYZ[2]);
94 mRPhiTheta[2] = atan2f(mXYZ[1], sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[2] * mXYZ[2]));
96 createQuaternionFromMatrix(mQuat, matrix);
114 mNCollissions = std::max<uint32_t>(mNCollissions, collision + 1);
115 mOverlayTFClusters.resize(mNCollissions);
116 mOverlayTFClusters[collision][sector] = cluster;
119void GPUDisplay::mAnimationCloseAngle(
float& newangle,
float lastAngle)
121 const float delta = lastAngle > newangle ? (2 * CAMath::Pi()) : (-2 *
CAMath::Pi());
122 while (fabsf(newangle + delta - lastAngle) < fabsf(newangle - lastAngle)) {
126void GPUDisplay::mAnimateCloseQuaternion(
float*
v,
float lastx,
float lasty,
float lastz,
float lastw)
128 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]);
129 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]);
130 if (distPos2 > distNeg2) {
131 for (int32_t
i = 0;
i < 4;
i++) {
152void GPUDisplay::updateConfig()
154 mBackend->setQuality();
155 mBackend->setDepthBuffer();
160 mNDrawCalls += mBackend->drawVertices(
v, t);
165 int32_t
retVal = initFailure;
168 retVal = InitDisplay_internal();
170 }
catch (
const std::runtime_error& e) {
171 GPUError(
"%s", e.what());
174 mInitResult =
retVal == 0 ? 1 : -1;
178int32_t GPUDisplay::InitDisplay_internal()
180 mThreadBuffers.resize(getNumThreads());
181 mThreadTracks.resize(getNumThreads());
182 if (mBackend->InitBackend()) {
185 mYFactor = mBackend->getYFactor();
186 mDrawTextInCompatMode = !mBackend->mFreetypeInitialized && mFrontend->
mCanDrawText == 1;
199 mBackend->ExitBackend();
205 mSemLockDisplay.
Lock();
214 }
else if (!mOverlayTFClusters.size()) {
218 DrawGLScene_internal();
219 }
catch (
const std::runtime_error& e) {
220 GPUError(
"Runtime error %s during display", e.what());
228void GPUDisplay::DrawGLScene_cameraAndAnimation(
float animateTime,
float& mixSlaveImage,
hmm_mat4& nextViewMatrix)
232 bool lookOrigin = mCfgR.camLookOrigin ^ mFrontend->
mKeys[mFrontend->
KEY_ALT];
233 bool yUp = mCfgR.camYUp ^ mFrontend->
mKeys[mFrontend->
KEY_CTRL] ^ lookOrigin;
238 float scalefactor = mFrontend->
mKeys[mFrontend->
KEY_SHIFT] ? 0.2f : 1.0f;
239 float rotatescalefactor = scalefactor * 0.25f;
240 if (mCfgL.drawSector != -1) {
243 float sqrdist = sqrtf(sqrtf(mViewMatrixP[12] * mViewMatrixP[12] + mViewMatrixP[13] * mViewMatrixP[13] + mViewMatrixP[14] * mViewMatrixP[14]) * GL_SCALE_FACTOR) * 0.8f;
244 if (sqrdist < 0.2f) {
250 scalefactor *= sqrdist;
254 if (animateCamera(animateTime, mixSlaveImage, nextViewMatrix)) {
256 }
else if (mResetScene) {
257 const float initialZpos = mCfgH.projectXY ? 16 : (mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR + 8) : 8);
258 nextViewMatrix = nextViewMatrix *
HMM_Translate({{0, 0, -initialZpos}});
262 mCfgL.pointSize = 2.0f;
263 mCfgL.lineWidth = 1.4f;
264 mCfgL.drawSector = -1;
265 mCfgH.xAdd = mCfgH.zAdd = 0;
266 mCfgR.camLookOrigin = mCfgR.camYUp =
false;
267 mAngleRollOrigin = -1e9f;
269 mUpdateDrawCommands = 1;
273 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);
276 float rotRoll = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[(
uint8_t)
'E'] - mFrontend->
mKeys[(uint8_t)
'F']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]);
277 float rotYaw = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_RIGHT] - mFrontend->
mKeys[mFrontend->
KEY_LEFT]);
278 float rotPitch = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_DOWN] - mFrontend->
mKeys[mFrontend->
KEY_UP]);
280 float mouseScale = 1920.f / std::max<float>(1920.f, mBackend->mScreenWidth);
293 mAnimationDelay += moveX;
294 if (mAnimationDelay < 0.05f) {
295 mAnimationDelay = 0.05f;
299 SetInfo(
"Animation delay set to %1.2f", mAnimationDelay);
303 mAngleRollOrigin = 0;
304 }
else if (!lookOrigin) {
305 mAngleRollOrigin = -1e6;
309 if (mAngleRollOrigin < -1e6) {
310 mAngleRollOrigin = yUp ? 0.f : -mAngle[2];
312 mAngleRollOrigin += rotRoll;
313 nextViewMatrix = nextViewMatrix *
HMM_Rotate(mAngleRollOrigin, {{0, 0, 1}});
314 float tmpX = moveX, tmpY = moveY;
315 moveX = tmpX * cosf(mAngle[2]) - tmpY * sinf(mAngle[2]);
316 moveY = tmpX * sinf(mAngle[2]) + tmpY * cosf(mAngle[2]);
319 const float x = mXYZ[0],
y = mXYZ[1],
z = mXYZ[2];
320 float r = sqrtf(
x *
x + +
y *
y +
z *
z);
321 float r2 = sqrtf(
x *
x +
z *
z);
322 float phi = atan2f(
z,
x);
324 float theta = atan2f(mXYZ[1], r2);
325 theta -= moveY * 0.1f;
326 const float max_theta = CAMath::Pi() / 2 - 0.01f;
327 if (theta >= max_theta) {
329 }
else if (theta <= -max_theta) {
332 if (moveZ >=
r - 0.1f) {
336 r2 =
r * cosf(theta);
337 mXYZ[0] = r2 * cosf(phi);
338 mXYZ[2] = r2 * sinf(phi);
339 mXYZ[1] =
r * sinf(theta);
344 nextViewMatrix = nextViewMatrix *
HMM_LookAt({{mXYZ[0], mXYZ[1], mXYZ[2]}}, {{0, 0, 0}}, {{0, 1, 0}});
346 nextViewMatrix = nextViewMatrix *
HMM_Translate({{moveX, moveY * mYFactor, moveZ}});
349 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotYaw, {{0, 1, 0}});
351 if (rotPitch != 0.f) {
352 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotPitch * mYFactor, {{1, 0, 0}});
354 if (!yUp && rotRoll != 0.f) {
355 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotRoll * mYFactor, {{0, 0, 1}});
358 nextViewMatrix = nextViewMatrix * mViewMatrix;
360 calcXYZ(&nextViewMatrix.
Elements[0][0]);
361 nextViewMatrix =
HMM_Rotate(mAngle[2] * 180.f / CAMath::Pi(), {{0, 0, 1}}) * nextViewMatrix;
367 if (rotPitch != 0.f) {
370 if (rotRoll != 0.f) {
371 if (rotateModelTPC) {
372 mModelMatrix =
HMM_Rotate(-rotRoll, {{0, 0, 1}}) * mModelMatrix;
381 float minSize = 0.4f / (mCfgR.drawQualityDownsampleFSAA > 1 ? mCfgR.drawQualityDownsampleFSAA : 1);
383 mCfgL.lineWidth += (
float)deltaLine * mFPSScale * 0.02f * mCfgL.lineWidth;
384 if (mCfgL.lineWidth < minSize) {
385 mCfgL.lineWidth = minSize;
388 SetInfo(
"%s line width: %f", deltaLine > 0 ?
"Increasing" :
"Decreasing", mCfgL.lineWidth);
389 mUpdateDrawCommands = 1;
393 mCfgL.pointSize += (
float)deltaPoint * mFPSScale * 0.02f * mCfgL.pointSize;
394 if (mCfgL.pointSize < minSize) {
395 mCfgL.pointSize = minSize;
398 SetInfo(
"%s point size: %f", deltaPoint > 0 ?
"Increasing" :
"Decreasing", mCfgL.pointSize);
399 mUpdateDrawCommands = 1;
404 if (animateTime < 0) {
405 mViewMatrix = nextViewMatrix;
406 calcXYZ(mViewMatrixP);
415void GPUDisplay::DrawGLScene_drawCommands()
417#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))
418#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))
419#define LOOP_COLLISION for (int32_t iCol = (mCfgL.showCollision == -1 ? 0 : mCfgL.showCollision); iCol < mNCollissions; iCol += (mCfgL.showCollision == -1 ? 1 : mNCollissions))
420#define LOOP_COLLISION_COL(cmd) \
423 if (mCfgL.colorCollisions) { \
424 SetCollisionColor(iCol); \
429 if (mCfgL.drawGrid) {
439 if (mCfgL.drawClusters) {
442 mBackend->lineWidthFactor(2);
444 if (mCfgL.drawFinal && mCfgL.colorClusters) {
448 mBackend->lineWidthFactor(1);
452 mBackend->pointSizeFactor(2);
454 mBackend->pointSizeFactor(1);
464 if (mCfgL.drawInitLinks) {
465 if (mCfgL.excludeClusters) {
468 if (mCfgL.colorClusters) {
474 if (mCfgL.drawLinks) {
475 if (mCfgL.excludeClusters) {
478 if (mCfgL.colorClusters) {
486 if (mCfgL.drawSeeds) {
487 if (mCfgL.excludeClusters) {
490 if (mCfgL.colorClusters) {
498 if (mCfgL.drawTracklets) {
499 if (mCfgL.excludeClusters) {
502 if (mCfgL.colorClusters) {
508 if (mCfgL.drawTracks) {
509 if (mCfgL.excludeClusters) {
512 if (mCfgL.colorClusters) {
519 if (mCfgL.drawExtrapolatedTracks) {
520 if (mCfgL.excludeClusters) {
523 if (mCfgL.colorClusters) {
524 SetColorExtrapolatedTracks();
532 if (mCfgL.drawFinal && mCfgL.propagateTracks < 2) {
533 if (mCfgL.excludeClusters) {
536 if (mCfgL.colorClusters) {
545 if (!mCfgH.clustersOnly && mCfgL.excludeClusters != 1) {
547 if (mCfgL.drawInitLinks) {
551 if (mCfgL.drawLinks) {
555 if (mCfgL.drawSeeds) {
559 if (mCfgL.drawTracklets) {
563 if (mCfgL.drawTracks) {
567 if (mCfgL.drawExtrapolatedTracks) {
568 SetColorExtrapolatedTracks();
572 if (mCfgL.drawFinal) {
576 if (mCfgL.colorCollisions) {
577 SetCollisionColor(iCol);
579 if (mCfgL.propagateTracks < 2) {
582 if (mCfgL.propagateTracks > 0 && mCfgL.propagateTracks < 3) {
585 if (mCfgL.propagateTracks == 2) {
588 if (mCfgL.propagateTracks == 3) {
592 if (mCfgH.drawTracksAndFilter ? (mCfgH.drawTPCTracks || mCfgH.drawTRDTracks || mCfgH.drawTOFTracks) : mCfgH.drawITSTracks) {
596 if (mCfgH.markClusters || mCfgH.markAdjacentClusters || mCfgH.markFakeClusters) {
597 if (mCfgH.markFakeClusters) {
598 mBackend->pointSizeFactor(3);
602 if (mCfgH.markFakeClusters) {
603 mBackend->pointSizeFactor(1);
609void GPUDisplay::DrawGLScene_internal(
float animateTime,
bool renderToMixBuffer)
611 bool showTimer =
false;
612 bool doScreenshot = (mRequestScreenshot || mAnimateScreenshot) && animateTime < 0;
615 if (animateTime < 0 && (mUpdateEventData || mResetScene || mUpdateVertexLists) && mIOPtrs) {
616 disableUnsupportedOptions();
618 if (mUpdateEventData || mUpdateVertexLists) {
619 mUpdateDrawCommands = 1;
622 if (animateTime < 0 && (mUpdateEventData || mResetScene) && mIOPtrs) {
624 DrawGLScene_updateEventData();
628 mUpdateVertexLists = 1;
629 mUpdateEventData = 0;
633 float mixSlaveImage = 0.f;
634 DrawGLScene_cameraAndAnimation(animateTime, mixSlaveImage, nextViewMatrix);
637 if (mUpdateVertexLists && mIOPtrs) {
638 size_t totalVertizes = DrawGLScene_updateVertexList();
640 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])));
645 nextViewMatrix = nextViewMatrix * mModelMatrix;
646 const float zFar = ((mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR) : 8.f) + 50.f) * 2.f;
648 mBackend->prepareDraw(proj, nextViewMatrix, doScreenshot || mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
649 mBackend->pointSizeFactor(1);
650 mBackend->lineWidthFactor(1);
652 if (mUpdateDrawCommands || mBackend->backendNeedRedraw()) {
654 DrawGLScene_drawCommands();
657 if (mCfgL.drawField) {
658 mBackend->drawField();
661 mUpdateDrawCommands = mUpdateRenderPipeline = 0;
662 mBackend->finishDraw(doScreenshot, renderToMixBuffer, mixSlaveImage);
664 if (animateTime < 0) {
669 float fps = (double)mFramesDoneFPS / fpstime;
671 "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) "
672 "(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)",
673 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(),
674 mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi());
676 if (mPrintInfoText & 2) {
679 if (mFPSScaleadjust++) {
680 mFPSScale = 60 / fps;
686 if (mPrintInfoText & 1) {
691 mBackend->finishFrame(mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
693 mRequestScreenshot =
false;
694 std::vector<char>
pixels = mBackend->getPixels();
695 char tmpFileName[48];
696 if (mAnimateScreenshot) {
697 snprintf(tmpFileName, 48,
"mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame);
699 DoScreenshot(mAnimateScreenshot ? tmpFileName : mScreenshotFile.c_str(),
pixels);
708 if (mMaxClusterZ <= 0) {
713 mUpdateEventData =
true;
723 while (mInitResult == 0) {
726 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 GPUSettingsProcessing & GetProcessingSettings() 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
GPUDisplay(GPUDisplayFrontend *frontend, GPUChainTracking *chain, GPUQA *qa, const GPUParam *param=nullptr, const GPUCalibObjectsConst *calib=nullptr, const GPUSettingsDisplay *config=nullptr, const GPUSettingsProcessing *proc=nullptr)
void SetCollisionFirstCluster(uint32_t collision, int32_t sector, int32_t cluster) override
void WaitForNextEvent() override
int32_t StartDisplay() override
GPUDisplayFrontend * frontend()
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