用相机相关函数实现场景空间变换

MATLAB提供了一些与相机有关的函数,利用这些函数也可以实现场景的空间变换,并且与使用相机工具条相比,使用函数更灵活,可以实现更多的功能。[大谦MATLAB,dqmatlab点com]

低级相机属性

相机工具工作时是基于一组控制相机位置和方向的坐标轴属性的。通常,使用相机相关命令使得可以不必直接获取这些属性。这些属性如表5-1中所示。

表5-1 相机的低级属性

属 性 功 能
CameraPosition 指定视点的位置
CameraPositionMode 如果是automatic模式,MATLAB基于场景自动确定视点的位置;如果是manual模式,则自己指定视点位置
CameraTarget 指定坐标系中相机指向的位置。与CameraPosition属性一起使用,可以定义视图坐标
CameraTargetMode 如果是automatic模式,MATLAB将CameraTarget属性的值指定为坐标系中图形包围盒的中心;如是manual模式,则自己指定位置
CameraUpVector 相机绕视图坐标的旋转用表示抬升方向的矢量定义
CameraUpVectorMode 如果是automatic模式,对于二维视图,MATLAB沿y轴正向确定抬升矢量中的方向,对于三维视图,则沿z轴正向确定。如果是manual模式,直接指定方向
CameraViewAngle 指定“镜头”的视域。如果给CameraViewAngle属性指定一个值,MATLAB会使自动拉伸图形并使之充满图形窗口这一默认操作失效
CameraViewAngleMode 如果是automatic模式,MATLAB将视角调整到可以捕获整个场景的最小角度。如果是manual模式,需要自己指定角度。将此属性设置为manual会使自动拉伸图形并使之充满图形窗口这一默认操作失效
Projection 选择正交投影或透视投影

相机相关函数

表5-2列出了可以进行相机操作的一系列函数。关于各函数的语法和用法,可以参见MATLAB帮助文档,这里不详细介绍。后面举了两个用函数进行场景变换的例子,中间用到了表中的部分函数。

表5-2 相机相关函数

函 数 功 能
camdolly 移动相机位置和目标点
camlookat 查看指定的目标
camorbit 绕目标点盘旋相机
campan 绕相机位置旋转相机目标点
campos 设置或获取相机位置
camproj 设置或获取投影类型
camroll 绕视轴旋转相机
camtarget 设置或获取相机目标点的位置
camup 设置或获取相机仰角的值
camva 设置或获取相机方位角的值
camzoom 用相机进行场景缩放操作

camdolly函数

利用该函数移动相机位置和目标,调用格式为:

camdolly(dx,dy,dz) 按指定大小移动相机位置和相机目标点。

camdolly(dx,dy,dz,'targetmode') targetmode参数可以取两个值来确定MATLAB移动相机的方式:

movetarget(默认)—相机和目标点都移动。

fixtarget—只移动相机。

camdolly(dx,dy,dz,'targetmode','coordsys') coordsys参数可以取下面3个值来确定MATLAB如何解释dx,dy和dz:

camera(默认)—在相机坐标系中移动,dx表示左右移动的距离,dy表示上下移动的距离,dz表示沿视轴移动的距离。单位相对于场景进行标称化。例如,将dx设置为1时将相机移到右侧,该操作将场景推向坐标系位置矩形组成的方框的左边缘。值为负时将场景推向相反的方向。将dz设置为0.5时将相机移动到相机位置与相机目标点中间的位置。

pixels—将dx和dy解释为像素偏移,忽略dz。

data—将dx,dy和dz解释为坐标系数据坐标中的偏移。

camdolly(axes_handle,…) 操作第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camdolly操作当前坐标系。

camdolly函数设置坐标系的CameraPosition属性和CameraTarget属性,它们又使得CameraPositionMode和CameraTargetMode属性设置为manual。

下面的例子首先生成peaks数据的曲面图,然后沿x轴和y轴连续移动相机,产生动画效果。

