⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cs

📁 功能:基于windows mobile 的地图查看器。使用vs2005开发
💻 CS
字号:
using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.WindowsMobile.DirectX;
using Microsoft.WindowsMobile.DirectX.Direct3D;

using WorldWindow;

namespace cfWorldWind
{
	public class Camera
	{
		private float latitude;
		private float longitude;

		private float distance = 0;
		private float altitude = 0;
		private float maxAltitude = 7 * Settings.Radius;

		private float yaw = 0;
		private float pitch = 0;
		private float roll = 0; //rotation of earth

		protected Matrix projectionMatrix;
		protected Matrix viewMatrix;
		protected Matrix worldMatrix = Matrix.Identity;

		private float viewRange = 0;
		private Viewport viewPort;

		public Camera()
		{
			ResetView();
		}

		public void ResetView()
		{
			latitude = 0f;
			longitude = 0f;
			distance = 3 * Settings.Radius; //to origin
			altitude = distance - Settings.Radius; //above earth
			yaw = 0f;
			pitch = 0f;
			roll = 0f;
			viewRange = 0f;
		}

		public Matrix Projection
		{
			get {return projectionMatrix;}
		}

		public Matrix View
		{
			get { return viewMatrix; }
		}

		public Matrix World
		{
			get { return worldMatrix; }
		}

		public float ViewRange
		{
			get{return viewRange;}
		}

		public float Altitude
		{
			get{return altitude;}
		}

		public float Distance
		{
			get
			{
				return distance;
			}
			set
			{
				if (value > Settings.Radius + 100 && value < maxAltitude)
				{
					distance = value;
					altitude = value - Settings.Radius;
				}
			}
		}

		public float Yaw
		{
			get
			{
				return yaw;
			}
			set
			{
				if(value > 6.28)
					value = 0f;
				if(value < 0)
					value = 6.28f;
				//yaw = value;
				if ((value >= 0f && value < .8f) || (value > 5.47f && value <= 6.28f))
					yaw = value;
			}
		}

		public float Pitch
		{
			get
			{
				return pitch;
			}
			set
			{
				if (value > 6.28)
					value = 0f;
				if (value < 0)
					value = 6.28f;
				//pitch = value;
				if ((value >= 0f && value < .8f) || (value > 5.47f && value <= 6.28f))
					pitch = value;
			}
		}

		public float Roll
		{
			get
			{
				return roll;
			}
			set
			{
				if (value > 6.28)
					value = 0f;
				if (value < 0)
					value = 6.28f;
				roll = value;
			}
		}

		public float Latitude
		{
			get
			{
				return latitude;
			}
			set
			{
				if (value < 90 && value > -90)
				{
					latitude = value;
				}
			}
		}

		public float Longitude
		{
			get
			{
				return longitude;
			}
			set
			{
				if (value > 180)
					value = -180f;
				if (value < -180)
					value = 180f;
				longitude = value;
			}
		}

