首页 > 解决方案 > 使用 PyOpenGL 从多个角度呈现纹理投影

问题描述

我对 OpenGL 很陌生。我动手进行相机校准(平移(X,Y,Z),旋转(X,Y,Z),焦距),并且我拥有来自每个相机的图像。另外,我有一个 3d 模型(obj),我设法将其构建到我的 openGL 项目中,并绘制了一个点云。我想将图像投影到我的对象上,如图像中所示:

https://imgur.com/0lmpDcs “投影图像”

但我很难做这个预测。我希望我的投影在 Obj 和点云上都有纹理(看起来很主要)我创建模型的主要循环是:

主绘制循环:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glPushMatrix()
    # Draw the Objects
    for i in range(len(obj)):
        glCallList(obj[i].gl_list)
    # Draw some point Clouds
    Ogl.draw_buffer(buffer_obj, num_of_points, 2)
    glPopMatrix()
    pygame.display.flip()
    pygame.time.wait(20)

我如何上传我的 OBJ 并绘制它们:

class OBJ:
    def __init__(self, filename, swapyz=False, stop_loop=False):
        self.vertices = []
        self.normals = []
        self.texcoords = []
        self.faces = []
        self.stop = stop_loop
        material = None
        self.current_path = os.getcwd()
        try:
            os.chdir(os.path.dirname(filename))
        except Exception, error_found:
            print error_found
            print("Path is broken => %s " % str(os.path.dirname(filename)))
        try:
            for line in open(filename, "r"):
                if line.startswith('#'):
                    continue
                values = line.split()
                if not values:
                    continue
                if values[0] == 'v':
                    v = map(float, values[1:4])
                    if swapyz:
                        v = (v[2] / float(10)) + 5, v[1], (v[0] / float(10)) - 9
                    self.vertices.append(v)
                elif values[0] == 'vn':
                    v = map(float, values[1:4])
                    if swapyz:
                        v = v[2], v[1], v[0]
                    self.normals.append(v)
                elif values[0] == 'vt':
                    self.texcoords.append(map(float, values[1:3]))
                elif values[0] in ('usemtl', 'usemat'):
                    material = values[1]
                elif values[0] == 'mtllib':
                    self.mtl = MTL(values[1])
                elif values[0] == 'f':
                    face = []
                    texcoords = []
                    norms = []
                    for v in values[1:]:
                        w = v.split('/')
                        face.append(int(w[0]))
                        if len(w) >= 2 and len(w[1]) > 0:
                            texcoords.append(int(w[1]))
                        else:
                            texcoords.append(0)
                        if len(w) >= 3 and len(w[2]) > 0:
                            norms.append(int(w[2]))
                        else:
                            norms.append(0)
                    self.faces.append((face, norms, texcoords, material))
        except Exception, error_found:
            print error_found
            print("Couldn't find the Obj file in path %s " % str(filename))
            print("Using Default OBJ file in %s\\Assets" % str(self.current_path))
            os.chdir(self.current_path + "\\Assets")
            for line in open("ground_NFL.obj", "r"):
                if line.startswith('#'):
                    continue
                values = line.split()
                if not values:
                    continue
                if values[0] == 'v':
                    v = map(float, values[1:4])
                    if swapyz:
                        v = (v[2] / float(10)) + 5, v[1], (v[0] / float(10)) - 9
                    self.vertices.append(v)
                elif values[0] == 'vn':
                    v = map(float, values[1:4])
                    if swapyz:
                        v = v[2], v[1], v[0]
                    self.normals.append(v)
                elif values[0] == 'vt':
                    self.texcoords.append(map(float, values[1:3]))
                elif values[0] in ('usemtl', 'usemat'):
                    material = values[1]
                elif values[0] == 'mtllib':
                    self.mtl = MTL(values[1])
                elif values[0] == 'f':
                    face = []
                    texcoords = []
                    norms = []
                    for v in values[1:]:
                        w = v.split('/')
                        face.append(int(w[0]))
                        if len(w) >= 2 and len(w[1]) > 0:
                            texcoords.append(int(w[1]))
                        else:
                            texcoords.append(0)
                        if len(w) >= 3 and len(w[2]) > 0:
                            norms.append(int(w[2]))
                        else:
                            norms.append(0)
                    self.faces.append((face, norms, texcoords, material))
        else:
            print("Obj file %s Was Successfully found" % str(filename))

        self.gl_list = glGenLists(1)
        glNewList(self.gl_list, GL_COMPILE)
        glEnable(GL_TEXTURE_2D)
        glFrontFace(GL_CCW)

        for face in self.faces:
            vertices, normals, texture_coords, material = face

            mtl = self.mtl[material]
            if 'texture_Kd' in mtl:
                # use diffuse texmap
                glBindTexture(GL_TEXTURE_2D, mtl['texture_Kd'])
            else:
                # just use diffuse colour
                glColor(*mtl['Kd'])

            glBegin(GL_POLYGON)

            for i in range(len(vertices)):
                if normals[i] > 0:
                    glNormal3fv(self.normals[normals[i] - 1])
                if texture_coords[i] > 0:
                    glTexCoord2fv(self.texcoords[texture_coords[i] - 1])
                glVertex3fv(self.vertices[vertices[i] - 1])
            glEnd()
        glDisable(GL_TEXTURE_2D)
        glEndList()
        os.chdir(self.current_path)
        print("---- OBJ time = %s ----" % (time.time() - start_time)) 


