Skip to content

Instantly share code, notes, and snippets.

@oguna
Created December 29, 2013 10:28
Show Gist options
  • Select an option

  • Save oguna/8169149 to your computer and use it in GitHub Desktop.

Select an option

Save oguna/8169149 to your computer and use it in GitHub Desktop.
DXUTのModelViewCameraっぽいのをC#で書いた。SharpDXでの利用を想定。マウス入力はフォームにイベントハンドラを与えることで取得する。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpDX;
namespace MeshFromOBJ
{
class GlobeCamera
{
#region メンバ
/// <summary>
/// 射影行列
/// </summary>
public Matrix ProjectionMat
{
get { return Matrix.PerspectiveFovLH(0.35f, 800f / 600, 0.01f, 100f); }
}
/// <summary>
/// ビュー行列
/// </summary>
public Matrix ViewMat
{
get { return Matrix.LookAtLH(CameraPosition, LookAtPosition, new Vector3(0.0f, 1.0f, 0.0f)); }
}
/// <summary>
/// カメラ位置
/// </summary>
public Vector3 CameraPosition;
/// <summary>
/// 視点
/// </summary>
public Vector3 LookAtPosition;
public Vector3 CamRot;
public float distants = 10.0f;
public float radius = 8.0f;
private int lastWhile = 0;
private int lastX = 0, lastY = 0;
int currentX, currentY;
bool currentR;
int deltaW;
#endregion
/// <summary>
/// デフォルトのコンストラクタ
/// </summary>
public GlobeCamera(Form form)
{
form.MouseDown += (object sender, MouseEventArgs e) =>
{
if(e.Button==MouseButtons.Right)
{
currentR = true;
}
};
form.MouseUp += (object sender, MouseEventArgs e) =>
{
if (e.Button == MouseButtons.Right)
{
currentR = false;
}
};
form.MouseMove += (object sender, MouseEventArgs e) =>
{
currentX = e.X;
currentY = e.Y;
};
form.MouseWheel += (object sender, MouseEventArgs e) =>
{
deltaW += e.Delta;
};
}
/// <summary>
/// デフォルトのデストラクタ
/// </summary>
~GlobeCamera()
{
}
public void OnUpdate(float elapsedTime)
{
// スクロールでカメラの距離
radius -= (float)(deltaW)*0.01f;
radius = Math.Max(5f, radius);
deltaW = 0;
if (currentR)
{
CamRot.Y -= (currentX - lastX) * 0.01f;
CamRot.X += (currentY - lastY) * 0.01f;
}
CamRot.X = Clamp(CamRot.X, -1.4f, 1.4f);
lastX = currentX;
lastY = currentY;
CameraPosition = LookAtPosition + AxisToForce(CamRot.X, CamRot.Y) * radius;
}
/// <summary>
/// <para> 方向ベクトルからXY軸角を生成 </para>
/// <para> 標準化不要 </para>
/// </summary>
/// <param name="normal">方向ベクトル</param>
/// <returns>ラジアン値のXY軸ベクトル</returns>
private static Vector3 ForceToAxis(Vector3 vector)
{
float sqrt = (float)Math.Sqrt(vector.Z * vector.Z + vector.X * vector.X);
float rotY = -(float)Math.Atan2(vector.Z, vector.X);
float rotX = -(float)Math.Atan2(vector.Y, sqrt);
return new Vector3(rotX, rotY, 0.0f);
}
/// <summary>
/// <para> XY軸角から方向ベクトルを生成 </para>
/// <para> X=90°:(0,1,0) </para>
/// <para> Y=0° :(1,0,0) </para>
/// </summary>
private static Vector3 AxisToForce(float radX, float radY)
{
float cosY = (float)Math.Cos((double)radY);
float cosX = (float)Math.Cos((double)radX);
float sinY = (float)Math.Sin((double)radY);
float sinX = (float)Math.Sin((double)radX);
return new Vector3(cosY * cosX, sinX, sinY * cosX);
}
/// <summary>
/// 値を指定された範囲に収める
/// </summary>
/// <param name="source">値</param>
/// <param name="min">下限</param>
/// <param name="max">上限</param>
/// <returns>範囲に収められた値</returns>
private static float Clamp(float source, float min, float max)
{
if (source < min)
{
source = min;
}
else if (source > max)
{
source = max;
}
return source;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment