我想要身体健康 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 MATLAB代码求涡量
  • ¥100 采用栈和深度优先算法对我的代码进行修改显示路径
  • ¥15 pointnet2包安装
  • ¥20 射频功率问题,解答者有酬谢!
  • ¥80 构建降雨和积水的预测模型
  • ¥15 #Qt Transform setTransform()在鼠标拖动移动视角是一致在原地不动,无法变换视角(细微观察似乎视图有在原地抖动),无法变换视角(细微观察似乎视图有在原地抖动)
  • ¥50 如何利用无人机拍摄的数码照片测量鸟卵的长短径
  • ¥100 github贡献者给与奖励
  • ¥15 使用DS18B20+ESP8266获取温度数据返回-127.00
  • ¥15 odbc代码新增sqlserver数据源