实现opengl 中gluLookAt函数 glulookat函数理解

opengl Distilled 中介绍了view 坐标转换的原理,先列一下原著中的介绍:

The view transformation transforms vertices into eye coordinates and is the inverse of atransformation to place and orient the viewer in world coordinates. The view transformation hastwo components: a 4 x 4 orientation matrix, O, and a 4 x 4 translation matrix, T. The viewtransformation matrix, V, is the concatenation of the two 4 x 4 matrices:V = OTThe orientation matrix O is an orthonormal basis derived from the view direction and upvectors. Given an [ x y z ] view direction d and an [ x y z ] up vector u, compute their crossproduct c as:c = d x uDiscard u and compute the actual up vector u' as:u' = c x dNormalize d, c, and u' to unit length, and create the orientation matrix O as follows:



The translation matrix T is simply the inverse translation to the eye location. If you alreadyhave the eye location stored in your application, you can use it directly in a call to glTranslated(), as shown in the code below. If you don't have the eye location, scale the view directionvector by the distance to the eye, negate it, and add it to the center location. The result is the

eye location.So if an application creates a double-precision orientation matrix called orientMatrix using thesteps above and has the eye location stored in a double-precision [ x y z ] array called eye, thecode to create the view transformation isglMatrixMode( GL_MODELVIEW );glLoadMatrixd( orientMatrix );glTranslated( -eye[0], -eye[1], -eye[2] );In fact, gluLookAt() does essentially the same thing internally. It computes the view directionby subtracting eye from center and then follows the above method to create the orientationmatrix. For this reason, if your application already stores the center location, view direction,and view distance, gluLookAt() is slightly less efficient than creating the view transformation inyour application code.

下面我大体翻译一下:

视图坐标转换实际上就是把定点的坐标转换进眼睛(摄像机)坐标系中,这个操作与将眼睛转换到相应位置并设定朝向的操作相反。

来完成视图变换操作的矩阵V由两部分矩阵连乘形成的,一部分是朝向矩阵O,一部分是平移矩阵T,所以我们有:

V= OT;

朝向矩阵是由视线朝向D和眼睛的上方向U决定的,这两个方向向量叉乘得到向量C,向量C和向量D叉乘得到U‘,C,U,D(对应x,y,z),形成了眼睛坐标系的三个方向,它们属于右手坐标系,

相关的公式如下:

c = d x u,

u' = c x d,

将得到的三个变量相应的单位化,分别用这三个变量传到下面的矩阵中,就得到了转换需要的朝向矩阵O:



,注意向量d的各个分量都被取了原值的负值。

而平移矩阵,则是将眼睛移动操作的反操作,如果你有眼睛的位置,直接将眼睛的位置全取原值负值就OK了,否则可以用Center位置加一个向量就得到眼睛的位置了。

有了上面的处理后,后面的处理就很简单了,将矩阵加载的opengl中,根据眼睛的位置平移就OK了。代码如下:

glMatrixMode( GL_MODELVIEW );glLoadMatrixd( orientMatrix );glTranslated( -eye[0], -eye[1], -eye[2] );

实际上glLookAt做了一样的事情。

下面上我的代码:

[cpp] view plaincopy

classFVector3

{

public:

union

{

struct

{

GLdoubleX,Y,Z;

};

struct

{

GLdoublex,y,z;

};

GLdoublev[3];

};

public:

FVector3(){}

FVector3(GLdoublex1,GLdoubley1,GLdoublez1):x(x1),y(y1),z(z1)

{}

FVector3(constFVector3&InV);

FVector3operator^(constFVector3&V)const;

FVector3&Normalize();

};

inline

FVector3::FVector3(constFVector3&InV)

{

x=InV.x;

y=InV.y;

z=InV.z;

}

inlineGLdoubleappInvSqrt(GLdoublef){return1.f/sqrt(f);}

inlineFVector3&

FVector3::Normalize()

{

GLdoubleSquareSum=X*X+Y*Y+Z*Z;

if(SquareSum<0.000001)

return*this;

GLdoubleScale=appInvSqrt(SquareSum);

X*=Scale;

Y*=Scale;

Z*=Scale;

return*this;

}

inlineFVector3

FVector3::operator^(constFVector3&V)const

{

returnFVector3(Y*V.Z-Z*V.Y,Z*V.X-X*V.Z,X*V.Y-Y*V.X);

}
实现opengl 中gluLookAt函数 glulookat函数理解

上面的是工具类,下面是实现函数:

[cpp] view plaincopy

staticvoidsuLookAt(GLdoubleeyeX,GLdoubleeyeY,GLdoubleeyeZ,GLdoublecenterX,GLdoublecenterY,GLdoublecenterZ,GLdoubleupX,GLdoubleupY,GLdoubleupZ)

{

GLdoubledirectMat[16];

for(inti=0;i<16;i++)

{

directMat[i]=0;

}

directMat[15]=1;

FVector3fvDirect(centerX-eyeX,centerY-eyeY,centerZ-eyeZ);

fvDirect.Normalize();

FVector3fvUpD(upX,upY,upZ);

fvUpD.Normalize();

FVector3fvC=fvDirect^fvUpD;

fvC.Normalize();

FVector3fvUp=fvC^fvDirect;

fvUp.Normalize();

fvDirect.x=-fvDirect.x;

fvDirect.y=-fvDirect.y;

fvDirect.z=-fvDirect.z;

directMat[0]=fvC.x;

directMat[4]=fvC.y;

directMat[8]=fvC.z;

directMat[1]=fvUp.x;

directMat[5]=fvUp.y;

directMat[9]=fvUp.z;

directMat[2]=fvDirect.x;

directMat[6]=fvDirect.y;

directMat[10]=fvDirect.z;

glLoadMatrixd(directMat);

glTranslated(-eyeX,-eyeY,-eyeZ);

}

调用方法跟gluLookAt一样

  

爱华网本文地址 » http://www.aihuau.com/a/25101012/133327.html

更多阅读

VBA编程中MsgBox函数怎么用 vba msgbox

VBA编程中MsgBox函数怎么用——简介Excel编程中的MsgBox函数用于输出一个对话框,该函数在编程调试以及输出结果方面具有极为重要的意义。下面小编就为大家讲解一下该函数的具体使用方法。VBA编程中MsgBox函数怎么用——方法/步骤

excel中round函数的使用方法 isodd函数的使用方法

excel中round函数的使用方法——简介不少朋友都会问在excel中round函数怎么用,作为使用频率较高函数之一,本文就介绍一下round函数的使用方法。excel中round函数的使用方法——工具/原料office excelexcel中round函数的使用方法——

Excel中COLUMN函数的使用 excel函数的使用方法

Excel中COLUMN函数的使用——简介COLUMN函数是一个简单的辅助函数,在一些复杂的函数计算中会使用到COLUMN函数,但是一般都不会对COLUMN函数作解析,很多朋友对公式函数中突然插入“=COLUMN()”表示理解。这里,为大家介绍COLUMN函数的使用。

Excel中Frequency函数的使用 excel frequency函数

Excel电子表格作为办公自动化中重要的一款软件,其强大的数据处理功能中很大一部分取决于函数的使用。本文就函数Frequency的使用做以简单介绍。以一列垂直数组返回某个区域中数据的频率分布。例如,使用函数FREQUENCY 可以计算公司员工

声明:《实现opengl 中gluLookAt函数 glulookat函数理解》为网友给伤痛微笑分享!如侵犯到您的合法权益请联系我们删除