Beispiel #1
0
def pack_geo(geo, name=None, xform=None):
    pack_verb = hou.sopNodeTypeCategory().nodeVerb('pack')
    pack_verb.setParms({'createpath': 0, 'pivot': 0, 'viewportlod': 'box'})

    packed_geo = hou.Geometry()
    pack_verb.execute(packed_geo, [geo])
    name_atr = packed_geo.addAttrib(hou.attribType.Prim,
                                    'name',
                                    '',
                                    create_local_variable=False)
    for prim in packed_geo.prims():
        if name is not None:
            prim.setAttribValue(name_atr, name)
        if xform is not None:
            prim.setTransform(xform)
    return packed_geo
Beispiel #2
0
def createFrustumGeometry():
    geo = hou.Geometry()
    tube_verb = hou.sopNodeTypeCategory().nodeVerb("tube")
    hou.SopVerb.setParms(
        tube_verb, {
            'type': 1,
            'cap': 1,
            'vertexnormals': 1,
            't': (0, 0, 0.25),
            'r': (-90, 0, 0),
            'rad': (0.5, 1),
            'height': 0.5,
            'cols': 10
        })
    hou.SopVerb.execute(tube_verb, geo, [])
    return geo
Beispiel #3
0
def load(node, geo, path):
    nodePath = node.path()
    function = inspect.stack()[0][3]
    try:
        missingframe = node.evalParm("missingframe")
        try:
            _geo = hou.Geometry()
            _geo.loadFromFile(path)
            geo.merge(_geo)
        except hou.OperationFailed:
            print("Could not load: " + path)
        except hou.GeometryPermissionError:
            print("Permissions Issue, are the files locked?")
    except (KeyboardInterrupt, SystemExit):
        print "Interrupt requested of " + function + " for " + nodePath + "...exiting"
        return
    def createVisPoint(self, i):
        self.point = hou.Geometry()

        u = self.node.parm('{}{}pos'.format(self.ramp_name, i + 1)).eval()
        pos = self.prim.positionAt(u)

        pt = self.point.createPoint()
        pt.setPosition(pos)

        self.point_vis = self.state_gadgets["point_vis"]
        self.point_vis.setGeometry(self.point)
        self.point_vis.setParams({
            "radius": 10,
            "draw_color": [1, 1, 0, 1],
            "locate_color": [1, 0, 0, 1],
            "pick_color": [1, 1, 0, 1]
        })
Beispiel #5
0
    def build_element_geo(self, variant=None):

        logging.info('Building element geo for %s', self.name)

        name = self.name
        element_dict = self.json_data
        if variant:
            name = variant
            logging.info('Constructing variant %s', name)
            if variant != 'base':
                element_dict = self.json_data['variants'][variant]
            else:
                # We don't need the transform matrix if we are a variant
                del element_dict['transformMatrix']
        geo = self.build_geo(name, element_dict)

        # If this was a variant exit out as we are done,
        # other wise keep on building any potential instance copies
        if variant:
            return geo

        out_geo = hou.Geometry()
        # We merge in the base geo
        out_geo.merge(geo)

        # Build instancedCopies
        for name, instance_dict in self.json_data.get('instancedCopies',
                                                      {}).iteritems():
            logging.info('Creating instance copy for %s', name)
            if (not instance_dict.get('instancedPrimitiveJsonFiles')
                    and not instance_dict.get('geomObjFile')):
                # No overrides of instance prims or geom so we can just copy the pack
                for prim in geo.prims():
                    prim.setAttribValue('name', name)
                    prim.setTransform(self.get_xform(instance_dict))
                    out_geo.merge(geo)
            else:
                instance_geo = self.build_geo(name, instance_dict)
                out_geo.merge(instance_geo)
                instance_geo.clear()

        geo.clear()
        return out_geo
Beispiel #6
0
    def test_copyPointAttributeValues(self):
        source = getObjGeo("test_copyPointAttributeValues")

        attribs = source.pointAttribs()

        geo = hou.Geometry()

        p1 = geo.createPoint()
        p2 = geo.createPoint()

        p1.copyAttribValues(source.iterPoints()[2], attribs)
        p2.copyAttribValues(source.iterPoints()[6], attribs)

        # Ensure all the attributes got copied right.
        self.assertEqual(len(geo.pointAttribs()), len(attribs))

        # Ensure P got copied right.
        self.assertEqual(p1.position(), hou.Vector3(5, 0, -5))
        self.assertEqual(p2.position(), hou.Vector3(-5, 0, 5))
Beispiel #7
0
    def test_copyPrimAttributeValues(self):
        source = getObjGeo("test_copyPrimAttributeValues")

        attribs = source.primAttribs()

        geo = hou.Geometry()

        p1 = geo.createPolygon()
        p2 = geo.createPolygon()

        p1.copyAttribValues(source.iterPrims()[1], attribs)
        p2.copyAttribValues(source.iterPrims()[4], attribs)

        # Ensure all the attributes got copied right.
        self.assertEqual(len(geo.primAttribs()), len(attribs))

        # Ensure P got copied right.
        self.assertEqual(p1.attribValue("prnum"), 1)
        self.assertEqual(p2.attribValue("prnum"), 4)
Beispiel #8
0
 def build_instanceprims(self, instance_dict):
     logging.info('Handling instancedPrimitiveJsonFiles')
     json_geo = hou.Geometry()
     for name, instance_prim in instance_dict.iteritems():
         logging.info('instancedPrimitiveJsonFiles: %s', name)
         if instance_prim['type'] == 'archive':
             json_prim = ArchivePrims(self, name, instance_prim)
         elif instance_prim['type'] == 'curve':
             json_prim = CurvePrims(self, name, instance_prim)
         elif instance_prim['type'] == 'element':
             json_prim = ElementPrims(self, name, instance_prim)
         else:
             logging.info('Unknown instance_prim type, %s, skipping',
                          instance_prim['type'])
             continue
         prim_geo = json_prim.build_geo()
         json_geo.merge(prim_geo)
         prim_geo.clear()
     return json_geo
Beispiel #9
0
    def test_setSharedPointStringAttribGroup(self):
        TARGET = ["point0"] * 5 + [""] * 5

        geo = hou.Geometry()

        attr = geo.addAttrib(hou.attribType.Point, "test", "")

        geo.createPoints(5)
        group = geo.createPointGroup("group1")

        for point in geo.points():
            group.add(point)

        geo.createPoints(5)

        geo.setSharedPointStringAttrib(attr.name(), "point0", group)

        vals = [point.attribValue(attr) for point in geo.points()]

        self.assertEqual(vals, TARGET)
Beispiel #10
0
    def createPoints(self):
        self.point_handle = hou.Geometry()

        rampKeys = self.ramp_parm.eval().keys()
        numPoints = len(rampKeys)

        for i in range(numPoints):
            u = self.node.parm('{}{}pos'.format(self.ramp_name, i + 1)).eval()
            pos = self.prim.positionAt(u)

            pt = self.point_handle.createPoint()
            pt.setPosition(pos)

        self.point_gadget = self.state_gadgets["point_gadget"]
        self.point_gadget.setGeometry(self.point_handle)
        self.point_gadget.setParams({
            "radius": 10,
            "draw_color": [0, 0.5, 1, 1],
            "locate_color": [0, 0.5, 1, 1],
            "pick_color": [0, 0.5, 1, 1]
        })
Beispiel #11
0
    def __init__(self, sceneviewer):

        self.scene_viewer = sceneviewer

        self.knob_geo = hou.Geometry()
        self.knob_pt = self.knob_geo.createPoint()

        self.knob_drawable = hou.GeometryDrawable(
            self.scene_viewer,
            hou.drawableGeometryType.Point,
            "highlighter_knob",
            params={
                'style': hou.drawableGeometryPointStyle.SmoothCircle,
                'color1': hou.Vector4(1.0, 1.0, 1.0, 1.0),
                'radius': 8,
                'fade_factor': 0.5
            })

        self.knob_drawable.setGeometry(self.knob_geo)

        self.show(False)
Beispiel #12
0
    def highlightPoint(self, point_num, position):
        ### Display a pystate drawable at a points position

        if point_num != -1:
            if point_num != self.currentPoint:
                ### We're only updating currentPoint when it is different to minimize update calls to Drawables.
                self.currentPoint = point_num
                #u = self.geometry.prim(self.currentPrimid).attribValueAtInterior("u", self.currentPrimu, 0, 0)
                #u = self.geometry.point(self.currentPoint).attribValue("u")
                #self.cursor_text = "<font size=4,>%f</font>" % (u)

                new_geo = hou.Geometry()
                point = new_geo.createPoint()
                point.setPosition(position)

                # update the drawable
                self.poly_guide.setGeometry(new_geo)
                self.showGuides(True)

        else:
            self.currentPoint = -1
            self.poly_geo = None
            self.showGuides(False)
