Read how much primitives are in a solaris node.

   2392   8   1
User Avatar
Member
24 posts
Joined: Nov. 2019
Offline
Hi! I am trying to cound how much primitives are in a node, as a way to detect if the variant I am looking for exist, but I don't know how to read this, I have a switch with the high lod and the low lod, and I want to detect when the 2nd node doesn't have low variant.

I achieved some progress by using the explore variants in a way that if there is now low variant it will show empty.

I don't know if it's there other way to do this cleaner, but this is what I have right now!


Thanks for reading me!
Final Layout.
Skydance, Madrid.
https://twitter.com/RodrigoMartinKJ [twitter.com]
User Avatar
Member
874 posts
Joined: Oct. 2008
Offline
In a Python Lop, does this get you what you want?

node = hou.pwd()
stage = node.editableStage()

# Add code to modify the stage.
# Use drop down menu to select examples.


yournode =  hou.node('/stage/null5').stage().GetPrimAtPath('/arcsmoke')

def count_prims(node):
    count = 0
    for child in node.GetChildren():
        count += 1
        count += count_prims(child)
    return count
    
prim_count = count_prims(yournode)
print("The node has", prim_count, "prims.")
--
Jobless
User Avatar
Member
24 posts
Joined: Nov. 2019
Offline
Soothsayer
In a Python Lop, does this get you what you want?

node = hou.pwd()
stage = node.editableStage()

# Add code to modify the stage.
# Use drop down menu to select examples.


yournode =  hou.node('/stage/null5').stage().GetPrimAtPath('/arcsmoke')

def count_prims(node):
    count = 0
    for child in node.GetChildren():
        count += 1
        count += count_prims(child)
    return count
    
prim_count = count_prims(yournode)
print("The node has", prim_count, "prims.")
Hi!

Yes it works, but there is a thing that I don't understand, in the viewport, having just 1 asset with 1 variation write "1 primitive" but the code reads 78, I understand that the node is reading all the primitives in the layer, so "object/geo_grp/body_grp/geometry" count as 5 primitives, one for each level. (I don't know exactly how to explain it in text but I understand the concept)

I imagine that running on this loop a filter with the name or the type of primitive will give the correct result I am looking, but I can't find the documentation for the functions you used, searching on the houdini documentatio for example stage().GetPrimAtPath() don't give a clear result.

Is there an external documentation or any list of functions I can look at for this? I think I am missing something and that all of this would be easier with that (if there is somewhere)

Thank you for the previous script too, I am one step closer to make all work!
Final Layout.
Skydance, Madrid.
https://twitter.com/RodrigoMartinKJ [twitter.com]
User Avatar
Member
874 posts
Joined: Oct. 2008
Offline
There are docs but I'm afraid it's not necessarily easier:

https://openusd.org/release/api/class_usd_stage.html#a6ceb556070804b712c01a7968f925735 [openusd.org]

Somebody correct me if I'm wrong but as far as I can work out it's a c++ api and the python bindings are generated from this, meaning that you can adapt them 'in a simple and straightforward way'.

Now, you could try this in python to see what's in the pxr usd module and then dig around in the docs for it.

from pxr import Usd
print(dir(Usd))

or if you are feeling more adventerous:

node = hou.pwd()
stage = node.editableStage()


def list_module_contents(module, prefix="", visited=None):
    contents = []

    # Initialize the visited set if it's not provided
    if visited is None:
        visited = set()

    # Prevent infinite recursion by checking if the module was already visited
    if id(module) in visited:
        return contents

    visited.add(id(module))

    for name in dir(module):
        # Check if the attribute is readable
        if not hasattr(module, name):
            continue

        attr = getattr(module, name)
        full_name = f"{prefix}{name}"

        if isinstance(attr, type):
            # If the attribute is a class, recursively list its contents
            contents.extend(list_module_contents(attr, f"{full_name}.", visited))
        else:
            contents.append(full_name)

    return contents




from pxr import Usd

# List everything in the Usd module recursively
contents = [i for i in list_module_contents(Usd) if '__' not in i]

print(contents)


There are also examples here: https://openusd.org/release/tut_traversing_stage.html [openusd.org]
--
Jobless
User Avatar
Member
24 posts
Joined: Nov. 2019
Offline
Soothsayer
There are docs but I'm afraid it's not necessarily easier:

https://openusd.org/release/api/class_usd_stage.html#a6ceb556070804b712c01a7968f925735 [openusd.org]

