Exemplo n.º 1
0
def wrangle_accelerator(obj, wrangler, now):

    node = wrangle_node_parm(obj, "accelerator_node", now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {"accelerator": SohoPBRT("accelerator", "string", ["bvh"], False)}
    parms = obj.evaluate(parm_selection, now)
    accelerator_name = parms["accelerator"].Value[0]

    if accelerator_name == "bvh":
        parm_selection = {
            "maxnodeprims": SohoPBRT("maxnodeprims", "integer", [4], True),
            "splitmethod": SohoPBRT("splitmethod", "string", ["sah"], True),
        }
    else:
        parm_selection = {
            "intersectcost": SohoPBRT("intersectcost", "integer", [80], True),
            "traversalcostcost": SohoPBRT("traversalcost", "integer", [1], True),
            "emptybonus": SohoPBRT("emptybonus", "float", [0.2], True),
            "maxprims": SohoPBRT("maxprims", "integer", [1], True),
            "kdtree_maxdepth": SohoPBRT(
                "kdtree_maxdepth", "integer", [1], True, key="maxdepth"
            ),
        }
    parms = obj.evaluate(parm_selection, now)

    paramset = ParamSet()

    for parm in parms:
        paramset.add(parms[parm].to_pbrt())

    return (accelerator_name, paramset)
Exemplo n.º 2
0
def wrangle_filter(obj, wrangler, now):

    node = wrangle_node_parm(obj, "filter_node", now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        "filter": SohoPBRT("filter", "string", ["gaussian"], False),
        "filter_width": SohoPBRT("filter_width", "float", [2.0, 2.0], False),
        "alpha": SohoPBRT("gauss_alpha", "float", [2.0], True, key="alpha"),
        "B": SohoPBRT("mitchell_B", "float", [0.333333], True, key="B"),
        "C": SohoPBRT("mitchell_C", "float", [0.333333], True, key="C"),
        "tau": SohoPBRT("sinc_tau", "float", [3], True, key="tau"),
    }
    parms = obj.evaluate(parm_selection, now)

    filter_name = parms["filter"].Value[0]
    paramset = ParamSet()
    xwidth = parms["filter_width"].Value[0]
    ywidth = parms["filter_width"].Value[1]
    paramset.add(PBRTParam("float", "xwidth", xwidth))
    paramset.add(PBRTParam("float", "ywidth", ywidth))

    if filter_name == "gaussian" and "alpha" in parms:
        paramset.add(parms["alpha"].to_pbrt())
    if filter_name == "mitchell" and "B" in parms:
        paramset.add(parms["B"].to_pbrt())
    if filter_name == "mitchell" and "C" in parms:
        paramset.add(parms["C"].to_pbrt())
    if filter_name == "sinc" and "tau" in parms:
        paramset.add(parms["tau"].to_pbrt())
    return (filter_name, paramset)
Exemplo n.º 3
0
def override_to_paramset(material, override_str):
    """Convert a material override to a ParamSet

    Args:
        material (str): An oppath to a material node
        override_str (str): A string with the overrides (material_override)

    Returns:
        ParamSet of the override params
    """
    paramset = ParamSet()
    override = eval(override_str)
    if not override or not material:
        return paramset
    node = hou.node(material)
    if not node:
        return paramset
    processed_parms = set()
    for parm_name in override:
        parm = node.parm(parm_name)
        if parm is None:
            continue
        parm_tuple = parm.tuple()
        if parm_tuple.name() in processed_parms:
            continue
        value = [override[x.name()] for x in parm_tuple]
        pbrt_param = pbrt_param_from_ref(parm_tuple, value)
        paramset.add(pbrt_param)
    return paramset
Exemplo n.º 4
0
def wrangle_filter(obj, wrangler, now):

    node = wrangle_node_parm(obj, 'filter_node', now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        'filter' : SohoPBRT('filter', 'string', ['gaussian'], False),
        'filter_width' : SohoPBRT('filter_width', 'float', [2.0, 2.0], False),
        'alpha' : SohoPBRT('gauss_alpha', 'float', [2.0], True, key='alpha'),
        'B' : SohoPBRT('mitchell_B', 'float', [0.333333], True, key='B'),
        'C' : SohoPBRT('mitchell_C', 'float', [0.333333], True, key='C'),
        'tau' : SohoPBRT('sinc_tau', 'float', [3], True, key='tau'),
    }
    parms = obj.evaluate(parm_selection, now)

    filter_name = parms['filter'].Value[0]
    paramset = ParamSet()
    xwidth = parms['filter_width'].Value[0]
    ywidth = parms['filter_width'].Value[1]
    paramset.add(PBRTParam('float', 'xwidth', xwidth))
    paramset.add(PBRTParam('float', 'ywidth', ywidth))

    if filter_name == 'gaussian' and 'alpha' in parms:
        paramset.add(parms['alpha'].to_pbrt())
    if filter_name == 'mitchell' and 'mitchell_B' in parms:
        paramset.add(parms['B'].to_pbrt())
    if filter_name == 'mitchell' and 'mitchell_C' in parms:
        paramset.add(parms['C'].to_pbrt())
    if filter_name == 'sinc' and 'tau' in parms:
        paramset.add(parms['tau'].to_pbrt())
    return (filter_name, paramset)
Exemplo n.º 5
0
def heightfield_prim_wrangler(prims,
                              paramset=None,
                              properties=None,
                              override_node=None):
    """Outputs a "heightfield" Shapes for the input geometry

    Args:
        prims (list of hou.Prims): Input prims
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """

    for prim in prims:
        resolution = prim.resolution()
        # If the z resolution is not 1 then this really isn't a heightfield
        if resolution[2] != 1:
            continue

        hf_paramset = ParamSet()

        # Similar to trianglemesh, this is more compact fast, however it might
        # be a memory issue and a generator per voxel or per slice might be a
        # better approach.
        voxeldata = array.array("f")
        voxeldata.fromstring(prim.allVoxelsAsString())

        with api.TransformBlock():

            xform = prim_transform(prim)
            xform = hou.Matrix4(xform)
            srt = xform.explode()
            # Here we need to split up the xform mainly so we can manipulate
            # the scale. In particular Houdini's prim xforms maintain a
            # rotation matrix but the z scale is ignored. So here we are
            # setting it directly to 1 as the "Pz" (or voxeldata) will always
            # be the exact height, no scales are applied to the prim xform.
            # We also need to scale up heightfield since in Houdini by default
            # the size is -1,-1,-1 to 1,1,1 where in pbrt its 0,0,0 to 1,1,1
            api.Translate(*srt["translate"])
            rot = srt["rotate"]
            if rot.z():
                api.Rotate(rot[2], 0, 0, 1)
            if rot.y():
                api.Rotate(rot[1], 0, 1, 0)
            if rot.x():
                api.Rotate(rot[0], 1, 0, 0)
            api.Scale(srt["scale"][0] * 2.0, srt["scale"][1] * 2.0, 1.0)
            api.Translate(-0.5, -0.5, 0)
            hf_paramset.add(PBRTParam("integer", "nu", resolution[0]))
            hf_paramset.add(PBRTParam("integer", "nv", resolution[1]))
            hf_paramset.add(PBRTParam("float", "Pz", voxeldata))
            hf_paramset |= paramset
            hf_paramset |= prim_override(prim, override_node)
            api.Shape("heightfield", hf_paramset)
    return
Exemplo n.º 6
0
def tube_wrangler(gdp, paramset=None, properties=None):
    """Outputs "cone" or "cylinder" Shapes for the input geometry

    Args:
        gdp (hou.Geometry): Input geo
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """

    for prim in gdp.prims():

        shape_paramset = ParamSet(paramset)

        with api.TransformBlock():
            xform = prim_transform(prim)
            taper = prim.intrinsicValue('tubetaper')

            # workaround, see TODO below in the else: pass
            if not (taper == 0 or taper == 1):
                api.Comment(
                    'Skipping tube, prim # %i, with non-conforming taper of %f'
                    % (prim.number(), taper))
                continue

            closed = prim.intrinsicValue('closed')
            api.ConcatTransform(xform)
            api.Rotate(-90, 1, 0, 0)
            if taper == 0:
                shape = 'cone'
                api.Translate(0, 0, -0.5)
            elif taper == 1:
                shape = 'cylinder'
                shape_paramset.add(PBRTParam('float', 'zmin', -0.5))
                shape_paramset.add(PBRTParam('float', 'zmax', 0.5))
            else:
                # TODO support hyperboloid, however pbrt currently
                # has no ends of trouble with this shape type
                # crashes or hangs
                pass
            with api.TransformBlock():
                # Flip in Y so parameteric UV's match Houdini's
                api.Scale(1, -1, 1)
                api.Shape(shape, shape_paramset)

            if closed:
                disk_paramset = ParamSet(paramset)
                if shape == 'cylinder':
                    disk_paramset.add(PBRTParam('float', 'height', 0.5))
                    api.Shape('disk', disk_paramset)
                    disk_paramset.add(PBRTParam('float', 'height', -0.5))
                    api.Shape('disk', disk_paramset)
                else:
                    disk_paramset.add(PBRTParam('float', 'height', 0))
                    api.Shape('disk', disk_paramset)
    return
Exemplo n.º 7
0
def mesh_alpha_texs(properties):
    if not properties:
        return
    paramset = ParamSet()
    for prop in ("alpha", "shadowalpha"):
        if prop not in properties:
            continue
        tex = properties[prop].Value[0]
        if not tex:
            continue
        paramset.add(PBRTParam("texture", prop, tex))
    return paramset
Exemplo n.º 8
0
def wrangle_sampler(obj, wrangler, now):

    node = wrangle_node_parm(obj, "sampler_node", now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        "sampler": SohoPBRT("sampler", "string", ["halton"], False),
        "pixelsamples": SohoPBRT("pixelsamples", "integer", [16], False),
        "jitter": SohoPBRT("jitter", "bool", [1], False),
        "samples": SohoPBRT("samples", "integer", [4, 4], False),
        "dimensions": SohoPBRT("dimensions", "integer", [4], False),
    }
    parms = obj.evaluate(parm_selection, now)

    sampler_name = parms["sampler"].Value[0]
    paramset = ParamSet()

    if sampler_name == "stratified":
        xsamples = parms["samples"].Value[0]
        ysamples = parms["samples"].Value[1]
        paramset.add(PBRTParam("integer", "xsamples", xsamples))
        paramset.add(PBRTParam("integer", "ysamples", ysamples))
        paramset.add(parms["jitter"].to_pbrt())
        paramset.add(parms["dimensions"].to_pbrt())
    else:
        paramset.add(parms["pixelsamples"].to_pbrt())

    return (sampler_name, paramset)
Exemplo n.º 9
0
def wrangle_sampler(obj, wrangler, now):

    node = wrangle_node_parm(obj, 'sampler_node', now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        'sampler' : SohoPBRT('sampler', 'string', ['halton'], False),
        'pixelsamples' : SohoPBRT('pixelsamples', 'integer', [16], False),
        'jitter' : SohoPBRT('jitter', 'bool', [1], False),
        'samples' : SohoPBRT('samples', 'integer', [4, 4], False),
        'dimensions' : SohoPBRT('dimensions', 'integer', [4], False),
    }
    parms = obj.evaluate(parm_selection, now)

    sampler_name = parms['sampler'].Value[0]
    paramset = ParamSet()

    if sampler_name == 'stratified':
        xsamples = parms['samples'].Value[0]
        ysamples = parms['samples'].Value[1]
        paramset.add(PBRTParam('integer', 'xsamples', xsamples))
        paramset.add(PBRTParam('integer', 'ysamples', ysamples))
        paramset.add(parms['jitter'].to_pbrt())
        paramset.add(parms['dimensions'].to_pbrt())
    else:
        paramset.add(parms['pixelsamples'].to_pbrt())

    return (sampler_name, paramset)
Exemplo n.º 10
0
def wrangle_sampler(obj, wrangler, now):

    node = wrangle_node_parm(obj, "sampler_node", now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        "sampler": SohoPBRT("sampler", "string", ["pmj02bn"], False),
        "pixelsamples": SohoPBRT("pixelsamples", "integer", [16], False),
        "randomization": SohoPBRT("randomization", "string", ["fastowen"],
                                  True),
        "jitter": SohoPBRT("jitter", "bool", [1], True),
        "samples": SohoPBRT("samples", "integer", [4, 4], False),
    }
    parms = obj.evaluate(parm_selection, now)

    sampler_name = parms["sampler"].Value[0]
    paramset = ParamSet()

    if sampler_name == "stratified":
        xsamples = parms["samples"].Value[0]
        ysamples = parms["samples"].Value[1]
        paramset.add(PBRTParam("integer", "xsamples", xsamples))
        paramset.add(PBRTParam("integer", "ysamples", ysamples))
        if "jitter" in parms:
            paramset.add(parms["jitter"].to_pbrt())
    else:
        if (sampler_name in ("sobol", "paddedsobol", "zsobol", "halton")
                and "randomization" in parms):
            # NOTE: If the halton sampler is picked, it is not compatible with the
            # randomization "fastowen".
            paramset.add(parms["randomization"].to_pbrt())
        paramset.add(parms["pixelsamples"].to_pbrt())

    return (sampler_name, paramset)
Exemplo n.º 11
0
def bounds_to_api_box(b):
    """Output a trianglemesh Shape of box based on the input bounds"""

    paramset = ParamSet()
    paramset.add(
        PBRTParam('point', 'P', [
            b[1], b[2], b[5], b[0], b[2], b[5], b[1], b[3], b[5], b[0], b[3],
            b[5], b[0], b[2], b[4], b[1], b[2], b[4], b[0], b[3], b[4], b[1],
            b[3], b[4]
        ]))
    paramset.add(
        PBRTParam('integer', 'indices', [
            0, 3, 1, 0, 2, 3, 4, 7, 5, 4, 6, 7, 6, 2, 7, 6, 3, 2, 5, 1, 4, 5,
            0, 1, 5, 2, 0, 5, 7, 2, 1, 6, 4, 1, 3, 6
        ]))
    api.Shape('trianglemesh', paramset)
Exemplo n.º 12
0
def override_to_paramset(material, override_str):
    """Convert a material override to a ParamSet

    Args:
        material (str): An oppath to a material node
        override_str (str): A string with the overrides (material_override)

    Returns:
        ParamSet of the override params
    """
    paramset = ParamSet()
    override = eval(override_str)
    if not override or not material:
        return paramset
    node = hou.node(material)
    if not node:
        return paramset
    for override_name in override:
        # 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_name:spectrum_type. If the parm name
        # ends in one of the "rgb/color" types then we'll handle it differently.
        try:
            parm_name, spectrum_type = override_name.split(':', 1)
            parm_tuple = node.parmTuple(parm_name)
        except ValueError:
            spectrum_type = None
            parm_name = override_name
            parm = node.parm(parm_name)
            if parm is None:
                continue
            parm_tuple = parm.tuple()

        if spectrum_type is None:
            value = [override[x.name()] for x in parm_tuple]
            pbrt_param = pbrt_param_from_ref(parm_tuple, value)
        elif spectrum_type in ('spectrum', 'xyz', 'blackbody'):
            pbrt_param = PBRTParam(spectrum_type, parm_name,
                                   override[override_name])
        else:
            raise ValueError('Unable to wrangle override name: %s' %
                             override_name)
        paramset.add(pbrt_param)
    return paramset
Exemplo n.º 13
0
def wrangle_film(obj, wrangler, now):

    node = wrangle_node_parm(obj, 'film_node', now)
    if node is not None:
        return node.type_and_paramset

    paramset = ParamSet()

    parm_selection = {
        'filename' : SohoPBRT('filename', 'string', ['pbrt.exr'], False),
        'maxsampleluminance' : SohoPBRT('maxsampleluminance', 'float', [1e38], True),
        'diagonal' : SohoPBRT('diagonal', 'float', [35], True),
    }
    parms = obj.evaluate(parm_selection, now)
    for parm_name, parm in parms.iteritems():
        paramset.add(parm.to_pbrt())

    parm_selection = {
        'res' : SohoPBRT('res', 'integer', [1280, 720], False),
    }
    parms = obj.evaluate(parm_selection, now)
    paramset.add(PBRTParam('integer', 'xresolution', parms['res'].Value[0]))
    paramset.add(PBRTParam('integer', 'yresolution', parms['res'].Value[1]))

    crop_region = obj.getCameraCropWindow(wrangler, now)
    if crop_region != [0.0, 1.0, 0.0, 1.0]:
        paramset.add(PBRTParam('float', 'cropwindow', crop_region))

    return ('image', paramset)
Exemplo n.º 14
0
def wrangle_film(obj, wrangler, now):

    node = wrangle_node_parm(obj, "film_node", now)
    if node is not None:
        return node.type_and_paramset

    paramset = ParamSet()

    parm_selection = {
        "filename": SohoPBRT("filename", "string", ["pbrt.exr"], False),
        "maxsampleluminance": SohoPBRT("maxsampleluminance", "float", [1e38], True),
        "diagonal": SohoPBRT("diagonal", "float", [35], True),
    }
    parms = obj.evaluate(parm_selection, now)
    for parm_name, parm in parms.iteritems():
        paramset.add(parm.to_pbrt())

    parm_selection = {"res": SohoPBRT("res", "integer", [1280, 720], False)}
    parms = obj.evaluate(parm_selection, now)
    paramset.add(PBRTParam("integer", "xresolution", parms["res"].Value[0]))
    paramset.add(PBRTParam("integer", "yresolution", parms["res"].Value[1]))

    crop_region = obj.getCameraCropWindow(wrangler, now)
    if crop_region != [0.0, 1.0, 0.0, 1.0]:
        paramset.add(PBRTParam("float", "cropwindow", crop_region))

    return ("image", paramset)
Exemplo n.º 15
0
def loopsubdiv_params(mesh_gdp):
    """Generates a ParamSet for a loopsubdiv

    The following attributes are checked for -
    P (point), built-in attribute

    Args:
        mesh_gdp (hou.Geometry): Input geo
    Returns: ParamSet of the attributes on the geometry
    """

    mesh_paramset = ParamSet()

    P = array.array("f")
    P.fromstring(mesh_gdp.pointFloatAttribValuesAsString("P"))

    indices = vtx_attrib_gen(mesh_gdp, None)

    mesh_paramset.add(PBRTParam("integer", "indices", indices))
    mesh_paramset.add(PBRTParam("point", "P", P))

    return mesh_paramset
Exemplo n.º 16
0
def wrangle_accelerator(obj, wrangler, now):

    node = wrangle_node_parm(obj, 'accelerator_node', now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        'accelerator' : SohoPBRT('accelerator', 'string', ['bvh'], False),
    }
    parms = obj.evaluate(parm_selection, now)
    accelerator_name = parms['accelerator'].Value[0]

    if accelerator_name == 'bvh':
        parm_selection = {
            'maxnodeprims' : SohoPBRT('maxnodeprims', 'integer', [4], True),
            'splitmethod' : SohoPBRT('splitmethod', 'string', ['sah'], True),
        }
    else:
        parm_selection = {
            'intersectcost' :
                SohoPBRT('intersectcost', 'integer', [80], True),
            'traversalcostcost' :
                SohoPBRT('traversalcost', 'integer', [1], True),
            'emptybonus' :
                SohoPBRT('emptybonus', 'float', [0.2], True),
            'maxprims' :
                SohoPBRT('maxprims', 'integer', [1], True),
            'kdtree_maxdepth' :
                SohoPBRT('kdtree_maxdepth', 'integer', [1], True,
                         key='maxdepth')
        }
    parms = obj.evaluate(parm_selection, now)

    paramset = ParamSet()

    for parm in parms:
        paramset.add(parms[parm].to_pbrt())

    return (accelerator_name, paramset)
Exemplo n.º 17
0
def wrangle_film(obj, wrangler, now):

    node = wrangle_node_parm(obj, "film_node", now)
    if node is not None:
        return node.type_and_paramset

    paramset = ParamSet()

    parm_selection = {
        "filename": SohoPBRT("filename", "string", ["pbrt.exr"], False),
        "maxcomponentvalue": SohoPBRT("maxcomponentvalue", "float", [1e38],
                                      True),
        "diagonal": SohoPBRT("diagonal", "float", [35], True),
        "savefp16": SohoPBRT("savefp16", "bool", [1], True),
    }
    parms = obj.evaluate(parm_selection, now)
    for parm in parms.values():
        paramset.add(parm.to_pbrt())

    parm_selection = {
        "film": SohoPBRT("film", "string", ["rgb"], False),
        "res": SohoPBRT("res", "integer", [1280, 720], False),
    }
    parms = obj.evaluate(parm_selection, now)
    film_name = parms["film"].Value[0]
    paramset.add(PBRTParam("integer", "xresolution", parms["res"].Value[0]))
    paramset.add(PBRTParam("integer", "yresolution", parms["res"].Value[1]))

    crop_region = obj.getCameraCropWindow(wrangler, now)
    if crop_region != [0.0, 1.0, 0.0, 1.0]:
        paramset.add(PBRTParam("float", "cropwindow", crop_region))

    parm_selection = {
        "iso": SohoPBRT("iso", "float", [100], True),
        "whitebalance": SohoPBRT("whitebalance", "float", [0], True),
        "sensor": SohoPBRT("sensor", "string", ["cie1931"], True),
    }

    if film_name == "spectral":
        parm_selection["buckets"] = SohoPBRT("buckets", "integer", [16], True)

    parms = obj.evaluate(parm_selection, now)
    for parm in parms.values():
        paramset.add(parm.to_pbrt())

    return (film_name, paramset)
Exemplo n.º 18
0
def nurbs_wrangler(gdp, paramset=None, properties=None, override_node=None):
    """Outputs a "nurbs" Shape for input geometry

    The following attributes are checked for -
    P (point), built-in attribute

    Args:
        gdp (hou.Geometry): Input geo
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """

    # TODO: - Figure out how the Pw attribute works in Houdini
    # has_Pw = False if gdp.findPointAttrib('Pw') is None else True
    has_Pw = False

    # TODO   - Figure out how to query [uv]_extent in hou
    # u_extent_h = gdp.attribute('geo:prim', 'geo:ubasisextent')
    # v_extent_h = gdp.attribute('geo:prim', 'geo:vbasisextent')

    for prim in gdp.prims():

        nurbs_paramset = ParamSet()

        row = prim.intrinsicValue("nu")
        col = prim.intrinsicValue("nv")
        u_order = prim.intrinsicValue("uorder")
        v_order = prim.intrinsicValue("vorder")
        u_wrap = prim.intrinsicValue("uwrap")
        v_wrap = prim.intrinsicValue("vwrap")
        u_knots = prim.intrinsicValue("uknots")
        v_knots = prim.intrinsicValue("vknots")

        if u_wrap:
            row += u_order - 1
        if v_wrap:
            col += v_order - 1
        nurbs_paramset.add(PBRTParam("integer", "nu", row))
        nurbs_paramset.add(PBRTParam("integer", "nv", col))
        nurbs_paramset.add(PBRTParam("integer", "uorder", u_order))
        nurbs_paramset.add(PBRTParam("integer", "vorder", v_order))
        nurbs_paramset.add(PBRTParam("float", "uknots", u_knots))
        nurbs_paramset.add(PBRTParam("float", "vknots", v_knots))
        # NOTE: Currently not sure how these are set within Houdini
        #       but they are queryable
        #       The Platonic SOP, Teapot -> Convert to NURBS can make these.
        # nurbs_paramset.add(PBRTParam('float', 'u0', u_extent[0]))
        # nurbs_paramset.add(PBRTParam('float', 'v0', v_extent[0]))
        # nurbs_paramset.add(PBRTParam('float', 'u1', u_extent[1]))
        # nurbs_paramset.add(PBRTParam('float', 'v1', v_extent[1]))

        # if row + u_order != len(u_knots):
        #    api.Comment('Invalid U')
        # if col + v_order != len(v_knots):
        #    api.Comment('Invalid V')

        P = []
        for v in xrange(col):
            for u in xrange(row):
                vtx = prim.vertex(u % prim.numCols(), v % prim.numRows())
                pt = vtx.point()
                P.append(pt.attribValue("P"))
        if not has_Pw:
            nurbs_paramset.add(PBRTParam("point", "P", P))
        else:
            # TODO: While the pbrt scene file looks right, the render
            #       is a bit odd. Scaled up geo? Not what I was expecting.
            #       Perhaps compare to RMan.
            w = prim_pt2vtx_attrib_gen(prim, "Pw")
            Pw = itertools.izip(P, w)
            nurbs_paramset.add(PBRTParam("float", "Pw", Pw))

        nurbs_paramset |= paramset
        nurbs_paramset |= prim_override(prim, override_node)
        api.Shape("nurbs", nurbs_paramset)
Exemplo n.º 19
0
def wrangle_integrator(obj, wrangler, now):

    node = wrangle_node_parm(obj, 'integrator_node', now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        'integrator' : SohoPBRT('integrator', 'string', ['path'], False),
        'maxdepth' : SohoPBRT('maxdepth', 'integer', [5], False),
        'rrthreshold' : SohoPBRT('rrthreshold', 'float', [1], True),
        'lightsamplestrategy' :
            SohoPBRT('lightsamplestrategy', 'string', ['spatial'], True),
        'visualizestrategies' :
            SohoPBRT('visualizestrategies', 'toggle', [False], True),
        'visualizeweights' :
            SohoPBRT('visualizeweights', 'toggle', [False], True),
        'iterations' :
            SohoPBRT('iterations', 'integer', [64], True),
        'photonsperiterations' :
            SohoPBRT('photonsperiterations', 'integer', [-1], True),
        'imagewritefrequency' :
            SohoPBRT('imagewritefrequency', 'integer', [2.14748e+09], True),
        'radius' :
            SohoPBRT('radius', 'float', [1], True),
        'bootstrapsamples' :
            SohoPBRT('bootstrapsamples', 'integer', [100000], True),
        'chains' :
            SohoPBRT('chains', 'integer', [1000], True),
        'mutationsperpixel' :
            SohoPBRT('mutataionsperpixel', 'integer', [100], True),
        'largestepprobability' :
            SohoPBRT('largestepprobability', 'float', [0.3], True),
        'sigma' :
            SohoPBRT('sigma', 'float', [0.01], True),
        'strategy' :
            SohoPBRT('strategy', 'string', ['all'], True),
        'nsamples' :
            SohoPBRT('nsamples', 'integer', ['64'], True),
        'cossample' :
            SohoPBRT('cossample', 'toggle', [True], True),
    }

    integrator_parms = {
        'ao' : ['nsamples', 'cossample'],
        'path' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy'],
        'bdpt' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy',
                  'visualizestrategies', 'visualizeweights'],
        'mlt' : ['maxdepth', 'bootstrapsamples', 'chains', 'mutationsperpixel',
                 'largestepprobability', 'sigma'],
        'sppm' : ['maxdepth', 'iterations', 'photonsperiteration',
                  'imagewritefrequency', 'radius'],
        'whitted' : ['maxdepth'],
        'volpath' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy'],
        'directlighting' : ['maxdepth', 'strategy'],
        }
    parms = obj.evaluate(parm_selection, now)

    integrator_name = parms['integrator'].Value[0]
    paramset = ParamSet()
    for parm_name in integrator_parms[integrator_name]:
        if parm_name not in parms:
            continue
        paramset.add(parms[parm_name].to_pbrt())

    return (integrator_name, paramset)
