Beispiel #1
0
    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)
Beispiel #2
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()
Beispiel #3
0
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
Beispiel #4
0
 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)
Beispiel #5
0
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)
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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))
Beispiel #11
0
 def Viewport(self):
     from Viewport import Viewport
     return Viewport(self)
Beispiel #12
0
    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()
Beispiel #13
0
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()