当前位置: 首页 > news >正文

OSG编程指南<十二>:OSG二三维文字创建及文字特效

1、字体基础知识

  适当的文字信息对于显示场景信息是非常重要的。在 OSG 中,osgText提供了向场景中添加文字的强大功能,由于有第三方插件 FreeType 的支持,它完全支持TrueType 字体。很多人可能对 FreeType 和 TrueType 还不太了解,下面进行具体介绍。
  TrueType 是由 AppleComputer 公司和 Microsoft 公司联合提出的一种新型数学字形描述技术。它用数学函数描述字体轮廓外形,含有字形构造、颜色填充、数字描述函数、流程条件控制、栅格处理控制和附加提示控制等指令。TrueType 采用几何学中的二次 B 样条曲线及直线来描述字体的外形轮廓,其特点是:既可以用作打印字体,又可以用作屏幕显示;由于它由指令对字形进行描述,因此与分辨率无关,输出时总是按照打印机的分辨率输出;无论放大或缩小,字符总是光滑的,不会有锯齿出现;但相对 PostScript 字体来说,其质量要差一些,特别是在文字太小时,就表现得不是很清楚。
  FreeType 是一种字体服务但没有提供为实现文字布局或图形化处理这样高阶的功能使用的 API(如带色文字渲染之类的)。然而,它提供一个简单、易用且统一的接口实现对多种字体文件的访问,从而大大简化了这些高级的任务。FreeType支持 TrueType 和 OpenType 规格定义的全部字符映射。同时,它也完全有能力自动合成 Type 使用的 Unicode 字符表,这种表要求必须把一个供转换编码时使用的结束符放置在表的末尾——这在 Type 使用的格式中是很常见的(当然,如果读者需要,原始的编码方式也是可用的)。FreeType 是一个完整且有效率的 TrueType字节码解释器,这个引擎可以用很小的点产生极好的输出。由于 TrueType 规格极其令人费解且十分含糊,所以其组件想要成功完成输出是极其困难的。但无论如何,我们现在已经能使 Windows 的显示质量达到 Mac 的水平。

2、osgText

  在 OSG 中,为了显示高质量的文字,专门定义了一个新的名字空间来管理场景中文字的渲染,这个名字空间中的类主要用于加载字体和控制文字各种渲染属性。该空间主要包括下面几个类:

class FadeText //渐变文字
class Font //字体
class Font3D //3D 字体
class VectorUInt //向量单元
class String //字符串——用于多字节字符和各类文字编码
class Text //文字
class Text3D //3D 文字
class TextBase //文字基类

  文字显示效果主要分为两大类,即二维平面文字和三维立体文字。osgText::Text 类负责二维平面文字的渲染,osgText::Text3D 负责三维立体文字的渲染。

2.1 osgText::Text 类

  osgText::Text 类继承自 osgText::TextBase 类,间接继承自 osg::Drawable 类。因此,在应用程序中想把文字信息加到场景中,就要像添加一个 Geometry 实例一样添加一个 Geode。osgText::TextBase 是一个基类,定义了文字渲染的基本接口。文字的主要属性包括颜色、位置、方向、大小模式、分辨率、对齐方式、输出格式、绘制模式、背景类型和颜色倾斜模式等。

  1. 颜色:设置颜色可以直接调用如下成员函数:
void setColor (const osg::Vec4 &color)
  1. 位置:设置位置可以直接调用如下成员函数:
void setPosition (const osg::Vec3 &pos)
  1. 方向:设置文字方向可以直接调用如下成员函数:
void Text::setAxisAlignment(AxisAlignment axis)

文字方向枚举模式如下:

enum AxisAlignment
{
XY_PLANE, //xy 面
REVERSED_XY_PLANE, //xy 面的反面
XZ_PLANE, //xz 面
REVERSED_XZ_PLANE, //xz 面的反面
YZ_PLANE, //yz 面
REVERSED_YZ_PLANE, //yz 面的反面
SCREEN, //屏幕
USER_DEFINED_ROTATION //用户自定义旋转
};
  1. 大小模式
    设置大小模式可以直接调用如下成员函数:
