예제 #1
0
파일: main.py 프로젝트: Doormatty/pyTrace
def can_see(point, object):
    cast_ray = Ray()
    cast_ray.o = point
    cast_ray.d = Vector3D(-260, -100, 0)
    cast_ray.d = cast_ray.d.normalize()
    hit = False
    for thing in World:
        intersection = thing.hit(cast_ray)
        #if it's not False, it hit something.
        if intersection != False:
            #is this the first time we've hit something?
            if hit == False:
                hit = True
                hit_distance = cast_ray.o.distance(intersection.hit_point)
                closest_object = intersection
            else:
                #check if the latest hit is closer
                if cast_ray.o.distance(intersection.hit_point) < hit_distance:
                    closest_object = intersection
                    hit_distance = cast_ray.o.distance(intersection.hit_point)
    if hit == False:
        return False
    else:
        if closest_object == object:
            return True
        else:
            return False
예제 #2
0
    def render_scene(self,objects,lights,res):
        #create a viewport and image
        v = ViewPort(res[0],res[1])
        im = Image.new("RGB",(v.w,v.h))
        pix = im.load()

        #define a ray
        #FIX BUG -- STILL ORTHO
        ray = Ray(np.array([0,0,0]),np.array([0,0,-1]))

        # Perform perspective ray-tracing
        print("...generating "+str(v)+" image")
        for col in range(v.w):
            for row in range(v.h):
                color = np.zeros(3)
                print(color)
                ray.o = v.getPixelCenter(col,row)
                for s in objects:
                    t = s.intersectRay(ray)
                    if (t != None):
                        xp = ray.getPoint(t)
                        for light in lights:
                            color+= phongShader(xp,s.getNormal(xp),s.material,light,self.eye)
                            print(color)
                        #pix[col,v.h-1-row] = color
                        pix[col,v.h-1-row]=(1,1,1)   
        # Show the image in a window
        im.show()
예제 #3
0
파일: Scene.py 프로젝트: danhp/socs
  def get_visible_lights(self, isect):
      '''
      isect is variable of type IntersectionResult. isect.p contains the
      intersection point. This function should return a python list containing
      all the lights that are "visible" from isect.p position. A light source
      is visible if there are no objects between the point and the light source.
      All light sources are of type Light (Light class is defined in HelperClasses.py).
      The light sources in the scene is stored in the variable Scene.lights
      (accessed using self.lights). Your returned list should be a subset
      of self.lights
      '''

      #you need to loop over the lights and return those that are visible from the position in result
      visibleLights = []
      #====== BEGIN SOLUTION =====
      for l in self.lights:
          ray = Ray()
          ray.eyePoint = isect.p
          ray.viewDirection = GT.normalize(l.pointFrom - ray.eyePoint)

          d = np.linalg.norm(l.pointFrom - ray.eyePoint)
          i = self.get_nearest_object_intersection(ray)

          if i.material is None or i.t >= d - 1e-9:
              visibleLights.append(l)
      # ===== END SOLUTION HERE =====
      return visibleLights
예제 #4
0
파일: Scene.py 프로젝트: danhp/socs
  def create_ray(self,row,col):
      '''
      Create ray (i.e. origin and direction) from a pixel specified by (row, col).
      The ray originates at the camera's eye and goes through the point in space
      that corresponds to the image pixel coordinate (row, col). Take a look at
      the Camera class to see the variables that can be used here.
      '''
      ray = Ray() # construct an empty ray
      '''
      The ray origin is set in this starter code. You need to compute and set
      the ray.viewDirection variable inside the solution block below.
      Note: GeomTransform.py implements a function called normalize for
      normalizing vectors (with appropriate check for division by zero).
      For a vector v, you can get the normalized vector as:
      normalized_v = GT.normalize(v)
      '''
      cam = self.render.camera # use a local variable to save some typing
      ray.eyePoint = cam.pointFrom # origin of the ray

      # ====== BEGIN SOLUTION ======
      dx = col / cam.imageWidth
      dy = row / cam.imageHeight

      stepx = dx * (cam.right - cam.left)
      stepy = dy * (cam.top - cam.bottom)

      ray.viewDirection = GT.normalize(cam.lookat + [cam.left + stepx, cam.top - stepy, 0])
      # ====== END SOLUTION =======
      return ray
예제 #5
0
	def getReflectedNormal(self, ray, t):
		p = Point(*(ray.d.scale(t)).v )+ray.o
		normal = self.normal
		
		rr = Ray()
		
		rr.o=p
		
		rr.d = ray.d - normal.scale(2*ray.d.dot(normal))
		rr.d=Vector(*rr.d.v)
		return rr, normal