Exemplo n.º 20
0
def curve_wrangler(gdp, paramset=None, properties=None):
    """Outputs a "curve" Shape for input geometry

    The following attributes are checked for -

    P (point), built-in attribute
    width (vertex/point/prim), float
    N (vertex/point), float[3]
    curvetype (prim), string (overrides the property pbrt_curvetype)

    Args:
        gdp (hou.Geometry): Input geo
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """
    if paramset is None:
        paramset = ParamSet()

    if properties is None:
        properties = {}

    curve_type = None
    if 'pbrt_curvetype' in properties:
        curve_type = properties['pbrt_curvetype'].Value[0]
        paramset.add(PBRTParam('string', 'type', curve_type))
    if 'splitdepth' in properties:
        paramset.add(properties['splitdepth'].to_pbrt())

    has_vtx_width = False if gdp.findVertexAttrib('width') is None else True
    has_pt_width = False if gdp.findPointAttrib('width') is None else True
    has_prim_width = False if gdp.findPrimAttrib('width') is None else True

    has_curvetype = False if gdp.findPrimAttrib('curvetype') is None else True

    has_vtx_N = False if gdp.findVertexAttrib('N') is None else True
    has_pt_N = False if gdp.findPointAttrib('N') is None else True

    for prim in gdp.prims():
        curve_paramset = ParamSet()
        prim_curve_type = curve_type

        # Closed curve surfaces are not supported
        if prim.intrinsicValue('closed'):
            continue

        order = prim.intrinsicValue('order')
        degree = order - 1
        # PBRT only supports degree 2 or 3 curves
        # TODO: We could possibly convert the curves to a format that
        #       pbrt supports but for now we'll expect the user to have
        #       a curve basis which is supported
        # https://www.codeproject.com/Articles/996281/NURBS-crve-made-easy
        if degree not in (2, 3):
            continue
        curve_paramset.add(PBRTParam('integer', 'degree', degree))

        if prim.intrinsicValue('typename') == 'BezierCurve':
            basis = 'bezier'
        else:
            basis = 'bspline'
        curve_paramset.add(PBRTParam('string', 'basis', [basis]))

        P = prim_pt2vtx_attrib_gen(prim)
        curve_paramset.add(PBRTParam('point', 'P', P))

        if has_curvetype:
            prim_val = prim.attribValue('curvetype')
            prim_curve_type = prim_val if prim_val else curve_type

        if prim_curve_type is not None:
            curve_paramset.add(PBRTParam('string', 'type', [prim_curve_type]))

        if prim_curve_type == 'ribbon':

            if has_vtx_N or has_pt_N:
                N = (prim.attribValueAt('N', u)
                     for u in prim.intrinsicValue('knots'))
            else:
                # If ribbon, normals must exist
                # TODO: Let pbrt error? Or put default values?
                N = [
                    (0, 0, 1),
                ] * len(prim.intrinsicValue('knots'))

            if N is not None:
                curve_paramset.add(PBRTParam('normal', 'N', N))

        if has_vtx_width:
            curve_paramset.add(
                PBRTParam('float', 'width0',
                          prim.vertex(0).attribValue('width')))
            curve_paramset.add(
                PBRTParam('float', 'width1',
                          prim.vertex(-1).attribValue('width')))
        elif has_pt_width:
            curve_paramset.add(
                PBRTParam('float', 'width0',
                          prim.vertex(0).point().attribValue('width')))
            curve_paramset.add(
                PBRTParam('float', 'width1',
                          prim.vertex(-1).point().attribValue('width')))
        elif has_prim_width:
            curve_paramset.add(
                PBRTParam('float', 'width', prim.attribValue('width')))
        else:
            # Houdini's default matches a width of 0.05
            curve_paramset.add(PBRTParam('float', 'width', 0.05))

        curve_paramset |= paramset
        api.Shape('curve', curve_paramset)
    return
