1
2 """
3 A module for building python-based VRED Qube jobs.
4
5 These jobs use a persistent VRED instance on the farm; a Dynamic Allocation jobtype.
6 """
7
8
9
10
11
12 import sys
13 import os
14 import re
15
16 try:
17 import qb
18 except:
19 if 'QBDIR' in os.environ:
20 QBDIR = os.environ['QBDIR']
21 else:
22 if os.name == 'posix':
23 if os.uname()[0] == 'Darwin':
24 QBDIR = '/Applications/pfx/qube'
25 else:
26 QBDIR = '/usr/local/pfx/qube'
27
28 sys.path.append('%s/api/python' % QBDIR)
29 import qb
30
31 try:
32 from qb import frontend
33 from qb.frontend import pythonFrontEnd as pythonFrontEnd
34 except ImportError:
35 from appUI import frontend
36 from appUI.frontend import pythonFrontEnd as pythonFrontEnd
37
38
40 """
41 The base class for a Load-Once VRED job.
42 """
43
44 kind = 'VRED'
45 prototype = 'VRED'
46
47 - def __init__(self, vred_exe, vred_args='', dev=False):
48 """
49 Function to initialize members of the class
50
51 @param vred_exe: Path to the VRED executable
52 @type vred_exe: C{str}
53
54 @param vred_args: Optional arguments to use when starting the VRED python session.
55 @type vred_args: C{str}
56
57 @param dev: Set the 'dev' value for the Qube job, enables debug output on the farm.
58 @type dev: bool
59 """
60 super(VRED_PythonJob, self).__init__(prototype=self.prototype, dev=dev)
61
62 self['kind'] = self.kind
63
64 pkg = {
65 'pyExecutable': vred_exe,
66 'regex_errors': 'License failure',
67 'vred_args': vred_args,
68 'smartAgenda': 1,
69 }
70 self['package'].update(pkg)
71
72 self['package']['regex_errors'] = '\n'.join(
73 ['License failure',
74 'Can\'t read .* No such file or directory'])
75
76 self['package']['regex_highlights'] = '\n'.join(
77 ['^Licence expires on.*'])
78
79 self.addJobCmds(self.loadVrModuleCmds())
80 self.addJobCmds('vrController.terminateVred()', cmdType='teardown')
81
82 self['agenda'] = []
83
85
86 load_mod_cmds = []
87
88 vr_modules = [
89 'vrAEBase',
90 'vrAmbientOcclusion',
91 'vrAnimation',
92 'vrAnimWidgets',
93 'vrAnnotation',
94 'vrAssetsModule',
95 'vrChunkPtr',
96 'vrClippingModule',
97 'vrCluster',
98 'vrCollision',
99 'vrColorDialog',
100 'vrConnector',
101 'vrController',
102 'vrCubeImages',
103
104 'vrFieldAccess',
105 'vrFileDialog',
106 'vrFileIO',
107 'vrFrame',
108
109 'vrImagePtr',
110
111 'vrInterpolator',
112 'vrJoystick',
113 'vrKey',
114 'vrMaterialEditor',
115 'vrMaterialPtr',
116
117 'vrMovieExport',
118
119
120 'vrNodePtr',
121 'vrNodeUtils',
122 'vrOpenPDM',
123 'vrOptimize',
124 'vrOSGWidget',
125 'vrParticle',
126
127
128 'vrQObject',
129
130 'vrRenderQueue',
131 'vrRenderSettings',
132 'vrRoute',
133
134 'vrScenegraph',
135 'vrScript',
136 'vrSequencer',
137 'vrSHLChunkPtr',
138 'vrSpacemouseButton',
139 'vrSurfaceAnalysis',
140 'vrSwitch',
141 'vrTextureChunkPtr',
142 'vrTimer',
143 'vrTouchSensor',
144
145 'vrTransform',
146 'vrTransformHelper',
147 'vrURManager',
148 'vrVariants',
149 'vrVariantSetPtr',
150 'vrVariantSets',
151
152 'vrViewPoint',
153 'vrVirtualEye',
154
155 'vrVRMLViewPoints',
156 'vrWater',
157 'vrWebOverlay',
158 'vrWidget',
159 ]
160
161 __vr_modules = [
162 'vrAEBase',
163 'vrChunkPtr',
164 'vrColorDialog',
165
166 'vrController',
167 'vrFieldAccess',
168 'vrFileDialog',
169 'vrFileIO',
170 'vrImagePtr',
171 'vrMaterialPtr',
172 'vrNodePtr',
173 'vrNodeUtils',
174 'vrOSGWidget',
175 'vrOptimize',
176 'vrQObject',
177 'vrRoute',
178 'vrSHLChunkPtr',
179 'vrScenegraph',
180 'vrScript',
181 'vrTextureChunkPtr',
182 'vrURManager',
183 'vrVariantSetPtr',
184 'vrVariants',
185 ]
186
187 for vr_mod in vr_modules:
188 load_mod_cmds.append('import %s' % vr_mod)
189
190 load_mod_cmds.append('exec ("import vrCameraEditor", "import vrCamera as vrCameraEditor")[float(vrController.getVredVersion()) > (9.02)]')
191
192
193
194
195
196
197
198
199
200 return load_mod_cmds
201
202
204 """
205 Run one or more VRED sequences, optionally across a frame range
206 """
207 kind = 'VRED Sequencer Render'
208
209 - def __init__(self, vred_exe, project_path, vred_sequences=None, frame_range='', frame_padding=1, vred_args='', job_name='', job_label='', dev=False):
210 """
211 Function to initialize members of the class
212
213 @param vred_exe: Path to the VRED executable on the worker
214 @type vred_exe: C{str}
215
216 @param vred_sequences: One or more VRED sequence names
217 @type vred_sequences: C{list}
218
219 @param project_path: The full disk path to a VRED scenefile
220 @type project_path: C{str}
221
222 @param frame_range: A frame range string. 1-3,6-10x2 expands to [1,2,3,6,8,10]
223 @type frame_range: C{str}
224
225 @param vred_args: Optional arguments to use when starting the VRED python session.
226 @type vred_args: C{str}
227
228 @param job_name: Optional qube job name
229 @type job_name: C{str}
230
231 @param job_label: Optional qube job label
232 @type job_label: C{str}
233
234 @param dev: Set the 'dev' value for the Qube job, enables debug output on the farm.
235 @type dev: bool
236 """
237 super(VRED_SequencerRenderJob, self).__init__(vred_exe, vred_args=vred_args, dev=dev)
238
239 self.project_path = project_path
240 self['package']['VRED_project'] = self.project_path
241
242 if not vred_sequences:
243 vred_sequences = []
244 elif isinstance(vred_sequences, str):
245 vred_sequences = list(vred_sequences)
246 self.vred_sequences = vred_sequences
247 self['package']['vred_sequences'] = self.vred_sequences
248
249 (scene_name, scene_ext) = os.path.splitext(os.path.basename(self.project_path))
250 if job_name:
251 self['name'] = job_name
252 else:
253 self['name'] = 'VRED render %s%s' % (scene_name, scene_ext)
254
255 self.frame_range = frame_range
256 self.frame_padding = frame_padding
257 if frame_range:
258 self['package']['range'] = self.frame_range
259 self['package']['padding'] = self.frame_padding
260 self['package']['smartAgenda'] = True
261
262 if job_label:
263 self['label'] = job_label
264
265 self.addJobCmds(self._jobSetupCmds())
266 self['agenda'] = self._buildAgenda()
267
269 cmds = []
270
271 cmds.append('vrController.newScene()')
272 cmds.append('sys.stderr = sys.__stderr__')
273 cmds.append('sys.stdout = sys.__stdout__')
274 cmds.append('vrFileIO.load(QB_CONVERT_PATH("%s"))' % self.project_path)
275
276 return cmds
277
279 """
280 Create an agenda for the job, complete with per-frame python commands.
281
282 @return: The populated work agenda for the job
283 @rtype: C{list}
284 """
285 agenda = []
286
287 if self.frame_range:
288 for frame in [x['name'] for x in qb.genframes(self.frame_range)]:
289 if self.vred_sequences:
290 for seq_name in self.vred_sequences:
291 cmds = []
292 work = {
293 'name': '%s @ %s' % (seq_name, frame),
294 'package': {
295 'commands': cmds
296 }
297 }
298 cmds.append('os.environ["QB_FRAME_NUMBER"] = "%0*d"' % (self.frame_padding, int(frame)))
299 cmds.append('vrAnimWidgets.setCurrentFrame(%s)' % frame)
300 cmds.append('vrSequencer.runSequence("%s")' % seq_name)
301
302 agenda.append(work)
303 else:
304 cmds = []
305 work = {
306 'name': 'All Sequences @ %s' % frame,
307 'package': {
308 'commands': cmds
309 }
310 }
311 cmds.append('os.environ["QB_FRAME_NUMBER"] = "%0*d"' % (self.frame_padding, int(frame)))
312 cmds.append('vrAnimWidgets.setCurrentFrame(%s)' % frame)
313 cmds.append('vrSequencer.runAllSequences()')
314
315 agenda.append(work)
316 else:
317 if self.vred_sequences:
318 for seq_name in self.vred_sequences:
319 cmds = []
320 work = {
321 'name': seq_name,
322 'package': {
323 'commands': cmds
324 }
325 }
326 cmds.append('vrSequencer.runSequence(\'%s\')' % seq_name)
327
328 agenda.append(work)
329 else:
330 work = {
331 'name': 'All Sequences',
332 'package': {
333 'commands': [
334 'vrSequencer.runAllSequences()'
335 ],
336 }
337 }
338
339 agenda.append(work)
340
341 return agenda
342
343
345 """
346 Render a one or more VRED Viewpoints
347 """
348 kind = 'VRED Viewpoint Render'
349
350 - def __init__(self,
351 vred_exe,
352 project_path,
353
354 image_path_template,
355
356 img_width,
357 img_height,
358
359 viewpoints='',
360
361 render_quality='',
362 ssf=0,
363
364 alpha=False,
365 alphaR=0,
366 alphaB=0,
367 alphaG=0,
368
369 dpi = 100,
370
371 vred_args='',
372
373 frame_range='', frame_padding=1,
374 job_name='', job_label='',
375 dev=False):
376 """
377 Function to initialize members of the class
378
379 @param vred_exe: Path to the VRED executable on the worker
380 @type vred_exe: C{str}
381
382 @param project_path: The full disk path to a VRED scenefile
383 @type project_path: C{str}
384
385 @param image_path_template: full path to rendered images, with '#' as a placeholder for the frame number
386 @type project_path: C{str}
387
388 @param viewpoints: A list of VRED viewpoints to render
389 @type viewpoints: C{list}
390
391 @param render_quality: VRED render quality
392 @type ssf: C{str}
393
394 @param ssf: VRED Supersampling factor
395 @type ssf: C{int}
396
397 @param alpha: Render an alpha channel
398 @type alpha: C{bool}
399
400 @param alphaR: Alpha channel red component, between 0.0 and 1.0
401 @type alphaR: C{float}
402
403 @param alphaG: Alpha channel blue component, between 0.0 and 1.0
404 @type alphaG: C{float}
405
406 @param alphaB: Alpha channel green component, between 0.0 and 1.0
407 @type alphaB: C{float}
408
409 @param dpi: Dots per inch for image printing
410 @type alphaB: C{int}
411
412 @param vred_args: Optional arguments to use when starting the VRED python session.
413 @type vred_args: C{str}
414
415 @param frame_range: A frame range string. 1-3,6-10x2 expands to [1,2,3,6,8,10]
416 @type frame_range: C{str}
417
418 @param job_name: Optional qube job name
419 @type job_name: C{str}
420
421 @param job_label: Optional qube job label
422 @type job_label: C{str}
423
424 @param dev: Set the 'dev' value for the Qube job, enables debug output on the farm.
425 @type dev: bool
426 """
427 super(VRED_ViewpointRenderJob, self).__init__(vred_exe, vred_args=vred_args, dev=dev)
428
429 self.project_path = project_path
430 self['package']['VRED_project'] = self.project_path
431
432 self.image_path_template = image_path_template
433 self.img_width = img_width
434 self.img_height = img_height
435
436 self.render_quality = render_quality
437 self.ssf = ssf
438
439 self.alpha = alpha
440 self.alphaR = alphaR
441 self.alphaG = alphaG
442 self.alphaB = alphaB
443
444 self.dpi = dpi
445
446 if viewpoints is None or len(viewpoints) == 0:
447 self.viewpoints = []
448 elif isinstance(viewpoints, str):
449 if viewpoints.count(','):
450 self.viewpoints = viewpoints.split(',')
451 else:
452 self.viewpoints = [viewpoints]
453 else:
454 self.viewpoints = viewpoints
455
456 (scene_name, scene_ext) = os.path.splitext(os.path.basename(self.project_path))
457 if job_name:
458 self['name'] = job_name
459 else:
460 self['name'] = 'VRED Viewpoint render %s:%s' % (scene_name, ','.join(self.viewpoints))
461
462 self.frame_range = frame_range
463 self['package']['range'] = self.frame_range
464
465 self.frame_padding = frame_padding
466 self['package']['padding'] = self.frame_padding
467
468 self['package']['smartAgenda'] = True
469
470 if job_label:
471 self['label'] = job_label
472
473 self.addJobCmds(self._jobSetupCmds())
474
475 self['agenda'] = self._buildAgenda()
476
478 cmds = []
479
480 cmds.append('vrController.newScene()')
481 cmds.append('sys.stderr = sys.__stderr__')
482 cmds.append('sys.stdout = sys.__stdout__')
483 cmds.append('vrOSGWidget.setRenderQuality(vrOSGWidget.%s)' % self.render_quality)
484 cmds.append('vrFileIO.load(QB_CONVERT_PATH("%s"))' % self.project_path)
485
486 return cmds
487
489 """
490 Create an agenda for the job, complete with per-frame python commands.
491
492 @return: The populated work agenda for the job
493 @rtype: C{list}
494 """
495 agenda = []
496
497 render_opts = {
498 'filename': self.image_path_template,
499 'width': self.img_width,
500 'height': self.img_height,
501 'ssf': self.ssf,
502 'alpha': self.alpha,
503 'alphaR': self.alphaR,
504 'alphaG': self.alphaG,
505 'alphaB': self.alphaB,
506 'dpi': self.dpi,
507 'overwrite': True,
508 'showImage': False,
509 }
510
511 if self.frame_range:
512 for frame_num in [x['name'] for x in qb.genframes(self.frame_range)]:
513 for vp in self.viewpoints:
514 cmds = []
515
516 vp_render_opts = render_opts.copy()
517 vp_render_opts['filename'] = self._buildImageName(vp, frame_number=frame_num)
518
519 work = {
520 'name': 'f%s - %s' % (frame_num, vp),
521 'package': {
522 'commands': cmds
523 },
524 'resultpackage': {
525 'outputPaths': vp_render_opts['filename']
526 },
527 }
528 cmds.append('vrCameraEditor.jumpViewPoint("%s")' % vp)
529 cmds.append('vrAnimWidgets.setCurrentFrame(%s)' % frame_num)
530 cmds.append('vrMovieExport.createSnapshot("%(filename)s", %(width)s, %(height)s, %(ssf)s, %(alpha)s, %(alphaR)s, %(alphaG)s, %(alphaB)s, %(dpi)s, %(overwrite)s, %(showImage)s)' % vp_render_opts)
531
532 agenda.append(work)
533 else:
534 for vp in self.viewpoints:
535 cmds = []
536
537 vp_render_opts = render_opts.copy()
538 vp_render_opts['filename'] = self._buildImageName(vp)
539
540 work = {
541 'name': vp,
542 'package': {
543 'commands': cmds
544 },
545 'resultpackage': {
546 'outputPaths': vp_render_opts['filename']
547 },
548 }
549 cmds.append('vrCameraEditor.jumpViewPoint("%s")' % vp)
550 cmds.append('vrAnimWidgets.setCurrentFrame(1)')
551 cmds.append('vrMovieExport.createSnapshot("%(filename)s", %(width)s, %(height)s, %(ssf)s, %(alpha)s, %(alphaR)s, %(alphaG)s, %(alphaB)s, %(dpi)s, %(overwrite)s, %(showImage)s)' % vp_render_opts)
552
553 agenda.append(work)
554
555 return agenda
556
558 image_name = self.image_path_template
559
560 if self.image_path_template.count('#'):
561 RGX_IMG_PATH = re.compile('(#+)')
562 else:
563 image_format = self.image_path_template.split('.')[-1]
564 RGX_IMG_PATH = re.compile('(%s)$' % image_format)
565
566 if frame_number:
567 frame_number_padded = '%0*d' % (self.frame_padding, int(frame_number))
568 if RGX_IMG_PATH.pattern.count('#'):
569 repl_str = '%s' % str(frame_number_padded)
570 else:
571 repl_str = r'%s.\1' % str(frame_number_padded)
572 image_name = RGX_IMG_PATH.sub(repl_str, self.image_path_template)
573
574 image_name = re.sub('<VRED_VIEWPOINT>', vp_name, image_name)
575
576 return image_name
577
578
579
580 if __name__ == '__main__':
581 """
582 A "hello world", meant to show how to build and submit a VRED dynamic allocation job using the pythonChildJob framework.
583 """
584
585
586
587 jobList = []
588
589 VRED_dir = 'C:/Program Files/Autodesk/VREDCluster-8.03/Bin/WIN64'
590
591
592 vred_exe = '%s/VREDServerNode.exe' % VRED_dir
593
594 vred_args = ''
595
596
597
598 vred_scene = 'C:/VRED_Working/simple_cube.vpb'
599
600 sequences = []
601
602
603
604
605 frame_range = '1-100x25'
606 frame_range = '1-10'
607
608 jobA = VRED_SequencerRenderJob(vred_exe, vred_scene, sequences, vred_args=vred_args, dev=False)
609
610 jobA['cpus'] = 1
611 jobA['name'] += 'VRED sequencer test'
612 jobList.append(jobA)
613
614 if '--arc' in sys.argv:
615 arcSize = qb.archivejob('job.qja', jobA, format=qb.QB_API_BINARY)
616 print 'job.qja: %s bytes' % arcSize
617 else:
618 for j in qb.submit(jobList):
619 print 'submitted: %(id)s' % j
620
621 sys.exit()
622