def insertReference( destFile, path, reffile, primPath=None, offset=0, scale=1 ): if os.path.exists( destFile ): stage = Usd.Stage.Open( destFile ) if not stage: soho.error("Could not open USD file: " + destFile) frameRange, defaultPrim, firstRoot = getMetaData( reffile ) existingRefPath = None returnVal = None for p in stage.GetRootLayer().rootPrims: returnVal = findMatchingReference( p, reffile ) if returnVal: break layerOffset = Sdf.LayerOffset(offset, scale) if returnVal: existingRefPath, existingPrimPath, existingLayerOffset = returnVal keepPrimPath = True if primPath: if primPath != existingPrimPath: keepPrimPath = False elif defaultPrim and defaultPrim != existingPrimPath: keepPrimPath = False elif firstRoot and firstRoot.pathString != existingPrimPath: keepPrimPath = False if ( existingRefPath == path and layerOffset == existingLayerOffset and keepPrimPath ): # Our exact link already exists. sys.exit() else: # There is a existing link to our file but we want to rename it, # target a new prim path or add/change the layer offset. # Delete the old link. prim = stage.GetPrimAtPath( existingRefPath ) refList = prim.GetReferences() existingRef = Sdf.Reference( reffile, existingPrimPath, layerOffset=existingLayerOffset ) refList.RemoveReference(existingRef) else: frameRange, defaultPrim, firstRoot = getMetaData( reffile ) stage = Usd.Stage.CreateNew( destFile ) if not stage: soho.error( "Could not create USD file: " + destFile ) if frameRange and not stage.HasAuthoredTimeCodeRange(): stage.SetStartTimeCode(frameRange[0]) stage.SetEndTimeCode(frameRange[1]) # If the the file that we are referencing defines a default prim, # we can use it (targetPrim = None). Otherwise, use rootPrim. An existing # or provided prim path overrides either. if not primPath: primPath = firstRoot if not defaultPrim else None addReference( stage, path, reffile, primPath, layerOffset=layerOffset ) stage.GetRootLayer().Save()
def _write_light(light, base_channel, data, wrangler, cam, now): """Write a light to the ifd. :param light: The light to write. :type light: soho.SohoObject :param base_channel: The channel name. :type base_channel: str :param data: AOV data. :type data: dict :param wrangler: A SOHO wrangler. :type wrangler: object :param cam: A SOHO camera. :type cam: soho.SohoObject :param now: The evaluation time. :type now: float :return: """ import soho # Try and find the suffix using the 'vm_export_suffix' # parameter. If it doesn't exist, use an empty string. suffix = light.getDefaultedString("vm_export_suffix", now, [''])[0] prefix = [] # Look for the prefix parameter. If it doesn't exist, use # the light's name and replace the '/' with '_'. The # default value of 'vm_export_prefix' is usually $OS. if not light.evalString("vm_export_prefix", now, prefix): prefix = [light.getName()[1:].replace('/', '_')] # If there is a prefix we construct the channel name using # it and the suffix. if prefix: channel = "{}_{}{}".format(prefix[0], base_channel, suffix) # If not and there is a valid suffix, add it to the channel # name. elif suffix: channel = "{}{}".format(base_channel, suffix) # Throw an error because all the per-light channels will # have the same name. else: soho.error("Empty suffix for per-light exports.") channel = base_channel data[consts.CHANNEL_KEY] = channel data[consts.LIGHTEXPORT_KEY] = light.getName() # Write this light export to the ifd. _write_data_to_ifd(data, wrangler, cam, now)
def main(): parameters = soho.evaluate(parameterDefines) # # init soho # logger = logging.getLogger() oldHandlers = logger.handlers handler = logging.StreamHandler( stream = sys.__stderr__ ) logger.handlers = [handler] ropName = parameters['ropname'].Value[0] node = hou.node( ropName ) vStr = node.type().nameComponents()[-1] version = 0 if not vStr else int( vStr ) now = parameters['now'].Value[0] soho.initialize(now, '') soho.lockObjects(now) if parameters['trange'].Value[0] == 0: ff = lf = int(now * parameters['fps'].Value[0] + 1) else: ff = int(parameters['f'].Value[0]) lf = int(parameters['f'].Value[1]) stride = int(parameters['f'].Value[2]) sourcefiles = parameters['sourcefiles'].Value[0] outfile = parameters['outfile'].Value[0] try: coalesceFiles( outfile, sourcefiles, range(ff,lf+1), stride ) except Exception as e: soho.error( 'Failed to stitch USD files: ' + str(e) + '\n' + traceback.format_exc()) finally: logger.handlers = oldHandlers
def insertReference( destFile, path, reffile ): if os.path.exists( destFile ): stage = Usd.Stage.Open( destFile ) if not stage: soho.error("Could not open USD file: " + destFile) existingRefPath = None for p in stage.GetRootLayer().rootPrims: existingRefPath = findMatchingReference( p, reffile ) if existingRefPath: break if existingRefPath: if existingRefPath == path: # Our link already exists. sys.exit() else: # There is a existing link to our file but we want to rename it. # Delete the old link stage.RemovePrim(existingRefPath) frameRange, defaultPrim, firstRoot = getMetaData( reffile ) else: frameRange, defaultPrim, firstRoot = getMetaData( reffile ) stage = Usd.Stage.CreateNew( destFile ) if not stage: soho.error( "Could not create USD file: " + destFile ) if frameRange and not stage.HasAuthoredTimeCodeRange(): stage.SetStartTimeCode(frameRange[0]) stage.SetEndTimeCode(frameRange[1]) # If the the file that we are referencing defines a default prim, # we can use it (targetPrim = None). Otherwise, use rootPrim. addReference( stage, path, reffile, firstRoot if not defaultPrim else None ) stage.GetRootLayer().Save()
def _lightExportPlanes(self, data, wrangler, cam, now): """Handle exporting the image planes based on their export settings.""" import soho base_channel = data["channel"] # Handle any light exporting. if self.lightexport is not None: # Get a list of lights matching our mask and selection. lights = cam.objectList("objlist:light", now, self.lightexport_scope, self.lightexport_select) if self.lightexport == "per-light": # Process each light. for light in lights: # Try and find the suffix using the 'vm_export_suffix' # parameter. If it doesn't exist, use an emptry string. suffix = light.getDefaultedString("vm_export_suffix", now, [''])[0] prefix = [] # Look for the prefix parameter. If it doesn't exist, use # the light's name and replace the '/' with '_'. The # default value of 'vm_export_prefix' is usually $OS. if not light.evalString("vm_export_prefix", now, prefix): prefix = [light.getName()[1:].replace('/', '_')] # If there is a prefix we construct the channel name using # it and the suffix. if prefix: channel = "{}_{}{}".format(prefix[0], base_channel, suffix) # If not and there is a valid suffix, add it to the channel # name. elif suffix: channel = "{}{}".format(base_channel, suffix) # Throw an error because all the per-light channels will # have the same name. else: soho.error("Empty suffix for per-light exports.") channel = base_channel data["channel"] = channel data["lightexport"] = light.getName() # Write this light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) elif self.lightexport == "single": # Take all the light names and join them together. lightexport = ' '.join([light.getName() for light in lights]) # If there are no lights, we can't pass in an empty string # since then mantra will think that light exports are # disabled. So pass down an string that presumably doesn't # match any light name. if not lightexport: lightexport = "__nolights__" data["lightexport"] = lightexport # Write the combined light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) elif self.lightexport == "per-category": # A mapping between category names and their member lights. category_map = {} # Process each selected light. for light in lights: # Get the category for the light. categories = [] light.evalString("categories", now, categories) # Light doesn't have a 'categories' parameter. if not categories: continue # Get the raw string. categories = categories[0] # Since the categories value can be space or comma # separated we replace the commas with spaces then split. categories = categories.replace(',', ' ') categories = categories.split() # If the categories list was empty, put the light in a fake # category. if not categories: no_category_lights = category_map.setdefault(None, []) no_category_lights.append(light) else: # For each category the light belongs to, add it to # the list. for category in categories: category_lights = category_map.setdefault( category, []) category_lights.append(light) # Process all the found categories and their member lights. for category, lights in category_map.iteritems(): # Construct the export string to contain all the member # lights. lightexport = ' '.join( [light.getName() for light in lights]) data["lightexport"] = lightexport if category is not None: # The channel is the regular channel named prefixed with # the category name. data["channel"] = "{}_{}".format( category, base_channel) else: data["channel"] = base_channel # Write the per-category light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) else: # Write a normal AOV definition. self.writeDataToIfd(data, wrangler, cam, now)
def soho_render(): control_parms = { # The time at which the scene is being rendered "now": SohoParm("state:time", "real", [0], False, key="now"), "camera": SohoParm("camera", "string", ["/obj/cam1"], False), } parms = soho.evaluate(control_parms) now = parms["now"].Value[0] camera = parms["camera"].Value[0] options = {} if not soho.initialize(now, camera, options): soho.error("Unable to initialize rendering module with given camera") object_selection = { # Candidate object selection "vobject": SohoParm("vobject", "string", ["*"], False), "alights": SohoParm("alights", "string", ["*"], False), "forceobject": SohoParm("forceobject", "string", [""], False), "forcelights": SohoParm("forcelights", "string", [""], False), "excludeobject": SohoParm("excludeobject", "string", [""], False), "excludelights": SohoParm("excludelights", "string", [""], False), "sololight": SohoParm("sololight", "string", [""], False), } for cam in soho.objectList("objlist:camera"): break else: soho.error("Unable to find viewing camera for render") objparms = cam.evaluate(object_selection, now) stdobject = objparms["vobject"].Value[0] stdlights = objparms["alights"].Value[0] forceobject = objparms["forceobject"].Value[0] forcelights = objparms["forcelights"].Value[0] excludeobject = objparms["excludeobject"].Value[0] excludelights = objparms["excludelights"].Value[0] sololight = objparms["sololight"].Value[0] forcelightsparm = "forcelights" if sololight: stdlights = excludelights = "" forcelights = sololight forcelightsparm = "sololight" # First, we add objects based on their display flags or dimmer values soho.addObjects( now, stdobject, stdlights, "", True, geo_parm="vobject", light_parm="alights", fog_parm="", ) soho.addObjects( now, forceobject, forcelights, "", False, geo_parm="forceobject", light_parm=forcelightsparm, fog_parm="", ) soho.removeObjects( now, excludeobject, excludelights, "", geo_parm="excludeobject", light_parm="excludelights", fog_parm="", ) # Lock off the objects we've selected soho.lockObjects(now) with hou.undos.disabler(), scene_state: if "SOHO_PBRT_DEV" in os.environ: # pragma: no coverage import cProfile pr = cProfile.Profile() pr.enable() try: PBRTscene.render(cam, now) finally: pr.disable() pr.dump_stats("hou-prbt.stats") else: PBRTscene.render(cam, now) return
project = bool(parmlist['render_viewcamera'].Value[0]) projection_attribute = parmlist['projection_attribute'].Value[0] attribute_rendering_resolution = [ parmlist['attribute_rendering_resolution'].Value[0], parmlist['attribute_rendering_resolution'].Value[1] ] attribute_scale_by_resolution = bool( parmlist['attribute_scale_by_resolution'].Value[0]) now = parmlist['now'].Value[0] camera = parmlist['camera'].Value[0] fps = parmlist['fps'].Value[0] options = {"state:autoheadlight": False} if not soho.initialize(now=now, camera=camera, options=options): soho.error('Unable to initialize rendering module with camera: {0}'.format( repr(camera))) for cam in soho.objectList('objlist:camera'): break else: soho.error("Unable to find viewing camera for render") camParms = { 'space:world': soho.SohoParm('space:world', 'real', [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], False), 'focal': soho.SohoParm('focal', 'real', [0.050], False), 'aperture': soho.SohoParm('aperture', 'real', [0.0414214], False), 'orthowidth':
# Evaluate the 'camera' parameter as a string. # If the 'camera' parameter # doesn't exist, use ['/obj/cam1']. # SOHO always returns lists of values. camera = soho.getDefaultedString('camera', ['/obj/cam1'])[0] # However, for our purposes, we don't actually need a camera, so... camera = None # Evaluate an intrinsic parameter (see HDK_SOHO_API::evaluate()) # The 'state:time' parameter evaluates the time from the ROP. evaltime = soho.getDefaultedFloat('state:time', [0.0])[0] # Initialize SOHO with the camera. if not soho.initialize(evaltime, camera): soho.error('Unable to initialize rendering module with camera: %s' % repr(camera)) # Now, add objects to our scene # addObjects(time, geometry, light, fog, use_display_flags) soho.addObjects(evaltime, "*", "*", "*", True) # Before we can evaluate the scene from SOHO, we need to lock the object lists. soho.lockObjects(evaltime) # Now, traverse all the objects def outputObjects(fp, prefix, list): fp.write('%s = {' % prefix) for obj in list: fp.write('"%s",' % obj.getName()) fp.write('}\n')
def outputPlanes(self, wrangler, cam, now): """Output all necessary planes. Args: wrangler : (Object) A wrangler object. cam : (soho.SohoObject) The camera being rendered. now : (float) The parameter evaluation time. Raises: N/A Returns: None """ import soho # The base data to pass along. data = { "variable": self.variable, "vextype": self.vextype, "channel": self.channel, "quantize": self.quantize, "planefile": self.planefile } if self.pfilter: data["pfilter"] = self.pfilter if self.sfilter: data["sfilter"] = self.sfilter # Apply any conditionals before the light export phase. if self.conditionals: for conditional in self.conditionals: data.update(conditional.getData(wrangler, cam, now)) # Handle any light exporting. if self.lightexport is not None: # Get a list of lights matching out mask and selection. lights = cam.objectList( "objlist:light", now, self.lightmask, self.lightselection ) if self.lightexport == "per-light": # Process each light. for light in lights: # Try and find the suffix using the 'vm_export_suffix' # parameter. If it doesn't exist, use an emptry string. suffix = light.getDefaultedString( "vm_export_suffix", now, [''] )[0] prefix = [] # Look for the prefix parameter. If it doesn't exist, use # the light's name and replace the '/' with '_'. The # default value of 'vm_export_prefix' is usually $OS. if not light.evalString("vm_export_prefix", now, prefix): prefix = [light.getName()[1:].replace('/', '_')] # If there is a prefix we construct the channel name using # it and the suffix. if prefix: channel = "{0}_{1}{2}".format( prefix[0], self.channel, suffix ) # If not and there is a valid suffix, add it to the channel # name. elif suffix: channel = "{0}{1}".format(self.channel, suffix) # Throw an error because all the per-light channels will # have the same name. else: soho.error("Empty suffix for per-light exports.") data["channel"] = channel data["lightexport"] = light.getName() # Write this light export to the ifd. self.writeToIfd(data, wrangler, cam, now) elif self.lightexport == "single": # Take all the light names and join them together. lightexport = ' '.join([light.getName() for light in lights]) # If there are no lights, we can't pass in an empty string # since then mantra will think that light exports are # disabled. So pass down an string that presumably doesn't # match any light name. if not lightexport: lightexport = "__nolights__" data["lightexport"] = lightexport # Write the combined light export to the ifd. self.writeToIfd(data, wrangler, cam, now) elif self.lightexport == "per-category": # A mapping between category names and their member lights. categoryMap = {} # Process each selected light. for light in lights: # Get the category for the light. categories = [] light.evalString("categories", now, categories) # Light doesn't have a 'categories' parameter. if not categories: continue # Get the raw string. categories = categories[0] # Since the categories value can be space or comma # separated we replace the commas with spaces then split. categories = categories.replace(',', ' ') categories = categories.split() # If the categories list was empty, put the light in a fake # category. if not categories: noCatLights = categoryMap.setdefault("__none__", []) noCatLights.append(light) else: # For each category the light belongs to, add it to # the list. for category in categories: catLights = categoryMap.setdefault(category, []) catLights.append(light) # Process all the found categories and their member lights. for category, lights in categoryMap.iteritems(): # Construct the export string to contain all the member # lights. lightexport = ' '.join( [light.getName() for light in lights] ) data["lightexport"] = lightexport # The channel is the regular channel named prefixed with # the category name. data["channel"] = "{0}_{1}".format(category, self.channel) # Write the per-category light export to the ifd. self.writeToIfd(data, wrangler, cam, now) else: # Write a normal plane definition. self.writeToIfd(data, wrangler, cam, now)
############################################################################### parameterDefines = { 'f': soho.SohoParm('f', 'real', [1, 1, 1], False), 'now': soho.SohoParm('state:time', 'real', [0], False, key='now'), 'destfile': soho.SohoParm('destfile', 'string', [''], False), 'path': soho.SohoParm('path', 'string', [''], False), 'reffile': soho.SohoParm('reffile', 'string', [''], False), } parameters = soho.evaluate(parameterDefines) # # init soho # now = parameters['now'].Value[0] soho.initialize(now, '') soho.lockObjects(now) destFile = parameters['destfile'].Value[0] path = parameters['path'].Value[0] reffile = parameters['reffile'].Value[0] try: insertReference(destFile, path, reffile) except Exception as e: soho.error('Failed to add USD file reference: ' + str(e))
def wrangle_camera(obj, wrangler, now): node = wrangle_node_parm(obj, "camera_node", now) if node is not None: output_cam_xform(obj, node.directive_type, now) return node.type_and_paramset paramset = ParamSet() window = obj.getCameraScreenWindow(wrangler, now) parm_selection = { "projection": SohoPBRT("projection", "string", ["perspective"], False), "focal": SohoPBRT("focal", "float", [50], False), "focalunits": SohoPBRT("focalunits", "string", ["mm"], False), "aperture": SohoPBRT("aperture", "float", [41.4214], False), "orthowidth": SohoPBRT("orthowidth", "float", [2], False), "res": SohoPBRT("res", "integer", [1280, 720], False), "aspect": SohoPBRT("aspect", "float", [1], False), "fstop": SohoPBRT("fstop", "float", [5.6], False), "focaldistance": SohoPBRT("focus", "float", [5], False, key="focaldistance"), "pbrt_dof": SohoPBRT("pbrt_dof", "integer", [0], False), } parms = obj.evaluate(parm_selection, now) aspect = parms["aspect"].Value[0] aspectfix = aspect * float(parms["res"].Value[0]) / float(parms["res"].Value[1]) projection = parms["projection"].Value[0] if parms["pbrt_dof"].Value[0]: paramset.add(parms["focaldistance"].to_pbrt()) # to convert from f-stop to lens radius # FStop = FocalLength / (Radius * 2) # Radius = FocalLength/(FStop * 2) focal = parms["focal"].Value[0] fstop = parms["fstop"].Value[0] units = parms["focalunits"].Value[0] focal = soho.houdiniUnitLength(focal, units) lens_radius = focal / (fstop * 2.0) paramset.add(PBRTParam("float", "lensradius", lens_radius)) if projection == "perspective": projection_name = "perspective" focal = parms["focal"].Value[0] aperture = parms["aperture"].Value[0] fov = 2.0 * focal / aperture fov = 2.0 * math.degrees(math.atan2(1.0, fov)) paramset.add(PBRTParam("float", "fov", [fov])) screen = [ (window[0] - 0.5) * 2.0, (window[1] - 0.5) * 2.0, (window[2] - 0.5) * 2.0 / aspectfix, (window[3] - 0.5) * 2.0 / aspectfix, ] paramset.add(PBRTParam("float", "screenwindow", screen)) elif projection == "ortho": projection_name = "orthographic" width = parms["orthowidth"].Value[0] screen = [ (window[0] - 0.5) * width, (window[1] - 0.5) * width, (window[2] - 0.5) * width / aspectfix, (window[3] - 0.5) * width / aspectfix, ] paramset.add(PBRTParam("float", "screenwindow", screen)) elif projection == "sphere": projection_name = "environment" else: soho.error("Camera projection setting of %s not supported by PBRT" % projection) output_cam_xform(obj, projection_name, now) return (projection_name, paramset)
for sourcefile, operation, destfile in zip(sourcefiles, operations, destfiles): sourcefile = sourcefile.replace('%d', str(i)) destfile = destfile.replace('%d', str(i)) if not sourcefile or not destfile: continue inserting = operation == 0 appending = operation == 1 removing = operation == 2 # check parms if not os.path.exists(destfile): soho.error("destfile does not exist: " + destfile) # modify the sublayers if needed from pxr import Sdf destLayer = Sdf.Layer.FindOrOpen(destfile) if not destLayer: soho.error("could not open destfile: " + destfile) if inserting: if sourcefile not in destLayer.subLayerPaths: if not os.access(destfile, os.W_OK): soho.error("destfile is not writable: " + destfile) destLayer.subLayerPaths.insert(0, sourcefile) if not destLayer.Save(): soho.error("could not save destfile: " + destfile)
def override_paramset(self, overrides): """Get a paramset with overrides applied Args: override_str (str): A string with the overrides (material_override) Returns: ParamSet with matching overrides applied """ paramset = ParamSet() if not overrides: return paramset for override_name, override in overrides.iteritems(): # The override can have a node_name/parm format which allows for point # instance overrides to override parms in a network. cached_override = self.override_cache.get(override_name, None) if cached_override is not None: if isinstance(cached_override, PBRTParam): # textures which can't be overridden paramset.add(cached_override) continue elif cached_override == -1: # Hint to just skip continue pbrt_name, pbrt_type, tuple_names = cached_override if tuple_names: value = [overrides[x] for x in tuple_names] else: value = override pbrt_param = PBRTParam(pbrt_type, pbrt_name, value) paramset.add(pbrt_param) continue override_match = self.override_pat.match(override_name) if override_match is None: soho.error( "{} is not a valid override parm".format(override_name)) spectrum_type = override_match.group("spectrum") parm_name = override_match.group("parm") override_node = override_match.group("node") if override_node is not None and override_node != self.name: self.override_cache[override_name] = -1 continue # There can be two style of "overrides" one is a straight parm override # which is similar to what Houdini does. The other style of override is # for the spectrum type parms. Since spectrum parms can be of different # types and the Material Overrides only support "rgb" we are limited # in the types of spectrum overrides we can do. To work around this we'll # support a different style, override_parm:spectrum_type. If the parm name # ends in one of the "rgb/color" types then we'll handle it differently. # TODO add a comment as to what the value would look like # NOTE: The material SOP will use a parm style dictionary if there # parm name matches exactly # ie) if there is a color parm you will get # {'colorb':0.372511,'colorg':0.642467,'colorr':0.632117,} # But if the parm name doesn't match (which we are allowing # for you will get something like this - # {'colora':(0.632117,0.642467,0.372511),} # Once we have a parm name, we need to determine what "style" it is. # Whether its a hou.ParmTuple or hou.Parm style. tuple_names = tuple() parm_tuple = self.node.parmTuple(parm_name) if parm_tuple is None: # We couldn't find a tuple of that name, so let's try a parm parm = self.node.parm(parm_name) if parm is None: # Nope, not valid either, let's move along self.override_cache[override_name] = -1 continue # if its a parm but not a parmtuple it must be a split. parm_tuple = parm.tuple() # we need to "combine" these and process them all at once and # then skip any other occurances. The skipping is handled by # the overall caching mechanism. self.override_cache tuple_names = tuple([x.name() for x in parm_tuple]) # This is for wrangling parm names of texture nodes due to having a # signature parm. pbrt_name = self.pbrt_parm_name(parm_tuple) if spectrum_type is None and tuple_names: # This is a "traditional" override, no spectrum or node name prefix value = [overrides[x] for x in tuple_names] pbrt_param = self._hou_parm_to_pbrt_param( parm_tuple, pbrt_name, value) elif spectrum_type is None and not tuple_names: pbrt_param = self._hou_parm_to_pbrt_param( parm_tuple, pbrt_name, override) elif spectrum_type in PBRTParam.spectrum_types: pbrt_param = PBRTParam(spectrum_type, pbrt_name, override) else: raise ValueError("Unable to wrangle override name: %s" % override_name) paramset.add(pbrt_param) # From here to the end of the loop is to allow for caching if pbrt_param.type == "texture": self.override_cache[override_name] = pbrt_param continue # we are making an assumption a split parm will never be a spectrum # or have a node prefix. The Material SOP doesn't allow for it as well. for name in tuple_names: # The -1 means "continue" self.override_cache[name] = -1 # Sanity check if tuple_names and override_name not in tuple_names: raise ValueError( "Override name: %s, not valid for a parmTuple" % override_name) # override_name must match one of the tuple_names self.override_cache[override_name] = ( pbrt_param.name, pbrt_param.param_type, tuple_names, ) return paramset
def soho_render(): control_parms = { # The time at which the scene is being rendered "now": SohoParm("state:time", "real", [0], False, key="now") } parms = soho.evaluate(control_parms) now = parms["now"].Value[0] camera = None options = {} if not soho.initialize(now, camera, options): soho.error("Unable to initialize rendering module with given camera") object_selection = { # Candidate object selection "vobject": SohoParm("vobject", "string", ["*"], False), "forceobject": SohoParm("forceobject", "string", [""], False), "excludeobject": SohoParm("excludeobject", "string", [""], False), } objparms = soho.evaluate(object_selection, now) stdobject = objparms["vobject"].Value[0] forceobject = objparms["forceobject"].Value[0] excludeobject = objparms["excludeobject"].Value[0] # First, we add objects based on their display flags or dimmer values soho.addObjects(now, stdobject, "", "", True, geo_parm="vobject", light_parm="", fog_parm="") soho.addObjects( now, forceobject, "", "", False, geo_parm="forceobject", light_parm="", fog_parm="", ) soho.removeObjects(now, excludeobject, "", "", geo_parm="excludeobject", light_parm="", fog_parm="") # Lock off the objects we've selected soho.lockObjects(now) with hou.undos.disabler(), scene_state: if "SOHO_PBRT_DEV" in os.environ: # pragma: no coverage import cProfile pr = cProfile.Profile() pr.enable() try: PBRTscene.archive(now) finally: pr.disable() pr.dump_stats("hou-prbtarchive.stats") else: PBRTscene.archive(now) return
def outputPlanes(self, wrangler, cam, now): """Output all necessary planes. Args: wrangler : (Object) A wrangler object. cam : (soho.SohoObject) The camera being rendered. now : (float) The parameter evaluation time. Raises: N/A Returns: None """ import soho # The base data to pass along. data = { "variable": self.variable, "vextype": self.vextype, "channel": self.channel, "quantize": self.quantize, "planefile": self.planefile } if self.pfilter: data["pfilter"] = self.pfilter if self.sfilter: data["sfilter"] = self.sfilter # Apply any conditionals before the light export phase. if self.conditionals: for conditional in self.conditionals: data.update(conditional.getData(wrangler, cam, now)) # Handle any light exporting. if self.lightexport is not None: # Get a list of lights matching out mask and selection. lights = cam.objectList("objlist:light", now, self.lightmask, self.lightselection) if self.lightexport == "per-light": # Process each light. for light in lights: # Try and find the suffix using the 'vm_export_suffix' # parameter. If it doesn't exist, use an emptry string. suffix = light.getDefaultedString("vm_export_suffix", now, [''])[0] prefix = [] # Look for the prefix parameter. If it doesn't exist, use # the light's name and replace the '/' with '_'. The # default value of 'vm_export_prefix' is usually $OS. if not light.evalString("vm_export_prefix", now, prefix): prefix = [light.getName()[1:].replace('/', '_')] # If there is a prefix we construct the channel name using # it and the suffix. if prefix: channel = "{0}_{1}{2}".format(prefix[0], self.channel, suffix) # If not and there is a valid suffix, add it to the channel # name. elif suffix: channel = "{0}{1}".format(self.channel, suffix) # Throw an error because all the per-light channels will # have the same name. else: soho.error("Empty suffix for per-light exports.") data["channel"] = channel data["lightexport"] = light.getName() # Write this light export to the ifd. self.writeToIfd(data, wrangler, cam, now) elif self.lightexport == "single": # Take all the light names and join them together. lightexport = ' '.join([light.getName() for light in lights]) # If there are no lights, we can't pass in an empty string # since then mantra will think that light exports are # disabled. So pass down an string that presumably doesn't # match any light name. if not lightexport: lightexport = "__nolights__" data["lightexport"] = lightexport # Write the combined light export to the ifd. self.writeToIfd(data, wrangler, cam, now) elif self.lightexport == "per-category": # A mapping between category names and their member lights. categoryMap = {} # Process each selected light. for light in lights: # Get the category for the light. categories = [] light.evalString("categories", now, categories) # Light doesn't have a 'categories' parameter. if not categories: continue # Get the raw string. categories = categories[0] # Since the categories value can be space or comma # separated we replace the commas with spaces then split. categories = categories.replace(',', ' ') categories = categories.split() # If the categories list was empty, put the light in a fake # category. if not categories: noCatLights = categoryMap.setdefault("__none__", []) noCatLights.append(light) else: # For each category the light belongs to, add it to # the list. for category in categories: catLights = categoryMap.setdefault(category, []) catLights.append(light) # Process all the found categories and their member lights. for category, lights in categoryMap.iteritems(): # Construct the export string to contain all the member # lights. lightexport = ' '.join( [light.getName() for light in lights]) data["lightexport"] = lightexport # The channel is the regular channel named prefixed with # the category name. data["channel"] = "{0}_{1}".format(category, self.channel) # Write the per-category light export to the ifd. self.writeToIfd(data, wrangler, cam, now) else: # Write a normal plane definition. self.writeToIfd(data, wrangler, cam, now)
def export(): """Main export function.""" is_last = False try: T = timer('FrameExport') ps = soho.evaluate({ 'now': SohoParm('state:time', 'real', [0], False, key='now'), 'fps': SohoParm('state:fps', 'real', [24], False, key='fps'), 'hver': SohoParm('state:houdiniversion', 'string', [''], False, key='hver'), 'objpath': SohoParm('objpath', 'string', [''], False), 'abcoutput': SohoParm('abcoutput', 'string', [''], False), 'camera': SohoParm('camera', 'string', [None], False), 'trange': SohoParm('trange', 'int', [0], False), 'f': SohoParm('f', 'int', None, False) }) now = ps['now'].Value[0] fps = ps['fps'].Value[0] hver = ps['hver'].Value[0] camera = ps['camera'].Value[0] dbg("now=%.3f fps=%.3f" % (now, fps)) if not soho.initialize(now, camera): soho.error("couldn't initialize soho (make sure camera is set)") abc_cleanup() return # NOTE: this is prone to float inaccuracies frame = now*fps + 1.0 objpath = ps['objpath'].Value[0] abc_file = ps['abcoutput'].Value[0] trange = ps['trange'].Value[0] f = ps['f'].Value is_first = frame < f[0]+0.5 # working around float funniness is_last = frame > f[1]-0.5 if trange==0: is_first= is_last= True dbg("is_first=%d is_last=%d" % (is_first, is_last)) dbg("now=%.3f fps=%.3f -> %f" % (now, fps, frame)) dbg("objpath=%s camera=%s abcoutput=%s trange=%d f=%s" % \ (objpath, camera, abc_file, trange, str(f))) T.lap('init') # collect hierarchy to be exported # (read from scene directly, ie. not containing instances, etc.) # results in array [ (parentname, objname) [, ...] ] -- (full pathnames) # #dbg("COLLECTING ARCHY:") archy = collect_archy(objpath) archy_objs = [ n[1] for n in archy ] #dbg("DONE.") # collect geometry to be exported and their render SOPS # (including point- and other instances, etc) # (NOTE: the entire scene is to be searched, unfortunately) # soho.addObjects(now, '*', '*', '', do_culling=False) soho.lockObjects(now) soho_objs = {} # {objname: soho_obj} soho_only = {} # soho-only objects (can't be accessed directly with hdk) obj_list = [] sop_dict = {} # {objname: sopname} objs = soho.objectList('objlist:instance') #dbg("COLLECT soho instance/sop pairs ------------------") for obj in objs: n = obj.getName() # full pathname obj_list.append(n) soho_objs[n] = obj path = obj.getDefaultedString('object:soppath', now, [None])[0] #dbg(" -- %s (sop:%s)" % (n, str(path)) ) if path and path!="": sop_dict[n] = path T.lap('collect-objs') if False: dbg( '-' * 40 ) dbg("sop_dict: %s" % str(sop_dict)) # extend hierarchy with per-point instances # p1 = re.compile(":[^:]+:") for obj in obj_list: if re.search(p1, obj): m = obj.split(":") p = m[-2] # parent: 2nd from right if p in archy_objs: archy.append( ( p, obj, "%s__%s" % (m[-2], m[-1]) ) ) soho_only[obj]=p #dbg(" -+- %s %s" % (p, obj)) # fill rest of the archy array # elem: (parentpath, objpath, exportname, soppath) # archy2 = [] for a in archy: N = list(a) if len(N)<3: N.append(N[1]) # N = [ N[0], N[1], N[1] ] if N[1] in sop_dict: N = [ N[0], N[1], N[2], sop_dict[N[1]] ] else: # empty xform (no sop) N = [ N[0], N[1], N[1], None ] N[2] = re.search("[^/]+$", N[2]).group(0) archy2.append(N) archy = archy2 if False: dbg( '-' * 40 ) dbg("COLLECTED ARCHY:") for a in archy: dbg("- %s: " % (a[1], )) dbg("COLLECTED ARCHY: %d elems" % len(archy)) T.lap('got-archy') # we now have a list of all objects to be exported # (parentname, objname, exportname, soppath) # archy_objs = [ n[1] for n in archy ] skip_frame = False now_out = now+(1.0/fps) # check for user abort # if False: # TODO: check for user abort! skip_frame = True is_last = True warn("user abort") # first frame: init all internal stuff # if is_first: dbg("\n\n\n") dbg("IS_FIRST--INIT") G.archy = archy[:] G.archy_objs = archy_objs[:] s = abc_init(abc_file, tstep=1.0/fps, tstart=now_out) if s: # build objects for oarchive # for E in archy: objname = E[1] parent = E[0] outname = E[2] soppath = E[3] if parent is None: parent="-" if soppath is None: soppath="-" # TODO: if instance, objname should be the base obj name obj_src = objname if objname in soho_only: obj_src = soho_only[objname] #dbg("-- new xform\n\toutname= %s\n\tobj = %s\n\tparent = %s\n\tsop = %s" % (outname, objname, parent, soppath)) hou.hscript('%s newobject "%s" "%s" "%s" "%s" "%s"' % \ (CCMD, objname, obj_src, parent, outname, soppath)) # set object flags (static, etc.) # if objname in soho_objs: ps = soho_objs[objname].evaluate({ 'abc_staticgeo': SohoParm('abc_staticgeo', 'int', [0], False) }, now) if ps['abc_staticgeo'].Value[0]!=0: hou.hscript('%s objset "%s" static' % (CCMD, objname)) else: warn("couldn't output to file %s--aborting" % abc_file) skip_frame = True is_last = True T.lap('frame-first') # frame export: collect xforms, geoms, and export them # if archy_objs==G.archy_objs and not skip_frame: dbg("\n") dbg(" -- EXPORTING frame %.1f" % frame) for E in archy: #dbg("\n-") #dbg("- OBJ: %s" % str(E)) objname = E[1] soppath = E[3] #dbg("- OBJ: %s" % E[1]) # get xform matrix (TODO: get pretransform too!) # xform = '' # TODO: use this only for instances! #if objname in soho_objs: if objname in soho_only: # get matrix from soho #dbg(" --- (mtx from soho)") xform = [] soho_objs[objname].evalFloat('space:local', now, xform) xform = hou.Matrix4(xform) xform = ' '.join([ str(n) for n in xform.asTuple() ]) # perform sample write # (c++ code decides if geom is to be written) # if True: hou.hscript('%s writesample %f "%s" %s' % \ (CCMD, now_out, objname, xform)) else: #soho.error("couldn't export frame %.1f--no. of objects changed" % frame) warn("couldn't export frame %.1f--no. of objects changed" % frame) T.lap('frame-export') except: dbg("INTERRUPTED BY EXCEPTION") is_last=True # last frame: cleanup all internal stuff, # finish export # if is_last: dbg("\n\n\n") dbg("IS_LAST--FINISHING...") abc_cleanup() T.lap('frame-last') T.stats()
parmlist = soho.evaluate(controlParameters) now = parmlist['now'].Value[0] IFDapi.ForceEmbedVex = parmlist['embedvex'].Value[0] decl_shops = parmlist['decl'].Value[0] inheritedproperties = parmlist['vm_inheritproperties'].Value[0] options = {} if inheritedproperties: # Turn off object->output driver inheritance options['state:inheritance'] = '-rop' if not soho.initialize(now, None): soho.error("Unable to initialize rendering module") # # Add objects to the scene, we check for parameters on the viewing # camera. If the parameters don't exist there, they will be picked up # by the output driver. # objectSelection = { # Candidate object selection # Candidate object selection 'vobject' : SohoParm('vobject', 'string', ['*'], False), 'alights' : SohoParm('alights', 'string', ['*'], False), 'vfog' : SohoParm('vfog', 'string', ['*'], False), 'forceobject' : SohoParm('forceobject', 'string', [''], False), 'forcelights' : SohoParm('forcelights', 'string', [''], False),
# Extract the values from the evaluation now = parmlist['now'].Value[0] camera = parmlist['camera'].Value[0] fps = parmlist['fps'].Value[0] picture = parmlist['vm_picture'].Value[0] samples = parmlist['vm_samples'].Value[0] sampler = parmlist['vm_sampler'].Value[0] reflectlimit = parmlist['vm_reflectlimit'].Value[0] integrator = parmlist['vm_integrator'].Value[0] camera = parmlist['camera'].Value[0] skip_geo_export = parmlist['skip_geo_export'].Value[0] if not soho.initialize(now, camera): soho.error("Unable to initialize rendering module with given camera") objectSelection = { # Candidate object selection 'vobject' : SohoParm('vobject', 'string', ['*'], False), 'alights' : SohoParm('alights', 'string', ['*'], False), 'vfog' : SohoParm('vfog', 'string', ['*'], False), 'forceobject' : SohoParm('forceobject', 'string', [''], False), 'forcelights' : SohoParm('forcelights', 'string', [''], False), 'forcefog' : SohoParm('forcefog', 'string', [''], False), 'excludeobject' : SohoParm('excludeobject', 'string', [''], False), 'excludelights' : SohoParm('excludelights', 'string', [''], False), 'excludefog' : SohoParm('excludefog', 'string', [''], False),
parameterDefines = { 'f' : soho.SohoParm('f', 'real', [1, 1, 1], False), 'now' : soho.SohoParm('state:time', 'real', [0], False, key = 'now'), 'destfile' : soho.SohoParm('destfile', 'string', [''], False ), 'path' : soho.SohoParm('path', 'string', [''], False ), 'reffile' : soho.SohoParm('reffile', 'string', [''], False ), } parameters = soho.evaluate(parameterDefines) # # init soho # now = parameters['now'].Value[0] soho.initialize(now, '') soho.lockObjects(now) destFile = parameters['destfile'].Value[0] path = parameters['path'].Value[0] reffile = parameters['reffile'].Value[0] try: insertReference( destFile, path, reffile ) except Exception as e: soho.error( 'Failed to add USD file reference: ' + str(e) )
for sourcefile, operation, destfile in zip(sourcefiles, operations, destfiles): sourcefile = sourcefile.replace('%d',str(i) ) destfile = destfile.replace('%d',str(i) ) if not sourcefile or not destfile: continue inserting = operation == 0 appending = operation == 1 removing = operation == 2 # check parms if not os.path.exists(destfile): soho.error("destfile does not exist: " + destfile) # modify the sublayers if needed from pxr import Sdf destLayer = Sdf.Layer.FindOrOpen(destfile) if not destLayer: soho.error("could not open destfile: " + destfile) if inserting: if sourcefile not in destLayer.subLayerPaths: if not os.access(destfile, os.W_OK): soho.error("destfile is not writable: " + destfile) destLayer.subLayerPaths.insert(0,sourcefile) if not destLayer.Save(): soho.error("could not save destfile: " + destfile)
def soho_render(): control_parms = { # The time at which the scene is being rendered 'now': SohoParm('state:time', 'real', [0], False, key='now'), 'fps': SohoParm('state:fps', 'real', [24], False, key='fps'), 'camera': SohoParm('camera', 'string', ['/obj/cam1'], False), } parms = soho.evaluate(control_parms) now = parms['now'].Value[0] camera = parms['camera'].Value[0] fps = parms['fps'].Value[0] options = {'state:precision': 6} if not soho.initialize(now, camera, options): soho.error("Unable to initialize rendering module with given camera") object_selection = { # Candidate object selection 'vobject': SohoParm('vobject', 'string', ['*'], False), 'alights': SohoParm('alights', 'string', ['*'], False), 'forceobject': SohoParm('forceobject', 'string', [''], False), 'forcelights': SohoParm('forcelights', 'string', [''], False), 'excludeobject': SohoParm('excludeobject', 'string', [''], False), 'excludelights': SohoParm('excludelights', 'string', [''], False), 'sololight': SohoParm('sololight', 'string', [''], False), } for cam in soho.objectList('objlist:camera'): break else: soho.error('Unable to find viewing camera for render') objparms = cam.evaluate(object_selection, now) stdobject = objparms['vobject'].Value[0] stdlights = objparms['alights'].Value[0] forceobject = objparms['forceobject'].Value[0] forcelights = objparms['forcelights'].Value[0] excludeobject = objparms['excludeobject'].Value[0] excludelights = objparms['excludelights'].Value[0] sololight = objparms['sololight'].Value[0] forcelightsparm = 'forcelights' if sololight: stdlights = excludelights = None forcelights = sololight forcelightsparm = 'sololight' # First, we add objects based on their display flags or dimmer values soho.addObjects(now, stdobject, stdlights, '', True) soho.addObjects(now, forceobject, forcelights, '', False) soho.removeObjects(now, excludeobject, excludelights, '') # Lock off the objects we've selected soho.lockObjects(now) with hou.undos.disabler(), scene_state: PBRTscene.render(cam, now) return
def export(): """Main export function.""" is_last = False try: T = timer('FrameExport') ps = soho.evaluate({ 'now': SohoParm('state:time', 'real', [0], False, key='now'), 'fps': SohoParm('state:fps', 'real', [24], False, key='fps'), 'hver': SohoParm('state:houdiniversion', 'string', [''], False, key='hver'), 'objpath': SohoParm('objpath', 'string', [''], False), 'abcoutput': SohoParm('abcoutput', 'string', [''], False), 'camera': SohoParm('camera', 'string', [None], False), 'trange': SohoParm('trange', 'int', [0], False), 'f': SohoParm('f', 'int', None, False) }) now = ps['now'].Value[0] fps = ps['fps'].Value[0] hver = ps['hver'].Value[0] camera = ps['camera'].Value[0] dbg("now=%.3f fps=%.3f" % (now, fps)) if not soho.initialize(now, camera): soho.error("couldn't initialize soho (make sure camera is set)") abc_cleanup() return # NOTE: this is prone to float inaccuracies frame = now * fps + 1.0 objpath = ps['objpath'].Value[0] abc_file = ps['abcoutput'].Value[0] trange = ps['trange'].Value[0] f = ps['f'].Value is_first = frame < f[0] + 0.5 # working around float funniness is_last = frame > f[1] - 0.5 if trange == 0: is_first = is_last = True dbg("is_first=%d is_last=%d" % (is_first, is_last)) dbg("now=%.3f fps=%.3f -> %f" % (now, fps, frame)) dbg("objpath=%s camera=%s abcoutput=%s trange=%d f=%s" % \ (objpath, camera, abc_file, trange, str(f))) T.lap('init') # collect hierarchy to be exported # (read from scene directly, ie. not containing instances, etc.) # results in array [ (parentname, objname) [, ...] ] -- (full pathnames) # #dbg("COLLECTING ARCHY:") archy = collect_archy(objpath) archy_objs = [n[1] for n in archy] #dbg("DONE.") # collect geometry to be exported and their render SOPS # (including point- and other instances, etc) # (NOTE: the entire scene is to be searched, unfortunately) # soho.addObjects(now, '*', '*', '', do_culling=False) soho.lockObjects(now) soho_objs = {} # {objname: soho_obj} soho_only = { } # soho-only objects (can't be accessed directly with hdk) obj_list = [] sop_dict = {} # {objname: sopname} objs = soho.objectList('objlist:instance') #dbg("COLLECT soho instance/sop pairs ------------------") for obj in objs: n = obj.getName() # full pathname obj_list.append(n) soho_objs[n] = obj path = obj.getDefaultedString('object:soppath', now, [None])[0] #dbg(" -- %s (sop:%s)" % (n, str(path)) ) if path and path != "": sop_dict[n] = path T.lap('collect-objs') if False: dbg('-' * 40) dbg("sop_dict: %s" % str(sop_dict)) # extend hierarchy with per-point instances # p1 = re.compile(":[^:]+:") for obj in obj_list: if re.search(p1, obj): m = obj.split(":") p = m[-2] # parent: 2nd from right if p in archy_objs: archy.append((p, obj, "%s__%s" % (m[-2], m[-1]))) soho_only[obj] = p #dbg(" -+- %s %s" % (p, obj)) # fill rest of the archy array # elem: (parentpath, objpath, exportname, soppath) # archy2 = [] for a in archy: N = list(a) if len(N) < 3: N.append(N[1]) # N = [ N[0], N[1], N[1] ] if N[1] in sop_dict: N = [N[0], N[1], N[2], sop_dict[N[1]]] else: # empty xform (no sop) N = [N[0], N[1], N[1], None] N[2] = re.search("[^/]+$", N[2]).group(0) archy2.append(N) archy = archy2 if False: dbg('-' * 40) dbg("COLLECTED ARCHY:") for a in archy: dbg("- %s: " % (a[1], )) dbg("COLLECTED ARCHY: %d elems" % len(archy)) T.lap('got-archy') # we now have a list of all objects to be exported # (parentname, objname, exportname, soppath) # archy_objs = [n[1] for n in archy] skip_frame = False now_out = now + (1.0 / fps) # check for user abort # if False: # TODO: check for user abort! skip_frame = True is_last = True warn("user abort") # first frame: init all internal stuff # if is_first: dbg("\n\n\n") dbg("IS_FIRST--INIT") G.archy = archy[:] G.archy_objs = archy_objs[:] s = abc_init(abc_file, tstep=1.0 / fps, tstart=now_out) if s: # build objects for oarchive # for E in archy: objname = E[1] parent = E[0] outname = E[2] soppath = E[3] if parent is None: parent = "-" if soppath is None: soppath = "-" # TODO: if instance, objname should be the base obj name obj_src = objname if objname in soho_only: obj_src = soho_only[objname] #dbg("-- new xform\n\toutname= %s\n\tobj = %s\n\tparent = %s\n\tsop = %s" % (outname, objname, parent, soppath)) hou.hscript('%s newobject "%s" "%s" "%s" "%s" "%s"' % \ (CCMD, objname, obj_src, parent, outname, soppath)) # set object flags (static, etc.) # if objname in soho_objs: ps = soho_objs[objname].evaluate( { 'abc_staticgeo': SohoParm('abc_staticgeo', 'int', [0], False) }, now) if ps['abc_staticgeo'].Value[0] != 0: hou.hscript('%s objset "%s" static' % (CCMD, objname)) else: warn("couldn't output to file %s--aborting" % abc_file) skip_frame = True is_last = True T.lap('frame-first') # frame export: collect xforms, geoms, and export them # if archy_objs == G.archy_objs and not skip_frame: dbg("\n") dbg(" -- EXPORTING frame %.1f" % frame) for E in archy: #dbg("\n-") #dbg("- OBJ: %s" % str(E)) objname = E[1] soppath = E[3] #dbg("- OBJ: %s" % E[1]) # get xform matrix (TODO: get pretransform too!) # xform = '' # TODO: use this only for instances! #if objname in soho_objs: if objname in soho_only: # get matrix from soho #dbg(" --- (mtx from soho)") xform = [] soho_objs[objname].evalFloat('space:local', now, xform) xform = hou.Matrix4(xform) xform = ' '.join([str(n) for n in xform.asTuple()]) # perform sample write # (c++ code decides if geom is to be written) # if True: hou.hscript('%s writesample %f "%s" %s' % \ (CCMD, now_out, objname, xform)) else: #soho.error("couldn't export frame %.1f--no. of objects changed" % frame) warn("couldn't export frame %.1f--no. of objects changed" % frame) T.lap('frame-export') except: dbg("INTERRUPTED BY EXCEPTION") is_last = True # last frame: cleanup all internal stuff, # finish export # if is_last: dbg("\n\n\n") dbg("IS_LAST--FINISHING...") abc_cleanup() T.lap('frame-last') T.stats()
# -*- coding: utf-8 -*- import hou import soho import afanasy current_afnode = hou.pwd() submit_afnode_parm = current_afnode.parm('submit_afnode') if submit_afnode_parm is None: soho.error( 'Can\'t find "submit_afnode" parameter on "%s"' % current_afnode.path() ) submit_afnode_path = submit_afnode_parm.eval() if submit_afnode_path is None: soho.error( 'Can\'t eval "submit_afnode" parameter on "%s"' % current_afnode.path() ) if submit_afnode_path == '': soho.error( 'Empty "submit_afnode" parameter on "%s"' % current_afnode.path() ) submit_afnode = hou.node(submit_afnode_path) if submit_afnode is None: soho.error( 'Can\'t find "%s" node specified in "%s"' % (submit_afnode_path, current_afnode.path())
def main(): import sys import hou import soho import sohoglue import SOHOcommon import sys import ctypes if hasattr(sys, 'setdlopenflags'): sys.setdlopenflags(sys.getdlopenflags() | ctypes.RTLD_GLOBAL) import _vfh_ipr from soho import SohoParm LogLevel = type('Enum', (), { 'Msg': 0, 'Info': 1, 'Progress': 2, 'Warning': 3, 'Error': 4, 'Debug': 5 }) def logMessage(level, fmt, *args): _vfh_ipr.logMessage(level, fmt % args) def printDebug(fmt, *args): logMessage(LogLevel.Debug, fmt, *args) def dumpObjects(listName): printDebug("Checking \"%s\"" % listName) for obj in soho.objectList(listName): printDebug(" %s", obj.getName()) def exportObjects(listName): for obj in soho.objectList(listName): _vfh_ipr.exportOpNode(opNode=obj.getName()) def deleteObjects(listName): for obj in soho.objectList(listName): _vfh_ipr.deleteOpNode(opNode=obj.getName()) def getViewParams(camera, sohoCam, t): camParms = { 'space:world': SohoParm('space:world', 'real', [], False), 'focal': SohoParm('focal', 'real', [0.050], False), 'aperture': SohoParm('aperture', 'real', [0.0414214], False), 'orthowidth': SohoParm('orthowidth', 'real', [2], False), 'near': SohoParm('near', 'real', [0.001], False), 'far': SohoParm('far', 'real', [1000], False), 'res': SohoParm('res', 'int', [640, 480], False), 'projection': SohoParm('projection', 'string', ["perspective"], False), 'cropl': SohoParm('cropl', 'real', [-1], False), 'cropr': SohoParm('cropr', 'real', [-1], False), 'cropb': SohoParm('cropb', 'real', [-1], False), 'cropt': SohoParm('cropt', 'real', [-1], False), 'camera': SohoParm('camera', 'string', ['/obj/cam1'], False), } camParmsEval = sohoCam.evaluate(camParms, t) if not camParmsEval: return {} viewParams = {} for key in camParmsEval: viewParams[key] = camParmsEval[key].Value[0] viewParams['transform'] = camParmsEval['space:world'].Value viewParams['ortho'] = 1 if camParmsEval['projection'].Value[0] in { 'ortho' } else 0 viewParams['res'] = camParmsEval['res'].Value cropX = viewParams['res'][0] * viewParams['cropl'] cropY = viewParams['res'][1] * (1.0 - viewParams['cropt']) cropW = viewParams['res'][0] * (viewParams['cropr'] - viewParams['cropl']) cropH = viewParams['res'][1] * (viewParams['cropt'] - viewParams['cropb']) printDebug(" Res: %s" % viewParams['res']) printDebug(" Crop: %i-%i %i x %i" % (cropX, cropY, cropW, cropH)) printDebug(" Camera: %s" % camera) return viewParams def exportView(rop, camera, sohoCam, t): printDebug("exportView()") _vfh_ipr.exportView(viewParams=getViewParams(camera, sohoCam, t)) mode = soho.getDefaultedString('state:previewmode', ['default'])[0] # Evaluate an intrinsic parameter (see HDK_SOHO_API::evaluate()) # The 'state:time' parameter evaluates the time from the ROP. now = soho.getDefaultedFloat('state:time', [0.0])[0] # Evaluate the 'camera' parameter as a string. # If the 'camera' parameter doesn't exist, use ['/obj/cam1']. # SOHO always returns lists of values. camera = soho.getDefaultedString('camera', ['/obj/cam1'])[0] # MPlay / Render View port. port = soho.getDefaultedInt("vm_image_mplay_socketport", [0])[0] # ROP node. ropPath = soho.getOutputDriver().getName() ropNode = hou.node(ropPath) printDebug("Initialize SOHO...") # Initialize SOHO with the camera. # XXX: This doesn't work for me, but it should according to the documentation... # soho.initialize(now, camera) if not sohoglue.initialize(now, camera, None): soho.error("Unable to initialize rendering module with given camera") # Now, add objects to our scene soho.addObjects(now, "*", "*", "*", True) # Before we can evaluate the scene from SOHO, we need to lock the object lists. soho.lockObjects(now) for sohoCam in soho.objectList('objlist:camera'): break else: soho.error("Unable to find viewing camera for render") sohoOverride = soho.getDefaultedString('soho_overridefile', ['Unknown'])[0] printDebug("Processing Mode: \"%s\"" % mode) if mode in {"generate"}: # generate: Generation phase of IPR rendering # In generate mode, SOHO will keep the pipe (soho_pipecmd) # command open between invocations of the soho_program. # objlist:all # objlist:camera # objlist:light # objlist:instance # objlist:fog # objlist:space # objlist:mat # printDebug("IPR Port: %s" % port) printDebug("Driver: %s" % ropPath) printDebug("Camera: %s" % camera) printDebug("Now: %.3f" % now) _vfh_ipr.init(rop=ropPath, port=port, now=now, viewParams=getViewParams(camera, sohoCam, now)) elif mode in {"update"}: # update: Send updated changes from previous generation # # In this rendering mode, the special object list parameters: # objlist:dirtyinstance # objlist:dirtylight # objlist:dirtyspace # objlist:dirtyfog # will contain the list of all objects modified since the last render # (whether a generate or update). # # As well, the parameters: # objlist:deletedinstance # objlist:deletedlight # objlist:deletedspace # objlist:deletedfog # will list all objects which have been deleted from the scene. # if not _vfh_ipr.isRopValid(): _vfh_ipr.init(rop=ropPath, port=port, now=now, viewParams=getViewParams(camera, sohoCam, now)) else: if _vfh_ipr.setTime(now): # Have to handle "time" event manually here. exportObjects("objlist:dirtyinstance") exportObjects("objlist:dirtylight") # Update view. exportView(ropPath, camera, sohoCam, now)
def wrangle_camera(obj, wrangler, now): node = wrangle_node_parm(obj, 'camera_node', now) if node is not None: output_cam_xform(obj, node.directive_type, now) return node.type_and_paramset paramset = ParamSet() window = obj.getCameraScreenWindow(wrangler, now) parm_selection = { 'projection' : SohoPBRT('projection', 'string', ['perspective'], False), 'focal' : SohoPBRT('focal', 'float', [50], False), 'focalunits' : SohoPBRT('focalunits', 'string', ['mm'], False), 'aperture' : SohoPBRT('aperture', 'float', [41.4214], False), 'orthowidth' : SohoPBRT('orthowidth', 'float', [2], False), 'res' : SohoPBRT('res', 'integer', [1280, 720], False), 'aspect' : SohoPBRT('aspect', 'float', [1], False), 'fstop' : SohoPBRT('fstop', 'float', [5.6], False), 'focaldistance' : SohoPBRT('focus', 'float', [5], False, key='focaldistance'), 'pbrt_dof' : SohoPBRT('pbrt_dof', 'integer', [0], False), } parms = obj.evaluate(parm_selection, now) aspect = parms['aspect'].Value[0] aspectfix = aspect * float(parms['res'].Value[0]) / float(parms['res'].Value[1]) projection = parms['projection'].Value[0] if parms['pbrt_dof'].Value[0]: paramset.add(parms['focaldistance'].to_pbrt()) # to convert from f-stop to lens radius # FStop = FocalLength / (Radius * 2) # Radius = FocalLength/(FStop * 2) focal = parms['focal'].Value[0] fstop = parms['fstop'].Value[0] units = parms['focalunits'].Value[0] focal = soho.houdiniUnitLength(focal, units) lens_radius = focal/(fstop*2.0) paramset.add(PBRTParam('float', 'lensradius', lens_radius)) if projection == 'perspective': projection_name = 'perspective' focal = parms['focal'].Value[0] aperture = parms['aperture'].Value[0] fov = 2.0 * focal / aperture fov = 2.0 * math.degrees(math.atan2(1.0, fov)) paramset.add(PBRTParam('float', 'fov', [fov])) screen = [(window[0] - 0.5) * 2.0, (window[1] - 0.5) * 2.0, (window[2] - 0.5) * 2.0 / aspectfix, (window[3] - 0.5) * 2.0 / aspectfix] paramset.add(PBRTParam('float', 'screenwindow', screen)) elif projection == 'ortho': projection_name = 'orthographic' width = parms['orthowidth'].Value[0] screen = [(window[0] - 0.5) * width, (window[1] - 0.5) * width, (window[2] - 0.5) * width / aspectfix, (window[3] - 0.5) * width / aspectfix] paramset.add(PBRTParam('float', 'screenwindow', screen)) elif projection == 'sphere': projection_name = 'environment' else: soho.error('Camera projection setting of %s not supported by PBRT' % projection) output_cam_xform(obj, projection_name, now) return (projection_name, paramset)
if mode != 'default': # Don't allow for nested evaluation in IPR mode inheritedproperties = False else: inheritedproperties = parmlist['vm_inheritproperties'].Value[0] options = {} if inheritedproperties: # Turn off object->output driver inheritance options['state:inheritance'] = '-rop' if propdefs and propdefs != 'stdin': options['defaults_file'] = propdefs if not soho.initialize(now, camera, options): soho.error("Unable to initialize rendering module with given camera") # # Add objects to the scene, we check for parameters on the viewing # camera. If the parameters don't exist there, they will be picked up # by the output driver. # objectSelection = { # Candidate object selection 'vobject': SohoParm('vobject', 'string', ['*'], False), 'alights': SohoParm('alights', 'string', ['*'], False), 'vfog': SohoParm('vfog', 'string', ['*'], False), 'forceobject': SohoParm('forceobject', 'string', [''], False), 'forcelights': SohoParm('forcelights', 'string', [''], False), 'forcefog': SohoParm('forcefog', 'string', [''], False), 'excludeobject': SohoParm('excludeobject', 'string', [''], False),
def _lightExportPlanes(self, data, wrangler, cam, now): """Handle exporting the image planes based on their export settings.""" import soho base_channel = data["channel"] # Handle any light exporting. if self.lightexport is not None: # Get a list of lights matching our mask and selection. lights = cam.objectList( "objlist:light", now, self.lightexport_scope, self.lightexport_select ) if self.lightexport == "per-light": # Process each light. for light in lights: # Try and find the suffix using the 'vm_export_suffix' # parameter. If it doesn't exist, use an emptry string. suffix = light.getDefaultedString( "vm_export_suffix", now, [''] )[0] prefix = [] # Look for the prefix parameter. If it doesn't exist, use # the light's name and replace the '/' with '_'. The # default value of 'vm_export_prefix' is usually $OS. if not light.evalString("vm_export_prefix", now, prefix): prefix = [light.getName()[1:].replace('/', '_')] # If there is a prefix we construct the channel name using # it and the suffix. if prefix: channel = "{}_{}{}".format( prefix[0], base_channel, suffix ) # If not and there is a valid suffix, add it to the channel # name. elif suffix: channel = "{}{}".format(base_channel, suffix) # Throw an error because all the per-light channels will # have the same name. else: soho.error("Empty suffix for per-light exports.") channel = base_channel data["channel"] = channel data["lightexport"] = light.getName() # Write this light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) elif self.lightexport == "single": # Take all the light names and join them together. lightexport = ' '.join([light.getName() for light in lights]) # If there are no lights, we can't pass in an empty string # since then mantra will think that light exports are # disabled. So pass down an string that presumably doesn't # match any light name. if not lightexport: lightexport = "__nolights__" data["lightexport"] = lightexport # Write the combined light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) elif self.lightexport == "per-category": # A mapping between category names and their member lights. category_map = {} # Process each selected light. for light in lights: # Get the category for the light. categories = [] light.evalString("categories", now, categories) # Light doesn't have a 'categories' parameter. if not categories: continue # Get the raw string. categories = categories[0] # Since the categories value can be space or comma # separated we replace the commas with spaces then split. categories = categories.replace(',', ' ') categories = categories.split() # If the categories list was empty, put the light in a fake # category. if not categories: no_category_lights = category_map.setdefault("__none__", []) no_category_lights.append(light) else: # For each category the light belongs to, add it to # the list. for category in categories: category_lights = category_map.setdefault(category, []) category_lights.append(light) # Process all the found categories and their member lights. for category, lights in category_map.iteritems(): # Construct the export string to contain all the member # lights. lightexport = ' '.join( [light.getName() for light in lights] ) data["lightexport"] = lightexport # The channel is the regular channel named prefixed with # the category name. data["channel"] = "{}_{}".format(category, base_channel) # Write the per-category light export to the ifd. self.writeDataToIfd(data, wrangler, cam, now) else: # Write a normal AOV definition. self.writeDataToIfd(data, wrangler, cam, now)
import hou import soho import afanasy current_afnode = hou.pwd() submit_afnode_parm = current_afnode.parm('submit_afnode') if submit_afnode_parm is None: soho.error('Can\'t find "submit_afnode" parameter on "%s"' % current_afnode.path()) submit_afnode_path = submit_afnode_parm.eval() if submit_afnode_path is None: soho.error('Can\'t eval "submit_afnode" parameter on "%s"' % current_afnode.path()) if submit_afnode_path == '': soho.error('Empty "submit_afnode" parameter on "%s"' % current_afnode.path()) submit_afnode = hou.node( submit_afnode_path) if submit_afnode is None: soho.error('Can\'t find "%s" node specified in "%s"' % (submit_afnode_path, current_afnode.path())) if submit_afnode.type().name() != 'afanasy': soho.error('Node "%s" specified in "%s" is not of "afanasy" type' % (submit_afnode_path, current_afnode.path())) afanasy.render( submit_afnode)