Exemplo n.º 1
0
def output_materials(obj, wrangler, now):
    """Output Materials for an object

    The shop_materialpath parameter and shop_materialpath prim attribute
    are both checked for output.
    """
    # We use a shaderhandle instead of a string so Soho instances are properly
    # resolved when Full Instancing is used.
    parms = [
        soho.SohoParm('shop_materialpath', 'shaderhandle', skipdefault=False)
    ]
    eval_parms = obj.evaluate(parms, now)
    if eval_parms:
        shop = eval_parms[0].Value[0]
        if shop:
            wrangle_shading_network(shop)

    soppath = []
    if not obj.evalString('object:soppath', now, soppath):
        return
    soppath = soppath[0]

    gdp = SohoGeometry(soppath, now)
    global_material = gdp.globalValue('shop_materialpath')
    if global_material is not None:
        wrangle_shading_network(global_material[0])

    attrib_h = gdp.attribute('geo:prim', 'shop_materialpath')
    if attrib_h >= 0:
        shop_materialpaths = gdp.attribProperty(attrib_h, 'geo:allstrings')
        for shop in shop_materialpaths:
            wrangle_shading_network(shop)
    return
Exemplo n.º 2
0
def getInstancerAttributes(obj, now):
    attribs = [
        'geo:pointxform',  # Required
        'v',
        'instance',
        'instancefile',
        'shop_materialpath',
        'material_override'
    ]

    sop_path = []
    if not obj.evalString('object:soppath', now, sop_path):
        return  # No geometry associated with this object

    geo = SohoGeometry(sop_path[0], now)
    if geo.Handle < 0:  # No geometry data available
        return

    npts = geo.globalValue('geo:pointcount')[0]
    if not npts:
        return

    attrib_map = {}

    for attrib in attribs:
        handle = geo.attribute('geo:point', attrib)
        if handle >= 0:
            attrib_map[attrib] = handle

    return (geo, npts, attrib_map)
Exemplo n.º 3
0
def output_materials(obj, wrangler, now):
    """Output Materials for an object

    The shop_materialpath parameter and shop_materialpath prim attribute
    are both checked for output.
    """
    # We use a shaderhandle instead of a string so Soho instances are properly
    # resolved when Full Instancing is used.
    parms = [soho.SohoParm("shop_materialpath", "shaderhandle", skipdefault=False)]
    eval_parms = obj.evaluate(parms, now)
    if eval_parms:
        shop = eval_parms[0].Value[0]
        if shop:
            wrangle_shading_network(shop)

    soppath = []
    if not obj.evalString("object:soppath", now, soppath):
        return
    soppath = soppath[0]

    gdp = SohoGeometry(soppath, now)
    global_material = gdp.globalValue("shop_materialpath")
    if global_material is not None:
        wrangle_shading_network(global_material[0])

    attrib_h = gdp.attribute("geo:prim", "shop_materialpath")
    if attrib_h >= 0:
        shop_materialpaths = gdp.attribProperty(attrib_h, "geo:allstrings")
        for shop in shop_materialpaths:
            wrangle_shading_network(shop)

    # TODO / CONSIDER, for very large number of instance objects it might speed things
    #   up to cache the fact we've already visited a source network.
    #   Store in scenestate?
    #   (This will avoid much of the below on a per instance basis)
    instance_info = get_full_instance_info(obj, now)
    if instance_info is None:
        return
    attrib_h = instance_info.gdp.attribute("geo:point", "shop_materialpath")
    if attrib_h >= 0:
        shop_materialpaths = instance_info.gdp.attribProperty(
            attrib_h, "geo:allstrings"
        )
        for shop in shop_materialpaths:
            wrangle_shading_network(shop)
    return
def process_full_pt_instance_material(obj, now):

    # The order of evaluation.
    #   1. shaders attached to the actual prims (handled in PBRTgeo.py)
    #   2. per point assignments on the instancer
    #   3. instancer's shop_materialpath
    #   4. object being instanced shop_materialpath
    #   5. nothing
    #   The choice between 3 and 4 is handled automatically by soho

    full_instance_info = get_full_instance_info(obj)
    instancer_obj = soho.getObject(full_instance_info.source)
    instancer_sop = []
    if not instancer_obj.evalString('object:soppath', now, instancer_sop):
        return False
    instancer_sop = instancer_sop[0]
    gdp = SohoGeometry(instancer_sop, now)

    override_attrib_h = gdp.attribute('geo:point', 'material_overrides')
    shop_attrib_h = gdp.attribute('geo:point', 'shop_materialpath')

    if shop_attrib_h < 0:
        return False

    # We can just reference a NamedMaterial since there are no overrides
    if shop_attrib_h >= 0 and override_attrib_h < 0:
        shop = gdp.value(shop_attrib_h, full_instance_info.number)[0]
        if shop in scene_state.shading_nodes:
            api.NamedMaterial(shop)
        else:
            raise ValueError('Could not find shop in scene state')
        return True

    # Fully expand shading network since there will be uniqueness
    #return
    #wrangle_shading_network(shop,
    #                        use_named=False,
    #                        saved_nodes=set()
    #                       )

    return False
