news 2026/9/18 14:29:58

Python+OpenGL绘制3D模型(五)绘制三角型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python+OpenGL绘制3D模型(五)绘制三角型

系列文章

基础
Python+OpenGL绘制3D模型(一)Python 和 PyQt环境搭建
Python+OpenGL绘制3D模型(二)程序框架PyQt5
Python+OpenGL绘制3D模型(三)程序框架PyQt6
Python+OpenGL绘制3D模型(四)绘制线段
Python+OpenGL绘制3D模型(五)绘制三角型
Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射
Python+OpenGL绘制3D模型(七)制作3dsmax导出插件
Python+OpenGL 杂谈(一)

高级
用 DeepDraw 几何引擎开发建筑设计软件(一):SketchUp 替代
用 DeepDraw 几何引擎开发建筑设计软件(二):下载DeepDraw
用 DeepDraw 几何引擎开发建筑设计软件(三):用代码绘制线段
用 DeepDraw 几何引擎开发建筑设计软件(四):用代码绘制面
用 DeepDraw 几何引擎开发建筑设计软件(五):创建选择工具
用 DeepDraw 几何引擎开发建筑设计软件(六):读取模型文件
用 DeepDraw 几何引擎开发建筑设计软件(七):InputPoint输入捕获器
用 DeepDraw 几何引擎开发建筑设计软件(八):画线工具
未完待续…

前言

Sketchup作为目前设计院最为流行的设计软件(非工程制图软件),深受设计师的喜爱,软件小巧,而功能强大,有不少为之开发的插件应运而生,不过呢,关于底层数据结构和工作原理相关的文章少之又少,本文意在填补一下这方面的空缺。


Python+OpenGL绘制3D模型(五)绘制三角型

运行效果

文章目录

  • 系列文章
  • 前言
  • Python+OpenGL绘制3D模型(五)绘制三角型
    • 一、绘制三角型
    • 二、绘制轮廓线
    • 三、运行
    • 四、Z-Buffer问题
    • 五、最终效果
    • 六、全部代码
  • 系列文章预告

一、绘制三角型

绘制面的最小单元是三角形,如果你在想,为什么不用OpenGL的多边形来绘制。很好的问题,根据实践,所有的3D软件,都是把多边形转成三角型来绘制的,而且转换的过程所用到的Tessellation算法非常耗时,要把3D空间的模型转到2D空间才能计算。绘制多边形,你要考虑所有顶点是不是在一个平面上,多边形是不是凸多边形,线是否有交叉,中间是否有开孔,等等。。

所以3D绘图,还是老老实实用三角面吧

