I baked a very heavy simulation that toke like 1 and an half hour, but I forgot that simulation had to start from frame 100 because, before starting, there should be some camera movements, but I forgot it and now simulation starts from frame 0 and I haven't time. Should I bake it again from frame 100 or is there a way I can start the animation from frame -100?
-
Does this answer your question? Selecting Negetive frames in timeline – Markus von Broady Jun 02 '21 at 12:31
-
It does something similar, but I mean rendering from frame -100, not executing physics from -100 – Arisyn ILY Jun 02 '21 at 12:34
-
Sorry, I thought you actually could render from negative frame, but you only can preview from negative frames by clicking the clock button left to the start frame field. What you can do is render a still image, so you actually could write a Python script to render negative frames – Markus von Broady Jun 02 '21 at 12:45
-
1@MarkusvonBroady I think there is an option somewhere to allow negative frames, but meanwhile, why not try and move the cache forward instead? I’m pretty sure there is a way to do that. – TheLabCat Jun 02 '21 at 12:52
-
@ZargulTheWizard according to this, you can't render multiple negative frames at once, using Blender's vanilla interface: https://developer.blender.org/T42151 – Markus von Broady Jun 02 '21 at 13:02
-
@MarkusvonBroady You are right. Oh well. – TheLabCat Jun 02 '21 at 13:04
-
What kind of simulation is it? Rigid body, Particles, Fluid? – Gordon Brinkmann Jun 02 '21 at 14:36
-
It's a soft body simulation – Arisyn ILY Jun 03 '21 at 13:04
-
Anyway, I fixed rendering 2 different scenes, one that starts from 0 and the other one with no physics – Arisyn ILY Jun 03 '21 at 13:04
1 Answers
Update: the previous version actually didn't work (because I forgot the most important part, frame_set()), sorry for any confusions caused.
Enable negative frames in your project: Selecting Negative frames in timeline, then click on the stopwatch ⏱ icon to be able to preview those frames in viewport:
, then add necessary animations and use the script below.
import bpy
start = bpy.context.scene.frame_preview_start # or just input the starting frame manually here
end = -1 # or maybe you want bpy.context.scene.frame_end or frame_preview_end
renders_path = "/tmp/"
filename = "{}.png"
negative_char = "_" # minus sign sorts poorly together with positive numbers
class Negative_Render(bpy.types.Operator):
"""Render negative frames without hanging the interface
adapted code from https://blender.stackexchange.com/q/71454/60486 """
bl_idname = "render.negative"
bl_label = "Render negative frames"
# Define some variables to register
_timer = None
current_frame = start
last_frame = end
stop = None
rendering = None
# Define the handler functions. I use pre and post to know if Blender "is rendering"
def pre(self, scene, context=None):
self.rendering = True
def post(self, scene, context=None):
self.current_frame += 1
self.rendering = False
def cancelled(self, scene, context=None):
self.stop = True
def add_handlers(self, context):
bpy.app.handlers.render_pre.append(self.pre)
bpy.app.handlers.render_post.append(self.post)
bpy.app.handlers.render_cancel.append(self.cancelled)
# The timer gets created and the modal handler is added to the window manager
self._timer = context.window_manager.event_timer_add(0.1, window=context.window)
context.window_manager.modal_handler_add(self)
def remove_handlers(self, context):
bpy.app.handlers.render_pre.remove(self.pre)
bpy.app.handlers.render_post.remove(self.post)
bpy.app.handlers.render_cancel.remove(self.cancelled)
context.window_manager.event_timer_remove(self._timer)
def execute(self, context):
# Define the variables during execution. This allows
# to define when called from a button
self.stop = False
self.rendering = False
self.add_handlers(context)
return {"RUNNING_MODAL"}
def modal(self, context, event):
if event.type == 'TIMER': # This event is signaled every 100 ms
# and will start the render if available
if self.stop:
# Cancelled:
self.remove_handlers(context)
return {"CANCELLED"}
if self.current_frame > end:
# Finished:
self.remove_handlers(context)
return {"FINISHED"}
if self.rendering is False: # Nothing is currently rendering.
# Proceed to render.
sc = context.scene
name = negative_char if self.current_frame < 0 else ""
name += f"{abs(self.current_frame):03d}"
sc.render.filepath = renders_path + filename.format(name)
sc.frame_set(self.current_frame)
bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)
return {"PASS_THROUGH"}
# This is very important! If we used "RUNNING_MODAL", this new modal function
# would prevent the use of the X button to cancel rendering, because this
# button is managed by the modal function of the render operator,
# not this new operator!
def register():
bpy.utils.register_class(Negative_Render)
def unregister():
bpy.utils.unregister_class(Negative_Render)
if name == "main":
register()
bpy.ops.render.negative() # Test call
I adapted the script from:
- 36,563
- 3
- 30
- 99