# class and helper function for scene definition
import numpy as np
from read_helper import *

class Scene:

    @staticmethod
    def norm_vec(vec):
        return vec / np.linalg.norm(vec)

    def __init__(self):
        # basic setup
        self.width = 0
        self.height = 0
        self.max_depth = 5
        self.output_name = 'ray_tracing.png'
        
        # default attenuation
        self.light_attenu = np.array([1.0, 0.0, 0.0])        

        # elements of the scene
        self.camera = {}
        self.lights = []
        self.vertices = []
        self.spheres = []
        self.triangles = []        
        
    def cam_init(self, input):
        input = [float(coor) for coor in input]
        camera = {}

        cam_from = np.array(input[0:3])
        camera['loc'] = cam_from

        cam_at = np.array(input[3:6])
        cam_up = np.array(input[6:9])

        camera['fovy'] = input[-1]
        camera['fovy_rad'] = camera['fovy'] / 180.0 * np.pi

        camera['fovx_rad'] = 2 * np.arctan(np.tan(camera['fovy_rad'] / 2) * self.width / self.height)
        camera['fovx'] = camera['fovx_rad'] / np.pi * 180.0

        # camera in the -z direction
        camera['dir'] = self.norm_vec(cam_from - cam_at)        

        # construct coordinate frame
        camera['u'] = self.norm_vec(np.cross(cam_up, camera['dir']))
        camera['v'] = self.norm_vec(np.cross(camera['dir'], camera['u']))

        self.camera = camera

    def triangle_init(self, input, mtx, material):
        # apply transformation to the triangle vertice
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:3] for index in input]
        
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], vertices[0] - vertices[2]))        

        triangle = {'A':vertices[0], 'B':vertices[1], 'C': vertices[2], \
            'transform':np.linalg.inv(mtx), 'surface':normal_vec, **material}

        self.triangles.append(triangle)

    def sphere_init(self, input, mtx, material):
        sphere = {'loc':np.array(input[0:3]), 'radius':input[-1], 'transform':np.linalg.inv(mtx), **material}
        self.spheres.append(sphere)


class SceneReader:
    
    # class interpreter map
    def_mapping = {'size':def_size, 'camera':def_cam, 'maxdepth':def_depth, 'output':def_filename, \
        'directional':def_dirlight, 'point':def_ptlight, 'pushTransform':def_push, 'popTransform':def_pop, \
        'translate':def_translate, 'rotate':def_rotation, 'scale':def_scale, 'sphere': def_sphere, \
        'tri':def_triangle, 'vertex':def_vertex, 'attenuation':def_attenuation, 'transparent': def_trans}
    
    def __init__(self, file_name):
        # assume scene file is in current dir
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]

        self.material = {'ambient':0.2*np.ones(3), 'diffuse':np.zeros(3), 'specular':np.zeros(3), \
                        'emission':np.zeros(3), 'shininess':np.array(0.0)}
        
        self.scene = Scene()
        
    def read_file(self, file_name = None):
        if file_name is None:            
            file_name = self.file_name

        scene_def = open(file_name, 'r')
        
        print('Load Scene Config')
        for line in scene_def:            
            if len(line) <= 1 or line[0] == "#":
                continue

            arg_list = line.split()
            arg_key = arg_list[0]

            if arg_key in self.def_mapping.keys():                
                self.def_mapping[arg_key](arg_list[1:], self)

            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in arg_list[1:]])

        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene
        
503f07d811d69aa17f375d7a53404dce1ebacd07
<mask token>


class Scene:
    <mask token>
    <mask token>
    <mask token>

    def triangle_init(self, input, mtx, material):
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:
            3] for index in input]
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], 
            vertices[0] - vertices[2]))
        triangle = {'A': vertices[0], 'B': vertices[1], 'C': vertices[2],
            'transform': np.linalg.inv(mtx), 'surface': normal_vec, **material}
        self.triangles.append(triangle)
    <mask token>