Exemplo n.º 21
0
def tube_wrangler(gdp, paramset=None, properties=None, override_node=None):
    """Outputs "cone" or "cylinder" Shapes for the input geometry

    Args:
        gdp (hou.Geometry): Input geo
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """

    for prim in gdp.prims():

        shape_paramset = ParamSet(paramset)
        shape_paramset |= prim_override(prim, override_node)

        with api.TransformBlock():

            side_paramset = ParamSet(shape_paramset)

            xform = prim_transform(prim)
            taper = prim.intrinsicValue("tubetaper")

            # workaround, see TODO below in the else: pass
            if not (taper == 0 or taper == 1):
                api.Comment(
                    "Skipping tube, prim # %i, with non-conforming taper of %f"
                    % (prim.number(), taper))
                continue

            closed = prim.intrinsicValue("closed")
            api.ConcatTransform(xform)
            api.Rotate(-90, 1, 0, 0)
            if taper == 0:
                shape = "cone"
                api.Translate(0, 0, -0.5)
            elif taper == 1:
                shape = "cylinder"
                side_paramset.add(PBRTParam("float", "zmin", -0.5))
                side_paramset.add(PBRTParam("float", "zmax", 0.5))
            else:
                # TODO support hyperboloid, however pbrt currently
                # has no ends of trouble with this shape type
                # crashes or hangs
                api.Comment("Hyperboloid skipped due to PBRT instability")
            with api.AttributeBlock():
                api.ReverseOrientation()
                # Flip in Y so parameteric UV's match Houdini's
                api.Scale(1, -1, 1)
                api.Shape(shape, side_paramset)

            if closed:
                disk_paramset = ParamSet(shape_paramset)
                if shape == "cylinder":
                    disk_paramset.add(PBRTParam("float", "height", 0.5))
                    api.Shape("disk", disk_paramset)
                    disk_paramset.replace(PBRTParam("float", "height", -0.5))
                    with api.AttributeBlock():
                        api.ReverseOrientation()
                        api.Shape("disk", disk_paramset)
                else:
                    with api.AttributeBlock():
                        api.ReverseOrientation()
                        api.Shape("disk", disk_paramset)
    return