void setCharacterSizeMode(CharacterSizeMode mode)

  文字大小模式枚举变量如下:

enum CharacterSizeMode
{
OBJECT_COORDS, //默认模式
SCREEN_COORDS, //根据屏幕坐标自动缩放
OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT
//根据视点自动缩放
};
  1. 分辨率
      设置文字分辨率可以直接调用如下成员函数:
void setFontResolution (unsigned int width, unsigned int height)

  在默认的情况下,OSG 为每个文字图形分配 32×32 个像素单元。通过改变字体纹理贴图的分辨率可以调整文字的清晰程度,通常,分辨率越大,越清晰,但是渲染负担就越大。建议在用户程序中可以清晰显示文字的情况下,默认使用最小的分辨率就可以满足需要了。

  1. 对齐方式
      设置对齐方式可以直接调用如下成员函数:
void Text::setAlignment(AlignmentType alignment)

对齐方式枚举模式如下:

enum AlignmentType
{
LEFT_TOP, //左上
LEFT_CENTER, //左中
LEFT_BOTTOM, //左下
CENTER_TOP, //中上
CENTER_CENTER, //中中
CENTER_BOTTOM, //中下
RIGHT_TOP, //右上
RIGHT_CENTER, //右中
RIGHT_BOTTOM, //右下
LEFT_BASE_LINE, //左基线
CENTER_BASE_LINE, //中间的基线
RIGHT_BASE_LINE, //右基线
LEFT_BOTTOM_BASE_LINE, //左下基线
CENTER_BOTTOM_BASE_LINE, //中下基线
RIGHT_BOTTOM_BASE_LINE, //右下基线
BASE_LINE = LEFT_BASE_LINE//default,左基线为默认方式
};
  1. 输出格式
    设置输出格式可以直接调用如下成员函数:
void setLayout(Layout layout)

文字输出格式枚举模式如下:

enum Layout
{
LEFT_TO_RIGHT, //default,默认格式从左到右
RIGHT_TO_LEFT, //从右到左
VERTICAL //垂直
};
  1. 绘制模式
    设置绘制模式可以直接调用如下成员函数:
void setDrawMode(unsigned int mode)

绘制模式枚举模式如下:

enum DrawModeMask
{
TEXT = 1, //默认模式文字
BOUNDINGBOX = 2, //包围盒
ALIGNMENT= 4 //对齐
};
  1. 背景类型
    设置背景类型可以直接调用如下成员函数:
void setBackdropType(BackdropType type)

背景类型枚举模式如下:

enum BackdropType
{
DROP_SHADOW_BOTTOM_RIGHT = 0, //默认阴影
DROP_SHADOW_CENTER_RIGHT,
DROP_SHADOW_TOP_RIGHT,
DROP_SHADOW_BOTTOM_CENTER,
DROP_SHADOW_TOP_CENTER,
DROP_SHADOW_BOTTOM_LEFT,
DROP_SHADOW_CENTER_LEFT,
DROP_SHADOW_TOP_LEFT,
OUTLINE,
NONE
};
  1. 颜色倾斜模式
    设置颜色倾斜模式可以直接调用如下成员函数:
void setColorGradientMode(ColorGradientMode mode)

颜色倾斜枚举模式如下:

enum ColorGradientMode
{
SOLID = 0, //立体,实心模式
PER_CHARACTER,//每一个字
OVERALL //全部
};

  从上面的介绍可以看出,文字的属性比较多,但并不是每一个都需要设置,可以选择设置,有些使用系统默认的即可。通常需要设置的有位置、内容、大小、对齐方式和颜色等。

