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

news2024/11/27 10:42:25

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_RIGHT
		text->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_CHARACTER
		text->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);

	//设置渲染顺序为POST
	camera->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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1254744.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化横行时代,手工测试如何突破重围?测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试是每个…

渗透测试【一】:渗透测试常见问题

渗透测试【一】&#xff1a;渗透测试常见问题 1、问题清单2、问题现象及解决办法2.1、点击劫持2.2、用户枚举2.3、Springboot未授权访问2.4、Swagger未授权访问2.5、Host头注入2.6、任意文件上传2.7、敏感路径泄露2.8、跨域资源共享2.9、Spring Cloud Gateway RCE2.10、Content…

java多线程一

1、什么是线程 线程&#xff08;Thread&#xff09;是一条程序内部的一条执行流程。 程序中如果只有一条执行流程&#xff0c;那这个程序就是单线程的程序。 2、什么是多线程 多线程&#xff08;multithreading&#xff09;&#xff0c;是指从软件或者硬件上实现多个线程并发执…

如何快速搭建一个大模型?简单的UI实现

&#x1f525;博客主页&#xff1a;真的睡不醒 &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;相信自己&#xff0c;一路风景一路歌&#xff0c;人生之美&#xff0c;正在于…

DataGrip 2023.2.3(IDE数据库开发)

DataGrip是一款数据库集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于数据库管理和开发。 DataGrip提供了许多强大的功能&#xff0c;如SQL语句编辑、数据库连接管理、数据导入和导出、数据库比较和同步等等。它支持多种数据库&#xff0c;如MySQL、PostgreSQL、Ora…

Python教程:DataFrame数据中使用resample计算月线平均值

在pandas库中&#xff0c;DataFrame可以使用resample()方法来对时间序列数据进行重采样。重采样是将原始数据按照指定的频率进行重新组织&#xff0c;以便进行更细粒度的分析或转换。下面是一个示例&#xff0c;演示如何使用resample()方法&#xff1a; # Author : 小红牛 # 微…

陶陶摘苹果、跳跃游戏

1. 陶陶摘苹果 题目描述&#xff1a; 陶陶家的院子里有一棵苹果树&#xff0c;每到秋天树上就会结出 10 个苹果。苹果成熟的时候&#xff0c;陶陶就会跑去摘苹果。陶陶有个 30 厘米高的板凳&#xff0c;当她不能直接用手摘到苹果的时候&#xff0c;就会踩到板凳上再试试。 现在…

人力资源管理后台 === 登陆+主页鉴权

目录 1. 分析登录流程 2. Vuex中用户模块的实现 3.Vue-cli代理解决跨域 4.axios封装 5.环境区分 6. 登录联调 7.主页权限验证-鉴权 1. 分析登录流程 传统思路都是登录校验通过之后&#xff0c;直接调用接口&#xff0c;获取token之后&#xff0c;跳转到主页。 vue-elemen…

概念解析 | 玻尔兹曼机

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:玻尔兹曼机。 概念解析 | 玻尔兹曼机 引言 随着人工智能技术的飞速发展,玻尔兹曼机作为一种重要的生成模型,受到了广泛的关注。 背景介绍 玻尔兹曼机(Boltzmann Machine)是一…

vs2019中出现Debug Error的原因

一般出现这种错误表示你的某个变量没有正确赋值&#xff0c;或者说本身在你的C程序中加了assert断言&#xff0c;assert的作用是先计算表达式expression,如果其值为假&#xff0c;那么它会打印一条错误信息 #include<assert.h> void assert(int expression); 例子&…

【23-24 秋学期】NNDL 作业8 卷积 导数 反向传播

习题5-2 证明宽卷积具有交换性&#xff0c; 即公式(5.13)&#xff0e; 图像X和卷积核W的宽卷积定义如下&#xff1a; 要证明&#xff1a;当图像X和卷积核W有固定长度时,他们的宽卷积具有满足交换性&#xff0c;如下&#xff1a; 设二维图像为&#xff1a;&#xff0c;也就是…

【华为OD】B\C卷真题 100%通过:找城市 多叉树实现 python源码

【华为OD】B\C卷真题 100%通过:找城市 多叉树实现 python源码 目录 题目描述&#xff1a; 示例1 示例2 解题思路&#xff1a; 代码实现&#xff1a; 题目描述&#xff1a; 一张地图上有n个城市&#xff0c;城市和城市之间有且只有一条道路相连&#xff1a;要么直接相连&…

Android设计模式--桥接模式

闻正言&#xff0c;行正道&#xff0c;左右前后皆正人 一&#xff0c;定义 将抽象部分与实现部分分离&#xff0c;使它们都可以独立地进行变化 二&#xff0c;使用场景 从模式的定义中&#xff0c;我们大致可以了解到&#xff0c;这里的桥接的作用其实就是连接抽象部分与实现…

如何提高API性能

下图给出了提高API性能的5个常用技巧 分页 当结果很大时&#xff0c;这是一种常见的优化。结果会流回客户端以提高服务响应能力。 异步日志记录 同步日志记录每次调用都会处理磁盘&#xff0c;并且会降低系统速度。异步日志记录首先将日志发送到无锁缓冲区并立即返回。日志将…

肾合胶囊 | 冬不养肾春易病,若出现了这六大表现,小心是肾虚!

冬季作为一年中最寒冷的季节&#xff0c;自然万物皆静谧闭藏&#xff0c;而肾具有潜藏、封藏、闭藏精气的特点&#xff0c;是封藏之本&#xff0c;肾的脏腑特性与冬季相通应&#xff0c;所以在冬季更应该重视养肾。 而现在正值初冬&#xff0c;正是开始养肾的最佳时间。此时培…

2018年3月26日 Go生态洞察:Go包版本管理提案分析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Java核心知识点整理大全16-笔记

Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全3-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全4-笔记-CSDN博客 Java核心知识点整理大全5-笔记-CSDN博客 Java核心知识点整理大全6…

4/5G互操作 EPSFB讲解

今天我们来讲一下4/5G之间之间互操作&#xff0c;以及5G的EPSFB是基于什么实现的~ 目录 4/5G互操作 重选 切换 基于覆盖的切换 基于业务的切换 两个面试问题 想要加快4G切换5G的速度&#xff0c;调哪个参数怎么调高效&#xff1f; 想要减慢5G切换4G的速度调哪个参数怎…

STM32 F1 串口空闲中断 + DMA实现数据发送

DMA实现数据发送 文章目录 DMA实现数据发送前言一、DMA二、代码编写1.DMA2.USART3.main 前言 当你遇到通信数据量大的时候&#xff0c;可以使用 空闲中断 DMA 的方案来减轻 CPU 的压力。 或者 在进行stm32开发时&#xff0c;有时会遇到这种情况&#xff1a;需要在设备间进行数…

字符串原地旋转

记录一下做的练习题 字符串原地旋转&#xff1a;五 三 mat [[1,2,3],[3,4,5],[4,5,6]] tag0 total 0 for i in mat:total total i[tag]tag 1 print(total) 四 X [[12,7,3],[4,5,6],[7,8,9]] Y [[5,8,1],[6,7,3],[4,5,9]] res [[0,0,0],[0,0,0],[0,0,0]] for i in rang…