Exemplo n.º 22
0
def trianglemesh_params(mesh_gdp, computeN=True):
    """Generates a ParamSet for a trianglemesh

    The following attributes are checked for -
    P (point), built-in attribute
    N (vertex/point), float[3]
    uv (vertex/point), float[3]
    S (vertex/point), float[3]
    faceIndices (prim), integer, used for ptex

    Args:
        mesh_gdp (hou.Geometry): Input geo
        computeN (bool): Whether to auto-compute normals if they don't exist
                         Defaults to True
    Returns: ParamSet of the attributes on the geometry
    """

    mesh_paramset = ParamSet()
    unique_points = False

    # Required
    P_attrib = mesh_gdp.findPointAttrib("P")

    # Optional
    N_attrib = mesh_gdp.findVertexAttrib("N")
    if N_attrib is None:
        N_attrib = mesh_gdp.findPointAttrib("N")

    # If there are no vertex or point normals and we need to compute
    # them with a SopVerb
    if N_attrib is None and computeN:
        normal_verb = hou.sopNodeTypeCategory().nodeVerb("normal")
        normal_verb.setParms({"type": 0})
        normals_gdp = hou.Geometry()
        normal_verb.execute(normals_gdp, [mesh_gdp])
        mesh_gdp.clear()
        del mesh_gdp
        mesh_gdp = normals_gdp
        N_attrib = mesh_gdp.findPointAttrib("N")

    uv_attrib = mesh_gdp.findVertexAttrib("uv")
    if uv_attrib is None:
        uv_attrib = mesh_gdp.findPointAttrib("uv")

    S_attrib = mesh_gdp.findVertexAttrib("S")
    if S_attrib is None:
        S_attrib = mesh_gdp.findPointAttrib("S")

    faceIndices_attrib = mesh_gdp.findPrimAttrib("faceIndices")

    # TODO: If uv's don't exist, check for 'st', we'll assume uvs are a float[3]
    #       in Houdini and st are a float[2], or we could just auto-convert as
    #       needed.

    # We need to unique the points if any of the handles
    # to vtx attributes exists.
    for attrib in (N_attrib, uv_attrib, S_attrib):
        if attrib is None:
            continue
        if attrib.type() == hou.attribType.Vertex:
            unique_points = True
            break

    S = None
    uv = None
    N = None
    faceIndices = None

    if faceIndices_attrib is not None:
        faceIndices = array.array("i")
        faceIndices.fromstring(
            mesh_gdp.primIntAttribValuesAsString("faceIndices"))

    # We will unique points (verts in PBRT) if any of the attributes are
    # per vertex instead of per point.
    if unique_points:
        P = vtx_attrib_gen(mesh_gdp, P_attrib)
        indices = linear_vtx_gen(mesh_gdp)

        if N_attrib is not None:
            N = vtx_attrib_gen(mesh_gdp, N_attrib)
        if uv_attrib is not None:
            uv = vtx_attrib_gen(mesh_gdp, uv_attrib)
        if S_attrib is not None:
            S = vtx_attrib_gen(mesh_gdp, S_attrib)
    else:
        # NOTE: We are using arrays here for very fast access since we can
        #       fetch all the values at once compactly, while faster, this
        #       will take more RAM than a generator approach. If this becomes
        #       and issue we can change it.
        P = array.array("f")
        P.fromstring(mesh_gdp.pointFloatAttribValuesAsString("P"))
        indices = vtx_attrib_gen(mesh_gdp, None)
        if N_attrib is not None:
            N = array.array("f")
            N.fromstring(mesh_gdp.pointFloatAttribValuesAsString("N"))
        if S_attrib is not None:
            S = array.array("f")
            S.fromstring(mesh_gdp.pointFloatAttribValuesAsString("S"))
        if uv_attrib is not None:
            uv = pt_attrib_gen(mesh_gdp, uv_attrib)

    mesh_paramset.add(PBRTParam("integer", "indices", indices))
    mesh_paramset.add(PBRTParam("point", "P", P))
    if N is not None:
        mesh_paramset.add(PBRTParam("normal", "N", N))
    if S is not None:
        mesh_paramset.add(PBRTParam("vector", "S", S))
    if faceIndices is not None:
        mesh_paramset.add(PBRTParam("integer", "faceIndices", faceIndices))
    if uv is not None:
        # Houdini's uvs are stored as 3 floats, but pbrt only needs two
        # We'll use a generator comprehension to strip off the extra
        # float.
        uv2 = (x[0:2] for x in uv)
        mesh_paramset.add(PBRTParam("float", "uv", uv2))

    return mesh_paramset
