PluginSDK中的相机类CameraBase是三维计算机图形学中的概念。观察者在三维场景中漫游时,通过眼睛看到的场景和相机拍摄过程非常一致。实际上,Direct3D和OpenGL都是先通过对现实世界中的场景先进行世界变换,再通过设置观察矩阵以在场景中安置一个虚拟相机,构建一个视景体来裁剪场景的可见区域,然后在通过投影变换(平行投影或透视投影),获取三维场景的“像”,最后再通过视口变换,将场景的“像”光栅化输出到二维显示屏幕上。如下图所示。
在三维地形系统中,通常定义一个虚拟相机来实现对三维场景的漫游等功能。可以通过操纵虚拟相机来实现在虚拟场景中切换和漫游。这种方式实质上是通过不断改变虚拟相机的相关参数(如位置和朝向等),然后通过这些参数重新构造世界矩阵、观察矩阵或投影矩阵来完成场景漫游的。
相机类的类图如下。由CameraBase派生出WorldCamera类,再派生出MomentumCamera类。
其中,基类CameraBase主要成员有:地形高程、(所观察的)星球半径(单位为米)、相机所在经度角度_longitude、纬度角度_latitude、相机的朝向角度_heading、_tilt倾斜角度、_bank横滚角度、_distance眼睛到目标的距离、_altitude相机到海平面的高度、四元数m_Orientation、视景体对象_viewFrustum、从星球设置参数获取的相机视场角,相机的_position向量。
同时设置相机的最小倾斜角度为0度,最大倾斜角度为85度。最小高度为10度,最大高度为无穷大。
m_ProjectionMatrix投影变换矩阵、m_ViewMatrix观察变换矩阵、m_WorldMatrix世界变换矩阵。viewRange可视范围角度,trueViewRange真实的可视范围角度,viewPort视口窗口结构体。lastStepZoomTickCount最后一步缩放计数器(与Environment.TickCount结合),cameraUpVector相机的向上向量,初始化默认为Point3d(0,0,1)。ReferenceCenter相机的参考中心,初始化默认为Point3d(0,0,0),lastResetTime最后的重置时间,DoubleTapDelay双Tap延迟。
m_absoluteViewMatrix、m_absoluteWorldMatrix、m_absoluteProjectionMatrix三个绝对矩阵不清楚与上面的三个相应矩阵有什么区别?还为它们定义了只读的属性AbsoluteViewMatrix、AbsoluteWorldMatrix、AbsoluteProjectionMatrix。
属性Altitude和TargetAltitude分别表示高出海平面的高度和经过移动后目标高出海平面的高度。
属性AltitudeAboveTerrain表示高出地表物体高程的高度。属性TerrainElevation用于设置或获取地表物体高程的高度。
属性Distance和TargetDistance分别表示到目标位置的距离和经过移动后到目标位置的距离。
ComputeDistance( double altitude, Angle tilt )用给定的相机高度和相机倾斜角计算距离。
方法ComputeAltitude( double distance, Angle tilt )的计算示意图如下所示。
方法ComputeTilt(_altitude, _distance) 的计算示意图如上所示。
ComputeAbsoluteMatrices()方法里面的矩阵我知道意义,但不太理解其运算的含义。为啥要那样运算?
虚方法Update(Device device)用相机新的世界矩阵、观察矩阵、投影矩阵更新当前场景,同时也更新了视景体的参数、可视范围角度,真实的可视范围角度和World.Settings中关于相机的参数。
虚方法Reset() 用于重置相机的参数。调用了虚方法SetPosition()。
虚方法PointGoto(double lat, double lon)设置相机位置。调用了虚方法SetPosition()。
虚方法SetPosition(double lat, double lon, double heading, double _altitude, double tilt, double bank)真正的被设计用来设置设置相机位置,有三种重载形式。
虚方法virtual void PickingRayIntersection(int screenX, int screenY,out Angle latitude,out Angle longitude)用给定的屏幕像素坐标计算对应位置的经度角度和纬度角度。用构造的向量Vector3 v1 = newVector3(screenX, screenY, Viewport. MinZ)和Vector3 v2 = newVector3(screenX, screenY, Viewport. MinZ)调用了Vector3. Unproject(object viewport, Matrix projection, Matrix view, Matrix world)方法拟向将一个向量从屏幕空间投影到目标空间。然后再用一元二次方程的判别式(Why?)决定经度角度和纬度角度的取值情况。如果判别式>0,则再通过方法MathEngine.CartesianToSphericalD()计算出点对象Point3d p1 = new Point3d(v1.X, v1.Y, v1.Z)和Point3d p2 = new Point3d(v2.X, v2.Y, v2.Z)所对应的球面坐标,最后调用Angle.FromRadians返回以度表示的经度角度和纬度角度。
虚方法ComputeProjectionMatrix(Viewport viewport)计算投影矩阵,用于将三维相机或观察空间坐标转换为二维的屏幕空间坐标。
虚方法RotationYawPitchRoll(Angle yaw, Angle pitch, Angle roll)使相机按照给定的航偏角yaw、倾斜角pitch和横滚角roll旋转,实际上是给相机的经度角度_longitude、纬度角度_latitude、相机的朝向角度_heading重新赋值。如下图所示。
虚方法ZoomStepped通过键盘或鼠标缩放场景。
虚方法Zoom(float percent)在目标距离方向上按指定的百分比缩放。
虚方法Pan(Angle lat, Angle lon)按指定的经、纬度偏移漫游场景。
方法Vector3 Project( Vector3 point ) 用于将世界空间中的三维点转换为二维的屏幕坐标。
静态方法static Angle[] getViewBoundingBox()以度为单位计算可见的外包围盒。