예제 #6
0
	def getReflectedNormal(self, ray, t):
		# need to find the point, then find normal at point
		#then get reflected ray, origin=pt
		p = Point(*(ray.d.scale(t)).v )+ray.o
		normal = Vector(*(p-self.origin).v)
		
		normal.normalize()
		
		rr = Ray()
		
		rr.o=p
		
		rr.d = ray.d - normal.scale(2*ray.d.dot(normal))
		rr.d=Vector(*rr.d.v)
		return rr, normal
예제 #7
0
파일: Scene.py 프로젝트: slflmm/RayTracer
  def create_ray(self,row,col):
      ''' 
      Create ray (i.e. origin and direction) from a pixel specified by (row, col).
      The ray originates at the camera's eye and goes through the point in space
      that corresponds to the image pixel coordinate (row, col). Take a look at
      the Camera class to see the variables that can be used here.
      '''
      ray = Ray() # construct an empty ray
      '''
      The ray origin is set in this starter code. You need to compute and set
      the ray.viewDirection variable inside the solution block below.
      Note: GeomTransform.py implements a function called normalize for 
      normalizing vectors (with appropriate check for division by zero). 
      For a vector v, you can get the normalized vector as:
      normalized_v = GT.normalize(v)
      '''
      cam = self.render.camera # use a local variable to save some typing
      ray.eyePoint = cam.pointFrom # origin of the ray

      #TODO ====== BEGIN SOLUTION ======

      # get the camera coordinates
      cam_x = col*(cam.right-cam.left)/cam.imageWidth + cam.left
      cam_y = row*-(cam.top-cam.bottom)/cam.imageHeight + cam.top
      cam_z = cam.near

      xa = cam.cameraXAxis
      ya = cam.cameraYAxis
      za = cam.cameraZAxis
      R = [ [xa[0], ya[0], za[0], 0],
            [xa[1], ya[1], za[1], 0],
            [xa[2], ya[2], za[2], 0],
            [0, 0, 0, 1] ]
      T = [ [1, 0, 0, -cam.pointFrom[0]], 
            [0, 1, 0, -cam.pointFrom[1]],
            [0, 0, 1, -cam.pointFrom[2]],
            [0, 0, 0, 1] ]

      cam_to_world = np.linalg.inv(np.dot(np.transpose(R),T))

      world_pixels = np.dot( cam_to_world, [cam_x, cam_y, cam_z, 1] )
      #world_pixels = world_pixels/world_pixels[3]
      ray.viewDirection = GT.normalize(world_pixels[0:3] - ray.eyePoint)

      # ===== END SOLUTION =====
      return ray    
예제 #8
0
파일: main.py 프로젝트: Doormatty/pyTrace
def raytrace(cast_ray, r = recurse):
    hit = False
    for thing in World:
        intersection = thing.hit(cast_ray)
        #if it's not False, it hit something.
        if intersection != False:
            #is this the first time we've hit something?
            if hit == False:
                hit = True
                hit_distance = cast_ray.o.distance(intersection.hit_point)
                closest_object = intersection
            else:
                #check if the latest hit is closer
                if cast_ray.o.distance(intersection.hit_point) < hit_distance:
                    closest_object = intersection
                    hit_distance = cast_ray.o.distance(intersection.hit_point)
    if hit == False:
        return background_color
    else:
        # At this point, closest_object[4] contains the closest item the ray intersects with.
        #Check for end of recursion
        if r == 1:
            #Now we apply lighting
            
            lit_color = lighting(closest_object)
            return RGB(1, 1, 1)
            return lit_color
        
        #Check for Reflectance
        if closest_object.object.mat.reflect > 0:
            reflect_ray = Ray()
            reflect_ray.o = closest_object.hit_point
            c1 = 0 - (closest_object.normal * cast_ray.d)
            reflect_ray.d = cast_ray.d + (2 * closest_object.normal * c1)
            reflect_ray.d = reflect_ray.d.normalize()
            reflect_color = raytrace(reflect_ray, r - 1)
            
            tcolor = lighting(closest_object)
            tcolor = tcolor + (reflect_color * closest_object.object.mat.reflect)
            return tcolor
        else:
            # The object isn't reflective.
            lit_color = lighting(closest_object)
            return lit_color
