scene.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2015-2019 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 // OpenFOAM includes
29 #include "scene.H"
30 #include "Constant.H"
31 
32 // VTK includes
33 #include "vtkCamera.h"
34 #include "vtkCubeSource.h"
35 #include "vtkLightKit.h"
36 #include "vtkPolyDataMapper.h"
37 #include "vtkPNGWriter.h"
38 #include "vtkRenderer.h"
39 #include "vtkRendererCollection.h"
40 #include "vtkRenderWindow.h"
41 #include "vtkWindowToImageFilter.h"
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 void Foam::functionObjects::runTimePostPro::scene::readCamera
46 (
47  const dictionary& dict
48 )
49 {
50  nFrameTotal_ = dict.getCheckOrDefault<label>
51  (
52  "nFrameTotal",
53  1,
55  );
56 
57  if
58  (
59  dict.readCheckIfPresent
60  (
61  "startPosition",
64  )
65  )
66  {
68  }
69 
70  if (nFrameTotal_ > 1)
71  {
72  scalar endPosition = dict.getCheckOrDefault<scalar>
73  (
74  "endPosition",
75  1,
77  );
78 
79  dPosition_ = (endPosition - startPosition_)/scalar(nFrameTotal_ - 1);
80  }
81 
85 
86  dict.readIfPresent("clipBox", clipBox_);
87  parallelProjection_ = dict.getOrDefault("parallelProjection", true);
89  {
90  if (dict.found("viewAngle"))
91  {
93  }
94  else
95  {
96  cameraViewAngle_.reset
97  (
98  new Function1Types::Constant<scalar>("viewAngle", 35.0)
99  );
100  }
101  }
102 
103  if (dict.found("zoom"))
104  {
106  }
107  else
108  {
109  cameraZoom_.reset
110  (
111  new Function1Types::Constant<scalar>("zoom", 1.0)
112  );
113  }
114 }
115 
116 
117 void Foam::functionObjects::runTimePostPro::scene::readColours
118 (
119  const dictionary& dict
120 )
121 {
122  const wordList colours(dict.toc());
123  for (const word& c : colours)
124  {
125  colours_.insert(c, Function1<vector>::New(c, dict));
126  }
127 }
128 
129 
130 void Foam::functionObjects::runTimePostPro::scene::setActorVisibility
131 (
132  vtkRenderer* renderer,
133  const bool visible
134 ) const
135 {
136  if (!renderer) return;
137 
138  vtkActorCollection *actors = renderer->GetActors();
139  for (int i = 0; i < actors->GetNumberOfItems(); ++i)
140  {
141  vtkActor *actor = vtkActor::SafeDownCast(actors->GetItemAsObject(i));
142  actor->SetVisibility(visible);
143  }
144 }
145 
146 
148 (
149  vtkRenderer* renderer,
150  const word& outputName
151 )
152 {
153  currentFrameI_ = 0;
154  position_ = startPosition_;
155 
156  outputName_ = outputName;
157 
158  if (!renderer) return;
159 
160 
161  // Set the background
162  const vector bgColour = colours_["background"]->value(position_);
163 
164  renderer->SetBackground(bgColour.x(), bgColour.y(), bgColour.z());
165 
166  // Apply gradient background if "background2" defined
167  if (colours_.found("background2"))
168  {
169  const vector bg2Colour = colours_["background2"]->value(position_);
170 
171  renderer->GradientBackgroundOn();
172  renderer->SetBackground2(bg2Colour.x(), bg2Colour.y(), bg2Colour.z());
173  }
174  else if (Pstream::parRun())
175  {
176  // Oddly enough we seem a gradient background for parallel rendering,
177  // otherwise the colours look quite funny.
178  // Doesn't seem to matter if we use SetBackground2() though
179 
180  renderer->GradientBackgroundOn();
181  renderer->SetBackground2(bgColour.x(), bgColour.y(), bgColour.z());
182  }
183 
184  // Depth peeling
185  renderer->SetUseDepthPeeling(true);
186  renderer->SetMaximumNumberOfPeels(4);
187  renderer->SetOcclusionRatio(0);
188 
189  // Set the camera
190  auto camera = vtkSmartPointer<vtkCamera>::New();
191  camera->SetParallelProjection(parallelProjection_);
192  renderer->SetActiveCamera(camera);
193 
194  // Add the lights
195  auto lightKit = vtkSmartPointer<vtkLightKit>::New();
196  lightKit->AddLightsToRenderer(renderer);
197 
198  if (!clipBox_.empty())
199  {
200  const point& min = clipBox_.min();
201  const point& max = clipBox_.max();
202  auto clipBox = vtkSmartPointer<vtkCubeSource>::New();
203  clipBox->SetXLength(max.x() - min.x());
204  clipBox->SetYLength(max.y() - min.y());
205  clipBox->SetZLength(max.z() - min.z());
206  clipBox->SetCenter
207  (
208  min.x() + 0.5*(max.x() - min.x()),
209  min.y() + 0.5*(max.y() - min.y()),
210  min.z() + 0.5*(max.z() - min.z())
211  );
212  auto clipMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
213  clipMapper->SetInputConnection(clipBox->GetOutputPort());
214 
215  clipBoxActor_ = vtkSmartPointer<vtkActor>::New();
216  clipBoxActor_->SetMapper(clipMapper);
217  clipBoxActor_->VisibilityOff();
218  renderer->AddActor(clipBoxActor_);
219  }
220 }
221 
222 
224 (
225  vtkRenderer* renderer
226 ) const
227 {
228  if (!renderer) return;
229 
230  vtkCamera* camera = renderer->GetActiveCamera();
231 
232  if (parallelProjection_)
233  {
234  // Restore parallel scale to allow application of zoom (later)
235  camera->SetParallelScale(1);
236  }
237  else
238  {
239  // Restore viewAngle (it might be reset by clipping)
240  camera->SetViewAngle(cameraViewAngle_->value(position_));
241  }
242 
243  const vector up = cameraUp_->value(position_);
244  const vector pos = cameraPosition_->value(position_);
245  const point focalPoint = cameraFocalPoint_->value(position_);
246  const scalar zoom = cameraZoom_->value(position_);
247 
248  camera->SetViewUp(up.x(), up.y(), up.z());
249  camera->SetPosition(pos.x(), pos.y(), pos.z());
250  camera->SetFocalPoint(focalPoint.x(), focalPoint.y(), focalPoint.z());
251 
252 
253  // Apply clipping if required
254  // Note: possible optimisation - if the camera is static, this only needs
255  // to be done once on initialisation
256  if (!clipBox_.empty())
257  {
258  setActorVisibility(renderer, false);
259  clipBoxActor_->VisibilityOn();
260 
261  // Call ResetCamera() to fit clip box in view
262  renderer->ResetCamera();
263 
264  setActorVisibility(renderer, true);
265  clipBoxActor_->VisibilityOff();
266  }
267 
268  // Zoom applied after all other operations
269  camera->Zoom(zoom);
270 
271  camera->Modified();
272 }
273 
274 
277 {
278  string str = Foam::name(currentFrameI_);
279  str.insert(0, 4 - str.length(), '0');
280 
281  return str;
282 }
283 
284 
285 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
286 
287 Foam::functionObjects::runTimePostPro::scene::scene
288 (
289  const objectRegistry& obr,
290  const word& name
291 )
292 :
293  obr_(obr),
294  name_(name),
295  colours_(),
296  cameraPosition_(nullptr),
297  cameraFocalPoint_(nullptr),
298  cameraUp_(nullptr),
299  cameraViewAngle_(nullptr),
300  cameraZoom_(nullptr),
301  clipBox_(boundBox::invertedBox),
302  clipBoxActor_(),
303  parallelProjection_(true),
304  nFrameTotal_(1),
305  startPosition_(0),
306  position_(0),
307  dPosition_(0),
308  currentFrameI_(0),
309  outputName_("unknown")
310 {}
311 
312 
313 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
314 
316 {}
317 
318 
319 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
320 
323 {
324  return colours_;
325 }
326 
327 
329 {
330  return currentFrameI_;
331 }
332 
333 
335 {
336  return position_;
337 }
338 
339 
341 (
342  const dictionary& dict
343 )
344 {
345  readCamera(dict.subDict("camera"));
346  readColours(dict.subDict("colours"));
347 }
348 
349 
351 {
352  static bool initialised = false;
353  setCamera(renderer);
354 
355  if (!initialised)
356  {
357  initialised = true;
358  return true;
359  }
360 
361  if (renderer)
362  {
363 
364  // Ensure that all objects can be seen without clipping
365  // Note: can only be done after all objects have been added!
366  renderer->ResetCameraClippingRange();
367 
368  // Save image from last iteration
369  saveImage(renderer->GetRenderWindow());
370  }
371 
372  ++currentFrameI_;
373 
374  position_ = startPosition_ + currentFrameI_*dPosition_;
375 
376  if (currentFrameI_ < nFrameTotal_)
377  {
378  return true;
379  }
380  else
381  {
382  initialised = false;
383  return false;
384  }
385 }
386 
387 
389 (
390  vtkRenderWindow* renderWindow
391 ) const
392 {
393  if (!renderWindow)
394  {
395  return;
396  }
397 
398  const Time& runTime = obr_.time();
399 
400  const fileName fName
401  (
402  runTime.globalPath()
404  / name_
405  / runTime.timeName()
406  / outputName_ + '.' + frameIndexStr() + ".png"
407  );
408 
409  renderWindow->Render();
410 
411  // Set up off-screen rendering
412  auto windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
413 
414  windowToImageFilter->SetInput(renderWindow);
415 
417  // windowToImageFilter->SetInputBufferTypeToRGBA();
418  windowToImageFilter->SetInputBufferTypeToRGB();
419 
420 // windowToImageFilter->ReadFrontBufferOff();
421  windowToImageFilter->Update();
422 
423  // Save the image
424 
425  if (Pstream::master())
426  {
427  mkDir(fName.path());
428 
430  writer->SetFileName(fName.c_str());
431  writer->SetInputConnection(windowToImageFilter->GetOutputPort());
432 
433  Info<< " Generating image: " << runTime.relativePath(fName) << endl;
434 
435  writer->Write();
436  }
437 }
438 
439 
440 
441 // ************************************************************************* //
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:78
Foam::functionObjects::runTimePostPro::scene::parallelProjection_
bool parallelProjection_
Parallel projection flag.
Definition: scene.H:164
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::functionObjects::runTimePostPro::scene::frameIndex
label frameIndex() const
Return the current frame index.
Definition: scene.C:328
Foam::functionObjects::runTimePostPro::scene::dPosition_
scalar dPosition_
Change in position per frame.
Definition: scene.H:176
Foam::functionObjects::runTimePostPro::scene::read
void read(const dictionary &dict)
Definition: scene.C:341
Foam::boundBox::invertedBox
static const boundBox invertedBox
A large inverted boundBox: min/max == +/- ROOTVGREAT.
Definition: boundBox.H:86
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::dimensioned::value
const Type & value() const
Return const reference to value.
Definition: dimensionedType.C:404
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:73
Foam::functionObjects::runTimePostPro::scene::loop
bool loop(vtkRenderer *renderer)
Main control loop.
Definition: scene.C:350
Foam::functionObjects::runTimePostPro::scene::cameraZoom_
autoPtr< Function1< scalar > > cameraZoom_
Zoom: 1 = do nothing, >1 = zoom in, <1 = zoom out.
Definition: scene.H:152
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:90
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::functionObjects::runTimePostPro::scene::frameIndexStr
string frameIndexStr() const
Definition: scene.C:276
scene.H
Foam::functionObjects::runTimePostPro::scene::saveImage
void saveImage(vtkRenderWindow *renderWindow) const
Save image to file.
Definition: scene.C:389
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:59
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::functionObjects::runTimePostPro::scene::initialise
void initialise(vtkRenderer *renderer, const word &outputName)
Definition: scene.C:148
Foam::functionObjects::runTimePostPro::scene::cameraViewAngle_
autoPtr< Function1< scalar > > cameraViewAngle_
View angle.
Definition: scene.H:147
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::functionObjects::runTimePostPro::scene::position_
scalar position_
Position [0-1].
Definition: scene.H:173
Foam::functionObjects::runTimePostPro::scene::cameraPosition_
autoPtr< Function1< point > > cameraPosition_
Position.
Definition: scene.H:138
Foam::functionObjects::runTimePostPro::scene::setCamera
void setCamera(vtkRenderer *renderer) const
Definition: scene.C:224
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::functionObjects::runTimePostPro::scene::clipBox_
boundBox clipBox_
Clipping box.
Definition: scene.H:158
Foam::MinMax< scalar >::zero_one
static MinMax< scalar > zero_one()
A 0-1 range corresponding to the pTraits zero, one.
Definition: MinMaxI.H:45
Foam::functionObject::outputPrefix
static word outputPrefix
Directory prefix.
Definition: functionObject.H:259
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::functionObjects::runTimePostPro::scene::colours
const HashPtrTable< Function1< vector > > & colours() const
Return the colours.
Definition: scene.C:322
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::writer
Base class for graphics format writing. Entry points are.
Definition: writer.H:80
Foam::functionObjects::runTimePostPro::scene::~scene
virtual ~scene()
Destructor.
Definition: scene.C:315
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:84
Foam::functionObjects::runTimePostPro::scene::nFrameTotal_
label nFrameTotal_
Number of frames.
Definition: scene.H:167
Foam::HashPtrTable
A HashTable of pointers to objects of type <T>.
Definition: HashPtrTable.H:54
Foam::MinMax::ge
static MinMax< T > ge(const T &minVal)
A semi-infinite range from minVal to the type max.
Definition: MinMaxI.H:31
Foam::Vector< scalar >
Foam::functionObjects::runTimePostPro::scene::cameraUp_
autoPtr< Function1< vector > > cameraUp_
Up direction.
Definition: scene.H:144
Foam::functionObjects::runTimePostPro::scene::cameraFocalPoint_
autoPtr< Function1< point > > cameraFocalPoint_
Focal point.
Definition: scene.H:141
Foam::functionObjects::runTimePostPro::scene::startPosition_
scalar startPosition_
Start position [0-1].
Definition: scene.H:170
Foam::functionObjects::runTimePostPro::scene::position
scalar position() const
Return the current position (in range 0-1)
Definition: scene.C:334
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Constant.H
Foam::Function1::New
static autoPtr< Function1< Type > > New(const word &entryName, const dictionary &dict, const word &redirectType=word::null)
Selector.
Definition: Function1New.C:35
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177