# Requirements

Heads up!

Please read the section about USD Clips (opens new window) to understand better the context of this tip. Then carry on reading below.

Because the clip manifest and topology files are generated by the USD libraries through an "in memory" process at runtime, it is possible for the USD library to go "out of memory" when generating the clip if your sequence data is very large and/or you are generating a clip for many frames.

Until this is not improved in USD itself we provide you with some workarounds, both in Multiverse for Maya and in Houdini.

# Writing USD clips in Multiverse for Maya (without going out of memory)

In Multiverse you can simply perform a Multiverse Read operation (via the shelf button), browse to the folder with your sequence of usd or alembic files, and use the UI to generate a short clip using very few frames (such as 10, note we are using a super simple scene just for illustrative purpose):

Then just open in your favorite text editor the and main clip and the topology .usda files (no edit required in the manifest file) that were generated by Multiverse and manually edit the timecodes upping them to 100, specifically:

  • open the main clip file and edit the endTimeCode, startTimeCode, templateEndTime and templateStartTime, e.g:

    #usda 1.0
    (
        endTimeCode = 100                                          <<<<<<
        startTimeCode = 1                                          <<<<<<
        subLayers = [
            @./fractureSequence.topology.usda@
        ]
    )
    over "pighead" (
        clips = {
            dictionary default = {
                bool interpolateMissingClipValues = 1
                asset manifestAssetPath = @./fractureSequence.manifest.usda@
                string primPath = "/pighead"
                string templateAssetPath = "fracture.####.usd"
                double templateEndTime = 100                       <<<<<<
                double templateStartTime = 1                       <<<<<<
                double templateStride = 1
            }
        }
    )
    {
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
  • open the topology file and edit the endTimeCode and startTimeCode, e.g:

    #usda 1.0
    (
        defaultPrim = "pighead"
        endTimeCode = 100                                          <<<<<<
        framesPerSecond = 24
        metersPerUnit = 1
        startTimeCode = 1                                          <<<<<<
        timeCodesPerSecond = 24
        upAxis = "Y"
    )
    
    def Xform "pighead" (
        kind = "component"
    )
    {
        def Xform "fracture"
        {
            def Mesh "fracture_Shape"
            {
                float3[] extent
                int[] faceVertexCounts
                int[] faceVertexIndices
                normal3f[] normals (
                    interpolation = "faceVarying"
                )
                uniform token orientation = "leftHanded"
                point3f[] points (
                    interpolation = "vertex"
                )
                uniform token subdivisionScheme = "none"
                vector3f[] velocities (
                    interpolation = "vertex"
                )
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

This will always produce perfect clip files with correct topology information and handling cases where there is no geometry in pre-rolls.

# Writing USD clips from Houdini (without going out of memory)

This is a trick to write your USD clip "manually" in Houdini via a Python SOP node in the Houdini Geometry context. We suggested this to one of our client who was kind enough to share their take at it in Houdini. Thank you dear Norwegian friends 😉

Note that, unlike with Multiverse, this method does not produce the manifest and topology files and will not work if the first frame of your clip does not contain any geometry, and it is therefore inferior to using Multiverse in Maya as in the previous section, but still it can be useful, so here we go, we are basically manually writing the clip file via Python, and no USD library is being called, preventing to go out of memory:

As you can see at the bottom of the Python SOP we are writing the clip file line by line, so no USD library will be called 😃

import os

node = hou.node("./")
usd_node = hou.node("../cache_USD")

# gather clip parms
folder = usd_node.parm('lopoutput').eval().rsplit('/', 1)[0]
end_frame = str(int(usd_node.parm('f2').eval()))
start_frame = str(int(usd_node.parm('f1').eval()))
default_prim = usd_node.parm('defaultprim').eval()

usd_file = usd_node.parm('lopoutput').eval().rsplit('/', 1)[1].rsplit('.', 1)[0].rsplit('.', 1)[0]
topology = usd_file + '.' + start_frame.zfill(4) + '.usd'

active = []
times = []
asset = []
frames = int(end_frame) - int(start_frame) + 1

for i in range(0, frames):
    frame = i + int(start_frame)
    num = i
    active.append("(" + str(frame) + ", " + str(num) + ")")
    times.append("(" + str(frame) + ", " + str(frame) + ")")
    asset.append("@" + usd_file + "." + str(frame).zfill(4) + ".usd@")

clipFile = folder + '/' + usd_file + '_clip.usda'

# check if folder exists
if not os.path.exists(folder):
    os.makedirs(folder)

    
# premade usda formatting to get clip to work
#
# the downside with this is that there has to exist some geom at first frame so
# there is something to attach the default prim to.
f = open(clipFile, "w+")

f.write("#usda 1.0\n(\n    endTimeCode = " + end_frame + "\n")
f.write("    startTimeCode = " + start_frame + "\n")
f.write("    subLayers = [\n        @./" + topology + "@\n    ]\n)\n\n")
f.write("over " '"' + default_prim.replace('/', '') + '" (\n    clips = {\n        dictionary ' + usd_file + " = {\n")
f.write("            double2[] active = [" + ', '.join(active) + "]\n")
f.write("            asset[] assetPaths = [" + ', '.join(asset) + "]\n")
f.write("            asset manifestAssetPath = @./" + topology + "@\n")
f.write("            string primPath = " + '"' + default_prim + '"\n')
f.write("            double2[] times = [" + ', '.join(times) + "]\n")
f.write("        }\n    }\n)\n{\n}")

f.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Last Updated: 6/30/2022, 3:38:14 PM