예제 #9
0
파일: main.py 프로젝트: Doormatty/pyTrace
def Render():
    pygame.init()
    windowSurfaceObj = pygame.display.set_mode((xres, yres))
    pygame.display.set_caption("Matt's Ray Tracer")
    pixArr = pygame.PixelArray(windowSurfaceObj)
    tRay = Ray()
    tRay.d = Vector3D(0, 0, -1)
    #Hardcoded Viewport for now
    tRay.o.z = Viewportz
    starttime = time.time() 
    
       
    for y in range(yres):
        for event in pygame.event.get():
            if event.type == QUIT:
                filename = datetime.datetime.strftime(datetime.datetime.now(), "%H.%M.%S_%d-%b-%Y") + '.png'
                pygame.image.save(windowSurfaceObj, filename)
                pygame.quit()
                sys.exit()
        pygame.display.set_caption("Matt's Ray Tracer - Render in Progress...")
        tRay.o.y = psize * (y - 0.5 * (yres - 1))
        for x in range(xres):
            tRay.o.x = psize * (x - 0.5 * (xres - 1))
            ray_color = raytrace(tRay)
            tcolor = ray_color.finalcolor()
            pixArr[x][y] = pygame.Color(tcolor[0], tcolor[1], tcolor[2])
        pygame.display.update()
        
        
            
    del pixArr
    pygame.display.set_caption("Matt's Ray Tracer - Render Finished - Total time: " + str(time.time() - starttime) + " seconds")
    print 'Time :', time.time() - starttime 
    filename = datetime.datetime.strftime(datetime.datetime.now(), "%H.%M.%S_%d-%b-%Y") + '.png'
    pygame.image.save(windowSurfaceObj, filename)
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pygame.event.post(pygame.event.Event(QUIT))
예제 #10
0
    def render_scene(objects,res):
        #create a viewport and image
        v = ViewPort(res[0],res[1])
        im = Image.new("RGB",(v.w,v.h))
        pix = im.load()

        #define a ray
        ray = Ray(np.array([0,0,0]),np.array([0,0,-1]))

        # Perform perspective ray-tracing

        for col in range(v.w):
            for row in range(v.h):
                ray.o = v.getPixelCenter(col,row)
                t = s.intersectRay(ray)
                if (t != None):
                    xp = ray.getPoint(t) 
                    pix[col,(v.h-1)-row] = phongShader(xp,s.getNormal(xp),s.material,light,eye)

        # Show the image in a window
        im.show()
        
예제 #11
0
    def isInShadows(self, ray, hitdist):
        if hitdist == float('inf'):
            return False

        hitpoint = ray.pointatparameter(hitdist)
        nv = self.licht.pos - hitpoint
        nnv = nv / np.linalg.norm(nv)

        lichtRay = Ray(hitpoint, nnv)
        maxdist = self.licht.distance(lichtRay)

        for obj in self.objects:
            hitdist = obj.intersectionparameter(lichtRay)
            if hitdist:
                if 0.001 <= hitdist <= maxdist:
                    return True
예제 #12
0
    def initExplosion(self, pos):
        n = self.POINTS_IN_DOT_WAVEFRONT * 2

        for i in range(n):
            angle = 2 * math.pi * i / n
            velocity = Vector2(math.cos(angle), math.sin(angle))
            self.rays = np.append(self.rays, Ray(pos, velocity))
            self.raysNum += 1

        for i in range(1, n - 1):
            self.rays[i].setLeft(self.rays[i - 1])
            self.rays[i].setRight(self.rays[i + 1])

        self.rays[0].setLeft(self.rays[n - 1])
        self.rays[0].setRight(self.rays[1])
        self.rays[n - 1].setLeft(self.rays[n - 2])
        self.rays[n - 1].setRight(self.rays[0])
예제 #13
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()
예제 #14
0
class Plane(Object):
    def __init__(self, point1, point2, color):
        Object.__init__(self, color, "plane")
        self.point = point1
        self.normal_vector = Ray(point1=point1, point2=point2)

    def normal(self, point):
        return self.normal_vector

    def ray_intersect(self, ray):
        denom = self.normal_vector.dotproduct(ray)
        if denom !=0:
            t = ( ray.origin.directionvector(self.point) ).\
                    dotproduct( self.normal_vector ) / denom
            if t >= 0:
                return t
        return 0.0
예제 #15
0
def getpixel(ray):
    # calculates the color of the current pixel based on interected objects
    intersect, dist = raytrace(ray, scene.objects)
    if intersect:
        intersect_point = ray.intersect_point(dist)
        light_vector = Ray(point1=scene.light, point2=intersect_point)
        normal_vector = intersect.normal(intersect_point)
        if inshadow(intersect_point, normal_vector, light_vector,
                    scene.objects):
            shade = 0.0
        else:
            shade = lambertshade(light_vector, normal_vector)
        point_color = intersect.pointcolor(scene.ambient_coefficient, \
                        scene.diffuse_coefficient(), shade)
        return point_color  # alter for shadow
    else:
        return scene.blank_color
    return
예제 #16
0
    def test_rand_eye_intersection_distance_correctness(self, NTEST = 100):
        ''' Shoot rays from random eye position towards the center. The intersection
        point should be radius distance from the center. '''
        np.random.seed(9125)
        for testNo in range(NTEST):
            # generate a random point outside of the range [-5, 5]
            sgn = 1 if np.random.rand(1) <= .5 else -1

            eye = (np.random.rand(1, 3).flatten() + 5) * sgn # generate a random point
            viewDir = GT.normalize(-eye) # direction towards the center

            #print(sgn, eye, viewDir)

            ray = Ray(eye, viewDir)

            result = self.sphere.intersect(ray)
            distance = np.linalg.norm(result.p - self.center)
            nptest.assert_almost_equal(distance, self.radius)