2.2 osgText::Font 类

  osgText::Font 类直接继承自 osg::Object 类,该类主要用于对字体的管理,使用 FreeType 插件来读取字体文件,根据字体文件构建字体贴图,同时创建一个字体对象。读取字体可以用下面的函数:

osgText::readFontFile(const std::string &filename, const osgDB::ReaderWriter::Options *userOptions=0)

  该类在读取字体后,可以设置字体的轮廓和纹理等。不过,在实际应用中,这些采用系统默认的设置就可以了,不合理的设置反而会导致文字变形等不正常的现象发生。
  在 OSG 中,文字显示的机制是:创建一个 Font 对象读取字体文件,把 Font 与对应的文字相关联,创建绘制字符串图形的纹理贴图。在文字渲染时,文字会根据该字符的形状生成纹理坐标,并为每一个字符绘制一个已添加纹理的四边形。

在场景中添加文字的主要步骤如下:
(1)创建一个 Font 字体对象,并读取字体。
(2)创建一个 osgText::Text 对象,设置文字的属性,同时关联字体,在默认情况下,系统有默认的字体。
(3)调用 addDrawable()方法将步骤(2)创建的 osgText::Text 实例对象添加到一个 Geode 实例,如果要多处添加文字,可以多次创建 osgText::Text 对象,也可以创建多个 Geode,然后逐个添加,添加后再到场景中进行渲染。

  在场景中显示文字很简单,但显示中文会有一些难度,需要先将中文变成宽字符(方法有很多,如 L 或 W2A()),字体需要使用中文字体 simhei.ttf。

2.3 文字显示示例

在这里插入图片描述

#include <windows.h>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osgText/Text>
#include <osgText/Font>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体
#include <osgUtil/DelaunayTriangulator> 
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")osg::ref_ptr<osg::Geode> createText()
{osg::ref_ptr<osgText::Text> text = new osgText::Text;osg::ref_ptr<osgText::Font> font = new osgText::Font();//读取字体font = osgText::readFontFile("simhei.ttf");// 设置字体文件text->setFont(font.get());// 设置文字信息text->setText(L"Hello,world!  你好,世界!");// 设置字体大小text->setCharacterSize(0.5f);text->setAutoRotateToScreen(false);//设置字体颜色text->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));// 设置显示的位置osg::Vec3f position = osg::Vec3f(0.0f, 0.0f, 0.0f);text->setPosition(position);// 设置对齐方式text->setAlignment(osgText::Text::CENTER_TOP);// 设置旋转方式text->setAxisAlignment(osgText::Text::XZ_PLANE);//添加到叶节点中osg::ref_ptr<osg::Geode> geode = new osg::Geode();geode->addDrawable(text.get());return geode.get();
}int main()
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//创建文字osg::ref_ptr<osg::Geode> node = createText();root->addChild(node.get());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());//方便查看在多边形之间切换,以查看三角网viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));viewer->addEventHandler(new osgViewer::StatsHandler());viewer->addEventHandler(new osgViewer::WindowSizeHandler());viewer->setSceneData(root.get());viewer->setUpViewInWindow(600, 600, 1000, 800);viewer->run();return 0;
}

2.4 文字效果(边框、阴影及颜色倾斜)

在这里插入图片描述

#include <windows.h>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osgText/Text>
#include <osgText/Font>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体
#include <osgUtil/DelaunayTriangulator> 
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")osg::ref_ptr<osg::Camera> createAllKindText()
{osg::ref_ptr<osg::Camera> camera = new osg::Camera();//设置投影矩阵camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1280, 0, 800));//设置视图矩阵  camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setViewMatrix(osg::Matrix::identity());//清除深度缓存camera->setClearMask(GL_DEPTH_BUFFER_BIT);//设置渲染顺寻,在主摄像机之前渲染camera->setRenderOrder(osg::Camera::POST_RENDER);//设置为不接收事件,始终不得到焦点camera->setAllowEventFocus(true);osg::ref_ptr<osgText::Font> font = osgText::readFontFile("simhei.ttf");osg::ref_ptr<osg::Geode> geode = new osg::Geode;osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);//-----------------------------------------------//-----------------------------------------------//设置文字输出的格式//设置格式为LEFT_TO_RIGHT,从左到右{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(20.0f);text->setPosition(osg::Vec3(50.0f, 750.0f, 0.0f));text->setLayout(osgText::Text::LEFT_TO_RIGHT);text->setText(L"从左到右");geode->addDrawable(text.get());}//设置格式为RIGHT_TO_LEFT,从右到左{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(30.0f);text->setPosition(osg::Vec3(1200.0f, 750.0f, 0.0f));text->setLayout(osgText::Text::RIGHT_TO_LEFT);text->setAlignment(osgText::Text::RIGHT_BASE_LINE);text->setText(L"从右到左");geode->addDrawable(text.get());}//设置格式为VERTICAL,垂直{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(20.0f);text->setPosition(osg::Vec3(500.0f, 750.0f, 0.0f));text->setLayout(osgText::Text::VERTICAL);text->setText(L"垂直");geode->addDrawable(text.get());}//-----------------------------------------------//-----------------------------------------------//设置阴影{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(40.0f);text->setPosition(osg::Vec3(100.0f, 650.0f, 0.0f));//设置阴影为DROP_SHADOW_BOTTOM_RIGHTtext->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);text->setBackdropColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));text->setBackdropOffset(0.1f, -0.1f);text->setText(L"阴影效果");geode->addDrawable(text.get());}//-----------------------------------------------//-----------------------------------------------//设置边框{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(30.0f);text->setPosition(osg::Vec3(100.0f, 450.0f, 0.0f));//设置边框对齐绘制text->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX | osgText::Text::ALIGNMENT);text->setText(L"文字边框");geode->addDrawable(text.get());}//-----------------------------------------------//-----------------------------------------------//设置颜色倾斜模式{osg::ref_ptr<osgText::Text> text = new osgText::Text;text->setFont(font.get());text->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));text->setCharacterSize(40.0f);text->setPosition(osg::Vec3(100.0f, 250.0f, 0.0f));//设置颜色倾斜模式为PER_CHARACTERtext->setColorGradientMode(osgText::Text::PER_CHARACTER);//设置倾斜四个角落的颜色text->setColorGradientCorners(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f), osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f),osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f), osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));text->setText(L"文字颜色倾斜");geode->addDrawable(text.get());}camera->addChild(geode.get());return camera.get();
}int main()
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();//创建各种文字效果osg::ref_ptr<osg::Camera> camera = createAllKindText();//添加到根节点osg::ref_ptr<osg::Group> root = new osg::Group();root->addChild(createAllKindText());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());viewer->setUpViewInWindow(600, 600, 1000, 800);viewer->run();return 0;
}

2.5 HUD 抬头显示

  HUD 显示文字是一种非常实用的技术,可以用来把一些重要的文字始终显示在屏幕上。HUD 的全称是 Heads Up Display,即抬头显示,这种技术最早应用在军事战斗机上。

创建 HUD 显示的基本步骤如下:
(1)创建一个 osg::Camera 对象,设置视图、投影矩阵及渲染顺序,以确保在场景图形全部渲染
完后才进行渲染。
(2)创建一个 osg::Geode 对象和一个 osgText::Text 对象,并设置相应的文字属性。把 osgText::Text
对象添加到 Geode 叶节点。
(3)把叶节点 Geode 关联到步骤(1)所创建的相机。

在创建 HUD 显示文字显示时,需要注意的有如下几点:
渲染顺序设置为 POST,否则可能会被场景中的其他图形所覆盖。
注意关闭光照和深度。
投影矩阵通常设置为屏幕尺寸大小。

在这里插入图片描述

