Bpy Programmatically Bake Oceans

Hi,

I would like to use a python script to bake out a very large number of Ocean Surface displacement maps for use in another program. I thought it would be fairly easy to simply loop over a function that pulls in some preset values and calls the function bpy.ops.object.ocean_bake(modifier="Ocean"), but I am getting some very inconsistent results. The below example assumes a plane with the Ocean modifier is already selected:

import bpy
import os
from pathlib import Path


def bake_ocean(ii):

    bpy.context.object.modifiers["Ocean"].wind_velocity = 6
    bpy.context.object.modifiers["Ocean"].foam_coverage = 0.01
    bpy.context.object.modifiers["Ocean"].frame_end = 1

    bakepath = Path("path_to_file_Test{}".format(ii))    
    bakepath.mkdir(parents=True, exist_ok=True)
    
    bpy.context.object.modifiers["Ocean"].filepath = str(bakepath)
    bpy.context.object.modifiers["Ocean"].spectrum = "PIERSON_MOSKOWITZ"
    bpy.context.object.modifiers["Ocean"].use_foam = False
    
    
    bpy.ops.object.ocean_bake(modifier="Ocean")


for ii in range(0, 4):
    bake_ocean(ii)

When I run this bit of code, I will get four sub-folders numbered 0 - 3. Of these, usually only the first and last folder will have any output. I have toyed around with timers and a function that checks whether the displacement map file has been created, but the details of such an implementation are a bit beyond me. Does anyone have a suggestion as to how I could get this to work? A simple workaround would be to repeatedly generate a single surface at a time and call blender in a loop via command line, but it would be neater to do that loop within blender.

Thanks!

Add a loop after ocean_bake that will ensure cache files are created (if it’s an empty folder then just check it until it has n files) and only then proceed to the next folder.

Thanks Andrej,

I tried the following code, and it generates the first displacement map, then hangs indefinitely:

import bpy
import os
from pathlib import Path


def check_disp_exists(path):
    
    disp_file = path / "disp_0001.exr"
    
    if os.path.exists(str(disp_file)):
        print(disp_file)
        return True
    else:
        return False

def bake_ocean(ii):

    bpy.context.object.modifiers["Ocean"].wind_velocity = 6
    bpy.context.object.modifiers["Ocean"].foam_coverage = 0.01
    bpy.context.object.modifiers["Ocean"].frame_end = 1

    bakepath = Path("path_to_file_Test{}".format(ii))    
    bakepath.mkdir(parents=True, exist_ok=True)
    
    bpy.context.object.modifiers["Ocean"].filepath = str(bakepath)
    bpy.context.object.modifiers["Ocean"].spectrum = "PIERSON_MOSKOWITZ"
    bpy.context.object.modifiers["Ocean"].use_foam = False
    
    bpy.ops.object.ocean_bake(modifier="Ocean")
    
    while not check_disp_exists(bakepath):
        continue
    

for ii in range(0, 4):
    bake_ocean(ii)

Can confirm, that’s interesting. It seems there are other people used the similar approach in the past but it doesn’t seem to work any more - https://github.com/search?q=bpy.ops.object.ocean_bake&type=code.

Possibly a bug in Blender API to report?

As a workaround, have you tried setting up a timer using https://docs.blender.org/api/current/bpy.app.timers.html ?
Something like:

  1. Run first loop that actually bakes something
  2. Set up a timer that will check in n secs that files were created
  3. If they’re not set up another timer to check it again
  4. If they are run next iteration

The idea is that then bake won’t be stuck inside 1 Python script and Blender will be able to function between the times timer is triggered and perhaps it will be update something to fix the baking process.