使用opengl绘制茶壶并实现鼠标拖动

难点如下:

        坐标轴绘制

 

 

        选定一个原点,将坐标轴正方向和反方向的俩个点进行连线,代码及效果如上图所示(本次程序中由于渲染原因,坐标轴颜色统一为棕色)

        如何实现鼠标响应

        OPENGL中封存有对鼠标进行相应的函数,但使用起来无法实现效果,于是我们需要进行一些偏移量计算以完成角度的拖拽,这在一定程度上给参考了solidworks中3D物品旋转的方式。

        1.计算鼠标距上一帧的偏移量。

        2.把偏移量添加到摄像机的俯仰角和偏航角中。

        3.对偏航角和俯仰角进行最大和最小值的限制。

        4.计算方向向量。

        5.将其封装到函数中

    

关键代码如上图所示

完整代码如下:

import numpy as np
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


IS_PERSPECTIVE = True  # 透视投影
VIEW = np.array([-0.8, 0.8, -0.8, 0.8, 0.5, 20.0])  # 视景体的left/right/bottom/top/near/far六个面
LEFT_IS_DOWNED = False
CameraPos = np.array([0.0, 0.0, 2])
CameraFront = np.array([0, 0, 0])
CameraUp = np.array([0, 1, 0])
SCALE_K = np.array([1, 1, 1])
yaw = 0
pitch = 0
MOUSE_X, MOUSE_Y = 0, 0
WIN_W = 640
WIN_H = 480

class MyPyOpenGLTest:
    def Mouse_click(self,button, state, x, y):
        global LEFT_IS_DOWNED
        global MOUSE_X, MOUSE_Y
        global SCALE_K
        MOUSE_X = x
        MOUSE_Y = y
        if button == GLUT_LEFT_BUTTON:
            LEFT_IS_DOWNED = state == GLUT_DOWN
    def Mouse_motion(self,x, y):
        global LEFT_IS_DOWNED
        global MOUSE_X, MOUSE_Y
        global yaw, pitch
        global CameraPos
        if LEFT_IS_DOWNED:
            dx = x - MOUSE_X
            dy = MOUSE_Y - y
            MOUSE_X = x
            MOUSE_Y = y
            sensitivity = 0.2
            dx = dx * sensitivity
            dy = dy * sensitivity
            yaw = yaw + dx
            pitch = pitch + dy
            if pitch > 89:
                pitch = 89
            if pitch < -89:
                pitch = -89
            CameraPos[0] = np.cos(np.radians(yaw)) * np.cos(np.radians(pitch))
            CameraPos[1] = np.sin(np.radians(pitch))
            CameraPos[2] = np.sin(np.radians(yaw)) * np.cos(np.radians(pitch))
            glutPostRedisplay()
    def __init__(self,width=640,height=480,title=b'SolidTeapot'):
        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH)
        glutInitWindowSize(width,height)
        self.window=glutCreateWindow(title)
        glutDisplayFunc(self.Draw)

        glutKeyboardFunc(self.BarPress)
        glutIdleFunc(self.Draw)
        self.InitGL(width,height)
        glutMouseFunc(self.Mouse_click)
        glutMotionFunc(self.Mouse_motion)

        self.x=0.0
        self.y=0.0
        self.z=0.0

        self.s=0.2
    def BarPress(self, key, x, y):
        if key==b'a':
            self.x+=1
        elif key ==b'd':
            self.x-=1
        elif key ==b'w':
            self.y+=1
        elif key ==b's':
            self.y-=1
        elif key ==b'q':
            self.z-=1
        elif key ==b'e':
            self.z+=1
        elif key ==b'x':
            self.s-=0.1
        elif key ==b'z':
            self.s+=0.1
    def Draw(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslate(0.0,0.0,-8.0)
        global IS_PERSPECTIVE, VIEW
        global CameraPos, CameraFront, CameraUp
        global SCALE_K
        global WIN_W, WIN_H
        global vertices2

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        # 设置投影(透视投影)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()

        if IS_PERSPECTIVE:
            glFrustum(VIEW[0], VIEW[1], VIEW[2], VIEW[3], VIEW[4], VIEW[5])

        # 设置模型视图
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        # 几何变换
        glScale(SCALE_K[0], SCALE_K[1], SCALE_K[2])

        # 视点
        gluLookAt(
            CameraPos[0], CameraPos[1], CameraPos[2],
            CameraFront[0], CameraFront[1], CameraFront[2],
            CameraUp[0], CameraUp[1], CameraUp[2]
        )

        glViewport(0, 0, WIN_W, WIN_H)

        glBegin(GL_LINES)

        # 以红色绘制x轴
        glColor3f(1.0, 0.0, 0.0)  # 设置当前颜色为红色不透明
        glVertex3f(-0.5, 0.0, 0.0)  # 设置x轴顶点(x轴负方向)
        glVertex3f(0.5, 0.0, 0.0)  # 设置x轴顶点(x轴正方向)

        # 以绿色绘制y轴
        glColor3f(0.0, 1.0, 0.0)  # 设置当前颜色为绿色不透明
        glVertex3f(0.0, -0.5, 0.0)  # 设置y轴顶点(y轴负方向)
        glVertex3f(0.0, 0.5, 0.0)  # 设置y轴顶点(y轴正方向)

        # 以蓝色绘制z轴
        glColor3f(0.0, 0.0, 1.0)  # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.0, -0.5)  # 设置z轴顶点(z轴负方向)
        glVertex3f(0.0, 0.0, 0.5)  # 设置z轴顶点(z轴正方向)

        glEnd()
        glRotate(self.x,1.0,0.0,0.0)
        glRotate(self.y, 0.0, 1.0, 0.0)
        glRotate(self.z, 0.0, 0.0, 1.0)
        glScalef(self.s,self.s,self.s)
        glColor3f(0.0,0.0,1.0)
        glutSolidTeapot(1.0)

        glutSwapBuffers()
    def InitGL(self,width,height):
        glClearColor(1.0,1.0,1.0,0.0)
        glClearDepth(1.0)
        glDepthFunc(GL_LESS)

        mat_SP=(1.0,1.0,1.0,1.0)
        mat_sh=[50.0]
        light_position=(-0.5,1.5,1,0)
        yellow_l=(1.0,0.1,0,1)
        ambient=(0.1,0.8,0.2,1.0)

        glMaterialfv(GL_FRONT,GL_SPECULAR,mat_SP)
        glMaterialfv(GL_FRONT,GL_SHININESS,mat_sh)
        glLightfv(GL_LIGHT0,GL_POSITION,light_position)
        glLightfv(GL_LIGHT0,GL_DIFFUSE ,yellow_l )
        glLightfv(GL_LIGHT0,GL_SPECULAR ,yellow_l )
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient)

        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_DEPTH_TEST)

        glEnable(GL_BLEND)
        glShadeModel(GL_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POLYGON_SMOOTH)
        glMatrixMode(GL_PROJECTION)

        glHint(GL_POINT_SMOOTH_HINT,GL_NICEST)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST)
        glLoadIdentity()

        gluPerspective(45.0,float(width)/float(height),0.1,100.0)
        glMatrixMode(GL_MODELVIEW)
    def MainLoop(self):
        glutMainLoop()

if __name__=='__main__':
        w=MyPyOpenGLTest()
        w.MainLoop()



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值