		public void Upate(Device device)
		{
			//If you are porting an application that is based on a right-handed coordinate system, 
			//you must make two changes to the data passed to Direct3D.
			//Flip the order of triangle vertices so that the system traverses them clockwise from the front. 
			//In other words, if the vertices are v0, v1, v2, pass them to Direct3D as v0, v2, v1. 
			//Use the view matrix to scale world space by -1 in the z direction. 
			//To do this, flip the sign of the M31, M32, M33, and M34 fields of the Matrix structure 
			//that you use for your view matrix. 

			float fovY = (float) (Math.PI / 4);
			float aspectRatio = 1f;
			float zNear = altitude * .1f;
			float zFar = (float)Math.Sqrt(distance * distance - Settings.Radius * Settings.Radius); //hypotenuse
			//Diagnostic.Instance(device).Add("zNear", (int)(zNear/1000);
			//Diagnostic.Instance(device).Add("zFar", (int)(zFar/1000);
			//Diagnostic.Instance(device).Add("dist", (int)(distance/1000);
			projectionMatrix = Matrix.PerspectiveFovRH(fovY, aspectRatio, zNear, zFar);
			device.Transform.Projection = projectionMatrix;

			//http://www.uwgb.edu/dutchs/mathalgo/sphere0.htm
			//Vector3 cameraPosition = MathEngine.SphericalToCartesian(-1 * latitude, longitude, -1 * distance);
			Vector3 cameraPosition = MathEngine.SphericalToCartesian(latitude, longitude, distance);
			Position.Instance(device).Add("alt", (int)(altitude / 1000));
			Position.Instance(device).Add("lon", longitude.ToString());
			Position.Instance(device).Add("lat", latitude.ToString());
			Vector3 cameraFacing = new Vector3(0, 0, 0);
			//Vector3 cameraUp = new Vector3(0, 1, 0);
			Vector3 cameraUp = new Vector3(0, 0, 1);
			viewMatrix = Matrix.LookAtRH(cameraPosition, cameraFacing, cameraUp);
			
			Diagnostic.Instance(device).Add("yaw", (int) MathEngine.RadiansToDegrees(yaw));
			Diagnostic.Instance(device).Add("pitch", (int) MathEngine.RadiansToDegrees(pitch));
			Diagnostic.Instance(device).Add("roll", (int) MathEngine.RadiansToDegrees(roll));
			viewMatrix *= Matrix.RotationYawPitchRoll(yaw, pitch, roll);
			//viewMatrix *= Matrix.Translation(0.0f, 0.0f, -1 * distance);
			device.Transform.View = viewMatrix;

			device.Transform.World = worldMatrix;

			// View range
			// TODO: Calculate view range correctly
			double factor = altitude / Settings.Radius;
			if (factor < 1)
				viewRange = (float) Math.Abs(Math.Asin((altitude) / Settings.Radius)) * 2;
			else
				viewRange = (float) Math.PI;
			Diagnostic.Instance(device).Add("range", (int)MathEngine.RadiansToDegrees(viewRange));
			//view port
			viewPort = device.Viewport;
		}

		/// <summary>
		/// Calculates latitude/longitude for given screen coordinate.
		/// </summary>
		public virtual void PickingRayIntersection(int screenX, int screenY, out Angle latitude, out Angle longitude)
		{
			Vector3 p1 = new Vector3();
			p1.X = screenX;
			p1.Y = screenY;
			p1.Z = viewPort.MinZ;
			p1.Unproject(viewPort, projectionMatrix, viewMatrix, worldMatrix);

			Vector3 p2 = new Vector3();
			p2.X = screenX;
			p2.Y = screenY;
			p2.Z = viewPort.MaxZ;
			p2.Unproject(viewPort, projectionMatrix, viewMatrix, worldMatrix);

			float a = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.Z - p1.Z) * (p2.Z - p1.Z);
			float b = 2 * ((p2.X - p1.X) * (p1.X) + (p2.Y - p1.Y) * (p1.Y) + (p2.Z - p1.Z) * (p1.Z));
			float c = (float)(p1.X * p1.X + p1.Y * p1.Y + p1.Z * p1.Z - Settings.Radius * Settings.Radius);

			float discriminant = (float)(b * b - 4 * a * c);
			if (discriminant <= 0)
			{
				latitude = Angle.NaN;
				longitude = Angle.NaN;
				return;
			}

			//	float t0 = ((-1.0f) * b + (float)Math.Sqrt(b*b - 4 * a * c)) / (2*a);
			float t1 = ((-1.0f) * b - (float)Math.Sqrt(b * b - 4 * a * c)) / (2 * a);

			//	Vector3 i0 = new Vector3(p1.X + t0*(p2.X - p1.X), p1.Y + t0*(p2.Y - p1.Y), p1.Z + t0 *(p2.Z - p1.Z));
			Vector3 i1 = new Vector3(p1.X + t1 * (p2.X - p1.X), p1.Y + t1 * (p2.Y - p1.Y), p1.Z + t1 * (p2.Z - p1.Z));

			//	Vector3 i0t = MathEngine.CartesianToSpherical(i0.X, i0.Y, i0.Z);
			//Vector3 i1t = MathEngine.CartesianToSpherical(i1.X, i1.Y, i1.Z);
			Vector3 i1t = MathEngine.CartesianToSpherical(i1.X, i1.Y, i1.Z);
			Vector3 mousePointer = i1t;

			latitude = Angle.FromRadians(mousePointer.Y);
			longitude = Angle.FromRadians(mousePointer.Z);
		}

		public virtual void PointGoto(float lat, float lon)
		{
			latitude = lat;
			longitude = lon;
		}

		public virtual void PointGoto(Angle lat, Angle lon)
		{
			latitude = (float) lat.Degrees;
			longitude = (float) lon.Degrees;
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -