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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

基础对象与算法.docx

1、基础对象与算法第二章 基 础 对 象 与 算 法 本章讲述Intra3D最底层功能的设计与实现。这些功能看起来很简单,但对于交互式3D软件开发工具而言都是必不可少的。读者不禁要问:“OpenGL那么优秀,为什么不提供Intra3D的功能呢?” 真是因为OpenGL很优秀,所以才不提供Intra3D的功能。有两个主要理由:(1)OpenGL雄心勃勃地想成为国际通用的图形标准,它必须能在所有流行的平台上运行,即做到与窗口系统无关。因此,OpenGL舍弃了诸如处理文字、数字图像这类常用的功能。(2)OpenGL必须提供一套高性能的API,这些API全是“精明能干”的C函数。就象设计CPU指令一样,O

2、penGL的API不是越多越好,而是要恰到好处。否则OpenGL就会臃肿得象中国的行政机构,让人不堪负重。OpenGL发展了十年,API只增加了几个,可见其系统设计之卓越。2.1 图形变换基础运算 本节是全书唯一出现数学公式的地方。大多数程序员害怕数学公式,我也害怕。所以咱们是同一条战线的,你就不用担心看不懂。 在图形学中,常用矩阵运算来实现图形变换。采用4*4的齐次矩阵就可以用统一的矩阵相乘来表示平移、比例与旋转变换。OpenGL提供了glMultMatrix、glRotate、glTranslate、glScale 等函数来实现常规的图形变换。但是矩阵难以表示图形变换的状态与过程,例如给出

3、前后两个矩阵,就无法判断平移量、缩放量、旋转量各是多少。可见仅使用矩阵运算并不满足交互式3D图形系统的需求。 Intra3D 使用四元组(Quaternion)表示旋转变换的状态,再用两个矢量分别表示平移变换与比例变换的状态。即总共用10个浮点变量就可以完全确定图形变换的状态与过程。在交互式3D图形系统中,常需要用二维的输入设备模拟三维操作。鼠标跟踪球算法就是用鼠标来实现三维旋转变换的一种方法。 本节将重点介绍四元组运算与鼠标跟踪球算法。由于矢量运算与矩阵运算是大家熟知的,本节仅列出相应的函数。 2.1.1 矢量运算 Intra3D 2.0 C+类库中矢量运算的程序见 Intra3D-DLLI

4、ncludeLayer1Algebra Vector.h和Intra3D-DLLLayer1AlgebraVector.cpp。COM库的程序见 Intra3D-COM Layer1Vector.h和Vector.cpp。 矢量的数据结构定义如下:class VECTORpublic:float x, y, z; VECTOR(float x=0.0, float y=0.0, float z=1.0);例如X、Y、Z方向的单位矢量A、B、C可以定义如下:VECTOR A(1, 0, 0), B(0, 1, 0), C(0, 0, 1) ;矢量运算的函数如表2.1所示。float Vector

5、Magnitude(VECTOR A);功能:矢量求模输入:A返回:A 的模 |A|void VectorNormalize(VECTOR *A);功能:矢量归一化输入:A输出:如果 |A|=0,输出矢量仍为 A;否则输出矢量为 A/(|A|)VECTOR operator + (VECTOR A, VECTOR B);功能:矢量相加输入:A, B返回:A + BVECTOR operator - (VECTOR A, VECTOR B);功能:矢量相减输入:A, B返回:A BVECTOR operator * (VECTOR A, float s);VECTOR operator * (f

6、loat s, VECTOR A);功能:矢量缩放输入:A, s返回:s * AVECTOR VectorCross(VECTOR A, VECTOR B);VECTOR operator * (VECTOR A, VECTOR B);功能:矢量叉积输入:A, B返回:A与B的叉积float VectorDot(VECTOR A, VECTOR B);float operator (VECTOR A, VECTOR B);功能:矢量点积输入:A, B返回:A与B的点积表2.1 矢量运算函数2.1.2 矩阵运算 Intra3D 2.0 C+类库中矩阵运算程序见 Intra3D-DLLInclud

7、eLayer1Algebra Matrix.h和Intra3D-DLLLayer1AlgebraMatrix.cpp。COM库的程序见 Intra3D-COM Layer1Matrix.h和Matrix.cpp。矩阵运算的函数如表2.2所示。void MatrixAdd(float *M, const float *A, const float *B, int i=4, int j=4);功能:矩阵相加输入:矩阵A(i,j) 与 B(i,j)输出:M=A+Bvoid MatrixSub(float *M, const float *A, const float *B, int i=4, int

8、 j=4);功能:矩阵相减输入:矩阵A(i,j) 与 B(i,j)输出:M=A-Bvoid MatrixMultiply(float *M, const float *M1, const float *M2, int i1, int j1, int i2, int j2);功能:矩阵相乘输入:矩阵M1(i1,j1) 与M2(i2,j2)输出:M (i1,j2) = M1*M2约束:i2=j1,否则不计算 Mvoid MatrixTranspose(float *M, const float *A, int i=4, int j=4);功能:矩阵转置输入:矩阵A(i,j)输出:M(j,i) =