예제 #17
0
 def initRay(self, x):
     for y in range(0, self.h):
         col = Vec3(0, 0, 0)
         # Aspect correction in the case the output image is not square
         # This took me super long to figure out
         mx = ((x + (self.h - self.w) / 2) * self.w/self.h)
         # average the samples
         for i in range(self.samples):
             # calculate direction
             # Adds the random to get anti-aliasing
             a = self.getDir(mx + random(), y + random())
             # create ray for rendering
             ray = Ray(orig=self.pos, dir=a)
             # render!
             col = col + self.rendererCalcColor(ray, 4, self.tracer)
         col = col ^ (1 / self.samples)  # average the samples
         self.savePixel(col, x, y)  # save pixel
     return "complete"
예제 #18
0
    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)
예제 #19
0
	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
예제 #20
0
 def mapPointToScreen(self, point):
     if self.ortho:
         direction = self.direction
     else:
         diff = point - self.eye
         if Roughly(diff.length_2(), 0):
             return None
         direction = diff.normalize()
     ray = Ray(self.eye, direction)
     hit = rayHitsPlane(-self.direction, self.screenCenter, ray)
     if hit.hit:
         assert not hit.inverted
         # TODO: This won't map points behind the eye.
         location = ray.origin + ray.offset.scale(hit.distance)
         offset = self.screenTopLeft - location
         distanceFromLeft = offset.dot(self.left)
         distanceFromTop = offset.dot(self.up)
         pixel = (int(distanceFromLeft / self.w * float(self.cols)),
                  int(distanceFromTop / self.h * float(self.rows)))
         return pixel
     return None
예제 #21
0
    def rendererCalcColor(self, ray, numBounce, tracer):
        """
        Calculates a pixel colour given a starting ray using Monte Carlo magik!
        Parameters:
            ray: Ray. The ray to be traced
            numBounce: Int. The number of bounces the ray is allowed to do
            tracer: Scene. The scene
        """
        # Variables for colour accumulation
        tCol = Vec3(0, 0, 0)
        gCol = Vec3(1, 1, 1)

        for i in range(numBounce):
            # intersect with seen
            isec = tracer.worldIntersect(ray)
            # intersection information
            sec = isec["t"]
            # if no intersection
            if not sec[0]:
                # stop the accumulation process or return the sky
                if i == 0:
                    return self.bgColor
                else:
                    break
            # Calculate intersection position
            pos = ray.o + (ray.d ^ sec[1])
            # load material
            material = isec["index"].mat
            # Load surface colour and compute direct lighting
            sCol = tracer.materials[material]
            dCol = self.applyDirectLighting(pos, sec[2], tracer)
            # Create new ray
            ray = Ray(orig=pos + (sec[2] ^ 0.1),
                      dir=OrientedHemiDir(sec[2]))
            # accumulate colours
            gCol = sCol * gCol
            tCol += gCol * dCol
        # return the total colour
        return tCol
예제 #22
0
    def test_rand_eye_intersection_distance_from_eye_correctness(self, NTEST = 100):
        ''' Shoot rays from random eye position towards the center. Test whether
        the distance to the intersection point from the eye position is distance
        to the center minus the radius.'''
        np.random.seed(9125) # uses the same random sequence as point to center distance test
        for testNo in range(NTEST):
            # generate a random point outside of the range [-5, 5]
            sgn = 1 if np.random.rand(1) <= .5 else -1

            eye = (np.random.rand(1, 3).flatten() + 5) * sgn # generate a random point
            viewDir = GT.normalize(-eye) # direction towards the center

            #print(sgn, eye, viewDir)

            ray = Ray(eye, viewDir)

            result = self.sphere.intersect(ray)
            isect_pt_from_eye_distance = np.linalg.norm(result.p - eye) # for sanity check
            eye_distance_from_center = np.linalg.norm(eye - self.center)
            #print(isect_pt_from_eye_distance, result.t)
            nptest.assert_almost_equal(result.t, isect_pt_from_eye_distance) # sanity check
            nptest.assert_almost_equal(result.t, eye_distance_from_center - self.radius) # sanity check
