<commit_before>from .rman_translator import RmanTranslator
from ..rman_sg_nodes.rman_sg_camera import RmanSgCamera
from ..rman_sg_nodes.rman_sg_node import RmanSgNode
from ..rman_utils import transform_utils
from ..rman_utils import property_utils
from ..rman_utils import object_utils
from ..rman_utils import scene_utils
from mathutils import Matrix, Vector
import math

def _render_get_resolution_(r):
    xres = int(r.resolution_x * r.resolution_percentage * 0.01)
    yres = int(r.resolution_y * r.resolution_percentage * 0.01)
    return xres, yres    

def _render_get_aspect_(r, camera=None, x=-1, y=-1):
    if x != -1 and y != -1:
        xratio = x * r.pixel_aspect_x / 200.0
        yratio = y * r.pixel_aspect_y / 200.0        
    else:
        xres, yres = _render_get_resolution_(r)
        xratio = xres * r.pixel_aspect_x / 200.0
        yratio = yres * r.pixel_aspect_y / 200.0

    if camera is None or camera.type != 'PERSP':
        fit = 'AUTO'
    else:
        fit = camera.sensor_fit

    if fit == 'HORIZONTAL' or fit == 'AUTO' and xratio > yratio:
        aspectratio = xratio / yratio
        xaspect = aspectratio
        yaspect = 1.0
    elif fit == 'VERTICAL' or fit == 'AUTO' and yratio > xratio:
        aspectratio = yratio / xratio
        xaspect = 1.0
        yaspect = aspectratio
    else:
        aspectratio = xaspect = yaspect = 1.0

    return xaspect, yaspect, aspectratio    

class RmanCameraTranslator(RmanTranslator):

    def __init__(self, rman_scene):
        super().__init__(rman_scene)
        self.bl_type = 'CAMERA'
        self.s_rightHanded = self.rman_scene.rman.Types.RtMatrix4x4(1.0,0.0,0.0,0.0,
                                                               0.0,1.0,0.0,0.0,
                                                               0.0,0.0,-1.0,0.0,
                                                               0.0,0.0,0.0,1.0) 

    def _set_orientation(self, rman_sg_camera):
        camtransform = self.rman_scene.rman.Types.RtMatrix4x4()
        camtransform.Identity()
        rman_sg_camera.sg_node.SetOrientTransform(self.s_rightHanded)        

    def update_transform_num_samples(self, rman_sg_camera, motion_steps ):
        rman_sg_camera.sg_node.SetTransformNumSamples(len(motion_steps))

    def _update_viewport_transform(self, rman_sg_camera):
        mtx = self.rman_scene.context.region_data.view_matrix.inverted()
        v = transform_utils.convert_matrix(mtx)
        if rman_sg_camera.cam_matrix == v:
            return 
        rman_sg_camera.cam_matrix = v
        rman_sg_camera.sg_node.SetTransform( v )    

    def _update_render_cam_transform(self, ob, rman_sg_camera, index=0):

        cam = ob.data
        mtx = ob.matrix_world

        v = transform_utils.convert_matrix(mtx)
        if rman_sg_camera.cam_matrix == v:
            return

        rman_sg_camera.cam_matrix = v
        if rman_sg_camera.is_transforming:
            rman_sg_camera.sg_node.SetTransformSample(index, v, rman_sg_camera.motion_steps[index] )              
        else:
            rman_sg_camera.sg_node.SetTransform( v )                            

    def update_transform(self, ob, rman_sg_camera, index=0):
        if self.rman_scene.is_viewport_render:
            self._update_viewport_transform(rman_sg_camera)
        else:
            self._update_render_cam_transform(ob, rman_sg_camera, index)

    def _export_viewport_cam(self, db_name=""):  
        sg_camera = self.rman_scene.sg_scene.CreateCamera(db_name)
        rman_sg_camera = RmanSgCamera(self.rman_scene, sg_camera, db_name)
        ob = self.update_viewport_resolution(rman_sg_camera)
        self.update_viewport_cam(ob, rman_sg_camera)
        self._set_orientation(rman_sg_camera)
        self._update_viewport_transform(rman_sg_camera)  
        return rman_sg_camera        

    def _export_render_cam(self, ob, db_name=""):
        sg_camera = self.rman_scene.sg_scene.CreateCamera(db_name)
        rman_sg_camera = RmanSgCamera(self.rman_scene, sg_camera, db_name)
        if self.rman_scene.do_motion_blur:
            rman_sg_camera.is_transforming = object_utils.is_transforming(ob)
            mb_segs = self.rman_scene.bl_scene.renderman.motion_segments
            if ob.renderman.motion_segments_override:
                mb_segs = ob.renderman.motion_segments
            if mb_segs > 1:
                subframes = scene_utils._get_subframes_(mb_segs, self.rman_scene.bl_scene)
                rman_sg_camera.motion_steps = subframes  
                self.update_transform_num_samples(rman_sg_camera, subframes )                
            else:
                rman_sg_camera.is_transforming = False
        self._update_render_cam(ob, rman_sg_camera)
        self._set_orientation(rman_sg_camera)
        self._update_render_cam_transform(ob, rman_sg_camera)
        return rman_sg_camera                  

    def export(self, ob, db_name=""):
        if self.rman_scene.is_viewport_render:
            return self._export_viewport_cam(db_name)
        else:
            return self._export_render_cam(ob, db_name)

    def update(self, ob, rman_sg_camera):
        if self.rman_scene.is_viewport_render:
            return self.update_viewport_cam(rman_sg_camera)
        else:
            return self._update_render_cam(ob, rman_sg_camera)   

    def update_viewport_resolution(self, rman_sg_camera):
        region = self.rman_scene.context.region
        region_data = self.rman_scene.context.region_data

        # get the current resolution multiplier
        res_mult = self.rman_scene.viewport_render_res_mult

        width = int(region.width * res_mult)
        height = int(region.height * res_mult)      

        updated = False
        if rman_sg_camera.res_width != width:
            rman_sg_camera.res_width = width
            updated = True
        
        if rman_sg_camera.res_height != height:
            rman_sg_camera.res_height = height                
            updated = True      

        if rman_sg_camera.view_perspective != region_data.view_perspective:
            rman_sg_camera.view_perspective = region_data.view_perspective
            updated = True            

        if rman_sg_camera.view_camera_zoom != self.rman_scene.context.region_data.view_camera_zoom:
            rman_sg_camera.view_camera_zoom = self.rman_scene.context.region_data.view_camera_zoom
            updated = True

        if rman_sg_camera.view_camera_offset != self.rman_scene.context.region_data.view_camera_offset:
            rman_sg_camera.view_camera_offset = self.rman_scene.context.region_data.view_camera_offset
            updated = True            

        prop = rman_sg_camera.sg_node.GetProperties()
        if region_data.view_perspective == 'CAMERA':
            ob = self.rman_scene.bl_scene.camera    
            if self.rman_scene.context.space_data.use_local_camera:
                ob = self.rman_scene.context.space_data.camera      

            cam = ob.data
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)

            # magic zoom formula copied from blenderseed, which got it from cycles
            zoom = 4 / ((math.sqrt(2) + rman_sg_camera.view_camera_zoom / 50) ** 2)   
                
            # shift and offset            
            offset = tuple(rman_sg_camera.view_camera_offset)
            dx = 2.0 * (aspectratio * cam.shift_x + offset[0] * xaspect * 2.0)
            dy = 2.0 * (aspectratio * cam.shift_y + offset[1] * yaspect * 2.0)       
            
            xaspect *= zoom
            yaspect *= zoom 
            xaspect += dx
            yaspect += dy
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect: 
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)      
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True

        elif region_data.view_perspective ==  'PERSP': 
            ob = self.rman_scene.context.space_data.camera 
            cam = ob.data
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)          
            zoom = 2.0  

            # shift and offset            
            offset = tuple(rman_sg_camera.view_camera_offset)
            dx = 2.0 * (aspectratio * cam.shift_x + offset[0] * xaspect * 2.0)
            dy = 2.0 * (aspectratio * cam.shift_y + offset[1] * yaspect * 2.0)               

            xaspect *= zoom
            yaspect *= zoom
            rman_sg_camera.lens = self.rman_scene.context.space_data.lens
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect:
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)   
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True                               

        else: 
            ob = self.rman_scene.context.space_data.camera       
            cam = ob.data
            
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)

            # 2.25 zoom value copied from blenderseed
            zoom = 2.25        
            lens = self.rman_scene.context.space_data.lens
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width

            ortho_scale = region_data.view_distance * sensor / lens
            xaspect = xaspect * ortho_scale / (aspectratio * 2.0)
            yaspect = yaspect * ortho_scale / (aspectratio * 2.0)

            xaspect *= zoom
            yaspect *= zoom            
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect:
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)   
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True                                          

        if updated:
            options = self.rman_scene.sg_scene.GetOptions()
            options.SetFloat(self.rman_scene.rman.Tokens.Rix.k_Ri_FormatPixelAspectRatio, 1.0)   
            options.SetIntegerArray(self.rman_scene.rman.Tokens.Rix.k_Ri_FormatResolution, (width, height), 2)
            self.rman_scene.sg_scene.SetOptions(options)
            rman_sg_camera.sg_node.SetProperties(prop)
            return ob
        return None

    def update_viewport_cam(self, ob, rman_sg_camera):
        region = self.rman_scene.context.region
        region_data = self.rman_scene.context.region_data

        # get the current resolution multiplier
        res_mult = self.rman_scene.viewport_render_res_mult

        width = rman_sg_camera.res_width
        height = rman_sg_camera.res_height
        view_camera_zoom = rman_sg_camera.view_camera_zoom

        proj = None
        fov = -1

        options = self.rman_scene.sg_scene.GetOptions()
        prop = rman_sg_camera.sg_node.GetProperties()

        updated = False

        if rman_sg_camera.view_perspective == 'CAMERA':
            cam = ob.data
            rman_sg_camera.bl_camera = ob

            aspectratio = rman_sg_camera.aspectratio
            lens = cam.lens
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width
                     
            fov = 360.0 * math.atan((sensor * 0.5) / lens / aspectratio) / math.pi

            if rman_sg_camera.rman_fov == -1:
                rman_sg_camera.rman_fov = fov  
                updated = True
            elif rman_sg_camera.rman_fov != fov:              
                rman_sg_camera.rman_fov = fov  
                updated = True

            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrCamera", "proj")
            projparams = proj.params         
            projparams.SetFloat(self.rman_scene.rman.Tokens.Rix.k_fov, fov) 

        elif rman_sg_camera.view_perspective ==  'PERSP': 
            cam = ob.data
            rman_sg_camera.bl_camera = ob
            
            aspectratio = rman_sg_camera.aspectratio
            lens = rman_sg_camera.lens 
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width
                     
            fov = 360.0 * math.atan((sensor * 0.5) / lens / aspectratio) / math.pi

            if rman_sg_camera.rman_fov == -1:
                rman_sg_camera.rman_fov = fov  
                updated = True
            elif rman_sg_camera.rman_fov != fov:              
                rman_sg_camera.rman_fov = fov  
                updated = True               

            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrCamera", "proj")
            projparams = proj.params         
            projparams.SetFloat(self.rman_scene.rman.Tokens.Rix.k_fov, fov)   

        else:
            # orthographic
            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrOrthographic", "proj")          

        if updated:
                        
            # This may look redundant given that we've already set screen window on the camera, 
            # but for some reason without this we seem to be getting
            # the default -1 1 -1 1 screen window every time we change any of the camera's
            # properties that affect FOV. Even setting the screen window again on the camera
            # doesn't work
            options = self.rman_scene.sg_scene.GetOptions()
            options.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-rman_sg_camera.xaspect, rman_sg_camera.xaspect, -rman_sg_camera.yaspect, rman_sg_camera.yaspect), 4)               
            self.rman_scene.sg_scene.SetOptions(options)

            rman_sg_camera.sg_node.SetProjection(proj)          
            rman_sg_camera.sg_node.SetRenderable(True)         

    def _update_render_cam(self, ob, rman_sg_camera):

        r = self.rman_scene.bl_scene.render
        cam = ob.data
        rm = self.rman_scene.bl_scene.renderman
        cam_rm = cam.renderman
        rman_sg_camera.bl_camera = ob

        xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam)
