1 |
jongui |
1037 |
""" |
2 |
|
|
@author: John NGUI |
3 |
|
|
""" |
4 |
|
|
|
5 |
|
|
import vtk |
6 |
|
|
from constant import Renderer, Color, Viewport |
7 |
|
|
|
8 |
|
|
class Scene: |
9 |
|
|
""" |
10 |
|
|
Class that defines a scene. A scene is a window in which objects are |
11 |
|
|
to be rendered on. Only one scene needs to be created and can display |
12 |
|
|
data from one source. However, a scene may be divided into four |
13 |
|
|
smaller windows called viewports (if needed). The four viewports in |
14 |
|
|
turn can display data from four different sources. |
15 |
|
|
""" |
16 |
|
|
|
17 |
|
|
def __init__(self, renderer = Renderer.ONLINE, num_viewport = 1, |
18 |
|
|
x_size = 1152, y_size = 864): |
19 |
|
|
""" |
20 |
|
|
Initialise the scene. |
21 |
|
|
|
22 |
|
|
@type renderer: String |
23 |
|
|
@param renderer: Type of renderer (i.e.Renderer.ONLINE, etc) |
24 |
|
|
@type num_viewport: Number |
25 |
|
|
@param num_viewport: Number of viewport(s) in the scene. Either 1 or 4 |
26 |
|
|
@type x_size: Number |
27 |
|
|
@param x_size: Size of the render window along the x-axis |
28 |
|
|
@type y_size: Number |
29 |
|
|
@param y_size: Size of the render window along the y-axis |
30 |
|
|
""" |
31 |
|
|
|
32 |
|
|
self.__renderer = renderer |
33 |
|
|
self.__num_viewport = num_viewport |
34 |
|
|
self.__x_size = x_size |
35 |
|
|
self.__y_size = y_size |
36 |
|
|
|
37 |
|
|
self.__vtk_render_window = vtk.vtkRenderWindow() |
38 |
|
|
self.__setupScene() |
39 |
|
|
|
40 |
|
|
def __setupScene(self): |
41 |
|
|
""" |
42 |
|
|
Setup the scene. |
43 |
|
|
""" |
44 |
|
|
|
45 |
|
|
self.__createViewport() |
46 |
|
|
self.__addRenderer() |
47 |
|
|
self.setBackground(Color.WHITE) # Default background color is white. |
48 |
|
|
|
49 |
|
|
# Default title bar. |
50 |
|
|
self.setTitleBar("Earth Systems Science Computational Centre (ESSCC)") |
51 |
|
|
self.__setSize(self.__x_size, self.__y_size) |
52 |
|
|
|
53 |
|
|
if(self.__renderer == Renderer.ONLINE): # True for online rendering. |
54 |
|
|
self.__setupOnlineRendering() |
55 |
|
|
else: # True for offline rendering. |
56 |
|
|
self.__setupOfflineRendering() |
57 |
|
|
|
58 |
|
|
def __createViewport(self): |
59 |
|
|
""" |
60 |
|
|
Create the viewport(s) in the scene. |
61 |
|
|
""" |
62 |
|
|
|
63 |
|
|
# Create the renderer(s) for the viewport(s). |
64 |
|
|
self.__vtk_renderer = [] |
65 |
|
|
for viewport in range(0, self.__num_viewport): |
66 |
|
|
self.__vtk_renderer.append(vtk.vtkRenderer()) |
67 |
|
|
|
68 |
|
|
if(self.__num_viewport == 4): |
69 |
|
|
# Renderer for the entire scene (background to the viewports). |
70 |
|
|
self.__vtk_renderer_background = vtk.vtkRenderer() |
71 |
|
|
|
72 |
|
|
# Specify the positioning of the four viewports (between 0 and 1). |
73 |
|
|
self.__vtk_renderer[Viewport.SOUTH_WEST].SetViewport( |
74 |
|
|
0.0, 0.0, 0.5, 0.5) |
75 |
|
|
self.__vtk_renderer[Viewport.NORTH_WEST].SetViewport( |
76 |
|
|
0.0, 0.5013, 0.5, 1) |
77 |
|
|
self.__vtk_renderer[Viewport.NORTH_EAST].SetViewport( |
78 |
|
|
0.501, 0.5013, 1, 1) |
79 |
|
|
self.__vtk_renderer[Viewport.SOUTH_EAST].SetViewport( |
80 |
|
|
0.501, 0.0, 1.0, 0.5) |
81 |
|
|
|
82 |
|
|
def setBackground(self, color): |
83 |
|
|
""" |
84 |
|
|
Set the background color of the scene. |
85 |
|
|
|
86 |
|
|
@type color: L{Color <constant.Color>} constant |
87 |
|
|
@param color: Scene background color |
88 |
|
|
""" |
89 |
|
|
|
90 |
|
|
# Color the entire scene (background) black initially. |
91 |
|
|
# This is carried out mainly to have the borders between |
92 |
|
|
# the viewports visibly black. |
93 |
|
|
if(self.__num_viewport == 4): |
94 |
|
|
self.__vtk_renderer_background.SetBackground(Color.BLACK) |
95 |
|
|
|
96 |
|
|
for viewport in range(0, self.__num_viewport): |
97 |
|
|
self.__vtk_renderer[viewport].SetBackground(color) |
98 |
|
|
|
99 |
|
|
def __addRenderer(self): |
100 |
|
|
""" |
101 |
|
|
Add the renderer(s) to the render window. |
102 |
|
|
""" |
103 |
|
|
# Renderer for the black scene (background). |
104 |
|
|
if(self.__num_viewport == 4): |
105 |
|
|
self.__vtk_render_window.AddRenderer( |
106 |
|
|
self.__vtk_renderer_background) |
107 |
|
|
|
108 |
|
|
for viewport in range(0, self.__num_viewport): |
109 |
|
|
self.__vtk_render_window.AddRenderer(self.__vtk_renderer[viewport]) |
110 |
|
|
|
111 |
|
|
def setTitleBar(self, text): |
112 |
|
|
""" |
113 |
|
|
Set the text on the title bar of the render window. |
114 |
|
|
|
115 |
|
|
@type text: String |
116 |
|
|
@param text: Text on the title bar |
117 |
|
|
""" |
118 |
|
|
|
119 |
|
|
self.__vtk_render_window.SetWindowName(text) |
120 |
|
|
|
121 |
|
|
def __setSize(self, x_size, y_size): |
122 |
|
|
""" |
123 |
|
|
Set the size of the render window. |
124 |
|
|
|
125 |
|
|
@type x_size: Number |
126 |
|
|
@param x_size: Size of the render window along the x-axis |
127 |
|
|
@type y_size: Number |
128 |
|
|
@param y_size: Size of the render window along the y-axis |
129 |
|
|
""" |
130 |
|
|
|
131 |
|
|
self.__vtk_render_window.SetSize(x_size, y_size) |
132 |
|
|
|
133 |
|
|
def __setupOnlineRendering(self): |
134 |
|
|
""" |
135 |
|
|
Setup the window interactor for online rendering. |
136 |
|
|
""" |
137 |
|
|
|
138 |
|
|
# Associate the window interactor with the render window. |
139 |
|
|
self.__vtk_render_window_interactor = vtk.vtkRenderWindowInteractor() |
140 |
|
|
self.__vtk_render_window_interactor.SetRenderWindow( |
141 |
|
|
self.__vtk_render_window) |
142 |
|
|
self.__vtk_render_window_interactor.Initialize() |
143 |
|
|
|
144 |
|
|
def __setupOfflineRendering(self): |
145 |
|
|
""" |
146 |
|
|
Setup the window to image filter for offline rendering. |
147 |
|
|
""" |
148 |
|
|
|
149 |
|
|
# Enable offscreen rendering. |
150 |
|
|
self.__vtk_render_window.OffScreenRenderingOn() |
151 |
|
|
# Convert the output of the render window into an image. |
152 |
|
|
self.__vtk_window_to_image = vtk.vtkWindowToImageFilter() |
153 |
|
|
self.__vtk_window_to_image.SetInput(self.__vtk_render_window) |
154 |
|
|
self.__vtk_image_writer = self.__getImageWriter() |
155 |
|
|
|
156 |
|
|
def __getImageWriter(self): |
157 |
|
|
""" |
158 |
|
|
Return the appropriate image writer based on the specified offline |
159 |
|
|
renderer. |
160 |
|
|
|
161 |
|
|
@rtype: vtkImageWriter |
162 |
|
|
@return: Image writer |
163 |
|
|
""" |
164 |
|
|
|
165 |
|
|
if(self.__renderer == Renderer.OFFLINE_JPG): |
166 |
|
|
return vtk.vtkJPEGWriter() |
167 |
|
|
elif(self.__renderer == Renderer.OFFLINE_BMP): |
168 |
|
|
return vtk.vtkBMPWriter() |
169 |
|
|
elif(self.__renderer == Renderer.OFFLINE_PNM): |
170 |
|
|
return vtk.vtkPNMWriter() |
171 |
|
|
elif(self.__renderer == Renderer.OFFLINE_PNG): |
172 |
|
|
return vtk.vtkPNGWriter() |
173 |
|
|
elif(self.__renderer == Renderer.OFFLINE_TIF): |
174 |
|
|
return vtk.vtkTIFFWriter() |
175 |
|
|
elif(self.__renderer == Renderer.OFFLINE_PS): |
176 |
|
|
return vtk.vtkPostScriptWriter() |
177 |
|
|
|
178 |
|
|
def saveImage(self, image_name): |
179 |
|
|
""" |
180 |
|
|
Save the rendered object as an image. |
181 |
|
|
|
182 |
|
|
@type image_name: String |
183 |
|
|
@param image_name: Name of the saved image. |
184 |
|
|
""" |
185 |
|
|
|
186 |
|
|
try: |
187 |
|
|
# NOTE: Render and Modified must be called everytime before writing |
188 |
|
|
# an image. Otherwise, only the first image will always be saved. |
189 |
|
|
# This is due to the architecture of VTK. |
190 |
|
|
self.__vtk_render_window.Render() |
191 |
|
|
self.__vtk_window_to_image.Modified() |
192 |
|
|
|
193 |
|
|
# Retrieve rendered object from the window and convert it into an |
194 |
|
|
# image. |
195 |
|
|
self.__vtk_image_writer.SetInput( |
196 |
|
|
self.__vtk_window_to_image.GetOutput()) |
197 |
|
|
self.__vtk_image_writer.SetFileName(image_name) |
198 |
|
|
self.__vtk_image_writer.Write() |
199 |
|
|
except AttributeError: |
200 |
|
|
print "ERROR: Incorrect use of the '" + self.__renderer + \ |
201 |
|
|
"' renderer. Kindly, use the 'offline' renderer instead." |
202 |
|
|
|
203 |
|
|
def animate(self): |
204 |
|
|
""" |
205 |
|
|
Animate the object onto the scene on-the-fly. No interaction can occur. |
206 |
|
|
""" |
207 |
|
|
|
208 |
|
|
self.__vtk_render_window.Render() |
209 |
|
|
|
210 |
|
|
def render(self): |
211 |
|
|
""" |
212 |
|
|
Render the object onto the scene. |
213 |
|
|
""" |
214 |
|
|
|
215 |
|
|
try: |
216 |
|
|
self.__vtk_render_window.Render() |
217 |
|
|
|
218 |
|
|
# NOTE: Once Start is executed, the driver will not further execute |
219 |
|
|
# any subsequent codes thereafter. |
220 |
|
|
self.__vtk_render_window_interactor.Start() |
221 |
|
|
except AttributeError: |
222 |
|
|
print "ERROR: Incorrect use of the '" + self.__renderer + \ |
223 |
|
|
"' renderer. Kindly, switch to the 'online' renderer." |
224 |
|
|
|
225 |
|
|
def _addActor3D(self, viewport, actor): |
226 |
|
|
""" |
227 |
|
|
Add the actor3D to the appropriate viewport. |
228 |
|
|
|
229 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
230 |
|
|
@param viewport: Viewport which the actor3D is to be added to |
231 |
|
|
@type actor: L{Actor3D <actor.Actor3D>} object |
232 |
|
|
@param actor: Actor3D which is to be added to the viewport |
233 |
|
|
""" |
234 |
|
|
|
235 |
|
|
self.__vtk_renderer[viewport].AddActor(actor) |
236 |
|
|
|
237 |
|
|
def _addActor2D(self, viewport, actor): |
238 |
|
|
""" |
239 |
|
|
Add the actor2D to the appropriate viewport. |
240 |
|
|
|
241 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
242 |
|
|
@param viewport: Viewport which the actor2D is to be added to |
243 |
|
|
@type actor: L{Actor2D <actor.Actor2D>} object |
244 |
|
|
@param actor: Actor2D which is to be added to the viewport |
245 |
|
|
""" |
246 |
|
|
|
247 |
|
|
self.__vtk_renderer[viewport].AddActor2D(actor) |
248 |
|
|
|
249 |
|
|
def _setActiveCamera(self, viewport, camera): |
250 |
|
|
""" |
251 |
|
|
Set the camera to the appropriate viewport. |
252 |
|
|
|
253 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
254 |
|
|
@param viewport: Viewport which the camera is to be added to |
255 |
|
|
@type camera: L{Camera <camera.Camera>} object |
256 |
|
|
@param camera: Camera which is to be assigned to the viewport |
257 |
|
|
""" |
258 |
|
|
|
259 |
|
|
self.__vtk_renderer[viewport].SetActiveCamera(camera) |
260 |
|
|
|
261 |
|
|
def _addLight(self, viewport, light): |
262 |
|
|
""" |
263 |
|
|
Add the light to the appropriate viewport. |
264 |
|
|
|
265 |
|
|
@type viewport: L{Viewport <constant.Viewport>} constant |
266 |
|
|
@param viewport: Viewport which the camera is to be added to |
267 |
|
|
@type light: L{Light <light.Light>} object |
268 |
|
|
@param light: Light which is to be assigned to the viewport |
269 |
|
|
""" |
270 |
|
|
|
271 |
|
|
self.__vtk_renderer[viewport].AddLight(light) |
272 |
|
|
|
273 |
|
|
def _getRenderer(self): |
274 |
|
|
""" |
275 |
|
|
Return the renderer(s) |
276 |
|
|
|
277 |
|
|
@rtype: One or more column tuple of vtkRenderer |
278 |
|
|
@return: Renderer(s) |
279 |
|
|
""" |
280 |
|
|
|
281 |
|
|
return self.__vtk_renderer |