예제 #23
0
    def getRay(self, x: float, y: float) -> Ray:
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        inverted_projection = numpy.linalg.inv(
            self._projection_matrix.getData().copy())
        transformation = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype=numpy.float32)
        near = numpy.dot(inverted_projection, near)
        near = numpy.dot(transformation, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype=numpy.float32)
        far = numpy.dot(inverted_projection, far)
        far = numpy.dot(transformation, far)
        far = far[0:3] / far[3]

        direction = far - near
        direction /= numpy.linalg.norm(direction)

        if self.isPerspective():
            origin = self.getWorldPosition()
            direction = -direction
        else:
            # In orthographic mode, the origin is the click position on the plane where the camera resides, and that
            # plane is parallel to the near and the far planes.
            projection = numpy.array([view_x, -view_y, 0.0, 1.0],
                                     dtype=numpy.float32)
            projection = numpy.dot(inverted_projection, projection)
            projection = numpy.dot(transformation, projection)
            projection = projection[0:3] / projection[3]

            origin = Vector(data=projection)

        return Ray(origin, Vector(direction[0], direction[1], direction[2]))
예제 #24
0
def Refraction(ray, air_ind, glass_ind, env="air"):
    sphere = Sphere(position=Vector(2, 2, 2), radius=1.0)
    print "ray.ray_origin", ray.origin
    print "ray.ray_dir", ray.ray_dir
    t_min = sphere.get_intersect(ray_origin=ray.origin,
                                 ray_dir=ray.ray_dir.normalize())
    print "t_min", t_min
    intersect_point = ray.origin.clone().add(
        (ray.ray_dir.normalize().clone()).constant_multiply(t_min * 0.001))
    print "intersect_point", intersect_point
    normal_vector = sphere.surface_normal(point=intersect_point.clone(),
                                          ray_origin=ray.origin.clone(),
                                          ray_dir=ray.ray_dir.clone())
    print "normal_vector", normal_vector
    c_1 = normal_vector.normalize().clone().dot(
        ray.ray_dir.normalize().clone())
    if env == "air":
        n = air_ind / glass_ind
        c_1 = -c_1
        print "n", n
        # print "c_1", c_1
    else:
        n = glass_ind / air_ind
        print "n", n
        normal_vector = normal_vector.normalize().constant_multiply(-1)
    k = (1 - (n**2) * (1 - (c_1)**2))
    if k < 0:
        return "K is negative"
    c_2 = math.sqrt(k)
    part_1 = ray.ray_dir.normalize().constant_multiply(n)
    part_2 = normal_vector.normalize().clone().constant_multiply(
        (n * c_1 - c_2))
    ref_ray_dir = (part_1.clone().add(part_2.clone())).normalize()
    # print "ref_ray_dir", ref_ray_dir
    ref_ray = Ray(origin=intersect_point, ray_dir=ref_ray_dir)
    # print "env", env
    # print "n", n
    return ref_ray
예제 #25
0
def compute_DirectLight(hitPointData):
    """
    Methode handled wie die Schnittpunktstelle gefärbt werden soll
    :param hitPointData: (Objekt, Schnittpunkt, Trefferdistanz, Ray)
    :return: gibt Farbe am Schnittpunkt mit Objekt zurück
    """
    color = BACKGROUND_COLOR
    current_obj = hitPointData[0]

    if hitPointData[0] and current_obj is not None:
        intersec_Point = hitPointData[1] #Schnittpunkt
        intersec_Light = Ray(intersec_Point, normalize(light.position - intersec_Point)) #Ray vom Schnittpunkt zum Licht
        in_shadow = check_Shadow(current_obj,intersec_Light) #Checkt ob Schnittpunkt auf der Oberfläche im Schatten liegt
        """in_shadow = False"""

        if in_shadow == True:
            if isinstance(current_obj,Plane):
                color = numpy.array(current_obj.rgb.baseColorAt(intersec_Point)) * shadow_ambient #Wenns im Schatten liegt nehme einen geringeren Ambient Faktor
            else:
                color = phong_Shader(intersec_Point,hitPointData,shadow_ambient)
        else:
            color = phong_Shader(intersec_Point, hitPointData, no_shadow_ambient) #Größerer Ambientfaktor wenns nicht im Schatten liegt

    return color
예제 #26
0
 def render(self, tracer, imgOut):
     """
     Renders a scene to an image
     Parameters:
         tracer: Scene. The scene to be rendered.
         imgOut: String. The name of the output file
     """
     # loop through all the pixels in the image
     for x in range(self.w):
         for y in range(self.h):
             col = Vec3(0, 0, 0)
             # Aspect correction in the case the output image is not square
             # This took me super long to figure out
             mx = ((x + (self.h - self.w) / 2) * self.w / self.h)
             # average the samples
             for i in range(self.samples):
                 # calculate direction
                 # Adds the random to get anti-aliasing
                 a = self.getDir(mx + random(), y + random())
                 # create ray for rendering
                 ray = Ray(orig=self.pos, dir=a)
                 # render!
                 col = col + self.rendererCalcColor(ray, 4, tracer)
             col = col ^ (1 / self.samples)  # average the samples
             self.savePixel(col, x, y)  # save pixel
         # ===Update progress bar===
         # Clear terminal
         os.system('cls' if os.name == 'nt' else 'clear')
         # Calculate progress
         prog = int(round((x) / self.w * self.barWidth))
         # Print progress bar
         print("[" + "=" * prog + ">" + " " * (self.barWidth - prog) +
               "] " + str(round(prog *
                                (100 / self.barWidth))) + "% completed")
     # ===Save Image===
     self.saveImage(imgOut)  # save image