Exemplo n.º 23
0
def wrangle_light(light, wrangler, now):

    # NOTE: Lights do not support motion blur so we disable it when
    #       outputs the xforms

    node = wrangle_node_parm(light, "light_node", now)

    parm_selection = {
        "light_wrangler": SohoPBRT("light_wrangler", "string", [""], False),
        "light_color": SohoPBRT("light_color", "float", [1, 1, 1], False),
        "light_intensity": SohoPBRT("light_intensity", "float", [1], False),
        "light_exposure": SohoPBRT("light_exposure", "float", [0], False),
    }
    parms = light.evaluate(parm_selection, now)
    light_wrangler = parms["light_wrangler"].Value[0]

    paramset = ParamSet()
    paramset.add(_to_light_scale(parms))

    if light_wrangler == "HoudiniEnvLight":
        env_map = []
        paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value))
        if light.evalString("env_map", now, env_map):
            paramset.add(PBRTParam("string", "mapname", env_map))
        output_xform(light, now, no_motionblur=True)
        api.Scale(1, 1, -1)
        api.Rotate(90, 0, 0, 1)
        api.Rotate(90, 0, 1, 0)
        _light_api_wrapper("infinite", paramset, node)
        return
    elif light_wrangler != "HoudiniLight":
        api.Comment("This light type, %s, is unsupported" % light_wrangler)
        return

    # We are dealing with a standard HoudiniLight type.

    light_type = light.wrangleString(wrangler, "light_type", now, ["point"])[0]

    if light_type in ("sphere", "disk", "grid", "tube", "geo"):

        single_sided = light.wrangleInt(wrangler, "singlesided", now, [0])[0]
        visible = light.wrangleInt(wrangler, "light_contribprimary", now, [0])[0]
        size = light.wrangleFloat(wrangler, "areasize", now, [1, 1])
        paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value))
        paramset.add(PBRTParam("bool", "twosided", [not single_sided]))

        # TODO, Possibly get the xform's scale and scale the geo, not the light.
        #       (for example, further multiplying down the radius)
        xform = get_transform(light, now)
        xform_to_api_srt(xform, scale=False)

        _light_api_wrapper("diffuse", paramset, node)

        api.AttributeBegin()

        # PBRT only supports uniform scales for non-mesh area lights
        # this is in part due to explicit light's area scaling factor.
        if light_type in ("grid", "geo"):
            api.Scale(size[0], size[1], size[0])

        # The visibility only applies to hits on the non-emissive side of the light.
        # the emissive side will still be rendered
        if not visible:
            api.Material("none")

        if light_type == "sphere":
            # We apply the scale to the radius instead of using a api.Scale
            api.Shape("sphere", [PBRTParam("float", "radius", 0.5 * size[0])])
        elif light_type == "tube":
            api.Rotate(90, 0, 1, 0)
            api.Shape(
                "cylinder",
                [
                    PBRTParam("float", "radius", 0.075 * size[1]),
                    PBRTParam("float", "zmin", -0.5 * size[0]),
                    PBRTParam("float", "zmax", 0.5 * size[0]),
                ],
            )
        elif light_type == "disk":
            # After pbrt-v3 commit #2f0852ce api.ReverseOrientation() is needed,
            # prior that it was a api.Scale(1,1,-1)
            # (see issue #183 in pbrt-v3)
            api.ReverseOrientation()
            api.Shape("disk", [PBRTParam("float", "radius", 0.5 * size[0])])
        elif light_type == "grid":
            api.Shape(
                "trianglemesh",
                [
                    PBRTParam("integer", "indices", [0, 3, 1, 0, 2, 3]),
                    PBRTParam(
                        "point",
                        "P",
                        [-0.5, -0.5, 0, 0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0],
                    ),
                ],
            )
        elif light_type == "geo":
            areageo_parm = hou.node(light.getName()).parm("areageometry")
            if not areageo_parm:
                api.Comment('No "areageometry" parm on light')
                return
            area_geo_node = areageo_parm.evalAsNode()
            if not area_geo_node:
                api.Comment("Skipping, no geometry object specified")
                return
            obj = soho.getObject(area_geo_node.path())
            api.Comment("Light geo from %s" % obj.getName())
            # TODO: The area light scale ('areasize') happens *after* the wrangle_obj's
            #       xform when 'intothisobject' is enabled.
            into_this_obj = light.wrangleInt(wrangler, "intothisobject", now, [0])[0]
            ignore_xform = not into_this_obj
            wrangle_obj(obj, None, now, ignore_xform=ignore_xform)

        api.AttributeEnd()

        return

    cone_enable = light.wrangleInt(wrangler, "coneenable", now, [0])[0]
    projmap = light.wrangleString(wrangler, "projmap", now, [""])[0]
    areamap = light.wrangleString(wrangler, "areamap", now, [""])[0]

    api_calls = []
    api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True))
    api_calls.append(_apiclosure(api.Scale, 1, 1, -1))
    api_calls.append(_apiclosure(api.Scale, 1, -1, 1))

    if light_type == "point":
        paramset.add(PBRTParam("rgb", "I", parms["light_color"].Value))
        if areamap:
            light_name = "goniometric"
            paramset.add(PBRTParam("string", "mapname", [areamap]))
            api_calls = []
            api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True))
            api_calls.append(_apiclosure(api.Scale, 1, -1, 1))
            api_calls.append(_apiclosure(api.Rotate, 90, 0, 1, 0))
        elif not cone_enable:
            light_name = "point"
        else:
            conedelta = light.wrangleFloat(wrangler, "conedelta", now, [10])[0]
            coneangle = light.wrangleFloat(wrangler, "coneangle", now, [45])[0]
            if projmap:
                light_name = "projection"
                paramset.add(PBRTParam("float", "fov", [coneangle]))
                paramset.add(PBRTParam("string", "mapname", [projmap]))
            else:
                light_name = "spot"
                coneangle *= 0.5
                coneangle += conedelta
                paramset.add(PBRTParam("float", "coneangle", [coneangle]))
                paramset.add(PBRTParam("float", "conedeltaangle", [conedelta]))
    elif light_type == "distant":
        light_name = light_type
        paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value))
    else:
        api.Comment("Light Type, %s, not supported" % light_type)
        return

    for api_call in api_calls:
        api_call()
    _light_api_wrapper(light_name, paramset, node)

    return
