Script to level the camera

Script to level the camera

michael
Contributor Contributor
939 Views
3 Replies
Message 1 of 4

Script to level the camera

michael
Contributor
Contributor

I use the following when making screen shots to straighten up the view, making vertical lines plumb (in ortho mode). Even in perspective mode it helps improve consistency between shots of different parts of the model.

 

There are some potential edge cases (e.g. upVector perpendicular to y-axis), but for my intended use I don't expect to be operating anywhere near them. If there's a way in the UI that I missed to accomplish the same thing I'd love to know about it 🙂

 

Cheers,

 

Michael

 

#Description- LevelCamera.py

import adsk.core, adsk.fusion, adsk.cam, traceback

def decomposeVector(a, b):
    
    aParallelB = b.copy()
    aParallelB.scaleBy(a.dotProduct(b) / b.dotProduct(b))
    
    aPerpendicularB = a.copy()
    aPerpendicularB.subtract(aParallelB)
    
    return [aParallelB, aPerpendicularB]
    
def verticalizeView():
    ui = None
    app = adsk.core.Application.get()
    ui  = app.userInterface

    cam = app.activeViewport.camera
    
    yAxisVector = adsk.core.Vector3D.create(0.0, 1.0, 0.0)
    upVector = cam.upVector
    # construct vector pointing from camera to target
    eyeVector = adsk.core.Vector3D.create(cam.target.x - cam.eye.x, cam.target.y - cam.eye.y, cam.target.z - cam.eye.z)

    # Whenever view is level, Y-axis, upVector, and eyeVector will be coplanar.
    # To roll the camera to make it level, project the upVector to the plane
    # formed by Y-axis + eyeVector then rescale to get new upVector

    # make sure the request makes sense   
    if yAxisVector.isParallelTo(eyeVector):
        # NOTE: above should really check instead to see if angle
        # between Y axis and eyeVector is closer than some arbitrary amount to 0 or pi
        ui.messageBox('Camera is pointing straight up or down')
    else:
        # get vector perpendicular to both yAxis + eyeVector
        orthoVector = yAxisVector.crossProduct(eyeVector)
        # isolate the portion of camera upVector that would remain once we project onto 
        # vertically oriented plane containing eyeVector
        upParallel, upPerpendicular = decomposeVector(upVector, orthoVector)
        # stretch remainder back to unit length (don't know if Fusion cares)
        upPerpendicular.scaleBy(1/upPerpendicular.length)
        cam.upVector = upPerpendicular
        rotation = round(upVector.angleTo(upPerpendicular) * 360 / 6.283,1)
        app.activeViewport.camera = cam
        ui.messageBox('Done. Camera rotated by ' + str(rotation) + ' degree(s)')

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        verticalizeView()

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

0 Likes
940 Views
3 Replies
Replies (3)
Message 2 of 4

ekinsb
Alumni
Alumni

I don't know of a built-in command in Fusion do this.  I believe this will accomplish the same thing in your case though.

 

def verticalizeView():
    app = adsk.core.Application.get()
    ui = app.userInterface

    view = app.activeViewport
    cam = view.camera
    
    yAxisVector = adsk.core.Vector3D.create(0.0, 1.0, 0.0)

    # make sure the request makes sense   
    if yAxisVector.isParallelTo(eyeVector):
        ui.messageBox('Camera is pointing straight up or down')
    else:
        cam.upVector = yAxisVector
        view = cam

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 3 of 4

michael
Contributor
Contributor

Hmm, I tried your code and I didn't see any effect (but also did not get any exception either). It would indeed be much simpler if I could just set the upVector that way without worrying about maintaining perpendicularity with camera->target vector

 

I did figure out though that if I set Orbit to Constrained in UI before maneuvering for my screen shot that it eliminates need for my script 🙂

 

Michael

 

0 Likes
Message 4 of 4

michael
Contributor
Contributor

 

PS: I pasted in the eyeVector line before trying to run:

 

eyeVector = adsk.core.Vector3D.create(cam.target.x - cam.eye.x, cam.target.y - cam.eye.y, cam.target.z - cam.eye.z)

0 Likes