Beispiel #13
0
def output_geo(soppath, now, properties=None):
    """Output the geometry by calling the appropriate wrangler

    Geometry is partitioned into subparts based on the shop_materialpath
    and material_override prim attributes.

    Args:
        soppath (str): oppath to SOP
        properties (dict, None): Dictionary of SohoParms
                                 (Optional, defaults to None)
    Returns:
        None
    """

    # split by material
    # split by geo type
    # if mesh type, split by material override
    # else deal with overrides per prim
    #
    # NOTE: We won't be splitting based on medium interior/exterior
    #       those will be left as a object level assignment only.
    #       Note, that in the case of Houdini Volumes they will look
    #       for the appropriate medium parameters as prim vars

    if properties is None:
        properties = {}

    ignore_materials = False
    if "pbrt_ignorematerials" in properties:
        ignore_materials = properties["pbrt_ignorematerials"].Value[0]

    # Houdini / Mantra allows for shop_materialpaths on both prims and details
    # at the same time. However prims full stomp over detail. If you have a prim
    # with an empty material assignment, it will NOT fall back to the detail
    # assignment. (It will fall back to the object since that is further up the
    # stack). This means if the shop_materialpath exists on the prim, the
    # detail is ignored entirely.

    # PBRT allows setting Material parameters on the Shapes in order to
    #       override a material's settings.  (Shapes get checked first)
    #       This paramset will be for holding those overrides and passing
    #       them down to the actual shape api calls.

    # We need the soppath to come along and since we are creating new
    # hou.Geometry() we'll lose the original sop connection so we need
    # to stash it here.

    node = hou.node(soppath)
    if node is None or node.type().category() != hou.sopNodeTypeCategory():
        return

    input_gdp = node.geometry()
    if input_gdp is None:
        return
    gdp = hou.Geometry()
    gdp.merge(input_gdp.freeze())

    default_material = ""
    default_override = ""
    if not ignore_materials:
        try:
            default_material = gdp.stringAttribValue("shop_materialpath")
        except hou.OperationFailed:
            pass
        if default_material not in scene_state.shading_nodes:
            default_material = ""

        try:
            default_override = gdp.stringAttribValue("material_override")
        except hou.OperationFailed:
            default_override = ""

    # These handles are only valid until until we clear the geo
    prim_material_h = gdp.findPrimAttrib("shop_materialpath")
    prim_override_h = gdp.findPrimAttrib("material_override")

    has_prim_overrides = bool(not ignore_materials
                              and prim_override_h is not None
                              and prim_material_h is not None)

    if prim_material_h is not None and not ignore_materials:
        material_gdps = partition_by_attrib(gdp, prim_material_h)
        gdp.clear()
    else:
        material_gdps = {default_material: gdp}

    # The gdp these point to may have been cleared
    del prim_override_h
    del prim_material_h

    for material, material_gdp in material_gdps.iteritems():

        if material not in scene_state.shading_nodes:
            material = ""
            material_node = None
        else:
            api.AttributeBegin()
            api.NamedMaterial(material)
            material_node = MaterialNode(material)

        shape_gdps = partition_by_attrib(material_gdp,
                                         "typename",
                                         intrinsic=True)
        material_gdp.clear()

        for shape, shape_gdp in shape_gdps.iteritems():

            # Aggregate overrides, instead of per prim
            if has_prim_overrides and requires_override_partition(shape):
                override_attrib_h = shape_gdp.findPrimAttrib(
                    "material_override")
                override_gdps = partition_by_attrib(shape_gdp,
                                                    override_attrib_h)
                shape_gdp.clear()
                del override_attrib_h

                # We don't the wranglers to handle the overrides since we are doing it
                # here. So we'll set this to false, which will mean the override_node
                # is None and not trigger per prim overrides
                has_prim_overrides = False
            else:
                override_gdps = {default_override: shape_gdp}

            for override, override_gdp in override_gdps.iteritems():

                override_paramset = ParamSet()
                if override and material_node is not None:
                    # material parm overrides are only valid for MaterialNodes
                    override_paramset |= material_node.override_paramset(
                        override)

                if has_prim_overrides:
                    override_node = material_node
                else:
                    override_node = None

                # At this point the gdps are partitioned first by material
                # then by type. And then if its in requires_override_partition
                # it has been further partitioned.
                # The implies that we will NOT have varying types or materials
                # past this point. The wranglers will need to know the following-
                #   * is there a prim override?
                #   * is the material valid?
                #   * the material_node itself to apply overrides if they exist
                #
                #   The only case where we *need* to pass down the override info is if
                #   * the material_node is valid
                #   * material_overrides exists
                #
                #   We don't want to reconstruct a new material_node for every prim
                #   as it will be constant.
                #
                #   Option 1: <selected>
                #   We can pass a material_node only if we need to apply overrides
                #   but that gives variable dual meaning.
                #   Option 2:
                #   Alternatively we can pass the material_node and also a
                #   prim_overrides flag either in the properties or as its own function
                #   arg.

                shape_wrangler = shape_wranglers.get(shape, not_supported)
                if shape_wrangler:
                    shape_wrangler(override_gdp, override_paramset, properties,
                                   override_node)
                override_gdp.clear()

        if material:
            api.AttributeEnd()
    return
