📄 camera.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 + -