ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:20.06KB ,
资源ID:29226116      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/29226116.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(贝塞尔曲面.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

贝塞尔曲面.docx

1、贝塞尔曲面贝塞尔曲面这篇教程旨在介绍贝塞尔曲面,希望有比我更懂艺术的人能用她作出一些很COOL的东东并且展示给大家。教程不能用做一个完整的贝塞尔曲面库,而是一个展示概念的程序让你熟悉曲面怎样实现的。而且这不是一篇正规的文章,为了方便理解,我也许在有些地方术语不当;我希望大家能适应这个。最后,对那些已经熟悉贝塞尔曲面想看我写的如何的,真是丢脸;-)但你要是找到任何纰漏让我或者NeHe知道,毕竟人无完人嘛?还有,所有代码没有象我一般写程序那样做优化,这是故意的。我想每个人都能明白写的是什么。好,我想介绍到此为止,继续看下文!数学:恶魔之音:(警告:内容有点长)好,如果想理解贝塞尔曲面没有对其数学基

2、本的认识是很难的,如果你不愿意读这一部分或者你已经知道了关于她的数学知识你可以跳过。首先我会描述贝塞尔曲线再介绍生成贝塞尔曲面。奇怪的是,如果你用过一个图形程序,你就已经熟悉了贝塞尔曲线,也许你接触的是另外的名称。它们是画曲线的最基本的方法,而且通常被表示成一系列点,其中有两个点与两端点表示左右两端的切线。下图展示了一个例子。这是最基础的贝塞尔曲线(长点的由很多点在一起(多到你都没发现)。这个曲线由4个点定义,有2个端点和2个中间控制点。对计算机而言这些点都是一样的,但是特意的我们通常把前后两对点分别连接,因为他们的连线与短点相切。曲线是一个参数化曲线,画的时候从曲线上平均找几点连接。这样你可

3、以控制曲线曲面的精度(和计算量)。最通常的方法是远距离少细分近距离多细分,对视点,看上去总是很完好的曲面而对速度的影响总是最小。贝塞尔曲面基于一个基本方程,其他复杂的都是基于此。方程为:t + (1 - t) = 1看起来很简单不是?的确是的,这是最基本的贝塞尔曲线,一个一维的曲线。你也许从术语中猜到,贝塞尔曲线是多项式形式的。从线性代数知,一个一维的多项式是一条直线,没多大意思。好,因为基本方程对所有t都成立,我们可以平方,立方两边,怎么都行,等式都是成立的,对吧?好,我们试试立方。(t + (1-t)3 = 13t3 + 3*t2*(1-t) + 3*t*(1-t)2 + (1-t)3 =

4、 1这是我们最常用的计算贝塞尔曲面的方程,a)她是最低维的不需要在一个平面内的多项式(有4个控制点),而且b)两边的切线互相没有联系(对于2维的只有3个控制点)。那么你看到了贝塞尔曲线了吗?呵呵,我们都没有,因为我还要加一个东西。好,因为方程左边等于1,可以肯定如果你把所有项加起来还是等于1。这是否意味着在计算曲线上一点时可以以此决定该用每个控制点的多少呢?(答案是肯定的)你对了!当我们要计算曲线上一点的值我们只需要用控制点(表示为向量)乘以每部分再加起来。基本上我们要用0=t=1,但不是必要的。不明白了把?这里有函数:P1*t3 + P2*3*t2*(1-t) + P3*3*t*(1-t)2

5、 + P4*(1-t)3 = Pnew因为多项式是连续的,有一个很好的办法在4个点间插值。曲线仅经过P1,P4,分别当t=1,0。好,一切都很好,但现在我怎么把这个用在3D里呢?其实很简单,为了做一个贝塞尔曲面,你需要16个控制点,(4*4),和2个变量t,v。你要做的是计算在分量v的沿4条平行曲线的点,再用这4个点计算在分量t的点。计算了足够的这些点,我们可以用三角带连接他们,画出贝塞尔曲面。恩,我认为现在已经有足够的数学背景了,看代码把!#include / 数学库#include / 标准输入输出库#include / 标准库typedef struct point_3d / 3D点的结

