文章目录
- 1.前言
- 2.效果
- 3.实现过程
- 3.1.场景代码
- 3.2.自定义模型的渲染
- 3.3.绘制直线或者网格
- 4.有待解决的一些问题
- 4.1.线宽的设置、背面消隐(culling)的设置
- 4.2.法线的问题
1.前言
之前是使用Coin3D来绘制机械手场景的【Qt利用Coin3D(OpenInventor)进行3d绘图】。
后来需要在HarmonyOS显示这个机械手模型,但是想要编译Coin3D到HarmonyOS的话,显然太难了。
然后尝试使用OpenGL原生的函数来绘制,但是HarmonyOS对很多函数都不支持,一查,发现HarmonyOS支持OpenglES。那就麻烦了。
最后,一番兜兜转转,还是用回Qt3D吧。
2.效果
效果也还行,但是某些功能还得研究一下。
点、线、面、灯光等各种功能都ok。
3.实现过程
主要是参考了Qt自带的例程以及网上的一些资料。
3.1.场景代码
3.2.自定义模型的渲染
【Qt3DExample】
3.3.绘制直线或者网格
【how-do-i-draw-a-simple-line-in-Qt3D】
int drawOriginGrid(const int rows,
const int cols,
const float step,
const QColor& color,
Qt3DCore::QEntity *_rootEntity)
{
auto *geometry = new Qt3DRender::QGeometry(_rootEntity);
QList<QVector3D> vertexList;
// 横线
for(int i = -rows; i <= rows; i++)
{
vertexList << QVector3D(cols * step, 0, i * step);
vertexList << QVector3D(-cols * step, 0, i * step);
}
// 竖线
for(int i = -cols; i <= cols; i++)
{
vertexList << QVector3D(i * step, 0, rows * step);
vertexList << QVector3D(i * step, 0, -rows * step);
}
QByteArray bufferBytes;
bufferBytes.resize(3 * vertexList.length() * sizeof(float));
float *positions = reinterpret_cast<float*>(bufferBytes.data());
for(int i = 0; i < vertexList.length(); i++)
{
QVector3D vertex = vertexList.at(i);
*positions++ = vertex.x();
*positions++ = vertex.y();
*positions++ = vertex.z();
}
auto *buf = new Qt3DRender::QBuffer(geometry);
buf->setData(bufferBytes);
auto *positionAttribute = new Qt3DRender::QAttribute(geometry);
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
positionAttribute->setVertexSize(3);
positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
positionAttribute->setBuffer(buf);
positionAttribute->setByteStride(3 * sizeof(float));
positionAttribute->setCount(vertexList.length());
geometry->addAttribute(positionAttribute); // We add the vertices in the geometry
// connectivity between vertices
QByteArray indexBytes;
indexBytes.resize(2 * vertexList.length() * sizeof(unsigned int));
unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data());
for(int i = 0; i < vertexList.length(); i++)
{
*indices++ = i;
}
auto *indexBuffer = new Qt3DRender::QBuffer(geometry);
indexBuffer->setData(indexBytes);
auto *indexAttribute = new Qt3DRender::QAttribute(geometry);
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
indexAttribute->setBuffer(indexBuffer);
indexAttribute->setCount(vertexList.length());
geometry->addAttribute(indexAttribute); // We add the indices linking the points in the geometry
// mesh
auto *line = new Qt3DRender::QGeometryRenderer(_rootEntity);
line->setGeometry(geometry);
line->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
auto *material = new Qt3DExtras::QPhongMaterial(_rootEntity);
material->setAmbient(color);
material->setDiffuse(color);
// entity
auto *lineEntity = new Qt3DCore::QEntity(_rootEntity);
lineEntity->addComponent(line);
lineEntity->addComponent(material);
return 0;
}
4.有待解决的一些问题
4.1.线宽的设置、背面消隐(culling)的设置
有资料说可以通过QRenderStateSet来设置,但是我设置了并没有得到有效的效果
Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x2b2b2b)));
if(0)
{
using namespace Qt3DRender;
qDebug() << "frameGraph:" << view->defaultFrameGraph() << view->activeFrameGraph();
Qt3DRender::QRenderSurfaceSelector *surSel;
auto childNodeList = view->activeFrameGraph()->childNodes();
foreach (Qt3DCore::QNode * childNode, childNodeList) {
qDebug() << "child:" << childNode;
if(qobject_cast<Qt3DRender::QRenderSurfaceSelector*>(childNode))
{
surSel = qobject_cast<Qt3DRender::QRenderSurfaceSelector*>(childNode);
}
}
qDebug() << surSel->childNodes() << surSel->childNodes()[0]->childNodes()
<< surSel->childNodes()[0]->childNodes()[0]->childNodes();
qDebug() << surSel->childNodes()[0]->childNodes()[0]->childNodes()[0];
((Qt3DRender::QClearBuffers*)(surSel->childNodes()[0]->childNodes()[0]->childNodes()[0]))
->setBuffers(QClearBuffers::ColorDepthBuffer);
QRenderStateSet *renderStateSet = new QRenderStateSet(surSel->childNodes()[0]->childNodes()[0]);
QCullFace *cullFace = new QCullFace();
cullFace->setMode(QCullFace::NoCulling);
// renderStateSet->addRenderState(cullFace);
QLineWidth *lineWidth = new QLineWidth();
lineWidth->setValue(100);
// renderStateSet->addRenderState(lineWidth);
QPointSize *ptSize = new QPointSize();
ptSize->setValue(100);
// renderStateSet->addRenderState(ptSize);
qDebug() << surSel->childNodes()[0]->childNodes()[0]->childNodes();
}
4.2.法线的问题
目前好像是支持点法线,不支持面法线,假如使用index模式来渲染面片时,会渲染出奇怪的效果