Jump to content
Kalina

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?

Share this post


Link to post
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.

Share this post


Link to post
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	# }")

 

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×