code.matlab
>> surf(peaks)
>> axis vis3d
>> t=0:pi/20:2*pi;
>> dx=sin(t)./40;
>> dy=cos(t)./40;
>> for i=1:length(t);
      camdolly(dx(i),dy(i),0)
    drawnow
end

生成平移动画,如图5-19所示。

Document Image
\[\]

图5-19 平移动画

下面的代码是只移动相机的情况。

code.matlab
>> surf(peaks)
>> axis vis3d
>> t=0:pi/20:4*pi;
>> dx=sin(t)./40;
>> dy=cos(t)./40;
>> for i=1:length(t)
     camdolly(dx(i),dy(i),0,'fixtarget')
     drawnow
end

camlight函数

该函数在相机坐标系中创建或移动light对象。调用格式为:

camlight('headlight') 在相机位置创建一个light对象。

camlight('right') 创建一个light对象,它位于相机的右上部。不带参数的camlight函数运行效果与本语法的相同。

camlight('left') 创建一个light对象,它位于相机的左上部。

camlight(az,el) 创建一个light对象,其位置由指定的相对于相机位置的方位角(az)和仰角(el)确定。相机目标点位于旋转中心,az和el的单位为度。

camlight(…,'style') 样式参数style可以取下面两个值:

local(默认)—light对象是一个点光源,它从该位置向所有方向发光。

infinite—light对象发射平行光。

camlight(light_handle,…) 使用light_handle指定的light对象。

light_handle=camlight(…) 返回light对象的句柄。

camlight函数设置light对象的Position和Style属性。camlight函数创建的light对象不会跟踪相机。为了使light对象相对于相机的位置固定,必须在移动相机的任何时候调用camlight函数。

下面的例子在曲面右上方添加一个光源。

code.matlab
>> surf(peaks)
>> axis vis3d
>> camlight('right')

生成图5-20。

Document Image
\[\]

图5-20 添加光源

camlookat函数

该函数设置相机位置,察看一个对象或一组对象。调用格式为:

camlookat(object_handles) 察看矢量object_handles确定的对象。

camlookat(axes_handle) 察看句柄为axes_handle的坐标系的子对象。

不带参数的camlookat函数察看当前坐标系中的对象。

注意:camlookat函数在保持相对视线方向和相机视角的情况下移动相机位置和相机目标点。察看的对象大致充满坐标系位置矩形。该函数会设置坐标系的CameraPosition和CameraTarget属性。

本例首先创建两个曲面。

code.matlab
>> [x,y,z]=peaks(30);
>> s1=surf(x,y,z);
>> hold on
>> s2=surf(x+5,y,z+8);
>> daspect([1 1 1])
>> view(30,10)

生成图5-21。

用camlookat函数查看s1曲面:

code.matlab
>> camlookat(s1)

生成图5-22。

Document Image Document Image
\[\]

图5-21 创建两个曲面 图5-22 查看s1曲面

camorbit函数

该函数绕相机目标点旋转相机,调用格式为:

camorbit(dtheta,dphi) 按照dtheta和dphi(单位都为度)指定的大小绕相机目标点旋转相机。dtheta表示水平旋转,dphi表示垂直旋转。

camorbit(dtheta,dphi,'coordsys') coordsys参数确定旋转中心,它可以取两个值:

data(默认)—绕相机目标点和方向定义的轴旋转相机(默认时为正z方向)。

camera—绕相机目标点定义的点旋转相机。

camorbit(dtheta,dphi,'coordsys','direction') direction参数与相机目标点组合,定义数据坐标系统的旋转轴。将direction指定为3元素矢量,该矢量包含方向的x,y和z组分,或者分别表示[1 0 0],[0 1 0]或[0 0 1]的字符x,y或z中的一个。

camorbit(axes_handle,…) 操作第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camorbit操作当前坐标系。

下面的例子用for循环比较两个坐标系中的旋转。第1个循环绕相机目标点和平行于y轴的方向所定义的线水平旋转相机。该旋转可用圆锥表示,圆锥的顶点为相机目标点,相机移动所经过的位置组成基底。

