你将学到:
控制三维空间:坐标变换 中有条理的显示出来,你必须根据它们的关系来安排。在这一节中你将学到在场景中移动形状和物体。实际上你并没有移动它们,只是改变了坐标系统。对任何一个三维程序员来说在三维场景中正确摆放物体是很重要的工具。正如你将看到的一样,这将会对你描述物体和平移旋转物体都是很方便的。
这是可怕的数学的一节?
是的,这是可怕的数学的一节。但是你大可放松一些,相对其它的课本而言我们将用更平实的方法来介绍这些知识。物体和坐标变换的关键就是OpenGL 提供的两个模型矩阵。为了使你熟悉这些矩阵,我在计算机图形学原理的两个极端之间做了一个折衷。一方面我要提醒你:请在学习此节之前复习一下线性代数!另一方面,我不能对这个虚伪的承诺永久负责:学习三维图形学不需要复杂的数学公式!但是我对这两种情况都不赞同。
实际上不理解好数学你也可以很好的理解三维图形学,就像你每天都开看车而你并不需要把机械和内燃机的原理都弄清楚一样。但是你最好要知道经常给车加油,并经常检查轮胎和更换坏掉的轮胎。这样做是对你自己的安全负责。若你想成为一个有责任有能力的OpenGL 程序员,也是一样的道理。你至少应知道最基本的知识,这样你就可以知道发生了什么和用什么工具适合这项工作。
因此即使你没有矩阵相乘和能力,但你应知道那个矩阵在三维空间中是什么和有什么用。当你准备掸一下旧的线性代数的书之前,也不需要害怕,在OpenGL 中都有为你做好了。想想你还不会在纸上做除法的时候,但是你可以用计算器来做的情景吧。尽管你不会自己做除法,但是你知道那是什么和怎使用。
理解变换
变换使三维坐标中的物体投影到二维的屏幕成为可能。变换也可以让你旋转物体,移动物体,甚至是拉伸,缩小,卷曲它们是通过变换坐标而不是修改物体的坐标来完成。一旦一个变换旋转了坐标系,物体被画出来的时候就旋转了。有三种变换:视点变换、模型变换、投影变换。在这一部分我将详细说明每种变换的原理。表7-1是对它们的总结:
视点坐标系
本节中的一个重要的观念就是视点坐标系(eye coordinates)。视点坐标系就以观察者的视角来看,不管发生了什么变换。把它们认为是绝对的屏幕坐标。因此视点坐标不是真正的坐标系统,只是一个虚拟的固定的坐标系统。本节中所讨论的所有变换都是关于这些变换和视点坐标系统的关系的。
图7-1所示为两个视点的视点坐标。左边的(a)为观察者的视线垂直于显示器,右边的(b)视点坐标旋转了一点,这样你就可以更好的看到Z 轴。X 轴Y 轴的正向分别指向右边和上面,从viewer 的角度;Z 轴正向指向user ,负方向远离视点指向屏幕。
图7-1
当你用OpenGL 绘制3D 物体时,你使用的是笛卡尔坐标系。先不淡变换,笛卡尔坐标系和视点坐标系是一样的。各种变换通过各种视点变换改变了当前的坐标系统。这就是你移动旋转物体的本质:相对视点坐标来说移动旋转了坐标系统。图7-2所示为一个二维的例子,它是把视点坐标顺时针旋转45度后得到的坐标系统。画在上面的方形也会跟着一起旋转了。
图7-2
这一节你将会学到在你绘制物体前对当前的坐标系统进行修改。你甚至可以保存当前的坐标状态,做一些变换和绘画,并恢复状态。把这些事情联系起来,你就可以在场景中任意摆放你的物体了。
视点变换
视点变换是你场景中最先使用的一个变换。它是用来决定场景中的点的。默认的观察点是在原点(0,0,0)向Z 轴的负向(即向显示器) 。This point of observation is moved relative to the eye coordinate system to provide a specific vantage point.当观察观察位于原点,有正值的物体将会在observer 之后。
视点变换可以让你把观察点放在任何位置上。决定视点变换就像放置和调整相机一样。在计划中视点变换必须在其它变换之前指定。这是因为那些变换都是相对视点坐标系统而言。以后的变换都是基于当前修改的坐标系而言的。以后我们将看到这是怎样工作的,现在我们只来看一看怎能样来做这些变换。
模型变换
模型变换是用于控制你的模型和里面的物体的。这种变换可以移动、旋转、缩放物体。图7-3所示为你将用到的三种模型变换。图7-3a 为平移变换,它可以沿一个给定的轴来移动物体。图7-3b 为旋转变换,它可以沿一个轴来旋转物体。图7-3c 所示为缩放的效果,它可以使用物体在给定的缩放量的情况下沿各个方向来放大或缩小物体。缩放也可以不规则,各个面的缩放量可以不同。
图7-3 模型变换
你场景中的物体最终效果很大程度上取决于你模型变换的顺序。图7-4a 所示为一个方形先绕Z 轴旋转再沿新的X 轴平移。图7-4b 所示为同一个方形先沿X 轴平移再沿Z 轴旋转。
最后不同的效果出现了,因为变换是跟先前的一个变换有关的。在图7-4A 中,方形先绕原点旋转。在7-4B 中,当方形平移后,旋转是绕新的平移后的原点进行的。
图7-4模型变换:旋转/平移变换 和 平移/旋转变换
The Modelview Duality
实际上,上述所说的视点变换和模型变换本质上是一回事,即图形学中的几何变换。只是视点变换一般只有平移和旋转,没有比例变换。当视点进行平移或旋转时,视点坐系中的物体就相当于在世界坐标系中作反方向的平移或旋转,如图7-5所示。因此从某种意义上讲,二者可以统一,只是各自的出发点不一样而已。它们之间的不同只是为了方便程序员而已。(你可以亲身经历一下:当你在十字路口坐在车中,你看到你旁边的车在向前开,看起来就像你的车在向移动一样。)[eryar:就是一个相对的概念 ]。用在这里的术语Modelview 只是为了标明你可把变换认为是模型变换或是视点变换,它们之间没有区别。
图7-5看视点变换的两种方式
视点变换本质上也就是模型变换。同样地,你也将马上看到,当你在场景中绘制的物体越来越多时,新的变换将会重复的指定。最初的变换给你以后的变换提供了一个参考。 投影变换
投影变换应用于最终的Modelview 。投影变换实际上是定义视景体并建立裁剪区域。再详细一点投影变换是指定一个完成的场景怎样变换到屏幕上。在本节中你将学到两种变换:正视投影和透视。
在正视投影(Orthographic projection) 中,所有的多边形在屏幕上显示的图形和你指定的尺寸相关。这主要应在计算机辅助设计CAD(Computer Aided Design)和建筑蓝图中,这些行业要求投影后的物体尺寸及相互间的角度不变。
在透视投影(perspective projection)中,物体或场景的显示和生活中的类似,而不同于蓝图。透视投影的标志就是foreshortening ,近大远小:对于同样尺寸的物体在远处看要比近看的尺寸要小。平行线将不再平行。例如铁轨,铁轨是平行的,但是在透视中它们将会聚于点,我们称这个点为灭点(vanishing point)。
透视投影的好处是不需要指定线在哪儿交汇,及远处的物体有多小。你所要做只是通过使用Modelview 变换指定场景,并应用透视投影。It will work all the magic for you。
图7-6为在两个不同的场景中比较正视投影和透视投影
图7-6
通常你在简单物体建模时使用正视投影,这些物体不会受位置和距离的影响。因此展览厅中的小车可用正视投影,但是当你站在车的正前方并看它的长度时,可用透视投影。透视投影用于渲染有很多物体的场景,可在场景中浏览或一个飞动的场景。总之透视投影是重要
的。
视口变换
至此为止,你将会以场景的二维投影映射到你的屏幕结束。这种映射到物理窗口坐标是最后的变换,称之为视口变换。视口已在第三节中讲解了。
矩阵Matrix Munching
现在你已经知道了一些基本术语和变换的定义,并准备好学习一点简单的矩阵数学的知识。让我们来看看OpenGL 是怎样来实现这些变换的,并学习为了达到你要的效果该调用哪些函数。
这些变换背后的数学用矩阵符号来表示是很简单的。任何一种变换都可以用矩阵相乘表示。其中一个矩阵包含顶点向量,乘以一个描述变换的矩阵。因此所有的OpenGL 中的变换都可以说成是控制两个或更多的矩阵。
矩阵是什么?What is a Matrix?
一个矩阵只不过是把一些数字按一定的形式安排在一起,用编程术语来说就是一个二维数组。一个矩阵不一定非要是一个方阵,每一行或列必须要有相同数量的数字。图7-7所示为一些矩阵的例子。这些矩阵没有特别的意思只是为了解释矩阵结构而设的例子。注意到矩阵也可以只有一列。
图7-7矩阵例子
我们这儿的目的不是深入地研究矩阵的细节和技巧。如果你想要知道更多的矩阵的知识及一些变换的代码,可以参考附录B 中的参考资料。
变换流程
为了看一看矩阵是怎样影响变换的,你要修改两个矩阵:Modelveiw Matrix 矩阵、投影矩阵Projection Matrix。不要担心,OpenGL 已经为你的变换提供了高水平的函数调用。 从顶点数据到屏幕坐标是一个漫长的过程。图7-8所示为这个过程。首先你的点被转换成一个1*4的矩阵,这个矩阵的前三个值是X 、Y 、Z 坐标,第四个值是比例因子,你可以调用顶点函数来手动设置这个值。这个坐标就是W 坐标,通常默认值是1.0。你通常很少手动去改变这个值,而是通过调用缩放函数。
图7-8
最后你的三维的坐标通过视口变换映射到二维平面。这也是通过矩阵来实现的,但是这个变换矩阵是不允许你直接修改。OpenGL 根据你在函数glViewport 中指定的值在内部设定好了。
The Modelview Matrix
Modelview 矩阵是一个4*4的矩阵,它代表你放置物体的变换坐标系统。你为图元提供的点以一个单行矩阵的形式,然后再乘以Modelview 矩阵得到跟视点坐标相关的新的变换坐标。
在图7-9中,一个包含一个点的矩阵乘以Modelview 矩阵得到新的视点坐标。点的坐标有四个值,多余的一个W 值是缩放因子。这个值默认为1,通常不改动它。
图7-9[eryar:此图表示有误。 XYZW应以行向量的形式]
平移
让我们来看一个修改Modelview 矩阵的例子。你用辅助库函数绘制一个立方体的线框模型通过调用函数auxWireCure(10.0f);然后你就得到一个位于原点的边长为10的立方体线框。为了把立方体在绘制出来之前沿Y 轴上移10个单位,你需要用一个描述平移变换——沿Y 轴平移10个单位的矩阵来乘以Modelview 矩阵,然后再画。大概的框架为:
//Construct a translation matrix for positive 10 Y构造一个沿Y 轴正方向平移的变换矩阵 ……
//Multiply it by the Modelview matrix 用Modelview 矩阵乘以变换矩阵
……
//Draw the cube 绘制立方体
auxWireCube(10.0f);
实际上,这样一个矩阵构造起来还是很简单的,但也需要一些代码。幸运地是有高水平的函数供你调用:void glTranslatef(GLfloat x,GLfloat y,GLfloat z);
这个函数的参数表示它沿X 、Y 、Z 轴的平移量。然后再构造一个矩阵再和Modelview 矩阵做乘法。效果如图7-10所示:
//Translate up the Y-axis 10 units沿Y 轴平移10个单位
glTranslatef(0.0f,10.0f,0.0f);
//Draw the cube
auxWireCube(10.0f);
图7-10沿Y 轴平移10个单位的立方体
旋转
把物体沿三个坐标轴旋转,你可以调用函数:
glRotatef(GLfloat angle, GLfloat x,GLfloat y,GLfloat z);
这里我们做了一个绕点X 、Y 、Z 的旋转变换。旋转角是逆时针的,度量为度,通过参数angle 指定。最简单的情况就是物体只沿一个轴旋转,因此只需要指定那个轴的值。
你也可指定XYZ 三个参数来使之绕任意轴旋转。为了确定旋转轴,你可以边接原点和你指定的点得到的线就是旋转轴所在直线。以下代码为绕指定轴旋转45度的一个立方体。 //Perform the transformation 旋转变换
glRotatef(90.0f,1.0f,1.0f,1.0f);
//Draw the cube绘制立方体
auxWireCube(10.0f);
图7-11 绕任意轴旋转的立方体
缩放
一个缩放变换可以在沿三个坐标轴的方向对物体进行缩放。函数:
glScalef(GLfloat x,GLfloat y,GLfloat z);
这个函数把通过参数指定的X ,Y ,Z 值作为缩放因子去乘以原来点的坐标。
缩放不一定要统一。如下面的代码就是对立方体进行缩放,使之沿X 轴和Z 轴都变大为原来的两倍,而Y 轴方向仍和原来一样。
//Perform the scaling transformation缩放变换
glScalef(2.0f,1.0f,2.0f);
//Draw the cube绘制立方体
auxWireCube(10.0f);
图7-12 立方体不统一的缩放变换
The Identity Matrix单位矩阵
你现在可能知道为什么我们一开始就提出矩阵的意思了吧。难道我们就是调用这些变换的函数来移动物体吗?我们真的需要知道Modelview 矩阵是怎样修改的吗?如果你只在场景中绘制一个物体的话,答案既是又不是。这是因为这些函数的效果是渐增的。每次你调用一个函数,一个矩阵就要被构造并乘以当前的Modelview 矩阵。得到的新的矩阵作为当
前的Modelview 矩阵。如此循环,,,
假设你要画两个球体,一个在Y 轴正方向10个单位长度上,一个在X 轴正方向10个单位长度上,如图7-13所示。你可能会用下面的代码:
//Go 10 units up the Y-axis 到Y 轴正向10个单位处
glTrnaslatef(0.0f,10.0f,0.0f);
//Draw the first sphere画第一个球体
auxSolidSphere(1.0f);
//Go 10 units out the x-axis到X 轴正向10个单位处
glTranslatef(10.0f,0.0f,0.0f);
//Draw the second sphere画第二个球体
auxSolidSphere(1.0f);
图7-13 画在X 轴Y 轴上的两个球体
可是每次调用函数它们的效果是累积的。因此第二次调用沿X 轴平移的函数时,得到的结果如图7-14所示:
图7-14两个连续变换的结果
你可以通过再调用平移函数glTranslatef 使它沿Y 轴负向移动10个单位来解决此问题。
但这会给一个复杂场景的编码和调试带来不便。一个简单的处理方式就是重新设置Modelview 矩阵使它处在我们视点坐标系统中的原点。
这就是通过调用单位矩阵来实现的。单位矩阵指定没有发生变换,即你指定的所有的坐标都是在视点坐标中进行的。一个单位矩阵是指除了对角线上的为1以外其它的值都为0。当这个矩阵被一个点的矩阵乘时,这个点的坐标没有改变。如图7-15所示:
图7-15点矩阵与单位矩阵相乘得到仍是点的矩阵 [eryar:此图矩阵乘法表示有误! 更正如下:
]
正如我前面说到的,本书不包括矩阵处理的细节。现在你只需要记住:载入单位矩阵就是没有对点做任何变换。实质上是重新设置Modelview 使它回到原来的原点。[eryar:实际上矩阵乘法也是很简单的。摘自同济四版《线性代数》P34定义:设A=(a ij )是一个m*s的矩阵,B=(bij ) 是一个s*n的矩阵,那么规定矩阵A 与矩阵B 乘积是一个m*n矩阵C=(cij ) ,其中:c ij = ai1b 1j + ai2b 2j + …+ ais b sj ( i= 1,2,,….m;j= 1,2,….n;) 并把此乘积记作:C=AB。 乘积矩阵AB=C的(i,j)元就是A 的第i 行与B 的第j 列的乘积。注意:只有当第一个矩阵(左矩阵) 的列数等于第二个矩阵(右矩阵) 的行数时,两个矩阵才能相乘。]
下面的两行代码为载入一个单位矩阵到Modelview 中:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
第一行指定当前操作矩阵为Modelview 矩阵。一旦你设定了当前矩阵,它就一直处于激活状态直到你改变它时为止。第二行把当前操作矩阵设置为单位矩阵。现在以下代码可以产生图7-13中的图形:
//Set current matrix to Modelview and reset glMatrixMode(GL_MODELVIEW); glLoadIdentity();
//Go 10 units up the y-axis glTranslatef(0.0f,10.0f,0.0f); //Draw the first sphere auxSolidSphere(1.0f); //Reset Modelview matrix glLoadIdentity();
//Go 10 units out the x-axis
glTranslatef(10.0f,0.0f,0.0f); //Draw the second sphere auxSolidSphere(1.0f);
矩阵堆栈
并不是在放置每个物体之前都用单位矩阵来重设Modelview 矩阵。有时你也想保存当前的变换状态并在以后需要时重新调用。
为了实现它OpenGL 为Modelview 和Projection 投影矩阵提供了一个矩阵堆栈。一个矩阵堆栈顾名思义就像一个普通的程序中的栈Stack 。你可以把当前矩阵压入栈保存起来,然后再改变你的当前矩阵。出栈就恢复场景。如图7-16所示栈的原理:
图7-16 矩阵栈操作
栈的最大深度可以通过调用函数:glGet(GL_MAX_MODELVIEW_STACK_DEPTH);或者glGet(GL_MAX_PROJECTION_STACK_DEPTH);
如果你超过了栈的深度,就会得到一个GL_STACK_OVERFLOW;如果当栈空时你执行了出栈操作,就会得到一个GL_STACK_UNDERFLOW。
一个原子的例子
让我们应用我们学到的知识。在下个例子中,我们会建立一个粗糙的原子的动画。这个原子有一个球体作为原子核,然后是三个在轨道上的电子组成。这里我们用了正视投影,和我们原来用的一样。(一些更好玩的投影将在下面介绍。)
我们的原子的程序使用了一个时钟,它使电子一秒钟移动四次。每次函数RenderScene 被调用。绕原子核旋转的角度就增加了。同样地每个电子在不同的平面上。清单7-1所示为函数Render 。程序的输出如图7-17所示:
图7-17 程序A TOM 的输出
清单7-1 程序A TOM 中的渲染程序 void RenderScene(void)
{ static float fElect1 = 0.0f;
//Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST);
//Yellow Electrons glColor3f(1.0f,1.0f,0.0f);
//First Electron orbit
//Reset the modelview matrix
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
//Translatef the whole scene out and into view //This is the initial viewing transformation glTranslatef(0.0f,0.0f,-100.0f); glColor3f(1.0f,0.0f,0.0f); auxSolidSphere(30.0f);
//Red Nucleus
//Save viewing transformation glPushMatrix();
//Rotate by the angle of revolution glRotatef(fElect1,0.0f,1.0f,0.0f);
//Translate out from origin to orbit distance glTranslatef(90.0f,0.0f,0.0f); //Draw the electron auxSolidSphere(10.0f);
//Restore the viewing transformation glPopMatrix(); //Second Electron orbit glPushMatrix();
glRotatef(45.0f,0.0f,0.0f,1.0f); glRotatef(fElect1,0.0f,1.0f,0.0f); glTranslatef(-70.0f,0.0f,0.0f); auxSolidSphere(10.0f); glPopMatrix(); //Third Electron Orbit
glPushMatrix();
glRotatef(120.0f,-45.0f,0.0f,1.0f); glRotatef(fElect1,0.0f,1.0f,0.0f); glTranslatef(0.0f,0.0f,90.0f); auxSolidSphere(10.0f); glPopMatrix();
//Increment the angle of revolution fElect1 += 10.0f; if(fElect1>360.0f)
fElect1 = 0.0f;
glFlush( ); }
让我们来检查一下放置一个电子的代码,一次两行。第一行保存当前的Moelview 矩阵,是通过把当前变换压入栈来实现的。 //First Electron Orbit //Save viewing transformation
glPushMatrix();
现在坐标系统就绕着Y 轴以角度fElect1旋转; //Rotate by angle of revolution
现在电子在新的坐标系中被平移;
//Translate out from origin to orbit distance
glTranslatef(90.0f,0.0f,0.0f);
然后电子被画出,我们又通过出栈来恢复Modelview 矩阵。 //Draw the electron auxSoliShpere(6.0f);
//Restore the viewing transformation glPopMatrix();
另外的电子也是一样的道理。
使用投影
投影矩阵实际上就是指定视景体的尺寸。到目前为止我们只创建过一个简单的平行视景体。那就是调用glOrtho 来设定参数:near,far, left, right, top and bottom。当投影矩阵被载入单位矩阵时,就被指定裁剪平面从各个方向上的原点到1。 正视投影
正视投影是到现在为止本书中使用最多的投影,它的视景体的每个边都是方形。它的六个面的逻辑宽度相等。这种平行投影使你不管物体有多远投影都是一样。这主要用于CAD 和建筑蓝图中,因为在它们中需要精确的尺寸。
图7-18正视投影中的空洞的立方体
图7-19侧面看到的立方体的长度
图7-20正视立方体
在图7-20中,你正视筒状的立方体。因为立方体不会在远处会聚,所以这不像我们生活中看到立方体。为了得到我们生活中看到的效果,就要使用透视投影。
透视投影
透视投影使离观察者远的物体变短和缩小。视景体背面和前面的宽度不是一致的。因此一个具有相同逻辑尺寸的物体,如果它被画在视景体的前面上,看上去要比它被画在视景体的背面时要大。
如图所示的几何形状称为截体Frustum 。截体是一个金子塔窄部到宽部的一部分。如图7-21所示:
图7-21 Frustum 定义的透视
你可以调用函数glFrustum 得到一个Frustum 。它的参数是前裁剪平面和后裁剪平面的坐标和距离。但是glFrustum 设置透视投影时并不是很直观的得到你想要的效果。而实用函数gluPerspective 更容易和直观:
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); 函数的参数是:一个在垂直方向的视域角度,一个高宽比;近裁剪平面和远裁剪平面。如图7-22所示。比例参数aspect 是由是通过裁剪前平面的width 除以height 得到。
图7-22 gluPerspective定义的截体
清单7-2所示为怎样使我们的正视投影变到透视投影的例子。按远近比例缩小的特点加入到我们的正视投影中,使它看起来更生动。
图7-23 方体的透视投影
图7-24 有比例缩小的侧面视野
图7-25 添加了透视效果的正视方体
清单7-2 设置透视投影
void ChangeSize(GLsizei width,GLsizei height) { GLfloat fAspect;
if(height == 0)
height = 1;
glViewport(0,0,width,height);
fAspect = (GLfloat)width/(GLfloat)height;
glMatrixMode(GL_PROJECTION); glLoadIdentity( );
gluPerspective(60.0f,fAspect,1.0f,400.0f); }
A Far-Out Example
在我们的模型中,地球绕太阳转,月亮绕地球转。
清单7-3所示为设置我们投影的代码,渲染的代码保持动画。如图7-26和7-27所示:
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
当地球离太阳近时,显得要大一点;当离远的时候显得要小一些。
清单7-3:图
7-26
图7-27
void ChangeSize(GLsizei width,GLsizei height)
{
GLfloat fAspect;
if(height == 0)
height = 1;
glViewport(0,0,width,height);
fAspect = (GLfloat)width/(GLfloat)height; glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
gluPerspective(45.0f,fAspect,1.0f,500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void RenderScene(void)
{
static float fMoonRot = 0.0f;
static float fEarthRot = 0.0f;
//Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//Reset the modelview matrix glMatrixMode(GL_MODELVIEW); glPushMatrix(); //Translate the whole scene out and and into view glTranslatef(0.0f,0.0f,-300.0f); glColor3f(1.0f,0.0f,0.0f); auxSolidSphere(15.0f); //Rotate coordinate system glRotatef(fEarthRot,0.0f,1.0f,0.0f); glTranslatef(105.0f,0.0f,0.0f); glColor3f(0.0f,0.0f,1.0f); auxSolidSphere(15.0f); //Draw the earth //Rotate from Earth-based coordinate and draw moon glRotatef(fMoonRot,0.0f,1.0f,0.0f); glTranslatef(30.0f,0.0f,0.0f); fMoonRot += 15.0f; //Set material color,RED //Sun
if(fMoonRot > 360.0f) fMoonRot = 0.0f; glColor3f(1.0f,1.0f,0.0f); auxSolidSphere(6.0f); //Restore the matrix state glPopMatrix(); //Step earth orbit 5 degrees fEarthRot += 5.0f; if(fEarthRot > 360.0f) fEarthRot = 0.0f; //Flush drawing commands
glFlush( );
}
高级矩阵操作
你并不是必须使用高级的函数调用来处理你的变换。我推荐你调用函数,毕竟这些函数是经过最优化处理的,而低级的函数是为通用性而设计的。两个高级的函数使你载入矩阵和作矩阵乘法成为可能。
载入一个矩阵
你可以载入任意一个矩阵到投影、Modelview 、材质矩阵栈中。首先声明一个有16个值的数组4*4。使设计的矩阵成为当前矩阵,并调用函数glLoadMatrix 。
矩阵存储的形式是column-major 顺序,简单的说就是每一列都是从小到大排列。图7-28所示为矩阵元素存储形式。以下代码所示为一个数组被载入单位矩阵,然后再载入到Modelview 矩阵栈中。这和调用高级函数glLoadIdentity 是相同的。
//Equivalent, but more flexible
glFloat m[] = {1.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f, 0.0f,0.0f,0.0f,1.0f
};
glMatrixMode(GL_MODELVIEW);
glLoadMatrix(m);
图7-28 Column-major matrix ordering
使用自己的变换
只要你想你可载入任何一个矩阵,并做乘法。以下代码所示为一个矩阵变换:沿X 轴平移10个单位。然后这个矩阵再和Modelview 相乘。你也可通过调用函数glTranslatef 来达到同样的效果。
//Define the Translation matrix
glFloat m[] = {1.0f,0.0f,0.0f,10.0f,
0.0f,1.0f,0.0f,0.0f, 0.0f,0.0f,1.0f,0.0f, 0.0f,0.0f,0.0f,1.0f };
//Multiply the translation matrix by the current modelview
//matrix. The new matrix becomes the modelview matrix.
glMatrixMode(GL_MODELVIEW);
glMultMatrix(m);
其它的变换
通过指定矩阵和重复调用函数glLoadIdentity 和glTranslatef 没有什么区别。允许你调用任意矩阵的真正目的是为了更复杂的矩阵变换。一种应用就是绘制阴影,你会在第九节中看到。更多高级应用的信息请参考附录B 。
总结:
在这一节中,你学会了用OpenGL 创建三维场景的重要概念。即使你对矩阵还不是很了解,现在你知道了什么是矩阵及它们怎样来做各种变换。你也学到了怎样控制Modelview 和投影矩阵栈来放置物体及它们怎样在屏幕上显示。
最后我们也讲了处理自己矩阵时要用到的函数。
索引:略
三维空间中直角坐标与球坐标的相互转换
三维直角坐标系
三维直角坐标系是一种利用直角坐标(x,y,z)来表示一个点?P?在三维空间的位置的三维正交坐标系。
注:本文所讨论的三维直角坐标系,默认其x-轴、y-轴、z-轴满足右手定则(如右图所示)。
在三维空间的任何一点?P?,可以用直角坐标(x,y,z)来表达其位置。如左下图显示了三维直角坐标的几何意义:点P在x-轴、y-轴、z-轴上的投影距离分别为x、y、z。如右下图所示,两个点?P?与?Q?的直角坐标分别为(3,0,5)与(-5,-5,7)?。
球坐标系
球坐标系是一种利用球坐标(r,?,?)来表示一个点?P?在三维空间的位置的三维正交坐标系。
下图描述了球坐标的几何意义:原点O与目标点P之间的径向距离为r,O到P的连线与正z-轴之间的夹角为天顶角? ,O到P的连线在xy-平面上的投影线与正x-轴之间的夹角为方位角? 。
假设?P?点在三维空间的位置的三个坐标是
。那么,?0???r?是从原点到?P?点的距离,?0????????是从原点到?P?点的连线与正?z-轴的夹角,?0
时,
与
都一起失去意义。当
或
时,
失去意义。
三维空间下直角坐标与球坐标的相互转换
直接坐标转球坐标
、
、
。
球坐标转直角坐标
、
、
。
基于Flex的坐标转换实现
直角坐标定义类CartesianCoord.cs
package?hans_gis.coord
{
public?class?CartesianCoord
{
public?var?x:Number;
public?var?y:Number;
public?var?z:Number;
static?private?var?temp:CartesianCoord?=?CartesianCoord.ZERO;
public?function?CartesianCoord(x:Number=0,?y:Number=0,?z:Number=0)
{
this.x?=?x;
this.y?=?y;
this.z?=?z;
}
public?function?clone():CartesianCoord
{
return?new?CartesianCoord(this.x,?this.y,?this.z);
}
public?function?copyTo(n:CartesianCoord):void
{
n.x?=?this.x;
n.y?=?this.y;
n.z?=?this.z;
}
public?function?copyFrom(n:CartesianCoord):void
{
this.x?=?n.x;
this.y?=?n.y;
this.z?=?n.z;
}
public?function?reset(newx:Number?=?0,?newy:Number?=?0,?newz:Number?=?0):void
{
this.x?=?newx;
this.y?=?newy;
this.z?=?newz;
}
static?public?function?get?ZERO():CartesianCoord
{
return?new?CartesianCoord(0,?0,?0);
}
}
}
球坐标定义类SphericalCoord.cs
package?hans_gis.coord
{
public?class?SphericalCoord
{
public?var?radius:Number;
public?var?theta:Number;
public?var?phi:Number;
static?private?var?temp:SphericalCoord?=?SphericalCoord.ZERO;
public?function?SphericalCoord(radius:Number=0,?theta:Number=0,?phi:Number=0)
{
this.radius?=?radius;
this.theta?=?theta;
this.phi?=?phi;
}
public?function?clone():SphericalCoord
{
return?new?SphericalCoord(this.radius,?this.theta,?this.phi);
}
public?function?copyTo(n:SphericalCoord):void
{
n.radius?=?this.radius;
n.theta?=?this.theta;
n.phi?=?this.phi;
}
public?function?copyFrom(n:SphericalCoord):void
{
this.radius?=?n.radius;
this.theta?=?n.theta;
this.phi?=?n.phi;
}
public?function?reset(newradius:Number?=?0,?newtheta:Number?=?0,?newphi:Number?=?0):void
{
this.radius?=?newradius;
this.theta?=?newtheta;
this.phi?=?newphi;
}
static?public?function?get?ZERO():SphericalCoord
{
return?new?SphericalCoord(0,?0,?0);
}
}
}
坐标转换定义类CoordsTransform.cs
package?hans_gis.coord
{
public?class?CoordsTransform
{
public?function?CoordsTransform()
{
}
public?function?CartesianToSpherical(coord:CartesianCoord):SphericalCoord{
var?radius?=?this.GetModuloFromCartesianCoord(coord);
var?theta?=?this.GetThetaFromCartesianCoord(coord);
var?phi?=?this.GetPhiFromCartesianCoord(coord);
return?new?SphericalCoord(radius,?theta,?phi);
}
protected?function?GetModuloFromCartesianCoord(coord:CartesianCoord):Number
{
return?Math.sqrt(?coord.x*coord.x?+?coord.y*coord.y?+?coord.z*coord.z?);
}
protected?function?GetThetaFromCartesianCoord(coord:CartesianCoord):Number{
//?return?Math.atan(Math.sqrt(coord.x*coord.x?+?coord.y*coord.y)/coord.z);
return?Math.acos(coord.z/this.GetModuloFromCartesianCoord(coord));
}
protected?function?GetPhiFromCartesianCoord(coord:CartesianCoord):Number{
return?Math.atan(coord.y/coord.x);
}
public?function?SphericalToCartesian(coord:SphericalCoord):CartesianCoord{
var?x?=?this.GetXFromSphericalCoord(coord);
var?y?=?this.GetYFromSphericalCoord(coord);
var?z?=?this.GetZFromSphericalCoord(coord);
return?new?CartesianCoord(x,?y,?z);
}
protected?function?GetXFromSphericalCoord(coord:SphericalCoord):Number{
return?coord.radius*Math.sin(coord.theta)*Math.cos(coord.phi);
}
protected?function?GetYFromSphericalCoord(coord:SphericalCoord):Number{
return?coord.radius*Math.sin(coord.theta)*Math.sin(coord.phi);
}
protected?function?GetZFromSphericalCoord(coord:SphericalCoord):Number{
return?coord.radius*Math.cos(coord.theta);
}
}
}
实例运行结果
附:实例下载
线性变换在二维空间和三维空间中的应用
线性变换在二维空间和三维空间中的应用 1、二维图形的几何变换
二维齐次坐标变换的矩阵的形式是:
这个矩阵每一个元素都是有特殊含义的。
其中
?
?
?
?
?
?
e
d
b
a
可以对图形进行缩放、旋转、对称、错切等变换;
?
?
?
?
?
?
f
c
是对图形进行平移变换; [g h]是对图形作
投影变换; [i]则是对图形整体进行缩放变换。
1.1 平移变换
1.2缩放变换
1.3旋转变换
在直角坐标平面中,将二维图形绕原点旋转
θ角的变换形式如下:
逆时针旋转
θ取正值,顺时针旋转 θ取负值。
1.4对称变换
对称变换其实只是 a 、 b 、 d 、 e 取 0、 1等特殊值产生的一些特殊效果。例如:
当 b=d=0, a=-1, e=1时有 x′=-x, y′=y,产生与 y 轴对称的图形。
A. 当 b=d=0, a=-1, e=-1时有 x′=x, y′=-y,产生与 x 轴对称的图形。
B. 当 b=d=0, a=e=-1时有 x′=-x, y′=-y,产生与原点对称的图形。
C. 当 b=d=1, a=e=0时有 x′=y, y′=x,产生与直线 y=x对称的图形。
D. 当 b=d=-1, a=e=0时有 x′=-y, y′=-x,产生与直线 y=-x对称的图形。
1.5错切变换
A. 当 d=0时, x′=x+by, y′=y,此时,图形的 y 坐标不变, x 坐标随初值 (x , y )及变换系数 b 作线性 变化。
B. 当 b=0时, x′=x, y′=dx+y,此时,图形的 x 坐标不变, y 坐标随初值 (x , y )及变换系数 d 作线性 变化。
1.6复合变换
如果图形要做一次以上的几何变换,那么可以将各个变换矩阵综合起来进行一步到位的变换。复合变换有如 下的性质:
A. 复合平移
对同一图形做两次平移相当于将两次的平移两加起来:
B. 复合缩放
两次连续的缩放相当于将缩放操作相乘:
C. 复合旋转
两次连续的旋转相当于将两次的旋转角度相加:
缩
放、 旋转变换都与参考点有关, 上面进行的各种变换都是以原点为参考点的。 如果相对某个一般的参考点 (xf , yf )作缩放、旋转变换,相当于将该点移到坐标原点处,然后进行缩放、旋转变换,最后将(xf , yf )点移 回原来的位置。切记复合变换时,先作用的变换矩阵在右端,后作用的变换矩阵在左端。 D. 关于(xf , yf )点的缩放变换
E. 绕(xf , yf )点的旋转变换
1.7、二维线性变换的应用实例
在多变量函数积分学中 , 合理进行变量代换 , 能起到化繁为简的作用 , 常用的变量代换 , 有球坐标 , 极 坐标代换 , 或类似此类的代换。而事实上,线性代数为我们看问题提供了一个非常好的视角。线性变换 用于多重积分,曲面,曲线积分中,往往更为灵活,并不是如球坐标等代换较易看出。
例:求
,
2
2
2dxdy e cz bxy ax
??∞
∞-∞
∞
-++其中
0, 02
<->ac b a 分析:这与 dx
e x ?
∞
∞
-2
似乎有关系,如何转化?
因为
()c
b b
a y x
c b b a y x
cy bxy ax ,
) (222???
? ???=++定正。
故
P
?正 交 , 使
, ' ' ???? ??=?
??
? ??y x P y x 即
A
?正 交 , 使 得
, 00211????
?
?=???? ??-λλA c b b a A 且
1det , 21222122=+=++-P y x cy bxy ax λλ, 原式 =
2
11
λ2
2121) ' () ' (2
' 22
'
1b ac y d e x d e
y x -==
???
∞
∞
-∞
∞
-πλλπλλλ
从以上的讨论看出:必须注意观察已知条件,才能合理进行线性变换,当积分区域,被积表达式具有某种 线性的特征时(也即可表为变量的线性组合)往往可以考虑线性变换,而定正矩阵的应用可视为一种技巧。
2、三维图形的几何变换
由于用齐次坐标表示,三维几何变换的矩阵是一个 4阶方阵,其形式如下:
其中 ??????????3332
31
232221
1312
11
a a a a a a a a a 产生缩放、旋转、错切等变换; ????
?
?????342414a a a 产生平移变换, []4342
41
a a a 产生投影变换, []44a 产生整体缩放变换。
2.1平移变换
参照二维的平移变换,我们很容易得到三维平移变换矩阵:
2.2缩放变换
直接考虑相对于参考点(xf , yf , zf )的缩放变换,其步骤为:
A. 将平移到坐标原点处;
B. 进行缩放变换;
C. 将参考点(xf , yf , zf )移回原来位置
则变换矩阵为:
2.3绕坐标轴的旋转变换
三维空间的旋转相对要复杂些,考虑右手坐标系下相对坐标原点绕坐标轴旋转 q 角的变换: A. 绕 x 轴旋转
B. 绕 y 轴旋转
C. 绕 z 轴旋转
三维空间的平移、旋转及缩放示意图
2.4绕任意轴的旋转变换
设旋转轴 AB 由任意一点 A (xa , ya , za )及其方向数 (a, b , c) 定义,空间一点 ) , , (p p p z y x P 绕 AB 轴
旋转角 到
) ' , ' , ' (' p p p z y x p 则
可以通过下列步骤来实现 P 点的旋转:
A. 将 A 点移到坐标原点。
B. 使 AB 分别绕 X 轴、 Y 轴旋转适当角度与 Z 轴重合。 C .将 AB 轴绕 Z 轴旋转 θ角。
D. 作上述变换的逆操作,使 AB 回到原来位置。 所以
)
, , () () () () () () , , () (1
1
1a a a x y z y x a a a ab z y x T R R R R a R z y x T R αβθβθ---=
其中各个矩阵的形式参照上面所讲的平移,选择矩阵,而 β
α, 分别是 AB 在 YOZ 平面与 XOZ 平面的投影与 Z
轴
3. 三维图形变换理论
3.1. 三维图形的几何变换
几何变换是指应用于对象几何描述并改变它的位置、方向或大小的操作.三维图形的几何变换也称三维几何变换, 是几何变换在三维空间的应用.由于几何变换可以用紧凑的矩阵形式表达,这不仅使得平移、缩放、旋转等变换变得更 加容易, 还使得一系列的几何变换可以很容易地结合起来构成 1个新的变换. 三维几何变换均可以用 1个 4×4的变 换矩 阵
T 描述,其变换矩阵为
式中:a , b , C , P , d , e , f , q , g , h , i , ,£, m , , 8为矩阵 T 的元素 式 (1)可从功能上分为以下部分:
(1)3×3子阵 ,,可以产生比例、旋转、错切及对称等变换.
(2)1×3行阵 [l, m , n]可以产生沿 X , Y , Z 轴的平移变换.
(3)3×1列阵 可以产生透视变换
(4)元素 8产生整体的比例变换
3.2 组合三维几何变换
4.2.1.1初等三维变换
式 (1)是 1个十分有用的变换矩阵,它可以描述三维空问的各种变换,但直接使用却十分困难.不如先分析平移、
缩放、旋转等初等三维变换矩阵.对初等三维变换矩阵进行组合,就得到了组合三维变换矩阵,从而实现一般性的三维 几何变换.下面是几个重要的初等三维变换矩阵:
式中:P 为平移矩阵,矩阵中 l , m , n 分别为沿 x , y , z 轴的平移量;矩阵 分别为绕
x , y , z 轴的旋转,其旋转角度为
,这里规定角度逆时针为正; c=COS a; s=sin a.
4.1.2.2 组合三维几何变换
三维几何变换可以任意组合,并且表示总变换的矩阵可以是每个初等三维矩阵乘积的形式.任意数目的几何变换都 能以这种方式组合在一起并产生 1个表示总变换的矩阵 T ,它由 n 个独立变换矩阵 T , T1,T2… Tn 相乘得到 ,
T=T1*T2… Tn (3)
基于球傅里叶变换的声源三维空间定位
汤永清黄青华方勇
( 200072),,上海大学通信与信息工程学院上海
: 。( SMA) 摘 要声源的空间方位信息是重建听觉环境重要的因素之一本文研究了球形麦克风阵列 在声源空间定位
。,。,- 的方法针对球麦克风的设计提出了一种等距离分布方法本文从声学原理出发利用球傅里叶变换将声场变换到波矢
) () ,,。 频率 k ω域推导出基于球傅里叶变换的声源定位算法从而获取其声源方位信息得到各声源的分布情况
,。,,,声压经虚拟仪器采集后进行了数值仿真结果表明该算法利用球谐波的正交性可以减少运算量能获得
,。多声源的准确定位并且阵列所需的麦克风数量远远小于其他分布
: ; ; ; 关键词球傅里叶变换球麦克风阵列球谐波声源定位
: TN911.7 : A: 1003 ) 0530(2010)05) 0654 ) 05中图分类号文献标识码文章编号
Localization of Sound Sources Based on Spherical Fourier
Transformation in Three-Dimension
TANG Yong-qing HUANG Qing-hua FANG Yong
(School Communication , Information Engineering,Shanghai University,Shanghai,200072)
The localizations information of sources is the important factorin reconstructing audio environment. ’Abstract: Localization of sources is researchedu sing spherical microphone array (SMA). For designing of SMA,a n ovel criterion on equidistance distribution isprovided and applied to sounsod urces’localization. According to sound’s physical characteristic,Sound pressureis expressed
as linear combination of different ordersspherical harmony,anids transformedin the domain from space-time to wave number-’
frequency by spherical Fourier transformation (SFT). The localization of sources is obtained using the algorithm deduced. The soundspressure on spherical microphone array was recordebdy NI instruments and simulated. The experiments demonstrated that ’
the array with equidis- tance work ewll for searching location of sound sourwcithe small computation making using of spherical harmony’s orthogonality,and the number moifc rophone is less than other isdtributions.
Key words: spherical Fourier transformation;spherical microphone array; spherical harmony;so undslocalization ’
,,时阵列的几何尺寸并不是很重要强调的是多个麦克 1 引言。,风组成的系统而在信号参数估计中麦克风阵列的 ,, 几何形状扮演着十分重要的作用例如在声源定位中,音频信号处理中麦克风是最基本的信号接收设
,阵列几何形状必须是事先已知的而且某些规则几何 。备之一将麦克风组成阵列形式的主要目的通过多个 ,3,,,形状的应用可以有效地减少运算量简化估计问题如 ,:、麦克风的信息可以解决很多实际问题回声噪声
,。均匀线阵圆形阵以及球形阵等 ;;;;的抑制视频会议虚拟现实技术场景分析波束形成
,由于考虑的是声源空间定位本文采用球麦克风 。:等应用背景大致可分为信号的参数估计或者感兴
。,阵列因为球具有良好的对称性及旋转特性以及球 。,趣的信号波形分离根据应用目的的不同对阵列要
,谐波的正交性球所构成麦克风阵列的研究近年来受 。求的侧重点也不同如在进行信号增强或者信号提取
2009 2009 : 6 19 ; : 10 26 收稿日期年 月 日修回日期年 月 日
,1, 2001 Meyer Elko。0,。,到越来越多的关注最初于 年由 和 的由于是刚性球在球表面处粒子的速度为 故球上2,, 。。Abhayapala Ward某点的声场可以由该点处的声压唯一决定提出基于球谐波的波束阵列和 研,6,:入射声场为 。Rafealy究了相似阵列的声学性能提出了利用球麦
n 。?克风阵列进行平面波分解的理论 n m p () = 4ij (a)D(Y () (4))!% k! ! n ??i0 n(3D),在三维音频以及虚拟听觉空间中需要建立 n = 0 m = ) n* m。,与声源方位相关的听觉环境因此在这种应用背景 = YD()() ,(4) 式中 是方位因子表示入射角 ! !0 n0 ,下声源的方位信息以及距离信息是信号两个重要的 (a) n Bessel,a ,j相关的函数为刚性球半径k为 阶球 n 。参数这些信息包含在用麦克风阵列所录制的声场 ,Y ,() = (,) 函数表示球谐波函数θ&表示平面波 !,4,0 0 0 。,中目的是从声场中通过信号处理手段提取这些 。入射角的球坐标形式 。,信息本文从声学原理出发利用球傅里叶变换将声 ,。球表面是由硬的介质所组成存在着声波的反射-() ),场变换到波矢频率k ω域推导出基于球麦克风阵 :由于反射所形成的声场为 ,, 列的声源检测与定位算法从而获取其声源方位信息 ′n? j( ) ka ,其中涉及到麦克风在球面上的分布问题文中给出等 n n p() =)4 i!% ??s ′,, 距离分布准则相比等角度分布该分布所需麦克风数 h() n = 0 m = ) nka (2)n (2)m。量大大减少 h()D()Y()(5)ka !!n0 n 2()′() ankel (),(5) hH。j式中 ka为 二 类 球 函 数ka n n (2)′ h() Bessel Hankel ka分别为球 函数和球二类 函数的 n
。一阶导数 2 球傅里叶变换及声场分析 ,因此总的声场可以描述入射声场与反射声场之 ,:,一般来说声压是四维函数三维空间坐标一维 :和 ,,时间坐标将声场用球傅里叶系数展开这样可以充分
p() + p()= p() !!! ,。 s i利用球傅里叶系数的正交性达到简化运算的目的 n?在这一节中首先引入球傅里叶变换的定义以及将球傅 m =b(,)D()Y()(6)krka!!? ? n 0 n 。里叶变换用于声场分析 n = 0 m = ) n′ ,4,j() ,,ka根据文献对于能量有限的实值函数其球傅里 nn (6) ,b(,) = 4i (j() ) h())式中krka% krkrn n ′ n :叶变换对可以表示为 h()ka n
。,称为特征幅值因为所测量的点是在球表面上进行的 n ?r = a,b。即 就可以简化成球半径的函数 n * m f() =fY()(1)!! nm n ??(6) ,n ,注意式的第一个和式是趋向于无穷大实 n = 0 m = ) n m(2) f= ,(6) ,Nf()Y()d际中是不可能实现的需要对式进行截短当取 !!!n nm
= (,) ,θ&表示球坐标 阶时,此时球表面声压 p() 可以表示为: ! N j f),(式中 为球傅里叶系数 !nm Nn 1 。如图 所示 m p() =b()D()Y()(7)kr!!!N j ? ? n 0 n j n = 0 m = ) n S* m p=p()Y()(8)w!!nm j N j n j ? j = 1
S N ,式中 指所采样的阶数为球面上采样麦克风的个
,j 。,数w为第 个麦克风的补偿加权值至此将声场表示 j
。成截短球谐波函数的线性组合
3 等距离球节点分布准则 图 1 球坐标示意图
球上麦克风的配置方式影响麦克风的数量以及对 :在球坐标系中傅里叶系数又可以表示为。,声场采样的性能最容易想到的布局就是等角度布局 % 2% m ,6, f= sin f()Yθ!(3)nm n 。,即俯仰角与方位角等角度间隔文献 指出对球上麦0 0 ()d!&。克风的布置可以有不同的方案从所能采样阶数与相 ,当平面波入射到硬边界面时即球由刚性物质所,5,,组成球表面所形成的声场可以表示为入射波声场 ,N,应的麦克风数量之间的关系上看对于采样阶数为 2 。,与反射波声场的叠加由声场欧拉方程可知一个声场 4(N + 1),等角度分布所需的麦克风总数 高斯分布 2 是由所形成的声压以及声场中相应的粒子速度所决定 2(N + 1),所需的麦克风总数 而等距离方案只需用
2 + 1)。:4 (N , 麦克风数为 比如对于 阶采集使用等角
100 ,度分布至少需要麦克风数量为 个用高斯分布至少
50 ,25 。需要 个而采用等距离分布的下限为 个但是该
。文献并没有给出如何在球上寻找满足条件的节点构
:造等距离分布的代价函数
N N 1 E(x,x,…x) (9)1 2 N ) i = 1 j = i +1 i j 2x = ??(9) 式中 表示欧式空间范数 ‖‖ 2 x‖ ‖ ,x= (rcos sin ,rsin sin ,rcos 利用球坐标展开& θ& θi i i i i i ii 3 (25 )图 球麦克风阵列点),,r= 1,(13),: θ并令为单位球取 代入上式可得i i N N 1 3 ,根据表 的分析结果制作成图 所示的球麦克风 E(,) =d(,,,)(10)& θ& θ& θi i ??i i j j ,。阵列并将其用于声源的检测与定位实验 i = 1 j = +1i
其中
d(,,,)& θ& θ i j i j = 4 声源方位检测及定位 2,(cossin )c ossin )& θ& θ i i j j :利用球麦克风阵列进行声源定位首先将声场描 ( )1 / 2)2 2+(sinsin )s insin ) + (cos )c os ) ,& θ& θθθ i i j j i j ,述成各阶球谐波的线性组合对声场进行球傅里叶变 ,至此对球坐标求解就转化为有约束非线性方程优化。,换根据球谐波的正交特性求得关于声源幅度密度的 。问题 ,,球傅里叶变换式再进行球傅里叶反变换可以得到各 N N ,个声源幅度密度的空间分布情况接着在空间坐标中 mn(d(,,,))i& θ& θ??i i j j i = 1 j = i +1,, 搜索声源找出幅度最大值并定位出声源的空间位置0 2 & %(1 i N) i 。下面就具体推导出所用公式 :满足(11)(1 i N)0 θ % i ,当空间只存在着一个声源时该声源所形成声压
2 :的球傅里叶变换为 ,(N + 1),根据空间采样定理球上布置的点数必须
,N即点数必须大于等于所抽取的谐波数的总和其中
*。,3, 为抽取的介数考虑实际实验条件取阶数为 为了增 m*p(,) = p()Y()dkr!!!! n j j0mn 0 j 2 ,(N25,= + 2)加冗余 度将 麦 克 风 总 点 数 取 为 在* m* Y= b()kr () (12) ! n n 0matlab ,1 , (中可以求得在球上的角度分布如表 所示θ& ,当空间存在若干个这样的声源时所形成的声场,,)。分别表示俯仰角以及方位角θ& 一一对应 (12) 的球傅里叶变换就是上面式在声源空间上的积 :25 示例个麦克风等距分布 ,a(,0),:分假设声源幅度密度为 kr可得 !1 4 25 (:)表 等距离球节点分布 阶 点单位角度 * m* ()Y (a(,db ()a ))= kr kr kr!!! n 00 0 nnm 0471004177507283129θ bn 002451102792401449683& (13)
821651151038012411291148θ ,又根据和的积分等于积分的和对若干个声源所 & 326192921712062912755262,(13) 形成的声压直接做球傅里叶变换结果就与是一 //50150126874144125θ ,(14) :致的因此联立方程可得式 9301181338//125153209& * p(,) = D()b()krkr !!lmn 0 0 n
* m* * = p()Y()d= a()b()krkr!!! j n j j nm n
(14)
(14) ,由上式经由球傅里叶反变换因为是有限个
,(15) :点的测量将 转化为可得式 ?
NnS 1 A(,) =kr!N ? ? ? b ()kr n = 1 m = ) nj = 1 n 2 (25 )图 球等距分布图点
* mm ,p()Y()Y()(15)场变得更为复杂在某些条件下需要结合声源先验知w !!!N j j n j n
。N A(,) 识才能给出正确的判断。下标 指所抽取的阶数经反变换得到的 kr就 !N
,是声源在整个空间中幅度密度的分布情况有声源的
。,位置幅值必然大于其余位置根据这个原理可寻找其
,。最大值所对应的坐标即为声源的方位
5 实验结果分析
) 4472 NI PXI 3 用 对图 所示球麦克风阵列表面声
,,压进行数据采集麦克风阵列由电容式麦克风组成软
labview ,8 , 件端得和谈 采样并存储一次使用 个通道
,9600H,100 分四次完成采样率设为 z每 个数据作为一 5 (,) 图 单声源幅度等高线图为真实入射角?为估计入射角。WF1965,个文件存储单频信号由函数信号发生器 经 (250,120),(252,121)真实值估计值 。由放大器产生输出
,4 。声源频率的选择与球半径的关系如图 所示实
(),心三角形?表示在所选球半径情况下所能达到的最
f。5. 3cm,大频率 本实验中所采用的球半径为 并结合 max
,,3kH。采样率声源的频率取为上限频率的一半即 z
6 (,), 图 双声源幅度等高线图为真实入射角?为估计入射角
1(135,45),1(139,45); 真实值 估计值
2(250,120),2(250,119)真实值 估计值
6 总结
,3D 、在需要声源空间方位信息的应用中如 音频 = /4,4 , 图 固定 θ % 频率与 & 之间的关系、、立体电视的音频系统空间声场合成与绘制高阶声场 (5949H) ?为对应于半径的最大频率z实验中分别,。录制等球麦克风有着良好的前景根据声音的传播
采用单声源以及双声源两种情况进行 ,,特性利用球麦克风进行声源定位充分利用了球的特
,,殊性与对称性以及球谐波函数的正交性可以有效地 定位。单声源情况,真实值的方位信息为(250,120),
,简化算法为空间声源方位信息的获取提供了一种新 (15)5 利用式所得到的幅度密度等高线示意图如图 所
。的思路同时对于声源定位的研究还有一些问题待解 ,,(252,121),示寻找到的最大值即估计值为图中三角
:,决比如相干声源的相互干扰可能会对声源的定位产 。(135,形表示的位置双声源定位分别取两个入射角
;,生不确定的因素由于球麦克风是离散布置的在空间 45)(250,120),6 。5 6 和如图 所示从图 及图 中可以
,分辨率内的不同声源定位也存在着一定的模糊性再 ,看出用等距离分布的球麦克风阵列可以根据所采集 ,,者就是声源个数的确定问题在上述实验过程中都不 ,到的声压值较好地进行声源定位实验结果可以和文 ,自觉地运用了一些关于声源先验的知识如假设声源 ,9,,9,,献等角度分布的结果进行比较文献不仅运算量 。。个数是已知等这些都是需要进一步研究的课题 ,。大而且在定位时会出现定位模糊的现象本文中所
,,使用的麦克风的数量明显变少易于实际应用特别当
,。 所使用的麦克风比较昂贵时该方案更具实际意义
,,参考文献在实验过程中发现当声源的数目变多时所形成的声
,1, J. Meyer,and GE. lk o,A highly scalable spherical mi-
crophone array based oornth oanno rmal decomposition ofTrans. on Speech anAudd io Processing,Vol. 15,No.2 ,the sound efd,CSSP 02,vo. 2,pp. ilIAl’’ pp.70 2-713,February 200.71781-1784, Z. Lin,B. Xu,Three-dimensional localization of multiple 9,,May 2002. acoustic sources using spherical microphone array ,J ,. ,2,T. D. Abhayapala,and D. B. W ard,Theory and design Journa of Nanng Unversty ( Natura Scences),o. ljiiiliVlof high order soundie lfd microphones using spherical mi- 42,No. 4,pp. 384-39J3u. y,2006. lcrophone rraay,ICASSP 02,vol. 2,pp. ’’
1949-1952. 10 , R. Boaz,The s pherical-shell microphone array ,J ,.,,3,
IEEE Trans. onA udio and Language Processing,Vol. J. Benesty,J. Chen,anY. d H uang,Microphone array
16,No. 4,pp. 740-743,May 200. 8signal processing. Berlin,Germany: Springer,2008. ,4,
E. G Wams,Fourer acoustc: Soundr adaton and illiiiii
near-field acoustical holography ,M,. London,England: 作者简介,,,Academic Press,1999. 杜功焕朱哲民龚秀芬声学基 ,5,. :. 2001().础南京南京大学出 版社第二版 (1973-),,,汤永清 男博士生主要研
:,。究方向阵列信号处理音频信号处理 R. Boaz,Analysis and design of spherical microphone ar-
,6,ray. I EEE Trans. on Speech anAudd io Processing,Vol.
13,No. 1,pp. 135-143,January 200. 5
N. Dmitry,D. Ramani,and A. Nail,Sound field de-
composition using spherical microphone arrays, Proc. ,7 , IEEE ICASSP 2008,pp. 277-28. 0 (1978-),,,,:黄青华女讲师博士主要研究方向盲信号Z. Li,and D. Ramani,Flexible and optimal design of ,。处理语音信号处理 spherical m icrophone arrays for eabm form ing. IEEE (1964-),,,,:方 勇男教授博导主要研究方向盲信号 ,8 ,、。处理通信信号处理和智能信息系统
file:///D|/我的资料/Desktop/新建文本文
档.txt
Appliance Error (configuration_error)
Your request could not be processed because of a configuration error: "Could not connect to LDAP server."
For assistance, contact your network support team.
file:///D|/我的资料/Desktop/新建文本文档.txt2012-07-12 20:42:52
三维空间坐标下的速度、加速度推导
图二极坐标下的加速a 度计算
θ,?)如图所示,以0点为原点建立以空间直角坐标系O-xyz ,空间人一点的球坐标为(r ,,
雷达坐标(r, 。在该点处坐标系三个单位矢量为e r 、e θ、e ?,也可以表示为e r 、e α、α, β)
e β。r 为该点到原点的距离。θ为该点相对0点位置矢量Z 轴的夹角,目标俯仰α为该点与原点连线和地平面的夹角(即与xOy 平面的夹角,通常范围-90°到90°)。?为该点相对0点位置矢量在0-xy 坐标平面上的投影与X 轴之间的夹角,目标方位β为该点相对0点位置矢量在0-xy 坐标平面上的投影与y 轴正向夹角,即指北向顺时针夹角(从y 轴正向向x 轴正向的夹角,范围为0~360°),
e r =sin θcos ?i +sin θsin ?j +cos θk (1)
e θ=cos θsin ?i +cos θsin ?j -sin θk (2)
e ?=sin ?i +cos ?j (3)
e r =θcos θcos ?i +cos ?j -sin θk +?sin θ(-sin ?i +cos ?j )sin ?i +cos ?j ()
e r =θe θ+?+sin θe ? (4)
e θ=-θsin θcos ?i +sin θsin ?j -cos θk +?cos θ(-sin ?i +cos ?j ) ()
e θ=-θe r +?cos θe ? (5) e ?=-?(cos ?i +sin ?j ) (6) k =cos θe r +sin θe ? (7) cos ?i +sin ?j =sin θe r +cos θe θ(8) e ?=-?(sin θe r +cos ?e θ) (9) r =re r (10) v =r =re r +re r v =re r +r θe θ+r ?sin θe ? (11) v =v r e r +v θe θ+v ?e ? (12)
??v r =r
?v θ=r θ (13) ??v ?=r ?sin θ
a =v =a r e r +a θe θ+a ?e ? (14) ?a 2r =r -r θ2-r ?sin 2?θ?a 2θ=r θ+2r θ-r ?sin θcos θ ??a ?=r ?sin θ+2r ?sin θ+2r θ?cos θ
??e r =e r
?e α=e θ (16) ??e β=e ?
15) (
转载请注明出处范文大全网 » 第七节控制三维空间:坐标变换
->