python 管线原理图_Python之OpenGL笔记(25):动态管线绘制球体

这篇博客介绍了如何利用Python的OpenGL库绘制一个球体,包括球体的生成、多边形显示方式的控制以及源代码实现。通过将球体横向和纵向切片,计算每个点的空间坐标,并使用OpenGL动态管线进行渲染。最后展示了源代码,包含顶点缓冲区和索引缓冲区的使用,以及动态更新旋转角度以实现动态效果。
摘要由CSDN通过智能技术生成

一、目的

1、画一个球体;

二、程序运行结果

球体

三、球体的生成

球面坐标计算示意图

1、将球体横向向切成30片, 纵向切30片,共900个点,见示意图

2、循环生成900个点的空间坐标(x,y,z),球面上点C的坐标

3、 x= R * cos(NumAngleHy) * cos(NumAngleZx)

4、 y = R * sin(NumAngleHy)

5、 z = R * cos(NumAngleHy) * sin(NumAngleZx)

6、将900个点按顺序存入顶点缓冲区,

7、将相邻的三个点的顺序索引值存入索引缓冲区。

8、调用OpenGL动态管线进行渲染。

四、glPolygonMode函数

功能:用于控制多边形的显示方式

glPolygonMode是一个函数,原型是:void glPolygonMode(GLenum face,GLenum mode);

face这个参数确定显示模式将适用于物体的哪些部分,控制多边形的正面和背面的绘图模式:

GL_FRONT表示显示模式将适用于物体的前向面(也就是物体能看到的面)

GL_BACK表示显示模式将适用于物体的后向面(也就是物体上不能看到的面)

GL_FRONT_AND_BACK表示显示模式将适用于物体的所有面

mode这个参数确定选中的物体的面以何种方式显示(显示模式):

GL_POINT表示显示顶点,多边形用点显示

GL_LINE表示显示线段,多边形用轮廓显示

GL_FILL表示显示面,多边形采用填充形式

五、源代码

"""

程序名称:GL_DrawSphere01.py

编程: dalong10

功能: 画一个球体

参考资料:

"""

import myGL_Funcs #Common OpenGL utilities,see myGL_Funcs.py

import sys, random, math

import OpenGL

from OpenGL.GL import *

from OpenGL.GL.shaders import *

import numpy

import numpy as np

import glfw

strVS = """

#version 330 core

layout(location = 0) in vec3 position;

uniform mat4 uMVMatrix;

uniform mat4 uPMatrix;

uniform float a;

uniform float b;

uniform float c;

uniform float Rx;

uniform float Ry;

uniform float Rz;

uniform float theta1;

void main(){

mat4 rot1=mat4(vec4(1.0, 0.0,0.0,0),

vec4(0.0, 1.0,0.0,0),

vec4(0.0,0.0,1.0,0.0),

vec4(a,b,c,1.0));

mat4 rot3=mat4( vec4(cos(theta1)+Rx*Rx*(1-cos(theta1)), Rx*Ry*(1-cos(theta1))-Rz*sin(theta1), Rx*Rz*(1-cos(theta1))+Ry*sin(theta1), 0),

vec4(Rx*Ry*(1-cos(theta1))+Rz*sin(theta1),cos(theta1)+Ry*Ry*(1-cos(theta1)),Ry*Rz*(1-cos(theta1))-Rx*sin(theta1),0),

vec4(Rx*Rz*(1-cos(theta1))-Ry*sin(theta1),Ry*Rz*(1-cos(theta1))+Rx*sin(theta1),cos(theta1)+Rz*Rz*(1-cos(theta1)), 0.0),

vec4(0.0, 0.0,0.0, 1.0));

gl_Position=uPMatrix * uMVMatrix* rot1 *rot3 *vec4(position.x, position.y, position.z, 1.0);

}

"""

strFS = """

#version 330 core

out vec3 color;

void main(){

color = vec3(0,1,1);

}

"""