9、A 的转置BOOL MatrixInverse(float *A, int n=4);功能:矩阵求逆 输入:A(n, n)输出:A = A 的逆返回:TRUE 表示求逆运算成功;FALSE 表示该逆矩阵不存在,此时A 保持不变。void MatrixIdentity(float *A, int n=4);功能:矩阵归一化 输入:A(n, n)输出:A = A 的归一化矩阵VECTOR VectorTransform(VECTOR V, float M16);功能:矢量的矩阵旋转变换输入:初始矢量 V,变换矩阵M16返回:V 经过 M 变换后为 V, 函数返回 V表2.2 矩阵运算函数2.1.3

10、 四元组运算与旋转变换一、复数概念 记Z为一复数,Z为Z的共轭复数,|Z| 为Z的模,则有: Z = a + bi Z= a bi 其中 i * i = -1 。 两个复数 Z1, Z2 相乘可表示为: Z1 = a1 + b1 i Z2 = a2 + b2 i Z1*Z2 =(a1 * a2 - b1 * b2 ) + (a1 * b2 + b1 * a2)i二、四元组概念 四元组是复数的一种扩展。记q为一四元组,q为q的共轭四元组,|q|为四元组的模, 为q的逆(即为1/q),则有: q = w + x i + y j + z k q= w - x i - y j - z k | q |

11、= 1 = q (q1 * q2) * q3 = q1 * (q2 * q3) q1 * q2 q2 * q1 其中 i * i = -1 j * j = -1k * k = -1 i * j = - j * i = kj * k = - k * j = ik * i = - i * k = j 四元组还可以表示为如下形式: q = w + xi + yj + zk = x y z w = ( s , v ) s = w v = x y z 两个四元组 q1和 q2相乘可表示为: q1 = ( s1, v1 ) q2 = ( s2, v2 ) q1*q2 = ( s1*s2 - v1v2 ,

12、s1*v2 + s2*v1 + v1v2)三、用四元组表示旋转变换 设一旋转变换的旋转轴为 u(单位矢量),旋转角度为。则与此旋转变换等价的四元组q为: q = ( s, v ) s = cos(/2) v = u sin(/2) 如果将空间一点p表示成四元组的形式 P=(0,p),则P点经过q旋转得到点Protated : Protated = q * P * 设有两个四元组 q1, q2分别表示前后两个旋转变换,则有: Protated = q2 * ( q1 * P *) * = (q2 * q1) * P * (*) = (q2 * q1) * P * 可见,两个四元组q1, q2的旋

13、转结果就相当于一个四元组(q2 * q1)表示的旋转变换。这与用矩阵相乘来表示旋转变换非常相似,事实上四元组 q(w,x,y,z)等价于如下旋转矩阵: w*w + x*x - y*y - z*z 2*x*y + 2*w*z 2*x*z 2*w*y 0 2*x*y 2*w*z w*w x*x+ y*y -z*z 2*y*z + 2*w*x 0 z*x*z +2*w*y 2*y*z 2*w*x w*w x*x y*y +z*z 0 0 0 0 w*w + x*x + y*y +z*z 有关四元组更深入的论述可参考文献Hearn 1997 Downs 1998。四、程序设计 C+类库中四元组运算程序

