-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRendering.tex
882 lines (717 loc) · 39.1 KB
/
Rendering.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
%-*- latex -*-
\chapter{Rendering}
\label{chap:Rendering}
\index{rendering|(}
Rendering, the generation of images from data, is a key component to visualization.
To assist with rendering, VTK-m provides a rendering package to produce imagery from data, which is located in the \vtkmrendering{} namespace.
The rendering package in VTK-m is not intended to be a fully featured
rendering system or library. Rather, it is a lightweight rendering package
with two primary use cases:
\begin{enumerate}
\item New users getting started with VTK-m need a ``quick and dirty''
render method to see their visualization results.
\item In situ visualization that integrates VTK-m with a simulation or
other data-generation system might need a lightweight rendering method.
\end{enumerate}
Both of these use cases require just a basic rendering platform. Because
VTK-m is designed to be integrated into larger systems, it does not aspire
to have a fully featured rendering system.
\begin{didyouknow}
VTK-m's big sister toolkit VTK is already integrated with VTK-m and has
its own fully featured rendering system. If you need more rendering
capabilities than what VTK-m provides, you can leverage VTK instead.
\end{didyouknow}
\section{Creating a Rendering Canvas}
\label{sec:Canvas}
\index{rendering!canvas|(}
\index{canvas|(}
The first step in using VTK-m's rendering package is to create a
\keyterm{canvas}, which is managed by \vtkmrendering{Canvas} and its
subclasses. The \textidentifier{Canvas} object manages the frame buffers
and the rendering context.
Subclasses of \textidentifier{Canvas} establish a context for different
rendering systems. Currently, there are two main subclasses: one for using
OpenGL rendering (\vtkmrendering{CanvasGL}) and one for using built in
ray tracing (\vtkmrendering{CanvasRayTracer}).
\subsection{Creating an OpenGL Context with GLUT}
\index{rendering!GLUT|(}
\index{rendering!OpenGL|(}
\index{canvas!GLUT|(}
\index{canvas!OpenGL|(}
\index{GLUT|(}
\index{OpenGL|(}
One feature that is notably (and intentionally) missing from the VTK-m
rendering package is the ability to open a rendering window or build a
graphical user interface. However, VTK-m can use an OpenGL context
established elsewhere to perform rendering. OpenGL is a widely-accepted
rendering library supported by all hardware vendors on pretty much all
computing platforms. It is also extensively used by many applications
performing rendering, particularly scientific visualization applications.
Once an OpenGL rendering context is established, it can be used by VTK-m by
simply creating a \vtkmrendering{CanvasGL}. When created,
\textidentifier{CanvasGL} will find the current OpenGL context, query its
size, and ready the VTK-m rendering system to use it.
Unfortunately, creating a window with an OpenGL context is platform
dependent. There are numerous libraries available that provide the ability
to create an OpenGL window that have been ported to many platforms (such as
MS Windows, Unix, and Mac OSX). One such library is \keyterm{GLUT}.
GLUT is a very simple utility toolkit that provides a basic mechanism for
creating a window with an OpenGL context. It additionally provides simple
user interface features to capture keystrokes and mouse movements. For the
purposes of demonstration, we will provide examples that use GLUT to make a
simple interactive rendering application.
\begin{didyouknow}
We are demonstrating rendering with GLUT for illustrative purposes only.
VTK-m is not directly associated with GLUT: It neither comes with GLUT
nor depends on GLUT. You are welcome to follow these boilerplate
examples, or you can integrate with another rendering system of your
choosing.
\end{didyouknow}
This section provides a terse description of getting a GLUT application up
and running. This is not meant to be a thorough description of the GLUT
library. There are other resources that document using the GLUT API, the
most complete of which is the book \emph{OpenGL Programming for the X
Window System} by Mark J. Kilgard. The information provided here is just
enough to get you started.
\begin{commonerrors}
Although distributed for free, the original GLUT library was not released
as open source. Unfortunately, the GLUT copyright holders are not as
actively developing GLUT as they once were, and consequently some systems
are declaring GLUT as deprecated. However, there some newer projects like
FreeGLUT and OpenGLUT that are open source, that are being more actively
developed, and that are drop in replacements to the original GLUT
library. There are also alternative libraries such as GLFW that have
similar capabilities but a different API. These are not documented here,
but are worth investigating if GLUT does not work for you.
\end{commonerrors}
The first call made to the GLUT library should be to the function
\textcode{glutInit}, which takes as arguments the \textcode{argc} and
\textcode{argv} arguments passed to the \textcode{main} C function.
\textcode{glutInit} will find any window-system specific flags (such as
\textcode{-display}), use them to initialize the windowing system, and
strip them from the arguments.
Next, the parameters for the window to be created should be established.
The function \textcode{glutInitWindowSize} takes the width and the height
of the renderable space in the window. The function
\textcode{glutInitDisplayMode} takes a mask of flags that are or-ed
together to specify the capabilities of the window. We recommend the flags
\textcode{GLUT\_RGBA}, \textcode{GLUT\_DOUBLE}, \textcode{GLUT\_ALPHA}, and
\textcode{GLUT\_DEPTH}. Once these are specified a call to
\textcode{glutCreateWindow} will create a window and initialize the OpenGL
context. \textcode{glutCreateWindow} takes a string for an argument that is
used in the title bar of the window.
\vtkmlisting{Initializing the GLUT library and creating a window to render into.}{InitializeGlut.cxx}
\index{GLUT!callbacks|(}
Apart from the initial setup, most of the interaction with the GLUT
library happens through callbacks. As part of its initialization, an
application provides function pointers to GLUT. GLUT then calls these
provided functions when certain events happen. GLUT supports many callbacks
for different types of events. Here is the small set of callbacks we use in
our small example.
\begin{description}
\item[\textcode{glutDisplayFunc}] The display function is called when the
window needs to be redrawn. The callback should issue the appropriate
OpenGL rendering calls and then call \textcode{glutSwapBuffers} to show
the result.
\item[\textcode{glutReshapeFunc}] The reshape function is called whenever
the window is resized. The callback is given the width and height of the
new rendering window.
\item[\textcode{glutMouseFunc}] The mouse button function is called
whenever a mouse button is pressed or released. The GLUT system gives the
index of the button, the state the button changed to
(\textcode{GLUT\_DOWN} or \textcode{GLUT\_UP}) and the pixel location of
the event.
\item[\textcode{glutMotionFunc}] The mouse motion function is called
whenever the mouse is moved while any button is pressed. The callback is
given the pixel location to where the mouse moved to, but not the state
of any of the buttons. If the button state is important, it must be
preserved in a global variable. If the mouse motion should result in a
change in the rendered view, the function should call
\textcode{glutPostRedisplay}, which will tell GLUT to call the display
function when the windowing system is ready.
\item[\textcode{glutKeygboardFunc}] The keyboard function is called
whenever a regular key is pressed. The callback is given the character of
the key pressed as well as the pixel location of the mouse when the key
was pressed. If the key press should result in a change in the rendered
view, the function should call \textcode{glutPostRedisplay}, which will
tell GLUT to call the display function when the windowing system is
ready.
\end{description}
\begin{didyouknow}
There are many other GLUT callbacks not documented here. Consult the GLUT
documentation for more information.
\end{didyouknow}
\vtkmlisting{Registering callbacks with GLUT.}{InitializeGlutCallbacks.cxx}
\index{GLUT!callbacks|)}
Once the GLUT library is initialized, the rendering window created, and all
the necessary callbacks are registered, call \textcode{glutMainLoop}. This
causes GLUT to enter its main event loop where it will manage the windowing
system. \textcode{glutMainLoop} will never return. Rather, it will continue
to respond to events and invoke the callbacks until the program is
otherwise interrupted.
Example~\ref{ex:BasicGlut} puts this all together to give a full example of
a simple GLUT program rendering with VTK-m. The output of the program is
shown in Figure~\ref{fig:BasicGlut}. The examples of the GLUT callbacks are
straightforward. The VTK-m rendering classes used are documented in the
following sections.
\vtkmlisting[ex:BasicGlut]{A simple but full example of an application using GLUT and VTK-m together.}{BasicGlut.cxx}
\begin{figure}[htb]
\centering
\includegraphics[width=4in]{images/BasicGlut}
\caption{Output of the rendering program listed in
Example~\ref{ex:BasicGlut}.}
\label{fig:BasicGlut}
\end{figure}
\index{OpenGL|)}
\index{GLUT|)}
\index{canvas!OpenGL|)}
\index{canvas!GLUT|)}
\index{rendering!OpenGL|)}
\index{rendering!GLUT|)}
\subsection{Creating an Off Screen Rendering Canvas}
\index{rendering!off screen|(}
\index{canvas!off screen|(}
\index{off screen|(}
Another use case for rendering in VTK-m is rendering to an off screen
buffer. This is the preferred method when doing automated visualization
such as when running visualization in situ with a simulation. VTK-m comes
built in with multiple methods to create off screen rendering contexts.
There are multiple subclasses to \vtkmrendering{Canvas} that, when
constructed, create their own rendering contexts, so can be used
immediately. All of these classes take as parameters to their constructors
the width and height of the image to create.
The following classes, when constructed, create an off screen rendering
buffer.
\begin{description}
\item[\vtkmrendering{CanvasEGL}]
\index{rendering!EGL} \index{canvas!EGL} \index{EGL}
Creates an off screen OpenGL rendering buffer using EGL.
EGL provides an interface to create a context for OpenGL rendering software without engaging the operating-system-specific windowing system.
For this to be available, \VTKm must have been configured to use the EGL library.
\item[\vtkmrendering{CanvasOSMesa}] \index{rendering!OSMesa}
\index{canvas!OSMesa} \index{OSMesa} Creates an off screen OpenGL
rendering buffer using the OSMesa library. For this to be available,
VTK-m must have been configured to use the OSMesa library. Also, be aware
that OSMesa contexts do not use GPU hardware.
\item[\vtkmrendering{CanvasRayTracer}] \index{rendering!ray tracing}
\index{canvas!ray tracing} \index{ray tracing!canvas} Creates the frame
buffers required for ray tracing. When invoking this canvas, you must use
other ray tracing component where applicable. OpenGL rendering does not
work with the \textidentifier{CanvasRayTracer}.
\end{description}
\index{canvas!off screen!saving}
\index{off screen!saving}
By their nature, when writing to an off screen canvas, you cannot directly
see the result. Typically, programs using off screen rendering save
rendered images as files to be viewed later. For convenience,
\textidentifier{Canvas} has a method named \textcode{SaveAs} that will
write the contents of the last saved image to a file. The files are written
in \index{portable pixel map}\index{PPM}portable pixel map (PPM) format,
which are also valid \index{portable anymap format}\index{PNM}portable
anymap format (PNM) files. This is a very simple format that is easy to
read and write. PPM files are supported by the
ImageMagick\footnote{\url{http://imagemagick.org}} software suite as well
as many other image software tools.
\vtkmlisting{Saving an image rendered in a \textidentifier{Canvas} to a file.}{SaveCanvasImage.cxx}
Alternately, the rendered image can be retrieved directly from the
\textidentifier{Canvas} by first calling the \textcode{RefreshColorBuffer}
method and then calling \textcode{GetColorBuffer}. This retrieves the raw
image data as a \vtkmcont{ArrayHandle}. \textidentifier{ArrayHandle}s are
documented later in Chapter~\ref{chap:ArrayHandle}.
\index{off screen|)}
\index{canvas!off screen|)}
\index{rendering!off screen|)}
\index{canvas|)}
\index{rendering!canvas|)}
\section{Scenes and Actors}
\label{sec:Scene}
\label{sec:Actor}
\index{rendering!actor|(}
\index{actor|(}
The primary intent of the rendering package in VTK-m is to visually display
the data that is loaded and processed. Data are represented in VTK-m by
\vtkmcont{DataSet} objects. \textidentifier{DataSet} is presented in
Chapters \ref{chap:FileIO} and \ref{chap:ProvidedFilters}. For now we treat
\textidentifier{DataSet} mostly as an opaque object that can be passed
around readers, writers, filters, and rendering units. Detailed
documentation for \textidentifier{DataSet} is provided in
Chapter~\ref{chap:DataSet}.
To render a \textidentifier{DataSet}, the data are wrapped in a
\vtkmrendering{Actor} class. The \textidentifier{Actor} holds the
components of the \textidentifier{DataSet} to render (a cell set, a
coordinate system, and a field). A color table can also be optionally be
specified, but a default color table will be specified otherwise.
\index{actor|)}
\index{rendering!actor|)}
\index{rendering!scene|(}
\index{scene|(}
\textidentifier{Actor}s are collected together in an object called
\vtkmrendering{Scene}. An \textidentifier{Actor} is added to a
\textidentifier{Scene} with the \textcode{AddActor} method. The following
example demonstrates creating a \textidentifier{Scene} with one
\textidentifier{Actor}.
\index{scene|)}
\index{rendering!scene|)}
\vtkmlisting{Creating an \textidentifier{Actor} and adding it to a \textidentifier{Scene}.}{ActorScene.cxx}
\section{Mappers}
\label{sec:Mapper}
\index{rendering!mapper|(}
\index{mapper|(}
A \keyterm{mapper} is a unit that converts data (managed by an
\textidentifier{Actor}) and issues commands to the rendering subsystem to
generate images. All mappers in VTK-m are a subclass of
\vtkmrendering{Mapper}. Different rendering systems (as established by the
\textidentifier{Canvas}) often require different mappers. Also, different
mappers could render different types of data in different ways. For
example, one mapper might render polygonal surfaces whereas another might
render polyhedra as a translucent volume. Thus, a mapper should be picked
to match both the rendering system of the \textidentifier{Canvas} and the
data in the \textidentifier{Actor}.
The following mappers are provided by VTK-m.
\begin{description}
\item[\vtkmrendering{MapperGL}] Uses OpenGL to render surfaces. If the data
contain polyhedra, then their faces are rendered.
\textidentifier{MapperGL} only works in conjunction with
\textidentifier{CanvasGL} or one of its subclasses.
\item[\vtkmrendering{MapperRayTracer}] Uses VTK-m's built in ray tracing
system to render the visible surface of a mesh.
\textidentifier{MapperRayTracer} only works in conjunction with
\textidentifier{CanvasRayTracer}.
\item[\vtkmrendering{MapperVolume}] Uses VTK-m's built in ray tracing
system to render polyhedra as a translucent volume.
\textidentifier{MapperVolume} only works in conjunction with
\textidentifier{CanvasRayTracer}.
\end{description}
\index{mapper|)}
\index{rendering!mapper|)}
\section{Views}
\label{sec:View}
\index{rendering!view|(}
\index{view|(}
A \keyterm{view} is a unit that collects all the structures needed to
perform rendering. It contains everything needed to take a
\textidentifier{Scene} (Section~\ref{sec:Scene}) and use a
\textidentifier{Mapper} (Section~\ref{sec:Mapper}) to render it onto a
\textidentifier{Canvas} (Section~\ref{sec:Canvas}). The view also annotates
the image with spatial and scalar properties.
The base class for all views is \vtkmrendering{View}.
\textidentifier{View} is an abstract class, and you must choose one of the three provided subclasses, \vtkmrendering{View3D}, \vtkmrendering{View2D}, and \vtkmrendering{View3D}, depending on the type of data being presented.
All three view classes take a \textidentifier{Scene}, a \textidentifier{Mapper}, and a \textidentifier{Canvas} as arguments to their constructor.
\vtkmlisting[ex:ConstructView]{Constructing a \textidentifier{View}.}{ConstructView.cxx}
\index{color}
The \textidentifier{View} constructors also take an optional fourth
argument for the background color. The background color (like other colors)
is specified using the \vtkmrendering{Color} helper class, which manages
the red, green, and blue color channels as well as an optional alpha
channel. These channel values are given as floating point values between 0
and 1.
\vtkmlisting{Creating a \textidentifier{View} with a background color.}{ViewBackgroundColor.cxx}
Once the \textidentifier{View} is created but before it is used to render,
the \textcode{Initialize} method should be called. This is demonstrated in
Example~\ref{ex:ConstructView}.
Once the \textcode{Initialize} method is called, the \textidentifier{View}
is ready to render the scene. This happens by calling the \textcode{Paint}
method, which will render the data into the contained canvas. When using
GLUT, as in Example~\ref{ex:BasicGlut}, or with most other GUI-based
systems, \textcode{Paint} is called in the display callback.
\vtkmlisting{Using \textidentifier{Canvas}\textcode{::Paint} in a display callback.}{PaintView.cxx}
\index{view|)}
\index{rendering!view|)}
\section{Manipulating the Camera}
\index{rendering!camera|(}
\index{camera|(}
The \vtkmrendering{View} uses an object called \vtkmrendering{Camera} to
describe the vantage point from which to draw the geometry. The camera can
be retrieved from the \textidentifier{View}'s \textcode{GetCamera} method.
That retrieved camera can be directly manipulated or a new camera can be
provided by calling \textcode{SetCamera} on the \textidentifier{View}.
A \textidentifier{Camera} operates in one of two major modes: 2D mode or 3D
mode. 2D mode is designed for looking at flat geometry (or close to flat
geometry) that is parallel to the x-y plane. 3D mode provides the freedom
to place the camera anywhere in 3D space. The different modes can be set
with \textcode{SetModeTo2D} and \textcode{SetModeTo3D}, respectively. The
interaction with the camera in these two modes is very different.
\subsection{2D Camera Mode}
\index{rendering!camera!2D|(}
\index{camera!2D|(}
The 2D camera is restricted to looking at some region of the x-y plane.
\subsubsection{View Range}
\index{rendering!camera!view range|(}
\index{camera!view range|(}
The vantage point of a 2D camera can be specified by simply giving the
region in the x-y plane to look at. This region is specified by calling
\textcode{SetViewRange2D} on \textidentifier{Camera}. This method takes the
left, right, bottom, and top of the region to view. Typically these are set
to the range of the geometry in world space as shown in
Figure~\ref{fig:CameraViewRange2D}.
\begin{figure}[htb]
\centering
\includegraphics{images/CameraViewRange2D}
\caption{The view range bounds to give a \textidentifier{Camera}.}
\label{fig:CameraViewRange2D}
\end{figure}
There are 3 overloaded versions of the \textcode{SetViewRange2D} method.
The first version takes the 4 range values, left, right, bottom, and top,
as separate arguments in that order. The second version takes two
\vtkm{Range} objects specifying the range in the x and y directions,
respectively. The third version trakes a single \vtkm{Bounds} object, which
completely specifies the spatial range. (The range in z is ignored.) The
\textidentifier{Range} and \textidentifier{Bounds} objects are documented
later in Sections \ref{sec:Range} and \ref{sec:Bounds}, respectively.
\index{camera!view range|)}
\index{rendering!camera!view range|)}
\subsubsection{Pan}
\index{rendering!camera!pan|(}
\index{camera!pan|(}
A camera pan moves the viewpoint left, right, up, or down. A camera pan is
performed by calling the \textcode{Pan} method on \textidentifier{Camera}.
\textcode{Pan} takes two arguments: the amount to pan in x and the amount
to pan in y.
The pan is given with respect to the projected space. So a pan of $1$ in
the x direction moves the camera to focus on the right edge of the image
whereas a pan of $-1$ in the x direction moves the camera to focus on the
left edge of the image. When using \textcode{Pan} to respond to mouse
movements, a natural pan will divide the distance traveled by the mouse
pointer by the width and height of the screen as demonstrated in the
following example.
\vtkmlisting{Pan the view based on mouse movements.}{MousePan.cxx}
\index{camera!pan|)}
\index{rendering!camera!pan|)}
\subsubsection{Zoom}
\index{rendering!camera!zoom|(}
\index{camera!zoom|(}
A camera zoom draws the geometry larger or smaller. A camera zoom is
performed by calling the \textcode{Zoom} method on \textidentifier{Camera}.
\textcode{Zoom} takes a single argument specifying the zoom factor. A
positive number draws the geometry larger (zoom in), and larger zoom factor
results in larger geometry. Likewise, a negative number draws the geometry
smaller (zoom out). A zoom factor of 0 has no effect.
When using \textcode{Zoom} to respond to mouse movements, a natural zoom
will divide the distance traveled by the mouse pointer by the width or
height of the screen as demonstrated in the following example.
\vtkmlisting{Zoom the view based on mouse movements.}{MouseZoom.cxx}
\index{camera!zoom|)}
\index{rendering!camera!zoom|)}
\index{camera!2D|)}
\index{rendering!camera!2D|)}
\subsection{3D Camera Mode}
\index{rendering!camera!3D|(}
\index{camera!3D|(}
The 3D camera is a free-form camera that can be placed anywhere in 3D space
and can look in any direction. The projection of the 3D camera is based on
the \index{pinhole camera}\index{camera!pinhole} pinhole camera model in
which all viewing rays intersect a single point. This single point is the
camera's position.
\subsubsection{Position and Orientation}
\index{rendering!camera!position}
\index{camera!position}
\index{rendering!camera!look at}
\index{camera!look at}
\index{look at}
\index{rendering!camera!focal point}
\index{camera!focal point}
\index{focal point}
The position of the camera, which is the point where the observer is
viewing the scene, can be set with the \textcode{SetPosition} method of
\textidentifier{Camera}. The direction the camera is facing is specified by
giving a position to focus on. This is called either the ``look at'' point
or the focal point and is specified with the \textcode{SetLookAt} method of
\textidentifier{Camera}. Figure~\ref{fig:CameraPositionOrientation3D} shows
the relationship between the position and look at points.
\begin{figure}[htb]
\centering
\includegraphics{images/CameraPositionOrientation}
\caption{The position and orientation parameters for a
\textidentifier{Camera}.}
\label{fig:CameraPositionOrientation3D}
\end{figure}
\index{rendering!camera!view up}
\index{rendering!camera!up}
\index{camera!view up}
\index{camera!up}
\index{view up}
In addition to specifying the direction to point the camera, the camera
must also know which direction is considered ``up.'' This is specified with
the view up vector using the \textcode{SetViewUp} method in
\textidentifier{Camera}. The view up vector points from the camera position
(in the center of the image) to the top of the image. The view up vector in
relation to the camera position and orientation is shown in
Figure~\ref{fig:CameraPositionOrientation3D}.
\index{rendering!camera!field of view}
\index{camera!field of view}
\index{field of view}
Another important parameter for the camera is its field of view. The field
of view specifies how wide of a region the camera can see. It is specified
by giving the angle in degrees of the cone of visible region emanating from
the pinhole of the camera to the \textcode{SetFieldOfView} method in the
\textidentifier{Camera}. The field of view angle in relation to the camera
orientation is shown in Figure~\ref{fig:CameraPositionOrientation3D}. A
field of view angle of $60^{\circ}$ usually works well.
\index{rendering!camera!clipping range}
\index{camera!clipping range}
\index{clipping range}
\index{rendering!camera!near clip plane}
\index{camera!near clip plane}
\index{near clip plane}
\index{rendering!camera!far clip plane}
\index{camera!far clip plane}
\index{far clip plane}
Finally, the camera must specify a clipping region that defines the valid
range of depths for the object. This is a pair of planes parallel to the
image that all visible data must lie in. Each of these planes is defined
simply by their distance to the camera position. The near clip plane is
closer to the camera and must be in front of all geometry. The far clip
plane is further from the camera and must be behind all geometry. The
distance to both the near and far planes are specified with the
\textcode{SetClippingRange} method in \textidentifier{Camera}.
Figure~\ref{fig:CameraPositionOrientation3D} shows the clipping planes in
relationship to the camera position and orientation.
\vtkmlisting{Directly setting \protect\vtkmrendering{Camera} position and orientation.}{CameraPositionOrientation.cxx}
\subsubsection{Movement}
In addition to specifically setting the position and orientation of the
camera, \vtkmrendering{Camera} contains several convenience methods that
move the camera relative to its position and look at point.
\index{rendering!camera!elevation}
\index{camera!elevation}
\index{elevation}
\index{rendering!camera!azimuth}
\index{camera!azimuth}
\index{azimuth}
Two such methods are elevation and azimuth, which move the camera around
the sphere centered at the look at point. \textcode{Elevation} raises or
lowers the camera. Positive values raise the camera up (in the direction of
the view up vector) whereas negative values lower the camera down.
\textcode{Azimuth} moves the camera around the look at point to the left or
right. Positive values move the camera to the right whereas negative values
move the camera to the left. Both \textcode{Elevation} and
\textcode{Azimuth} specify the amount of rotation in terms of degrees.
Figure~\ref{fig:CameraMovement} shows the relative movements of
\textcode{Elevation} and \textcode{Azimuth}.
\begin{figure}[htb]
\centering
\includegraphics{images/CameraMovement}
\caption{\textidentifier{Camera} movement functions relative to position
and orientation.}
\label{fig:CameraMovement}
\end{figure}
\vtkmlisting{Moving the camera around the look at point.}{CameraMovement.cxx}
\begin{commonerrors}
The \textcode{Elevation} and \textcode{Azimuth} methods change the
position of the camera, but not the view up vector. This can cause some
wild camera orientation changes when the direction of the camera view is
near parallel to the view up vector, which often happens when the
elevation is raised or lowered by about 90 degrees.
\end{commonerrors}
In addition to rotating the camera around the look at point, you can move
the camera closer or further from the look at point. This is done with the
\textcode{Dolly} method. The \textcode{Dolly} method takes a single value
that is the factor to scale the distance between camera and look at point.
Values greater than one move the camera away, values less than one move the
camera closer. The direction of dolly movement is shown in
Figure~\ref{fig:CameraMovement}.
Finally, the \textcode{Roll} method rotates the camera around the viewing
direction. It has the effect of rotating the rendered image. The
\textcode{Roll} method takes a single value that is the angle to rotate in
degrees. The direction of roll movement is shown in
Figure~\ref{fig:CameraMovement}.
\subsubsection{Interactive Rotations}
\index{rendering!camera!mouse|(}
\index{camera!mouse|(}
\index{mouse rotation|(}
A common and important mode of interaction with 3D views is to allow the
user to rotate the object under inspection by dragging the mouse. To
facilitate this type of interactive rotation, \vtkmrendering{Camera}
provides a convenience method named \textcode{TrackballRotate}. The
\textcode{TrackballRotate} method takes a start and end position of the
mouse on the image and rotates viewpoint as if the user grabbed a point on
a sphere centered in the image at the start position and moved under the
end position.
The \textcode{TrackballRotate} method is typically called from within a
mouse movement callback. The callback must record the pixel position from
the last event and the new pixel position of the mouse. Those pixel
positions must be normalized to the range -1 to 1 where the position
(-1,-1) refers to the lower left of the image and (1,1) refers to the upper
right of the image. The following example demonstrates the typical
operations used to establish rotations when dragging the mouse.
\vtkmlisting{Interactive rotations through mouse dragging with \textidentifier{Camera}\textcode{::TrackballRotate}.}{MouseRotate.cxx}
\index{mouse rotation|)}
\index{camera!mouse|)}
\index{rendering!camera!mouse|)}
\subsubsection{Pan}
\index{rendering!camera!pan|(}
\index{camera!pan|(}
A camera pan moves the viewpoint left, right, up, or down. A camera pan is
performed by calling the \textcode{Pan} method on \textidentifier{Camera}.
\textcode{Pan} takes two arguments: the amount to pan in x and the amount
to pan in y.
The pan is given with respect to the projected space. So a pan of $1$ in
the x direction moves the camera to focus on the right edge of the image
whereas a pan of $-1$ in the x direction moves the camera to focus on the
left edge of the image. When using \textcode{Pan} to respond to mouse
movements, a natural pan will divide the distance traveled by the mouse
pointer by the width and height of the screen as demonstrated in the
following example.
\vtkmlisting{Pan the view based on mouse movements.}{MousePan.cxx}
\textcode{Pan} operates in image space, not world space. Panning does not
change the camera position or orientation. Thus the look at point will be
off center with respect to the image.
\index{camera!pan|)}
\index{rendering!camera!pan|)}
\subsubsection{Zoom}
\index{rendering!camera!zoom|(}
\index{camera!zoom|(}
A camera zoom draws the geometry larger or smaller. A camera zoom is
performed by calling the \textcode{Zoom} method on \textidentifier{Camera}.
\textcode{Zoom} takes a single argument specifying the zoom factor. A
positive number draws the geometry larger (zoom in), and larger zoom factor
results in larger geometry. Likewise, a negative number draws the geometry
smaller (zoom out). A zoom factor of 0 has no effect.
When using \textcode{Zoom} to respond to mouse movements, a natural zoom
will divide the distance traveled by the mouse pointer by the width or
height of the screen as demonstrated in the following example.
\vtkmlisting{Zoom the view based on mouse movements.}{MouseZoom.cxx}
\textcode{Zoom} operates in image space, not world space. Zooming differs
from \textcode{Dolly} in that the reported position of the camera does not
change. Instead, the image gets magnified or shrunk.
\index{camera!zoom|)}
\index{rendering!camera!zoom|)}
\index{camera!3D|)}
\index{rendering!camera!3D|)}
\index{camera|)}
\index{rendering!camera|)}
\index{rendering|)}
\subsubsection{Reset}
\index{rendering!camera!reset|(}
\index{camera!reset|(}
Setting a specific camera position and orientation can be frustrating,
particularly when the size, shape, and location of the geometry is not
known a priori. Typically this involves querying the data and finding a
good camera orientation.
To make this process simpler, \vtkmrendering{Camera} has a convenience
method named \textcode{ResetToBounds} that automatically positions the
camera based on the spatial bounds of the geometry. The most expedient
method to find the spatial bounds of the geometry being rendered is to get
the \vtkmrendering{Scene} object and call \textcode{GetSpatialBounds}. The
\textidentifier{Scene} object can be retrieved from the
\vtkmrendering{View}, which, as described in Section~\ref{sec:View}, is the
central object for managing rendering.
\vtkmlisting{Resetting a \textidentifier{Camera} to view geometry.}{ResetCamera.cxx}
The \textcode{ResetToBounds} method operates by placing the look at point
in the center of the bounds and then placing the position of the camera
relative to that look at point. The position is such that the view
direction is the same as before the call to \textcode{ResetToBounds} and
the distance between the camera position and look at point has the bounds
roughly fill the rendered image. This behavior is a convenient way to
update the camera to make the geometry most visible while still preserving
the viewing position. If you want to reset the camera to a new viewing
angle, it is best to set the camera to be pointing in the right direction
and then calling \textcode{ResetToBounds} to adjust the position.
\vtkmlisting{Resetting a \textidentifier{Camera} to be axis aligned.}{AxisAlignedCamera.cxx}
\index{camera!reset|)}
\index{rendering!camera!reset|)}
\section{Color Tables}
\label{sec:ColorTables}
\index{rendering!color tables|(}
\index{color tables|(}
\index{pseudocolor}
An important feature of VTK-m's rendering units is the ability to
pseudocolor objects based on scalar data. This technique maps each scalar
to a potentially unique color. This mapping from scalars to colors is
defined by a \vtkmrendering{ColorTable} object. A
\textidentifier{ColorTable} can be specified as an optional argument when
constructing a \vtkmrendering{Actor}. (Use of \textidentifier{Actor}s is
discussed in Section~\ref{sec:Actor}.)
\vtkmlisting{Specifying a \textidentifier{ColorTable} for an \textidentifier{Actor}.}{SpecifyColorTable.cxx}
The easiest way to create a \textidentifier{ColorTable} is to provide the
name of one of the many predefined sets of color provided by VTK-m. A list
of all available predefined color tables is provided below.
% Insert an inline table
\newlength{\fontdrop} % Set length to drop below baseline so that
\settodepth{\fontdrop}{()} % we can drop the image to fill the actual line
\newcommand*{\includecolortable}[1]{%
\raisebox{-\fontdrop}{\includegraphics[height=10pt,width=1in]{images/ColorTables/#1}}%
}
\newcommand*{\ctcolumns}[1]{%
\includecolortable{#1} & #1 & %
}
\begin{longtabu} to \textwidth {llX}
\ctcolumns{cool2warm} A color table designed to be perceptually even, to
work well on shaded 3D surfaces, and to generally perform well across
many uses. This is also the default color map and will be used if no
\textidentifier{ColorTable} is given to an \textidentifier{Actor} or if
``default'' is specified. % \index{rendering!color tables!default}
\index{color tables!default} \\
\ctcolumns{blue} A monochromatic blue color map. \\
\ctcolumns{orange} A monochromatic orange color map. \\
\ctcolumns{temperature} A very saturated diverging color map. \\
\ctcolumns{rainbow} There have been many scientific perceptual studies on
the effectiveness of different color maps, and this rainbow color map is
by far the most studied. These perceptual studies uniformly agree that
this rainbow color map is terrible. Never use it.\\
\ctcolumns{levels} A map of 5 distinct colors. \\
\ctcolumns{dense} This is similar to the rainbow color map but with an
intentional variation in brightness. This probably makes the map more
effective, but not by much. \\
\ctcolumns{sharp} A map of 11 fairly distinct colos. \\
\ctcolumns{thermal} A diverging color map of heat-based colors. \\
\ctcolumns{IsoL} An isoluminant (constant brightness) color map of
varying hues. Isoluminant color maps are sometimes recommended for 3D
surfaces, but they have poor perceptual resolution. \\
\ctcolumns{CubicYF} A modification to the rainbow color map to make it
more perceptually uniform. This corrects some (but not all) of the
problems with the rainbow color map. \\
\ctcolumns{CubicL} Similar to CubicYF but extends the hues to red at the
expense of some perceptual non-linearity. \\
\ctcolumns{LinearL} Runs throught the same hues as the rainbow color map
but also adjusts the brightness from minimum (black) to maximum (white)
in a perceptually linear manner. This is sometimes referred to as the
Kindlmann color map. \\
\ctcolumns{LinLhot} Based on the colors for black body radiation, but
modified to be perceptually linear. \\
\ctcolumns{PuRd} A sequential color map from unsaturated purple to red. \\
\ctcolumns{Blues} A sequential color map of blue varied by saturation. \\
\ctcolumns{BuGn} A sequential color map from unsaturated blue to green. \\
\ctcolumns{BuPu} A sequential color map from unsaturated blue to purple. \\
\ctcolumns{GnBu} A sequential color map from unsaturated green to blue. \\
\ctcolumns{Greens} A sequential color map of green varied by saturation. \\
\ctcolumns{Greys} A sequential color map of grays of different lightness. \\
\ctcolumns{Oranges} A sequential color map of orange varied by saturation. \\
\ctcolumns{OrRd} A sequential color map from unsaturated orange to red. \\
\ctcolumns{PuBu} A sequential color map from unsaturated purple to blue. \\
\ctcolumns{PuBuGn} A sequential color map from unsaturated purple to blue
to green. \\
\ctcolumns{PuRd} A sequential color map from unsaturated purple to red. \\
\ctcolumns{Purples} A sequential color map of purple varied by saturation. \\
\ctcolumns{RdPu} A sequential color map from unsaturated red tu purple. \\
\ctcolumns{Reds} A sequential color map of red varied by saturation. \\
\ctcolumns{YlGnBu} A sequential color map from yellow to green to blue. \\
\ctcolumns{YlGn} A sequential color map from yellow to green. \\
\ctcolumns{YlOrBr} A sequential color map from yellow to orange to brown. \\
\ctcolumns{YlOrRd} A sequential color map from yellow to orange to red. \\
\ctcolumns{BrBG} A diverging color map from brown to greenish blue. \\
\ctcolumns{PiYG} A diverging color map from pink to yellowish green. \\
\ctcolumns{PRGn} A diverging color map from purple to green. \\
\ctcolumns{PuOr} A diverging color map from orange to purple. \\
\ctcolumns{RdBu} A diverging color map from red to blue. \\
\ctcolumns{RdGy} A diverging color map from red to gray. \\
\ctcolumns{RdYlBu} A diverging color map from red to blue through yellow. \\
\ctcolumns{RdYlGn} A diverging color map from red to green through yellow. \\
\ctcolumns{Spectral} A diverging color map incorporating most of the
spectral hues. \\
\ctcolumns{Dark2} A collection of 8 distinct dark colors. \\
\ctcolumns{Paired} A collection of 12 distinct colors paired into light
and dark versions of 6 different hues. \\
\ctcolumns{Pastel1} A collection of 9 distinct pastel (light) colors. \\
\ctcolumns{Pastel2} A collection of 8 distinct pastel (light) colors. \\
\ctcolumns{Set1} A collection of 9 distinct colors. \\
\ctcolumns{Set2} A collection of 8 distinct colors. \\
\ctcolumns{Set3} A collection of 12 distinct colors. \\
\ctcolumns{Accent} A collection of 8 colors. \\
\end{longtabu}
\fix{There is more functionality to document in
\textidentifier{ColorTable}. In particular, building color tables by
adding control points. However, I am not bothering to document that right
now because (1) I don't think many people will use it and (2) it is
pretty clear from the Doxygen.}
\index{color tables|)}
\index{rendering!color tables|)}