예제 #27
0
 def calcRay(self, x, y):
     """calculates a ray for the main"""
     xcomp = np.multiply(self.s, (x * self.pixelWidth - self.viewWidth / 2))
     ycomp = np.multiply(self.u,
                         (y * self.pixelHeigth - self.viewheight / 2))
     return Ray(self.e, np.add(self.f, np.add(xcomp, ycomp)))
예제 #28
0
 def calcRay(x, y):
     """calculates a ray for the main"""
     xcomp = np.multiply(s, (x * pixelWidth - viewWidth / 2))
     ycomp = np.multiply(u, (y * pixelHeigth - viewheight / 2))
     return Ray(e, np.add(f, np.add(xcomp, ycomp)))
예제 #29
0
def optimized_shadows(polygons,
                      light_point,
                      surface,
                      box_borders=(Vector2D(0, 0), Vector2D(1280, 0),
                                   Vector2D(1280, 720), Vector2D(0, 720)),
                      color=(0, 0, 0)):
    # need to understand https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
    # need to understand https://thecodingtrain.com/CodingChallenges/145-2d-ray-casting.html

    for polygon in range(0, len(polygons)):
        if isinstance(polygons[polygon], Polygon):
            polygons[polygon] = polygons[polygon].get_points()

    screen_borders = list(box_borders)

    for polygon in polygons:
        casted_points = [None for point in polygon]
        touched_side = [0 for point in polygon]
        for point in range(0, len(polygon)):
            point_to_light = light_point.copy()
            point_to_light -= polygon[point]
            ray_light_to_point = Ray(polygon[point], point_to_light)

            closest_point = None
            closest_d = 10000
            side = 0

            for i in range(0, len(screen_borders)):
                p1 = screen_borders[i]
                p2 = screen_borders[(i + 1) % len(screen_borders)]
                hit = ray_light_to_point.cast([p1, p2])

                if hit:
                    d = hit.copy()
                    d -= polygon[point]
                    d = d.magnitude
                    if d < closest_d:
                        closest_point = hit.copy()
                        closest_d = d
                        side = i
                        break

            if closest_point:
                casted_points[point] = closest_point.copy()
                touched_side[point] = side

        for point in range(0, len(polygon)):
            if casted_points[point] is None or casted_points[
                (point + 1) % len(polygon)] is None:
                continue
            points = [point, (point + 1) % len(polygon)]
            if touched_side[points[0]] > touched_side[points[1]]:
                t = points[0]
                points[0] = points[1]
                points[1] = t

            extra_points = []

            if abs(touched_side[points[0]] -
                   touched_side[points[1]]) == 2:  # Parallel touching
                if touched_side[points[0]] % 2 == 0:  # Horizontal
                    d = casted_points[points[0]].x
                    if d > light_point.x:
                        extra_points.append(screen_borders[1].list())
                        extra_points.append(screen_borders[2].list())
                    else:
                        extra_points.append(screen_borders[0].list())
                        extra_points.append(screen_borders[3].list())
                else:  # Vertical
                    d = casted_points[points[0]].y
                    if d > light_point.y:
                        extra_points.append(screen_borders[2].list())
                        extra_points.append(screen_borders[3].list())
                    else:
                        extra_points.append(screen_borders[0].list())
                        extra_points.append(screen_borders[1].list())
            elif abs(touched_side[points[0]] -
                     touched_side[points[1]]) == 1:  # Contiguous sides
                extra_points.append(
                    screen_borders[touched_side[points[1]]].list())
            elif abs(touched_side[points[0]] -
                     touched_side[points[1]]) == 3:  # Contiguous sides
                extra_points.append(screen_borders[0].list())

            polygon_points = [
                polygon[points[0]].list(), casted_points[points[0]].list()
            ]
            polygon_points.extend(extra_points)
            polygon_points.extend(
                [casted_points[points[1]].list(), polygon[points[1]].list()])
            try:
                pygame.draw.polygon(surface, color, polygon_points)
            except Exception as e:
                print polygon_points
                raise e
    return
예제 #30
0
 def testRaysOppositeEachother(self):
     ray1 = Ray({"x": 0, "y": 0}, 0, 1)
     ray2 = Ray({"x": 1, "y": 0}, pi, 1)
     assert ray1 == ray2
예제 #31
0
from Vector import Vector
from Ray import Ray
from Triangle import Triangle
from Sphere import Sphere
from Triangle import Triangle
from Screen2D import Screen2D
from Viewport import Viewport
from PointLight import PointLight
import math
import sys