VIEW=np.array([-0.8, 0.8, -0.8, 0.8, 1.0, 20.0]) # 视景体的left/right/bottom/top/near/far六个面

SCALE_K=np.array([1.0, 1.0, 1.0]) # 模型缩放比例

cameraPos=np.array([0.0, 0.0, 1.2]) # 眼睛的位置(默认z轴的正方向)

cameraFront=np.array([0.0, 0.0, 0.0]) # 瞄准方向的参考点(默认在坐标原点)

cameraUp=np.array([0.0, 1.0, 0.0]) # 定义对观察者而言的上方(默认y轴的正方向)

WIN_W, WIN_H = 640, 480 # 保存窗口宽度和高度的变量

class FirstSphere:

def __init__(self, cube_verticeside ,indices):

# load shaders

self.program = myGL_Funcs.loadShaders(strVS, strFS)

glUseProgram(self.program)

self.vertIndex = glGetAttribLocation(self.program, b"position")

cube_vertices = cube_verticeside

self.indices = indices

# set up vertex array object (VAO)

self.vao = glGenVertexArrays(1)

glBindVertexArray(self.vao)

# set up VBOs

vertexData = numpy.array(cube_vertices, numpy.float32)

self.vertexBuffer = glGenBuffers(1)

glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)

glBufferData(GL_ARRAY_BUFFER, 4*len(vertexData), vertexData, GL_STATIC_DRAW)

# set up EBOs

indiceData = numpy.array(indices, numpy.int32)

self.eboID = glGenBuffers(1)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.eboID)

glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 *len(indiceData), indiceData, GL_STATIC_DRAW)

# enable arrays

glEnableVertexAttribArray(self.vertIndex)

# Position attribute

glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)

glVertexAttribPointer(self.vertIndex, 3, GL_FLOAT, GL_FALSE, 0,None)

# unbind VAO

glBindVertexArray(0)

glBindBuffer(GL_ARRAY_BUFFER, 0)

def render(self, xx, yy, zz, Rx,Ry,Rz,r1,pMatrix,mvMatrix):

# use shader

glUseProgram(self.program)

# set proj matrix

glUniformMatrix4fv(glGetUniformLocation(self.program, 'uPMatrix'),

1, GL_FALSE, pMatrix)

# set modelview matrix

glUniformMatrix4fv(glGetUniformLocation(self.program, 'uMVMatrix'),

1, GL_FALSE, mvMatrix)

glUniform1f(glGetUniformLocation(self.program, "a"), xx)

glUniform1f(glGetUniformLocation(self.program, "b"), yy)

glUniform1f(glGetUniformLocation(self.program, "c"), zz)

glUniform1f(glGetUniformLocation(self.program, "Rx"), Rx)

glUniform1f(glGetUniformLocation(self.program, "Ry"), Ry)

glUniform1f(glGetUniformLocation(self.program, "Rz"), Rz)

theta1 = r1*PI/180.0

glUniform1f(glGetUniformLocation(self.program, "theta1"), theta1)

# bind VAO

glBindVertexArray(self.vao)

# draw

glDrawElements(GL_TRIANGLES, self.indices.size, GL_UNSIGNED_INT, None)

# unbind VAO

glBindVertexArray(0)

def drawglobeVBO():

PI = 3.14159265358979323846264

statcky = 30 # 横向向切成多少片

stlicex = 30 # 纵向切多少片

R = 1.0 # 半径

angleHy = (2*PI)/statcky # 横向每份的角度 算出弧度值

angleZx = (2*PI)/stlicex; # 纵向每份的角度 算出弧度值

NumAngleHy = 0.0 # 当前横向角度

NumAngleZx = 0.0 # 当前纵向角度

x=0.0

y=0.0

z=0.0

c=numpy.array([], numpy.float32)

for j in range(statcky):

for i in range(stlicex):

NumAngleHy = angleHy*i #

