ClickRay.cs
上传用户:lslight
上传日期:2022-01-10
资源大小:14248k
文件大小:13k
源码类别:

DirextX编程

开发平台:

C#

  1. ///////////////////////////////////////////////////////////////////////
  2. //      ■■■■     ■■■■■       ■■■■       ■       ■      //
  3. //    ■                 ■         ■               ■       ■      //
  4. //    ■                 ■         ■    ■■■     ■       ■      //
  5. //    ■                 ■         ■       ■      ■       ■      //
  6. //      ■■■■         ■           ■■■■         ■■■■       //
  7. // Copyright (c) 三峡大学水利与环境学院 肖泽云. All rights reserved.  //
  8. ////////////////////////////////////////////////////////////////////////
  9. using System;
  10. using System.ComponentModel;
  11. using System.Data;
  12. using System.Drawing;
  13. using System.Windows.Forms;
  14. using Microsoft.DirectX;
  15. using Microsoft.DirectX.Direct3D;
  16. namespace 点击射线
  17. {
  18.     public partial class ClickRay : Form
  19.     {
  20.         Device device = null;//定义绘图设备
  21.         private float angleY=0.01f;//定义绕Y轴旋转变量
  22.         private Vector3 CamPostion = new Vector3(0, 30, -30);//定义摄像机位置
  23.         private Vector3 CamTarget = new Vector3(0, 0, 0);//定义摄像机目标位置
  24.         private int mouseLastX,mouseLastY;//记录鼠标按下时的坐标位置
  25.         private bool isRotateByMouse=false;//记录是否由鼠标控制旋转
  26.         private bool isMoveByMouse = false;//记录是否由鼠标控制移动
  27.         private CustomVertex.PositionColored[] rayVertices;//定义射线顶点变量
  28.         public ClickRay()
  29.         {
  30.             this.ClientSize = new Size(800, 600);//指定窗体尺寸
  31.             this.Text = "点击射线";//指定窗体标题
  32.         }
  33.         public bool InitializeDirect3D()
  34.         {
  35.             try
  36.             {
  37.                 PresentParameters presentParams = new PresentParameters();
  38.                 presentParams.Windowed = true; //指定以Windows窗体形式显示
  39.                 presentParams.SwapEffect = SwapEffect.Discard; //当前屏幕绘制后它将自动从内存中删除
  40.                 presentParams.AutoDepthStencilFormat = DepthFormat.D16;
  41.                 presentParams.EnableAutoDepthStencil = true;
  42.                 presentParams.PresentationInterval = PresentInterval.Immediate;
  43.                 device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); //实例化device对象
  44.                 return true;
  45.             }
  46.             catch (DirectXException e)
  47.             {
  48.                 MessageBox.Show(e.ToString(), "Error"); //处理异常
  49.                 return false;
  50.             }
  51.         }
  52.         private void ShowMatrix(Matrix matrix)
  53.         {
  54.             string matrixString = "";
  55.             matrixString = matrix.M11.ToString("F3") + "  " + matrix.M12.ToString("F3") + "  " +
  56.                 matrix.M13.ToString("F3") + "  " + matrix.M14.ToString("F3") + "n" +
  57.                 matrix.M21.ToString("F3") + "  " + matrix.M22.ToString("F3") + "  " +
  58.                 matrix.M23.ToString("F3") + "  " + matrix.M24.ToString("F3") + "n" +
  59.                 matrix.M31.ToString("F3") + "  " + matrix.M32.ToString("F3") + "  " +
  60.                 matrix.M33.ToString("F3") + "  " + matrix.M34.ToString("F3") + "n" +
  61.                 matrix.M41.ToString("F3") + "  " + matrix.M42.ToString("F3") + "  " +
  62.                 matrix.M43.ToString("F3") + "  " + matrix.M44.ToString("F3") + "n";
  63.             Console.WriteLine(matrixString);
  64.         }
  65.         public void Render()
  66.         {
  67.             if (device == null)   //如果device为空则不渲染
  68.             {
  69.                 return;
  70.             }
  71.             SetUpCamera();
  72.             device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0);  //清除windows界面为深蓝色
  73.             device.BeginScene();
  74.             //在此添加渲染图形代码
  75.             device.RenderState.Lighting = false;
  76.             if (rayVertices != null)
  77.             {
  78.                 device.VertexFormat = CustomVertex.PositionColored.Format;
  79.                 device.DrawUserPrimitives(PrimitiveType.LineList, rayVertices.Length / 2, rayVertices);
  80.             }
  81.             device.EndScene();
  82.             device.Present();
  83.         }
  84.         private void SetUpCamera()//摄像机
  85.         {
  86.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  87.             device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.ClientSize.Width / this.ClientSize.Height, 0.3f, 500f);
  88.             device.Transform.View = viewMatrix;
  89.         }
  90.         protected override void OnKeyDown(KeyEventArgs e)
  91.         {
  92.             Vector4 tempV4;
  93.             Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  94.             switch (e.KeyCode)
  95.             {
  96.                 case Keys.Left:
  97.                     CamPostion.Subtract(CamTarget);
  98.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  99.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), -angleY)));
  100.                     CamPostion.X = tempV4.X + CamTarget.X;
  101.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  102.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  103.                     break;
  104.                 case Keys.Right:
  105.                     CamPostion.Subtract(CamTarget);
  106.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  107.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), angleY)));
  108.                     CamPostion.X = tempV4.X + CamTarget.X;
  109.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  110.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  111.                     break;
  112.                 case Keys.Up:
  113.                     CamPostion.Subtract(CamTarget);
  114.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  115.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  116.                        , device.Transform.View.M21, device.Transform.View.M31), -angleY)));
  117.                     CamPostion.X = tempV4.X + CamTarget.X;
  118.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  119.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  120.                     break;
  121.                 case Keys.Down:
  122.                     CamPostion.Subtract(CamTarget);
  123.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  124.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  125.                        , device.Transform.View.M21, device.Transform.View.M31), angleY)));
  126.                     CamPostion.X = tempV4.X + CamTarget.X;
  127.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  128.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  129.                     break;
  130.                 case Keys.Add:
  131.                     CamPostion.Subtract(CamTarget);
  132.                     CamPostion.Scale(0.95f);
  133.                     CamPostion.Add(CamTarget);
  134.                     break;
  135.                 case Keys.Subtract:
  136.                     CamPostion.Subtract(CamTarget);
  137.                     CamPostion.Scale(1.05f);
  138.                     CamPostion.Add(CamTarget);
  139.                     break;
  140.             }
  141.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  142.             device.Transform.View = viewMatrix;
  143.         }
  144.         protected override void OnMouseDown(MouseEventArgs e)
  145.         {
  146.             if (e.Button == MouseButtons.Left)
  147.             {
  148.                 mouseLastX = e.X;
  149.                 mouseLastY = e.Y;
  150.                 isRotateByMouse = true;
  151.                 
  152.                 //计算摄像机投影窗口上对应的点击位置坐标
  153.                 Vector3 SVector = new Vector3();
  154.                 SVector.X = 2 * (float)e.X / this.ClientSize.Width - 1;
  155.                 SVector.Y = -2 * (float)e.Y / this.ClientSize.Height + 1;
  156.                 SVector.Z = 1.0f / (float)Math.Tan(Math.PI / 8);
  157.                 //视图矩阵
  158.                 Matrix viewMatrix = device.Transform.View;
  159.                 viewMatrix.Invert();//计算视图矩阵的逆矩阵
  160.                 Vector4 VectorOP = Vector3.Transform(SVector, viewMatrix);
  161.                 //射线位置
  162.                 Vector3 rayPos = new Vector3(VectorOP.X, VectorOP.Y, VectorOP.Z);
  163.                 //射线方向
  164.                 Vector3 rayDir = Vector3.Subtract(rayPos,CamPostion);
  165.                 //设置绘制射线的顶点坐标
  166.                 rayVertices = new CustomVertex.PositionColored[2];
  167.                 rayVertices[0].Position = rayPos;
  168.                 rayVertices[0].Color = Color.Red.ToArgb();
  169.                 rayVertices[1].Position = rayDir;
  170.                 rayVertices[1].Color = Color.Red.ToArgb();
  171.             }
  172.             else if (e.Button == MouseButtons.Middle)
  173.             {
  174.                 mouseLastX = e.X;
  175.                 mouseLastY = e.Y;
  176.                 isMoveByMouse=true;
  177.             }
  178.         }
  179.         
  180.         protected override void OnMouseUp(MouseEventArgs e)
  181.         {
  182.             isRotateByMouse = false;
  183.             isMoveByMouse = false;
  184.         }
  185.         protected override void OnMouseMove(MouseEventArgs e)
  186.         {
  187.             if (isRotateByMouse)
  188.             {
  189.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  190.                 float tempAngleY = 2 * (float)(e.X - mouseLastX) / this.Width;
  191.                 CamPostion.Subtract(CamTarget);
  192.                 Vector4 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  193.                     Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), tempAngleY)));
  194.                 CamPostion.X = tempV4.X;
  195.                 CamPostion.Y = tempV4.Y;
  196.                 CamPostion.Z = tempV4.Z;
  197.                 float tempAngleX = 4 * (float)(e.Y - mouseLastY) / this.Height;
  198.                 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  199.                     Quaternion.RotationAxis(new Vector3(currentView.M11, currentView.M21, currentView.M31), tempAngleX)));
  200.                 CamPostion.X = tempV4.X + CamTarget.X;
  201.                 CamPostion.Y = tempV4.Y + CamTarget.Y;
  202.                 CamPostion.Z = tempV4.Z + CamTarget.Z;
  203.                 Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  204.                 device.Transform.View = viewMatrix;
  205.                 mouseLastX = e.X;
  206.                 mouseLastY = e.Y;
  207.             }
  208.             else if (isMoveByMouse)
  209.             {
  210.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  211.                 float moveFactor=0.01f;
  212.                 CamTarget.X += -moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  213.                 CamTarget.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  214.                 CamTarget.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  215.                 CamPostion.X +=- moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  216.                 CamPostion.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  217.                 CamPostion.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  218.              
  219.                 Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  220.                 device.Transform.View = viewMatrix;
  221.                 mouseLastX = e.X;
  222.                 mouseLastY = e.Y;
  223.             }
  224.         }
  225.         protected override void OnMouseWheel(MouseEventArgs e)
  226.         {
  227.             float scaleFactor = -(float)e.Delta / 2000 + 1f;
  228.             CamPostion.Subtract(CamTarget);
  229.             CamPostion.Scale(scaleFactor);
  230.             CamPostion.Add(CamTarget);
  231.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  232.             device.Transform.View = viewMatrix;
  233.         }
  234.         static void Main()
  235.         {
  236.             ClickRay clickRay = new ClickRay(); //创建窗体对象
  237.             if (clickRay.InitializeDirect3D() == false) //检查Direct3D是否启动
  238.             {
  239.                 MessageBox.Show("无法启动Direct3D!", "错误!");
  240.                 return;
  241.             }
  242.             clickRay.Show(); //如果一切都初始化成功,则显示窗体
  243.             while (clickRay.Created) //设置一个循环用于实时更新渲染状态
  244.             {
  245.                 clickRay.Render(); //保持device渲染,直到程序结束
  246.                 Application.DoEvents(); //处理键盘鼠标等输入事件
  247.             }
  248.         }
  249.     }
  250. }