Skip to content

Instantly share code, notes, and snippets.

@mfairclough
Last active July 18, 2024 23:56
Show Gist options
  • Select an option

  • Save mfairclough/467e5e328912d6b556e2179188ed3ba5 to your computer and use it in GitHub Desktop.

Select an option

Save mfairclough/467e5e328912d6b556e2179188ed3ba5 to your computer and use it in GitHub Desktop.
import os
import os.path
import re
import subprocess
import sys
class TerragenExe:
exe_folder = ''
exe_filename = ''
def __init__(self):
print("os.name:", os.name)
print("sys.platform:", sys.platform)
if (sys.platform == 'win32'):
self.exe_folder = r"C:\Program Files\Planetside Software\Terragen 4"
self.exe_filename = 'tgdcli.exe'
elif (sys.platform == 'darwin'):
# Warning: This script has not been tested on MacOS
self.exe_folder = r"/Applications/Terragen 4/Terragen 4.app/Contents/MacOS"
self.exe_filename = 'Terragen 4'
elif (sys.platform == 'linux'):
# Warning: This script has not been tested on Linux
self.exe_folder = r"PATH_TO_TERRAGEN_FOLDER"
self.exe_filename = 'terragen'
def full_path(self):
return os.path.join(self.exe_folder, self.exe_filename)
def run_with_arguments(self, arguments: tuple, funcname_for_logging, verbose=True):
if verbose:
print("")
print(f"==== {funcname_for_logging}: Starting ====")
print("")
arguments = tuple(self.full_path()) + arguments
child = subprocess.Popen( arguments, executable = self.full_path() )
result = child.wait()
if verbose:
exit_status = ""
if (result == 0):
exit_status = "Finished"
else:
exit_status = "Returned error code " + str(result)
print("")
print(f"==== {funcname_for_logging}: {exit_status} ====")
print("")
return result
def render(tgexe: TerragenExe,
project_filepath: str):
funcname_for_logging = "Render"
arguments = ('-p', project_filepath, '-r', '-exit')
return tgexe.run_with_arguments(arguments, funcname_for_logging)
def render_frame(tgexe: TerragenExe,
project_filepath: str,
frame: int):
funcname_for_logging = f"Render Frame {frame}"
arguments = ('-p', project_filepath, '-f', str(frame))
arguments += ('-r', '-exit')
return tgexe.run_with_arguments(arguments, funcname_for_logging)
def exportvdb_frame(tgexe: TerragenExe,
project_filepath: str,
frame: int,
cloud_node: str,
vdb_filepath: str,
threads = None):
funcname_for_logging = f"Export VDB Frame {frame}"
arguments = ('-p', project_filepath, '-f', str(frame))
arguments += ('-exportvdb', cloud_node, vdb_filepath)
if threads:
arguments += ('-threads', str(threads))
return tgexe.run_with_arguments(arguments, funcname_for_logging)
def replace_frame_number(frame: int, filepath: str):
try:
return filepath % frame # this works if filepath contains '%04d' or '%06d' etc.
except:
# Replace a series of '#' characters with the frame number,
# padding with zeros to match the number of '#' characters.
# e.g. "hello_####.vdb" will produce "hello_0001.vdb" for frame 1.
def pad_number(match):
pattern = match.group(0)
length = len(pattern)
return f"{frame:0{length}d}" # format the number with the same length as the pattern and leading zeros
return re.sub("#+", pad_number, filepath)
def export_vdb_sequence(tgexe: TerragenExe,
project_filepath: str,
first_frame: int,
last_frame: int,
frame_step: int,
cloud_node: str,
vdb_filepath: str):
# You can set the number of threads here, or use 'None' if you want Terragen to decide automatically.
# The VDB exporter might not be efficient with a large number of threads, so use a relatively low number here.
threads = 8
for frame in range(first_frame, last_frame + 1, frame_step):
frame_vdb_filepath = replace_frame_number(frame, vdb_filepath)
exportvdb_frame(tgexe,
project_filepath = project_filepath,
frame = frame,
cloud_node = cloud_node,
vdb_filepath = frame_vdb_filepath,
threads = threads)
if __name__ == "__main__":
tgexe = TerragenExe()
# optional override of Terragen 4 folder
#tgexe.exe_folder = r"C:\Program Files\Planetside Software\Terragen 4"
export_vdb_sequence(tgexe,
project_filepath = r"",
first_frame = 1,
last_frame = 5,
frame_step = 1,
cloud_node = r"Easy cloud 01",
vdb_filepath = r"./terragen_export_####.vdb")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment