Delay capture using native Rhino animation


(Jakob Normand) #1

Hi All

Wasn’t sure wether to post to Neon or Rhino category, but here goes: Is it possible - using the native Rhino animation tools - to delay the frame capture, so that Neon is able to complete its cycle (by either time or sample count)? From what I can find here on Discourse, it’s a feature in Bongo, but my needs don’t really justify a full blown animation plugin - I’ll just do it manually, stepping one frame ahead, waiting, screen-grabbing, stepping one frame ahead, waiting, screen-grabbing etc. Tedious, but cheap :smile:

TIA, Jakob


Here is a hack for you…
I couldn’t find any ways to read out any animation details so you have to type them in.

Make sure:

  • Save before use! It is a hack, so it can crash and freeze and lose data for you so use at own risk.
  • An animation is set.
  • The animation is set to use Neon.
  • You know how many frames it has
  • The perspective view is current

How to use it:

  • Run the script (load it in the python script editor)
  • Choose folder for frames, it will automatically number them from 00001 and up and will overwrite existing files
  • Set the time to wait for each frame in seconds
  • Set the number of frames to calculate. If lower than what the animation has it will stop at the given frame, if more then it will continue, at least on turntable.
  • Make sure Rhino is the active program and don’t use the computer while it renders
  • Press Escape if you need to terminate. Press and hold if it doesn’t terminate at once.

Good luck.

Neon Rhino Animation render (1.4 KB)

(Jakob Normand) #3

Oh, @Holo, you are the best! Just tested the script, and it works like a charm - takk!!! Every single time I need a tool like this, I regret not being able to script - but I’m SO grateful that you guys here take the time to help out! Thanks again, Jørgen!

Regards, Jakob


Hi @holo-
I’ve been using your script and it normally works just fine (thank you very much!). Sometimes, however, it renders each frame twice… or renders once like normal, then you get the “neon Rendering” popup window that you get when you try to close Rhino while in Neon mode. This doubles rendering time, and weirdly sets an arbitrary size for the saved images which doesn’t seem to relate to the Neon viewport size. Any ideas on how to prevent this?


Hi Cairn,
I have no idea as I don’t use the script due to no need for rendering at the moment :smile:

But does this happen if you only have one Rhino running and don’t touch the machine while it works?


Hi Holo,

I am also only an occasional animator, so no biggie.
Problem goes away by re-starting Rhino…


This script is totally heaven sent. Thank you so much.

Edit: Any way to make it look at sampling level rather than seconds passed?


Hi Holo,
I’ve been making some animated 3d zoetropes and I wondered if you could help…BabelSpin3

So far, I have been manually rotating the geometry and rendering one frame out at a time, but it occurred to me that it is probably possible to modify your neon render script to automate this process…
In other words, your modified script would run as before, but in-between each render it would (for example) select all/rotate by n degrees/deselect all/ then wait n seconds and save/repeat.
I imagine this is probably trivial to someone who knows how to script, but I just don’t seem to have the head for it… any chance you could help a brother out?


Sweet! It is no big deal to modify the script, but this week and next I am flooded with stuff to do, so it has to wait a bit. Could you ask at the end of next week? (I will probably forget by then)
And please describe what you need. Camera rotation around w0,0,0 with fixed Z height and distance based on the view is my assumtion for a good start. Also you probably need the ability to choose how many frames you want.

An other option would be to rotate the object so the lighting stays the same.

Oh, and do you use Rhino5 or Rhino6? (I presume 5 since you mention Neon)


Thanks Holo,
For my purposes, rotating the object and keeping the lighting fixed is working best.
I’ll give you a poke next week…


Hi Holo,
JIC you have get to it before next week, here’s the gig:

Your Neon script, with the added per frame option of selecting all geometry in the scene and rotating around Z-axis by a given angle (if you write something in the script like: [replace this text with rotation angle] I could insert any angle before running the script). It will also be necessary to deselect all geometry before rendering each frame in order to get rid of the selection highlight (I tried the Highlight Toggle hack by Jared
but it seems to break the Neon viewport every time I use it…).
That’s it, all the other options in your script are good as-is (Frame count, wait-time etc…
You can imagine the tedium this will save me… :slight_smile:
Friend for life,


Hi cairn,
I finally have some time to look at this, but I want it to work on V6 as well, so I got a bug to iron out first.

@nathanletwory do you know why Cycles restarts for every frame when I make a script like this:

(This is just an initial dummy to see if stuff works like planned)

When Cycles is running and objects are selected I can manipulate them in realtime with gumball, but the moment a script is doing it then it becomes veeery sluggish. I tried with time.sleep(‘seconds’) too, but that too stops cycles from calculating.

Can I get Rhino to wait and still have cycles calculating like Neon did?

#Rotate object, wait and viewcapture

import rhinoscriptsyntax as rs
import scriptcontext

obj_ids=rs.GetObjects("Select object(s) to rotate while capturing frames")
if obj_ids:
    nr_Frames=rs.GetInteger(message="How many frames for a 360 degree spin?", minimum=1)
    if nr_Frames:
        renderTime=rs.GetReal(message="Render time for each frame?", minimum=0.001)
        if renderTime:
            dupObjects=rs.CopyObjects(obj_ids, (0,0,0))
            for frame in range(nr_Frames):
                if scriptcontext.escape_test(False):
                rs.RotateObjects(dupObjects, center, angle, axis=(0,0,1), copy=False)


I got it, had to use a while True loop and check for time instead.

Test works like a charm now

(Nathan 'jesterKing' Letwory) #14

You are changing objects, so that is changing the scene. This in turn triggers updates in the changequeue for the Raytraced viewport.

Your script is probably running on the main thread, so it kinda blocks everything. You should have a look at doing a semi-modal dialog in Eto to get better response. Probably a panel would be a good solution.

I have no knowledge of Neon, I only have heard of it - I may have seen it for a minute or two back in 2013 when I started talking with Andy about Cycles integration.


Thanks as always!
And see above, now it is responsive.

(Nathan 'jesterKing' Letwory) #16

Yah, I saw your mod answer had sent mine :slight_smile:

(Nathan 'jesterKing' Letwory) #17

I assume you have a _ViewCaptureToFile somewhere in your actual script? :slight_smile:


Yeah, it will be there soon!
Just have to do some economics here before midnight first :wink:

The downside with V6 though is that I will have to override the users _viewcapturetofile settings to avoid recalculations IF the users has used a different scale than 1 and has more iterations sat than what it manages to do in the given time. (So I wish for a V5 style, dead simple, viewcapture command that just captures the actual view with out messing with the settings)

(Nathan 'jesterKing' Letwory) #19

If you use the dashed version I think the default is to use viewport size, scale 1. Also set a low NumberOfPasses (or whatever it is called - I always forget), so that at least this won’t restart the entire render session separately.


Yeah, thanks, I have it at 1.
By the way, this is what the string looks like:
(the x part is to change “1” to “00001” and so on. I figured 99999 frames to be enough for this kind of animations :wink: )

x= "%05d" % counter
rs.Command("_-ViewCaptureToFile Unit=pixels Scale=1 NumberOfPasses=1 DrawGrid=No  DrawWorldAxes=No  DrawCPlaneAxes=No  ScaleDrawing=No  TransparentBackground=No " + chr(34) + str(location) +chr(92) +"frame_"+ str(x) +".jpg"+ chr(34) + " _Enter", False)