Beispiel #14
0
    def test_setPointStringAttribValuesInvalidAttribute(self):
        TARGET = ('point0', 'point1', 'point2', 'point3', 'point4')
        geo = hou.Geometry()

        self.assertRaises(hou.OperationFailed, geo.setPointStringAttribValues,
                          "test", TARGET)
Beispiel #15
0
def onGenerate(self, item_holder, upstream_items, generation_type):
    # static parms
    MULTILAYER = ("RGB", "RGBA", "P", "CMYK", "YCbCr", "LAB", "HSV")
    SINGLELAYER = ("1", "L", "I", "F")
    BIT32 = ("I", "F")
    BIT8 = ("L" ,"P", "RGB", "RGBA", "P", "CMYK", "YCbCr", "LAB", "HSV")
    BIT1 = ("1")
    CONVERT32 = 65535.0
    CONVERT8 = 255.0
    node = hou.nodeBySessionId(self.customId)
    isprintlog = node.parm("isprintlog").eval()
    issetattribute = node.parm("setattribute").eval()
    attributeName = node.parm("nofileattribute").evalAsString()
    hasher = hashlib.md5()
    def createHeightFieldGeometry(name, size, center, rotate, heightscale=1, moveheight=0, 
                                  isFileExists=0, filepath="", initval=0):
        '''
        create HeightField Geometry from file
        '''
        # init geometry
        fileerror = False

        geo = hou.Geometry().freeze()
        geo.addAttrib(hou.attribType.Prim, "name", "")

        halfsize = size * 0.5
        bounds = hou.Geometry().boundingBox()
        bounds.setTo((-halfsize, -halfsize, -0.5, halfsize, halfsize, 0.5))
        
        # init volume
        vol = geo.createVolume(size, size, 1, bounds)
        vol.setAttribValue("name", name)
        im_hash = "-1"
        if isFileExists:
        # read landscape/masks
            try:
                im = Image.open(filepath)
                im = im.transpose(Image.TRANSPOSE)
                # check image size
                if im.size[0] != size or im.size[1] != size:
                    im = im.resize((size, size))
                # save as image numpy array pix
                im_hash = hashlib.md5(im.tobytes()).hexdigest()
                im_hash = str(im_hash)
                immode = im.mode
                if immode in SINGLELAYER:
                    if immode in BIT32:
                        pix = np.asarray(im) / CONVERT32
                    elif immode in BIT8:
                        pix = np.asarray(im) / CONVERT8
                    else: 
                        pix = np.asarray(im)
              #  im_hash = str(im_hash)

            except:
                fileerror = True
                pix = np.full((size, size), initval)
        else:
            pix = np.full((size, size), initval)
        # set pix to volume
        vol.setAllVoxels((pix*heightscale+moveheight).flatten())            
        # transform geometry
        rotationMtx = hou.hmath.buildRotate(-90,-90,0)
        transformMtx = hou.hmath.buildTranslate(center[0],0,center[1])
        geo.transform(rotationMtx)
        geo.transform(transformMtx)

        return geo, fileerror, im_hash

    E = lambda p : node.parm(p).eval()
    # gather parameters
    size = node.parm("size").evalAsInt()
    filepath = node.parm("filepath").evalAsString()
    center = node.parmTuple('t').eval()
    rotate = E('rotate')
    heightscale = E('heightscale')
    moveheight = E('moveheight')

    iffilenotexist = E('iffilenotexist') # 0 -> report error
                                                        # 1 -> set black
                                                        # 2 -> set white
                                                        # 3 -> set value
    setvalue = E('setvalue')             # only if iffilenotexist == 3                                           
    loadtype = E("loadtype")   # 0 -> create heightfield from scrach 
                                                # 1 -> load to upstream heightfield
    createtype = E("type")     # 0 -> heightfield, 
                                                # 1 -> mask
    layername = E("layer")     # if load to upstream heightfield, set custom mask name
    layermode = E("layermode") # 0 -> replace
                                                # 1 -> add
                                                # 2 -> subtract
                                                # 3 -> difference
                                                # 4 -> multiply
                                                # 5 -> maximum
                                                # 6 -> minimum

    bordertype = E("layerborder") # 0 -> constant
                                                    # 1 -> repeat
                                                    # 2 -> streak

    borderval = E("layerborderval") # only if bordertype == 0

    is_set_hash = E("issethash")
    hash_attrib = E("hashattributename")
    is_add_hash = E("isaddhash")
    add_hash_attrib = E("addhashattrib")
    for upstream_item in upstream_items:     
        fileerror = False

        # check if file exist
        isfileexists = checkfile(filepath)
        initval = 0

        if not isfileexists:
            if iffilenotexist == 0:
                raise IOError("File not found! Please check your file {0}".format(filepath))
            elif iffilenotexist == 2:
                initval = 1
            elif iffilenotexist == 3:
                initval = setvalue

        # do works
        ## node verb for border type (primitive node)
        maskprimitiveVerb = createVolumePrimitiveVerb("mask")
        im_hash = -1
        if loadtype == 0:
            heightfieldpeimitiveVerb = createVolumePrimitiveVerb("height")
            if createtype == 0:
                name = "height"
                heightfield, fileerror, im_hash = createHeightFieldGeometry(name, size, center, rotate, heightscale, moveheight, isfileexists, filepath, initval)
                masklayer, maskerror, _ = createHeightFieldGeometry("mask", size, center, rotate)
            else:
                name = "mask"
                masklayer, fileerror, im_hash = createHeightFieldGeometry(name, size, center, rotate, heightscale, moveheight, isfileexists, filepath, initval)
                heightfield, maskerror, _ = createHeightFieldGeometry("height", size, center, rotate)
            
            heightfieldpeimitiveVerb.execute(heightfield, [heightfield])
            maskprimitiveVerb.execute(masklayer, [masklayer])

            heightfield.merge(masklayer)
            
        else:
            heightfield = hou.Geometry().freeze()
            heightfield.loadFromFile(upstream_item.resultData[0][0])
            name = layername
            additionallayer, fileerror, im_hash = createHeightFieldGeometry(name, size, center, rotate, heightscale, moveheight, isfileexists, filepath, initval)
            additionalPrimitiveVerb = createVolumePrimitiveVerb(name, bordertype, borderval)
            additionalPrimitiveVerb.execute(additionallayer, [additionallayer])

            ismergelayer = 0
            for layer in heightfield.prims():
                if layer.stringAttribValue("name") == name:
                    ismergelayer = 1
                    voxels = additionallayer.prims()[0]
                    if layermode == 0:                # 0 -> replace
                        layer.setAllVoxels(voxels.allVoxels())
                    else:
                        in_voxelArray = np.asanyarray(layer.allVoxels)
                        blend_voxelArray = np.asanyarray(voxels.allVoxels)
                        if layermode == 1:                # 1 -> add
                            layer.setAllVoxels((in_voxelArray+blend_voxelArray).flatten())
                        elif layermode == 2:              # 2 -> subtract
                            layer.setAllVoxels((in_voxelArray-blend_voxelArray).flatten())
                        elif layermode == 3:              # 3 -> difference
                            layer.setAllVoxels(np.absolute(in_voxelArray-blend_voxelArray).flatten())
                        elif layermode == 4:              # 4 -> multiply
                            layer.setAllVoxels((in_voxelArray*blend_voxelArray).flatten())
                        elif layermode == 5:              # 5 -> maximum
                            layer.setAllVoxels(np.maximum(in_voxelArray+blend_voxelArray).flatten())
                        elif layermode == 6:              # 6 -> minimum
                            layer.setAllVoxels(np.minimum(in_voxelArray+blend_voxelArray).flatten())
            if ismergelayer == 0:
                heightfield.merge(additionallayer)
        ## node verb for visulization (volumevisualization node)
        heightfieldVisVerb = createHeightFieldVisVerb()
        heightfieldVisVerb.execute(heightfield, [heightfield])
        
        work_item = item_holder.addWorkItem(cloneResultData=False, preserveType=True,
            parent=upstream_item)

        if is_set_hash:
            if is_add_hash:
                im_hash = "%x" % (int(im_hash, 16) + int(add_hash_attrib, 16))
            work_item.data.setString(hash_attrib, im_hash, 0)
            outputfile = node.parm('outputfile').unexpandedString()
            outputfile = outputfile.replace("`@{0}`".format(hash_attrib), im_hash)
            outputfile = hou.expandString(outputfile)
        else:
            outputfile = E('outputfile') 
        # self.scheduler.localizePath(work_item.resultData[0][0])
        makeoutputpathsafe(outputfile)
        heightfield.saveToFile(outputfile)
        work_item.addResultData(outputfile, "file/geo", 0)

        if not isfileexists:
            if isprintlog:
                print "File not found: {0}".format(filepath)
            if issetattribute:
                work_item.data.setInt(attributeName, 1, 0)
        else:
            if issetattribute:
                if fileerror:
                    work_item.data.setInt(attributeName, 1, 0)
                else:
                    work_item.data.setInt(attributeName, 0, 0)
        return pdg.result.Success
