Jump to content

How to create and render one IFD with multiple cameras?


Recommended Posts

I am using an IFD workflow, and I want to render an identical scene from 3+ different camera positions. I've come across several different ways of rendering these 3+ images sequentially, but that's not exactly what I want. I would like to make 1 IFD file that renders 3+ images from different camera positions. Is there a way to do that?

I am working with a large dataset. For easy math, let's say that it takes 10 minutes to read/load, and then 10 minutes to render. Rather than doing three sets of load+render + load+render + load+render (60 minutes), I'd like to be able to do load+render+render+render (40 minutes).

I have found that I can use the "Stereo Cam Template" (even though I am not rendering in stereo) to work with two of these cameras to do load+render+render in one IFD file. But how can I do this with more cameras?

Link to comment
Share on other sites

I don't think there's an easy way to swap cameras in an IFD by name... you'd have to edit the camera properties individually, which would get really tedious. The best way I'm aware of to solve your problem is to cache the geometry you want to render as .bgeo and then load it back in via a File SOP as a Packed Disk Primitive. This means you'll still have to generate IFDs, but they'll store just a link to your geometry on disk rather than embedding it in the generated files.

Link to comment
Share on other sites

Thanks for the reply. I guess I wasn't clear enough in my original post - I do want to keep generating IFDs, that is not the problem. I want to change what is written to these IFDs. And, I am already using Packed Disk Primitives.

I came up with a hacky solution, still hoping there's a better one. Here it is in case anyone else finds it useful:

1. Write out all the IFDs separately from 3+ out nodes, where each out node is identical, except for a different camera.

2. Use the script below to go through and merge the 3+ IFDs for each frame into one new IFD for each frame.

3. Render these newly-created IFDs rather than the ones created by Houdini.

 

"""
Usage:

python mergeIfds.py -frames 1-100%2 -baseNames multitest1,multitest2
"""


import sys
import os

frameRange = [1001,1001,1]
baseNames = ["multitest1", "multitest2"]
basePath = "/fb1/bope/earthscall/ifd/" #Assumes all the IFDs are in this directory, e.g. /fb1/bope/earthscall/ifd/multitest1/multitest1.0001.ifd etc

# Get (optional) command line parameters
ii = 1
while len(sys.argv) > ii+1 and sys.argv[ii][0] == "-":
    a = sys.argv[ii]
    b = sys.argv[ii+1]
    if a == "-frames":
        inp = b.split('%')
        if len(inp) > 1:
            frameRange[2] = int(inp[1])
        if "-" not in inp[0]:
            frameRange[0] = int(inp[0])
            frameRange[1] = int(frameRange[0])
        else:
            r = inp[0].split('-')
            frameRange[0] = int(r[0])
            frameRange[1] = int(r[1])
        ii += 2
    elif a == "-base":
        inp = b.split(',')
        baseNames = []
        for baseName in inp:
            baseNames.append(baseName)
        ii += 2
    else:
        print "ERROR: Unknown option " + a
        sys.exit()

# Make new directory for the new IFDs if it doesn't exist
newBaseName = baseNames[0] + "_combo"
if not os.path.exists(basePath + newBaseName):
    os.makedirs(basePath + newBaseName)

# Go through all the frames in the specified frame range
for i in range(frameRange[0], frameRange[1]+1, frameRange[2]):
    
    padNum = str(i).zfill(4)

    with open(basePath + newBaseName + "/" + newBaseName + "." + padNum + ".ifd", "w") as outF:

        # Copy entire first file over, except for the last line
        with open(basePath + baseNames[0] + "/" + baseNames[0] + "." + padNum + ".ifd", "r") as inF:
            for line in inF:
                if not "ray_quit" in line: # this is the last line
                    outF.write(line)

        # Write a new last line
        outF.write("ray_reset  -l -o -f	# }")

        # Loop through the rest of the basePaths
        for j in range(1, len(baseNames)):
            baseName = baseNames[j]

            isLast = False
            if j == len(baseNames)-1:
                isLast = True
        
            # Copy the relevant sections
            copy = False
            with open(basePath + baseName + "/" + baseName + "." + padNum + ".ifd", "r") as inF:
                print basePath + baseName + "/" + baseName + "." + padNum + ".ifd"
                for line in inF:
                    if "Main image from" in line:
                        copy = True
                    if copy:
                        if (not "ray_quit" in line) or (isLast):
                            outF.write(line)

            # Write a new last line if this isn't the last IFD
            if not isLast:
                outF.write("ray_reset  -l -o -f	# }")

 

Link to comment
Share on other sites

Ah, right, I get it now. You could try adding the "vm_cameralist" render property to one of your cameras considered the "master" camera, that would contain the names of all the renderable cameras you want? Then tell your Mantra ROP to render from that "master" camera. That's what the Stereo camera is doing internally.

Link to comment
Share on other sites

  • 5 months later...

I have a question you may be able to answer for me.

I have created ifd's - I now want to change my camera - do i have to recache everything - this is a problem because of the time needed.

-- I have not been able to get the "packed primative" workflow working - I am working from home in a team of 1 and so do not have anyone beside me to ask and my ifd's have cached all my cached geometry and so are large --

Can you help me with my pain ... PS I am a button pusher more than a script runner ... I am hoping that will change 

C

Link to comment
Share on other sites

I don't know if there's a simple way to swap cameras in an IFD that's already saved out... the IFD is going to bake in the camera's parameters and transforms.

The packed workflow for making small IFDs is pretty straightforward... just cache your renderable objects to .bgeo or .bgeo.sc, then load those files back in using the File SOP set to load as "Packed Disk Primitives." That's all there is to it... if the renderable objects are simply packed disk primitives, Mantra will link to those primitives on disk rather than embedding the geometry into the IFDs.

SideFX IFD docs

Link to comment
Share on other sites

Ditto to what toadstorm said, using packed disk primitives is not much work and it's a game changer. Do it do it do it and it will save you a lot of time and headache. Then writing out the IFDs is much faster and the files are much smaller... So it's less of a commitment to re-run them with a new camera.

Otherwise though, depending on how you write them out, IFDs are either plain text or have a text component. You could write a script that parses the text in the files and swaps out camera positions. Not an ideal solution (especially if you're not comfortable with scripting), but it should work.

Link to comment
Share on other sites

4 hours ago, toadstorm said:

I don't know if there's a simple way to swap cameras in an IFD that's already saved out... the IFD is going to bake in the camera's parameters and transforms.

You can use Python filtering to change some of mantra properties inside IFD file: 

https://www.sidefx.com/docs/houdini/render/python.html

basically:

mantra -f my-scene.ifd -P changing-some-params.py

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...