class SceneReader:
    def_mapping = {'size': def_size, 'camera': def_cam, 'maxdepth':
        def_depth, 'output': def_filename, 'directional': def_dirlight,
        'point': def_ptlight, 'pushTransform': def_push, 'popTransform':
        def_pop, 'translate': def_translate, 'rotate': def_rotation,
        'scale': def_scale, 'sphere': def_sphere, 'tri': def_triangle,
        'vertex': def_vertex, 'attenuation': def_attenuation, 'transparent':
        def_trans}

    def __init__(self, file_name):
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]
        self.material = {'ambient': 0.2 * np.ones(3), 'diffuse': np.zeros(3
            ), 'specular': np.zeros(3), 'emission': np.zeros(3),
            'shininess': np.array(0.0)}
        self.scene = Scene()

    def read_file(self, file_name=None):
        if file_name is None:
            file_name = self.file_name
        scene_def = open(file_name, 'r')
        print('Load Scene Config')
        for line in scene_def:
            if len(line) <= 1 or line[0] == '#':
                continue
            arg_list = line.split()
            arg_key = arg_list[0]
            if arg_key in self.def_mapping.keys():
                self.def_mapping[arg_key](arg_list[1:], self)
            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in
                    arg_list[1:]])
        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene

<mask token>


class Scene:
    <mask token>

    def __init__(self):
        self.width = 0
        self.height = 0
        self.max_depth = 5
        self.output_name = 'ray_tracing.png'
        self.light_attenu = np.array([1.0, 0.0, 0.0])
        self.camera = {}
        self.lights = []
        self.vertices = []
        self.spheres = []
        self.triangles = []
    <mask token>

    def triangle_init(self, input, mtx, material):
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:
            3] for index in input]
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], 
            vertices[0] - vertices[2]))
        triangle = {'A': vertices[0], 'B': vertices[1], 'C': vertices[2],
            'transform': np.linalg.inv(mtx), 'surface': normal_vec, **material}
        self.triangles.append(triangle)
    <mask token>


class SceneReader:
    def_mapping = {'size': def_size, 'camera': def_cam, 'maxdepth':
        def_depth, 'output': def_filename, 'directional': def_dirlight,
        'point': def_ptlight, 'pushTransform': def_push, 'popTransform':
        def_pop, 'translate': def_translate, 'rotate': def_rotation,
        'scale': def_scale, 'sphere': def_sphere, 'tri': def_triangle,
        'vertex': def_vertex, 'attenuation': def_attenuation, 'transparent':
        def_trans}

    def __init__(self, file_name):
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]
        self.material = {'ambient': 0.2 * np.ones(3), 'diffuse': np.zeros(3
            ), 'specular': np.zeros(3), 'emission': np.zeros(3),
            'shininess': np.array(0.0)}
        self.scene = Scene()

    def read_file(self, file_name=None):
        if file_name is None:
            file_name = self.file_name
        scene_def = open(file_name, 'r')
        print('Load Scene Config')
        for line in scene_def:
            if len(line) <= 1 or line[0] == '#':
                continue
            arg_list = line.split()
            arg_key = arg_list[0]
            if arg_key in self.def_mapping.keys():
                self.def_mapping[arg_key](arg_list[1:], self)
            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in
                    arg_list[1:]])
        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene

<mask token>


class Scene:
    <mask token>

    def __init__(self):
        self.width = 0
        self.height = 0
        self.max_depth = 5
        self.output_name = 'ray_tracing.png'
        self.light_attenu = np.array([1.0, 0.0, 0.0])
        self.camera = {}
        self.lights = []
        self.vertices = []
        self.spheres = []
        self.triangles = []

    def cam_init(self, input):
        input = [float(coor) for coor in input]
        camera = {}
        cam_from = np.array(input[0:3])
        camera['loc'] = cam_from
        cam_at = np.array(input[3:6])
        cam_up = np.array(input[6:9])
        camera['fovy'] = input[-1]
        camera['fovy_rad'] = camera['fovy'] / 180.0 * np.pi
        camera['fovx_rad'] = 2 * np.arctan(np.tan(camera['fovy_rad'] / 2) *
            self.width / self.height)
        camera['fovx'] = camera['fovx_rad'] / np.pi * 180.0
        camera['dir'] = self.norm_vec(cam_from - cam_at)
        camera['u'] = self.norm_vec(np.cross(cam_up, camera['dir']))
        camera['v'] = self.norm_vec(np.cross(camera['dir'], camera['u']))
        self.camera = camera

    def triangle_init(self, input, mtx, material):
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:
            3] for index in input]
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], 
            vertices[0] - vertices[2]))
        triangle = {'A': vertices[0], 'B': vertices[1], 'C': vertices[2],
            'transform': np.linalg.inv(mtx), 'surface': normal_vec, **material}
        self.triangles.append(triangle)
    <mask token>