code.matlab
>> surf(peaks)
>> axis vis3d
>> for i=1:36
      camorbit(10,0,'data',[0 1 0])
      drawnow
  end

下面在相机坐标系中,绕坐标轴沿圆形盘旋相机,保持圆心位于相机目标点处。

code.matlab
>> surf(peaks)
>> axis vis3d
>> for i=1:36
      camorbit(10,0,'camera')
      drawnow
  end

campan函数

该函数绕相机位置旋转相机目标点。调用函数为:

campan(dtheta,dphi) 按照dtheta和dphi(单位都为度)指定的大小,绕相机位置旋转相机目标点。dtheta为水平旋转大小,dphi为垂直旋转大小。

campan(dtheta,dphi,'coordsys') coordsys参数确定旋转中心,可取下面两个值:

data(默认)—绕相机位置和方向定义的轴线旋转相机目标点(默认时为z轴正向)。

camera—绕相机目标点定义的点旋转相机。

campan(dtheta,phi,'coordsys','direction') direction参数和相机位置一起,定义数据坐标系的旋转轴。将direction指定为3元素矢量,该矢量包含方向的x,y和z组分,或者分别表示[1 0 0],[0 1 0]或[0 0 1]的字符x,y或z中的一个。

campan(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,campan函数操作当前坐标系。

下面的例子绕相机位置旋转相机目标点。

code.matlab
>> surf(peaks);
>> axis vis3d
>> hPan=sin(-pi:1:pi);
>> vPan=cos(-pi:1:pi);
>> for k=1:length(hPan)
     campan(hPan(k),vPan(k))
     pause(1)
  end

campos函数

该函数设置或查询相机位置,调用格式为:

campos 没有输入参数时返回相机在当前坐标系中的位置。

campos([camera_position]) 将相机在当前坐标系中的位置设置为指定值。将位置指定为3元素矢量,该矢量包含所要求的位置的x,y和z坐标,单位为坐标系中数据的单位。

campos('mode') 返回相机位置模式的值,可以是auto(默认)或manual。

campos('auto') 将相机位置模式设置为auto。

campos('manual') 将相机位置模式设置为manual。

campos(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,campos函数操作当前坐标系。

注意:campos函数设置或查询坐标系CameraPosition和CameraPositionMode属性的值。

下面的例子沿x轴连续移动相机。

code.matlab
>> surf(peaks)
>> axis vis3d off
>> for x=-200:5:200
  campos([x,5,10])
  drawnow
end

生成图5-23。

Document Image
\[\]

图5-23 沿x轴连续移动相机

camproj函数

该函数设置或查询投影类型,调用格式为:

camproj 没有输入参数,返回当前坐标系设置的投影类型。

camproj('projection_type') 将当前坐标系的投影类型设置为指定值,值可以为orthographic和perspective。

camproj(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camproj函数操作当前坐标系。

注意:camproj函数设置或查询坐标系对象的Projection属性的值。

下面分别用透视投影和正交投影绘制曲面图。

code.matlab
>> subplot(1,2,1)
>> surf(peaks(20))
>> camproj('perspective')
>> subplot(1,2,2)
>> surf(peaks(20))
>> camproj('orthographic')

生成图5-24。

Document Image
\[\]

图5-24 使用透视投影和正交投影

camroll函数

该函数绕视轴旋转相机,调用格式为:

camroll(dtheta) 按照dtheta指定的大小绕相机视轴旋转相机。视轴由穿过相机位置和相机目标点的直线定义。

camroll(axes_handle,dtheta) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camroll函数操作当前坐标系。

注意:camroll函数设置坐标系的CameraUpVector属性,还设置CameraUpVectorMode属性的值为manual。

下面绕视轴旋转相机。

code.matlab
>> surf(peaks)
>> axis vis3d
>> for i=1:36
	camroll(10)
	drawnow
end

camtarget函数

该函数设置或查询相机目标点的位置,调用格式为:

camtarget 没有参数时返回相机在当前坐标系中的位置。

camtarget([camera_target]) 将相机在当前坐标系中的目标点设置为指定值。将目标点指定为一个包含x,y和z坐标的3元素矢量,单位为坐标系的数据单位。

camtarget('mode') 返回相机目标模式的值,可以是auto(默认)或manual。

camtarget('auto') 将相机目标模式设置为auto。

camtarget('manual') 将相机目标模式设置为manual。

camtarget(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camtarget函数操作当前坐标系。

注意:camtarget函数设置或查询坐标系对象的CameraTarget和CameraTargetMode属性的值。相机目标模式为auto时,MATLAB将相机目标点放在坐标系绘图框的中心。

下面的例子沿x轴连续移动相机位置和相机目标点。

code.matlab
>> surf(peaks);
>> axis vis3d
>> xp=linspace(-150,40,50);
>> xt=linspace(25,50,50);
>> for i=1:50
     campos([xp(i),25,5]);
     camtarget([xt(i),30,0])
     drawnow
end

camup函数

该函数设置或查询相机抬升矢量,调用格式为:

camup 没有输入参数时返回当前坐标系中设置的相机抬升矢量。

camup([up_vector]) 将当前坐标系中的抬升矢量设置为指定值。用x,y和z分量指定抬升矢量。

camup('mode') 返回相机抬升矢量模式的当前值,可以是auto(默认)或manual。

camup('auto') 将相机的抬升矢量模式设置为auto。在auto模式下,对于2维视图,MATLAB使用抬升矢量[0 1 0],这表示z轴指向抬升方向。

camup('manual') 设置相机抬升矢量模式为manual。在manual模式下,MATLAB不改变相机抬升矢量的值。

camup(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camup函数操作当前坐标系。

注意:camup函数设置或查询坐标系对象的CameraUpVector和CameraUpVectorMode属性的值。

下面设置相机抬升矢量。

code.matlab
>> surf(peaks)
>> camup([1 0 0]);

生成图5-25。

Document Image
\[\]

图5-25 设置相机抬升矢量

camva函数

相机的视角确定相机的视域。角度越大,场景看起来越小。可以通过改变相机的视角来实现图形缩小和放大。用camva函数设置或查询相机的视角,调用格式为:

camva 没有输入参数时,返回当前坐标系设置的相机视角。

camva(view_angle) 将当前坐标系的视角设置为指定值,视角的单位为度。

camva('mode') 返回相机视角模式的当前值,可以是auto(默认)或manual。

camva('auto') 将相机视角模式设置为auto。

camva('manual') 将相机视角模式设置为manual。

camva(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camva函数操作当前坐标系。

注意:camva函数设置或查询坐标系对象的CameraViewAngle和CameraViewAngleMode属性的值。相机视角模式为auto时,MATLAB调整相机视角,使场景充满整个窗口。如果将相机移动到不同位置,MATLAB会改变相机视角来使得场景充满窗口。

设置相机视角或将相机视角模式为manual,会取消MATLAB的拉伸填充功能。这意味着将相机视角设置为它的当前值,即

code.matlab
camva(camva)

会导致图形外观的改变。

下面连续改变相机的视域。

code.matlab
>> surf(peaks)
>> axis vis3d
>> for i=1:25
	camva(10*i)
	pause(.5)
end

camzoom函数

使用该函数放大和缩小场景,调用格式为:

camzoom(zoom_factor) 根据zoom_factor指定的值放大或缩小场景。如果zoom_factor大于1,则场景显得更大;如果zoom_factor大于0但小于1,则场景显得更小。

camzoom(axes_handle,…) 操作由第1个参数axes_handle确定的坐标系。不指定坐标系句柄时,camzoom函数操作当前坐标系。

注意:camzoom函数设置坐标系的CameraViewAngle属性,它又使CameraViewAngleMode属性设置为manual。设置CameraViewAngle属性会取消MATLAB的拉伸填充功能。这会改变图形的纵横比。

下面连续放大场景。

code.matlab
>> surf(peaks)
>> axis vis3d
>> for i=1:25
	camzoom(1.1)
	pause(.3)
end

view函数

视点位置确定坐标系的朝向。用方位角和仰角,或者三维空间中的某个点指定视点。该函数指定视点,调用格式为:

view(az,el)和view([ax,el]) 设置三维图的视角。方位角az为从y轴负轴开始绕z轴水平旋转的角度。正值表示视点的逆时针旋转。el为垂向上视点的仰角,单位为度。仰角为正,表示向上移动;为负,表示向下移动。

view([x,y,z]) 设置视点坐标为x,y,z。

view(2) 设置默认的2维视图,az=0,el=90。

view(3) 设置默认的3维视图,az=-37.5,el=30。

view(T) 根据变换矩阵T设置视图,T是一个4×4的矩阵,可以看作viewmtx函数生成的投影变换。

[az,el]=view 返回当前的方位角和仰角。

T=view 返回当前的4×4变换矩阵。

注意:方位角是x-y平面上的极角,为正时表示视点逆时针方向旋转。仰角为正时位于x-y平面上方,为负时位于下方。图5-26显示了方位角、仰角、坐标系统和视点等之间的关系,图中箭头方向表示正向。

Document Image

方位角图形包围盒的中心仰角视点方位角图形包围盒的中心仰角视点Inline Image

图5-26 方位角和仰角

下面的代码确定从正上方直接察看对象。

code.matlab
>> az=0;
>> el=90;
>> view(az, el);

沿y轴设置视图。

code.matlab
>> view([0 0]);

绕z轴旋转180度。

code.matlab
>> az=180;
>> el=90;
>> view(az, el);

viewmtx函数

用该函数察看变换矩阵,调用格式为:

T=viewmtx(az,el) 返回一个对应于方位角az和仰角el的正交变换矩阵。az为视点的方位角,单位为度;el为视点的仰角,单位为度。返回的矩阵与下面命令得到的相同:

code.matlab
>> view(az,el)
>> T=view

但不改变当前视图。

T=viewmtx(az,el,phi) 返回投影变换矩阵。phi为投影视角,单位为度。phi不同时,有不同的投影效果,如表5-3所示。

表5-3 不同phi值的投影效果

phi值 描 述
0度 正交投影
10度 近似于telephoto镜头
25度 近似于一般镜头
60度 近似于广角镜

使用view(T),用返回的矩阵设置视图变换。4×4的透视变换矩阵将4维均一矢量转换为形如(x,y,z,w)的非标称化矢量,其中w不等于1。标称化矢量(x/w,y/w,z/w,1)的x和y组分是必要的二维组分。

T=viewmtx(az,el,phi,xc) 将xc作为目标点,返回投影变换矩阵。用3元素矢量在[0 1]区间内指定该点,即xc=[xc,yc,zc]。默认值为xc=[0,0,0]。在对应的3维矢量后面添加1可以组成4维均一矢量。例如,[x,y,z,1]是对应于3维点[x,y,z]的4维矢量。

makehgtform函数

用makeghtform函数创建图形对象的平移、缩放和旋转变换矩阵。通过将父hgtransform对象的Matrix属性指定为该变换矩阵,对图形对象进行变换。调用格式为:

M=makeghtform 返回一个单位变换矩阵。

M=makeghtform( 'translate',[tx ty tz])或M=makeghtform( 'translate',tx,ty,tz) 返回沿x轴平移tx,沿y轴平移ty,沿z轴平移tz的变换矩阵。

M=makeghtform( 'scale',s) 返回沿x,y和z轴均匀比例变换的矩阵。

M=makeghtform( 'scale',[sx,sy,sz]) 返回x,y和z轴方向上的比例分别为sx,sy和sz的比例变换矩阵。

M=makehgtform( 'xrotate',t) 返回绕x轴旋转t个弧度的变换矩阵。

M=makeghtform( 'yrotate',t) 返回绕y轴旋转t个弧度的变换矩阵。

M=makeghtform( 'zrotate',t) 返回绕z轴旋转t个弧度的变换矩阵。