11 #include "ViewInterpolate.h"
22 #include <QApplication>
23 #include <QElapsedTimer>
24 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QProgressDialog>
35 #ifdef QFFMPEG_SUPPORT
42 #if defined(CV_WINDOWS)
56 dir.setFilter(QDir::Files | QDir::NoSymLinks);
60 QList<QByteArray> formats = QImageReader::supportedImageFormats();
61 if (formats.empty()) {
67 for (
int i = 0; i < formats.size(); ++i) {
68 QString filter = QString(
"*.%1").arg(formats[i].data());
69 filters.append(filter);
73 dir.setNameFilters(filters);
74 QFileInfoList infoList = dir.entryInfoList();
75 QStringList filesList;
76 for (
size_t i = 0; i < infoList.size(); i++) {
77 filesList.append(infoList.at(i).absoluteFilePath());
83 : QDialog(parent, Qt::Tool),
Ui::AnimationDialog(), m_view3d(view3d) {
87 QString defaultOutputFormat;
90 settings.beginGroup(
"qAnimation");
96 defaultDir = QApplication::applicationDirPath();
98 defaultDir = QDir::homePath();
100 const QString defaultFileName(defaultDir +
"/animation.mp4");
101 QString lastFilename =
102 settings.value(
"filename", defaultFileName).toString();
103 QString lastTexturePath =
104 settings.value(
"texturesPath", defaultDir).toString();
105 #ifndef QFFMPEG_SUPPORT
106 lastFilename = QFileInfo(lastFilename).absolutePath();
108 outputFileLineEdit->setText(lastFilename);
109 inputTexturesPathLineEdit->setText(lastTexturePath);
110 textureNumLabel->setText(
111 QString(
"Textures num: %1")
117 bool startPreviewFromSelectedStep =
118 settings.value(
"previewFromSelected",
119 previewFromSelectedCheckBox->isChecked())
122 settings.value(
"updateTextures",
123 updateTexturesCheckBox->isChecked())
126 settings.value(
"loop", loopCheckBox->isChecked()).toBool();
128 settings.value(
"frameRate", fpsSpinBox->value()).toInt();
130 settings.value(
"superRes", superResolutionSpinBox->value())
133 settings.value(
"renderingMode",
134 renderingModeComboBox->currentIndex())
137 settings.value(
"bitRate", bitrateSpinBox->value()).toInt();
138 bool autoStepDuration =
139 settings.value(
"autoStepDuration",
140 autoStepDurationCheckBox->isChecked())
143 settings.value(
"smoothTrajectory",
144 smoothTrajectoryGroupBox->isChecked())
147 settings.value(
"smoothRatio",
148 smoothRatioDoubleSpinBox->value())
150 defaultOutputFormat = settings.value(
"outputFormat").toString();
152 previewFromSelectedCheckBox->setChecked(
153 startPreviewFromSelectedStep);
155 loopCheckBox->setChecked(loop);
156 fpsSpinBox->setValue(frameRate);
157 superResolutionSpinBox->setValue(superRes);
158 renderingModeComboBox->setCurrentIndex(renderingMode);
159 bitrateSpinBox->setValue(bitRate);
160 autoStepDurationCheckBox->setChecked(
164 smoothRatioDoubleSpinBox->setValue(smoothRatio);
172 outputFormatComboBox->addItem(
"Auto", QVariant(QString()));
173 #ifdef QFFMPEG_SUPPORT
174 std::vector<QVideoEncoder::OutputFormat> formats;
176 int defaultIndex = 0;
178 QString title = f.longName;
179 if (!f.extensions.isEmpty()) {
180 title +=
"[" + f.extensions +
"]";
181 static const int s_maxTitleLength = 48;
182 if (title.size() > s_maxTitleLength)
183 title = title.left(s_maxTitleLength - 3) +
"...";
185 outputFormatComboBox->addItem(title, QVariant(f.shortName));
186 if (defaultIndex == 0 && !defaultOutputFormat.isEmpty() &&
187 defaultOutputFormat == f.shortName) {
188 defaultIndex = outputFormatComboBox->count() - 1;
191 outputFormatComboBox->setCurrentIndex(defaultIndex);
196 connect(autoStepDurationCheckBox, &QAbstractButton::toggled,
this,
198 connect(smoothTrajectoryGroupBox, &QGroupBox::toggled,
this,
200 connect(smoothRatioDoubleSpinBox,
201 static_cast<void (QDoubleSpinBox::*)(
double)
>(
202 &QDoubleSpinBox::valueChanged),
206 static_cast<void (QSpinBox::*)(
int)
>(&QSpinBox::valueChanged),
this,
208 connect(totalTimeDoubleSpinBox,
209 static_cast<void (QDoubleSpinBox::*)(
double)
>(
210 &QDoubleSpinBox::valueChanged),
212 connect(stepTimeDoubleSpinBox,
213 static_cast<void (QDoubleSpinBox::*)(
double)
>(
214 &QDoubleSpinBox::valueChanged),
216 connect(loopCheckBox, &QAbstractButton::toggled,
this,
219 connect(browseButton, &QAbstractButton::clicked,
this,
221 connect(browseTextureButton, &QAbstractButton::clicked,
this,
224 connect(previewButton, &QAbstractButton::clicked,
this,
226 connect(renderButton, &QAbstractButton::clicked,
this,
228 connect(exportFramesPushButton, &QAbstractButton::clicked,
this,
230 connect(buttonBox, &QDialogButtonBox::accepted,
this,
232 connect(buttonBox, &QDialogButtonBox::rejected,
this,
243 return updateTexturesCheckBox->isChecked() && !
m_mesh_list.empty();
247 const std::vector<ccMesh*>& meshes) {
248 if (viewports.size() < 2 && meshes.empty()) {
256 }
catch (
const std::bad_alloc&) {
261 ccBBox visibleObjectsBBox;
264 for (
size_t i = 0; i < viewports.size(); ++i) {
269 double duration_sec = 2.0;
273 autoStepDurationCheckBox->blockSignals(
true);
274 autoStepDurationCheckBox->setChecked(
false);
275 autoStepDurationCheckBox->blockSignals(
false);
277 bool isChecked =
true;
282 QString itemName = QString(
"step %1 (%2)")
283 .arg(QString::number(i + 1), vp->
getName());
284 QListWidgetItem* item =
285 new QListWidgetItem(itemName, stepSelectionList);
286 item->setFlags(item->flags() |
287 Qt::ItemIsUserCheckable);
288 item->setCheckState(isChecked
291 stepSelectionList->addItem(item);
296 m_videoSteps[i].indexInOriginalTrajectory =
static_cast<int>(i);
304 for (std::size_t i = 0; i < meshes.size(); ++i) {
312 connect(stepSelectionList, &QListWidget::currentRowChanged,
this,
314 connect(stepSelectionList, &QListWidget::itemChanged,
this,
317 stepSelectionList->setCurrentRow(0);
326 assert(stepSelectionList->count() >=
m_videoSteps.size());
331 if (!autoStepDurationCheckBox->isChecked()) {
337 (stepSelectionList->item(
static_cast<int>(i))->checkState() ==
344 settings.beginGroup(
"qAnimation");
345 settings.setValue(
"previewFromSelected",
346 previewFromSelectedCheckBox->isChecked());
347 settings.setValue(
"updateTextures",
348 updateTexturesCheckBox->isChecked());
349 settings.setValue(
"loop", loopCheckBox->isChecked());
350 settings.setValue(
"frameRate", fpsSpinBox->value());
351 settings.setValue(
"renderingMode",
352 renderingModeComboBox->currentIndex());
353 settings.setValue(
"superRes", superResolutionSpinBox->value());
354 settings.setValue(
"bitRate", bitrateSpinBox->value());
355 settings.setValue(
"autoStepDuration",
356 autoStepDurationCheckBox->isChecked());
357 settings.setValue(
"smoothTrajectory",
358 smoothTrajectoryGroupBox->isChecked());
359 settings.setValue(
"smoothRatio", smoothRatioDoubleSpinBox->value());
360 settings.setValue(
"outputFormat",
361 outputFormatComboBox->currentData().toString());
371 step.indexInSmoothTrajectory = -1;
382 size_t vp1Index = 0, vp2Index = 0;
384 assert(vp1Index < stepSelectionList->
count());
391 if (vp2Index < vp1Index) {
399 if (smoothTrajectoryGroupBox->isChecked()) {
403 if (autoStepDurationCheckBox->isChecked()) {
419 size_t vp1Index = 0, vp2Index = 0;
421 assert(vp1Index < stepSelectionList->
count());
427 if (i1Smooth < 0 || i2Smooth < 0) {
431 if (i2Smooth < i1Smooth) {
437 for (
int i = i1Smooth; i < i2Smooth; ++i) {
444 for (
int i = i1Smooth; i < i2Smooth; ++i) {
451 if (vp2Index < vp1Index) {
462 if (iterationCount == 0) {
464 CVLog::Warning(
"[smoothTrajectory] Invalid input (iteration count)");
468 if (ratio < 0.05 || ratio > 0.45) {
475 if (enabledStepCount < 3) {
486 const Trajectory* currentIterationTrajectory = &previousTrajectory;
488 bool openPoly = !loopCheckBox->isChecked();
490 for (
unsigned it = 0; it < iterationCount; ++it) {
492 size_t vertCount = currentIterationTrajectory->size();
493 size_t segmentCount = (openPoly ? vertCount - 1 : vertCount);
496 newTrajectory.reserve(segmentCount * 2);
500 newTrajectory.push_back(currentIterationTrajectory->front());
503 for (
size_t i = 0; i < segmentCount; ++i) {
505 size_t iQ = ((iP + 1) % vertCount);
507 const Step& sP = currentIterationTrajectory->at(iP);
508 const Step& sQ = currentIterationTrajectory->at(iQ);
513 if (!openPoly || i != 0) {
514 Step interpolatedStep;
523 newTrajectory.push_back(interpolatedStep);
526 if (!openPoly || i + 1 != segmentCount) {
527 Step interpolatedStep;
537 newTrajectory.push_back(interpolatedStep);
543 newTrajectory.push_back(currentIterationTrajectory->back());
547 if (it + 1 == iterationCount) {
550 previousTrajectory = newTrajectory;
551 currentIterationTrajectory = &previousTrajectory;
558 --smoothSegmentCount;
560 for (
size_t i = 0; i < smoothSegmentCount; ++i) {
573 .indexInSmoothTrajectory < 0);
575 .indexInSmoothTrajectory =
static_cast<int>(i);
581 }
catch (
const std::bad_alloc&) {
594 step.indexInSmoothTrajectory = -1;
597 if (!smoothTrajectoryGroupBox->isChecked()) {
606 const unsigned chaikinIterationCount = 5;
607 const double chaikinRatio = smoothRatioDoubleSpinBox->value();
610 CVLog::Error(
"Failed to generate the smooth trajectory");
611 smoothTrajectoryGroupBox->blockSignals(
true);
612 smoothTrajectoryGroupBox->setChecked(
false);
613 smoothTrajectoryGroupBox->blockSignals(
false);
636 assert(referenceTrajectory);
639 double referenceLength = 0;
640 for (
const Step& s : *referenceTrajectory) {
641 referenceLength += s.length;
644 double totalTime = 0.0;
645 double totalTimeSmooth = 0.0;
648 size_t vp1Index = 0, vp2Index = 0;
650 assert(vp1Index < stepSelectionList->
count());
656 int i1Smooth = -1, i2Smooth = -1;
660 if (i1Smooth < 0 || i2Smooth < 0) {
664 if (i2Smooth < i1Smooth) {
669 for (
int i = i1Smooth; i < i2Smooth; ++i) {
682 (
length / referenceLength);
686 for (
int i = i1Smooth; i < i2Smooth; ++i) {
697 if (vp2Index < vp1Index) {
706 .arg(totalTimeSmooth));
720 if (smoothTrajectoryGroupBox->isChecked()) {
731 return exportTrajectoryCheckBox->isChecked();
735 double totalDuration_sec = 0;
736 size_t vp1Index = 0, vp2Index = 0;
738 assert(vp1Index < stepSelectionList->
count());
739 totalDuration_sec +=
m_videoSteps[vp1Index].duration_sec;
740 if (vp2Index < vp1Index) {
747 return totalDuration_sec;
751 return stepSelectionList->currentRow();
768 if (autoStepDurationCheckBox->isChecked()) {
775 if (previousTime_sec != newTime_sec) {
776 assert(previousTime_sec != 0);
777 double scale = newTime_sec / previousTime_sec;
780 double totalTime = 0.0;
781 double totalTimeSmooth = 0.0;
783 size_t vp1Index = 0, vp2Index = 0;
785 assert(vp1Index < stepSelectionList->
count());
795 if (i1Smooth < 0 || i2Smooth < 0) {
799 if (i2Smooth < i1Smooth) {
805 for (
int i = i1Smooth; i < i2Smooth; ++i) {
814 size_t count =
static_cast<size_t>(i2Smooth - i1Smooth);
815 for (
int i = i1Smooth; i < i2Smooth; ++i) {
824 for (
int i = i1Smooth; i < i2Smooth; ++i) {
833 if (vp2Index < vp1Index) {
842 .arg(totalTimeSmooth));
852 if (currentStepIndex >= 0) {
865 #ifdef QFFMPEG_SUPPORT
866 QString
filename = QFileDialog::getSaveFileName(
867 this, tr(
"Output animation file"), outputFileLineEdit->text());
869 QString
filename = QFileDialog::getExistingDirectory(
870 this, tr(
"Open Directory"), outputFileLineEdit->text(),
871 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
879 outputFileLineEdit->setText(
filename);
883 QString texturePath = QFileDialog::getExistingDirectory(
884 this, tr(
"Input textures Directory"),
885 inputTexturesPathLineEdit->text(),
886 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
888 if (texturePath.isEmpty()) {
893 inputTexturesPathLineEdit->setText(texturePath);
894 textureNumLabel->setText(
900 assert(stepSelectionList->count() ==
static_cast<int>(
m_videoSteps.size()));
903 for (
int i = 0; i < stepSelectionList->count(); ++i) {
904 if (stepSelectionList->item(i)->checkState() == Qt::Checked) ++
count;
912 assert(stepSelectionList->count() ==
static_cast<int>(
m_videoSteps.size()));
918 size_t inputVP1Index = vp1Index;
919 while (stepSelectionList->item(
static_cast<int>(vp1Index))->checkState() ==
923 if (loopCheckBox->isChecked()) {
930 if (vp1Index == inputVP1Index) {
936 for (vp2Index = vp1Index + 1; vp2Index <=
m_videoSteps.size(); ++vp2Index) {
937 if (vp1Index == vp2Index) {
942 if (loopCheckBox->isChecked()) {
950 if (stepSelectionList->item(
static_cast<int>(vp2Index))->checkState() ==
963 int totalFrameCount = 0;
965 double fps = fpsSpinBox->value();
967 size_t vp1Index = startIndex;
968 size_t vp2Index = vp1Index + 1;
972 int frameCount =
static_cast<int>(fps * currentStep.
duration_sec);
973 totalFrameCount += frameCount;
976 if (vp2Index < vp1Index) {
977 assert(loopCheckBox->isChecked());
984 return totalFrameCount;
991 compressedTrajectory.clear();
995 compressedTrajectory.reserve(enabledStepCount);
996 }
catch (
const std::bad_alloc&) {
1000 assert(stepSelectionList->count() ==
static_cast<int>(
m_videoSteps.size()));
1002 if (stepSelectionList->item(
static_cast<int>(i))->checkState() ==
1014 bool openPoly = !loopCheckBox->isChecked();
1015 int fps = fpsSpinBox->value();
1016 double timeStep = 1.0 / fps;
1018 qint64 delay_ms =
static_cast<qint64
>(1000 / fps);
1020 QString inputTexturesPath = inputTexturesPathLineEdit->text();
1021 QStringList texture_files =
getImageList(inputTexturesPath);
1023 bool update_textures =
updateTextures() && !texture_files.empty();
1026 int total_count = texture_files.size();
1027 QProgressDialog progressDialog(QString(
"Frames: %1").arg(total_count),
1028 "Cancel", 0, total_count,
this);
1029 progressDialog.setWindowTitle(
"Preview");
1030 progressDialog.show();
1031 progressDialog.setModal(
true);
1032 progressDialog.setAutoClose(
false);
1033 QApplication::processEvents();
1037 size_t vp1Index = previewFromSelectedCheckBox->isChecked()
1046 assert(
m_videoSteps[vp1Index].indexInSmoothTrajectory >= 0);
1047 vp1Index =
static_cast<size_t>(
1054 trajectory = &compressedTrajectory;
1058 size_t segmentCount = trajectory->size();
1059 if (openPoly && segmentCount != 0) {
1063 if (vp1Index >= segmentCount) {
1068 double totalTime = 0;
1069 double startTime = 0;
1070 for (
size_t i = 0; i < segmentCount; ++i) {
1071 totalTime += trajectory->at(i).duration_sec;
1073 startTime += trajectory->at(i).duration_sec;
1078 double remainingTime = (openPoly ? totalTime - startTime : totalTime);
1079 int frameCount =
static_cast<int>(fps * remainingTime);
1081 int total_count = frameCount;
1082 if (frameCount == 0 && update_textures) {
1083 total_count = texture_files.size();
1087 QProgressDialog progressDialog(QString(
"Frames: %1").arg(total_count),
1088 "Cancel", 0, total_count,
this);
1089 progressDialog.setWindowTitle(
"Preview");
1090 progressDialog.show();
1091 progressDialog.setModal(
true);
1092 progressDialog.setAutoClose(
false);
1093 QApplication::processEvents();
1095 assert(stepSelectionList->count() >=
m_videoSteps.size());
1097 double currentTime = startTime;
1098 double currentStepStartTime = startTime;
1100 if (frameCount == 0 && update_textures) {
1102 }
else if (frameCount > 0) {
1104 QElapsedTimer
timer;
1106 for (
int frameIndex = 0; frameIndex < frameCount;) {
1107 size_t vp2Index = vp1Index + 1;
1108 if (vp2Index == trajectory->size()) {
1113 const Step& step1 = trajectory->at(vp1Index);
1114 double deltaTime = currentTime - currentStepStartTime;
1116 const Step& step2 = trajectory->at(vp2Index);
1125 if (update_textures) {
1126 QString texture_file =
1127 texture_files[frameIndex %
1128 texture_files.size()];
1129 if (QFileInfo::exists(texture_file)) {
1134 "Update Textures failed, please "
1135 "toggle shown material first!");
1140 "texture image: %1")
1141 .arg(texture_file));
1148 currentTime += timeStep;
1151 progressDialog.setValue(frameIndex);
1152 QApplication::processEvents();
1153 if (progressDialog.wasCanceled()) {
1157 qint64 dt_ms =
timer.elapsed();
1160 if (dt_ms < delay_ms) {
1161 int wait_ms =
static_cast<int>(delay_ms - dt_ms);
1162 #if defined(CV_WINDOWS)
1165 usleep(wait_ms * 1000);
1172 if (vp1Index == segmentCount) {
1179 currentStepStartTime = 0.0;
1180 currentTime =
std::max(0.0, currentTime - totalTime);
1188 "Please select update tetures and set textures path or "
1189 "select at least two viewports!");
1193 "Please select update tetures and set textures path or "
1194 "select at least two viewports!");
1204 QProgressDialog& progressDialog) {
1205 bool openPoly = !loopCheckBox->isChecked();
1206 int fps = fpsSpinBox->value();
1207 double timeStep = 1.0 / fps;
1209 qint64 delay_ms =
static_cast<qint64
>(1000 / fps);
1210 std::size_t total_count = texture_files.size();
1212 QElapsedTimer
timer;
1214 for (std::size_t frameIndex = 0; frameIndex < texture_files.size();) {
1216 QString texture_file = texture_files[frameIndex];
1217 if (QFileInfo::exists(texture_file)) {
1221 "Update Textures failed, please "
1222 "toggle shown material first!");
1226 CVLog::Warning(QString(
"Ignoring not existing texture image: %1")
1227 .arg(texture_file));
1234 progressDialog.setValue(frameIndex);
1235 QApplication::processEvents();
1236 if (progressDialog.wasCanceled()) {
1240 qint64 dt_ms =
timer.elapsed();
1243 if (dt_ms < delay_ms) {
1244 int wait_ms =
static_cast<int>(delay_ms - dt_ms);
1245 #if defined(CV_WINDOWS)
1248 usleep(wait_ms * 1000);
1252 if (!openPoly && frameIndex == total_count) {
1259 const QStringList& texture_files,
1260 QProgressDialog& progressDialog,
1261 bool asSeparateFrames
1262 #ifdef QFFMPEG_SUPPORT
1264 QScopedPointer<QVideoEncoder>& encoder
1268 bool success =
true;
1269 bool openPoly = !loopCheckBox->isChecked();
1270 int fps = fpsSpinBox->value();
1271 double timeStep = 1.0 / fps;
1273 qint64 delay_ms =
static_cast<qint64
>(1000 / fps);
1274 std::size_t total_count = texture_files.size();
1277 int superRes = superResolutionSpinBox->value();
1278 const int SUPER_RESOLUTION = 0;
1280 int renderingMode = renderingModeComboBox->currentIndex();
1281 assert(renderingMode == SUPER_RESOLUTION || renderingMode == ZOOM);
1283 QString outputFilename = outputFileLineEdit->text();
1284 QDir outputDir(QFileInfo(outputFilename).absolutePath());
1287 QElapsedTimer
timer;
1289 for (std::size_t frameIndex = 0; frameIndex < total_count;) {
1290 if (QFileInfo::exists(texture_files[frameIndex])) {
1292 if (!mesh->updateTextures(
1295 "Update Textures failed, please "
1296 "toggle shown material first!");
1305 if (
image.isNull()) {
1306 QMessageBox::critical(
this,
"Error",
"Failed to grab the screen!");
1311 if (renderingMode == SUPER_RESOLUTION && superRes > 1) {
1313 image.width() / superRes,
image.height() / superRes,
1314 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1317 if (asSeparateFrames) {
1319 QString(
"frame_%1.png").arg(frameIndex, 6, 10, QChar(
'0'));
1320 QString fullPath = outputDir.filePath(
filename);
1321 if (!
image.save(fullPath)) {
1322 QMessageBox::critical(
this,
"Error",
1323 QString(
"Failed to save frame #%1")
1324 .arg(frameIndex + 1));
1329 #ifdef QFFMPEG_SUPPORT
1330 QString errorString;
1331 if (!encoder->encodeImage(
image, frameIndex, &errorString)) {
1332 QMessageBox::critical(
this,
"Error",
1333 QString(
"Failed to encode frame #%1: %2")
1334 .arg(frameIndex + 1)
1345 progressDialog.setValue(frameIndex);
1346 QApplication::processEvents();
1347 if (progressDialog.wasCanceled()) {
1348 QMessageBox::warning(
this,
"Warning",
1349 QString(
"Process has been cancelled"));
1364 QString outputFilename = outputFileLineEdit->text();
1365 QString inputTexturesPath = inputTexturesPathLineEdit->text();
1366 QStringList texture_files =
getImageList(inputTexturesPath);
1368 bool update_textures =
updateTextures() && !texture_files.empty();
1373 settings.beginGroup(
"qAnimation");
1374 settings.setValue(
"filename", outputFilename);
1375 settings.setValue(
"texturesPath", inputTexturesPath);
1376 settings.endGroup();
1381 "Please select update tetures and set textures path or select "
1382 "at least two viewports!");
1399 trajectory = &compressedTrajectory;
1403 bool openPoly = !loopCheckBox->isChecked();
1404 size_t segmentCount = trajectory->size();
1405 if (openPoly && segmentCount != 0) {
1409 double totalTime = 0;
1410 for (
size_t i = 0; i < segmentCount; ++i) {
1411 totalTime += trajectory->at(i).duration_sec;
1415 int fps = fpsSpinBox->value();
1416 int frameCount =
static_cast<int>(fps * totalTime);
1417 int total_count = frameCount;
1418 if (total_count == 0 && update_textures) {
1419 total_count = texture_files.size();
1423 int superRes = superResolutionSpinBox->value();
1424 const int SUPER_RESOLUTION = 0;
1426 int renderingMode = renderingModeComboBox->currentIndex();
1427 assert(renderingMode == SUPER_RESOLUTION || renderingMode == ZOOM);
1430 QProgressDialog progressDialog(QString(
"Frames: %1").arg(total_count),
1431 "Cancel", 0, total_count,
this);
1432 progressDialog.setWindowTitle(
"Render");
1433 progressDialog.show();
1434 QApplication::processEvents();
1436 #ifdef QFFMPEG_SUPPORT
1437 QScopedPointer<QVideoEncoder> encoder(
nullptr);
1438 QSize originalViewSize;
1439 if (!asSeparateFrames) {
1447 QSize customSize = originalViewSize;
1448 if (originalViewSize.width() % 8 || originalViewSize.height() % 8) {
1449 if (originalViewSize.width() % 8)
1450 customSize.setWidth((originalViewSize.width() / 8 + 1) * 8);
1451 if (originalViewSize.height() % 8)
1452 customSize.setHeight((originalViewSize.height() / 8 + 1) *
1455 QApplication::processEvents();
1459 int bitrate = bitrateSpinBox->value() * 1024;
1462 if (renderingMode == ZOOM) {
1463 animScale = superRes;
1469 static_cast<unsigned>(fpsSpinBox->value())));
1471 QString outputFormat = outputFormatComboBox->currentData().toString();
1472 bool success = encoder->open(outputFormat, errors);
1473 for (
const QString& e : errors) {
1478 QMessageBox::critical(
1480 QString(
"Failed to open file for output: %1")
1481 .arg(errors.back()));
1488 if (!asSeparateFrames) {
1489 QMessageBox::critical(
1491 QString(
"Animation mode is not supported (no FFMPEG support)"));
1496 QDir outputDir(QFileInfo(outputFilename).absolutePath());
1498 bool success =
true;
1500 if (frameCount == 0 && update_textures) {
1503 #ifdef QFFMPEG_SUPPORT
1509 double currentTime = 0.0;
1510 double currentStepStartTime = 0.0;
1511 double timeStep = 1.0 / fps;
1512 size_t vp1Index = 0;
1513 for (
int frameIndex = 0; frameIndex < frameCount;) {
1514 size_t vp2Index = vp1Index + 1;
1515 if (vp2Index == trajectory->size()) {
1520 const Step& step1 = trajectory->at(vp1Index);
1521 double deltaTime = currentTime - currentStepStartTime;
1523 const Step& step2 = trajectory->at(vp2Index);
1532 if (update_textures) {
1533 QString texture_file =
1534 texture_files[frameIndex % texture_files.size()];
1535 if (QFileInfo::exists(texture_file)) {
1537 if (!mesh->updateTextures(
1540 "Update Textures failed, please "
1541 "toggle shown material first!");
1547 .arg(texture_file));
1557 if (
image.isNull()) {
1558 QMessageBox::critical(
this,
"Error",
1559 "Failed to grab the screen!");
1564 if (renderingMode == SUPER_RESOLUTION && superRes > 1) {
1566 image.width() / superRes,
image.height() / superRes,
1567 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1570 if (asSeparateFrames) {
1572 QString(
"frame_%1.png")
1573 .arg(frameIndex, 6, 10, QChar(
'0'));
1574 QString fullPath = outputDir.filePath(
filename);
1575 if (!
image.save(fullPath)) {
1576 QMessageBox::critical(
1578 QString(
"Failed to save frame #%1")
1579 .arg(frameIndex + 1));
1584 #ifdef QFFMPEG_SUPPORT
1585 QString errorString;
1586 if (!encoder->encodeImage(
image, frameIndex,
1588 QMessageBox::critical(
1590 QString(
"Failed to encode frame #%1: %2")
1591 .arg(frameIndex + 1)
1600 currentTime += timeStep;
1603 progressDialog.setValue(frameIndex);
1604 QApplication::processEvents();
1605 if (progressDialog.wasCanceled()) {
1606 QMessageBox::warning(
this,
"Warning",
1607 QString(
"Process has been cancelled"));
1616 if (vp1Index == segmentCount) {
1623 #ifdef QFFMPEG_SUPPORT
1628 m_view3d->resize(originalViewSize);
1629 QApplication::processEvents();
1633 progressDialog.hide();
1634 QApplication::processEvents();
1637 QMessageBox::information(
this,
"Job done",
1638 "The animation has been saved successfully");
1647 totalTimeDoubleSpinBox->blockSignals(
true);
1648 totalTimeDoubleSpinBox->setValue(totalDuration_sec);
1649 totalTimeDoubleSpinBox->blockSignals(
false);
1655 stepTimeDoubleSpinBox->blockSignals(
true);
1656 stepTimeDoubleSpinBox->setValue(
1658 stepTimeDoubleSpinBox->blockSignals(
false);
1669 stepIndexLabel->setText(QString::number(index + 1));
1678 .indexInSmoothTrajectory]
1686 stepSelectionList->item(index)->checkState() == Qt::Checked);
1687 bool isLoop = loopCheckBox->isChecked();
1688 currentStepGroupBox->setEnabled(
1690 ((index >= 0 && index + 1 <
m_videoSteps.size()) || isLoop));
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
std::shared_ptr< core::Tensor > image
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Video encoder based on FFmpeg.
static bool GetSupportedOutputFormats(std::vector< OutputFormat > &formats, bool ignoreIfNoFileExtension=true)
Returns the list of supported output formats.
Type norm() const
Returns vector norm.
The ViewInterpolate class.
bool interpolate(ecvViewportParameters &a_returned_viewport, double ratio) const
Interpolates the 2 viewports at a given (relative) position.
const ecvViewportParameters & getParameters() const
Gets parameters.
Vector3Tpl< T > getTranslationAsVec3D() const
Returns a copy of the translation as a CCVector3.
ccGLMatrixTpl< T > inverse() const
Returns inverse transformation.
Double version of ccGLMatrixTpl.
virtual QString getName() const
Returns object name.
void setMetaData(const QString &key, const QVariant &data)
Sets a meta-data element.
QVariant getMetaData(const QString &key) const
Returns a given associated meta data.
bool hasMetaData(const QString &key) const
Returns whether a meta-data element with the given key exists or not.
Standard parameters for GL displays/viewports.
ccGLMatrixd computeViewMatrix() const
Computes the view matrix.
Trajectory m_smoothVideoSteps
Smoothed animation.
int countFrames(size_t startIndex=0)
void onTotalTimeChanged(double)
int getCurrentStepIndex()
bool updateCameraTrajectory()
bool getNextSegment(size_t &vp1, size_t &vp2) const
bool smoothTrajectory(double ratio, unsigned iterationCount)
std::vector< Step > Trajectory
size_t countEnabledSteps() const
void textureAnimationPreview(const QStringList &texture_files, QProgressDialog &progressDialog)
void onBrowseTexturesButtonClicked()
void onCurrentStepChanged(int)
QWidget * m_view3d
Associated 3D view.
qAnimationDlg(QWidget *view3d, QWidget *parent=nullptr)
Default constructor.
void onSmoothRatioChanged(double)
void updateSmoothTrajectoryDurations()
void onStepTimeChanged(double)
Trajectory m_videoSteps
Animation.
void onItemChanged(QListWidgetItem *)
bool exportTrajectoryOnExit()
bool updateTextures() const
bool getCompressedTrajectory(Trajectory &compressedTrajectory) const
void updateTotalDuration()
double computeTotalTime()
virtual ~qAnimationDlg()
Destrcuctor.
bool smoothModeEnabled() const
void onAutoStepsDurationToggled(bool)
void updateCurrentStepDuration()
bool textureAnimationRender(const QStringList &texture_files, QProgressDialog &progressDialog, bool asSeparateFrames)
void onBrowseButtonClicked()
ccPolyline * getTrajectory()
bool init(const std::vector< cc2DViewportObject * > &viewports, const std::vector< ccMesh * > &meshes)
Initialize the dialog with a set of viewports.
void applyViewport(const ecvViewportParameters &viewportParameters)
bool updateSmoothCameraTrajectory()
void onSmoothTrajectoryToggled(bool)
void render(bool asSeparateFrames)
__host__ __device__ float length(float2 v)
static const std::string path
void Sleep(int milliseconds)
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
static const QString s_stepDurationKey("StepDurationSec")
QStringList getImageList(const QString &path)
static const QString s_stepEnabledKey("StepEnabled")
Simple step (viewport + time)
int indexInSmoothTrajectory
int indexInOriginalTrajectory
ecvViewportParameters viewportParams