PySide6 Qt3DCore 3D线框查看器QLineF线条无法显示问题
问题根因
你写的QLineF不显示,根本不是渲染参数的问题——QLineF是Qt GUI模块里用来存2D平面线段坐标的工具类,压根不属于Qt3D的实体组件体系,3D渲染管线根本不会识别它,当然画不出来。
Qt3D是ECS(实体-组件)架构,所有能在场景里显示的内容,都必须是QEntity实例,并且挂载齐网格、材质、变换三类核心组件,缺一个都不会渲染。你直接实例化一个2D几何数据类就想让它出现在3D场景里,相当于拿着平面设计图往3D打印机里塞,机器根本不认。
正确实现方法
Qt3D没有内置现成的3D线段、曲线网格类,要画点、直线、贝塞尔曲线这类线框元素,自己写自定义网格就行,步骤很固定:
- 自定义几何类继承
Qt3DRender.QGeometry,开辟一块顶点缓冲区存储要绘制图形的3D顶点坐标:单线段存2个端点,多段线/贝塞尔曲线按采样密度存一串顶点,点云就存所有点的坐标 - 用
QGeometryRenderer包裹自定义几何,设置对应图元类型:单线段用Lines,连续线/曲线用LineStrip,画点就用Points - 给实体挂上几何渲染器、材质、变换三个组件,加到场景根节点下即可。材质不用特殊配置,普通的
QPhongMaterial就能画线,要是怕线被实体挡住可以关闭深度测试。 - 注意你原来写的线段坐标范围是±2000,你设置的相机远裁剪面才到1000,就算画出来也在视锥外面看不见,测试的时候要把坐标范围收进视锥体内。
可直接运行的核心替换代码
把你createScene方法最后那行无效的self.lineEntity = QLineF(...)删掉,先补全需要的导入,再加下面的代码:
from PySide6.QtGui import QColor from PySide6.Qt3DRender import QGeometry, QAttribute, QBuffer, QGeometryRenderer from PySide6.QtCore import QByteArray import ctypes class Line3DGeometry(QGeometry): def __init__(self, start: QVector3D, end: QVector3D, parent=None): super().__init__(parent) vertex_buf = QBuffer(self) data = QByteArray() float_bytes = ctypes.sizeof(ctypes.c_float) # 写入两个端点的XYZ坐标 coords = [start.x(), start.y(), start.z(), end.x(), end.y(), end.z()] data.resize(len(coords)*float_bytes) for idx, val in enumerate(coords): data[idx*float_bytes : (idx+1)*float_bytes] = ctypes.c_float(val) vertex_buf.setData(data) pos_attr = QAttribute(self) pos_attr.setName(QAttribute.defaultPositionAttributeName()) pos_attr.setVertexBaseType(QAttribute.Float) pos_attr.setVertexSize(3) pos_attr.setAttributeType(QAttribute.VertexAttribute) pos_attr.setBuffer(vertex_buf) pos_attr.setByteStride(3*float_bytes) pos_attr.setCount(2) self.addAttribute(pos_attr) # 创建线段实体 line_entity = Qt3DCore.QEntity(self.rootEntity) line_render = QGeometryRenderer() line_render.setGeometry(Line3DGeometry(QVector3D(-20,-20,0), QVector3D(20,20,0))) line_render.setPrimitiveType(QGeometryRenderer.Lines) line_mat = Qt3DExtras.QPhongMaterial() line_mat.setAmbient(QColor(255,0,0)) # 设置线段为红色 line_entity.addComponent(line_render) line_entity.addComponent(line_mat) line_entity.addComponent(Qt3DCore.QTransform())
扩展说明
要画贝塞尔曲线、多段线、点云,逻辑完全一致,只需要修改几何类里的顶点生成逻辑:比如三次贝塞尔曲线按参数t从0到1采样几十上百个点,把顶点按顺序存进缓冲区,图元类型改成LineStrip就是连续曲线;图元改成Points再调整点大小就是点云。要是想让场景里的环面、球体显示线框,根本不用自己生成几何,直接拿对应的mesh调用setPrimitiveType(QGeometryRenderer.Lines)即可。
内容的提问来源于stack exchange,提问作者Yves
相关产品推荐
相关产品推荐

