65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (6投票s)

2010 年 7 月 24 日

CPOL

3分钟阅读

viewsIcon

35129

downloadIcon

1348

本教程展示了 2D 纹理的库代码以及如何在 MFC 应用程序中使用鼠标以编程方式绘制它们。

引言

在本教程中,我们将学习如何绘制 2D 纹理。您必须下载该库才能编译示例。单击此处前往下载页面。使用 OAG_2D,您可以保存和打开 XML 文件 (*.oagxml)。

2D 纹理和环绕

无环绕 重复 裁剪

绘制 2D 纹理

要使用该库绘制字体,您需要创建一个 oag::TextureMappingTable 实例来存储纹理,并创建一个 TextureMapping 实例。oag::TextureMappingTable 类管理用于绘制的纹理。一旦您选择一个纹理并将其存储在 oag::TextureMappingTable 类中,它就会被添加到 oag::TextureMappingTable 类的一个纹理数组列表中。可用于纹理映射的类是 oag::OAGRectangleMappingoag::OAGTriangleMappingoag::OAGRectangleMapping 类将纹理绘制为矩形,而 oag::OAGTriangleMapping 类将纹理绘制为三角形。oag::OAGRectangleMappingoag::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;
  }
}
© . All rights reserved.