Somebody correct me if I'm wrong but as far as I can work out it's a c++ api and the python bindings are generated from this, meaning that you can adapt them 'in a simple and straightforward way'.

Now, you could try this in python to see what's in the pxr usd module and then dig around in the docs for it.

from pxr import Usd
print(dir(Usd))

or if you are feeling more adventerous:

node = hou.pwd()
stage = node.editableStage()


def list_module_contents(module, prefix="", visited=None):
    contents = []

    # Initialize the visited set if it's not provided
    if visited is None:
        visited = set()

    # Prevent infinite recursion by checking if the module was already visited
    if id(module) in visited:
        return contents

    visited.add(id(module))

    for name in dir(module):
        # Check if the attribute is readable
        if not hasattr(module, name):
            continue

        attr = getattr(module, name)
        full_name = f"{prefix}{name}"

        if isinstance(attr, type):
            # If the attribute is a class, recursively list its contents
            contents.extend(list_module_contents(attr, f"{full_name}.", visited))
        else:
            contents.append(full_name)

    return contents




from pxr import Usd

# List everything in the Usd module recursively
contents = [i for i in list_module_contents(Usd) if '__' not in i]

print(contents)


There are also examples here: https://openusd.org/release/tut_traversing_stage.html [openusd.org]

Wow, I think this weekend I will have some fun diving into this, I'm sure I will hit some walls in the path but progress is progress at the end!

Thank you so much! This is great!
Final Layout.
Skydance, Madrid.
https://twitter.com/RodrigoMartinKJ [twitter.com]
User Avatar
Member
874 posts
Joined: Oct. 2008
Offline
It's not complete but here are some ideas to filter it:

node = hou.pwd()
stage = node.editableStage()
from pxr import Usd
# Add code to modify the stage.
# Use drop down menu to select examples.

xs = [x for x in stage.Traverse()]
y = xs[0]
for prim in xs:
    children = [c for c in prim.GetAllChildren()]
    models = [m for m in children if m.IsModel()]
    if prim.IsLoaded():
        print(prim, prim.GetTypeName(), models)


#print(dir(y))

Unquote that last line and you can see what you can access on a prim, then use the docs to get some better ideas of what arguments, if any, it wants.
Edited by Soothsayer - May 5, 2023 08:25:36
--
Jobless
User Avatar
Member
874 posts
Joined: Oct. 2008
Offline
How about this? (You need to make a parm called nodepath and drag your node into it)

from pxr import Usd

node = hou.pwd()
stage = node.editableStage()


user_node_path = hou.parm('nodepath').eval()
user_node = stage.GetPrimAtPath(user_node_path)

child_counts = {}

for child in user_node.GetChildren():
    child_type = child.GetTypeName()

    if child_type in child_counts:
        child_counts[child_type] += 1
    else:
        child_counts[child_type] = 1


print(f"USD Prims child count by type for node: {user_node_path}")
for child_type, count in child_counts.items():
    print(f"  {child_type}: {count}")
print("=============================")
Edited by Soothsayer - May 5, 2023 10:45:32
--
Jobless
User Avatar
Member
130 posts
Joined: June 2019
Offline
You probably can use prim stats from LopNode:

hou.node("/stage/your_node").stagePrimStats()["Mesh:Total"]

# or even this one to get polygon count

hou.node("/stage/your_node").stagePrimStats(do_geometry_counts=True)["Mesh (Polygons):Total"]

For more complicated stuff houdini has its own pretty robust solution for stage traversal and prim queries: https://www.sidefx.com/docs/houdini/solaris/pattern.html [www.sidefx.com]

It's usable in python via hou.LopSelectionRule
User Avatar
Staff
43 posts
Joined: March 2022
Offline
Some advice I got from goldleaf a while ago has served me well:

Okay so I've found the best way to learn Python and USD is the unit tests on GitHub. For example, here are some tests for Primvars, and Materials:

https://github.com/PixarAnimationStudios/USD/blob/3abc46452b1271df7650e9948fef9f0ce602e3b2/pxr/usd/usdGeom/testenv/testUsdGeomPrimvar.py#L512 [github.com]

https://github.com/PixarAnimationStudios/USD/blob/v22.11/pxr/usd/usdShade/testenv/testUsdShadeBinding.py [github.com]

I like to search for things on Github, and filter for the Python language; most of the time points me to a unit test in Python that shows how to do something.
  • Quick Links