class SceneReader:
    def_mapping = {'size': def_size, 'camera': def_cam, 'maxdepth':
        def_depth, 'output': def_filename, 'directional': def_dirlight,
        'point': def_ptlight, 'pushTransform': def_push, 'popTransform':
        def_pop, 'translate': def_translate, 'rotate': def_rotation,
        'scale': def_scale, 'sphere': def_sphere, 'tri': def_triangle,
        'vertex': def_vertex, 'attenuation': def_attenuation, 'transparent':
        def_trans}

    def __init__(self, file_name):
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]
        self.material = {'ambient': 0.2 * np.ones(3), 'diffuse': np.zeros(3
            ), 'specular': np.zeros(3), 'emission': np.zeros(3),
            'shininess': np.array(0.0)}
        self.scene = Scene()

    def read_file(self, file_name=None):
        if file_name is None:
            file_name = self.file_name
        scene_def = open(file_name, 'r')
        print('Load Scene Config')
        for line in scene_def:
            if len(line) <= 1 or line[0] == '#':
                continue
            arg_list = line.split()
            arg_key = arg_list[0]
            if arg_key in self.def_mapping.keys():
                self.def_mapping[arg_key](arg_list[1:], self)
            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in
                    arg_list[1:]])
        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene

<mask token>


class Scene:

    @staticmethod
    def norm_vec(vec):
        return vec / np.linalg.norm(vec)

    def __init__(self):
        self.width = 0
        self.height = 0
        self.max_depth = 5
        self.output_name = 'ray_tracing.png'
        self.light_attenu = np.array([1.0, 0.0, 0.0])
        self.camera = {}
        self.lights = []
        self.vertices = []
        self.spheres = []
        self.triangles = []

    def cam_init(self, input):
        input = [float(coor) for coor in input]
        camera = {}
        cam_from = np.array(input[0:3])
        camera['loc'] = cam_from
        cam_at = np.array(input[3:6])
        cam_up = np.array(input[6:9])
        camera['fovy'] = input[-1]
        camera['fovy_rad'] = camera['fovy'] / 180.0 * np.pi
        camera['fovx_rad'] = 2 * np.arctan(np.tan(camera['fovy_rad'] / 2) *
            self.width / self.height)
        camera['fovx'] = camera['fovx_rad'] / np.pi * 180.0
        camera['dir'] = self.norm_vec(cam_from - cam_at)
        camera['u'] = self.norm_vec(np.cross(cam_up, camera['dir']))
        camera['v'] = self.norm_vec(np.cross(camera['dir'], camera['u']))
        self.camera = camera

    def triangle_init(self, input, mtx, material):
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:
            3] for index in input]
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], 
            vertices[0] - vertices[2]))
        triangle = {'A': vertices[0], 'B': vertices[1], 'C': vertices[2],
            'transform': np.linalg.inv(mtx), 'surface': normal_vec, **material}
        self.triangles.append(triangle)

    def sphere_init(self, input, mtx, material):
        sphere = {'loc': np.array(input[0:3]), 'radius': input[-1],
            'transform': np.linalg.inv(mtx), **material}
        self.spheres.append(sphere)


class SceneReader:
    def_mapping = {'size': def_size, 'camera': def_cam, 'maxdepth':
        def_depth, 'output': def_filename, 'directional': def_dirlight,
        'point': def_ptlight, 'pushTransform': def_push, 'popTransform':
        def_pop, 'translate': def_translate, 'rotate': def_rotation,
        'scale': def_scale, 'sphere': def_sphere, 'tri': def_triangle,
        'vertex': def_vertex, 'attenuation': def_attenuation, 'transparent':
        def_trans}

    def __init__(self, file_name):
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]
        self.material = {'ambient': 0.2 * np.ones(3), 'diffuse': np.zeros(3
            ), 'specular': np.zeros(3), 'emission': np.zeros(3),
            'shininess': np.array(0.0)}
        self.scene = Scene()

    def read_file(self, file_name=None):
        if file_name is None:
            file_name = self.file_name
        scene_def = open(file_name, 'r')
        print('Load Scene Config')
        for line in scene_def:
            if len(line) <= 1 or line[0] == '#':
                continue
            arg_list = line.split()
            arg_key = arg_list[0]
            if arg_key in self.def_mapping.keys():
                self.def_mapping[arg_key](arg_list[1:], self)
            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in
                    arg_list[1:]])
        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene

# class and helper function for scene definition
import numpy as np
from read_helper import *

class Scene:

    @staticmethod
    def norm_vec(vec):
        return vec / np.linalg.norm(vec)

    def __init__(self):
        # basic setup
        self.width = 0
        self.height = 0
        self.max_depth = 5
        self.output_name = 'ray_tracing.png'
        
        # default attenuation
        self.light_attenu = np.array([1.0, 0.0, 0.0])        

        # elements of the scene
        self.camera = {}
        self.lights = []
        self.vertices = []
        self.spheres = []
        self.triangles = []        
        
    def cam_init(self, input):
        input = [float(coor) for coor in input]
        camera = {}

        cam_from = np.array(input[0:3])
        camera['loc'] = cam_from

        cam_at = np.array(input[3:6])
        cam_up = np.array(input[6:9])

        camera['fovy'] = input[-1]
        camera['fovy_rad'] = camera['fovy'] / 180.0 * np.pi

        camera['fovx_rad'] = 2 * np.arctan(np.tan(camera['fovy_rad'] / 2) * self.width / self.height)
        camera['fovx'] = camera['fovx_rad'] / np.pi * 180.0

        # camera in the -z direction
        camera['dir'] = self.norm_vec(cam_from - cam_at)        

        # construct coordinate frame
        camera['u'] = self.norm_vec(np.cross(cam_up, camera['dir']))
        camera['v'] = self.norm_vec(np.cross(camera['dir'], camera['u']))

        self.camera = camera

    def triangle_init(self, input, mtx, material):
        # apply transformation to the triangle vertice
        vertices = [(mtx @ np.append(np.array(self.vertices[index]), 1))[0:3] for index in input]
        
        normal_vec = self.norm_vec(np.cross(vertices[0] - vertices[1], vertices[0] - vertices[2]))        

        triangle = {'A':vertices[0], 'B':vertices[1], 'C': vertices[2], \
            'transform':np.linalg.inv(mtx), 'surface':normal_vec, **material}

        self.triangles.append(triangle)

    def sphere_init(self, input, mtx, material):
        sphere = {'loc':np.array(input[0:3]), 'radius':input[-1], 'transform':np.linalg.inv(mtx), **material}
        self.spheres.append(sphere)


class SceneReader:
    
    # class interpreter map
    def_mapping = {'size':def_size, 'camera':def_cam, 'maxdepth':def_depth, 'output':def_filename, \
        'directional':def_dirlight, 'point':def_ptlight, 'pushTransform':def_push, 'popTransform':def_pop, \
        'translate':def_translate, 'rotate':def_rotation, 'scale':def_scale, 'sphere': def_sphere, \
        'tri':def_triangle, 'vertex':def_vertex, 'attenuation':def_attenuation, 'transparent': def_trans}
    
    def __init__(self, file_name):
        # assume scene file is in current dir
        self.file_name = './' + file_name
        self.transform = [np.eye(4)]

        self.material = {'ambient':0.2*np.ones(3), 'diffuse':np.zeros(3), 'specular':np.zeros(3), \
                        'emission':np.zeros(3), 'shininess':np.array(0.0)}
        
        self.scene = Scene()
        
    def read_file(self, file_name = None):
        if file_name is None:            
            file_name = self.file_name

        scene_def = open(file_name, 'r')
        
        print('Load Scene Config')
        for line in scene_def:            
            if len(line) <= 1 or line[0] == "#":
                continue

            arg_list = line.split()
            arg_key = arg_list[0]

            if arg_key in self.def_mapping.keys():                
                self.def_mapping[arg_key](arg_list[1:], self)

            elif arg_key in self.material.keys():
                self.material[arg_key] = np.array([float(val) for val in arg_list[1:]])

        scene_def.close()
        self.scene.vertices = np.array(self.scene.vertices).T
        return self.scene
        