OAG 库 (OpenGL) 第 2.2 部分 - 使用鼠标和程序化方式绘制 2D 文本





4.00/5 (4投票s)
本教程展示了用于 2D 文本的库代码,以及如何在 MFC 应用程序中使用鼠标和程序化方式绘制它们。
引言
在本教程中,我们将学习如何绘制 2D 字体。您必须下载库才能编译示例。点击 此处 进入下载页面。使用 OAG_2D,您可以保存和打开 XML 文件 (*.oagxml)。
绘制 2D 字体
要使用库绘制字体,您需要创建一个 oag::FontMappingTable
实例来存储字体,以及一个 oag::OAGFontMapping2D
实例。oag::FontMappingTable
类管理用于绘制的字体。选择字体并将其存储在 oag::FontMappingTable
类中后,它将被添加到 oag::FontMappingTable
类中的字体数组列表中。oag::OAGFontMapping2D
类用于使用存储在 oag::FontMappingTable
类中的字体绘制文本。
设置文档类
文档的成员
oag::ObjectsMappingTable* pObjectsMappingTable;
oag::OAGScene* m_pScene;
文档的操作
void CreateLibraryObjects();
void UnloadLibraryObjects();
构造函数和析构函数
COAGMFCDoc::COAGMFCDoc()
:m_pScene(NULL)
,m_pObjectsMappingTable(NULL)
{
CreateLibraryObjects();
}
COAGMFCDoc::~COAGMFCDoc()
{
UnloadLibraryObjects();
}
void COAGMFCDoc::CreateLibraryObjects()
{
if( m_pObjectsMappingTable == NULL)
m_pObjectsMappingTable = new oag::ObjectsMappingTable();
if( m_pScene == NULL )
{
m_pScene = new oag::OAGScene();
m_pScene->SetFontMappingTable( m_pObjectsMappingTable->GetFontMappingTable() );
m_pScene->SetTextureMappingTable( m_pObjectsMappingTable->GetTextureMappingTable() );
}
}
void COAGMFCDoc::UnloadLibraryObjects()
{
//Deletes the scene and all objects from the memory
if ( m_pScene )
{
m_pScene->DeleteAllObjects();
delete m_pScene;
m_pScene = NULL;
}
if ( m_pObjectsMappingTable )
{
delete m_pObjectsMappingTable;
m_pObjectsMappingTable = NULL;
}
}
创建新文档时,我们需要删除所有对象并重新创建它们
BOOL COAGMFCDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
//Deleting all library objects when a new document is started.
//The Fonts must be deleted and created again,
//if not they are not drawn properly
UnloadLibraryObjects();
CreateLibraryObjects();
UpdateAllViews(NULL);
return TRUE;
}
插入字体
要插入字体,请点击“TableObjects”菜单,点击“Font”,然后选择一种 True Type 字体。
选择字体后,它将以 24 的大小创建。函数 pFont->SetFontSize(24)
执行此操作。您不需要再次使用此字体来绘制 2D 文本,只需从 m_pFontMappingTable
获取此字体并使用它来绘制 2D 文本即可。
void COAGMFCDoc::OnInsertFont()
{
CString filter;
filter.LoadString( IDS_FONT_FILTER );
CFileDialog dlg(TRUE, "*.ttf", NULL,
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST, filter );
if(dlg.DoModal() == IDOK)
{
CString strFileName = dlg.GetPathName().GetString();
POSITION pos = GetFirstViewPosition();
COAGMFCView* pView = (COAGMFCView*) GetNextView(pos);
if ( pView->m_pWinGraphicContext->MakeCurrent() )
{
oag::OAGFont* pFont = oag::OAGFontLoader::LoadFontFromDisk(
strFileName.GetString(), OAG_FONT_MAP_2D );
if( pFont )
{
pFont->SetFontSize(24);
pFont->SetFontName("arial");
if ( pFontMapTable == NULL ||
!m_pObjectsMappingTable->GetFontMappingTable()->AddFont( pFont ) )
delete pFont;
else
pFontMapTable->AddFont( pFont );
}
pView->m_pWinGraphicContext->DeleteCurrent();
}
}
}
插入 2D 文本
要插入 2D 文本,请选择“Draw”菜单,点击“2DText”,然后在屏幕上点击以插入文本
插入 2D 文本的代码
函数 font2d->SetText
设置要在屏幕上绘制的文本,而 font2d->SetPosition
设置屏幕上的文本位置。函数 font2d->SetFontNameReference
用于在保存到 XML 文件时获取当前设置的字体。如果未使用 font2d->SetFontNameReference
,则在读取 XML 文件时,字体将未设置,并且屏幕上不会绘制任何文本。
void CText2DTool::AddAllVerticesToScene()
{
oag::OAGFontMapping2D* font2d = new oag::OAGFontMapping2D();
if( m_pScene->GetFontMappingTable()->m_ListFont.size() > 0 )
{
font2d->SetFont( m_pScene->GetFontMappingTable()->m_ListFont[0]->GetFont() );
font2d->SetFontNameReference (
m_pScene->GetFontMappingTable()->m_ListFont[0]->GetFontName() );
}
oag::OAGVector3f vec = m_arrVector[0];
font2d->SetText("Example of 2DText");
font2d->SetPosition( oag::OAGVector3f( vec.m_X, vec.m_Y, vec.m_Z ) );
m_pScene->AddObject( font2d );
}
void CText2DTool::OnMouseClick(oag::OAGVector3f& ptMouse)
{
switch( m_nStep )
{
case 0:
{
m_arrVector.Add( ptMouse );
AddAllVerticesToScene();
CTool::OnFinalize();
}
break;
}
}
XML文件
在下面的 XML 中,节点 Tables
存储一个节点 Fonts
。节点 Fonts
存储用于绘制文本的字体。对于此示例,我们使用了大小为 24 的 arial.tff。节点 <Font Name="" FileName="arial.ttf" Size="24."/>
显示了这一点。
节点 Objects
存储要绘制在屏幕上的 2D 文本。节点 Text2D
显示了这一点
<?xml version="1.0" encoding="ISO-8859-1"?>
<OAGLibrary>
<Tables>
<Fonts>
<Font Name="arial" FileName="arial.ttf" Size="24."/>
</Fonts>
</Tables>
<Scene Type="Draw">
<Objects>
<Text2D Name="">
<UseFont Name="arial"/>
<String Value="Example of 2DText"/>
<Color Red="1." Green="1." Blue="1." Alpha="1."/>
<Transform>
<Translation x="161." y="148." z="0."/>
<Scale x="1." y="1." z="1."/>
<Rotation x="0." y="0." z="0."/>
</Transform>
</Text2D>
</Objects>
</Scene>
</OAGLibrary>
类 oag::Font
class OAGFont
{
public:
OAGFont(void);
virtual ~OAGFont(void);
//Attributes
protected:
bool m_bIsDone;
int m_nFontSize;
OAG_FONT_MAPPING m_enumFontMapping;
FTFont* m_pFont;
std::string m_strName;
std::string m_strFolderPath, m_strFilename;
//Operations
public:
//Gets the FileName used by the font
std::string GetFileName()
{
return m_strFilename;
}
FTFont* GetFont()
{
return m_pFont;
}
int GetFontSize()
{
return m_nFontSize;
}
//Gets the current name set for the texture
std::string GetFontName()
{
return m_strName;
}
//Sets the Font Size
void SetFontSize(int nFontSize)
{
int newSize = nFontSize;
if ( m_pFont )
{
if ( m_pFont->FaceSize( newSize ) )
m_nFontSize = nFontSize;
}
}
//Sets a for the object
void SetFontName(std::string strName)
{
m_strName = strName;
}
void SetIOSystemFilter(std::string folderPath, std::string fileName)
{
m_strFolderPath = folderPath;
m_strFilename = fileName;
}
//bool IsInitialized() { return m_bIsInitialized; };
//Virtual
public:
virtual void LoadFontFromDisk(std::string strFileName){}
};
//Constructor
oag::OAGFont::OAGFont(void)
:m_bIsDone(false)
,m_pFont(NULL)
,m_nFontSize(10)
{
}
//Destructor
oag::OAGFont::~OAGFont(void)
{
if( m_pFont )
{
delete m_pFont;
m_pFont = NULL;
}
}
类 oag::OAGFontMapping
class OAGFontMapping : public oag::OAGObject
{
public:
OAGFontMapping(void);
virtual ~OAGFontMapping(void);
//Attributes
protected:
std::string m_strText;
FTFont* m_pFont;
std::string m_strFontNameReference;
//Operations
public:
std::string GetText()
{
return m_strText;
}
void SetFontNameReference(std::string strFontNameReference)
{
m_strFontNameReference = strFontNameReference;
}
void SetText(std::string strText)
{
m_strText = strText;
}
void SetFont(FTFont* pFont)
{
m_pFont = pFont;
}
//Virtual
public:
virtual void OnDraw(){};
virtual void ReadNodeXML(CXmlNode* pNode);
virtual void SaveNodeXML(CXmlNode* pNode);
};