Exemplo n.º 24
0
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)
Exemplo n.º 25
0
def bounds_to_api_box(b):
    """Output a trianglemesh Shape of box based on the input bounds"""

    paramset = ParamSet()
    paramset.add(
        PBRTParam(
            "point",
            "P",
            [
                b[1],
                b[2],
                b[5],
                b[0],
                b[2],
                b[5],
                b[1],
                b[3],
                b[5],
                b[0],
                b[3],
                b[5],
                b[0],
                b[2],
                b[4],
                b[1],
                b[2],
                b[4],
                b[0],
                b[3],
                b[4],
                b[1],
                b[3],
                b[4],
            ],
        ))
    paramset.add(
        PBRTParam(
            "integer",
            "indices",
            [
                0,
                3,
                1,
                0,
                2,
                3,
                4,
                7,
                5,
                4,
                6,
                7,
                6,
                2,
                7,
                6,
                3,
                2,
                5,
                1,
                4,
                5,
                0,
                1,
                5,
                2,
                0,
                5,
                7,
                2,
                1,
                6,
                4,
                1,
                3,
                6,
            ],
        ))
    api.Shape("trianglemesh", paramset)
Exemplo n.º 26
0
def wrangle_integrator(obj, wrangler, now):

    node = wrangle_node_parm(obj, "integrator_node", now)
    if node is not None:
        return node.type_and_paramset

    parm_selection = {
        "integrator": SohoPBRT("integrator", "string", ["path"], False),
        "maxdepth": SohoPBRT("maxdepth", "integer", [5], False),
        "rrthreshold": SohoPBRT("rrthreshold", "float", [1], True),
        "lightsamplestrategy": SohoPBRT(
            "lightsamplestrategy", "string", ["spatial"], True
        ),
        "visualizestrategies": SohoPBRT("visualizestrategies", "toggle", [False], True),
        "visualizeweights": SohoPBRT("visualizeweights", "toggle", [False], True),
        "iterations": SohoPBRT("iterations", "integer", [64], True),
        "photonsperiterations": SohoPBRT("photonsperiterations", "integer", [-1], True),
        "imagewritefrequency": SohoPBRT(
            "imagewritefrequency", "integer", [2.14748e09], True
        ),
        "radius": SohoPBRT("radius", "float", [1], True),
        "bootstrapsamples": SohoPBRT("bootstrapsamples", "integer", [100000], True),
        "chains": SohoPBRT("chains", "integer", [1000], True),
        "mutationsperpixel": SohoPBRT("mutataionsperpixel", "integer", [100], True),
        "largestepprobability": SohoPBRT("largestepprobability", "float", [0.3], True),
        "sigma": SohoPBRT("sigma", "float", [0.01], True),
        "strategy": SohoPBRT("strategy", "string", ["all"], True),
        "nsamples": SohoPBRT("nsamples", "integer", ["64"], True),
        "cossample": SohoPBRT("cossample", "toggle", [True], True),
    }

    integrator_parms = {
        "ao": ["nsamples", "cossample"],
        "path": ["maxdepth", "rrthreshold", "lightsamplestrategy"],
        "bdpt": [
            "maxdepth",
            "rrthreshold",
            "lightsamplestrategy",
            "visualizestrategies",
            "visualizeweights",
        ],
        "mlt": [
            "maxdepth",
            "bootstrapsamples",
            "chains",
            "mutationsperpixel",
            "largestepprobability",
            "sigma",
        ],
        "sppm": [
            "maxdepth",
            "iterations",
            "photonsperiteration",
            "imagewritefrequency",
            "radius",
        ],
        "whitted": ["maxdepth"],
        "volpath": ["maxdepth", "rrthreshold", "lightsamplestrategy"],
        "directlighting": ["maxdepth", "strategy"],
    }
    parms = obj.evaluate(parm_selection, now)

    integrator_name = parms["integrator"].Value[0]
    paramset = ParamSet()
    for parm_name in integrator_parms[integrator_name]:
        if parm_name not in parms:
            continue
        paramset.add(parms[parm_name].to_pbrt())

    return (integrator_name, paramset)
