Пример #1
0
    def intersect(self, ray):
        '''
    Implement intersection between the ray and the current object and
    return IntersectionResult variable (isect) which will store the
    intersection point, the normal at the intersection and material of the
    object at the intersection point. The variable isect should contain the
    nearest intersection point and all its properties.
    '''
        isect = IntersectionResult()
        transformedRay = Ray()
        # Eyepoint transformed
        transformedRay.eyePoint = np.dot(self.Minv,
                                         np.append(ray.eyePoint, [1]))
        transformedRay.eyePoint = transformedRay.eyePoint[:
                                                          3] / transformedRay.eyePoint[
                                                              3]
        # Ray transformed, since it's a vector not from origin need to do this calc
        ray_tip = ray.eyePoint + ray.viewDirection
        trans_ray_tip = np.dot(self.Minv, np.append(ray_tip, [1]))
        trans_ray_tip = trans_ray_tip[:3] / trans_ray_tip[3]
        transformedRay.viewDirection = GT.normalize(trans_ray_tip -
                                                    transformedRay.eyePoint)

        global EPS_DISTANCE  # use this for testing if a variable is close to 0
        # TODO ===== BEGIN SOLUTION HERE =====
        intersections = []

        # Get all the intersections
        for child in self.children:
            intersection = child.intersect(transformedRay)
            if intersection.t == np.inf:
                continue

            # Point transformed
            intersection.p = np.dot(self.M, np.append(intersection.p, [1]))
            intersection.p = intersection.p[:3] / intersection.p[3]

            # Distance in world coords
            intersection.t = np.linalg.norm(intersection.p - ray.eyePoint)

            # Normal, inverse transpose because it's a normal to remove scale issues
            intersection.n = GT.normalize(
                np.dot(np.transpose(self.Minv), np.append(intersection.n,
                                                          [0]))[:3])

            intersections.append(intersection)

        min_isect = isect

        # Get the closest intersection
        for iss in intersections:
            if (iss.t < min_isect.t):
                min_isect = iss

        isect = min_isect
        # ===== END SOLUTION HERE =====
        return isect
Пример #2
0
  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
Пример #3
0
  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
  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 pixel center positions
      normalized_x = (2.0*float(col))/(cam.imageWidth) - 1.0
      normalized_y = 1.0 - (2.0*float(row))/(cam.imageHeight)

      # Get other factors
      ch = cam.top / cam.near
      cw = ch * cam.aspect
      cx = cam.cameraXAxis * cw
      cy = cam.cameraYAxis * ch

      ray.viewDirection = GT.normalize((cam.lookat + normalized_x*cx + normalized_y*cy))

      # ===== END SOLUTION =====
      return ray
Пример #5
0
  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 = []

      # TODO ====== BEGIN SOLUTION =====
      for l in self.lights:
        ray = Ray()
        ray.eyePoint = isect.p
        ray.viewDirection = GT.normalize(l.pointFrom - isect.p)
        nearest_isect = self.get_nearest_object_intersection(ray)

        # PLEASE NOTE: while i used to have
        # np.fabs(nearest_isect.t -  np.linalg.norm(l.pointFrom - isect.p)) <= EPS_DISTANCE
        # This gave more different results than the solution images, as such
        # I kept this which gave a closer version to what scene4 gave
        # As was said in the forums, this shouldn't matter for grading as it only gives
        # slightly different shading results
        if nearest_isect.t == np.inf or nearest_isect.t >= np.linalg.norm(l.pointFrom - isect.p):
          # no further intersection than to the given point
          visibleLights.append(l)

      # ===== END SOLUTION HERE =====
      return visibleLights
Пример #6
0
  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