Exemplo n.º 5
0
def get_full_instance_info(obj, now):
    tokens = obj.getName().split(":")
    if len(tokens) != 3:
        return None
    instancer_obj = soho.getObject(tokens[1])
    instancer_sop = []
    if not instancer_obj.evalString("object:soppath", now, instancer_sop):
        return None
    instancer_sop = instancer_sop[0]
    gdp = SohoGeometry(instancer_sop, now)
    if gdp is None:
        return None
    return _FullInstance(tokens[0], tokens[1], int(tokens[2]), gdp)
Exemplo n.º 6
0
def mts_objects(obj, now, mat):
    """Add objects to mts_proxy... dict:
    dict = {'/obj/geo1/facet1': 
    (string_matrix4x4, proxy_file_path), 
     ...}
    """
    soppath = []
    if not obj.evalString('object:soppath', now, soppath):
        return
    geo = SohoGeometry(soppath[0], now)
    if geo.Handle < 0:
        return       
    plist = obj.evaluate(objectParms, now)
    xform = plist['space:world'].Value
    
    if len(xform) != 16:
        return  
    xform = hou.Matrix4(xform)
    xform = mts_matrix(xform)
    mts_proxy_files[soppath[0]]  = (xform, saveGeometry(soppath[0], now, mts_proxy_path), mat)
Exemplo n.º 7
0
def wrangle_fast_instances(obj, times):
    """Output instanced geoemtry defined by fast instancing"""

    # NOTE: Homogenous volumes work when applied to a ObjectBegin/End however
    #       Heterogenous volumes do not. The p0 p1 params aren't being
    #       transformed properly by the instance's CTM.

    if len(times) == 2:
        now, close = times
    else:
        now = times[0]
        close = None

    soppath = []
    if not obj.evalString("object:soppath", now, soppath):
        api.Comment("Can not find soppath for object")
        return
    sop = soppath[0]

    obj_node = hou.node(obj.getName())
    sop_node = hou.node(sop)
    if obj_node is None or sop_node is None:
        api.Comment("Can not resolve obj or geo")
        return

    # Exit out quick if we can't fetch the proper instance attribs.
    geo = SohoGeometry(sop, now)
    if geo.Handle < 0:
        api.Comment("No geometry available, skipping")
        return

    num_pts = geo.globalValue("geo:pointcount")[0]
    if not num_pts:
        api.Comment("No points, skipping")
        return

    # If motion blur is enabled, but our geometry isn't time dependent use one sample
    if close is not None:
        time_dependent = geo.globalValue("geo:timedependent")[0]
        if not time_dependent:
            close = None

    pt_attribs = (
        "geo:pointxform",
        "instance",
        # NOTE: Materials can not be applied to ObjectInstances
        # ( or setting material params (overrides) for that matter
        # See Excersise B.2 in 'The Book'
        # same applies for medium interfaces as well.
        # Applying them to the ObjectInstances does nothing
        # works on the base instance defintion
        # 'shop_materialpath',
        # 'material_override',
    )

    instancepath = []
    obj.evalString("instancepath", now, instancepath)
    instance_node = obj_node.node(instancepath[0])
    if instance_node is not None:
        default_instance_geo = instance_node.path()
    else:
        default_instance_geo = ""

    pt_attrib_map = {}
    for attrib in pt_attribs:
        attrib_h = geo.attribute("geo:point", attrib)
        if attrib_h >= 0:
            pt_attrib_map[attrib] = attrib_h

    if "geo:pointxform" not in pt_attrib_map:
        api.Comment("Can not find instance xform attribs, skipping")
        return

    # Default is 9 from CommonControl.ds
    soho_precision = []
    obj.evalInt("soho_precision", now, soho_precision)
    soho_precision = soho_precision[0] if soho_precision else 9

    concat_fmt = ("{{:.{}g}} ".format(soho_precision)) * 16
    instance_tmpl = (
        "\tAttributeBegin\t# {{\n"
        "\t    #  {}:{}\n"
        "\t    ConcatTransform [ " + concat_fmt + "]\n"
        '\t    ObjectInstance "{}"\n'
        "\tAttributeEnd\t# }}"
    ).format

    if close is not None:
        geo_1 = SohoGeometry(sop, close)
        if geo_1.Handle < 0:
            api.Comment("No geometry at shutter close available, skipping")
            return

        num_pts_1 = geo_1.globalValue("geo:pointcount")[0]
        if not num_pts_1:
            api.Comment("No points at shutter close, skipping")
            return

        if num_pts != num_pts_1:
            api.Comment("Point count mismatch between shutter open and close, skipping")
            return

        pointxform_1_h = geo_1.attribute("geo:point", "geo:pointxform")
        if pointxform_1_h < 0:
            api.Comment(
                "Can not find instance xform attribs in shutter close, skipping"
            )
            return

        instance_tmpl = (
            "\tAttributeBegin\t# {{\n"
            "\t    #  {}:{}\n"
            "\t    ActiveTransform StartTime\n"
            "\t    ConcatTransform [ " + concat_fmt + "]\n"
            "\t    ActiveTransform EndTime\n"
            "\t    ConcatTransform [ " + concat_fmt + "]\n"
            "\t    ActiveTransform All\n"
            '\t    ObjectInstance "{}"\n'
            "\tAttributeEnd\t# }}"
        ).format

    for pt in range(num_pts):
        instance_geo = default_instance_geo
        if "instance" in pt_attrib_map:
            pt_instance_geo = geo.value(pt_attrib_map["instance"], pt)[0]
            pt_instance_node = sop_node.node(pt_instance_geo)
            if pt_instance_node is not None:
                instance_geo = pt_instance_node.path()

        if not instance_geo:
            continue

        xform = geo.value(pt_attrib_map["geo:pointxform"], pt)

        ## Optimizaiton Start

        # The following is an optimization due to this being a hot section of the code
        # Avoiding the overhead of the various api.* calls and their handling of of
        # arrays can result in significant speeds ups.
        # In the case of 3,200,000 instances the overhead of wrangle_fast_instances
        # goes from 90.4s to 19.6s

        # Note: fstrings were compared against a str.format() and the resultant timings
        # were about the same but the format tmpl being cleaner on the code side.
        if close is None:
            print(instance_tmpl(sop, pt, *xform, instance_geo))
        else:
            xform1 = geo_1.value(pointxform_1_h, pt)
            print(instance_tmpl(sop, pt, *xform, *xform1, instance_geo))

        # The above replaces the following logic.
        # with api.AttributeBlock():
        #    api.Comment("%s:%i" % (sop, pt))
        #    xform = geo.value(pt_attrib_map["geo:pointxform"], pt)
        #    if close is None:
        #        api.ConcatTransform(xform)
        #    else:
        #        api.ActiveTransform("StartTime")
        #        api.ConcatTransform(xform)
        #        api.ActiveTransform("EndTime")
        #        xform = geo_1.value(pointxform_1_h, pt)
        #        api.ConcatTransform(xform)
        #        api.ActiveTransform("All")
        #    api.ObjectInstance(instance_geo)

        ## Optimizaiton End
    return
Exemplo n.º 8
0
def wrangle_instances(obj, now):
    """Output any instanced geoemtry referenced by the Soho Object"""

    # We need hou.Node handles so we can resolve relative paths
    # since soho does not do this.
    # NOTE: the above isn't true, some cleverness from RIBsettings shows
    # if len(shop_path) > 0:
    #   if not posixpath.isabs(shop_path):
    #     # make the shop_path absolute
    #     obj_path = obj.getDefaultedString("object:name", now, [''])[0]
    #     shop_path = posixpath.normpath(posixpath.join(obj_path, shop_path))
    soppath = []
    if not obj.evalString('object:soppath', now, soppath):
        api.Comment('Can not find soppath for object')
        return
    sop = soppath[0]

    obj_node = hou.node(obj.getName())
    sop_node = hou.node(sop)
    if obj_node is None or sop_node is None:
        api.Comment('Can not resolve obj or geo')
        return

    # Exit out quick if we can't fetch the proper instance attribs.
    geo = SohoGeometry(sop, now)
    if geo.Handle < 0:
        api.Comment('No geometry available, skipping')
        return

    num_pts = geo.globalValue('geo:pointcount')[0]
    if not num_pts:
        api.Comment('No points, skipping')
        return

    pt_attribs = (
        'geo:pointxform',
        'instance',
        # NOTE: Materials can not be applied to ObjectInstances
        # ( or setting material params (overrides) for that matter
        # See Excersise B.2 in 'The Book'
        # same applies for medium interfaces as well.
        # Applying them to the ObjectInstances does nothing
        # works on the base instance defintion
        # 'shop_materialpath',
        # 'material_override',
    )

    # NOTE: Homogenous volumes work when applied to a ObjectBegin/End however
    #       Heterogenous volumes do not. The p0 p1 params aren't being
    #       transformed properly by the instance's CTM.

    pt_attrib_map = {}
    for attrib in pt_attribs:
        attrib_h = geo.attribute('geo:point', attrib)
        if attrib_h >= 0:
            pt_attrib_map[attrib] = attrib_h

    if 'geo:pointxform' not in pt_attrib_map:
        api.Comment('Can not find instance xform attribs, skipping')
        return

    instancepath = []
    obj.evalString('instancepath', now, instancepath)
    instance_node = obj_node.node(instancepath[0])
    if instance_node is not None:
        default_instance_geo = instance_node.path()
    else:
        default_instance_geo = ''

    for pt in xrange(num_pts):
        instance_geo = default_instance_geo
        if 'instance' in pt_attrib_map:
            pt_instance_geo = geo.pt_instance_geovalue(
                pt_attrib_map['instance'], pt)[0]
            pt_instance_node = sop_node.node(pt_instance_geo)
            if pt_instance_node is not None:
                instance_geo = pt_instance_node.path()

        if not instance_geo:
            continue

        with api.AttributeBlock():
            api.Comment('%s:[%i]' % (sop, pt))
            xform = geo.value(pt_attrib_map['geo:pointxform'], pt)
            api.ConcatTransform(xform)
            api.ObjectInstance(instance_geo)
    return