OAG 库 (OpenGL) 第 2.3 部分 - 使用鼠标和编程方式绘制 2D 纹理






4.29/5 (6投票s)
本教程展示了 2D 纹理的库代码以及如何在 MFC 应用程序中使用鼠标以编程方式绘制它们。
引言
在本教程中,我们将学习如何绘制 2D 纹理。您必须下载该库才能编译示例。单击此处前往下载页面。使用 OAG_2D,您可以保存和打开 XML 文件 (*.oagxml)。
2D 纹理和环绕
无环绕 | 重复 | 裁剪 |
---|---|---|
|
|
|
绘制 2D 纹理
要使用该库绘制字体,您需要创建一个 oag::TextureMappingTable
实例来存储纹理,并创建一个 TextureMapping
实例。oag::TextureMappingTable
类管理用于绘制的纹理。一旦您选择一个纹理并将其存储在 oag::TextureMappingTable
类中,它就会被添加到 oag::TextureMappingTable
类的一个纹理数组列表中。可用于纹理映射的类是 oag::OAGRectangleMapping
和 oag::OAGTriangleMapping
。oag::OAGRectangleMapping
类将纹理绘制为矩形,而 oag::OAGTriangleMapping
类将纹理绘制为三角形。oag::OAGRectangleMapping
和 oag::OAGTriangleMapping
类使用存储在 oag::TextureMappingTable
类中的纹理在屏幕上绘制纹理。
设置文档类
文档的成员
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.
UnloadLibraryObjects();
CreateLibraryObjects();
UpdateAllViews(NULL);
return TRUE;
}
插入纹理
要插入纹理,请单击 TableObjects 菜单,单击 Texture,然后选择一个纹理文件。
对于演示,我们将使用一到两张纹理。如果您选择一张纹理,您将看到使用一张 Texture
的对象。如果您选择两张纹理,您可以使用 MultiTexture
绘制对象。纹理的过滤器是在您通过单击命令菜单项选择纹理时创建的。
void COAGMFCDoc::OnInsertTexture()
{
CString filter;
filter.LoadString( IDS_TEXTURE_FILTER );
CFileDialog dlg(TRUE, "*.*", 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::OAGTexture* pTexture =
oag::OAGTextureLoader::LoadTextureFromDisk( strFileName.GetString() );
if( pTexture )
{
if( m_pScene->GetTextureMappingTable()->m_ListTexture.size() < 1)
pTexture->SetTextureName("Image1");
else
pTexture->SetTextureName("Image2");
oag::TextureMappingTable* pTexMapTable =
m_pObjectsMappingTable->GetTextureMappingTable();
if ( pTexMapTable == NULL || !pTexMapTable->AddTexture( pTexture ) )
delete pTexture;
else
pTexMapTable->AddTexture( pTexture );
}
pView->m_pWinGraphicContext->DeleteCurrent();
}
}
}
插入 2D 纹理
现在我们可以使用 m_pScene->GetTextureMappingTable()->GetTexture("Image1")
从 m_pTextureMappingTable
获取纹理。请记住,Image1
是上面加载的纹理的名称。
定义纹理过滤器
枚举 OAG_TEXTURE_FILTER | OpenGL 命令 |
---|---|
MAG_FILTER_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) |
MAG_FILTER_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) |
MAG_FILTER_GL_NEAREST_MIPMAP_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_LINEAR) |
MAG_FILTER_GL_NEAREST_MIPMAP_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST); |
MAG_FILTER_GL_LINEAR_MIPMAP_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR) |
MAG_FILTER_GL_LINEAR_MIPMAP_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST) |
MIN_FILTER_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) |
MIN_FILTER_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) |
MIN_FILTER_GL_NEAREST_MIPMAP_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR) |
MIN_FILTER_GL_NEAREST_MIPMAP_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST) |
MIN_FILTER_GL_LINEAR_MIPMAP_LINEAR |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) |
MIN_FILTER_GL_LINEAR_MIPMAP_NEAREST |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST) |
将过滤器添加到纹理
函数 GetTexture
用于选择纹理。在这种情况下,我们将使用 Image1
。
oag::OAGTexture* t1 = GetTexture("Image1");
std::vector<OAG_TEXTURE_FILTER> filterList;
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
t1->SetTextureMode(GL_MODULATE);
t1->SetTextureFilter( filterList );
定义纹理环绕
枚举 OAG_TEXTURE_WRAP | OpenGL 命令 |
---|---|
WRAP_S_REPEAT |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) |
WRAP_S_CLAMP |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) |
WRAP_T_REPEAT |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) |
WRAP_T_CLAMP |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) |
将环绕重复添加到纹理
oag::OAGTexture* t1 = GetTexture("Image1");
std::vector<OAG_TEXTURE_FILTER> filterList;
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
t1->SetTextureFilter( filterList );
std::vector<OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_REPEAT);
wrapList.push_back( WRAP_T_REPEAT);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 4 );
t1->SetTextureMode(GL_MODULATE);
将环绕裁剪添加到纹理
oag::OAGTexture* t1 = GetTexture("Image1");
std::vector<OAG_TEXTURE_FILTER> filterList;
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
t1->SetTextureFilter( filterList );
std::vector<OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_CLAMP);
wrapList.push_back( WRAP_T_CLAMP);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 4 );
t1->SetTextureMode(GL_MODULATE);
矩形映射
要插入矩形映射类型的 2D 纹理,请选择 TexureMapping 菜单,选择 RasterImage Rectangle,或 RasterImage Rectangle Repeating,或 RasterImage Rectangle Clamping,然后单击屏幕以插入矩形纹理映射。
void CRasterImageRectTool::AddAllVerticesToScene()
{
m_pWinGraphicContext->MakeCurrent();
oag::OAGRectangleMapping* tex = new oag::OAGRectangleMapping();
oag::OAGVector3f vec1 = m_arrVector[0];
tex->SetPosition( oag::OAGVector3f( vec1.m_X, vec1.m_Y, vec1.m_Z ) );
oag::OAGTexture* t1 = m_pScene->GetTextureMappingTable()->GetTexture("Image1");
if ( t1 )
{
//Clear filters and wraps set for the texture
t1->ClearFiltersAndWraps();
std::vector<oag::OAGTexture::TEXTURE_FILTER> filterList;
switch( m_textureRenderMode)
{
case NORMAL:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
}
break;
case REAPEATING:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
//Reapeating
std::vector<oag::OAGTexture::OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_REPEAT);
wrapList.push_back( WRAP_T_REPEAT);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 6 );//Value for texture reapeating
t1->SetTextureMode( GL_MODULATE );
}
break;
case CLAMPING:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
//Clamping
std::vector<oag::OAGTexture::OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_CLAMP);
wrapList.push_back( WRAP_T_CLAMP);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 4 ); //Value for texture clamping
t1->SetTextureMode( GL_MODULATE );
}
break;
}
t1->SetTextureFilter( filterList );
t1->SetTextureHeight(256);
t1->SetTextureWidth(256);
t1->BuildTexture();
}
tex->SetTexture(t1);
m_pScene->AddObject( tex );
m_pWinGraphicContext->DeleteCurrent();
}
要插入三角形映射类型的 2D 纹理,请选择 TexureMapping 菜单,选择 RasterImage Triangle,或 RasterImage Triangle Repeating,或 RasterImage Triangle Clamping,然后单击屏幕以插入三角形纹理映射。
void CRasterImageTriangleTool::AddAllVerticesToScene()
{
m_pWinGraphicContext->MakeCurrent();
oag::OAGTriangleMapping* tex = new oag::OAGTriangleMapping();
oag::OAGVector3f vec1 = m_arrVector[0];
tex->SetPosition( oag::OAGVector3f( vec1.m_X, vec1.m_Y, vec1.m_Z ) );
oag::OAGTexture* t1 = m_pScene->GetTextureMappingTable()->GetTexture("Image1");
if ( t1 )
{
//Clear filters and wraps set for the texture
t1->ClearFiltersAndWraps();
std::vector<oag::OAGTexture::TEXTURE_FILTER> filterList;
switch( m_textureRenderMode)
{
case NORMAL:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
}
break;
case REAPEATING:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
//Reapeating
std::vector<oag::OAGTexture::OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_REPEAT);
wrapList.push_back( WRAP_T_REPEAT);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 6 );//Value for texture reapeating
t1->SetTextureMode( GL_MODULATE );
}
break;
case CLAMPING:
{
//Filters
filterList.push_back( MAG_FILTER_LINEAR);
filterList.push_back( MIN_FILTER_LINEAR);
//Clamping
std::vector<oag::OAGTexture::OAG_TEXTURE_WRAP> wrapList;
wrapList.push_back( WRAP_S_CLAMP);
wrapList.push_back( WRAP_T_CLAMP);
t1->SetTextureWrap( wrapList );
t1->SetWrapValue( 4 ); //Value for texture clamping
t1->SetTextureMode( GL_MODULATE );
}
break;
}
t1->SetTextureFilter(filterList);
t1->SetTextureHeight(256);
t1->SetTextureWidth(256);
t1->BuildTexture();
}
tex->SetTexture( t1 );
m_pScene->AddObject( tex );
m_pWinGraphicContext->DeleteCurrent();
}
XML文件
在下图中所示的 XML 中,Tables
节点存储一个 Textures
节点。Textures
节点存储用于绘制 2D 纹理的纹理。在此示例中,我们使用了 honda.bmp。<Texture Name="Image1" FileName="honda.bmp"/>
节点显示了这一点。
Objects
节点存储要在屏幕上绘制的 2D 纹理。TextureMapping
节点显示了这一点。TextureMappings
中的 <UseTexture Name="Image1"/>
节点意味着在加载此 XML 时,两个 2D 纹理将使用 image1
纹理进行绘制。
<OAGLibrary>
<?xml version="1.0" encoding="ISO-8859-1"?>
<OAGLibrary>
<Scene>
<Tables>
<Textures>
<Texture Name="Image1" FileName="honda-pcx.jpg"/>
</Textures>
</Tables>
<Objects>
<TextureMapping Name="" Type="Rectangle">
<Transform>
<Translation x="5." y="49." z="0."/>
</Transform>
<UseTexture Name="Image1"/>
</TextureMapping>
<TextureMapping Name="" Type="Triangle">
<Transform>
<Translation x="589." y="52." z="0."/>
</Transform>
<UseTexture Name="Image1"/>
</TextureMapping>
</Objects>
</Scene>
</OAGLibrary>
加载 XML 后,您将看到这两个纹理
创建纹理顶点
void oag::OAGTexture::CreateTextureVertices()
{
switch( m_enumTextureMapping )
{
case OAG_TEXTURE_MAP_RECT:
{
m_nNumberOfPoints = 4;
m_nTextureVertices.resize( 0 );
m_nTextureVertices.reserve( m_nNumberOfPoints );
m_nTextureVertices.push_back(
oag::OAGVector3d(m_position.m_X, m_position.m_Y, 0));
m_nTextureVertices.push_back( oag::OAGVector3d( m_position.m_X,
m_position.m_Y + m_nHeight, 0));
m_nTextureVertices.push_back( oag::OAGVector3d(m_position.m_X + m_nWidth,
m_position.m_Y + m_nHeight, 0) );
m_nTextureVertices.push_back( oag::OAGVector3d(m_position.m_X +
m_nWidth, m_position.m_Y) );
}
break;
case OAG_TEXTURE_MAP_TRIANGLE:
{
m_nNumberOfPoints = 3;
m_nTextureVertices.resize( 0 );
m_nTextureVertices.reserve( m_nNumberOfPoints );
m_nTextureVertices.push_back(
oag::OAGVector3d(m_position.m_X, m_position.m_Y, 0 ) );
m_nTextureVertices.push_back( oag::OAGVector3d(m_position.m_X +
m_nWidth, m_position.m_Y, 0) );
m_nTextureVertices.push_back( oag::OAGVector3d(m_position.m_X +
(m_nWidth/2.f), m_position.m_Y + m_nHeight, 0) );
}
break;
}
}
创建纹理坐标
void oag::OAGTexture::CreateTextureCoordinates()
{
m_nTextureCoordinates.resize(0);
switch( m_enumTextureMapping)
{
case OAG_TEXTURE_MAP_RECT:
{
//Rectangle
m_nNumberOfCoordinates = 8;
float values[8] = { 0, 0, 0, m_fWrapValue, m_fWrapValue,
m_fWrapValue, m_fWrapValue, 0 };
m_nTextureCoordinates.reserve(8);
for(int i=0; i < 8; i++)
m_nTextureCoordinates.push_back( values[i] );
}
break;
case OAG_TEXTURE_MAP_TRIANGLE:
{
//Triangle
m_nNumberOfCoordinates = 6;
float values[6] = { 0, 0, m_fWrapValue, 0, 0.5, m_fWrapValue };
m_nTextureCoordinates.reserve(6);
for(int i=0; i < 6; i++)
m_nTextureCoordinates.push_back( values[i] );
}
break;
}
}