6、构double x, y, z; POINT_3D;typedef struct bpatch / 贝塞尔面片结构POINT_3Danchors44;/ 由4x4网格组成GLuintdlBPatch;/ 绘制面片的显示列表名称GLuinttexture;/ 面片的纹理 BEZIER_PATCH;BEZIER_PATCHmybezier;/ 创建一个贝塞尔曲面结构BOOLshowCPoints=TRUE;/ 是否显示控制点intdivs = 7;/ 细分精度,控制曲面的显示精度以下是一些简单的向量数学的函数。如果你是C+爱好者你可以用一个顶点类(保证其为3D的)。/ 两个向量相加,p=p+qPO

7、INT_3D pointAdd(POINT_3D p, POINT_3D q) p.x += q.x;p.y += q.y;p.z += q.z;return p;/ 向量和标量相乘p=c*pPOINT_3D pointTimes(double c, POINT_3D p) p.x *= c;p.y *= c;p.z *= c;return p;/ 创建一个3D向量POINT_3D makePoint(double a, double b, double c) POINT_3D p;p.x = a;p.y = b;p.z = c;return p;这基本上是用C写的3维的基本函数,她用变量u和

8、4个顶点的数组计算曲线上点。每次给u加上一定值,从0到1,我们可得一个很好的近似曲线。求值器基于Bernstein多项式定义曲线,定义p(u )为:p(u)=Bni(u)Ri这里Ri为控制点Bni(u)=niui(1-u)n-i且00=1,n0=1u=(u-u1)/(u2-u1)当为贝塞尔曲线时,控制点为4,相应的4个Bernstein多项式为:1、B30 =(1-u)32、B31 =3u(1-u)23、B32 =3u2(1-u)4、B33 =u3/ 计算贝塞尔方程的值/ 变量u的范围在0-1之间POINT_3D Bernstein(float u, POINT_3D *p) POINT_3D

9、a, b, c, d, r;a = pointTimes(pow(u,3), p0);b = pointTimes(3*pow(u,2)*(1-u), p1);c = pointTimes(3*u*pow(1-u),2), p2);d = pointTimes(pow(1-u),3), p3);r = pointAdd(pointAdd(a, b), pointAdd(c, d);return r;这个函数完成共享工作,生成所有三角带,保存在display list。我们这样就不需要每贞都重新计算曲面,除了当其改变时。另外,你可能想用一个很酷的效果,用MORPHING教程改变控制点位置。这可以

10、做一个很光滑,有机的,morphing效果,只要一点点开销(你只要改变16个点,但要从新计算)。“最后”的数组元素用来保存前一行点,(因为三角带需要两行)。而且,纹理坐标由表示百分比的u,v来计算(平面映射)。还有一个我们没做的是计算法向量做光照。到了这一步,你基本上有2种选择。第一是找每个三角形的中心计算X,Y轴的切线,再做叉积得到垂直与两向量的向量,再归一化,得到法向量。或者(恩,这是更好的方法)你可以直接用三角形的法矢(用你最喜欢的方法计算)得到一个近似值。我喜欢后者;我认为不值得为了一点点真实感影响速度。/ 生成贝塞尔曲面的显示列表GLuint genBezier(BEZIER_PAT

11、CH patch, int divs) intu = 0, v;floatpy, px, pyold;GLuintdrawlist = glGenLists(1);/ 创建显示列表POINT_3Dtemp4;POINT_3D*last = (POINT_3D*)malloc(sizeof(POINT_3D)*(divs+1);/ 更具每一条曲线的细分数,分配相应的内存if (patch.dlBPatch != NULL)/ 如果显示列表存在则删除glDeleteLists(patch.dlBPatch, 1);temp0 = patch.anchors03;/ 获得u方向的四个控制点temp1

12、 = patch.anchors13;temp2 = patch.anchors23;temp3 = patch.anchors33;for (v=0;v=divs;v+) / 根据细分数,创建各个分割点额参数px = (float)v)/(float)divs);/ 使用Bernstein函数求的分割点的坐标lastv = Bernstein(px, temp);glNewList(drawlist, GL_COMPILE);/ 创建一个新的显示列表glBindTexture(GL_TEXTURE_2D, patch.texture);/ 邦定纹理for (u=1;u=divs;u+) py

