渲染模型在某个时刻消失

2024-09-21 05:25:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在尝试用PyOpenGL渲染一个简单的茶壶,但是遇到了一些奇怪的问题。尽管代码很简单,但我似乎无法准确地找出错误的来源。你知道吗

你知道吗主.py你知道吗

import pygame
from pygame.locals import *
from MV import *
import ctypes
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GLU import *
import teapot as tp

vertex_shader = '''
#version 420

in vec3 vpos_modelspace;
in vec3 vnorm_modelspace;
uniform mat4 mvp;
out vec4 vertcolor;

void main(){
    vertcolor = vec4(vnorm_modelspace, 1.0);
    gl_Position = mvp * vec4(vpos_modelspace, 1.0);
}
'''

fragment_shader = '''
#version 420

in vec4 vertcolor;
out vec4 fragcolor;

void main(){
    fragcolor = vertcolor;
}
'''

model = tp.teapot

pygame.init()
canvas = pygame.display.set_mode((800, 600), DOUBLEBUF|OPENGL)
pygame.display.set_caption('Test')
glClearColor(.5, .5, .5, 1)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glDisable(GL_CULL_FACE)
VERTEXSHADER = shaders.compileShader(vertex_shader, GL_VERTEX_SHADER)
FRAGMENTSHADER = shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER)
program = shaders.compileProgram(VERTEXSHADER, FRAGMENTSHADER)
glUseProgram(program)

vpos_loc = glGetAttribLocation(program, 'vpos_modelspace')
vnorm_loc = glGetAttribLocation(program, 'vnorm_modelspace')
mvp_loc = glGetUniformLocation(program, 'mvp')

eye = numpy.array([0, 0, 1], dtype=numpy.float32)
at = numpy.array([0, 0, 0], dtype=numpy.float32)
up = numpy.array([0, 1, 0], dtype=numpy.float32)

mvp = frustum(-1, 1, 1, -1, .1, 1000)@lookAt(eye, at, up)

vao = glGenVertexArrays(1)
glBindVertexArray(vao)

vbo_pos = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo_pos)

vbo_norm = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo_norm)

verts = []
normals = []
for i in range(0, len(model.faces), 3):
    index = model.faces[i:i+3]
    verts.extend(model.vertices[3*index[0]:3*index[0]+3])
    verts.extend(model.vertices[3*index[1]:3*index[1]+3])
    verts.extend(model.vertices[3*index[2]:3*index[2]+3])
    normals.extend(model.normals[3*index[0]:3*index[0]+3])
    normals.extend(model.normals[3*index[1]:3*index[1]+3])
    normals.extend(model.normals[3*index[2]:3*index[2]+3])

verts = numpy.array(verts, dtype=numpy.float32)
normals = numpy.array(normals, dtype=numpy.float32)

glBindBuffer(GL_ARRAY_BUFFER, vbo_pos)
glBufferData(GL_ARRAY_BUFFER, verts.size * verts.itemsize, verts, GL_STATIC_DRAW)

glVertexAttribPointer(vpos_loc, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(vpos_loc)

glBindBuffer(GL_ARRAY_BUFFER, vbo_norm)
glBufferData(GL_ARRAY_BUFFER, normals.size * normals.itemsize, normals, GL_STATIC_DRAW)

glVertexAttribPointer(vnorm_loc, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(vnorm_loc)

glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)

while(True):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
    glUseProgram(program)
    rotation_matrix = rotate(.01, [0, 1, 0])
    mvp =  mvp @ rotation_matrix
    glUniformMatrix4fv(mvp_loc, 1, GL_FALSE, mvp.flatten())
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

    glBindVertexArray(vao)
    glDrawArrays(GL_TRIANGLES, 0, int(verts.size/3))
    glBindVertexArray(0)
    glUseProgram(0)
    pygame.display.flip()

main()

你知道吗中压比你知道吗

import numpy

def normalize(vector):
    return vector/numpy.linalg.norm(vector)

def translate(pos):
    return numpy.array([[1, 0, 0, pos[0]],
                        [0, 1, 0, pos[1]],
                        [0, 0, 1, pos[2]],
                        [0, 0, 0, 1]], dtype=numpy.float32)

def rotate(angle, axis):
    rads = angle * numpy.pi/180
    v = normalize(axis)
    c = numpy.cos(rads)
    omc = 1-c
    s = numpy.sin(rads)
    return numpy.array([[v[0]*v[0]*omc + c,   v[0]*v[1]*omc - v[2]*s, v[0]*v[2]*omc + v[1]*s, 0],
                        [v[0]*v[1]*omc + v[2]*s, v[1]*v[1]*omc + c,   v[1]*v[2]*omc - v[0]*s, 0],
                        [v[0]*v[2]*omc - v[1]*s, v[1]*v[2]*omc + v[0]*s, v[2]*v[2]*omc + c,   0],
                        [0, 0, 0, 1]], dtype=numpy.float32)

def lookAt(eye, at, up):
    n = normalize(at-eye)
    u = normalize(numpy.cross(n, up))
    v = normalize(numpy.cross(u, n))

    rotate = numpy.array([[u[0], v[0], -n[0], 0],
                          [u[1], v[1], -n[1], 0],
                          [u[2], v[2], -n[2], 0],
                          [0,    0,    0,    1]], dtype=numpy.float32).transpose()
    return rotate@translate(-eye)

def frustum(left, right, top, bottom, near, far):
    rl = right-left
    tb = top-bottom
    fn = far-near

    return numpy.array([[2*near/rl, 0,         (right+left)/rl, 0],
                        [0,         2*near/tb, (top+bottom)/tb, 0],
                        [0,         0,        -(far+near)/fn,   -(2*far*near)/fn],
                        [0,         0,        -1,               0]], dtype=numpy.float32)

输出显示茶壶正在旋转(虽然不是围绕我预期的轴旋转),并且在旋转0、pi、2pi等时有点收缩和消失。我相信茶壶顶点正在正确处理,因为它在旋转时确实显示出来,并且用正常值正确着色。你知道吗

5度输出-模型正在“增长” enter image description here

30度输出-奇怪的剔除? enter image description here

60度输出-相对正常 enter image description here

170度时的输出-模型正在“收缩” enter image description here

190度时的输出-模型在飞机的另一侧“增长” enter image description here

在旋转0、pi、2pi等时,模型完全看不见/太小而看不见。你知道吗


Tags: importnumpyindexmodelbufferarraypygameloc

热门问题