赞
踩
基本思路:获取字体的轮廓,使用OpenGL轮廓绘制
使用的类和api:QPainterPath,toSubpathPolygons;
static QMap<QString, QList<QPolygonF>> m_3DtextBuffer; //缓存,减少耗时
if (!m_3DtextBuffer.contains(m_Text)) {
QPainterPath path;
path.addText(0, 0, QFont(), m_Text);
QTransform T;
T.scale(1, -1); //Qt窗口坐标转OpenGL屏幕坐标
T.translate(-path.boundingRect().width() / 2.0, 0); //移至中间
m_3DtextBuffer[m_Text] = path.toSubpathPolygons(T);
}
基本思路:1、将字体的朝向转成相机的朝向;2、字体的高的方向转向屏幕Y轴的方向(或者宽的方向转向屏幕X轴的方向),这里屏幕Y轴(X轴)的方向实际上也就是相机的up方向和right方向;
//GLWidget继承自QOpenGLExtraFunctions; myPaint为自定义实现; //projection透视矩阵,view视图矩阵 void GLWiget::myPaint(const QMatrix4x4& projection, const QMatrix4x4& view){ QMatrix4x4 mt, mt2, mt3; mt.setToIdentity(); mt2.setToIdentity(); mt3.setToIdentity(); //字体导入场景时的初始值,需要具体情况具体分析 QVector3D NText { 0, 0, 1 }; //字体朝向 (字体厚度) // QVector3D WText{1,0,0}; //字体的宽方向 QVector3D HText { 0, 1, 0 }; //字体的高方向 QVector3D NCamera = m_CameraDir; //m_CameraDir相机的朝向,传入的值 //求字体法线旋转 QVector3D Naxis = QVector3D::crossProduct(NText, NCamera).normalized(); auto theta = acos(QVector3D::dotProduct(NText, NCamera)); mt.rotate(RADIAN_TO_DEGREE(theta), Naxis); //摆正字体 QVector3D cameraUp = QVector3D::crossProduct(NCamera, QVector3D::crossProduct({ 0, 1, 0 }, NCamera)); HText = (mt * HText); auto thetaH = acos(QVector3D::dotProduct(HText.normalized(), cameraUp.normalized())); auto angle = RADIAN_TO_DEGREE(thetaH); auto dir = QVector3D::dotProduct({ 1, 0, 0 }, cameraUp.normalized()); mt2.rotate(angle * (dir < 0 ? 1 : -1), NCamera); //angel值始终都是正的,需要计算逆时针和顺时针下的旋转 //往相机方向偏移一点 mt3.translate(NCamera * 15); bool isDraw = true; QVector<QVector<QVector3D>> tempPolygons; for (auto polygon : m_3DtextBuffer.value(m_Text)) { if (polygon.isClosed()) { QVector<QVector3D> temp; for (int i = 0; i < polygon.size(); i++) { QVector3D oriantPos = QVector3D { (float)polygon[i].x(), (float)polygon[i].y(), 0 }; QVector3D pos3d = mt3 * (mt2 * (mt * oriantPos)) + this->getPos(); pos3d = projection * view * pos3d; if (pos3d.x() > 1 || pos3d.x() < -1 || pos3d.y() > 1 || pos3d.y() < -1) { isDraw = false; break; } temp.push_back(pos3d); } tempPolygons << temp; } } if (isDraw) { for (auto temp : tempPolygons) { glBegin(GL_LINE_LOOP); for (auto pos : temp) { glVertex3f(pos.x(), pos.y(), pos.z()); } glEnd(); } } }
虽然2D渲染文字即可实现相关效果(始终朝向屏幕),但是3D字体的方式,可以轻松利用场景的深度测试,将不渲染被遮住的字体;
且2D字体跟随屏幕缩放时,需要做额外的算法处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。