OpenGL曲面纹理贴图技术--波浪的模拟(转 作者 Y_Y)

 
    学过OpenGL的人都很容易的把图片贴到四边形和三角行上,但将纹理贴到一般的曲面上认为很困难,其实

通过本文的简单分析,其实很简单。本文以波浪模拟为例,来介绍一般纹理贴图技术,大家很容易举一反三来

模拟其他的现象。代码的蓝本主要来自NeHe。
1.简单的数学知识介绍

向量的乘积(这里指叉乘)。
用程序写出来如下。

// 三维点定义
struct  cvPoint
{
 
float x,y,z; //点的坐标
}
;
// 矢量相乘C=A*B (方向符合右手定则)
void  vect_mult( struct  cvPoint  * A,  struct  cvPoint  * B,  struct  cvPoint  * C)
{
 C
->x=A->* B->-->* B->y;
 C
->y=A->* B->-->* B->z;
 C
->z=A->* B->-->* B->x;
}

 

四边形的法向选取
    四边形的法向选取采用四边形两条对角线向量相乘。问什么不采用四边形的边相乘,因为四边形四顶点点

并不一定共平面,采用四边形两条对角线向量相乘,显然要更精确一些。

波浪方程(其实就是正弦或余弦函数绕z轴旋转的)

double  t = 0.0 ; // 相位
double  sf( double  x, double  y)
{
 
return cos(sqrt(x*x+y*y)+t);
}

 

2.创建纹理(NeHe)
不清楚的可参考NeHe的教程,清楚地可跳过本节。

 

GLuint texture[ 3 ];
AUX_RGBImageRec 
* LoadBMP( char   * Filename)      //  载入位图图象
{
 FILE 
*File=NULL;       // 文件句柄
 if(!Filename)        // 确保文件名已

提供
 
{
  
return NULL;       // 如果没提供,

返回 NULL
 }

 File
=fopen(Filename,"r");      // 尝试打开文件
 if(File)        // 文件存在么?
 {
  fclose(File);       
// 关闭句柄
  return auxDIBImageLoad(Filename);    // 载入位图并返

回指针
 }

 
return NULL;        // 如果载入失败

,返回 NULL
}

int  LoadGLTextures()         //  载入位图(调用

上面的代码)并转换成纹理
{
 
int Status=FALSE;       // 状态指示器
 AUX_RGBImageRec *TextureImage[1];     // 创建纹理的存

储空间
 memset(TextureImage,
0,sizeof(void *)*1);    // 将指针设为 

NULL
 
// 载入位图,检查有无错误,如果位图没找到则退出
 if(TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
 
{
  Status
=TRUE;       // 将 Status 设

为 TRUE
  glGenTextures(
3&texture[0]);     // 创建纹理
  
  
// 创建 Nearest 滤波贴图
  glBindTexture(GL_TEXTURE_2D, texture[0]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
  glTexImage2D(GL_TEXTURE_2D, 
03, TextureImage[0]->sizeX, TextureImage[0]-

>sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
  
// 创建线性滤波纹理
  glBindTexture(GL_TEXTURE_2D, texture[1]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  glTexImage2D(GL_TEXTURE_2D, 
03, TextureImage[0]->sizeX, TextureImage[0]-

>sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
  
// 创建 MipMapped 纹理
  glBindTexture(GL_TEXTURE_2D, texture[2]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); 
  gluBuild2DMipmaps(GL_TEXTURE_2D, 
3, TextureImage[0]->sizeX, TextureImage[0]-

>sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); 
 }

 
if (TextureImage[0])       // 纹理是否存在
 {
  
if (TextureImage[0]->data)     // 纹理图像是否

存在
  
{
   free(TextureImage[
0]->data);    // 释放纹理图像

占用的内存
  }
  
  free(TextureImage[
0]);      // 释放图像结构
 }

 
return Status;        // 返回 Status
}



3.曲面纹理贴图的关键
    曲面纹理贴图的关键就是把曲面分成小块(本文采用四边形),纹理贴图也要相对应的分成小块,然后相

对应的把纹理贴到相对应的曲面小块。注意一定要相对应,连顶点都要相对应。
    先将曲面分割,并存储其分割的顶点。

 

float  ver[ 21 ][ 21 ][ 3 ];
GLvoid initVer()
{
 
int i,j;
 
float dx=D_PI*8/20.0,dy=D_PI*8/20.0;
 
for(i=0;i<=20;i++)
  
for(j=0;j<=20;j++)
  
{
   ver[i][j][
0]=i*dx-D_PI*4;
   ver[i][j][
1]=j*dy-D_PI*4;
   ver[i][j][
2]=(float)sf(ver[i][j][0],ver[i][j][1]);
  }

}

开始贴图
cvPoint pa,pb,pc;
for ( int  i = 0 ;i < 20 ;i ++ )
    
for ( int  j = 0 ;j < 20 ;j ++ )
    
{
        
//第一条对角线
        pa.x=ver[i+1][j+1][0]-ver[i][j][0];
        pa.y
=ver[i+1][j+1][1]-ver[i][j][1];
        pa.z
=ver[i+1][j+1][2]-ver[i][j][2];
        
//第二条对角线
        pb.x=ver[i][j+1][0]-ver[i+1][j][0];
        pb.y
=ver[i][j+1][1]-ver[i+1][j][1];
        pb.z
=ver[i][j+1][2]-ver[i+1][j][2];

        vect_mult(
&pa,&pb,&pc);//计算法向,注意顺序
        glNormal3f(pc.x,pc.y,pc.z);
        
//注意要一一对应
        glBegin(GL_QUADS);
        glTexCoord2f(
0.05*i,0.05*j);
        glVertex3f(ver[i][j][
0],ver[i][j][1],ver[i][j][2]);
        glTexCoord2f(
0.05*(i+1),0.05*j);
        glVertex3f(ver[i
+1][j][0],ver[i+1][j][1],ver[i+1][j][2]);
        glTexCoord2f(
0.05*(i+1),0.05*(j+1));
        glVertex3f(ver[i
+1][j+1][0],ver[i+1][j+1][1],ver[i+1][j+1][2]);
        glTexCoord2f(
0.05*i,0.05*(j+1));
        glVertex3f(ver[i][j
+1][0],ver[i][j+1][1],ver[i][j+1][2]);
        glEnd();
    }



动起来
这个So Simple!改变相位即可。

t += 0.05 ;

 

搞定,曲面纹理贴图技术就这么简单。

完整的代码(运行前,先在创建Data文件夹,并放一张256×256的位图以供加载纹理)

#include  < windows.h >    //  Windows的头文件
#include  < GL / gl.h >    //  包含最新的gl.h,glu.h库
#include  < GL / glu.h >    //  包含OpenGL实用库
#include  < GL / glaux.h >
#include 
< stdio.h >    //  标准输入/输出库的头文件
#include  < math.h >
#define  D_PI 3.141592653
#pragma  warning(disable:4305)
#pragma  warning(disable:4244)

struct  cvPoint
{
 
float x,y,z; //点的坐标
}
;
// 矢量相乘C=A*B 
void  vect_mult( struct  cvPoint  * A,  struct  cvPoint  * B,  struct  cvPoint  * C)
{
 C
->x=A->* B->-->* B->
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值