Beispiel #16
0
def output_geo(soppath, now, properties=None):
    """Output the geometry by calling the appropriate wrangler

    Geometry is partitioned into subparts based on the shop_materialpath
    and material_override prim attributes.

    Args:
        soppath (str): oppath to SOP
        properties (dict, None): Dictionary of SohoParms
                                 (Optional, defaults to None)
    Returns:
        None
    """
    # split by material
    # split by material override #
    # split by geo type
    # NOTE: We won't be splitting based on medium interior/exterior
    #       those will be left as a object level assignment only.
    #       Note, that in the case of Houdini Volumes they will look
    #       for the appropriate medium parameters as prim vars

    if properties is None:
        properties = {}

    ignore_materials = False
    if 'pbrt_ignorematerials' in properties:
        ignore_materials = properties['pbrt_ignorematerials'].Value[0]

    # PBRT allows setting Material parameters on the Shapes in order to
    #       override a material's settings.  (Shapes get checked first)
    #       This paramset will be for holding those overrides and passing
    #       them down to the actual shape api calls.
    material_paramset = ParamSet()

    # We need the soppath to come along and since we are creating new
    # hou.Geometry() we'll lose the original sop connection so we need
    # to stash it here.

    node = hou.node(soppath)
    if node is None or node.type().category() != hou.sopNodeTypeCategory():
        return

    input_gdp = node.geometry()
    if input_gdp is None:
        return
    gdp = hou.Geometry()
    gdp.merge(input_gdp.freeze())

    # Partition based on materials
    global_material = None
    if not ignore_materials:
        try:
            global_material = gdp.stringAttribValue('shop_materialpath')
        except hou.OperationFailed:
            pass

    attrib_h = gdp.findPrimAttrib('shop_materialpath')
    if attrib_h is not None and not ignore_materials:
        material_gdps = partition_by_attrib(gdp, attrib_h)
    else:
        material_gdps = {global_material: gdp}

    global_override = None
    if not ignore_materials:
        try:
            global_override = gdp.stringAttribValue('material_override')
        except hou.OperationFailed:
            pass

    # Further partition based on material overrides
    has_prim_overrides = bool(
        not ignore_materials
        and gdp.findPrimAttrib('material_override') is not None)

    for material in material_gdps:
        if material:
            api.AttributeBegin()
            api.NamedMaterial(material)

        material_gdp = material_gdps[material]
        #api.Comment('%s %i' % (material_gdp,len(material_gdp.prims())))

        if has_prim_overrides:
            attrib_h = material_gdp.findPrimAttrib('material_override')
            override_gdps = partition_by_attrib(material_gdp, attrib_h)
            # Clean up post partition
            material_gdp.clear()
        else:
            override_gdps = {global_override: material_gdp}

        for override in override_gdps:
            override_gdp = override_gdps[override]
            #api.Comment(' %s %i' % (override_gdp, len(override_gdp.prims())))

            shape_gdps = partition_by_attrib(override_gdp,
                                             'typename',
                                             intrinsic=True)
            override_gdp.clear()

            for shape in shape_gdps:
                material_paramset = ParamSet()

                if override and material:
                    material_paramset.update(
                        override_to_paramset(material, override))

                shape_gdp = shape_gdps[shape]
                #api.Comment('  %s %i' % (shape_gdp, len(shape_gdp.prims())))

                shape_wrangler = shape_wranglers.get(shape, not_supported)
                if shape_wrangler:
                    shape_wrangler(shape_gdp, material_paramset, properties)
                shape_gdp.clear()

        if material:
            api.AttributeEnd()
    return
Beispiel #17
0
    def test_createPointsInvalidNumber(self):
        geo = hou.Geometry()

        self.assertRaises(hou.OperationFailed, geo.createPoints, -4)
Beispiel #18
0
    def test_createPoints(self):
        geo = hou.Geometry()
        points = geo.createPoints(15)

        self.assertEqual(points, geo.points())
Beispiel #19
0
    def test_createPoint(self):
        geo = hou.Geometry()

        point = geo.createPoint(hou.Vector3(1, 2, 3))

        self.assertEqual(point.position(), hou.Vector3(1, 2, 3))
Beispiel #20
0
 def test_isReadOnlyFalse(self):
     geo = hou.Geometry()
     self.assertFalse(geo.isReadOnly())
Beispiel #21
0
def createPointGeometry():
    geo = hou.Geometry()
    hou.Geometry.createPoint(geo)
    return geo
Beispiel #22
0
def createLineGeometry():
    geo = hou.Geometry()
    line_verb = hou.sopNodeTypeCategory().nodeVerb("line")
    hou.SopVerb.setParms(line_verb, {'dir': (0, 0, 1)})
    hou.SopVerb.execute(line_verb, geo, [])
    return geo
Beispiel #23
0
def createSphereGeometry():
    geo = hou.Geometry()
    sphere_verb = hou.sopNodeTypeCategory().nodeVerb("sphere")
    hou.SopVerb.setParms(sphere_verb, {'type': 2, 'rows': 30, 't': (0, 0, 1)})
    hou.SopVerb.execute(sphere_verb, geo, [])
    return geo
