1 |
ksteube |
1147 |
""" |
2 |
jongui |
1197 |
@var __author__: name of author |
3 |
|
|
@var __copyright__: copyrights |
4 |
|
|
@var __license__: licence agreement |
5 |
|
|
@var __url__: url entry point on documentation |
6 |
|
|
@var __version__: version |
7 |
|
|
@var __date__: date of the version |
8 |
ksteube |
1147 |
""" |
9 |
|
|
|
10 |
jongui |
1197 |
__author__="John Ngui, john.ngui@uq.edu.au" |
11 |
|
|
__copyright__=""" Copyright (c) 2006 by ACcESS MNRF |
12 |
|
|
http://www.access.edu.au |
13 |
|
|
Primary Business: Queensland, Australia""" |
14 |
|
|
__license__="""Licensed under the Open Software License version 3.0 |
15 |
|
|
http://www.opensource.org/licenses/osl-3.0.php""" |
16 |
|
|
__url__="http://www.iservo.edu.au/esys" |
17 |
|
|
__version__="$Revision$" |
18 |
|
|
__date__="$Date$" |
19 |
|
|
|
20 |
|
|
|
21 |
ksteube |
1147 |
import vtk |
22 |
jongui |
1190 |
from constant import Renderer, Color, Viewport, ImageFormat |
23 |
ksteube |
1147 |
|
24 |
|
|
class Scene: |
25 |
|
|
""" |
26 |
|
|
Class that defines a scene. A scene is a window in which objects are to |
27 |
|
|
be rendered on. Only one scene needs to be created. However, a scene may |
28 |
|
|
be divided into four smaller windows called viewports (if needed). |
29 |
|
|
Each viewport can render a different object. |
30 |
jongui |
1199 |
|
31 |
|
|
@attention: If the IV or VRML renderer type is used, then only one |
32 |
|
|
viewport can be used (four viewports are not supported for these two |
33 |
|
|
cases). |
34 |
ksteube |
1147 |
""" |
35 |
|
|
|
36 |
|
|
def __init__(self, renderer = Renderer.ONLINE, num_viewport = 1, |
37 |
|
|
x_size = 1152, y_size = 864): |
38 |
|
|
""" |
39 |
|
|
Initialise the scene. |
40 |
|
|
|
41 |
|
|
@type renderer: L{Renderer <constant.Renderer>} constant |
42 |
|
|
@param renderer: Type of renderer |
43 |
|
|
@type num_viewport: Number |
44 |
|
|
@param num_viewport: Number of viewport(s) in the scene. Either 1 or 4 |
45 |
|
|
@type x_size: Number |
46 |
|
|
@param x_size: Size of the render window along the x-axis |
47 |
|
|
@type y_size: Number |
48 |
|
|
@param y_size: Size of the render window along the y-axis |
49 |
|
|
""" |
50 |
|
|
|
51 |
|
|
self.__renderer = renderer |
52 |
|
|
self.__num_viewport = num_viewport |
53 |
|
|
self.__x_size = x_size |
54 |
|
|
self.__y_size = y_size |
55 |
jongui |
1148 |
# Stores the visualization modules (i.e. Map, Velocity, Ellipsoid, etc) |
56 |
|
|
# which needs to be rendered. |
57 |
|
|
self.__visualization_modules = [] |
58 |
ksteube |
1147 |
|
59 |
|
|
self.__OFFLINE = "offline" |
60 |
jongui |
1168 |
self.__VRML = "vrml" |
61 |
|
|
self.__IV = "iv" |
62 |
ksteube |
1147 |
|
63 |
|
|
self.__vtk_render_window = vtk.vtkRenderWindow() |
64 |
|
|
self.__setupScene() |
65 |
|
|
|
66 |
|
|
def __setupScene(self): |
67 |
|
|
""" |
68 |
|
|
Setup the scene. |
69 |
|
|
""" |
70 |
|
|
|
71 |
|
|
self.__createViewport() |
72 |
|
|
self.__addRenderer() |
73 |
|
|
self.setBackground(Color.WHITE) # Default background color is white. |
74 |
|
|
|
75 |
gross |
1163 |
|
76 |
ksteube |
1147 |
# Default title bar. |
77 |
|
|
self.setTitleBar("Earth Systems Science Computational Centre (ESSCC)") |
78 |
|
|
self.__setSize(self.__x_size, self.__y_size) |
79 |
|
|
|
80 |
|
|
# True for Online rendering. |
81 |
|
|
if(self.__renderer.startswith(Renderer.ONLINE)): |
82 |
|
|
self.__setupOnlineRendering() |
83 |
|
|
# True for all Online renderers except Renderer.ONLINE. |
84 |
|
|
if(self.__renderer != Renderer.ONLINE): |
85 |
|
|
self.__setupWindowToImage() |
86 |
|
|
# True for Offline rendering. |
87 |
|
|
elif(self.__renderer.startswith(self.__OFFLINE)): |
88 |
|
|
self.__setupOfflineRendering() |
89 |
|
|
self.__setupWindowToImage() |
90 |
|
|
# True for Display rendering. |
91 |
|
|
elif(self.__renderer.startswith(Renderer.DISPLAY)): |
92 |
|
|
# True for all Display renderers except Renderer.DISPLAY. |
93 |
|
|
if(self.__renderer != Renderer.DISPLAY): |
94 |
|
|
self.__setupWindowToImage() |
95 |
|
|
|
96 |
|
|
def __createViewport(self): |
97 |
|
|
""" |
98 |
|
|
Create the viewport(s) in the scene. |
99 |
|
|
""" |
100 |
|
|
|
101 |
|
|
# Create the renderer(s) for the viewport(s). |
102 |
|
|
self.__vtk_renderer = [] |
103 |
|
|
for viewport in range(0, self.__num_viewport): |
104 |
|
|
self.__vtk_renderer.append(vtk.vtkRenderer()) |
105 |
|
|
|
106 |
|
|
if(self.__num_viewport == 4): |
107 |
|
|
# Renderer for the entire scene (background). |
108 |
|
|
self.__vtk_renderer_background = vtk.vtkRenderer() |
109 |
|
|
|
110 |
|
|
# Specify the positioning of the four viewports (between 0 and 1). |
111 |
|
|
self.__vtk_renderer[Viewport.SOUTH_WEST].SetViewport( |
112 |
|
|
0.0, 0.0, 0.5, 0.5) |
113 |
|
|
self.__vtk_renderer[Viewport.NORTH_WEST].SetViewport( |
114 |
|
|
0.0, 0.5013, 0.5, 1) |
115 |
|
|
self.__vtk_renderer[Viewport.NORTH_EAST].SetViewport( |
116 |
|
|
0.501, 0.5013, 1, 1) |
117 |
|
|
self.__vtk_renderer[Viewport.SOUTH_EAST].SetViewport( |
118 |
|
|
0.501, 0.0, 1.0, 0.5) |
119 |
|
|
|
120 |
|
|
def setBackground(self, color): |
121 |
|
|
""" |
122 |
|
|
Set the background color of the scene. |
123 |
|
|
|
124 |
|
|
@type color: L{Color <constant.Color>} constant |
125 |
|
|
@param color: Scene background color |
126 |
|
|
""" |
127 |
|
|
|
128 |
|
|
# Color the entire scene (background) black initially. |
129 |
|
|
# This is carried out mainly to have the borders between |
130 |
|
|
# the viewports visibly black. |
131 |
|
|
if(self.__num_viewport == 4): |
132 |
|
|
self.__vtk_renderer_background.SetBackground(Color.BLACK) |
133 |
|
|
|
134 |
|
|
for viewport in range(0, self.__num_viewport): |
135 |
|
|
self.__vtk_renderer[viewport].SetBackground(color) |
136 |
|
|
|
137 |
|
|
def __addRenderer(self): |
138 |
|
|
""" |
139 |
|
|
Add the renderer(s) to the render window. |
140 |
|
|
""" |
141 |
|
|
|
142 |
|
|
# Add the renderer for the black scene (background). |
143 |
|
|
if(self.__num_viewport == 4): |
144 |
|
|
self.__vtk_render_window.AddRenderer( |
145 |
|
|
self.__vtk_renderer_background) |
146 |
|
|
|
147 |
|
|
for viewport in range(0, self.__num_viewport): |
148 |
|
|
self.__vtk_render_window.AddRenderer(self.__vtk_renderer[viewport]) |
149 |
|
|
|
150 |
|
|
def setTitleBar(self, text): |
151 |
|
|
""" |
152 |
|
|
Set the text on the title bar of the render window. |
153 |
|
|
|
154 |
|
|
@type text: String |
155 |
|
|
@param text: Text on the title bar |
156 |
|
|
""" |
157 |
|
|
|
158 |
|
|
self.__vtk_render_window.SetWindowName(text) |
159 |
|
|
|
160 |
|
|
def __setSize(self, x_size, y_size): |
161 |
|
|
""" |
162 |
|
|
Set the size of the render window. |
163 |
|
|
|
164 |
|
|
@type x_size: Number |
165 |
|
|
@param x_size: Size of the render window along the x-axis |
166 |
|
|
@type y_size: Number |
167 |
|
|
@param y_size: Size of the render window along the y-axis |
168 |
|
|
""" |
169 |
|
|
|
170 |
|
|
self.__vtk_render_window.SetSize(x_size, y_size) |
171 |
|
|
|
172 |
|
|
def __setupOnlineRendering(self): |
173 |
|
|
""" |
174 |
|
|
Setup the window interactor for online rendering. |
175 |
|
|
""" |
176 |
|
|
|
177 |
|
|
# Associate the window interactor with the render window. |
178 |
|
|
self.__vtk_render_window_interactor = vtk.vtkRenderWindowInteractor() |
179 |
|
|
self.__vtk_render_window_interactor.SetRenderWindow( |
180 |
|
|
self.__vtk_render_window) |
181 |
|
|
self.__vtk_render_window_interactor.Initialize() |
182 |
|
|
|
183 |
|
|
def __setupOfflineRendering(self): |
184 |
|
|
""" |
185 |
|
|
Enables the offline rendering (no window comes up). |
186 |
|
|
""" |
187 |
jongui |
1197 |
|
188 |
ksteube |
1147 |
# Enables the offscreen rendering. |
189 |
|
|
self.__vtk_render_window.OffScreenRenderingOn() |
190 |
|
|
|
191 |
|
|
def __setupWindowToImage(self): |
192 |
|
|
""" |
193 |
|
|
Setup the window to image filter to convert the output from the render |
194 |
jongui |
1199 |
window into an image, vrml or open inventor file. |
195 |
ksteube |
1147 |
""" |
196 |
jongui |
1197 |
|
197 |
ksteube |
1147 |
self.__vtk_window_to_image = vtk.vtkWindowToImageFilter() |
198 |
|
|
self.__vtk_window_to_image.SetInput(self.__vtk_render_window) |
199 |
|
|
self.__vtk_image_writer = self.__getImageWriter() |
200 |
|
|
|
201 |
|
|
def __getImageWriter(self): |
202 |
|
|
""" |
203 |
jongui |
1168 |
Return the appropriate image writer or exporter based on the |
204 |
|
|
specified renderer. |
205 |
ksteube |
1147 |
|
206 |
jongui |
1168 |
@rtype: vtkImageWriter or vtkExporter |
207 |
|
|
@return: Image writer or exporter |
208 |
ksteube |
1147 |
""" |
209 |
|
|
|
210 |
jongui |
1190 |
if(self.__renderer.endswith(ImageFormat.JPG)): |
211 |
ksteube |
1147 |
return vtk.vtkJPEGWriter() |
212 |
jongui |
1190 |
elif(self.__renderer.endswith(ImageFormat.BMP)): |
213 |
ksteube |
1147 |
return vtk.vtkBMPWriter() |
214 |
jongui |
1190 |
elif(self.__renderer.endswith(ImageFormat.PNM)): |
215 |
ksteube |
1147 |
return vtk.vtkPNMWriter() |
216 |
jongui |
1190 |
elif(self.__renderer.endswith(ImageFormat.PNG)): |
217 |
ksteube |
1147 |
return vtk.vtkPNGWriter() |
218 |
jongui |
1190 |
elif(self.__renderer.endswith(ImageFormat.TIF)): |
219 |
ksteube |
1147 |
return vtk.vtkTIFFWriter() |
220 |
jongui |
1190 |
elif(self.__renderer.endswith(ImageFormat.PS)): |
221 |
ksteube |
1147 |
return vtk.vtkPostScriptWriter() |
222 |
jongui |
1168 |
elif(self.__renderer.endswith(self.__VRML)): |
223 |
|
|
return vtk.vtkVRMLExporter() # Generates VRML files (.wrl). |
224 |
|
|
elif(self.__renderer.endswith(self.__IV)): |
225 |
|
|
return vtk.vtkIVExporter() # Generate OpenInventor files (.iv). |
226 |
ksteube |
1147 |
|
227 |
|
|
def __saveImage(self, image_name): |
228 |
|
|
""" |
229 |
jongui |
1199 |
Save the rendered object as an image, vrml or open inventor file. |
230 |
ksteube |
1147 |
|
231 |
|
|
@type image_name: String |
232 |
jongui |
1199 |
@param image_name: Name of the saved image, vrml or open inventor file |
233 |
ksteube |
1147 |
""" |
234 |
|
|
|
235 |
|
|
# NOTE: Render and Modified must be called everytime before writing |
236 |
jongui |
1199 |
# an image, vrml or open inventor file. Otherwise, only the first |
237 |
|
|
# object will always be saved. This is due to the architecture of VTK. |
238 |
ksteube |
1147 |
self.__vtk_render_window.Render() |
239 |
|
|
self.__vtk_window_to_image.Modified() |
240 |
|
|
|
241 |
|
|
# Retrieve the rendered object from the window and convert it into an |
242 |
jongui |
1199 |
# image, vrml or open inventor file. |
243 |
jongui |
1168 |
# True for all writers besides VRML. |
244 |
|
|
if(not(self.__renderer.endswith(self.__VRML)) and \ |
245 |
|
|
not(self.__renderer.endswith(self.__IV))): |
246 |
|
|
self.__vtk_image_writer.SetInput( |
247 |
|
|
self.__vtk_window_to_image.GetOutput()) |
248 |
|
|
# True only for VRML and IV. |
249 |
|
|
elif(self.__renderer.endswith(self.__VRML) or \ |
250 |
|
|
self.__renderer.endswith(self.__IV)): |
251 |
|
|
self.__vtk_image_writer.SetInput( |
252 |
|
|
self.__vtk_render_window) |
253 |
ksteube |
1147 |
self.__vtk_image_writer.SetFileName(image_name) |
254 |
|
|
self.__vtk_image_writer.Write() |
255 |
|
|
|
256 |
|
|
def __animate(self): |
257 |
|
|
""" |
258 |
|
|
Animate the rendered object on-the-fly. |
259 |
|
|
""" |
260 |
|
|
|
261 |
|
|
# With Render() ONLY, the rendered object is animated onto the |
262 |
|
|
# scene on-the-fly and no interaction can occur. |
263 |
|
|
self.__vtk_render_window.Render() |
264 |
|
|
|
265 |
|
|
def render(self, image_name = None): |
266 |
|
|
""" |
267 |
|
|
Render the object using either the online, offline or display mode. |
268 |
jongui |
1197 |
|
269 |
|
|
@type image_name: String |
270 |
jongui |
1199 |
@param image_name: Name of the saved image, vrml or open inventor file |
271 |
ksteube |
1147 |
""" |
272 |
jongui |
1197 |
|
273 |
jongui |
1148 |
for i in range(0, len(self.__visualization_modules)): |
274 |
jongui |
1158 |
self.__visualization_modules[i]._render(self) |
275 |
jongui |
1189 |
self.__vtk_render_window.Render() |
276 |
ksteube |
1147 |
|
277 |
|
|
self.__vtk_render_window.Render() |
278 |
|
|
|
279 |
|
|
if(self.__renderer.startswith(Renderer.ONLINE)): |
280 |
|
|
# NOTE: Once Start() is executed, the driver will not further |
281 |
|
|
# execute any subsequent codes thereafter unless the 'q' or |
282 |
|
|
# 'e' keys are pressed. |
283 |
|
|
self.__vtk_render_window_interactor.Start() |
284 |
|
|
|
285 |
|
|
# True for all online renderers except Renderer.ONLINE. |
286 |
|
|
if(self.__renderer != Renderer.ONLINE): |
287 |
|
|
self.__saveImage(image_name) |
288 |
|
|
# True for all display renderers except Renderer.DISPLAY. |
289 |
|
|
elif(self.__renderer.startswith(self.__OFFLINE) or |
290 |
|
|
self.__renderer != Renderer.DISPLAY): |
291 |
|
|
self.__saveImage(image_name) |
292 |
|
|
|
293 |
|
|
def _addActor3D(self, viewport, actor): |
294 |
|
|
""" |
295 |
|
|
Add the actor3D to the appropriate viewport. |
296 |
|
|
|
297 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
298 |
|
|
@param viewport: Viewport in which the actor3D is to be added to |
299 |
|
|
@type actor: vtkActor |
300 |
|
|
@param actor: Actor3D which is to be added to the viewport |
301 |
|
|
""" |
302 |
|
|
|
303 |
|
|
self.__vtk_renderer[viewport].AddActor(actor) |
304 |
|
|
|
305 |
|
|
def _addActor2D(self, viewport, actor): |
306 |
|
|
""" |
307 |
|
|
Add the actor2D to the appropriate viewport. |
308 |
|
|
|
309 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
310 |
|
|
@param viewport: Viewport in which the actor2D is to be added to |
311 |
|
|
@type actor: vtkActor2D |
312 |
|
|
@param actor: Actor2D which is to be added to the viewport |
313 |
|
|
""" |
314 |
|
|
|
315 |
|
|
self.__vtk_renderer[viewport].AddActor2D(actor) |
316 |
|
|
|
317 |
|
|
def _setActiveCamera(self, viewport, camera): |
318 |
|
|
""" |
319 |
|
|
Set the camera to the appropriate viewport. |
320 |
|
|
|
321 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
322 |
|
|
@param viewport: Viewport in which the camera is to be added to |
323 |
|
|
@type camera: vtkCamera |
324 |
|
|
@param camera: Camera which is to be assigned to the viewport |
325 |
|
|
""" |
326 |
|
|
|
327 |
|
|
self.__vtk_renderer[viewport].SetActiveCamera(camera) |
328 |
|
|
|
329 |
|
|
def _addLight(self, viewport, light): |
330 |
|
|
""" |
331 |
|
|
Add the light to the appropriate viewport. |
332 |
|
|
|
333 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
334 |
|
|
@param viewport: Viewport in which the camera is to be added to |
335 |
|
|
@type light: vtkLight |
336 |
|
|
@param light: Light which is to be assigned to the viewport |
337 |
|
|
""" |
338 |
|
|
|
339 |
|
|
self.__vtk_renderer[viewport].AddLight(light) |
340 |
|
|
|
341 |
|
|
def _getRenderer(self): |
342 |
|
|
""" |
343 |
|
|
Return the renderer(s) |
344 |
|
|
|
345 |
|
|
@rtype: List |
346 |
|
|
@return: A list of renderer(s) |
347 |
|
|
""" |
348 |
|
|
|
349 |
|
|
return self.__vtk_renderer |
350 |
|
|
|
351 |
jongui |
1148 |
def _addVisualizationModules(self, module): |
352 |
|
|
""" |
353 |
|
|
Store visualization modules (i.e. Map, Velocity, Ellipsoid, etc) |
354 |
|
|
which needs to be rendered. |
355 |
|
|
|
356 |
jongui |
1199 |
@type module: Visualization modules |
357 |
|
|
@param module: Visualization modules to be rendered |
358 |
jongui |
1148 |
""" |
359 |
|
|
|
360 |
|
|
self.__visualization_modules.append(module) |
361 |
|
|
|