defdraw_tirangle(p1,p2,p3,gl):gl.glBegin(gl.GL_TRIANGLES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glVertex3d(p3.x(),p3.y(),p3.z())gl.glEnd()

一个4边型是由2个三角型组成的,所以绘制1个面需要完整的调用2次三角形绘制

defdraw_single_face(p1,p2,p3,p4,gl):gl.glBegin(gl.GL_TRIANGLES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glVertex3d(p3.x(),p3.y(),p3.z())gl.glEnd()gl.glBegin(gl.GL_TRIANGLES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glVertex3d(p3.x(),p3.y(),p3.z())gl.glEnd()

一个完整的立方体,由6个面组成,我们现在来把它们全部画出来

defdraw_box_faces(gl):p1=QVector3D(-1,-1,0)p2=QVector3D(+1,-1,0)p3=QVector3D(+1,+1,0)p4=QVector3D(-1,+1,0)p5=QVector3D(-1,-1,2)p6=QVector3D(+1,-1,2)p7=QVector3D(+1,+1,2)p8=QVector3D(-1,+1,2)draw_single_face(p1,p2,p3,p4,gl)draw_single_face(p5,p6,p7,p8,gl)draw_single_face(p1,p2,p6,p5,gl)draw_single_face(p3,p4,p8,p7,gl)draw_single_face(p2,p3,p7,p6,gl)draw_single_face(p4,p1,p5,p8,gl)

二、绘制轮廓线

现在的程序,是没有开启明暗处理和灯光的,所以绘制的所有面都是一个颜色的,画出来的东西是一片混沌,区分不出不同的面,现在我们用单色面+线框的方式来绘制,我们把盒子的所有线断都绘制出来

defdraw_box_lines(gl):p1=QVector3D(-1,-1,0)p2=QVector3D(+1,-1,0)p3=QVector3D(+1,+1,0)p4=QVector3D(-1,+1,0)p5=QVector3D(-1,-1,2)p6=QVector3D(+1,-1,2)p7=QVector3D(+1,+1,2)p8=QVector3D(-1,+1,2)# 一个立方体有12条边draw_single_line(p1,p2,gl)draw_single_line(p2,p3,gl)draw_single_line(p3,p4,gl)draw_single_line(p4,p1,gl)draw_single_line(p5,p6,gl)draw_single_line(p6,p7,gl)draw_single_line(p7,p8,gl)draw_single_line(p8,p5,gl)draw_single_line(p1,p5,gl)draw_single_line(p2,p6,gl)draw_single_line(p3,p7,gl)draw_single_line(p4,p8,gl)defdraw_single_line(p1,p2,gl):gl.glBegin(gl.GL_LINES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glEnd()

三、运行

运行后,我们得到一个方形的盒子,很漂亮,用这么少的代码,就可以达到如此的效果

四、Z-Buffer问题

我们已经绘制出模型和轮廓了,但是有个很明显的问题,模型的轮廓有时候是虚线,有时候是实线,闪来闪去,看着很不舒服

这是3D编辑软件都会遇到的一个问题,因为3D软件需要显示模型的线框,但是画线和画面在遇到同一个像素时,就会出现Z-Buffer的值一样,那么这个像素最后是画线时的颜色还是画面时的颜色是个不确定的值。这在3D领域有个专有名词叫做z-fighting,就是说2个面靠的很近很近的时候,这2个面就会来回闪硕的现象。

解决这个问题有个技巧,叫做z-buff bias,也叫做z-buff偏移,具体的办法是在绘制面的时候算出的z-buff值稍微增加一个很小的单位,那么在画线的时候,这个地方的Z值就肯定比画线的Z值小那么一点,就能够保证线能正常显示,不会和面发生z-buff冲突

五、最终效果

六、全部代码

fromPyQt5.QtGuiimportQVector3D############# draw# 绘图主入口############defdraw(gl):# Python+OpenGL绘制3D模型(四) 绘制线段#draw_rect(gl)# Python+OpenGL绘制3D模型(五) 绘制三角面draw_filled_cube(gl)############# draw_filed_cube# 绘制填充的方形############defdraw_filled_cube(gl):# 设置z-buff偏移gl.glEnable(gl.GL_POLYGON_OFFSET_FILL)gl.glPolygonOffset(1,1)# 绘制填充面gl.glColor3f(0.9,0.83,0.6)draw_box_faces(gl)# 关闭z-buff偏移gl.glDisable(gl.GL_POLYGON_OFFSET_FILL)# 绘制线框gl.glColor3f(0.0,0.0,0.0)draw_box_lines(gl)############# draw_box_faces# 画面 - 中间的填充部分############defdraw_box_faces(gl):p1=QVector3D(-1,-1,0)p2=QVector3D(+1,-1,0)p3=QVector3D(+1,+1,0)p4=QVector3D(-1,+1,0)p5=QVector3D(-1,-1,2)p6=QVector3D(+1,-1,2)p7=QVector3D(+1,+1,2)p8=QVector3D(-1,+1,2)draw_single_face(p1,p2,p3,p4,gl)draw_single_face(p5,p6,p7,p8,gl)draw_single_face(p1,p2,p6,p5,gl)draw_single_face(p3,p4,p8,p7,gl)draw_single_face(p2,p3,p7,p6,gl)draw_single_face(p4,p1,p5,p8,gl)defdraw_single_face(p1,p2,p3,p4,gl):gl.glBegin(gl.GL_TRIANGLES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glVertex3d(p3.x(),p3.y(),p3.z())gl.glEnd()gl.glBegin(gl.GL_TRIANGLES)gl.glVertex3d(p3.x(),p3.y(),p3.z())gl.glVertex3d(p4.x(),p4.y(),p4.z())gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glEnd()############# draw_box_lines# 画面 外侧的线############defdraw_box_lines(gl):p1=QVector3D(-1,-1,0)p2=QVector3D(+1,-1,0)p3=QVector3D(+1,+1,0)p4=QVector3D(-1,+1,0)p5=QVector3D(-1,-1,2)p6=QVector3D(+1,-1,2)p7=QVector3D(+1,+1,2)p8=QVector3D(-1,+1,2)# 一个立方体有12条边draw_single_line(p1,p2,gl)draw_single_line(p2,p3,gl)draw_single_line(p3,p4,gl)draw_single_line(p4,p1,gl)draw_single_line(p5,p6,gl)draw_single_line(p6,p7,gl)draw_single_line(p7,p8,gl)draw_single_line(p8,p5,gl)draw_single_line(p1,p5,gl)draw_single_line(p2,p6,gl)draw_single_line(p3,p7,gl)draw_single_line(p4,p8,gl)defdraw_single_line(p1,p2,gl):gl.glBegin(gl.GL_LINES)gl.glVertex3d(p1.x(),p1.y(),p1.z())gl.glVertex3d(p2.x(),p2.y(),p2.z())gl.glEnd()############# draw_rect# 绘制线段组成的方形############defdraw_rect(gl):gl.glColor3f(1.0,0.0,0.0)gl.glBegin(gl.GL_LINES)gl.glVertex3d(-1,0,0)gl.glVertex3d(+1,0,0)gl.glEnd()gl.glBegin(gl.GL_LINES)gl.glVertex3d(-1,0,2)gl.glVertex3d(+1,0,2)gl.glEnd()gl.glBegin(gl.GL_LINES)gl.glVertex3d(-1,0,0)gl.glVertex3d(-1,0,2)gl.glEnd()gl.glBegin(gl.GL_LINES)gl.glVertex3d(+1,0,0)gl.glVertex3d(+1,0,2)gl.glEnd()

系列文章预告

目标是开发一个Sketchup Viewer,能够显示Sketchup的.skp文件中的3D模型

Corona渲染器照片级渲染效果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 14:29:38

给 docmd 的 Markdown 文档站加 MCP,TaoToken 只提供 Key

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 14:26:41

FMEA知识与操作实务:从RPN评分到AP优先级与Python自动化

简介:PPT培训课件系统讲解FMEA(失效模式与效应分析)知识与操作实务,适合企业质量工程师、研发设计人员、生产制造及工艺管理人员学习参考。内容从FMEA发展历程和应用分类入手,涵盖DFMEA与PFMEA两大类型,梳理…

作者头像 李华
网站建设 2026/9/18 14:25:46

智慧补货系统:构建数据闭环驱动的动态库存决策

简介:本资源是IBM推出的《智慧补货解决方案》专业资料,面向零售企业运营管理者、供应链决策者及数字化转型实践者,聚焦解决传统依赖经验的粗放式补货导致的缺货、积压与区域适配失准等核心痛点。文档系统阐述了以数据驱动的多维智能补货模型&…

作者头像 李华