Help: Fastest move camera and update view and rs.Redraw() bug?

Hi guys, I am working on Holomark3 and really want a good way to manually control the camera and target and update the view in the same speed as rs.

Here are my results from this test:

Turn on/off EnableRedraw: 3.43
Using rs.Redraw(): 10.14
Using Rhino.Display.RhinoView Redraw: 3.33
ViewSpeedTest 1 frame at a time: 3.33

As you can see it is much (3x!) faster to turn redraw off and on than to just call redraw, is that a bug?
Note: I’m on a laptop with a 750m on this test. Simple cube in wireframe.

And the built in testmaxspeed is done in 1.6 seconds…
Could I achive something similar in Python if I moved the camera along a path?
(I can get good results with rs.ViewSpeedTest() by setting the target and only moving a segment of a circle, but I would like even more freedom :wink: )

And here is the code:

import Rhino
import rhinoscriptsyntax as rs
import time
import scriptcontext

view=rs.CurrentView()

camera1=(50,-50,50)
camera2=(-50,-50,50)
target1=(0,0,0)
target2=(0,0,0)

time1=time.time()
for i in range(100):
    rs.EnableRedraw(False)
    rs.ViewCameraTarget(view,camera1, target1)
    rs.EnableRedraw(True)
    rs.EnableRedraw(False)
    rs.ViewCameraTarget(view,camera2, target2)
    rs.EnableRedraw(True)
time2=time.time()
print "Turn on/off EnableRedraw:",round(time2-time1,2)

time1=time.time()
for i in range(100):
    rs.ViewCameraTarget(view,camera1, target1)
    rs.Redraw()
    rs.ViewCameraTarget(view,camera2, target2)
    rs.Redraw()
time2=time.time()
print "Using rs.Redraw():",round(time2-time1,2)

view2 = scriptcontext.doc.Views.ActiveView

time1=time.time()
for i in range(100):
    rs.ViewCameraTarget(view,camera1, target1)
    rs.Sleep(0)
    Rhino.Display.RhinoView.Redraw(view2)
    rs.ViewCameraTarget(view,camera2, target2)
    rs.Sleep(0)
    Rhino.Display.RhinoView.Redraw(view2)
time2=time.time()
print "Using Rhino.Display.RhinoView Redraw:",round(time2-time1,2)

time1=time.time()
for i in range(100):
    rs.ViewSpeedTest(view, frames=1, direction=0, angle_degrees=45)
    rs.ViewSpeedTest(view, frames=1, direction=1, angle_degrees=45)
time2=time.time()
print "ViewSpeedTest 1 frame at a time:",round(time2-time1,2)

hi Jorgen,

testing here:

Turn on/off EnableRedraw: 5.13
Using rs.Redraw(): 16.0
Using Rhino.Display.RhinoView Redraw: 3.33
ViewSpeedTest 1 frame at a time: 3.33

Both rs.EnableRedraw and rs.Redraw, redraw views and UI as well (you can see it by having some layers selected in Layers panel - the selection will flicker and slowdown). The other 2 methods just redraw the vport, which is MUCH faster. Something is odd with rs.Redraw as it should be the same speed as rs. EnableRedraw, at least is it the case in RhinoScript.

Also, in RhinoScript Dale recently added an additional argument to Rhino.Redraw(True/False) which actually enables the fast redraw without UI. Not sure if this has been added to Python method yet. If not, your best bet is to use RhinoCommon method.

hth,

–jarek

1 Like

Thanks for testing and I see you get a big speed difference on the two first too where rs.Redraw() is slowest.

I’ll test out Rhino.Redraw() but would still love a faster way :slight_smile:

I am testing with a scene with Skylight shadows; also what matters is the number of layers visible and selected in the Layer dialog, if visible. From what I can tell that matters for the methods that redraw the UI. But if you are in for speed, you don’t want any of these.

Are you trying to get even faster than RhinoCommon method? It seems to be the same as ViewSpeedTest / TestMaxSpeed commands… I also would like to know if this is possible, even though these already seem very fast…

Maybe McNeel devs. can chime in… I think there are some more potential speedups that kick in if you are inside a view change mode, like RMB-drag rotation. For sure Skylight degradation kicks in then, maybe more. I recently found a way to manually control the skylight degradation, so to some degree you can simulate that for modes with Skylight shadows for speedups, but other than that I don’t know how to go even faster!

–jarek

Here is the reference to how to control Skylight degradation:

1 Like

Yes, when comparing calling it 100 times, but running testmaxspeed with 100 internal redraws are faster, and that is what really shows what Rhino is capable of, so that’s what I wish to get closer to :slight_smile:

Yes, I also tested with the default rendered mode and got about the same results. I think I will stay away from degeneration though.

1 Like

Your test loops are 100 times but each has 2 redraws, if you run testmaxspeed it has only 1 redraw/camera change per move, so the speed doubles. Over here TestMaxSpeed is 1.66s vs. you RhinoCommon loop test method: 3.33s. Rhino.Redraw(False) has the same speed as testmaxspeed.

So this is probably as fast as you can go via scripting. I would be happy to be wrong :slight_smile:

– jarek

Oh damn… that was embarrasing… :smile:

Hi Jarek,

I just remembered that Vsync is on by default, limiting the scores to 60fps so you can turn it off first with:

_-TestMaxSpeed VerticalSync=Disabled _Enter

Then I get these results:

Turn on/off EnableRedraw: 2.81
Using rs.Redraw(): 9.37
Using Rhino.Display.RhinoView Redraw: 1.2
ViewSpeedTest 1 frame at a time: 0.33

And testmaxspeed with 200 frames:
Time to regen viewport 200 times = 0.34 seconds. (583.09 FPS)

1 Like

Hi @Holo
Using inspect to check the source code:

import rhinoscriptsyntax as rs
import inspect

print inspect.getsource(rs.Redraw)
print inspect.getsource(rs.EnableRedraw)

I get

def Redraw():
    "Redraws all views"
    old = scriptcontext.doc.Views.RedrawEnabled
    scriptcontext.doc.Views.RedrawEnabled = True
    scriptcontext.doc.Views.Redraw()
    Rhino.RhinoApp.Wait()
    scriptcontext.doc.Views.RedrawEnabled = old

def EnableRedraw(enable=True):
    """Enables or disables screen redrawing
    Returns: previous screen redrawing state
    """
    old = scriptcontext.doc.Views.RedrawEnabled
    if old!=enable: scriptcontext.doc.Views.RedrawEnabled = enable
    return old

So Redraw is doing a lot more work, including enabling and disabling redraw. Note that enableredraw does not in itself force a redraw

2 Likes

And here is a camera along path script, but with this I only get 160 FPS:

import Rhino
import rhinoscriptsyntax as rs
import time
import scriptcontext as sc

rs.Command("_-TestMaxSpeed VerticalSync=Disabled FrameCount=1 _Enter")

segments=100

def CameraAlongCurve(segments):
    
    curve=rs.GetObject("Select CameraCurve",rs.filter.curve)
    if not curve: return
    
    rs.HideObject(curve)
    
    target=(0,0,0)
    camPts=rs.DivideCurve(curve,segments)
    view=rs.CurrentView()
    view2 = sc.doc.Views.ActiveView
    
    initCamTarPos=rs.ViewCameraTarget(view)
    
    time1=time.time()
    for i in range(segments):
        rs.ViewCameraTarget(view,camPts[i], target)
        rs.Sleep(0)
        Rhino.Display.RhinoView.Redraw(view2)
    
    time2=time.time()
    
    rs.ViewCameraTarget(view,initCamTarPos[0],initCamTarPos[1])
    rs.ShowObject(curve)
    
    return round(time2-time1,2)

runTime=CameraAlongCurve(segments)

print "Redrawing",segments,"frames took",runTime,"seconds @",round(segments/runTime,1),"FPS"

Hey, that was handy!
Thanks for sharing that, and yes, using Rhino.Display.RhinoView.Redraw(view2) is by far the fastest as it only redraws the selected view, so that will go into Holomark3 if I see it is fast enough for high end systems.

So… the rhinoscriptcontext is actually using scriptcontext and Rhino common in the background, I didn’t know that :slight_smile: It all makes more sense now!

You’re very welcome.
also check out from timeit import timeit for more accurate timing of snippets of python code. Use the setup parameter to pass initialisation code which you don’t want to time (such as your imports).

https://docs.python.org/2/library/timeit.html

1 Like

Yes and then add in Rhino Inside and you could have RhinoCommon (Ironpython) behind rhinoscriptsyntax (Ironpython) running in Rhino inside Cpython!

image

1 Like

hi Jorgen,

thanks, I forgot about that setting - it improves the FPS greatly, at least on lightweight scenes.

@Jeff - why is this OFF by default - can enabling it lead to problems on some systems?
Also, is the only way to change it running the -_TestMaxSpeed command?
What are the other settings in that command doing? (DisplayList, DynamicDraw)
I am tempted to run this command with VSync off at the beginning of the script for speed gains but I don’t want to cause any issues…

–jarek

Because we don’t ever like “forcing” something to be On or Off that is related to hardware… especially when the OEM/ODM has a setting for it.

If you always want it ON…then go into your driver’s Settings Panel, and look for Vertical Sync or Vertical Retrace setting, and turn it OFF… This can usually be set globally (for all apps.) or on an app-by-app basis through an Application Profile.

-J

Note: Rhino isn’t turning anything On or Off by default… If it’s ON, then it’s because that’s what your driver’s default setting is. So I just don’t want you thinking that Rhino is for some reason turning it ON as some kind of default setting… Rhino only allows you to turn it off…it doesn’t turn it ON, ever. So even if you use the TestMaxSpeed setting and choose not to use the VSync option, that doesn’t mean VSync is now ON…it’ll only be ON if that’s what your drivers set it to…if that makes sense.

-J

Hi Jeff, I am fine on my system, just want other potential users of my script to take advantage of it, without getting into this nitty-gritty setting. I wanted to find out f turning this OFF may have some potential bad results.

Yes, it makes sense - ON means use global driver setting (will use it if enabled), OFF would override whatever setting and not use it.

So is TextMaxSpeed command the only way to switch this setting in Rhino?

–jarek

For anyone interested, here is what VSync actually does (from driver description):
Capture

Yes, but keep in mind that the only thing it does is wasting power as there is not much real life sense in feeding more FPS out of a graphiccard than a monitor can present :slight_smile: So limiting the GPU to 60 (or 140 if you have one of those monitors) makes a lot of sense. It keeps the system cooler and quieter too and is at least beneficial for laptops. But when benchmarkin it is nice to get the full power presented.

1 Like