最近做项目需要实现二维平面对非规则多边形的纹理填充,要求纹理能够铺满任何形状的多边形。从网上找了一些二维纹理映射的方法。比如说:
glBindTexture(GL_TEXTURE_2D, furniture->GetImage2D()->GetTextureID())
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(pt1.x, pt1.y, pt1.z);
glTexCoord2f(0, 1);
glVertex3f(pt2.x, pt2.y, pt2.z);
glTexCoord2f(1, 1);
glVertex3f(pt3.x, pt3.y, pt3.z);
glTexCoord2f(1, 0);
glVertex3f(pt4.x, pt4.y, pt4.z);
glEnd();
但是,这种方法有一定的局限性,它只能应用于四边形上,对于非规则的多边形并不适用。为了实现对非规则多边形的纹理映射,我采用一种新的方法,并且成功实现了此功能。由于项目比较大,功能融合到项目中,所以我只说明一下具体的实现思路。方法如下:
一、定义多边形三角化后的拓扑关系数据结构,用结构体TriangleInfo进行表示;
struct TriangleInfo
{
int m_iVertexNumber;//三角化后点的数目
glm::vec3* m_vVertice = NULL;//三角化后多边形上点的坐标
glm::vec3* m_vNormal = NULL;//三角化后多边形上点的法向
glm::vec2* m_vTexcoord = NULL;//三角化后多边形上点的纹理坐标
glm::ivec3* m_vTriangle = NULL;//三角后多边形上点的坐标对应的下边
}m_struTriangleInfo;
二、对多边形进行三角化,并把对应的点的拓扑关系加入到结构体TriangleInfo中:
(1)三角化多边形
使用Triangluation的三角化方法实现,这个接口已经做好了,是别人写好的代码。
网站链接如下:http://www.cs.cmu.edu/~quake/triangle.html
http://www.cs.cmu.edu/~quake/triangle.research.html
(2)构建点之间的拓扑结构
根据三角化后得到的TriangulateIO结构数据,对点的纹理坐标进行计算,并保存到结构体TriangleInfo中
三、加载纹理,并绑定纹理对象;
四、将三角化后的多边形点的信息传入OpenGL渲染管线,进行绘制。
GLfloat curColor[4];
glGetFloatv(GL_CURRENT_COLOR, curColor);
glColor3f(1.0f, 1.0f, 1.0f);
int vertice_number = m_struTriangleInfo.m_iVertexNumber;
glm::vec3* vertices = m_struTriangleInfo.m_vVertice;
glm::vec2* texcoords = m_struTriangleInfo.m_vTexcoord;
// enable and specify pointers to vertex arrays
if (vertices)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
}
if (texcoords)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TextureID);//TextureID是之前绑定的纹理对象
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
(float*)(&(vec4(1.0))));
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
(float*)(&(vec4(0.1, 0.1, 0.1, 1.0))));
glDrawElements(GL_TRIANGLES, vertice_number, GL_UNSIGNED_INT, m_struTriangleInfo.m_vTriangle);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
if (vertices)
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (texcoords)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glColor3f(curColor[0], curColor[1], curColor[2]);
通过这种方法,就可以实现任意多边形的纹理映射,图片效果如下: