Project
Loading...
Searching...
No Matches
GPUDisplayAnimation.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include "GPUDisplay.h"
16#include "frontend/GPUDisplayInfo.inc"
17#include "GPUCommonMath.h"
18#include "HandMadeMath.h"
19
20using namespace o2::gpu;
21
22constexpr hmm_mat4 MY_HMM_FROM(float (&v)[16]) { return {{{v[0], v[1], v[2], v[3]}, {v[4], v[5], v[6], v[7]}, {v[8], v[9], v[10], v[11]}, {v[12], v[13], v[14], v[15]}}}; }
23
24void GPUDisplay::setAnimationPoint()
25{
26 if (mCfgL.animationMode & 4) // Spherical
27 {
28 float rxy = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[2] * mXYZ[2]);
29 float anglePhi = atan2f(mXYZ[0], mXYZ[2]);
30 float angleTheta = atan2f(mXYZ[1], rxy);
31 if (mAnimateVectors[0].size()) {
32 mAnimationCloseAngle(anglePhi, mAnimateVectors[2].back());
33 }
34 if (mAnimateVectors[0].size()) {
35 mAnimationCloseAngle(angleTheta, mAnimateVectors[3].back());
36 }
37 mAnimateVectors[1].emplace_back(0);
38 mAnimateVectors[2].emplace_back(anglePhi);
39 mAnimateVectors[3].emplace_back(angleTheta);
40 } else {
41 for (int32_t i = 0; i < 3; i++) {
42 mAnimateVectors[i + 1].emplace_back(mXYZ[i]);
43 }
44 // Cartesian
45 }
46 float r = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[1] * mXYZ[1] + mXYZ[2] * mXYZ[2]);
47 mAnimateVectors[4].emplace_back(r);
48 if (mCfgL.animationMode & 1) // Euler-angles
49 {
50 for (int32_t i = 0; i < 3; i++) {
51 float newangle = mAngle[i];
52 if (mAnimateVectors[0].size()) {
53 mAnimationCloseAngle(newangle, mAnimateVectors[i + 5].back());
54 }
55 mAnimateVectors[i + 5].emplace_back(newangle);
56 }
57 mAnimateVectors[8].emplace_back(0);
58 } else { // Quaternions
59 float v[4];
60 createQuaternionFromMatrix(v, &mViewMatrix->Elements[0][0]);
61 if (mAnimateVectors[0].size()) {
62 mAnimateCloseQuaternion(v, mAnimateVectors[5].back(), mAnimateVectors[6].back(), mAnimateVectors[7].back(), mAnimateVectors[8].back());
63 }
64 for (int32_t i = 0; i < 4; i++) {
65 mAnimateVectors[i + 5].emplace_back(v[i]);
66 }
67 }
68 float delay = 0.f;
69 if (mAnimateVectors[0].size()) {
70 delay = mAnimateVectors[0].back() + ((int32_t)(mAnimationDelay * 20)) / 20.f;
71 }
72 mAnimateVectors[0].emplace_back(delay);
73 mAnimateConfig.emplace_back(mCfgL);
74}
75
76void GPUDisplay::resetAnimation()
77{
78 for (int32_t i = 0; i < 9; i++) {
79 mAnimateVectors[i].clear();
80 }
81 mAnimateConfig.clear();
82 mAnimate = 0;
83}
84
85void GPUDisplay::removeAnimationPoint()
86{
87 if (mAnimateVectors[0].size() == 0) {
88 return;
89 }
90 for (int32_t i = 0; i < 9; i++) {
91 mAnimateVectors[i].pop_back();
92 }
93 mAnimateConfig.pop_back();
94}
95
96void GPUDisplay::startAnimation()
97{
98 for (int32_t i = 0; i < 8; i++) {
99 mAnimationSplines[i].create(mAnimateVectors[0], mAnimateVectors[i + 1]);
100 }
101 mAnimationTimer.ResetStart();
102 mAnimationFrame = 0;
103 mAnimate = 1;
104 mAnimationLastBase = 0;
105 mAnimationMixBase = -1;
106}
107
108int32_t GPUDisplay::animateCamera(float& animateTime, float& mixSlaveImage, hmm_mat4& nextViewMatrix)
109{
110 float time = animateTime;
111 if (mAnimate && time < 0) {
112 if (mAnimateScreenshot) {
113 time = mAnimationFrame / 30.f;
114 } else {
115 time = mAnimationTimer.GetCurrentElapsedTime();
116 }
117
118 float maxTime = mAnimateVectors[0].back();
119 if (time >= maxTime) {
120 time = maxTime;
121 mAnimate = mAnimateScreenshot = 0;
122 SetInfo("Animation finished. (%1.2f seconds, %d frames)", time, mAnimationFrame);
123 } else {
124 SetInfo("Running mAnimation: time %1.2f/%1.2f, frames %d", time, maxTime, mAnimationFrame);
125 }
126 mAnimationFrame++;
127 }
128 if (!mAnimate) {
129 return 0;
130 }
131 float vals[8];
132 for (int32_t i = 0; i < 8; i++) {
133 vals[i] = mAnimationSplines[i].evaluate(time);
134 }
135 if (mAnimationChangeConfig && animateTime < 0) {
136 int32_t base = 0;
137 int32_t k = mAnimateVectors[0].size() - 1;
138 while (base < k && time > mAnimateVectors[0][base]) {
139 base++;
140 }
141 if (base > mAnimationLastBase + 1) {
142 mAnimationLastBase = base - 1;
143 }
144
145 const bool mixing = base != mAnimationLastBase && mAnimateVectors[0][mAnimationLastBase] != mAnimateVectors[0][base] && memcmp(&mAnimateConfig[base], &mAnimateConfig[mAnimationLastBase], sizeof(mAnimateConfig[base]));
146 if ((mixing ? base : -1) != mAnimationMixBase) { // Blended configs changed: cached (Vulkan) command buffers must be re-recorded, otherwise they are kept while mixing
147 mAnimationMixBase = mixing ? base : -1;
148 mUpdateDrawCommands = true;
149 }
150 if (mixing) {
151 mixSlaveImage = 1.f - (time - mAnimateVectors[0][mAnimationLastBase]) / (mAnimateVectors[0][base] - mAnimateVectors[0][mAnimationLastBase]);
152 if (mixSlaveImage > 0) {
153 mCfgL = mAnimateConfig[mAnimationLastBase];
154 updateConfig();
155 DrawGLScene_internal(time, true);
156 }
157 }
158
159 if (memcmp(&mAnimateConfig[base], &mCfgL, sizeof(mCfgL))) {
160 mCfgL = mAnimateConfig[base];
161 updateConfig();
162 }
163 }
164
165 if (mCfgL.animationMode != 6) {
166 if (mCfgL.animationMode & 1) // Rotation from euler angles
167 {
168 nextViewMatrix = nextViewMatrix * HMM_Rotate(-vals[4] * 180.f / CAMath::Pi(), {{1, 0, 0}}) * HMM_Rotate(vals[5] * 180.f / CAMath::Pi(), {{0, 1, 0}}) * HMM_Rotate(-vals[6] * 180.f / CAMath::Pi(), {{0, 0, 1}});
169 } else { // Rotation from quaternion
170 const float mag = sqrtf(vals[4] * vals[4] + vals[5] * vals[5] + vals[6] * vals[6] + vals[7] * vals[7]);
171 if (mag < 0.0001f) {
172 vals[7] = 1;
173 } else {
174 for (int32_t i = 0; i < 4; i++) {
175 vals[4 + i] /= mag;
176 }
177 }
178
179 float xx = vals[4] * vals[4], xy = vals[4] * vals[5], xz = vals[4] * vals[6], xw = vals[4] * vals[7], yy = vals[5] * vals[5], yz = vals[5] * vals[6], yw = vals[5] * vals[7], zz = vals[6] * vals[6], zw = vals[6] * vals[7];
180 float mat[16] = {1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0, 2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0, 2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0, 0, 0, 0, 1};
181 nextViewMatrix = nextViewMatrix * MY_HMM_FROM(mat);
182 }
183 }
184 if (mCfgL.animationMode & 4) // Compute cartesian translation from sperical coordinates (euler angles)
185 {
186 const float r = vals[3], phi = vals[1], theta = vals[2];
187 vals[2] = r * cosf(phi) * cosf(theta);
188 vals[0] = r * sinf(phi) * cosf(theta);
189 vals[1] = r * sinf(theta);
190 } else if (mCfgL.animationMode & 2) { // Scale cartesion translation to interpolated radius
191 float r = sqrtf(vals[0] * vals[0] + vals[1] * vals[1] + vals[2] * vals[2]);
192 if (fabsf(r) < 0.0001f) {
193 r = 1;
194 }
195 r = vals[3] / r;
196 for (int32_t i = 0; i < 3; i++) {
197 vals[i] *= r;
198 }
199 }
200 if (mCfgL.animationMode == 6) {
201 nextViewMatrix = HMM_LookAt({{vals[0], vals[1], vals[2]}}, {{0, 0, 0}}, {{0, 1, 0}});
202 } else {
203 nextViewMatrix = nextViewMatrix * HMM_Translate({{-vals[0], -vals[1], -vals[2]}});
204 }
205 return 1;
206}
int16_t time
Definition RawEventData.h:4
int32_t i
constexpr hmm_mat4 MY_HMM_FROM(float(&v)[16])
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)
Definition timer.cxx:117
void ResetStart()
Definition timer.cxx:70
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLboolean r
Definition glcorearb.h:1233