<commit_msg>Comment out workaround for RMAN-16122. We seem to hit a crash when the resolution changes. I think the solution is to set screen window in view_update and not view_draw.<commit_after>from .rman_translator import RmanTranslator
from ..rman_sg_nodes.rman_sg_camera import RmanSgCamera
from ..rman_sg_nodes.rman_sg_node import RmanSgNode
from ..rman_utils import transform_utils
from ..rman_utils import property_utils
from ..rman_utils import object_utils
from ..rman_utils import scene_utils
from mathutils import Matrix, Vector
import math

def _render_get_resolution_(r):
    xres = int(r.resolution_x * r.resolution_percentage * 0.01)
    yres = int(r.resolution_y * r.resolution_percentage * 0.01)
    return xres, yres    

def _render_get_aspect_(r, camera=None, x=-1, y=-1):
    if x != -1 and y != -1:
        xratio = x * r.pixel_aspect_x / 200.0
        yratio = y * r.pixel_aspect_y / 200.0        
    else:
        xres, yres = _render_get_resolution_(r)
        xratio = xres * r.pixel_aspect_x / 200.0
        yratio = yres * r.pixel_aspect_y / 200.0

    if camera is None or camera.type != 'PERSP':
        fit = 'AUTO'
    else:
        fit = camera.sensor_fit

    if fit == 'HORIZONTAL' or fit == 'AUTO' and xratio > yratio:
        aspectratio = xratio / yratio
        xaspect = aspectratio
        yaspect = 1.0
    elif fit == 'VERTICAL' or fit == 'AUTO' and yratio > xratio:
        aspectratio = yratio / xratio
        xaspect = 1.0
        yaspect = aspectratio
    else:
        aspectratio = xaspect = yaspect = 1.0

    return xaspect, yaspect, aspectratio    