Exemplo n.º 27
0
def smoke_prim_wrangler(prims,
                        paramset=None,
                        properties=None,
                        override_node=None):
    """Outputs a "heterogeneous" Medium and bounding Shape for the input geometry

    The following attributes are checked for via medium_prim_paramset() -
    (See pbrt_medium node for what each parm does)
    pbrt_interior (prim), string
    preset (prim), string
    g (prim), float
    scale (prim), float[3]
    sigma_a (prim), float[3]
    sigma_s (prim), float[3]

    Args:
        prims (list of hou.Prims): Input prims
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """
    # NOTE: Overlapping heterogeneous volumes don't currently
    #       appear to be supported, although this may be an issue
    #       with the Medium interface order? Visually it appears one
    #       object is blocking the other.

    # NOTE: Not all samplers support heterogeneous volumes. Determine which
    #       ones do, (and verify this is accurate).
    if properties is None:
        properties = {}

    if "pbrt_ignorevolumes" in properties and properties[
            "pbrt_ignorevolumes"].Value[0]:
        api.Comment("Ignoring volumes because pbrt_ignorevolumes is enabled")
        return

    medium_paramset = ParamSet()
    if "pbrt_interior" in properties:
        interior = BaseNode.from_node(properties["pbrt_interior"].Value[0])
        if interior is not None and interior.directive_type == "pbrt_medium":
            medium_paramset |= interior.paramset
        # These are special overrides that come from full point instancing.
        # It allows "per point" medium values to be "stamped" out to volume prims.
        interior_paramset = properties.get(".interior_overrides")
        if interior_paramset is not None:
            medium_paramset.update(interior_paramset)

    medium_suffix = ""
    instance_info = properties.get(".instance_info")
    if instance_info is not None:
        medium_suffix = ":%s[%i]" % (instance_info.source,
                                     instance_info.number)

    exterior = None
    if "pbrt_exterior" in properties:
        exterior = properties["pbrt_exterior"].Value[0]
    exterior = "" if exterior is None else exterior

    for prim in prims:
        smoke_paramset = ParamSet()

        medium_name = "%s[%i]%s" % (
            properties["object:soppath"].Value[0],
            prim.number(),
            medium_suffix,
        )
        resolution = prim.resolution()
        # TODO: Benchmark this vs other methods like fetching volumeSlices
        voxeldata = array.array("f")
        voxeldata.fromstring(prim.allVoxelsAsString())
        smoke_paramset.add(PBRTParam("integer", "nx", resolution[0]))
        smoke_paramset.add(PBRTParam("integer", "ny", resolution[1]))
        smoke_paramset.add(PBRTParam("integer", "nz", resolution[2]))
        smoke_paramset.add(PBRTParam("point", "p0", [-1, -1, -1]))
        smoke_paramset.add(PBRTParam("point", "p1", [1, 1, 1]))
        smoke_paramset.add(PBRTParam("float", "density", voxeldata))

        medium_prim_overrides = medium_prim_paramset(prim, medium_paramset)
        smoke_paramset.update(medium_prim_overrides)
        smoke_paramset |= paramset

        # By default we'll set a sigma_a and sigma_s to be more Houdini-like
        # however the object's pbrt_interior, or prim's pbrt_interior
        # or prim attribs will override these.
        if (PBRTParam("color", "sigma_a") not in smoke_paramset and PBRTParam(
                "color", "sigma_s") not in smoke_paramset) and PBRTParam(
                    "string", "preset") not in smoke_paramset:
            smoke_paramset.add(PBRTParam("color", "sigma_a", [1, 1, 1]))
            smoke_paramset.add(PBRTParam("color", "sigma_s", [1, 1, 1]))

        with api.AttributeBlock():
            xform = prim_transform(prim)
            api.ConcatTransform(xform)
            api.MakeNamedMedium(medium_name, "heterogeneous", smoke_paramset)
            api.Material("none")
            api.MediumInterface(medium_name, exterior)
            # Pad this slightly?
            bounds_to_api_box([-1, 1, -1, 1, -1, 1])
    return