14、见 Intra3D-DLLIncludeLayer1AlgebraRotation.h 和Intra3D-DLLLayer1AlgebraRotation.cpp。COM库中四元组运算程序见Intra3D-COMLayer1 Rotation.h 和Rotation.cpp。 四元组的数据结构定义如下:class QUATERNIONpublic: float x, y, z, w; QUATERNION(float x=0.0, float y=0.0, float z=1.0f, float w=0.0);四元组运算的函数如表2.3所示。float QuaternionMagnitude(

15、QUATERNION A);功能:四元组求模输入:四元组A返回:|A|void QuaternionInverse(QUATERNION *A);功能:四元组求逆输入:四元组A输出:如果 |A|=0,不改变 A;否则输出为 A 的逆void QuaternionConjugate(QUATERNION *A);功能:四元组求共扼输入:四元组A输出:A 的共扼QUATERNION operator * (QUATERNION A, QUATERNION B); 功能:四元组相乘输入:四元组A与B返回:A * Bvoid QuaternionToMatrix(float M16, QUATERNI

16、ON Q);功能:求四元组等价的旋转矩阵输入:四元组Q输出:M为与四元组Q等价的旋转矩阵表2.3 四元组运算函数 四元组运算的程序如下:const float DELTA_ROT=1.0E-10; / 允许存在的误差float QuaternionMagnitude(QUATERNION A) return float(sqrt(A.x*A.x + A.y*A.y + A.z*A.z +A.w*A.w);void QuaternionNormalize(QUATERNION *A) float magnitude = float(sqrt(A-x*A-x + A-y*A-y + A-z*A-z

17、 +A-w*A-w); if(magnitude = DELTA_ROT) A-x = A-x/magnitude; A-y = A-y/magnitude; A-z = A-z/magnitude; A-w = A-w/magnitude; void QuaternionInverse(QUATERNION *A) float magnitude2 = A-x*A-x + A-y*A-y + A-z*A-z + A-w*A-w; if(magnitude2 = DELTA_ROT) A-x = -A-x/magnitude2; A-y = -A-y/magnitude2; A-z = -A-

18、z/magnitude2; A-w = A-w/magnitude2; void QuaternionConjugate(QUATERNION *A) A-x = -A-x; A-y = -A-y; A-z = -A-z;QUATERNION operator * (QUATERNION q1, QUATERNION q2) QUATERNION Q; Q.x =q1.w * q2.x + q1.x * q2.w +q1.y * q2.z - q1.z * q2.y; Q.y =q1.w * q2.y + q1.y * q2.w +q1.z * q2.x - q1.x * q2.z; Q.z

19、= q1.w * q2.z + q1.z * q2.w +q1.x * q2.y - q1.y * q2.x; Q.w =q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; return Q;void QuaternionToMatrix(float M16, const QUATERNION quat) float m44; float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; / calculate coefficients x2 = quat.x * 2.0f; y2 = qu

20、at.y * 2.0f; z2 = quat.z * 2.0f; xx = quat.x * x2; xy = quat.x * y2; xz = quat.x * z2; yy = quat.y * y2; yz = quat.y * z2; zz = quat.z * z2; wx = quat.w * x2; wy = quat.w * y2; wz = quat.w * z2; m00 = 1.0f - (yy + zz); m01 = xy + wz; m02 = xz - wy; m03 = 0.0f; m10 = xy - wz; m11 = 1.0f - (xx + zz);

21、m12 = yz + wx; m13 = 0.0f; m20 = xz + wy; m21 = yz - wx; m22 = 1.0f - (xx + yy); m23 = 0.0f; m30 = 0; m31 = 0; m32 = 0; m33 = 1; for(int i=0; i4; i+) for(int j=0; j4; j+) Mi*4+j=mij; 由于四元组的(x,y,z,w)变量并不直观,Intra3D 提供更加简明的旋转结构ROTATION来表示旋转变换。ROTATION的数据结构定义如下:class ROTATIONpublic: VECTOR axis ; / 旋转轴,

22、为单位矢量 float angle; / 旋转角度,0 - 360 度 ROTATION(float x=0.0, float y=0.0, float z=1.0, float angle=0.0); ROTATION(VECTOR axis, float angle); ROTATION运算是通过四元组运算来实现的,函数如表2.4所示。ROTATION operator * ( ROTATION R1, ROTATION R2);功能:ROTATION 相乘,先执行 R1 旋转,后执行 R2 旋转。输入:R1, R2返回:R1与R2的旋转合成Void RotationToMatrix(fl

23、oat M16, ROTATION R);功能:求与ROTATION结构等价的旋转矩阵输入:R输出:M为与R等价的旋转矩阵VECTOR VectorTransform(VECTOR V, ROTATION R);功能:矢量的旋转变换输入:初始矢量 V, 旋转结构R返回:V 经过 R变换后为 V, 函数返回 V表2.4 ROTATION运算函数ROTATION运算的程序如下:/ 将 ROTATION 结构表示成 QUATERNIONQUATERNION RotationToQuaternion(const ROTATION R) QUATERNION Q; float theta = R.ang

24、le/180.0f*3.14159f; float cosValue = cos(theta/2.0f); float sinValue = sin(theta/2.0f); Q.x = sinValue*R.axis.x; Q.y = sinValue*R.axis.y; Q.z = sinValue*R.axis.z; Q.w = cosValue; return Q;/ 将 QUATERNION 结构表示成 ROTATIONROTATION QuaternionToRotation(const QUATERNION Q) ROTATION R; float halfTheta= acos

25、(Q.w); float sinValue = sin(halfTheta); if(sinValue -DELTA_ROT) & (R1.angle-DELTA_ROT) & (R2.angle-DELTA_ROT) & (R.angleDELTA_ROT) ) return V; QUATERNION Q; Q=RotationToQuaternion(R); return VectorTransform(V, Q);2.1.4 鼠标跟踪球算法 用鼠标在窗口中转动一个形体,记窗口的宽度为w,高度为h,形体的转动中心坐标为(cx, cy),鼠标的起点坐标为P1(mx1, my1),终点坐标为P2(mx2, my2)。跟踪球算法的目的就是要计算出旋转轴矢量u,与旋转角度。将P1、P2投影到以(cx, cy)为中心的一个半球面上得到P1与P2,P1与P2在半球面上的矢量表示记为v1与v2。可以近似地认为旋转轴矢量u即为v1与v2的叉积(Cross Product): u = v1 v2旋转角度即为v1与v2的夹角,可用矢量点积(Dot Product)求出: = 180 * acos(v1v2)/ 问题的关键在于求出任一鼠标坐标(mx, my)在半球面上的投影矢量v,该算法的程序如下:

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

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