If I spend a couple hours baking a smoke simulation and then realize that I want it to happen several frames later in my animation, is there any way to shift what frames it occurs on without having to bake it again?
Locate the cache of the simulation. Per default, this would be in a subdirectory called blendcache_smoke.
Next open up the folder and find the frame index in the filename.
In my case the index is positioned at the -15th to -9th position counted from the end.
43756265_000001_00.bphys
By simply replacing 000001 with 000011 the simulated cache of frame 1 is moved to frame 10.
Several options:
- Replace all the filenames manually.
- Use a third party program to rename files.
- Use a python script.
This script will do what you asked for.
import os
from bpy import path
def OffsetCacheIdx(pPath, offset = 0, idx_position = [-15, -9]):
start, end = idx_position
idx_length = end - start
if (idx_length <= 1):
print("Need a valid index position.")
return
smokedir_path = path.abspath(pPath)
smokecache_files = []
for (dirpath, dirnames, filenames) in os.walk(smokedir_path):
smokecache_files.extend(filenames)
smokecache_files = list(reversed(sorted(smokecache_files)))
smokecache_indices = []
# parse index to int and store in list
for i, sc_f in enumerate(smokecache_files):
name = sc_f[start:end]
smokecache_indices.append(int(name))
if (smokecache_indices[-1] - offset >= 0):
print("Negative frame values, can't do that.")
return
for i, file_name in enumerate(smokecache_files):
smokecache_indices[i] += offset
new_file_name = file_name[:start] + str(smokecache_indices[i]).zfill(idx_length) + file_name[end:]
os.rename(os.path.join(smokedir_path, file_name), os.path.join(smokedir_path, new_file_name))
OffsetCacheIdx("//blendcache_smoke", 10)
The only line you need to change is the last line. The first parameter is the path of the folder containing the cache files, the second parameter is the offset (how many frames you want to shift the simulation).
An optional third parameter can be the position of the index in the filename.
OffsetCacheIdx("//blendcache_smoke", 10, [1, 10])
-
$\begingroup$ Very cool! Thank you. I wouldn't have guessed it would be so complicated. Maybe Blender should add a feature like this. $\endgroup$ – Anson Savage Dec 28 '16 at 16:12
I tweaked the above script to let me shift the cache in negative frames, not sure if this is dangerous or not but just saved me a couple of hours of rebaking :)
I basically commented out the negative frames part and the list reverse statement and added a '-' to the smokecache_indices statement...
import os
from bpy import path
def OffsetCacheIdx(pPath, offset = 0, idx_position = [-13, -9]):
start, end = idx_position
idx_length = end - start
if (idx_length <= 1):
print("Need a valid index position.")
return
smokedir_path = path.abspath(pPath)
smokecache_files = []
for (dirpath, dirnames, filenames) in os.walk(smokedir_path):
smokecache_files.extend(filenames)
#smokecache_files = list(reversed(sorted(smokecache_files)))
smokecache_indices = []
# parse index to int and store in list
for i, sc_f in enumerate(smokecache_files):
name = sc_f[start:end]
smokecache_indices.append(int(name))
print (name)
#if (smokecache_indices[-1] - offset >= 0):
# print("Negative frame values, can't do that.")
# return
for i, file_name in enumerate(smokecache_files):
smokecache_indices[i] += -offset
new_file_name = file_name[:start] + str(smokecache_indices[i]).zfill(idx_length) + file_name[end:]
os.rename(os.path.join(smokedir_path, file_name), os.path.join(smokedir_path, new_file_name))
OffsetCacheIdx("//blendcache_AKV_CABIN", 50)