def test_percentage_to_point(self): viewport = Viewport() view_port_pixel = viewport.percentage_to_point(50, 50) self.assertEqual(view_port_pixel.x, 2.5) self.assertEqual(view_port_pixel.y, 2.5) self.assertEqual(view_port_pixel.z, 0.0)
def __init__(self, screen2D=[256, 256], primitives=[] , lights=[] , camerapos=Vector(0, 0, 0), O=Vector(0, 0, 0), U=Vector(0, 0, 0), V=Vector(0, 0, 0)): self.lights = lights self.camerapos = camerapos self.viewportpos = Viewport(O=O, U=U, V=V) self.list_of_primitives = [] self.primitives = primitives self.screen2D = Screen2D(screen2D[0], screen2D[1]) self.size = self.screen2D.image.size # cornell box components triangle_back_1 = Triangle(a= Vector(0, 0, 10), b= Vector(20, 0, 10), c= Vector(0, 20, 10), color= Vector(247, 195, 49)) triangle_right_1 = Triangle(a= Vector(10, 20, 0), b= Vector(10, 0, 20), c= Vector(10, 0, 0), color= Vector(70, 130, 180)) triangle_top_1 = Triangle(a= Vector(0, 10, 0), b= Vector(20, 10, 0), c= Vector(0, 10, 20), color= Vector(176, 224, 230)) triangle_left_1 = Triangle(a= Vector(0, 0, 0), b= Vector(0, 0, 20), c= Vector(0, 20, 0), color= Vector(215, 57, 37)) triangle_bottom_1 = Triangle(a= Vector(0, 0, 0), b= Vector(20, 0, 0), c= Vector(0, 0, 20), color= Vector(205, 205, 201)) for prim in self.primitives: print "prim", prim self.list_of_primitives.append(prim) # appending cornell box componenet to the list_of_primitives self.list_of_primitives.append(triangle_back_1) self.list_of_primitives.append(triangle_right_1) self.list_of_primitives.append(triangle_top_1) self.list_of_primitives.append(triangle_left_1) self.list_of_primitives.append(triangle_bottom_1) #calculate ambient illumination for the point_light self.ambient = self.lights[0].ambient_illumination()
def workArea(screenRect): wArea = Viewport() wArea.setBackgroundBrush(QColor(PV['bgColor'])) wArea.resize(screenRect.width(), screenRect.height()) wArea.setTransformationAnchor(wArea.AnchorUnderMouse) wAreaScene = Scene(QRectF(0.0, 0.0, 1240.0, 720.0), wArea) wArea.setScene(wAreaScene) return wArea
def __init__(self): ''' Constructor ''' # TODO: Replace redraw with an event? Better parallelism? self.__redraw = True # TODO: REMOVE HARD-CODED DIMENSIONS? self.__window = Window(WINX, WINY) self.__viewport = Viewport(WINX, WINY) self.__objects = list() self.__timer = Stopwatch() self.__lastFrameTime = 0.0 self._modifiers = list() Events.RegisterEvent("REDRAW", self.Redraw)
def main(): options = Options() options.ParseCMD(sys.argv) viewport = Viewport() root = Tk() space = Canvas(root, width = viewport.windowSize.x, height = viewport.windowSize.y, bg = "black") space.pack() viewport.AddMouseControl(space) if (options.play): UniPlayer.PlayUniverse(root, space, viewport, options) else: StartUniverse(root, space, viewport, options)
def setupUi(self, SceneWindow): SceneWindow.setObjectName(_fromUtf8("SceneWindow")) SceneWindow.resize(800, 600) self.centralwidget = QtGui.QWidget(SceneWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.gridLayout = QtGui.QGridLayout(self.centralwidget) self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.graphicsView = Viewport(self.centralwidget) self.graphicsView.setMinimumSize(QtCore.QSize(0, 0)) self.graphicsView.setFocusPolicy(QtCore.Qt.NoFocus) self.graphicsView.setFrameShadow(QtGui.QFrame.Plain) self.graphicsView.setObjectName(_fromUtf8("graphicsView")) self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1) SceneWindow.setCentralWidget(self.centralwidget) self.statusbar = QtGui.QStatusBar(SceneWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) SceneWindow.setStatusBar(self.statusbar) self.retranslateUi(SceneWindow) QtCore.QMetaObject.connectSlotsByName(SceneWindow)
class RayTracer(): def __init__(self, screen2D=[256, 256], primitives=[] , lights=[] , camerapos=Vector(0, 0, 0), O=Vector(0, 0, 0), U=Vector(0, 0, 0), V=Vector(0, 0, 0)): self.lights = lights self.camerapos = camerapos self.viewportpos = Viewport(O=O, U=U, V=V) self.list_of_primitives = [] self.primitives = primitives self.screen2D = Screen2D(screen2D[0], screen2D[1]) self.size = self.screen2D.image.size # cornell box components triangle_back_1 = Triangle(a= Vector(0, 0, 10), b= Vector(20, 0, 10), c= Vector(0, 20, 10), color= Vector(247, 195, 49)) triangle_right_1 = Triangle(a= Vector(10, 20, 0), b= Vector(10, 0, 20), c= Vector(10, 0, 0), color= Vector(70, 130, 180)) triangle_top_1 = Triangle(a= Vector(0, 10, 0), b= Vector(20, 10, 0), c= Vector(0, 10, 20), color= Vector(176, 224, 230)) triangle_left_1 = Triangle(a= Vector(0, 0, 0), b= Vector(0, 0, 20), c= Vector(0, 20, 0), color= Vector(215, 57, 37)) triangle_bottom_1 = Triangle(a= Vector(0, 0, 0), b= Vector(20, 0, 0), c= Vector(0, 0, 20), color= Vector(205, 205, 201)) for prim in self.primitives: print "prim", prim self.list_of_primitives.append(prim) # appending cornell box componenet to the list_of_primitives self.list_of_primitives.append(triangle_back_1) self.list_of_primitives.append(triangle_right_1) self.list_of_primitives.append(triangle_top_1) self.list_of_primitives.append(triangle_left_1) self.list_of_primitives.append(triangle_bottom_1) #calculate ambient illumination for the point_light self.ambient = self.lights[0].ambient_illumination() def set_light_pos(self, position=Vector(0, 0, 0)): self.lights = self.lights[0](position=position) return self.lightpos def set_camera_pos(self, position=Vector(0, 0, 0)): self.camerapos = position return self.camerapos def is_in_shadow(self, intersect_point, obj): """ """ #1. calculate ray from intersect point to light source light_intersect_vector = self.lights[0].position.clone().sub(intersect_point) t_ray_light = light_intersect_vector.mag() light_intersect_ray = Ray(origin =intersect_point.clone(), ray_dir= light_intersect_vector.normalize()) #2. determine if ray intersects any OTHER primitives is_intersected = False for test_obj in self.list_of_primitives: if obj != test_obj and test_obj.material != "glass": t = test_obj.get_intersect(light_intersect_ray.origin.clone(), light_intersect_ray.ray_dir.clone()) if t and t < t_ray_light: is_intersected = True break else: is_intersected = False else: continue return is_intersected def illumination(self, ray, normal_vector, intersect_point, surface_color): plane_normal_ray_vec_dot = ray.ray_dir.clone().dot(normal_vector) #l(ray_dir).n (normal_plane) if plane_normal_ray_vec_dot > 1e-6: #if ray and normal vector to the plane are in the same direction (the angle between them is 0) normal_vector.constant_multiply(-1) #change the direction of the ray else: normal_vector.constant_multiply(1) plane_normal_ray_vec_dot = ray.ray_dir.clone().dot(normal_vector) diffuse = self.lights[0].diffuse_illumination(Normal_vector=normal_vector.clone() , point=intersect_point) #calculate diffuse illumination for the point_light add_diffuse_ambient = diffuse.clone().add(self.ambient.clone()) #add diffuse and ambient illumination #rescaling the surface color between 0 and 1, multiplying with diffuse and ambient illumination """ final_color_R = (surface_color.clone().div(255.0)).x * add_diffuse_ambient.x final_color_G = (surface_color.clone().div(255.0)).y * add_diffuse_ambient.y final_color_B = (surface_color.clone().div(255.0)).z * add_diffuse_ambient.z #converting the color scale between 0 and 255 final_color_R = int(math.floor(final_color_R*255)) final_color_G = int(math.floor(final_color_G*255)) final_color_B = int(math.floor(final_color_B*255)) final_color = (final_color_R, final_color_G, final_color_B) return final_color def scene_intersect(self, ray, n_current): intersect_scale_dic = {} num_of_bounces_glass = 0 num_of_bounces_mirror = 0 for obj in self.list_of_primitives: t = obj.get_intersect(ray.origin.clone(), ray.ray_dir.normalize().clone()) if t: intersect_scale_dic[obj] = t if len(intersect_scale_dic) != 0: t_min = min(intersect_scale_dic.itervalues()) intersected_obj = (min(intersect_scale_dic, key=intersect_scale_dic.get)) surface_color = intersected_obj.color intersect_point = ray.origin.clone().add(ray.ray_dir.normalize().clone().constant_multiply(t_min)) normal_vector = intersected_obj.surface_normal(point=intersect_point.clone(), ray_origin=self.camerapos.clone(), ray_dir=ray.ray_dir.normalize().clone()) if intersected_obj.material == "glass" and num_of_bounces_glass <= 200: num_of_bounces_glass += 1 if n_current == "air": nFrom = 1 nTo = 1.5 else: nFrom = 1.5 nTo = 1 ray = ray.refract(nFrom, nTo, intersect_point, normal_vector) ray.origin = ray.origin.clone().add(ray.ray_dir.normalize().clone().constant_multiply(0.001)) if ray.reflect_called == False: if n_current == "air": n_current = "glass" else: n_current = "air" return self.scene_intersect(ray, n_current) if intersected_obj.material == "mirror" and num_of_bounces_mirror <= 200: num_of_bounces_mirror += 1 ray = ray.reflect(intersect_point, normal_vector) ray.origin = ray.origin.clone().add(ray.ray_dir.normalize().clone().constant_multiply(0.001)) return self.scene_intersect(ray, "air") else: # calling is_in_shadow function to check if the intersect point is in shadow or not is_intersected = self.is_in_shadow(intersect_point.clone(), intersected_obj) if is_intersected: return (0, 0, 0) else: # calling illumination function if the intersect_point light_position Ray does not intersects with any other primitives final_color = self.illumination(ray, normal_vector, intersect_point, surface_color) return final_color else: return (0, 0, 0) # @jit def render_image(self, call_back_func_progress_percentage, call_back_func_send_image): """ Two call_back_function is passed to the render_image function where the first one send the percentage progress of rendering image to the front end and the second one send the rendered image to the front end. In order to render image, this function converts the position of pixels in a screen 2D to the correlate pixel positions in the viewport and claculates the ray direction and also color of the picture. """ #looping over the size of the width of screen2D for i in range(self.size[0]): #calculate the percentage of the pixel position corresponding to the width of the screen2D image perc = (float(i+1)/(self.size[0]))*100 if perc == 25 or perc == 50 or perc == 75 or perc == 100: #call back function to send the percentage of the calculation progress to the front end in app.py file call_back_func_progress_percentage(perc) #looping over the height of the image for j in range(self.size[1]): #finding pixel position percentage in the screen2D percentage_pos = self.screen2D.pixel_position_percentage(i, j) #converting pixel position percentage in the screen2D to the correlate pixel position in the viewport view_port_pixel = self.viewportpos.percentage_to_point(percentage_pos[0], percentage_pos[1]) ray_dir = view_port_pixel.sub(self.camerapos.clone()) ray = Ray(self.camerapos.clone(), ray_dir.clone()) #defining a ray color = self.scene_intersect(ray, "air") """ assign the color to the screen2D pixels (x,y) === (0,0) is defined at the bottom left corner of the viewport but at the top left corner or the screen2D. so to avoid rendering the image upside down we need to convert the pixels by having self.size[1] - j - 1 unless we define the viewport as U= vector(-5, 0, 0) and V= vector(0, -5, 0) where we can assign the color to the screen2D.pixels[i, j] = color. """ self.screen2D.pixels[i,self.size[1] - j - 1] = color image = self.screen2D.image call_back_func_send_image(image)
class Display(): ''' classdocs ''' def __init__(self): ''' Constructor ''' # TODO: Replace redraw with an event? Better parallelism? self.__redraw = True # TODO: REMOVE HARD-CODED DIMENSIONS? self.__window = Window(WINX, WINY) self.__viewport = Viewport(WINX, WINY) self.__objects = list() self.__timer = Stopwatch() self.__lastFrameTime = 0.0 self._modifiers = list() Events.RegisterEvent("REDRAW", self.Redraw) def __del__(self): ''' Destructor (Clean up OpenGL) ''' print "Stopping display" def Initialise(self): ''' Initialise settings for the display ''' # Set up the display mode glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) # Set up a default clear colour glClearColor(0.0, 0.0, 0.0, 1.0) # Set up a default point size glPointSize(5.0) # Set up Blending glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_LINE_SMOOTH) # Set up face culling glDisable(GL_CULL_FACE) # Set up the depth buffer glEnable(GL_DEPTH_TEST) # Setup menu - TODO: THIS # GetMain()->m_input->m_popup->CreateMenu(); def Start(self): ''' Start the main display loop ''' glutInit() # Initialise the display settings self.Initialise() # Set up the OpenGL.GLUT window self.__window.Init() # Give OpenGL functions to call for display, input, etc OpenGLStatics.SetupOpenGLStatics() # Ready? # Reeeeady? # Okay. # Hit it. print "Starting display" glutMainLoop() def Draw(self): ''' Main display function ''' # Start timer self.__timer.Reset() # Clear background #HACK - Clear disabled to test frame buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Start up viewports # TODO: ALLOW MORE THAN ONE self.__viewport.Begin() # Set up blend functions for this run (TODO: Pass to object draw code / shaders) #glEnable(GL_BLEND) #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # TODO: REMOVE THIS HACK AND REPLACE WITH PROPER SHADERS glColor4f(1.0,0.0,0.0,0.2) glPointSize(3.0) # Set up modifier for mod in self._modifiers: mod.Init(self) # Begin modifier for mod in self._modifiers: mod.Begin(self) # Draw each object, passing them the camera in case they need it # TODO: Add scene graph object to deal with this? for it in self.__objects: it.Draw(self.__viewport) # Run modifier end actions for mod in self._modifiers: mod.End(self) # Finish up drawing self.__viewport.End() glFlush() glutSwapBuffers() # Don't need to redraw no more self.__redraw = False # Read off draw time self.__lastFrameTime = self.__timer.Time() #print "Frame time: ", self.__lastFrameTime def Idle(self): ''' Is GLUT not doing anything? Do these things! ''' # Check for redraw request and if there's one, do that if self.__redraw: self.Draw() def Redraw(self, dummy=0): ''' Tell the display to redraw its contents the next time it gets a chance Dummy required to allow use as an event-driven function ''' self.__redraw = True def Window(self): ''' Return the display's window object ''' return self.__window def Viewport(self): ''' Return the viewport ''' return self.__viewport def AddObject(self, newObject): ''' Preload and add object to display list ''' # Preload removed as this must happen in an OpenGL context #newObject.Preload() self.__objects.append(newObject) def AddModifier(self, newModifier): ''' Add modifier to display ''' self._modifiers.append(newModifier) def FramesPerSecond(self): ''' Return the current FPS (based on last frame draw time) ''' return 1.0/self.__lastFrameTime
from Viewport import Viewport from Mesh import Mesh import pickle import pygame motion = pickle.load(open("tensor.pickle", "rb")) v = Viewport(disable_mouse=True, w=700, h=600) v.add_object( Mesh(name="cube", primitive_type="cube", pos=[0, 0, -5], color=(0, 0, 255), segments=10)) v.add_object( Mesh(name="cube", primitive_type="cube", pos=[2.5, 0, -5], color=(0, 255, 0), segments=10)) v.add_object( Mesh(name="cube", primitive_type="cube", pos=[-2.5, 0, -5], color=(255, 0, 0), segments=10)) #v.add_object(Mesh(name="Sphere4", primitive_type="uvsphere", pos=[3, 0, 0], segments=10)) #v.add_object(Mesh(namew="Sphere8", primitive_type="uvsphere", pos=[0, 0, 0], segments=8)) #v.add_object(Mesh(name="Sphere12", primitive_type="uvsphere", pos=[-3, 0, 0], segments=12)) #v.add_object(Mesh(name="Sphere16", primitive_type="uvsphere", pos=[-6, 0, 0], segments=16))
def Viewport(self): from Viewport import Viewport return Viewport(self)
def __init__(self, lightpos=Vector(0, 0, 0), camerapos=Vector(0, 0, 0), O=Vector(0, 0, 0), U=Vector(0, 0, 0), V=Vector(0, 0, 0)): self.lightpos = PointLight(position=lightpos) self.camerapos = camerapos self.viewportpos = Viewport(O=O, U=U, V=V) self.list_of_primitives = [] self.screen2D = Screen2D(100, 100) self.size = self.screen2D.image.size self.list_of_primitives = [] # primitives sphere_1 = Sphere(position=Vector(4, 4, -6), radius=1.0, color=Vector(255, 255, 224)) #gray sphere_2 = Sphere(position=Vector(7, 2, -4), radius=1.0, color=Vector(50, 205, 50)) #green sphere_3 = Sphere(position=Vector(2, 2, -3), radius=1.5, color=Vector(255, 255, 255), material="mirror") sphere_4 = Sphere(position=Vector(8, 2, -2), radius=0.5, color=Vector(0, 0, 0), material="mirror") triangle_1 = Triangle(b=Vector(7, 2, -7), a=Vector(6, 5, -7), c=Vector(5, 2, -7), color=Vector(205, 92, 92)) triangle_2 = Triangle(a=Vector(4, 1, -5), b=Vector(5, 4, -5), c=Vector(6, 1, -5), color=Vector(72, 61, 139)) # cornell box components triangle_back_1 = Triangle(a=Vector(1, 1, -8), b=Vector(9, 1, -8), c=Vector(1, 9, -8), color=Vector(255, 215, 0)) triangle_back_2 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, -8), c=Vector(1, 9, -8), color=Vector(255, 215, 0)) triangle_right_1 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, -8), c=Vector(9, 1, 0), color=Vector(205, 205, 201)) triangle_right_2 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, 0), c=Vector(9, 9, 0), color=Vector(205, 205, 201)) triangle_top_1 = Triangle(a=Vector(1, 9, -8), b=Vector(9, 9, -8), c=Vector(1, 9, 0), color=Vector(176, 224, 230)) triangle_top_2 = Triangle(a=Vector(1, 9, 0), b=Vector(9, 9, 0), c=Vector(9, 9, -8), color=Vector(176, 224, 230)) triangle_left_1 = Triangle(a=Vector(1, 1, -8), b=Vector(1, 9, -8), c=Vector(1, 1, 0), color=Vector(255, 69, 0)) triangle_left_2 = Triangle(a=Vector(1, 1, 0), b=Vector(1, 9, -8), c=Vector(1, 9, 0), color=Vector(255, 69, 0)) triangle_bottom_1 = Triangle(a=Vector(1, 1, -8), b=Vector(9, 1, -8), c=Vector(1, 1, 0), color=Vector(70, 130, 180), material="mirror") triangle_bottom_2 = Triangle(a=Vector(1, 1, 0), b=Vector(9, 1, 0), c=Vector(9, 1, -8), color=Vector(70, 130, 180), material="mirror") # appending the objects in the scene to a list (list_of_primtives) self.list_of_primitives.append(sphere_1) self.list_of_primitives.append(sphere_2) self.list_of_primitives.append(sphere_3) self.list_of_primitives.append(sphere_4) self.list_of_primitives.append(triangle_1) self.list_of_primitives.append(triangle_2) # appending cornell box componenet to the list_of_primitives self.list_of_primitives.append(triangle_back_1) self.list_of_primitives.append(triangle_back_2) self.list_of_primitives.append(triangle_right_1) self.list_of_primitives.append(triangle_right_2) self.list_of_primitives.append(triangle_top_1) self.list_of_primitives.append(triangle_top_2) self.list_of_primitives.append(triangle_left_1) self.list_of_primitives.append(triangle_left_2) self.list_of_primitives.append(triangle_bottom_1) self.list_of_primitives.append(triangle_bottom_2) #calculate ambient illumination for the point_light self.ambient = self.lightpos.ambient_illumination()
class RayTracer(): def __init__(self, lightpos=Vector(0, 0, 0), camerapos=Vector(0, 0, 0), O=Vector(0, 0, 0), U=Vector(0, 0, 0), V=Vector(0, 0, 0)): self.lightpos = PointLight(position=lightpos) self.camerapos = camerapos self.viewportpos = Viewport(O=O, U=U, V=V) self.list_of_primitives = [] self.screen2D = Screen2D(100, 100) self.size = self.screen2D.image.size self.list_of_primitives = [] # primitives sphere_1 = Sphere(position=Vector(4, 4, -6), radius=1.0, color=Vector(255, 255, 224)) #gray sphere_2 = Sphere(position=Vector(7, 2, -4), radius=1.0, color=Vector(50, 205, 50)) #green sphere_3 = Sphere(position=Vector(2, 2, -3), radius=1.5, color=Vector(255, 255, 255), material="mirror") sphere_4 = Sphere(position=Vector(8, 2, -2), radius=0.5, color=Vector(0, 0, 0), material="mirror") triangle_1 = Triangle(b=Vector(7, 2, -7), a=Vector(6, 5, -7), c=Vector(5, 2, -7), color=Vector(205, 92, 92)) triangle_2 = Triangle(a=Vector(4, 1, -5), b=Vector(5, 4, -5), c=Vector(6, 1, -5), color=Vector(72, 61, 139)) # cornell box components triangle_back_1 = Triangle(a=Vector(1, 1, -8), b=Vector(9, 1, -8), c=Vector(1, 9, -8), color=Vector(255, 215, 0)) triangle_back_2 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, -8), c=Vector(1, 9, -8), color=Vector(255, 215, 0)) triangle_right_1 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, -8), c=Vector(9, 1, 0), color=Vector(205, 205, 201)) triangle_right_2 = Triangle(a=Vector(9, 9, -8), b=Vector(9, 1, 0), c=Vector(9, 9, 0), color=Vector(205, 205, 201)) triangle_top_1 = Triangle(a=Vector(1, 9, -8), b=Vector(9, 9, -8), c=Vector(1, 9, 0), color=Vector(176, 224, 230)) triangle_top_2 = Triangle(a=Vector(1, 9, 0), b=Vector(9, 9, 0), c=Vector(9, 9, -8), color=Vector(176, 224, 230)) triangle_left_1 = Triangle(a=Vector(1, 1, -8), b=Vector(1, 9, -8), c=Vector(1, 1, 0), color=Vector(255, 69, 0)) triangle_left_2 = Triangle(a=Vector(1, 1, 0), b=Vector(1, 9, -8), c=Vector(1, 9, 0), color=Vector(255, 69, 0)) triangle_bottom_1 = Triangle(a=Vector(1, 1, -8), b=Vector(9, 1, -8), c=Vector(1, 1, 0), color=Vector(70, 130, 180), material="mirror") triangle_bottom_2 = Triangle(a=Vector(1, 1, 0), b=Vector(9, 1, 0), c=Vector(9, 1, -8), color=Vector(70, 130, 180), material="mirror") # appending the objects in the scene to a list (list_of_primtives) self.list_of_primitives.append(sphere_1) self.list_of_primitives.append(sphere_2) self.list_of_primitives.append(sphere_3) self.list_of_primitives.append(sphere_4) self.list_of_primitives.append(triangle_1) self.list_of_primitives.append(triangle_2) # appending cornell box componenet to the list_of_primitives self.list_of_primitives.append(triangle_back_1) self.list_of_primitives.append(triangle_back_2) self.list_of_primitives.append(triangle_right_1) self.list_of_primitives.append(triangle_right_2) self.list_of_primitives.append(triangle_top_1) self.list_of_primitives.append(triangle_top_2) self.list_of_primitives.append(triangle_left_1) self.list_of_primitives.append(triangle_left_2) self.list_of_primitives.append(triangle_bottom_1) self.list_of_primitives.append(triangle_bottom_2) #calculate ambient illumination for the point_light self.ambient = self.lightpos.ambient_illumination() def set_light_pos(self, position=Vector(0, 0, 0)): self.lightpos = PointLight(position=position) return self.lightpos def set_camera_pos(self, position=Vector(0, 0, 0)): self.camerapos = position return self.camerapos def is_in_shadow(self, intersect_point, obj): #1. calculate ray from intersect point to light source light_intersect_vector = self.lightpos.position.clone().sub( intersect_point) t_ray_light = light_intersect_vector.mag() light_intersect_ray = Ray(origin=intersect_point.clone(), ray_dir=light_intersect_vector.normalize()) #2. determine if ray intersects any OTHER primitives is_intersected = False for test_obj in self.list_of_primitives: if obj != test_obj: t = test_obj.get_intersect(light_intersect_ray.origin.clone(), light_intersect_ray.ray_dir.clone()) if t and t < t_ray_light: is_intersected = True break else: is_intersected = False else: continue return is_intersected def illumination(self, ray, normal_vector, intersect_point, surface_color): plane_normal_ray_vec_dot = ray.ray_dir.clone().dot( normal_vector) #l(ray_dir).n (normal_plane) if plane_normal_ray_vec_dot > 1e-6: #if ray and normal vector to the plane are in the same direction (the angle between them is 0) normal_vector.constant_multiply( -1) #change the direction of the ray else: normal_vector.constant_multiply(1) plane_normal_ray_vec_dot = ray.ray_dir.clone().dot(normal_vector) diffuse = self.lightpos.diffuse_illumination( Normal_vector=normal_vector.clone(), point=intersect_point ) #calculate diffuse illumination for the point_light add_diffuse_ambient = diffuse.clone().add( self.ambient.clone()) #add diffuse and ambient illumination #rescaling the surface color between 0 and 1, multiplying with diffuse and ambient illumination """ final_color_R = ( surface_color.clone().div(255.0)).x * add_diffuse_ambient.x final_color_G = ( surface_color.clone().div(255.0)).y * add_diffuse_ambient.y final_color_B = ( surface_color.clone().div(255.0)).z * add_diffuse_ambient.z #converting the color scale between 0 and 255 final_color_R = int(math.floor(final_color_R * 255)) final_color_G = int(math.floor(final_color_G * 255)) final_color_B = int(math.floor(final_color_B * 255)) final_color = (final_color_R, final_color_G, final_color_B) return final_color def scene_intersect(self, ray): intersect_scale_dic = {} num_of_bounces = 0 for obj in self.list_of_primitives: t = obj.get_intersect(ray.origin.clone(), ray.ray_dir.clone()) if t: intersect_scale_dic[obj] = t if len(intersect_scale_dic) != 0: t_min = min(intersect_scale_dic.itervalues()) intersected_obj = (min(intersect_scale_dic, key=intersect_scale_dic.get)) surface_color = intersected_obj.color intersect_point = ray.origin.clone().add( ray.ray_dir.clone().constant_multiply(t_min)) normal_vector = intersected_obj.surface_normal( point=intersect_point.clone(), ray_origin=self.camerapos.clone(), ray_dir=ray.ray_dir.clone()) if intersected_obj.material == "mirror" and num_of_bounces <= 100: num_of_bounces += 1 def_ray_dir = ray.ray_dir.constant_multiply( -1).clone().reflected_ray_dir(normal_vector.clone()) intersect_point = intersect_point.clone().add( def_ray_dir.normalize().clone().constant_multiply(0.001)) def_ray = Ray(origin=intersect_point.clone(), ray_dir=def_ray_dir.clone()) return self.scene_intersect(def_ray) else: # calling is_in_shadow function to check if the intersect point is in shadow or not is_intersected = self.is_in_shadow(intersect_point.clone(), intersected_obj) if is_intersected: return (0, 0, 0) else: # calling illumination function if the intersect_point light_position Ray does not intersects with any other primitives final_color = self.illumination(ray, normal_vector, intersect_point, surface_color) return final_color else: return (0, 0, 0) def render_image(self): """ converting the position of pixels in a screen 2D to the correlate pixel positions in the viewport """ for i in range(self.size[0]): for j in range(self.size[1]): percentage_pos = self.screen2D.pixel_position_percentage( i, j) #finding pixel position percentage in the screen2D view_port_pixel = self.viewportpos.percentage_to_point( percentage_pos[0], percentage_pos[1] ) #converting pixel position percentage in the screen2D to the correlate pixel position in the viewport ray_dir = view_port_pixel.sub(self.camerapos.clone()) ray = Ray(self.camerapos.clone(), ray_dir.clone()) #defining a ray color = self.scene_intersect(ray) """ assign the color to the screen2D pixels """ self.screen2D.pixels[i, self.size[1] - j - 1] = color self.screen2D.image.show()