SPH
Movie.cpp
Go to the documentation of this file.
1 #include "gui/objects/Movie.h"
2 #include "gui/MainLoop.h"
3 #include "gui/Settings.h"
4 #include "gui/Utils.h"
5 #include "gui/objects/Bitmap.h"
6 #include "gui/objects/Camera.h"
8 #include "io/FileSystem.h"
10 #include "system/Process.h"
11 #include "system/Statistics.h"
12 #include "thread/CheckFunction.h"
13 #include <condition_variable>
14 #include <mutex>
15 #include <wx/dcmemory.h>
16 #include <wx/image.h>
17 
19 
20 std::once_flag initFlag;
21 
22 Movie::Movie(const GuiSettings& settings,
23  AutoPtr<IRenderer>&& renderer,
24  Array<AutoPtr<IColorizer>>&& colorizers,
25  RenderParams&& params)
26  : renderer(std::move(renderer))
27  , colorizers(std::move(colorizers))
28  , params(std::move(params)) {
29  enabled = settings.get<bool>(GuiSettingsId::IMAGES_SAVE);
30  makeAnimation = settings.get<bool>(GuiSettingsId::IMAGES_MAKE_MOVIE);
31  outputStep = settings.get<Float>(GuiSettingsId::IMAGES_TIMESTEP);
32  cameraVelocity = settings.get<Vector>(GuiSettingsId::CAMERA_VELOCITY);
33  cameraOrbit = settings.get<Float>(GuiSettingsId::CAMERA_ORBIT);
34 
35  const Path directory(settings.get<std::string>(GuiSettingsId::IMAGES_PATH));
36  const Path name(settings.get<std::string>(GuiSettingsId::IMAGES_NAME));
37  const Size firstIndex(settings.get<int>(GuiSettingsId::IMAGES_FIRST_INDEX));
38  paths = OutputFile(directory / name, firstIndex);
39 
40  const Path animationName(settings.get<std::string>(GuiSettingsId::IMAGES_MOVIE_NAME));
41  animationPath = directory / animationName;
42 
43  std::call_once(initFlag, wxInitAllImageHandlers);
44  nextOutput = outputStep;
45 }
46 
47 Movie::~Movie() = default;
48 
49 INLINE std::string escapeColorizerName(const std::string& name) {
50  std::string escaped = replaceAll(name, " ", "");
51  escaped = replaceAll(escaped, ".", "_");
52  return lowercase(escaped);
53 }
54 
56 private:
57  std::condition_variable waitVar;
58  std::mutex waitMutex;
59 
60  Path currentPath;
61 
62 
63 public:
64  void setPath(const Path& path) {
65  currentPath = path;
66  }
67 
68  virtual void update(const Bitmap<Rgba>& bitmap, Array<Label>&& labels, const bool isFinal) override {
69  if (!isFinal) {
70  // no need for save intermediate results on disk
71  return;
72  }
73 
74  if (isMainThread()) {
75  this->updateMainThread(bitmap, std::move(labels));
76  } else {
77  std::unique_lock<std::mutex> lock(waitMutex);
78  executeOnMainThread([this, &bitmap, &labels] {
79  std::unique_lock<std::mutex> lock(waitMutex);
80  this->updateMainThread(bitmap, std::move(labels));
81  waitVar.notify_one();
82  });
83  waitVar.wait(lock);
84  }
85  }
86 
87  virtual void update(Bitmap<Rgba>&& bitmap, Array<Label>&& labels, const bool isFinal) override {
88  update(bitmap, std::move(labels), isFinal);
89  }
90 
91 private:
92  void updateMainThread(const Bitmap<Rgba>& bitmap, Array<Label>&& labels) {
94  wxBitmap wx;
95  toWxBitmap(bitmap, wx);
96  wxMemoryDC dc(wx);
97  printLabels(dc, labels);
98  dc.SelectObject(wxNullBitmap);
99  saveToFile(wx, currentPath);
100  }
101 };
102 
103 void Movie::onTimeStep(const Storage& storage, Statistics& stats) {
104  if (!enabled || stats.get<Float>(StatisticsId::RUN_TIME) < nextOutput) {
105  return;
106  }
107 
108  this->save(storage, stats);
109  nextOutput += outputStep;
110 }
111 
112 void Movie::save(const Storage& storage, Statistics& stats) {
113  const Float time = stats.getOr<Float>(StatisticsId::RUN_TIME, 0._f);
114  const Float dt = time - lastFrame;
115 
116  const Vector target = params.camera->getTarget();
117  const Vector cameraPos = params.camera->getFrame().translation();
118  Vector dir = cameraPos - target;
119  dir[H] = 0._f;
120  if (cameraOrbit != 0._f) {
121  const Vector up = params.camera->getUpVector();
122  AffineMatrix rotation = AffineMatrix::rotateAxis(up, cameraOrbit * dt);
123  dir = rotation * dir;
124  }
125 
126  // move the camera (shared for all colorizers)
127  if (params.tracker != nullptr) {
128  Vector trackedPos, trackedVel;
129  tie(trackedPos, trackedVel) = params.tracker->getTrackedPoint(storage);
130  params.camera->setPosition(trackedPos + dir);
131  params.camera->setTarget(trackedPos);
132  } else {
133  params.camera->setTarget(target + dt * cameraVelocity);
134  params.camera->setPosition(target + dir + dt * cameraVelocity);
135  }
136  lastFrame = time;
137 
138  const Path path = paths.getNextPath(stats);
140 
141  MovieRenderOutput output;
142  for (const auto& e : colorizers) {
143  Path actPath(replaceAll(path.native(), "%e", escapeColorizerName(e->name())));
144 
145  // initialize the colorizer
146  e->initialize(storage, RefEnum::WEAK);
147 
148  // initialize render with new data (outside main thread)
149  renderer->initialize(storage, *e, *params.camera);
150 
151  // create the bitmap and save it to file
152  output.setPath(actPath);
153  renderer->render(params, stats, output);
154  }
155 }
156 
158  params.camera = std::move(camera);
159 }
160 
162  if (!makeAnimation) {
163  return;
164  }
165 
166  for (auto& e : colorizers) {
167  std::string name = escapeColorizerName(e->name());
168  std::string outPath = animationPath.native();
169  outPath = replaceAll(outPath, "%e", name);
170  std::string inPath = paths.getMask().native();
171  inPath = replaceAll(inPath, "%e", name);
172  inPath = replaceAll(inPath, "%d", "%04d");
173  // clang-format off
174  Process ffmpeg(Path("/bin/ffmpeg"), {
175  "-y", // override existing files
176  "-nostdin", // don't prompt for confirmation, etc.
177  "-framerate", "25", // 25 FPS
178  "-i", inPath,
179  "-c:v", "libx264", // video codec
180  outPath
181  });
182  // clang-format on
183  ffmpeg.wait();
184  }
185 }
186 
187 void Movie::setEnabled(const bool enable) {
188  enabled = enable;
189 }
190 
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
void saveToFile(const wxBitmap &wx, const Path &path)
Definition: Bitmap.cpp:59
NAMESPACE_SPH_BEGIN void toWxBitmap(const Bitmap< Rgba > &bitmap, wxBitmap &wx)
Definition: Bitmap.cpp:12
Wrapper of wxBitmap, will be possibly replaced by custom implementation.
Defines projection transforming 3D particles onto 2D screen.
bool isMainThread()
Checks if the calling thread is the main thred.
Helper functions to check the internal consistency of the code.
@ MAIN_THREAD
Function can only be executed from main thread.
#define CHECK_FUNCTION(flags)
Definition: CheckFunction.h:40
Object converting quantity values of particles into colors.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
NAMESPACE_SPH_BEGIN void executeOnMainThread(const Function< void()> &function)
Posts a callback to be executed on main thread.
Definition: MainLoop.cpp:8
Posting events to be executed on main thread.
NAMESPACE_SPH_BEGIN std::once_flag initFlag
Definition: Movie.cpp:20
INLINE std::string escapeColorizerName(const std::string &name)
Definition: Movie.cpp:49
Periodically saves rendered images to disk.
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Creating and managing processes.
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Definition: StaticArray.h:281
Statistics gathered and periodically displayed during the run.
@ RUN_TIME
Current time of the simulation in code units. Does not necessarily have to be 0 when run starts.
std::string replaceAll(const std::string &source, const std::string &old, const std::string &s)
Replaces all occurences of string with a new string.
std::string lowercase(const std::string &s)
Converts all uppercase characters to their lowercase variants. Other characters are unchanged.
Definition: StringUtils.cpp:94
void printLabels(wxDC &dc, ArrayView< const IRenderOutput::Label > labels)
Definition: Utils.cpp:186
Random utility functions for drawing stuff to DC.
@ H
Definition: Vector.h:25
INLINE Vector translation() const
Definition: AffineMatrix.h:49
static AffineMatrix rotateAxis(const Vector &axis, const Float angle)
Definition: AffineMatrix.h:159
Generic dynamically allocated resizable storage.
Definition: Array.h:43
INLINE TValue get(const GuiSettingsId id) const
Definition: Settings.h:245
virtual AffineMatrix getFrame() const =0
Returns the transformation matrix converting camera space to world space.
virtual Vector getTarget() const =0
Returns the current target point of the camera.
virtual void setTarget(const Vector &newTarget)=0
virtual void setPosition(const Vector &newPosition)=0
Moves the camera to new position in world space.
virtual Vector getUpVector() const =0
Returns the reference "up" direction of the camera.
virtual void initialize(const Storage &storage, const IColorizer &colorizer, const ICamera &camera)=0
Prepares the objects for rendering and updates its data.
virtual void render(const RenderParams &params, Statistics &stats, IRenderOutput &output) const =0
Draws particles into the bitmap, given the data provided in initialize.
virtual Pair< Vector > getTrackedPoint(const Storage &storage) const =0
void setPath(const Path &path)
Definition: Movie.cpp:64
virtual void update(Bitmap< Rgba > &&bitmap, Array< Label > &&labels, const bool isFinal) override
May be called once after render finishes or multiple times for progressive renderers.
Definition: Movie.cpp:87
virtual void update(const Bitmap< Rgba > &bitmap, Array< Label > &&labels, const bool isFinal) override
May be called once after render finishes or multiple times for progressive renderers.
Definition: Movie.cpp:68
Movie(const GuiSettings &settings, AutoPtr< IRenderer > &&renderer, Array< AutoPtr< IColorizer >> &&colorizers, RenderParams &&params)
Definition: Movie.cpp:22
void onTimeStep(const Storage &storage, Statistics &stats)
Called every time step, saves the images every IMAGES_TIMESTEP.
Definition: Movie.cpp:103
void save(const Storage &storage, Statistics &stats)
Manually saves the images.
Definition: Movie.cpp:112
void setEnabled(const bool enable=true)
Definition: Movie.cpp:187
void finalize()
Creates the animations from generated images.
Definition: Movie.cpp:161
void setCamera(AutoPtr< ICamera > &&camera)
Definition: Movie.cpp:157
Helper file generating file names for output files.
Definition: Output.h:21
Path getNextPath(const Statistics &stats) const
Returns path to the next output file.
Definition: Output.cpp:28
Path getMask() const
Returns the file mask as given in constructor.
Definition: Output.cpp:94
Object representing a path on a filesystem.
Definition: Path.h:17
std::string native() const
Returns the native version of the path.
Definition: Path.cpp:71
Path parentPath() const
Returns the parent directory. If the path is empty or root, return empty path.
Definition: Path.cpp:35
Holds a handle to a created process.
Definition: Process.h:19
void wait()
Blocks the calling thread until the managed process exits. The function may block indefinitely.
Definition: Process.cpp:50
Object holding various statistics about current run.
Definition: Statistics.h:22
TValue get(const StatisticsId idx) const
Returns value of a statistic.
Definition: Statistics.h:88
TValue getOr(const StatisticsId idx, const TValue &other) const
Returns value of a statistic, or a given value if the statistic is not stored.
Definition: Statistics.h:98
Container storing all quantities used within the simulations.
Definition: Storage.h:230
@ IMAGES_NAME
Mask of the image names, having d where the output number will be placed.
@ IMAGES_PATH
Path of directory where the rendered images will be saved.
@ IMAGES_SAVE
If true, rendered images are saved to disk.
Outcome createDirectory(const Path &path, const Flags< CreateDirectoryFlag > flags=CreateDirectoryFlag::ALLOW_EXISTING)
Creates a directory with given path. Creates all parent directories as well.
Definition: FileSystem.cpp:119
Overload of std::swap for Sph::Array.
Definition: Array.h:578
Parameters of the rendered image.
Definition: IRenderer.h:60
AutoPtr< ICamera > camera
Camera used for rendering.
Definition: IRenderer.h:63
AutoPtr< ITracker > tracker
Tracker used for camera motion.
Definition: IRenderer.h:68