@zipit
That's quite alright. I still have the workaround of manually unsetting the active camera for now, so I don't have a problem waiting for the update. Thanks very much for looking into it.
Posts made by beezle
-
RE: Adding multiple cameras from a single file to the render queue
-
RE: Adding multiple cameras from a single file to the render queue
@zipit Thanks for the update
-
RE: Adding multiple cameras from a single file to the render queue
@zipit Thanks for looking into it!
-
RE: Adding multiple cameras from a single file to the render queue
@zipit
- Yeah, the renders all go through. The "R" column is all green.
- Manually adding the cameras from the original file renders the corrects cameras. So does adding the cameras from the documents your script created. But interestingly, when I opened those files, and found the right cameras selected in each one, I added them to the render queue, and it queued up the wrong camera. It wasn't until I changed the active camera to a different one, and then reselected the correct camera that it queued up the right camera when I manually added it with the Render Queue's "Add Current Project" button.
- I haven't installed any plugins in this iteration of c4d.
-
RE: Adding multiple cameras from a single file to the render queue
@zipit
- It's not failing, so there are no error messages.
- It adds one render item for every camera in the scene, but the cameras in these render items, instead of each being a different camera, are all set to whatever camera was the active camera before I ran the script.
- I'm not sure what you mean by this, but other than the issues I've mentioned, I haven't noticed any other issues.
- Yes. So each file is being saved with the proper camera selected, but it's not being queued that way for some reason.
- No
- Yes
- Yes
The scene I'm using is the example scene you sent me. The ONLY difference between whether or not the script works is if I have an active camera set before I run the script. I've even added this line of code at the beginning of your script to try to foolproof it, but it doesn't seem to work.
docs.GetActiveDocument().GetActiveBaseDraw().SetSceneCamera(None)
It seems it's behaving more stable now, and the script consistently works correctly if I make sure to unset the active camera manually before running the script, but obviously if we can get the script to work without that manual condition, all the better. I understand that it makes no sense on your end that the script working would hinge on this, but I can't think of any other difference between the times the script works and when it doesn't.
Are you not able to recreate this same issue on your end with your script and your document? Could it be a version issue? I'm on Windows 10, currently testing R23.110 build RB330286.
-
RE: Adding multiple cameras from a single file to the render queue
@zipit Yeah, you're right. It's flaking out on me again. I'll keep messing with it. Thanks.
-
RE: Adding multiple cameras from a single file to the render queue
@zipit said in Adding multiple cameras from a single file to the render queue:
"""Demonstrates how to create batch render jobs for multiple cameras in a scene file as discussed in: https://developers.maxon.net/forum/topic/13059 Note: * This script is designed for Cinema's native camera objects, to include other camera types, either modify CAMERA_TYPES or adopt get_scene_cameras to accommodate render engines which use tags to mark "their" camera types. * This script has been written for R23, i.e., relies on Python 3 syntax. * This is not by any means production ready code, but rather a code example. The script for example does not handle preventing overwriting existing files, some proper batch render status feedback, etc. """ import c4d import os import time # The node types which we consider to be a camera. CAMERA_TYPES = (c4d.Ocamera,) def get_scene_cameras(doc): """Returns all relevant camera objects in the passed document. Args: doc (c4d.documents.BaseDocument): The document to get the camera objects for. Returns: list[c4d.BaseObject]: The retrieved camera objects. Can be an empty list. Raises: RuntimeError: When the document does not contain any objects. """ def get_next(op): """Returns the "next" node in a graph in a depth-first traversal. Args: op (c4d.GeListNode): The node from which to traverse. stop_node (c4d.GeListNode): A node not to exceed in the horizontal hierarchical traversal. Returns: c4d.GeListNode or None: A child or grandchild of op. Or `None` when the graph has been exhausted. """ if op is None: return None elif op.GetDown(): return op.GetDown() while op.GetUp() and not op.GetNext(): op = op.GetUp() return op.GetNext() # Get the first object and raise if there is none. node = doc.GetFirstObject() if not isinstance(node, c4d.BaseObject): raise RuntimeError("Could not find any objects.") # Return all nodes which are of type CAMERA_TYPES result = [] while node: if node.GetType() in CAMERA_TYPES: result.append(node) node = get_next(node) return result def save_camera_variations(doc, cameras): """Saves a variant of `doc` for each camera in `cameras`. Args: doc (c4d.documents.BaseDocument): The document to save the variations for. cameras (list[c4d.BaseObject]): The list of nodes in `doc` to use as cameras. Returns: list[str]: The file paths of the generated variations. Raises: IOError: When a file could not be written. RuntimeError: When `doc` has no file path, i.e. is an unsaved file. """ # Raise when the master document has not been saved yet. if doc.GetDocumentPath() in (None, ""): raise RuntimeError("Cannot be run on unsaved documents.") # The render BaseDraw, the initial render camera and render data. bd = doc.GetRenderBaseDraw() initial_camera = bd.GetSceneCamera(doc) rd = doc.GetActiveRenderData() # The render path and the document name. render_path = rd[c4d.RDATA_PATH] render_path, render_ext = os.path.splitext(render_path) document_name = os.path.splitext(doc.GetDocumentName())[0] # Go over all cameras and store a document for each of them. document_paths = [] cameras = sorted(cameras, key=lambda cam: cam.GetName()) SaveDocument = c4d.documents.SaveDocument for i, camera in enumerate(cameras): # Set the next camera as the render camera and modify the render data # to set a new render path. bd.SetSceneCamera(camera) rd[c4d.RDATA_PATH] = f"{render_path}_{i}{render_ext}" print (rd[c4d.RDATA_PATH]) doc.SetActiveRenderData(rd) c4d.EventAdd() # Save the file and store the save path. path = os.path.join(doc.GetDocumentPath(), f"{document_name}_{i}.c4d") result = SaveDocument(doc=doc, name=path, saveflags=c4d.SAVEDOCUMENTFLAGS_NONE, format=c4d.FORMAT_C4DEXPORT) if result is False: raise IOError(f"Could not write file to: {path}") print (f"Saved camera variation to: {path}") document_paths.append(path) # Set the render path of the document back to its initial value and set # the camera back. rd[c4d.RDATA_PATH] = f"{render_path}{render_ext}" doc.SetActiveRenderData(rd) bd.SetSceneCamera(initial_camera) c4d.EventAdd() return document_paths def run_batch_jobs(paths): """Runs a batch renderer job with the `paths` generated by the rest of the script. Args: paths (list[str]): The file paths for the Cinema 4D documents to render. Raises: IOError: When a file path in `paths` is not accessible. """ batch = c4d.documents.GetBatchRender() # Populate the batch renderer. for i, path in enumerate(paths): if not os.path.exists(path): raise IOError(f"Could not access path: {path}") batch.AddFile(path, i) print (f"Added job for: {path}.") # Run the renders. batch.SetRendering(c4d.BR_START) def main(): """Entry point. """ # Get all cameras. cameras = get_scene_cameras(doc) # Generate new documents for each camera. paths = save_camera_variations(doc, cameras) # Render these new documents. run_batch_jobs(paths) if __name__ == "__main__": main()
Oh my god, I figured it out. Both of our scripts were working sporadically, but it wasn't a script issue. Neither was my file, since it now works on my file as well. Apparently, if I have an active camera set before I run the script, instead of updating the active camera each iteration, it makes copies of the camera that was active before the script was run. If I create a new camera, set it to be the active camera, and then delete it before running the script (or in script, set the active camera to None), both our scripts work. Holy crap this was driving me crazy.
-
RE: Adding multiple cameras from a single file to the render queue
@zipit Damn. I'm testing your script against your file and mine, and when I bring your cameras into my file, I get the repeated camera behavior bug again. There's some difference between the files that's causing the incorrect behavior. My file has a lot of large assets in it - could it be a memory issue? I can send the files to the address you specified. I'm having someone email that address with an NDA. Thanks!
-
RE: Adding multiple cameras from a single file to the render queue
@zipit
A couple issues:
This works on your file, but not on my own files. On my files, It simply repeats the same camera for as many cameras are in the project, which is the behavior I was getting with my script. Unfortunately, I'm new to C4D - is there something unique about how you've set up these cameras that allow the script to work?The other issue is I see that the way it works is to create a new file for every camera in the original file. We could have hundreds of cameras per file, and we have lots of these files. Creating a new file for every camera isn't really sustainable for us. Is there another way to do this?
-
Adding multiple cameras from a single file to the render queue
Hey guys, I'm back on R&D, and while I've posted this question before, I've tried some things and have some new questions.
Basically, where I left off was, I'm trying to add all selected cameras to the render queue at once. I can add as many cameras as I have selected to the render queue, but they're all the same camera - whatever camera was set as the scene camera before the script was run. There are no object properties for then changing the Camera, which we can do manually with each render item via dropdown.
I've tried a couple things to work around this. First was to loop through all the cameras, and on each iteration, set the current camera I'm adding as the active camera, save, and add the file to the render queue. Then close and reload the file, and continue doing that until I've iterated through all the selected cameras. Unfortunately, no matter what I do (even after adding a time.sleep command to give c4d time to load the file completely before trying to set the camera), it seems c4d ignores all the commands to set the active camera until the very end, after the rest of the script has run. I imagine an event trigger might be a good way to trick the compiler into executing the queued "set active camera" command, but I'm not seeing any events for when a file loads.
The only other thing I could think of to do was to use pyautogui to automate keyboard commands to traverse the render queue via the gui and change the camera dropdowns "manually". Unfortunately, unless I'm missing something, it seems like pyautogui commands don't work in c4d.
Does anyone have any suggestions? Because I'm at wit's end trying to automate this frankly basic functionality, which should've been included with the software, let alone it being impossible to automate via python.
-
RE: Changing camera/take/render setting in the render queue
@m_adam Thanks. I gave that a shot, but unfortunately, it's still adding multiple copies of the same camera. Am I doing something wrong?
docs = c4d.documents doc = docs.GetActiveDocument() cams = getSelectedCameras(doc.GetActiveObjects(0)) path = doc.GetDocumentPath() cFile = path + '\\' + fName queue = docs.GetBatchRender() queue.Open() base = doc.GetActiveBaseDraw() for cam in cams: docs.LoadDocument(cFile, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS) base.SetSceneCamera(cam) docs.SaveDocument(doc, cFile, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, c4d.FORMAT_C4DEXPORT) queue.AddFile(cFile, queue.GetElementCount())
-
Changing camera/take/render setting in the render queue
Hey guys,
I'm trying to write a script for batch rendering. I've seen a few scripts floating around that do this, but these are for adding a separate file for every render.
Our pipeline is a bit different. We have many cameras in a single environment c4d file, each of which we need a single PSD octane render for. I can queue up the renders from the file using AddFile just fine, but they all populate with the same settings, rendering the same camera. I don't know how to access that new item in the queue so I can then change everything with the script that I can do manually through the dropdowns: the Camera most importantly, but also the Take and Render Settings if need be.
Is there any way to do this?
Thanks.