def MTL(filename):
    start_time = time.time()
    print("---- started MTL ----")
    contents = {}
    mtl = None
    for line in open(filename, "r"):
        if line.startswith('#'):
            continue
        values = line.split()
        if not values:
            continue
        if values[0] == 'newmtl':
            mtl = contents[values[1]] = {}
        elif mtl is None:
            raise ValueError, "mtl file doesn't start with newmtl stmt"
        elif values[0] == 'map_Kd':
            # load the texture referred to by this declaration
            mtl[values[0]] = values[1]
            surf = pygame.image.load(mtl['map_Kd'])
            image = pygame.image.tostring(surf, 'RGBA', 1)
            ix, iy = surf.get_rect().size
            tex_id = mtl['texture_Kd'] = glGenTextures(1)
            glBindTexture(GL_TEXTURE_2D, tex_id)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
        else:
            mtl[values[0]] = map(float, values[1:])
    print("---- MTL time = %s ----" % (time.time() - start_time))
    return contents

我如何上传我的点云并绘制它们:

def create_buffer(vertices, colors):
    start_time = time.time()
    print("---- Started Creating Buffer ----")
    buffer_data = (ctypes.c_float*len(vertices))(*vertices)  # float buffer
    buffer_size = len(vertices)*4                           # buffer size in bytes
    color_buffer = (ctypes.c_float*len(colors))(*colors)
    color_size = len(colors)*4

    vbo = glGenBuffers(2)
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
    glBufferData(GL_ARRAY_BUFFER, buffer_size, buffer_data, GL_STATIC_DRAW)

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
    glBufferData(GL_ARRAY_BUFFER, color_size, color_buffer, GL_STATIC_DRAW)

    glBindBuffer(GL_ARRAY_BUFFER, 0)
    print("---- CreateBuffer time = %s ----" % (time.time() - start_time))
    return vbo


def draw_buffer(vbo, num_of_points, point_size):
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, None)

    glEnableClientState(GL_COLOR_ARRAY)
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
    glColorPointer(3, GL_FLOAT, 0, None)

    glPointSize(point_size)
    glDrawArrays(GL_POINTS, 0, num_of_points)

    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_COLOR_ARRAY)
    glBindBuffer(GL_ARRAY_BUFFER, 0)

我尝试使用这些功能,但缺少某些东西或者它们完全错误:)

def load_image_texture(image_path):
    surf = pygame.image.load(image_path)
    image = pygame.image.tostring(surf, 'RGBA', 1)
    ix, iy = surf.get_rect().size
    tex_id = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, tex_id)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)


def load_texture_projection(x,y,z,rot_x,rot_y,rot_z):
    glMatrixMode(GL_TEXTURE)
    glLoadIdentity()
    glTranslatef(x, y, z)
    glRotatef(1, rot_x, rot_y, rot_z)
    glMatrixMode(GL_MODELVIEW)

标签: pythonopengltexturespyopenglopengl-compat

解决方案


推荐阅读