Exemplo n.º 1
0
class MotionRender:
    class VertexAttributes(Enum):
        """ Name of each used vertex attribute"""
        Position = {"name": "in_Position", "location": 0}
        Normal = {"name": "in_Normal", "location": 1}

    def __init__(self, skeleton=None):
        self._cylinder_mem_info = None
        self._sphere_mem_info = None
        self._skeleton = None
        self._skeleton_trans = None
        self._motion_cache = {}
        self._character_color = glm.vec4(124.0 / 255.0, 174.0 / 255.0,
                                         255.0 / 255.0, 1.0)
        self._joints_color = glm.vec4(200.0 / 255.0, 200.0 / 255.0,
                                      200.0 / 255.0, 1.0)
        self._uniforms = {}

        self._setup_render_matrices()
        self._setup_ligthing()
        self._create_shaders()
        self._create_mesh_data()
        self._create_gl_objects()

        self.add_motion(skeleton)

    def set_render_matrices(self, view, project):
        self._view_matrix = view
        self._proj_matrix = project

    def _on_draw_part(self, ntype, name, transform, length, rest_rot):
        render_data = RENDER_DATA.get(ntype)
        if render_data is None or not render_data.enabled:
            return

        GL.glBindVertexArray(self._vao)

        # Draw body Parts
        scale = glm.scale(glm.mat4(), glm.vec3(0.5, max(length, 0.5), 0.5))
        model = transform * rest_rot * scale

        GL.glUniformMatrix4fv(self._uniforms['model_mat_loc'], 1, GL.GL_FALSE,
                              np.ascontiguousarray(model))
        GL.glUniform4fv(self._uniforms['character_color_loc'], 1,
                        np.ascontiguousarray(self._character_color))

        GL.glDrawArrays(GL.GL_TRIANGLES, self._cylinder_mem_info[0],
                        self._cylinder_mem_info[1])

        # Draw joints
        # Ignoring the following parts

        # NodeType.UPPER_ARM: RightShoulder
        # NodeType.UPPER_ARM: LeftShoulder
        # NodeType.TORSO    : RHipJoint
        # NodeType.TORSO    : LHipJoint
        # NodeType.FINGER   : LThumb
        # NodeType.FINGER   : LeftFingerBase
        # NodeType.FINGER   : LeftHandIndex1
        IGNORED_PARTS = [NT.TORSO, NT.UPPER_ARM, NT.FINGER]
        if ntype not in IGNORED_PARTS:
            scale = glm.scale(glm.mat4(), glm.vec3(0.55, 0.55, 0.55))
            model = transform * rest_rot * scale

            GL.glUniformMatrix4fv(self._uniforms['model_mat_loc'], 1,
                                  GL.GL_FALSE, np.ascontiguousarray(model))
            GL.glUniform4fv(self._uniforms['character_color_loc'], 1,
                            np.ascontiguousarray(self._joints_color))

            GL.glDrawArrays(GL.GL_TRIANGLES, self._sphere_mem_info[0],
                            self._sphere_mem_info[1])

    def set_color(self, color):
        self._character_color = color

    def draw(self, frame):
        if self._skeleton is None:
            return

        frame = frame % self._skeleton.frame_count

        # TODO: remove these strings
        self._uniforms = {
            'model_mat_loc':
            self._shader_program.uniform_location("modelMatrix"),
            'view_mat_loc':
            self._shader_program.uniform_location("viewMatrix"),
            'proj_mat_loc':
            self._shader_program.uniform_location("projectionMatrix"),
            'normal_mat_loc':
            self._shader_program.uniform_location("normalMatrix"),
            'character_color_loc':
            self._shader_program.uniform_location("characterColor"),
            #'ambient_color_loc': self._shader_program.uniform_location("ambientColor"),
            #'specular_color_loc': self._shader_program.uniform_location("specularColor"),
            #'shininess_loc': self._shader_program.uniform_location("shininess")
        }

        # Setting all shared data
        self._shader_program.bind()

        GL.glUniformMatrix4fv(self._uniforms['view_mat_loc'], 1, GL.GL_FALSE,
                              np.ascontiguousarray(self._view_matrix))
        GL.glUniformMatrix4fv(self._uniforms['proj_mat_loc'], 1, GL.GL_FALSE,
                              np.ascontiguousarray(self._proj_matrix))

        self._skeleton.traverse(frame, self._on_draw_part,
                                self._skeleton_trans)

    def clean_up(self):
        """This function frees all used resources. It includes all VBO's, VAO's, and so on.
        It must be explicitly called since there is no guarantee that there will be a a  OpenGL
        context when this object is garbage collected.
        """

        GL.glDeleteVertexArrays(1, self._vao)
        GL.glDeleteBuffers(1, self._vertex_bo)
        GL.glDeleteBuffers(1, self._normal_bo)

    def add_motion(self, motion, trans=glm.mat4()):
        self._skeleton = motion
        self._skeleton_trans = trans

    def _setup_render_matrices(self):
        """It simply initializes model, view, and projection matrices"""

        self._view_matrix = glm.mat4()
        self._proj_matrix = glm.mat4()

    def _setup_ligthing(self):
        """Setup shading colors"""

        self._diffuse_color = glm.vec4(0.26, 0.80, 0.26, 1.0)
        self._ambient_color = self._diffuse_color * 0.3
        self._specular_color = glm.vec4(0.84, 0.30, 0.74, 1.0)
        self._shininess = 64

    def _create_shaders(self):
        """Creates the shader program"""

        self._shader_program = ShaderProgram(self._get_vertex_shader_fn(),
                                             self._get_fragent_shader_fn())

        # Setup Vertex Attributes
        for _, attrib in MotionRender.VertexAttributes.__members__.items():
            self._shader_program.bind_attribute(attrib.value["location"],
                                                attrib.value["name"])

        self._shader_program.compile()

    def _create_mesh_data(self):
        """All mesh data is created by this function. So far, it basically creates one
        cube that will be used to draw the squared characters. Each character's body part
        is drawn as cube.

        TODO: It should be generalized to support multiple rendering styles.
        """
        #vertices, normals = mesh.create_cube_mesh()
        cylinder_mesh = mesh.create_cylinder_mesh(15)
        sphere_mesh = mesh.create_sphere_mesh(30)

        self._vertices = np.concatenate(
            (cylinder_mesh.vertices, sphere_mesh.vertices))
        self._normals = np.concatenate(
            (cylinder_mesh.normals, sphere_mesh.normals))

        self._cylinder_mem_info = (0, len(cylinder_mesh.vertices) // 3)
        self._sphere_mem_info = (len(cylinder_mesh.vertices) // 3,
                                 len(sphere_mesh.vertices) // 3)

    def _create_gl_objects(self):
        """This function creates and initiliazes all opengl objects needed to render the character."""

        self._vao = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(self._vao)

        # Generate buffer object for the mesh vertices
        self._vertex_bo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._vertex_bo)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, self._vertices.nbytes,
                        self._vertices, GL.GL_STATIC_DRAW)

        # Setup Vertex Attrib Pointer
        pos_attrib_pointer = MotionRender.VertexAttributes.Position.value[
            "location"]
        GL.glEnableVertexAttribArray(pos_attrib_pointer)
        GL.glVertexAttribPointer(pos_attrib_pointer, 3, GL.GL_FLOAT, False, 0,
                                 ctypes.c_void_p(0))

        self._normal_bo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._normal_bo)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, self._normals.nbytes,
                        self._normals, GL.GL_STATIC_DRAW)

        normal_attrib_pointer = MotionRender.VertexAttributes.Normal.value[
            "location"]
        GL.glEnableVertexAttribArray(normal_attrib_pointer)
        GL.glVertexAttribPointer(normal_attrib_pointer, 3, GL.GL_FLOAT, False,
                                 0, ctypes.c_void_p(0))

        # Unbind each used GL object
        GL.glBindVertexArray(0)
        GL.glDisableVertexAttribArray(pos_attrib_pointer)
        GL.glDisableVertexAttribArray(normal_attrib_pointer)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)

    def _get_vertex_shader_fn(self):
        return "./shaders/squared_character.vs"

    def _get_fragent_shader_fn(self):
        return "./shaders/squared_character.fs"