Beispiel #24
0
    def write_ramp_sketch(self):
        if len(self.positions) < 2:
            return

        positions = np.array([(float(p.x()), float(-p.y()))
                              for p in self.positions])

        min_point = positions.min(axis=0)
        max_point = positions.max(axis=0)

        ramp_range = max_point - min_point

        if not np.any((ramp_range == 0.0)):
            norm_positions = (positions - min_point) / ramp_range

            geo_points = []
            geo_points.append(
                hou.Vector3(norm_positions[0][0], norm_positions[0][1], 0.0))
            left = 0.0
            for pt in norm_positions[1:-1]:
                if pt[0] >= left:
                    left = pt[0]
                    geo_points.append(hou.Vector3(pt[0], pt[1], 0.0))

            geo_points.append(
                hou.Vector3(norm_positions[-1][0], norm_positions[-1][1], 0.0))

            ramp_geo = hou.Geometry()  # type: hou.Geometry
            ramp_points = ramp_geo.createPoints(geo_points)
            ramp_geo.createPolygons((ramp_points, ), False)

            resample_verb = hou.sopNodeTypeCategory().nodeVerb(
                "resample")  # type: hou.SopVerb
            resample_verb.setParms({"length": 0.04})

            resample_verb.execute(ramp_geo, [ramp_geo])

            facet_verb = hou.sopNodeTypeCategory().nodeVerb(
                "facet")  # type: hou.SopVerb
            facet_verb.setParms({"inline": 1, "inlinedist": 0.003})

            facet_verb.execute(ramp_geo, [ramp_geo])

            ramp_poly = ramp_geo.prim(0)
            ramp_points = ramp_poly.points()

            ramp_basis = hou.rampBasis.BSpline if self.disable_gamma_correction else hou.rampBasis.Linear

            basis = []
            keys = []
            values = []

            for point in ramp_points:  # type: hou.Point
                basis.append(ramp_basis)
                pos = point.position()
                keys.append(pos.x())
                values.append(pos.y())

            ramp = hou.Ramp(basis, keys, values)
            self.parm.set(ramp)
            self.parm.pressButton()
Beispiel #25
0
def build_bgeo(obj, bgeo, element_name):
    """Convert a obj file to a bgeo

    obj (str): File path to obj (input)
    bgeo (str): File path to bgeo (output)
    element_name (str): Name of the element (for material assignments)
    """

    logging.info('Converting %s to %s', obj, bgeo)
    bgeo_dir = os.path.dirname(bgeo)
    if not os.path.isdir(bgeo_dir):
        os.makedirs(bgeo_dir)

    hier = os.path.splitext(obj)[0] + '.hier'
    with open(hier, 'rb') as hier_h:
        hier_data = json.load(hier_h)

    geo = hou.Geometry()
    prim_counter = collections.Counter()

    with make_tempfile() as tmp_obj_h:
        with ObjReader(obj) as f:
            for line in f:
                tmp_obj_h.write(line)
            tmp_obj_h.close()

            geo.loadFromFile(tmp_obj_h.name)

            # If duplication is detected (and verified that there
            # is an even number of them) delete the back half.
            num_prims = len(geo.prims())
            if f.doubled_geo() and num_prims % 2 == 0:
                logging.warning('Duplicate geo detected, cleaning!')
                duped_prims = geo.prims()[num_prims / 2:]
                geo.deletePrims(duped_prims)

            # Optional, remove N (normals) as we'll be subdividing
            #N_atr = geo.findPointAttrib('N')
            #if N_atr:
            #    N_atr.destroy()

            name_atr = geo.addAttrib(hou.attribType.Prim,
                                     'name',
                                     '',
                                     create_local_variable=False)
            #hier_atr = geo.addAttrib(hou.attribType.Prim, 'hier', '',
            #                         create_local_variable=False)
            facenum_atr = geo.addAttrib(hou.attribType.Prim,
                                        'facenum',
                                        0,
                                        create_local_variable=False)
            for prim in geo.prims():
                prim_name = f.prim_names[prim.number()]
                prim_hier = hier_data.get(prim_name, '')
                prim.setAttribValue(name_atr, prim_name)
                material = prim.attribValue('shop_materialpath')
                material_name = os.path.basename(material)
                element_material = '/mat/%s.%s' % (element_name, material_name)
                prim.setAttribValue('shop_materialpath', element_material)
                #prim.setAttribValue(hier_atr, prim_hier)
                prim.setAttribValue(facenum_atr, prim_counter[prim_name])
                prim_counter[prim_name] += 1
            logging.info('Saving out %s', bgeo)
            geo.saveToFile(bgeo)
        geo.clear()
    return prim_counter
Beispiel #26
0
 def build_geo(self):
     return hou.Geometry()
Beispiel #27
0
    def write_color_ramp(self):
        if len(self.colors) < 2:
            return

        color_points = []

        vlast_color = hou.Vector3(hou.qt.fromQColor(self.colors[0])[0].rgb())
        last_color_index = 0

        color_points.append((vlast_color, 0))

        # remove same keys in a row
        for index, color in enumerate(self.colors[1:]):
            color_index = index + 1
            vcolor = hou.Vector3(hou.qt.fromQColor(color)[0].rgb())
            dist = vcolor.distanceTo(vlast_color)

            if dist > TOLERANCE:
                # if color_index - last_color_index > 1 and dist > SHARP_PRECISION:
                #     color_points.append((hou.Vector3(vlast_color), color_index - 1))
                color_points.append((hou.Vector3(vcolor), color_index))
                vlast_color = vcolor
                last_color_index = color_index

        if color_points[-1][1] < (len(self.colors) - 1):
            color_points.append(
                (hou.Vector3(hou.qt.fromQColor(self.colors[-1])[0].rgb()),
                 len(self.colors) - 1))

        # Create a polyline representing ramp and remove inline points with Facet SOP
        points = [color_point[0] for color_point in color_points]
        pos = [color_point[1] for color_point in color_points]

        ramp_geo = hou.Geometry()

        pos_attrib = ramp_geo.addAttrib(hou.attribType.Point,
                                        "ramp_pos",
                                        0.0,
                                        create_local_variable=False)

        ramp_points = ramp_geo.createPoints(points)
        fnum_points = float(len(self.colors) - 1)

        for ptnum, point in enumerate(ramp_points):  # type: (int, hou.Point)
            point.setAttribValue(pos_attrib, float(pos[ptnum]) / fnum_points)

        ramp_poly = ramp_geo.createPolygons((ramp_points, ),
                                            False)[0]  # type: hou.Face

        facet_verb = hou.sopNodeTypeCategory().nodeVerb(
            "facet")  # type: hou.SopVerb

        facet_verb.setParms({"inline": 1, "inlinedist": 0.02})

        facet_verb.execute(ramp_geo, [ramp_geo])

        ramp_poly = ramp_geo.prim(0)
        ramp_points = ramp_poly.points()

        linear = hou.rampBasis.Linear

        basis = []
        keys = []
        values = []

        pos_attrib = ramp_geo.findPointAttrib("ramp_pos")

        for point in ramp_points:  # type: hou.Point
            basis.append(linear)
            keys.append(point.attribValue(pos_attrib))
            values.append(tuple(point.position()))

        if not self.disable_gamma_correction:
            values = [np.power(v, 2.2) for v in values]

        ramp = hou.Ramp(basis, keys, values)
        self.parm.set(ramp)
        self.parm.pressButton()
Beispiel #28
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