Exemplo n.º 28
0
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)
Exemplo n.º 29
0
def wrangle_light(light, wrangler, now):


    # NOTE: Lights do not support motion blur so we disable it when
    #       outputs the xforms

    node = wrangle_node_parm(light, 'light_node', now)

    parm_selection = {
        'light_wrangler' : SohoPBRT('light_wrangler', 'string', [''], False),
        'light_color' : SohoPBRT('light_color', 'float', [1, 1, 1], False),
        'light_intensity' : SohoPBRT('light_intensity', 'float', [1], False),
        'light_exposure' : SohoPBRT('light_exposure', 'float', [0], False),
    }
    parms = light.evaluate(parm_selection, now)
    light_wrangler = parms['light_wrangler'].Value[0]

    paramset = ParamSet()
    paramset.add(_to_light_scale(parms))

    if light_wrangler == 'HoudiniEnvLight':
        env_map = []
        paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value))
        if light.evalString('env_map', now, env_map):
            paramset.add(PBRTParam('string', 'mapname', env_map))
        output_xform(light, now, no_motionblur=True)
        api.Scale(1, 1, -1)
        api.Rotate(90, 0, 0, 1)
        api.Rotate(90, 0, 1, 0)
        _light_api_wrapper('infinite', paramset, node)
        return
    elif light_wrangler != 'HoudiniLight':
        api.Comment('This light type, %s, is unsupported' % light_wrangler)
        return

    # We are dealing with a standard HoudiniLight type.

    light_type = light.wrangleString(wrangler, 'light_type', now, ['point'])[0]

    if light_type in ('sphere', 'disk', 'grid', 'tube', 'geo'):

        single_sided = light.wrangleInt(wrangler, 'singlesided', now, [0])[0]
        visible = light.wrangleInt(wrangler, 'light_contribprimary', now, [0])[0]
        size = light.wrangleFloat(wrangler, 'areasize', now, [1, 1])
        paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value))
        paramset.add(PBRTParam('bool', 'twosided', [not single_sided]))

        # TODO, Possibly get the xform's scale and scale the geo, not the light.
        #       (for example, further multiplying down the radius)
        xform = get_transform(light, now)
        xform_to_api_srt(xform, scale=False)

        _light_api_wrapper('diffuse', paramset, node)

        api.AttributeBegin()

        # PBRT only supports uniform scales for non-mesh area lights
        # this is in part due to explicit light's area scaling factor.
        if light_type in ('grid', 'geo'):
            api.Scale(size[0], size[1], size[0])

        # The visibility only applies to hits on the non-emissive side of the light.
        # the emissive side will still be rendered
        if not visible:
            api.Material('none')

        if light_type == 'sphere':
            # We apply the scale to the radius instead of using a api.Scale
            api.Shape('sphere', [PBRTParam('float', 'radius', 0.5*size[0])])
        elif light_type == 'tube':
            api.Rotate(90, 0, 1, 0)
            api.Shape('cylinder', [PBRTParam('float', 'radius', 0.075*size[1]),
                                   PBRTParam('float', 'zmin', -0.5*size[0]),
                                   PBRTParam('float', 'zmax', 0.5*size[0])])
        elif light_type == 'disk':
            # A bug was introduced with Issue #154 which requires a -z scale
            # on disk area lights
            # See issue #183
            # api.Scale(1,1,-1)
            api.Shape('disk', [PBRTParam('float', 'radius', 0.5*size[0])])
        elif light_type == 'grid':
            api.Shape('trianglemesh', [PBRTParam('integer', 'indices', [0, 3, 1,
                                                                        0, 2, 3]),
                                       PBRTParam('point', 'P', [-0.5, -0.5, 0,
                                                                0.5, -0.5, 0,
                                                                -0.5, 0.5, 0,
                                                                0.5, 0.5, 0])])
        elif light_type == 'geo':
            areageo_parm = hou.node(light.getName()).parm('areageometry')
            if not areageo_parm:
                api.Comment('No "areageometry" parm on light')
                return
            area_geo_node = areageo_parm.evalAsNode()
            if not area_geo_node:
                api.Comment('Skipping, no geometry object specified')
                return
            obj = soho.getObject(area_geo_node.path())
            api.Comment('Light geo from %s' % obj.getName())
            # TODO: The area light scale ('areasize') happens *after* the wrangle_obj's xform
            #       when 'intothisobject' is enabled.
            into_this_obj = light.wrangleInt(wrangler, 'intothisobject', now, [0])[0]
            ignore_xform = not into_this_obj
            wrangle_obj(obj, None, now, ignore_xform=ignore_xform)

        api.AttributeEnd()

        return

    cone_enable = light.wrangleInt(wrangler, 'coneenable', now, [0])[0]
    projmap = light.wrangleString(wrangler, 'projmap', now, [''])[0]
    areamap = light.wrangleString(wrangler, 'areamap', now, [''])[0]

    api_calls = []
    api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True))
    api_calls.append(_apiclosure(api.Scale, 1, 1, -1))
    api_calls.append(_apiclosure(api.Scale, 1, -1, 1))

    if light_type == 'point':
        paramset.add(PBRTParam('rgb', 'I', parms['light_color'].Value))
        if areamap:
            light_name = 'goniometric'
            paramset.add(PBRTParam('string', 'mapname', [areamap]))
            api_calls = []
            api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True))
            api_calls.append(_apiclosure(api.Scale, 1, -1, 1))
            api_calls.append(_apiclosure(api.Rotate, 90, 0, 1, 0))
        elif not cone_enable:
            light_name = 'point'
        else:
            conedelta = light.wrangleFloat(wrangler, 'conedelta', now, [10])[0]
            coneangle = light.wrangleFloat(wrangler, 'coneangle', now, [45])[0]
            if projmap:
                light_name = 'projection'
                paramset.add(PBRTParam('float', 'fov', [coneangle]))
                paramset.add(PBRTParam('string', 'mapname', [projmap]))
            else:
                light_name = 'spot'
                coneangle *= 0.5
                coneangle += conedelta
                paramset.add(PBRTParam('float', 'coneangle', [coneangle]))
                paramset.add(PBRTParam('float', 'conedeltaangle', [conedelta]))
    elif light_type == 'distant':
        light_name = light_type
        paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value))
    else:
        api.Comment('Light Type, %s, not supported' % light_type)
        return

    for api_call in api_calls:
        api_call()
    _light_api_wrapper(light_name, paramset, node)

    return
Exemplo n.º 30
0
def curve_wrangler(gdp, paramset=None, properties=None, override_node=None):
    """Outputs a "curve" Shape for input geometry

    The following attributes are checked for -

    P (point), built-in attribute
    width (vertex/point/prim), float
    N (vertex/point), float[3]
    curvetype (prim), string (overrides the property pbrt_curvetype)

    Args:
        gdp (hou.Geometry): Input geo
        paramset (ParamSet): Any base params to add to the shape. (Optional)
        properties (dict): Dictionary of SohoParms (Optional)
    Returns: None
    """

    if properties is None:
        properties = {}

    shape_paramset = ParamSet(paramset)

    curve_type = None
    if "pbrt_curvetype" in properties:
        curve_type = properties["pbrt_curvetype"].Value[0]
        shape_paramset.add(PBRTParam("string", "type", curve_type))
    if "splitdepth" in properties:
        shape_paramset.add(properties["splitdepth"].to_pbrt())

    gdp = _convert_nurbs_to_bezier(gdp)

    has_vtx_width = False if gdp.findVertexAttrib("width") is None else True
    has_pt_width = False if gdp.findPointAttrib("width") is None else True
    has_prim_width = False if gdp.findPrimAttrib("width") is None else True
    has_prim_width01 = False
    if (gdp.findPrimAttrib("width0") is not None
            and gdp.findPrimAttrib("width1") is not None):
        has_prim_width01 = True

    has_curvetype = False if gdp.findPrimAttrib("curvetype") is None else True

    has_vtx_N = False if gdp.findVertexAttrib("N") is None else True
    has_pt_N = False if gdp.findPointAttrib("N") is None else True

    for prim in gdp.prims():

        curve_paramset = ParamSet()
        prim_curve_type = curve_type

        # Closed curve surfaces are not supported
        if prim.intrinsicValue("closed"):
            continue

        order = prim.intrinsicValue("order")
        degree = order - 1
        # PBRT only supports degree 2 or 3 curves
        # TODO: We could possibly convert the curves to a format that
        #       pbrt supports but for now we'll expect the user to have
        #       a curve basis which is supported
        # https://www.codeproject.com/Articles/996281/NURBS-crve-made-easy
        if degree not in (2, 3):
            continue
        curve_paramset.add(PBRTParam("integer", "degree", degree))

        if prim.intrinsicValue("typename") == "BezierCurve":
            basis = "bezier"
        else:
            # We should not see these as they are being converted to BezierCurves
            basis = "bspline"
        curve_paramset.add(PBRTParam("string", "basis", [basis]))

        # SPEED consideration, run inline:
        # P = prim_pt2vtx_attrib_gen(prim)
        P = [pt.attribValue("P") for pt in prim.points()]
        curve_paramset.add(PBRTParam("point", "P", P))

        if has_curvetype:
            prim_val = prim.attribValue("curvetype")
            prim_curve_type = prim_val if prim_val else curve_type

        if prim_curve_type is not None:
            curve_paramset.add(PBRTParam("string", "type", [prim_curve_type]))

        if prim_curve_type == "ribbon":

            if has_vtx_N or has_pt_N:
                N = (prim.attribValueAt("N", u)
                     for u in prim.intrinsicValue("knots"))
            else:
                # If ribbon, normals must exist
                # TODO: Let pbrt error? Or put default values?
                N = [(0, 0, 1)] * len(prim.intrinsicValue("knots"))

            if N is not None:
                curve_paramset.add(PBRTParam("normal", "N", N))

        if has_vtx_width:
            curve_paramset.add(
                PBRTParam("float", "width0",
                          prim.vertex(0).attribValue("width")))
            curve_paramset.add(
                PBRTParam("float", "width1",
                          prim.vertex(-1).attribValue("width")))
        elif has_pt_width:
            curve_paramset.add(
                PBRTParam("float", "width0",
                          prim.vertex(0).point().attribValue("width")))
            curve_paramset.add(
                PBRTParam("float", "width1",
                          prim.vertex(-1).point().attribValue("width")))
        elif has_prim_width01:
            curve_paramset.add(
                PBRTParam("float", "width0", prim.attribValue("width0")))
            curve_paramset.add(
                PBRTParam("float", "width1", prim.attribValue("width1")))
        elif has_prim_width:
            curve_paramset.add(
                PBRTParam("float", "width", prim.attribValue("width")))
        else:
            # Houdini's default matches a width of 0.05
            curve_paramset.add(PBRTParam("float", "width", 0.05))

        curve_paramset |= shape_paramset
        curve_paramset |= prim_override(prim, override_node)
        api.Shape("curve", curve_paramset)
    return