我想要身体健康 2023-01-22 13:23 采纳率: 100%
浏览 95
已结题

OpenGL框选动画

问题遇到的现象和发生背景

你好,我需要OpenGL实现框选的动画,就是鼠标按下移动时会跟随鼠标生成矩形,松开时矩形消失

遇到的现象和发生背景,请写出第一个错误信息

顶点应该是正确的,但窗口上没有图像

用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
import numpy as np
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GL import shaders


class RectPainter():
    def __init__(self):
        """准备模型数据"""
        vshader_src = """
            #version 420 core
            layout (location = 0) in vec3 aPos;
            void main(){ 
                gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); // gl_Position是内置变量
            }
        """

        fshader_src = """
            #version 420 core
            out vec4 frag_color;
            void main(){
                frag_color = vec4(1.0f, 0.5f, 0.2f, 1.0f);// gl_FragColor是内置变量    
            } 
        """
        vshader = shaders.compileShader(vshader_src, GL_VERTEX_SHADER)
        fshader = shaders.compileShader(fshader_src, GL_FRAGMENT_SHADER)
        self.PROGRAM = shaders.compileProgram(vshader, fshader)
        self.start_x = 0
        self.start_y = 0
        self.end_x = 0
        self.end_y = 0
        self.clear_flag = False
        self.vao = glGenVertexArrays(1) 
        self.vertices_buffer = glGenBuffers(1)

    def draw(self):
        """绘制模型"""
        glClearColor(178 / 255, 195 / 255, 234 / 255, 0.5)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)  # 清除缓冲区
        glUseProgram(self.PROGRAM)
        glBindVertexArray(self.vao)
        if self.clear_flag is True:
            self.start_x = 0
            self.start_y = 0
            self.end_x = 0
            self.end_y = 0
        # 顶点数据
        vertices = [[self.start_x, self.start_y, 0.0], [self.end_x, self.start_y, 0.0], [self.end_x, self.end_y, 0.0], [self.start_x, self.end_y, 0.0]]
        vertices = np.array(vertices, dtype=np.float32)

        glBindBuffer(GL_ARRAY_BUFFER, self.vertices_buffer)
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_DYNAMIC_DRAW)  # 动态绘制
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
        glEnableVertexAttribArray(0)
        # 绘制
        print("四点数据:", vertices)
        glDrawArrays(GL_LINE_LOOP, 0, 4)
        # 结束
        glBindVertexArray(0)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glUseProgram(0)
        glFlush()  # 执行缓冲区指令


def mymouse(button, state, x, y):
    if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN:
        painter.start_x, painter.start_y = x, y
        painter.end_x, painter.end_y = x, y
        painter.clear_flag = False
    elif button == GLUT_LEFT_BUTTON and state == GLUT_UP:
        painter.end_x, painter.end_y = x, y
        painter.clear_flag = True
        glutPostRedisplay()#update

    '''
    glutPostRedisplay()是一个OpenGL函数,用于重绘当前窗口。
    它通知OpenGL重新渲染整个窗口,以便更新视图。
    这通常用于动画等场景,在窗口大小、位置或其他视图参数发生变化时也会调用。
    '''

def mymotion(x, y):
    painter.end_x, painter.end_y = x, y
    glutPostRedisplay()#update


if __name__ == "__main__":
    glutInit()  # 1. 初始化glut库
    glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE)  # 2. 设置显示模式
    glutInitWindowSize(600, 400)  # 3. 设置窗口大小
    glutCreateWindow('OpenGL Demo')  # 2. 创建glut窗口
    painter = RectPainter()  # 3. 生成着色器程序、顶点数据集、颜色数据集
    glutDisplayFunc(painter.draw)  # 4. 绑定模型绘制函数
    glutMouseFunc(mymouse)  # 5. 绑定鼠标事件
    glutMotionFunc(mymotion)
    glutMainLoop()  # 6. 进入glut主循环


我的解答思路和尝试过的方法

定义一个类RectPainter,包含了初始化,绘图方法,重写鼠标点击,释放事件,在点击释放时记录坐标,释放时clear_flag为True,这样绘制时顶点坐标重置为0(不绘制)同时更新画面,重写鼠标移动事件,鼠标移动时记录坐标并更新画面

  • 写回答

1条回答 默认 最新

  • P2441M 2023-01-26 21:21
    关注

    OpenGL 使用 NDC(标准化设备坐标) 作为坐标系啊,中心是(0,0),右上角是(1,1),左下角是(-1,-1),所以要把屏幕坐标转换为 NDC 坐标

    vert_start_x = self.start_x / 300 - 1
    vert_start_y = 1 - self.start_y / 200
    vert_end_x = self.end_x / 300 - 1
    vert_end_y = 1 - self.end_y / 200
    # 顶点数据
    vertices = [[vert_start_x, vert_start_y, 0.0], [vert_end_x, vert_start_y, 0.0], [vert_end_x, vert_end_y, 0.0], [vert_start_x, vert_end_y, 0.0]]
    vertices = np.array(vertices, dtype=np.float32)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 2月4日
  • 已采纳回答 1月27日
  • 创建了问题 1月22日

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分