NumAngleZx = angleZx*j # 起点都是轴指向的方向。根据右手定则决定转向,只要转向相同,那么两个就合适

x = R*np.cos(NumAngleHy)*np.cos(NumAngleZx)

y = R*np.sin(NumAngleHy)

z = R*np.cos(NumAngleHy)*np.sin(NumAngleZx)

c=np.hstack((c,numpy.array([x,y,z], numpy.float32) ))

return c

def drawglobeEBO():

PI = 3.14159265358979323846264

statcky = 30 # 横向向切成多少片

stlicex = 30 # 纵向切多少片

vbo = drawglobeVBO()

only = vbo.size

num = (int)((only/(3*statcky))*2)

ebo=numpy.array([], numpy.int)

for x in range(int(stlicex/2)):

for y in range(statcky):

ebo=np.hstack((ebo,numpy.array([y+x*stlicex,y+x*stlicex+1,y+x*stlicex+stlicex,y+x*stlicex+stlicex+1,y+x*stlicex+stlicex,y+x*stlicex+1])))

return ebo

#Is called whenever a key is pressed/released via GLFW

def on_key(window, key, scancode, action, mods):

if key == glfw.KEY_ESCAPE and action == glfw.PRESS:

glfw.set_window_should_close(window,1)

if __name__ == '__main__':

import sys

import glfw

import OpenGL.GL as gl

keys=numpy.zeros(1024)

deltaTime = 0.0

lastFrame = 0.0 # Time of last frame

# Initialize the library

if not glfw.init():

sys.exit()

# Create a windowed mode window and its OpenGL context

window = glfw.create_window(640, 480, "GL_DrawSphere01 ", None, None)

if not window:

glfw.terminate()

sys.exit()

# Make the window's context current

glfw.make_context_current(window)

# Install a key handler

glfw.set_key_callback(window, on_key)

PI = 3.14159265358979323846264

# 画球面

vert = drawglobeVBO()

ind = drawglobeEBO()

# Loop until the user closes the window

a=0

firstSphere1 = FirstSphere(vert,ind)

while not glfw.window_should_close(window):

currentFrame = glfw.get_time()

deltaTime = currentFrame - lastFrame

lastFrame = currentFrame

# Render here

width, height = glfw.get_framebuffer_size(window)

WIN_W, WIN_H =width, height

ratio = width / float(height)

glfw.poll_events()

gl.glViewport(0, 0, width, height)

gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); #用于控制多边形的显示方式

gl.glMatrixMode(gl.GL_PROJECTION)

gl.glLoadIdentity()

gl.glOrtho(-ratio, ratio, -1, 1, 1, -1)

gl.glMatrixMode(gl.GL_MODELVIEW)

gl.glLoadIdentity()

gl.glClearColor(0.0,0.1,0.1,1.0)

# modelview matrix

mvMatrix = myGL_Funcs.lookAt(cameraPos, cameraFront, cameraUp) # 设置视点

if WIN_W > WIN_H:

zLeft=VIEW[0] * WIN_W / WIN_H

zRight=VIEW[1] * WIN_W / WIN_H

zBottom=VIEW[2]

zTop=VIEW[3]

zNear=VIEW[4]

zFar=VIEW[5]

else:

zLeft=VIEW[0]

zRight=VIEW[1]

zBottom=VIEW[2] * WIN_H / WIN_W

zTop=VIEW[3] * WIN_H / WIN_W

zNear=VIEW[4]

zFar=VIEW[5]

pMatrix =myGL_Funcs.perspective(zLeft,zRight,zTop,zBottom, zNear, zFar)

firstSphere1.render( 0, 0, 0, 0, 1,1, a ,pMatrix, mvMatrix) #地球

# a=a+1

# if a>360:

# a=0

# Swap front and back buffers

glfw.swap_buffers(window)

# Poll for and process events

glfw.poll_events()

glfw.terminate()

六、参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值