def blihn_pmong(self, ray_direction, ray_origin, t, lamps, sensibility, environment): p = ray_direction.map(lambda value, index: value * t + ray_origin.vector[index]).vector n = Vector.init_with_points(p, self.center).unit_vector() v = ray_direction.unit_vector() pixel_color = [] lambert = self.lambert(ray_direction, ray_origin, t, lamps) L = 0 for index, rgb_color in enumerate(self.color): for lamp in lamps: l = Vector.init_with_points(p, lamp.position).unit_vector() h = v.map(lambda value, index: value + l.vector[index]).unit_vector() L += lambert[index] + lamp.color[index] * lamp.intensity * math.pow(max(0, numpy.dot(n.vector, h.vector)), sensibility) pixel_color.append(environment.intensity * environment.color[index] + L) L = 0 return (int(pixel_color[0]), int(pixel_color[1]), int(pixel_color[2]))
def polygon_normal(self, p): different_points_in_triangle = [] for index, point in enumerate(self.triangle_touched.points): if different_points_in_triangle.__len__() < 2: if p != point: different_points_in_triangle.append(point) return Vector(numpy.cross((Vector.init_with_points(p, different_points_in_triangle[0])).vector, (Vector.init_with_points(p, different_points_in_triangle[1])).vector)).unit_vector()
def divide_into_nine_squares(points, side_size): squares = [] unit_x_vector = Vector.init_with_points(points[0], points[1]).unit_vector() unit_y_vector = Vector.init_with_points(points[0], points[3]).unit_vector() for y in range(3): for x in range(3): squares.append(Polygon(points=[ ((points[0][0] + (unit_x_vector.vector[0] * x * (side_size / 3)) + ( unit_y_vector.vector[0] * y * (side_size / 3))), (points[0][1] + (unit_x_vector.vector[1] * x * (side_size / 3)) + ( unit_y_vector.vector[1] * y * (side_size/3))), (points[0][2] + (unit_x_vector.vector[2] * x * (side_size / 3)) + ( unit_y_vector.vector[2] * y * (side_size/3)))), ((points[0][0] + (unit_x_vector.vector[0] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[0] * y * (side_size / 3))), (points[0][1] + (unit_x_vector.vector[1] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[1] * y * (side_size / 3))), (points[0][2] + (unit_x_vector.vector[2] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[2] * y * (side_size / 3)))), ((points[0][0] + (unit_x_vector.vector[0] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[0] * (y + 1) * (side_size / 3))), (points[0][1] + (unit_x_vector.vector[1] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[1] * (y + 1) * (side_size / 3))), (points[0][2] + (unit_x_vector.vector[2] * (x + 1) * (side_size / 3)) + ( unit_y_vector.vector[2] * (y + 1) * (side_size / 3)))), ((points[0][0] + (unit_x_vector.vector[0] * x * (side_size / 3)) + ( unit_y_vector.vector[0] * (y + 1) * (side_size / 3))), (points[0][1] + (unit_x_vector.vector[1] * x * (side_size / 3)) + ( unit_y_vector.vector[1] * (y + 1) * (side_size / 3))), (points[0][2] + (unit_x_vector.vector[2] * x * (side_size / 3)) + ( unit_y_vector.vector[2] * (y + 1) * (side_size / 3)))), ], color=(colors[x+y]))) return squares
def lambert(self, ray_direction, ray_origin, t, lamps): p = ray_direction.map(lambda value, index: value * t + ray_origin.vector[index]).vector n = Vector.init_with_points(p, self.center).unit_vector() pixel_color = [] L = 0 for rgb_color in self.color: for lamp in lamps: l = Vector.init_with_points(p, lamp.position).unit_vector() L += rgb_color * lamp.intensity * max(0, numpy.dot(n.vector, l.vector)) pixel_color.append(L) L = 0 return (int(pixel_color[0]), int(pixel_color[1]), int(pixel_color[2]))
def __init__(self, point_e, distance, top, bottom, right, left): self.point_e = Vector(point_e) self.distance = distance self.top = top self.bottom = bottom self.right = right self.left = left self.w = self.point_e.unit_vector() self.t = self.w.non_collinear_vector() self.u = Vector(numpy.cross(self.w.vector, self.t.vector)).unit_vector() self.v = Vector(numpy.cross(self.w.vector, self.u.vector))
class Ray: def __init__(self, point_e, distance, top, bottom, right, left): self.point_e = Vector(point_e) self.distance = distance self.top = top self.bottom = bottom self.right = right self.left = left self.w = self.point_e.unit_vector() self.t = self.w.non_collinear_vector() self.u = Vector(numpy.cross(self.w.vector, self.t.vector)).unit_vector() self.v = Vector(numpy.cross(self.w.vector, self.u.vector)) def get_U(self, index_i, row): return self.left + (self.right - self.left) * (index_i + 0.5) / row def get_V(self, index_j, column): return self.bottom + (self.top - self.bottom) * (index_j + 0.5) / column def get_perspective_direction(self, U, V): return ((self.u.map(lambda value, index: value * U) ).map(lambda value, index: value + (self.v.map( lambda value, index: value * V)).vector[index]) ).map(lambda value, index: value + (self.w.map( lambda value, index: value * self.distance)).vector[index]) def get_parallel_origin(self, U, V): return (self.u.map(lambda value, index: value * U) ).map(lambda value, index: value + (self.v.map(lambda value, index: value * V)).vector[ index] + self.point_e.vector[index]) def perspective_projection(self, row, column): matrix = numpy.zeros((row, column), dtype=numpy.ndarray) for index, pixel in numpy.ndenumerate(matrix): matrix[index[0]][index[1]] = (self.get_perspective_direction( self.get_U(index[0], row), self.get_V(index[1], column)), self.point_e) return matrix def perspective_projection_2d(self, row, column, matrix_2d): matrix = numpy.zeros((row, column), dtype=numpy.ndarray) # delta_U = self.left + (self.right - self.left) * (row + 0.5) / row # delta_V = self.bottom + (self.top - self.bottom) * (column + 0.5) / column delta_U = 0 delta_V = 0 for index, pixel in numpy.ndenumerate(matrix): matrix_result = numpy.matmul([ self.get_U(index[0], row) + delta_U, self.get_V(index[1], column) + delta_V ], matrix_2d) matrix[index[0]][index[1]] = (self.get_perspective_direction( matrix_result[0] - delta_U, matrix_result[1] - delta_V), self.point_e) return matrix def parallel_projection(self, row, column): matrix = numpy.zeros((row, column), dtype=numpy.ndarray) for index, pixel in numpy.ndenumerate(matrix): matrix[index[0]][index[1]] = (self.w, self.get_parallel_origin( self.get_U(index[0], row), self.get_V(index[1], column))) return matrix