Why does rotating Perspective viewport change WorldToScreenScale?

There’s probably some simple explanation but it simply looks very weird to me.

Hi @ivelin.peychev, it depends on the point you pass to the method as pointInFrustum. If it is the current mouse position, this changes while you rotate or pan, especially in a perspective view.

_
c.

Hi @clement,

I pass Rhino.Geometry.Point3d.Origin

@ivelin.peychev, without showing some code it is not easy to find out why you’re seeing this. Below is an example, in a perspective viewport, set the camera target to 0,0,0 then run the script and rotate using RMB. Watch the StatusBarDistancePane for the value, it should stay constant while you rotate.

import Rhino
import scriptcontext

origin = Rhino.Geometry.Point3d.Origin

def GetPointDynamicDrawFunc( sender, args ):
    vp = scriptcontext.doc.Views.ActiveView.ActiveViewport
    rc, scale = vp.GetWorldToScreenScale(origin)
    if rc: Rhino.UI.StatusBar.SetDistancePane(scale)

def DoSomething():
    gp = Rhino.Input.Custom.GetPoint()
    gp.DynamicDraw += GetPointDynamicDrawFunc
    gp.Get()

DoSomething()

Next Pan in the perspective view, this should move the camera target out of the center of the viewport. If you rotate again now using RMB, you’ll see that the WorldToScreenScale value changes, because you change the distance from the world origin to the camera location. Does that make sense ?

_
c.

This is what I’m doing:

take the code from there just replace the “pt” (currently commented) with Rhino.Geometry.Point3d.Origin.

Compare to which viewport my example above limits the calculation of the scale, then change above code to do it like in your example to understand why it happens. Note that a display conduit event can be fired for every viewport if you use e.Viewport.

Your code behaves when changed to this:

class dc(Rhino.Display.DisplayConduit):
    def CalculateBoundingBox(self,e):
        global vp
        vp = e.Viewport
        rc, scale = vp.GetWorldToScreenScale(Rhino.Geometry.Point3d.Origin)
        if rc: print scale, vp.Name

Using a constuct like this is likely to cause a problem:

vp = e.Viewport.GetWorldToScreenScale(pt)[1]

if the function return value is False. As you noted already, pt is undefined.
_
c.

Hi @clement,

import scriptcontext as sc
import Rhino



scale_ratio = None


class dc(Rhino.Display.DisplayConduit):
    def CalculateBoundingBox(self,e):
        global scale_ratio
        pt = Rhino.Geometry.Point3d.Origin
        if scale_ratio == e.Viewport.GetWorldToScreenScale(pt)[1]:
            pass#print "no zoom"
        else:
            scale_ratio = e.Viewport.GetWorldToScreenScale(pt)[1]
            print scale_ratio
            #print "zoomed"

def zoom_event_helper_func():
    #Event trigger helper function
    if sc.sticky.has_key('ZoomCallback'):
        callback = sc.sticky['ZoomCallback']
        if callback:
            callback.Enabled = False
            callback = None
            sc.sticky.Remove('ZoomCallback')
            print "zoom event listener stopped."
    else:
        callback = dc()
        callback.Enabled = True
        sc.sticky['ZoomCallback'] = callback
        print "zoom event listener started."




if __name__ == "__main__":
    
    
    zoom_event_helper_func()
    
    

This is my actual code. I made the scale global, because I want it somehow to trigger another even that I haven’t yet figured out how to implement.

If you run this and pan any of the planar views you won’t get any change, but if you rotate the perspective view you get a small (but still) change which is weird because you do not move the camera location nor the origin point. I do not understand why would there be a scale-change.

Again, set the camera target to the origin in perspective viewport. Turn on the camera.Then while you rotate the view, watch how the camera target stays at the origin, but note what happens if you print the viewport name along with the scale value:

print scale_ratio, e.Viewport.Name

I get something like this in a 4 view layout:

2.49249179146 Perspective
1.17446404155 Top
1.72136400272 Front
4.41240304599 Right
2.49249179146 Perspective
1.17446404155 Top
1.72136400272 Front
4.41240304599 Right
2.49249179146 Perspective
1.17446404155 Top
1.72136400272 Front
4.41240304599 Right
2.49249179146 Perspective
1.17446404155 Top
1.72136400272 Front
4.41240304599 Right

The event gets fired for any viewport if your perspective view is not maximized and there is something which changes in the other views while you rotate the perspective view, eg. the camera widget.

Now Pan in the perspective viewport, this moves the target out of the center of the view. If you rotate now, the distance from the camera to the origin measured in screen space changes, therefore the scale value changes as well.

Btw. if i turn Off the camera, set the target to the origin and rotate using your last example, i only get a constant scale printed. If i pan once, then rotate, it changes the scale.

_
c.

Hi @clement,

No, that’s not my result at all.

How did you set the camera target ? Make the same vid with the properties tab visible so i can see the target is at 0,0,0. To me it looks like it is slightly off.

_
c.

I simply started Rhino and launched the script. If it is slightly off then this is the default upon start.

I’ll take a look.

Without anything selected, open the Properties tab. Then click the Place button for the target.

_
c.

1 Like

Thanks @clement, that was it indeed.