ray = Ray(origin=Vector(0.0, 0.0, 0.0), ray_dir=Vector(1.0, 1.0, 0.5))
sphere = Sphere(position=Vector(2, 2, 2), radius=1.0)
t_min = sphere.get_intersect(ray_origin=Vector(0.0, 0.0, 0.0),
                             ray_dir=Vector(1.0, 1.0, 0.5))
print t_min
intersect_point = ray.origin.clone().add(
    ray.ray_dir.clone().constant_multiply(t_min))
normal_vector = sphere.surface_normal(point=intersect_point.clone(),
                                      ray_origin=ray.origin.clone(),
                                      ray_dir=ray.ray_dir.clone())
# print "normal_vector", normal_vector
# print "ray_dir", ray.ray_dir
# print "ray_dir_normalize", ray.ray_dir.normalize()
# print "intersect_point", intersect_point


def Refraction(ray, air_ind, glass_ind, env="air"):
    sphere = Sphere(position=Vector(2, 2, 2), radius=1.0)
    print "ray.ray_origin", ray.origin
    print "ray.ray_dir", ray.ray_dir
예제 #32
0
    def get_intersect(self,
                      ray_origin=Vector(0, 0, 0),
                      ray_dir=Vector(1, 1, 1)):
        """
		this method returns the point where a Ray and a sphere intersects.
		if the Ray does not intersect with the sphere the function returns False

		following are the calculation steps:

		(1) the equation of a sphere x^2 + y^2 + z^2 = R^2
		
		(2) the equation of a ray P = O + tD 
			(O is the origin of the ray and D is the normalized vector which corresponds to the ray direction and P 
			is a point at the end of the ray based on the scaling factor t. t is in fact the parametric distance from the origin of the ray 
			to the point of interest along the ray) 
		
		(3) if x, y, and z in equation 1 are the coordinates of point P in equation 2: P^2 - R^2 = 0
			(when the sphere is not centered at the origin, equation 2 is equal to  |P - C|^2 - R^2 = 0 (equation 3) 
		
		(4) equation 3 can be rewritten as |O + tD - C|^2 - R^2 = 0 (equation 4), where C is the center of the sphere in space
		
		(5) equation 4 is a quadratic function where a = 1 (dot product of a normalized vector with itself) and 
			b = 2D(O-C) and c = |O-C|^2 - R^2.
		(6) delta = b^2 - 4*a*c   t1, t2 = (-b +- sqrt(delta)/2a
			if delta > 0, the ray intersects the sphere in two points (t1 and t2)
			if delta = 0, the ray intersects the sphere in one point only (t1=t2)
			if delta < 0, the ray does not intersect with the sphere.    
		"""
        ray = Ray(ray_origin, ray_dir)

        a = ray.ray_dir.dot(
            ray.ray_dir
        )  #a = D^2 = 1 (D is a normalized vector for ray direction)
        vector_O_C = ray.origin.clone().sub(self.position.clone(
        ))  #the vector between origin of the ray and the center of the circle

        scaled_ray_direction = ray.ray_dir.clone().constant_multiply(2)  # 2*D
        b = scaled_ray_direction.dot(vector_O_C)

        mag_vector_O_C = vector_O_C.mag()

        c = (mag_vector_O_C)**2 - (self.radius)**2

        if solve_quadratic(a, b, c) is None:
            return False

        t1, t2 = solve_quadratic(a, b, c)

        if t1 > 0 and t2 > 0:
            if t1 < t2:
                return t1
            return t2

        elif t1 == t2:
            return t1
        elif t1 > 0 and t2 < 0:
            return t1
        elif t2 > 0 and t1 < 0:
            return t2
        else:
            return False
예제 #33
0
 def getRay(self, x, y):
     xcomp = self.s * ((x * self.pixelWidth) - (self.width / 2))
     ycomp = self.u * ((y * self.pixelHeight) - (self.height / 2))
     return Ray(self.e, self.f + xcomp + ycomp)
예제 #34
0
        #We need this to calculate the camera right vector

        distance = toLookAt.length()
        toLookAtNormalized = toLookAt.toNormalized()
        width = math.cos(camera.fov) * distance
        height = math.cos(camera.fov) * distance
        #width and height should be the same unless we set different fovs for width and height

        # TODO: This should be toLookAtNormalize
        cameraRight = toLookAtNormalized.cross(camera.up)
        rightWorld = cameraRight.toScaled(width * xPercent)
        upWorld =  camera.up.toScaled(height * yPercent)
        pixelLookAt = Point3D.fromVector(upWorld.plus(rightWorld))
        #We now have our world look at points
        #We need to generate our look at ray and NORMALIZE IT!!!
        ray = Ray(camera.origin, pixelLookAt.minus(camera.origin).toNormalized())

        # jitter the ray

        r = 0
        g = 0
        b = 0
        samples = 12
        for i in range(samples):
            ray2 = Ray(Point3D.fromVector(ray.origin.vector.clone()), ray.direction.clone())
            ray2.direction.x += (random.random() - .5)*2*width/frame.width
            ray2.direction.y += (random.random() - .5)*2*height/frame.height
            ray2.direction = ray2.direction.toNormalized()
            color = getColor(ray2, None, 4)
            r += color.x
            g += color.y