13、 = (float)u)/(float)divs);/ 计算v方向上的细分点的参数pyold = (float)u-1.0f)/(float)divs);/ 上一个v方向上的细分点的参数temp0 = Bernstein(py, patch.anchors0);/ 计算每个细分点v方向上贝塞尔曲面的控制点temp1 = Bernstein(py, patch.anchors1);temp2 = Bernstein(py, patch.anchors2);temp3 = Bernstein(py, patch.anchors3);glBegin(GL_TRIANGLE_STRIP);/ 开始绘制

14、三角形带for (v=0;vsizeX, TextureImage-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage-data);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);if (TextureImage-data)free(TextureImage-data);return success;仅仅加了曲面初始化在这。你每次建一个曲面时都会用

15、这个。再一次,这里是一个用C+的好地方(贝塞尔曲面类?)。int InitGL(GLvoid)/ 初始化OpenGLglEnable(GL_TEXTURE_2D);/ 使用2D纹理glShadeModel(GL_SMOOTH);/ 使用平滑着色glClearColor(0.05f, 0.05f, 0.05f, 0.5f);/ 设置黑色背景glClearDepth(1.0f);/ 设置深度缓存glEnable(GL_DEPTH_TEST);/ 使用深度缓存glDepthFunc(GL_LEQUAL);/ 设置深度方程glHint(GL_PERSPECTIVE_CORRECTION_HINT, G

16、L_NICEST);initBezier();/ 初始化贝塞尔曲面LoadGLTexture(&(mybezier.texture), ./Data/NeHe.bmp);/ 载入纹理mybezier.dlBPatch = genBezier(mybezier, divs);/ 创建显示列表return TRUE;/ 初始化成功首先调贝塞尔display list。再(如果边线要画)画连接控制点的线。你可以用SPACE键开关这个。int DrawGLScene(GLvoid)/ 绘制场景int i, j;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_

17、BIT);glLoadIdentity();glTranslatef(0.0f,0.0f,-4.0f);/ 移入屏幕4个单位glRotatef(-75.0f,1.0f,0.0f,0.0f);glRotatef(rotz,0.0f,0.0f,1.0f);/ 旋转一定的角度glCallList(mybezier.dlBPatch);/ 调用显示列表,绘制贝塞尔曲面if (showCPoints) / 是否绘制控制点glDisable(GL_TEXTURE_2D);glColor3f(1.0f,0.0f,0.0f);for(i=0;i4;i+) / 绘制水平线glBegin(GL_LINE_STRI

18、P);for(j=0;j4;j+)glVertex3d(mybezier.anchorsij.x, mybezier.anchorsij.y, mybezier.anchorsij.z);glEnd();for(i=0;i4;i+) / 绘制垂直线glBegin(GL_LINE_STRIP);for(j=0;j 1) / 按下键,减少曲面的细分数目divs-;mybezier.dlBPatch = genBezier(mybezier, divs);/ 更新贝塞尔曲面的显示列表keysVK_DOWN = FALSE;if (keysVK_SPACE) / 按空格切换控制点的可见性showCPoints = !showCPoints;keysVK_SPACE = FALSE;恩,我希望这个教程让你了然于心而且你现在象我一样喜欢上了贝塞尔曲面。;-)如果你喜欢这个教程我会继续写一篇关于NURBS的如果有人喜欢。请EMAIL我让我知道你怎么想这篇教程。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1