Exemplo n.º 2
0
class EnvironmentRender:
    class VertexAttributes(Enum):
        """ Name of each used vertex attribute"""
        Position = {"name": "in_Position", "location": 0}
        Normal = {"name": "in_Normal", "location": 1}
        TexCoord = {"name": "in_TexCoord", "location": 2}

    def __init__(self):
        self._shader_program = ShaderProgram(self._get_floor_vs_fn(), self._get_floor_fs_fn())
        for _, attrib in EnvironmentRender.VertexAttributes.__members__.items():
            self._shader_program.bind_attribute(attrib.value["location"], attrib.value["name"])
        self._shader_program.compile()

        vertices, normals, texcoords = mesh.create_grid_mesh(1000, 1000, 100)
        self._vertices = np.asarray(vertices, dtype=np.float32)
        self._normals = np.asarray(normals, dtype=np.float32)
        self._texcoords = np.asarray(texcoords, dtype=np.float32)

        print(self._texcoords)

        self._vao = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(self._vao)

        # Generate buffer object for the mesh vertices
        self._vertex_bo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._vertex_bo)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, self._vertices.nbytes,
                        self._vertices, GL.GL_STATIC_DRAW)

        # Setup Vertex Attrib Pointer
        pos_attrib_pointer = EnvironmentRender.VertexAttributes.Position.value["location"]
        GL.glEnableVertexAttribArray(pos_attrib_pointer)
        GL.glVertexAttribPointer(pos_attrib_pointer, 3, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0))

        self._normal_bo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._normal_bo)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, self._normals.nbytes,
                        self._normals, GL.GL_STATIC_DRAW)

        normal_attrib_pointer = EnvironmentRender.VertexAttributes.Normal.value["location"]
        GL.glEnableVertexAttribArray(normal_attrib_pointer)
        GL.glVertexAttribPointer(normal_attrib_pointer, 3, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0))

        self._texcoord_bo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._texcoord_bo)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, self._texcoords.nbytes, self._texcoords, GL.GL_STATIC_DRAW)

        texcoord_attrib_pointer = EnvironmentRender.VertexAttributes.TexCoord.value["location"]
        GL.glEnableVertexAttribArray(texcoord_attrib_pointer)
        GL.glVertexAttribPointer(texcoord_attrib_pointer, 2, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0))

        # Unbind each used GL object
        GL.glBindVertexArray(0)
        GL.glDisableVertexAttribArray(pos_attrib_pointer)
        GL.glDisableVertexAttribArray(normal_attrib_pointer)
        GL.glDisableVertexAttribArray(texcoord_attrib_pointer)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)

        floor_image = PIL.Image.open('textures/floor.png')
        floor_texture_data = np.array(list(floor_image.getdata()), np.uint8)
        self.floor_texture = GL.glGenTextures(1)
        GL.glBindTexture(GL.GL_TEXTURE_2D, self.floor_texture)
        GL.glTexParameterf(GL.GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0); 
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR)
        GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, floor_image.size[0], floor_image.size[1], 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, floor_texture_data)
        GL.glGenerateMipmap(GL.GL_TEXTURE_2D)

    def set_render_matrices(self, view, projection):
        self._view_matrix = view
        self._proj_matrix = projection

    def draw(self):
        self._shader_program.bind()
        GL.glEnable(GL.GL_DEPTH_TEST)

        model_loc = self._shader_program.uniform_location('modelMatrix')
        view_loc = self._shader_program.uniform_location('viewMatrix')
        proj_loc = self._shader_program.uniform_location('projectionMatrix')
        sampler_loc = self._shader_program.uniform_location('color_map')

        FLOOR_SIZE = 1
        scale = glm.scale(glm.mat4(), glm.vec3(FLOOR_SIZE, 1, FLOOR_SIZE)) * glm.translate(glm.mat4(), glm.vec3(0.0, -20.0, 0.0))

        GL.glUniformMatrix4fv(model_loc, 1, GL.GL_FALSE, np.ascontiguousarray(scale))
        GL.glUniformMatrix4fv(view_loc, 1, GL.GL_FALSE, np.ascontiguousarray(self._view_matrix))
        GL.glUniformMatrix4fv(proj_loc, 1, GL.GL_FALSE, np.ascontiguousarray(self._proj_matrix))

        GL.glActiveTexture(GL.GL_TEXTURE0)
        GL.glBindTexture(GL.GL_TEXTURE_2D, self.floor_texture)
        GL.glUniform1i(sampler_loc, 0)

        GL.glBindVertexArray(self._vao)
        GL.glDrawArrays(GL.GL_TRIANGLES, 0, int(self._vertices.size / 3))

    def _get_floor_vs_fn(self):
        return './shaders/floor.vs'

    def _get_floor_fs_fn(self):
        return './shaders/floor.fs'