Esempio n. 1
0
class Renderer:
    def __init__(self, walls=(), ground=None, sky=None, filename='SOURCE-2.jpg', reducing=1):
        self.walls = walls
        self.ground = ground
        print ground
        self.sky = sky

        self.vertexes = VertexData()
        self.triangles = []
        self.count = 0

        self.filename = filename
        self.project = CameraProperties.make_project_name(filename)
        self.cp = CameraProperties(project=self.project)
        self.reducing = reducing
        # self.world_image = self.cp.image2plane(reducing=self.reducing)
        self.world_image = self.get_world_coordinates_image(self.project)

    def get_world_coordinates_image(self, project=''):
        world_image = ExtendedImage.load(project)
        if not world_image:
            world_image = self.cp.image2plane(reducing=self.reducing)
        return world_image

    def set_vertexes(self, increase=2):
        # self.set_ground_by_points_in_grid(increase=1)
        self.set_ground_by_lines(increase=increase)
        # self.set_ground_by_vertexes()
        for wall in self.walls:
            self.set_wall(wall=wall)
        self.set_sky()

    def set_ground_by_lines(self, increase=4.0):
        if not self.ground:
            return
        tangents = [line[0][1] / line[0][0] for line in self.ground]
        idx_min_tg = tangents.index(min(tangents))
        points_count = len(self.ground)
        p1, p2 = self.ground[(idx_min_tg - 1) % points_count][0], \
                 self.ground[(idx_min_tg + 1) % points_count][0]
        next_idx = (idx_min_tg - 1) % points_count if p1[0] > p2[0] \
            else (idx_min_tg + 1) % points_count
        oriented_points = [self.ground[idx_min_tg][0], self.ground[next_idx][0]]
        now_idx, prev_idx = next_idx, idx_min_tg
        idx = self.find_next_point(now_idx=now_idx, prev_idx=prev_idx)
        while now_idx != idx_min_tg:
            print idx
            oriented_points.append(self.ground[idx][0])
            now_idx, prev_idx = idx, now_idx
            idx = self.find_next_point(now_idx=now_idx, prev_idx=prev_idx, count=points_count)
        print oriented_points

        orientations = [self.line_orientation(oriented_points[i], oriented_points[(i + 1) % points_count])
                        for i in range(points_count)]
        param = lambda indx: get_parameters((oriented_points[indx], oriented_points[(indx + 1) % points_count]))
        lines_func = [lambda x, y: y <= get_value(param(i), x) if orientations[i] > 0 else y >= get_value(param(i), x)
                      for i in range(points_count)]

        increase = float(increase)
        min_x, min_y, max_x, max_y = 10000, 10000, 0, 0
        for line in lines:
            x, y = line[0]
            min_x = min(min_x, x)
            min_y = min(min_y, y)
            max_x = max(max_x, x)
            max_y = max(max_y, y)
        square = 0

        x, x_m, y_m = 0, max_x - min_x, max_y - min_y
        while x < x_m:
            y = 0
            while y < y_m:
                if all(func(x, y) for func in lines_func):
                    square += 1
                    from random import random
                    self.vertexes += Vertex(pos=(int(x / increase), int(y / increase), 0),
                                            nor=(0, 0, 1), col=(random(), random(), random()))
                y += 1 / increase
            x += 1 / increase
        # for x in [0: 1/increase: max_x - min_x]:
        #     for y in range((max_y - min_y) * int(increase)):
        #         if all(func(x, y) for func in lines_func):
        #             square += 1
        #             from random import random
        #             self.vertexes += Vertex(pos=(int(x / increase), int(y / increase), 0),
        #                                     nor=(0, 0, 1), col=(random(), random(), random()))
        print square
        if not self.triangles:
            self.set_triangles()

    def set_ground_by_points_in_grid(self, normal=(0, 0, 1), increase=2.0):
        if not self.ground:
            return
        increase = float(increase)
        points_on_plane = get_points_on_plane(self.ground, increase=increase)
        print points_on_plane
        pop = points_on_plane
        square = 0
        for i in range(pop.shape[0]):
            for j in range(pop.shape[1]):
                if pop[i][j]:
                    square += 1
                    from random import random
                    self.vertexes += Vertex(pos=(int(i / increase), int(j / increase), 0),
                                            nor=normal, col=(random(), random(), random()))
        print square
        if not self.triangles:
            self.set_triangles()

    def __draw_ground_by_vertexes(self):
        if not self.ground:
            return
        glColor3f(1, 1, 1)
        glBindTexture(GL_TEXTURE_2D, self.world_texture)
        glBegin(GL_POLYGON)
        glNormal3f(0, 0, -1)
        for line in self.ground:
            point_x, point_y = line[0]
            # glTexCoord2f(point_x / self.image_width, point_y / self.image_height)
            wp = self.cp.img2world(point=(point_x, point_y), reducing=self.reducing)
            glTexCoord2fv(self.world_image.image_coordinates(wp))
            glVertex3f(float(wp[0]), float(wp[1]), 0)
        glEnd()

    @staticmethod
    def find_next_point(now_idx=1, prev_idx=0, count=5):
        return (now_idx + 1 if prev_idx == (now_idx - 1) % count else now_idx - 1) % count

    @staticmethod
    def line_orientation(p1, p2):
        return 1 if p1[0] > p2[0] else -1

    def set_wall(self, wall=None, normal=(1, 0, 0)):
        pass

    def set_sky(self, normal=(0, -1, 0)):
        pass

    def set_triangles(self):
        points = []
        for ver in self.vertexes:
            points.append(ver.pos[0:2])
        triangles = delaunay(points)
        for tri in triangles:
            self.triangles.extend(self.vertexes[tri[i]].pos for i in xrange(3))

    def __draw_cube(self, pos=(), size=1):
        if not pos:
            pos = self.cen
        x1, y1, z1 = pos
        x2, y2, z2 = map(lambda p: p + size, [x1, y1, z1])
        glBindTexture(GL_TEXTURE_2D, self.texture)
        glBegin(GL_POLYGON)  # front face
        glNormal3f(0.0, 0.0, 1.0)
        glTexCoord2f(0, 0)
        glVertex3f(x1, y1, z2)
        glTexCoord2f(1, 0)
        glVertex3f(x2, y1, z2)
        glTexCoord2f(1, 1)
        glVertex3f(x2, y2, z2)
        glTexCoord2f(0, 1)
        glVertex3f(x1, y2, z2)
        glEnd()

        glBegin(GL_POLYGON)  # back face
        glNormal3f(0.0, 0.0, -1.0)
        glTexCoord2f(1, 0)
        glVertex3f(x2, y1, z1)
        glTexCoord2f(0, 0)
        glVertex3f(x1, y1, z1)
        glTexCoord2f(0, 1)
        glVertex3f(x1, y2, z1)
        glTexCoord2f(1, 1)
        glVertex3f(x2, y2, z1)
        glEnd()

        glBegin(GL_POLYGON)  # left face
        glNormal3f(-1.0, 0.0, 0.0)
        glTexCoord2f(0, 0)
        glVertex3f(x1, y1, z1)
        glTexCoord2f(0, 1)
        glVertex3f(x1, y1, z2)
        glTexCoord2f(1, 1)
        glVertex3f(x1, y2, z2)
        glTexCoord2f(1, 0)
        glVertex3f(x1, y2, z1)
        glEnd()

        glBegin(GL_POLYGON)  # right face
        glNormal3f(1.0, 0.0, 0.0)
        glTexCoord2f(0, 1)
        glVertex3f(x2, y1, z2)
        glTexCoord2f(0, 0)
        glVertex3f(x2, y1, z1)
        glTexCoord2f(1, 0)
        glVertex3f(x2, y2, z1)
        glTexCoord2f(1, 1)
        glVertex3f(x2, y2, z2)
        glEnd()

        glBegin(GL_POLYGON)  # top face
        glNormal3f(0.0, 1.0, 0.0)
        glTexCoord2f(0, 1)
        glVertex3f(x1, y2, z2)
        glTexCoord2f(1, 1)
        glVertex3f(x2, y2, z2)
        glTexCoord2f(1, 0)
        glVertex3f(x2, y2, z1)
        glTexCoord2f(0, 0)
        glVertex3f(x1, y2, z1)
        glEnd()

        glBegin(GL_POLYGON)  # bottom face
        glNormal3f(0.0, -1.0, 0.0)
        glTexCoord2f(1, 1)
        glVertex3f(x2, y1, z2)
        glTexCoord2f(1, 0)
        glVertex3f(x1, y1, z2)
        glTexCoord2f(0, 0)
        glVertex3f(x1, y1, z1)
        glTexCoord2f(0, 1)
        glVertex3f(x2, y1, z1)
        glEnd()

    @staticmethod
    def __draw_coordinates():
        glLineWidth(2)
        glColor3f(1, 0, 0)
        glBegin(GL_LINES)
        glVertex3f(0, 0, 0)
        glVertex3f(10, 0, 0)
        glEnd()

        glLineWidth(2)
        glColor3f(0, 1, 0)
        glBegin(GL_LINES)
        glVertex3f(0, 0, 0)
        glVertex3f(0, 10, 0)
        glEnd()

        glLineWidth(2)
        glColor3f(0, 0, 1)
        glBegin(GL_LINES)

        glVertex3f(0, 0, 0)
        glVertex3f(0, 0, 10)
        glEnd()

    def __load_world_texture(self):
        image = self.world_image.image
        self.world_image_width = image.size[0]
        self.world_image_height = image.size[1]
        image = image.tobytes('raw', 'RGBA', 0, -1)
        texture = glGenTextures(1)

        glBindTexture(GL_TEXTURE_2D, texture)  # 2d texture (x and y size)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
        gluBuild2DMipmaps(GL_TEXTURE_2D, 3, self.world_image_width, self.world_image_height,
                          GL_RGBA, GL_UNSIGNED_BYTE, image)
        self.world_texture = texture

    def __load_texture(self, filename='SOURCE.jpg', image=None):
        if not image:
            image = Image.open(filename)
        self.image_width = image.size[0]
        self.image_height = image.size[1]
        image = image.tobytes('raw', 'RGBA', 0, -1)
        texture = glGenTextures(1)

        glBindTexture(GL_TEXTURE_2D, texture)  # 2d texture (x and y size)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
        gluBuild2DMipmaps(GL_TEXTURE_2D, 3, self.image_width, self.image_height, GL_RGBA, GL_UNSIGNED_BYTE, image)
        self.texture = texture

    def __init(self):
        glClearColor(0, 0, 0, 0)
        glClearDepth(1.0)
        glDepthFunc(GL_LEQUAL)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_TEXTURE_2D)
        glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
        # self.eye, self.cen, self.up = [0, 0, 5], [3, 3, 0], [0, 1, 1]
        self.eye, self.cen, self.up = self.cp.get_eye_center_up_right(reducing=self.reducing) / self.world_image.reducing
        self.mouse_x, self.mouse_y, self.push = 0, 0, False
        # self.__load_texture(filename=self.filename)
        self.__load_world_texture()
        gluPerspective(60, 1.5, 0.1, 100000)

    def __reshape(self, width, height):
        glViewport(0, 0, width, height)
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(60.0, float(width) / float(height), 1.0, 1000.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        gluLookAt(self.eye[0], self.eye[1], self.eye[2],
                  self.cen[0], self.cen[1], self.cen[2],
                  self.up[0], self.up[1], self.up[2])
        print self.eye, self.cen

    def __display(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        gluLookAt(self.eye[0], self.eye[1], self.eye[2],
                  self.cen[0], self.cen[1], self.cen[2],
                  self.up[0], self.up[1], self.up[2])
        # glLoadIdentity()
        # glTranslatef(1, 0, 3)
        # glRotatef(0, 1, -1, 0)
        # d = 3 / sqrt(3)
        # glTranslatef(d - 1.5, d - 1.5, d - 1.5)
        # glTranslatef(1.5, 1.5, 1.5)  # move cube from the center
        # glRotatef(0, 1.0, 1.0, 0.0)
        # glTranslatef(-1.5, -1.5, -1.5)  # move cube into the center
        # self.__draw_objects()
        self.__draw_ground_by_vertexes()
        self.__draw_coordinates()
        # self.__draw_cube()
        glutSwapBuffers()

    def __e_pressed(self, speed):
        temp = map(lambda a, b: (a - b) * speed / 3.0, self.cen, self.eye)
        self.eye = map(lambda a, t: a + t, self.eye, temp)
        self.cen = map(lambda a, t: a + t, self.cen, temp)

    def __q_pressed(self, speed):
        temp = map(lambda a, b: (a - b) * speed / 3.0, self.cen, self.eye)
        self.eye = map(lambda a, t: a - t, self.eye, temp)
        self.cen = map(lambda a, t: a - t, self.cen, temp)

    def __w_pressed(self, speed):
        self.eye[2] += 3 * speed
        self.cen[2] += 3 * speed

    def __s_pressed(self, speed):
        self.eye[2] -= 3 * speed
        self.cen[2] -= 3 * speed

    def __a_pressed(self, speed):
        cross_vector = normalize(np.cross(np.array(map(lambda a, b: a - b, self.eye, self.cen)),
                                          np.array(self.up)))
        self.eye = map(lambda a, b: a + b * speed, self.eye, cross_vector)
        self.cen = map(lambda a, b: a + b * speed, self.cen, cross_vector)

    def __d_pressed(self, speed):
        cross_vector = normalize(np.cross(np.array(map(lambda a, b: a - b, self.eye, self.cen)),
                                          np.array(self.up)))
        self.eye = map(lambda a, b: a - b * speed, self.eye, cross_vector)
        self.cen = map(lambda a, b: a - b * speed, self.cen, cross_vector)

    def __keyboard(self, key, mx, my):
        speed = 0.8
        print self.cen, self.eye
        {
            'e': self.__e_pressed,
            'q': self.__q_pressed,
            'w': self.__w_pressed,
            'a': self.__a_pressed,
            's': self.__s_pressed,
            'd': self.__d_pressed,
        }[key](speed)

    def __mouse(self, button, mode, pos_x, pos_y):
        if button == GLUT_LEFT_BUTTON:
            self.mouse_x = pos_x
            self.mouse_y = pos_y
            self.push = True if mode == GLUT_DOWN else False

    def __mouse_move(self, pos_x, pos_y):
        if self.push:
            _x, _y = pos_x - self.mouse_x, pos_y - self.mouse_y
            temp = map(lambda a, b: a - b, self.cen, self.eye)
            if _x:
                fx = _x * pi / 180.0 / 20.0
                self.cen[2] = self.eye[2] + sin(fx) * temp[0] + cos(fx) * temp[2]
                self.cen[0] = self.eye[0] + cos(fx) * temp[0] - sin(fx) * temp[2]
            print _x, _y
            if _y:
                self.cen[1] -= _y / 20.0
        self.mouse_x = pos_x
        self.mouse_y = pos_y

    def render(self):
        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(500, 500)
        glutCreateWindow('First Try')
        glutDisplayFunc(self.__display)
        glutReshapeFunc(self.__reshape)
        glutKeyboardFunc(self.__keyboard)
        glutMouseFunc(self.__mouse)
        glutMotionFunc(self.__mouse_move)
        glutIdleFunc(glutPostRedisplay)
        self.__init()
        glutMainLoop()