class RmanCameraTranslator(RmanTranslator):

    def __init__(self, rman_scene):
        super().__init__(rman_scene)
        self.bl_type = 'CAMERA'
        self.s_rightHanded = self.rman_scene.rman.Types.RtMatrix4x4(1.0,0.0,0.0,0.0,
                                                               0.0,1.0,0.0,0.0,
                                                               0.0,0.0,-1.0,0.0,
                                                               0.0,0.0,0.0,1.0) 

    def _set_orientation(self, rman_sg_camera):
        camtransform = self.rman_scene.rman.Types.RtMatrix4x4()
        camtransform.Identity()
        rman_sg_camera.sg_node.SetOrientTransform(self.s_rightHanded)        

    def update_transform_num_samples(self, rman_sg_camera, motion_steps ):
        rman_sg_camera.sg_node.SetTransformNumSamples(len(motion_steps))

    def _update_viewport_transform(self, rman_sg_camera):
        mtx = self.rman_scene.context.region_data.view_matrix.inverted()
        v = transform_utils.convert_matrix(mtx)
        if rman_sg_camera.cam_matrix == v:
            return 
        rman_sg_camera.cam_matrix = v
        rman_sg_camera.sg_node.SetTransform( v )    

    def _update_render_cam_transform(self, ob, rman_sg_camera, index=0):

        cam = ob.data
        mtx = ob.matrix_world

        v = transform_utils.convert_matrix(mtx)
        if rman_sg_camera.cam_matrix == v:
            return

        rman_sg_camera.cam_matrix = v
        if rman_sg_camera.is_transforming:
            rman_sg_camera.sg_node.SetTransformSample(index, v, rman_sg_camera.motion_steps[index] )              
        else:
            rman_sg_camera.sg_node.SetTransform( v )                            

    def update_transform(self, ob, rman_sg_camera, index=0):
        if self.rman_scene.is_viewport_render:
            self._update_viewport_transform(rman_sg_camera)
        else:
            self._update_render_cam_transform(ob, rman_sg_camera, index)

    def _export_viewport_cam(self, db_name=""):  
        sg_camera = self.rman_scene.sg_scene.CreateCamera(db_name)
        rman_sg_camera = RmanSgCamera(self.rman_scene, sg_camera, db_name)
        ob = self.update_viewport_resolution(rman_sg_camera)
        self.update_viewport_cam(ob, rman_sg_camera)
        self._set_orientation(rman_sg_camera)
        self._update_viewport_transform(rman_sg_camera)  
        return rman_sg_camera        

    def _export_render_cam(self, ob, db_name=""):
        sg_camera = self.rman_scene.sg_scene.CreateCamera(db_name)
        rman_sg_camera = RmanSgCamera(self.rman_scene, sg_camera, db_name)
        if self.rman_scene.do_motion_blur:
            rman_sg_camera.is_transforming = object_utils.is_transforming(ob)
            mb_segs = self.rman_scene.bl_scene.renderman.motion_segments
            if ob.renderman.motion_segments_override:
                mb_segs = ob.renderman.motion_segments
            if mb_segs > 1:
                subframes = scene_utils._get_subframes_(mb_segs, self.rman_scene.bl_scene)
                rman_sg_camera.motion_steps = subframes  
                self.update_transform_num_samples(rman_sg_camera, subframes )                
            else:
                rman_sg_camera.is_transforming = False
        self._update_render_cam(ob, rman_sg_camera)
        self._set_orientation(rman_sg_camera)
        self._update_render_cam_transform(ob, rman_sg_camera)
        return rman_sg_camera                  

    def export(self, ob, db_name=""):
        if self.rman_scene.is_viewport_render:
            return self._export_viewport_cam(db_name)
        else:
            return self._export_render_cam(ob, db_name)

    def update(self, ob, rman_sg_camera):
        if self.rman_scene.is_viewport_render:
            return self.update_viewport_cam(rman_sg_camera)
        else:
            return self._update_render_cam(ob, rman_sg_camera)   

    def update_viewport_resolution(self, rman_sg_camera):
        region = self.rman_scene.context.region
        region_data = self.rman_scene.context.region_data

        # get the current resolution multiplier
        res_mult = self.rman_scene.viewport_render_res_mult

        width = int(region.width * res_mult)
        height = int(region.height * res_mult)      

        updated = False
        if rman_sg_camera.res_width != width:
            rman_sg_camera.res_width = width
            updated = True
        
        if rman_sg_camera.res_height != height:
            rman_sg_camera.res_height = height                
            updated = True      

        if rman_sg_camera.view_perspective != region_data.view_perspective:
            rman_sg_camera.view_perspective = region_data.view_perspective
            updated = True            

        if rman_sg_camera.view_camera_zoom != self.rman_scene.context.region_data.view_camera_zoom:
            rman_sg_camera.view_camera_zoom = self.rman_scene.context.region_data.view_camera_zoom
            updated = True

        if rman_sg_camera.view_camera_offset != self.rman_scene.context.region_data.view_camera_offset:
            rman_sg_camera.view_camera_offset = self.rman_scene.context.region_data.view_camera_offset
            updated = True            

        prop = rman_sg_camera.sg_node.GetProperties()
        if region_data.view_perspective == 'CAMERA':
            ob = self.rman_scene.bl_scene.camera    
            if self.rman_scene.context.space_data.use_local_camera:
                ob = self.rman_scene.context.space_data.camera      

            cam = ob.data
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)

            # magic zoom formula copied from blenderseed, which got it from cycles
            zoom = 4 / ((math.sqrt(2) + rman_sg_camera.view_camera_zoom / 50) ** 2)   
                
            # shift and offset            
            offset = tuple(rman_sg_camera.view_camera_offset)
            dx = 2.0 * (aspectratio * cam.shift_x + offset[0] * xaspect * 2.0)
            dy = 2.0 * (aspectratio * cam.shift_y + offset[1] * yaspect * 2.0)       
            
            xaspect *= zoom
            yaspect *= zoom 
            xaspect += dx
            yaspect += dy
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect: 
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)      
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True

        elif region_data.view_perspective ==  'PERSP': 
            ob = self.rman_scene.context.space_data.camera 
            cam = ob.data
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)          
            zoom = 2.0  

            # shift and offset            
            offset = tuple(rman_sg_camera.view_camera_offset)
            dx = 2.0 * (aspectratio * cam.shift_x + offset[0] * xaspect * 2.0)
            dy = 2.0 * (aspectratio * cam.shift_y + offset[1] * yaspect * 2.0)               

            xaspect *= zoom
            yaspect *= zoom
            rman_sg_camera.lens = self.rman_scene.context.space_data.lens
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect:
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)   
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True                               

        else: 
            ob = self.rman_scene.context.space_data.camera       
            cam = ob.data
            
            r = self.rman_scene.bl_scene.render

            xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam, x=width, y=height)

            # 2.25 zoom value copied from blenderseed
            zoom = 2.25        
            lens = self.rman_scene.context.space_data.lens
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width

            ortho_scale = region_data.view_distance * sensor / lens
            xaspect = xaspect * ortho_scale / (aspectratio * 2.0)
            yaspect = yaspect * ortho_scale / (aspectratio * 2.0)

            xaspect *= zoom
            yaspect *= zoom            
            if rman_sg_camera.xaspect != xaspect or rman_sg_camera.yaspect != yaspect:
                prop.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-xaspect, xaspect, -yaspect, yaspect), 4)   
                rman_sg_camera.xaspect = xaspect
                rman_sg_camera.yaspect = yaspect  
                rman_sg_camera.aspectratio = aspectratio
                updated = True                                          

        if updated:
            options = self.rman_scene.sg_scene.GetOptions()
            options.SetFloat(self.rman_scene.rman.Tokens.Rix.k_Ri_FormatPixelAspectRatio, 1.0)   
            options.SetIntegerArray(self.rman_scene.rman.Tokens.Rix.k_Ri_FormatResolution, (width, height), 2)
            self.rman_scene.sg_scene.SetOptions(options)
            rman_sg_camera.sg_node.SetProperties(prop)
            return ob
        return None

    def update_viewport_cam(self, ob, rman_sg_camera):
        region = self.rman_scene.context.region
        region_data = self.rman_scene.context.region_data

        # get the current resolution multiplier
        res_mult = self.rman_scene.viewport_render_res_mult

        width = rman_sg_camera.res_width
        height = rman_sg_camera.res_height
        view_camera_zoom = rman_sg_camera.view_camera_zoom

        proj = None
        fov = -1

        options = self.rman_scene.sg_scene.GetOptions()
        prop = rman_sg_camera.sg_node.GetProperties()

        updated = False

        if rman_sg_camera.view_perspective == 'CAMERA':
            cam = ob.data
            rman_sg_camera.bl_camera = ob

            aspectratio = rman_sg_camera.aspectratio
            lens = cam.lens
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width
                     
            fov = 360.0 * math.atan((sensor * 0.5) / lens / aspectratio) / math.pi

            if rman_sg_camera.rman_fov == -1:
                rman_sg_camera.rman_fov = fov  
                updated = True
            elif rman_sg_camera.rman_fov != fov:              
                rman_sg_camera.rman_fov = fov  
                updated = True

            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrCamera", "proj")
            projparams = proj.params         
            projparams.SetFloat(self.rman_scene.rman.Tokens.Rix.k_fov, fov) 

        elif rman_sg_camera.view_perspective ==  'PERSP': 
            cam = ob.data
            rman_sg_camera.bl_camera = ob
            
            aspectratio = rman_sg_camera.aspectratio
            lens = rman_sg_camera.lens 
            sensor = cam.sensor_height \
                if cam.sensor_fit == 'VERTICAL' else cam.sensor_width
                     
            fov = 360.0 * math.atan((sensor * 0.5) / lens / aspectratio) / math.pi

            if rman_sg_camera.rman_fov == -1:
                rman_sg_camera.rman_fov = fov  
                updated = True
            elif rman_sg_camera.rman_fov != fov:              
                rman_sg_camera.rman_fov = fov  
                updated = True               

            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrCamera", "proj")
            projparams = proj.params         
            projparams.SetFloat(self.rman_scene.rman.Tokens.Rix.k_fov, fov)   

        else:
            # orthographic
            proj = self.rman_scene.rman.SGManager.RixSGShader("Projection", "PxrOrthographic", "proj")          

        if updated:
                        
            # This may look redundant given that we've already set screen window on the camera, 
            # but for some reason without this we seem to be getting
            # the default -1 1 -1 1 screen window every time we change any of the camera's
            # properties that affect FOV. Even setting the screen window again on the camera
            # doesn't work
            #options = self.rman_scene.sg_scene.GetOptions()
            #options.SetFloatArray(self.rman_scene.rman.Tokens.Rix.k_Ri_ScreenWindow, (-rman_sg_camera.xaspect, rman_sg_camera.xaspect, -rman_sg_camera.yaspect, rman_sg_camera.yaspect), 4)               
            #self.rman_scene.sg_scene.SetOptions(options)

            rman_sg_camera.sg_node.SetProjection(proj)          
            rman_sg_camera.sg_node.SetRenderable(True)         

    def _update_render_cam(self, ob, rman_sg_camera):

        r = self.rman_scene.bl_scene.render
        cam = ob.data
        rm = self.rman_scene.bl_scene.renderman
        cam_rm = cam.renderman
        rman_sg_camera.bl_camera = ob

        xaspect, yaspect, aspectratio = _render_get_aspect_(r, cam)

{'fraction_non_alphanumeric': 0.07861158805507862, 'fraction_numerical': 0.00919099080900919, 'mean_word_length': 1.9488732254541845, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7238044', 'n_tokens_mistral': 9780, 'n_tokens_neox': 9377, 'n_words': 1628}