예제 #35
0
                p2,
                p3,
                np.array([1.0, 1.0, 1.0]),
                0.8,
                0.75,
                0.05,
                100,
                0.6,
                "tri2",
                texture="triangle1.jpg",
                origin=1,
                hori=np.array([20.0, 0.0, 0.0]),
                verti=np.array([0.0, -20.0, 0.0]))
tree.insert(tri)
tree.insert(tri1)
ray = Ray(np.array([0.0, 0.0, 0.0]), np.array([0.0, 0.0, -1.0]))

point = np.array([0.0, -10.0, 0.0])
normal = np.array([0.0, -1.0, 0.0])
p = Plane(point, normal, np.array([1.0, 1.0, 1.0]), 1.0, 1.0, 0.05, 150, 0.6,
          "plane1")
tree.insert(p)
radius = 3
center = np.array([-10.0, -7.0, -17.0])
s = Sphere(radius,
           center,
           np.array([0.289, 0.2845, 0.3779]),
           1.0,
           1.0,
           1.0,
           4,
예제 #36
0
 def testGetEndPointOnAngle(self):
     expectedPoint = {"x": 1, "y": 1}
     ray = Ray({"x": 0, "y": 0}, pi / 4, 2**0.5)
     assert Ray.pointsVeryClose(ray.getEndPoint(), expectedPoint)
예제 #37
0
 def testEmptyConstructor(self):
     assertThrows(lambda: Ray(), Exception)
예제 #38
0
 def testGetEndPointBackwards(self):
     expectedPoint = {"x": 1, "y": 1}
     ray = Ray({"x": 5, "y": 4}, atan(3 / 4) + pi, 5)
     assert Ray.pointsVeryClose(ray.getEndPoint(), expectedPoint)
예제 #39
0
 def testGetEndPointVerticalAngle(self):
     expectedPoint = {"x": 5, "y": 5}
     ray = Ray({"x": 5, "y": 0}, pi / 2, 5)
     assert Ray.pointsVeryClose(ray.getEndPoint(), expectedPoint)
예제 #40
0
 def testGetEndPointHorizontalAngle(self):
     expectedPoint = {"x": 5, "y": 5}
     ray = Ray({"x": 0, "y": 5}, 0, 5)
     assert Ray.pointsVeryClose(ray.getEndPoint(), expectedPoint)
예제 #41
0
    phi = numpy.arange(tube.start, tube.end, 0.1)
    rho = numpy.asarray([tube.turn_radius]*numpy.size(phi))
        
    w = (rho) * numpy.cos(phi)
    x = (rho) * numpy.sin(phi)
    
    y = (rho + 2) * numpy.cos(phi)
    z = (rho + 2) * numpy.sin(phi)
    
    return w, x, y, z
    
#define tube
tube_ex = SemicircleTube(1, 1000, 1.0, 0, math.pi*2)

#define ray
ray_ex = Ray(theta_i=.04, p_i=(math.pi,1001))

# propogate
for i in range(10):
    point = interact(tube_ex, ray_ex)

# graph
tx, ty =  tube_ex.plot()
#rx, ry =  ray_ex.pol_plot()
rrx, rry =  ray_ex.car_plot()
a,b,c,d = plot(tube_ex)

#matplotlib.pyplot.plot()
#matplotlib.pyplot.plot(rrx, rry)
#matplotlib.pyplot.plot(tx, ty)
#matplotlib.pyplot.plot(tx, ty)
예제 #42
0
from Sphere import Sphere
from Ray import Ray
from ViewPort import ViewPort

#create a viewport and image
v = ViewPort(500,500)
im = Image.new("RGB",(v.w,v.h))
pix = im.load()

#define a sphere
radius = 1.0
center = np.array([0,0, -2.5])
s = Sphere(radius,center,np.array([255,0,0]))

#define a ray
ray = Ray(np.array([0,0,0]),np.array([0,0,-1]))

# define a light direction
ldir = np.array([0,0,1]) #light direction
kd = 0.75  #reflectivity 
illum = 1.0  #light luminosity


def phongDiffuse(x,n,mat):
    """Implements a Phong-style diffuse shading function

    Args:
         x: is a point on a surface
         n: is the unit normal at that point
         mat: is an RGB tuple of the surface color