#include <windows.h>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osgText/Text>
#include <osgText/Font>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体
#include <osgUtil/DelaunayTriangulator> 
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")osg::ref_ptr<osg::Camera> createHUDText()
{osg::ref_ptr<osg::Camera> camera = new osg::Camera();//设置投影矩阵camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1280, 0, 800));//设置视图矩阵,同时确保不被场景其他图形位置变换影响,使用//绝对帧引用camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setViewMatrix(osg::Matrix::identity());//清除深度缓存camera->setClearMask(GL_DEPTH_BUFFER_BIT);//设置渲染顺序为POSTcamera->setRenderOrder(osg::Camera::POST_RENDER);//设置为不接收事件,始终不得到焦点camera->setAllowEventFocus(false);osg::ref_ptr<osg::Geode> geode = new osg::Geode();osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();//关闭光照stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);//关闭深度测试stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);//设置文字osg::ref_ptr<osgText::Text> text = new osgText::Text();osg::ref_ptr<osgText::Font> font = new osgText::Font();font = osgText::readFontFile("simhei.ttf");text->setFont(font.get());text->setText(L"OSG抬头显示文字");text->setPosition(osg::Vec3(400.0f, 600.0f, 0.0f));text->setCharacterSize(40.0f);text->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));text->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);geode->addDrawable(text.get());camera->addChild(geode.get());return camera.get();
}int main()
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//读取模型osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("logo.ive");root->addChild(node.get());//添加HUD文字root->addChild(createHUDText());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());viewer->setUpViewInWindow(600, 600, 1000, 800);viewer->run();return 0;
}

3、osgText3D文字

  三维立体文字比二维平面文字显示效果更好,相对二维平面文字,它有非常好的立体显示效果。在实际虚拟现实项目中,过多使用三维立体文字会降低渲染效率,加重渲染负担,相对平面二维文字,它占用的内存是非常大的。

3.1 osgText::Text3D类

  osgText::Text3D 类继承自 osgText::TextBase 类,从继承关系图可以看出,它继承自 osgText::TextBase 类,因此它具备普通二维文字的属性设置方法。它的方法与平面文字的创建方法基本一致,但它是有厚度的文字,并没有直接设置颜色的接口,可以通过设置材质来设置颜色。

  在 osgText::Text3D 类中包含一个设置深度信息的函数,可以通过该函数设置立体文字的深度:

void setCharacterDepth (float characterDepth);

3.2 3D文字效果

在这里插入图片描述

3.2 源码

#include <windows.h>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osgText/Text>
#include <osgText/Font>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/Material>
#include <osgText/Text3D>
#include <osgText/Font3D>
#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体
#include <osgUtil/DelaunayTriangulator> 
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")osg::ref_ptr<osg::Geode> create3DText()
{osg::ref_ptr<osg::Geode> geode = new osg::Geode();//创建三维文字osg::ref_ptr<osgText::Text3D> text = new osgText::Text3D();text->setText(L"OpengSceneGraph中国官方");text->setFont("simhei.ttf");text->setCharacterSize(60.0f);text->setPosition(osg::Vec3(-250.0f, 50.0f, 150.0f));//设置文字渲染模式text->setRenderMode(osgText::Text3D::PER_GLYPH);//设置文字深度text->setCharacterDepth(10.0f);text->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX);//设置文字与坐标轴对齐方式text->setAxisAlignment(osgText::Text3D::XZ_PLANE);geode->addDrawable(text.get());//设置材质osg::ref_ptr<osg::Material> front = new osg::Material;front->setColorMode(osg::Material::AMBIENT);front->setAlpha(osg::Material::FRONT_AND_BACK, 1);front->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));front->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));geode->getOrCreateStateSet()->setAttributeAndModes(front.get());return geode.get();
}int main()
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//添加三维文字root->addChild(create3DText());//读取模型osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("logo.ive");root->addChild(node.get());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());viewer->setSceneData(root.get());viewer->setUpViewInWindow(600, 600, 1000, 800);viewer->run();return 0;
}

相关文章:

OSG编程指南<十二>:OSG二三维文字创建及文字特效

1、字体基础知识 适当的文字信息对于显示场景信息是非常重要的。在 OSG 中&#xff0c;osgText提供了向场景中添加文字的强大功能&#xff0c;由于有第三方插件 FreeType 的支持&#xff0c;它完全支持TrueType 字体。很多人可能对 FreeType 和 TrueType 还不太了解&#xff0c…...

visionOS空间计算实战开发教程Day 6 拖拽和点击

在之前的学习中我们在空间中添加了3D模型&#xff0c;但在初始摆放后就无法再对其进行移动或做出修改。本节我们在​​Day 5​​显示和隐藏的基础上让我们模型可以实现拖拽效果&#xff0c;同时对纯色的立方体实现点击随机换色的功能。 首先是入口文件&#xff0c;无需做出改变…...

C# APS.NET CORE 6.0 WEB API IIS部署

1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码&#xff1a; 项目文件展开&#xff1a; launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…...

C/C++ 常用加密与解密算法

计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性&#xff0c;常常需要使用加密和解密算法。C是一种广泛使用的编程语言&#xff0c;提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法&#xff0c;这其中包括Xo…...

从Qt源码的角度分析Qt对象树与内存管理模式

作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目录 一、Qt对象树(Object Tree)和父子关系二、源码角度:QObject的内存管理构造函数析构函数addChild() 和 removeChild()三、C++模拟实现Qt的对象树内存管理模式Qt框架提供了一…...

MySQL与Redis如何保证数据的一致性

文章目录 MySQL与Redis如何保证数据的一致性&#xff1f;不好的方案1. 先写 MySQL&#xff0c;再写 Redis2. 先写 Redis&#xff0c;再写 MySQL3. 先删除 Redis&#xff0c;再写 MySQL 好的方案4. 先删除 Redis&#xff0c;再写 MySQL&#xff0c;再删除 Redis5. 先写 MySQL&am…...

micropython - espnow

espnow这个东西可以很简单的进行多设备近距离互联&#xff0c;连握手都不用注册一下就能发信息 目前8266那个8角的刷20231105的1M的固件可以运行 8266目前没有信号强度功能所以我自己写的类强度返回为0 我写的类实例化后最后注册谁发消息就是给谁而接收端则是什么都接&#xff…...

京东数据采集(京东数据运营):怎样快速获取京东市场大数据?

相信京东平台的很多品牌方们都有做数据分析的需求&#xff0c;但面对多而杂的市场数据&#xff0c;很多运营者都没有思路。单依靠肉眼来看&#xff0c;很多商品的类目、销售成绩、价格分布等运营者也未必清楚。 其实对于京东平台上市场数据的获取&#xff0c;品牌可以直接借助一…...

​重生奇迹mu迷宫攻略​

重生奇迹mu迷宫是一种比较有挑战性的游戏玩法&#xff0c;需要一定的技巧和策略才能完成。以下是一些基本的攻略和技巧&#xff1a; 了解每个迷宫的特点&#xff1a;不同的迷宫有不同的规则和特点&#xff0c;需要根据迷宫的特点来制定合理的策略。在进入迷宫前可以先了解一下…...

[网络] 4. HTTP/1.1 相比 HTTP/1.0 提高了什么性能?

HTTP/1.1 相比 HTTP/1.0 性能上的改进 ● 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。 ● 支持管道&#xff08;pipeline&#xff09;网络传输&#xff0c;只要第一个请求发出去了&#xff0c;不必等其回来&#xff0c;就可以发第二个请求出去&#xff0c;可以减…...

3.1.2 Linux时间子系统 hrtimer示例使用

文章目录 结构体定义接口初始化启动修改取消示例示例1示例2示例3结构体定义 struct hrtimer {struct timerqueue_node node;ktime_t _softexpires;enum hrtimer_restart...

04 _ 系统设计目标(二):系统怎样做到高可用?

这里将探讨高并发系统设计的第二个目标——高可用性。 高可用性&#xff08;High Availability&#xff0c;HA&#xff09;是你在系统设计时经常会听到的一个名词&#xff0c;它指的是系统具备较高的无故障运行的能力。 我们在很多开源组件的文档中看到的HA方案就是提升组件可…...

Android相机性能提高50%

文章目录 应用举例&#xff08;可以不看这一part&#xff0c;直接跳过看具体怎么做&#xff09;&#xff1a;Snapchat 通过 Camera2 Extensions API 将新相机功能的集成速度提高了 50%**Camera2 扩展 API 可以访问高级功能更多设备上的更多机会 正文&#xff1a;开始使用扩展架…...

STM32F103C8T6第5天:独立看门狗、窗口看门狗、dma实验

1. 独立看门狗IWDG介绍&#xff08;341.45&#xff09; 什么是看门狗&#xff1f; 在由单片机构成的微型计算机系统中&#xff0c;由于单片机的工作常常会受到来自外界电磁场的干扰&#xff0c;造成程序的跑飞&#xff0c;而陷入死循环&#xff0c;程序的正常运行被打断&#…...

QT已有项目导入工程时注意事项

文章目录 从qt其他版本上开发的工程导入另一qt版本时 从qt其他版本上开发的工程导入另一qt版本时 这里以之前在qt5.12.2上开发的项目为例&#xff0c;现在到在qt6.5.3上运行。 不能直接导入IDE上&#xff0c;否则会报各种莫名奇妙的错误。 首先要把扩展名位.pro.user文件 删掉…...

Django视图层

一、请求与响应 视图函数 视图函数&#xff0c;简称视图&#xff0c;属于Django的视图层&#xff0c;默认定义在views.py文件中&#xff0c;是用来处理web请求信息以及返回响应信息的函数&#xff0c;所以研究视图函数只需熟练掌握两个对象即可&#xff1a;请求对象(HttpRequ…...

我在electron中集成了自己的ai大模型

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、大模型选择二、获取key三、调用api四、调用ai模型api时&#xff0c;解决跨域总结 前言 最近单位把gpt、文心一言、通义千问、星火等等等等你能想到的ai大模型都给禁掉了&#xff0c;简直丧心病狂。 不知道有多少感同…...

oracle rac环境归档日志清除

文章目录 一、处理步骤1、使用终端登录上服务器查看磁盘使用状态2、使用恢复备份管理工具RMAN删除归档日志 二、详细操作步骤三、定时任务自动清归档日志1、编写删除脚本4、测试脚本运行情况5、设置定时任务每周执行一次&#xff0c;并测试运行效果 昨天单位的所有系统都连不上…...

【数据结构】树与二叉树(廿六):树删除指定结点及其子树(算法DS)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点4. 删除结点及其左右子树a. 逻辑删除与物理删除b. 算法DSTc. 算法解析d. 代码实现递归释放树算法DS e. 算法测试 5. 代码整合…...

交叉编译 和 软硬链接 的初识(面试重点)

目录 交叉编译的初认识Q&A Q1: 编译是什么&#xff1f; Q2: 交叉编译是什么&#xff1f; Q3: 为什么要交叉编译 Q3.1&#xff1a;树莓派相对于C51大得多&#xff0c;可以集成编译器比如gcc&#xff0c;那么树莓派就不需要交叉编译了吗&#xff1f; Q4: 什么是宿主机和…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

小智AI+MCP

什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析&#xff1a;AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github&#xff1a;https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...

Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用

Linux 内存管理调试分析&#xff1a;ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础&#xff0c;但这一子系统结构复杂&#xff0c;常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题&#xff0c;需要一套工具化、…...