OpenGL基本作图及其人机交互
可参考链接
VBO相关函数
- glGenBuffers: 产生缓冲
- C原型 void glGenBuffers(GLsizei n,GLuint * buffers)
- n: 整型,表示产生多个缓冲
- buffer 整型的指针,表示缓冲的地址指针
- 说明: 其实质就是告知GL内存某个空间是画图的缓冲,该空间实际可能没有任何数据,仅仅是将内存某个空间的地址与GL系统用来画图的缓冲指针关联起来。
- py原型buffer=glGenBuffers(n)
- n是缓冲个数
- buffer是返回的numpy.ndarray类型的对象
- glBindBuffer: 绑定缓冲
- C原型: void glBindBuffer(GLenum target,GLuint buffer)
- target: 枚举类型,绑定的目标,其常用类型如下
- GL_ARRAY_BUFFER 顶点数据缓冲
- GL_ELEMENT_ARRAY_BUFFER 顶点指示缓冲
- buffer: 缓冲内存
- py原型: glBindBuffer(target , buffer)
- webGL原型:gl.bindBuffer(target, buffer)
- target常用的类型的webGL值为
- gl.ARRAY_BUFFER
- gl.ELEMENT_ARRAY_BUFFER
- glBufferData: 给缓冲赋予数据
- C原型:void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
- py原型:glBufferData(target, n , data, usage)
- webGL原型:gl.BufferData(target, data, usage)
- 以上三个函数在python中更简便的形式,其函数在库array里,对象为vbo
- vbo.VBO(data,target)
- 该函数是将以data的数据生成一个vbo的对象,data可以是numpy的array对象
- target:是
- vbo.bind():绑定,该函数虽然是绑定函数,但其绑定的目标在生成时就已经有了
- glInterleavedArrays: 分离数组
- VBO是一种组合数组,它把顶点坐标、颜色、法式、纹理等数据都集成在一起了,该函数就是将VBO分离开来,从而可以绘图
- C原型void glInterleavedArrays(GLenum format, GLsizei stride,const void * pointer)
- format是枚举型,有如下选择:
- stride表示跨距,也就是各个数据的间隔,如果是0表示数据相邻
- pointer: 可能是缓存的指针 - py原型 glInterleavedArrays(format, stride, pointer)
- webGL原型: 目前未知,后续探索
- 奉上python代码示例
import numpy as np
from OpenGL.GL import *
class cubic():
def __init__(self):
self.vbo_vertices=None
self.vbo_indices=None
self.bCreate=False
def createVAO(self):
l=0.8
vertices_normal = np.array([
0.3, 0.6, 0.9, 1, 0,0,1, -l, l, l,
0.3, 0.6, 0.9, 1, 0,0,1, l, l, l,
0.3, 0.6, 0.9, 1, 0,0,1, l, -l, l,
0.3, 0.6, 0.9, 1, 0,0,1, -l, -l, l,
0.3, 0.6, 0.9, 1, 0,0,-1, -l, l, -l,
0.3, 0.6, 0.9, 1, 0,0,-1, l, l, -l,
0.3, 0.6, 0.9, 1, 0,0,-1, l, -l, -l,
0.3, 0.6, 0.9, 1, 0,0,-1, -l, -l, -l,
0.3, 0.6, 0.9, 1, 0,1,0, -l, l, l,
0.3, 0.6, 0.9, 1, 0,1,0, l, l, l,
0.3, 0.6, 0.9, 1, 0,1,0, l, l, -l,
0.3, 0.6, 0.9, 1, 0,1,0, -l, l, -l,
0.3, 0.6, 0.9, 1, 0,-1,0, l, -l, l,
0.3, 0.6, 0.9, 1, 0,-1,0, -l, -l, l,
0.3, 0.6, 0.9, 1, 0,-1,0, -l, -l, -l,
0.3, 0.6, 0.9, 1, 0,-1,0, l, -l, -l,
0.3, 0.6, 0.9, 1, -1,0,0, -l, l, l,
0.3, 0.6, 0.9, 1, -1,0,0, -l, -l, l,
0.3, 0.6, 0.9, 1, -1,0,0, -l, -l, -l,
0.3, 0.6, 0.9, 1, -1,0,0, -l, l, -l,
0.3, 0.6, 0.9, 1, 1,0,0, l, l, l,
0.3, 0.6, 0.9, 1, 1,0,0, l, -l, l,
0.3, 0.6, 0.9, 1, 1,0,0, l, -l, -l,
0.3, 0.6, 0.9, 1, 1,0,0, l, l, -l,
], dtype=np.float32)
indices_normal=np.array([ 0,1,2,3,
4,5,6,7,
8,9,10,11,
12,13,14,15,
16,17,18,19,
20,21,22,23
],dtype=np.int)
self.vbo_vertices = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo_vertices)
glBufferData(GL_ARRAY_BUFFER, 4*len(vertices_normal), vertices_normal, GL_STATIC_DRAW)
self.vbo_indices = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4*len(indices_normal), indices_normal, GL_STATIC_DRAW)
self.bCreate=True
def draw(self):
if self.bCreate==False:
self.createVAO()
glInterleavedArrays(GL_C4F_N3F_V3F, 0, None)
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, None)
光照模型
可参考链接
STL文件读取
- STL文件格式
[80个字节]: 文件起始的80个字节是文件头,用于存贮文件名
[4个字节]: 4 个字节的整数来描述模型的三角面片个数(小端存储)
[50*n个字节]: 实际数据,逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节(小端存储),依次是:
- 实际数据格式
[12]3个4字节浮点数(角面片的法矢量)
[12]3个4字节浮点数(第1个顶点的坐标)
[12]3个4字节浮点数(第2个顶点的坐标)
[12]3个4字节浮点数(第3个顶点的坐标)
[2]三角面片的最后2个字节用来描述三角面片的属性信息
- 文件读取
stl_file=open(path,'rb')
header=stl_file.read(80)
file_disc=bytes.decode(header)
neck=stl_file.read(4)
self.number=int.from_bytes(neck,byteorder='little',signed=False)
raw_data=stl_file.read()
for i in range(self.number):
j=50*i
self.data.append(struct.unpack('<f',raw_data[j+0:j+4]))
self.data.append(struct.unpack('<f',raw_data[j+4:j+8]))
self.data.append(struct.unpack('<f',raw_data[j+8:j+12]))
self.data.append(struct.unpack('<f',raw_data[j+12:j+16]))
self.data.append(struct.unpack('<f',raw_data[j+16:j+20]))
self.data.append(struct.unpack('<f',raw_data[j+20:j+24]))
self.data.append(struct.unpack('<f',raw_data[j+0:j+4]))
self.data.append(struct.unpack('<f',raw_data[j+4:j+8]))
self.data.append(struct.unpack('<f',raw_data[j+8:j+12]))
self.data.append(struct.unpack('<f',raw_data[j+24:j+28]))
self.data.append(struct.unpack('<f',raw_data[j+28:j+32]))
self.data.append(struct.unpack('<f',raw_data[j+32:j+36]))
self.data.append(struct.unpack('<f',raw_data[j+0:j+4]))
self.data.append(struct.unpack('<f',raw_data[j+4:j+8]))
self.data.append(struct.unpack('<f',raw_data[j+8:j+12]))
self.data.append(struct.unpack('<f',raw_data[j+36:j+40]))
self.data.append(struct.unpack('<f',raw_data[j+40:j+44]))
self.data.append(struct.unpack('<f',raw_data[j+44:j+48]))