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

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 PickObject : 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 Mesh meshObj;//定义茶壶网格对象
  28.         //private Material meshMaterials; //定义网格材质对象
  29.         private Mesh[] meshObj;//定义茶壶网格对象
  30.         private Material[] meshMaterials; //定义网格材质对象
  31.         private Matrix[] meshPosition;//定义茶壶网格的位置
  32.         public PickObject()
  33.         {
  34.             this.ClientSize = new Size(800, 600);//指定窗体尺寸
  35.             this.Text = "拾取对象";//指定窗体标题
  36.         }
  37.         public bool InitializeDirect3D()
  38.         {
  39.             try
  40.             {
  41.                 PresentParameters presentParams = new PresentParameters();
  42.                 presentParams.Windowed = true; //指定以Windows窗体形式显示
  43.                 presentParams.SwapEffect = SwapEffect.Discard; //当前屏幕绘制后它将自动从内存中删除
  44.                 presentParams.AutoDepthStencilFormat = DepthFormat.D16;
  45.                 presentParams.EnableAutoDepthStencil = true;
  46.                 presentParams.PresentationInterval = PresentInterval.Immediate;
  47.                 device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); //实例化device对象
  48.                 
  49.                 /*
  50.                 meshObj = Mesh.Teapot(device);//定义茶壶对象
  51.                 //定义材质
  52.                 meshMaterials.Diffuse = Color.White;
  53.                 meshMaterials.Ambient = Color.White;
  54.                 meshMaterials.Specular = Color.LightGray;
  55.                 meshMaterials.SpecularSharpness = 15.0F;
  56.                 */
  57.                 //定义三个茶壶对象
  58.                 meshObj = new Mesh[3];
  59.                 meshObj[0] = Mesh.Teapot(device);//定义茶壶对象
  60.                 meshObj[1] = Mesh.Teapot(device);//定义茶壶对象
  61.                 meshObj[2] = Mesh.Teapot(device);//定义茶壶对象
  62.                 //定义茶壶位置
  63.                 meshPosition = new Matrix[3];
  64.                 meshPosition[0] = Matrix.Translation(-10f, 0f, 0f);
  65.                 meshPosition[1] = Matrix.Translation(0f, 0f, 0f);
  66.                 meshPosition[2] = Matrix.Translation(10f, 0f, 0f);
  67.                 //定义材质
  68.                 meshMaterials = new Material[3];
  69.                 meshMaterials[0].Diffuse = Color.White;
  70.                 meshMaterials[0].Ambient = Color.White;
  71.                 meshMaterials[0].Specular = Color.LightGray;
  72.                 meshMaterials[0].SpecularSharpness = 15.0F;
  73.                 meshMaterials[2] = meshMaterials[1] = meshMaterials[0];
  74.                                 
  75.                 return true;
  76.             }
  77.             catch (DirectXException e)
  78.             {
  79.                 MessageBox.Show(e.ToString(), "Error"); //处理异常
  80.                 return false;
  81.             }
  82.         }
  83.         public void Render()
  84.         {
  85.             if (device == null)   //如果device为空则不渲染
  86.             {
  87.                 return;
  88.             }
  89.             SetUpCamera();
  90.             device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0);  //清除windows界面为深蓝色
  91.             device.BeginScene();
  92.             //在此添加渲染图形代码
  93.             //灯光设置            
  94.             device.RenderState.Lighting = true;
  95.             device.Lights[0].Type = LightType.Directional;
  96.             device.Lights[0].Diffuse = System.Drawing.Color.Red;
  97.             device.Lights[0].Direction = new Vector3(-1.0f, 1.0f, 1.0f);
  98.             device.Lights[0].Enabled = true; //打开灯光
  99.             device.Lights[1].Type = LightType.Directional;
  100.             device.Lights[1].Diffuse = System.Drawing.Color.Green;
  101.             device.Lights[1].Direction = new Vector3(1f, -1.0f, 1.0f);
  102.             device.Lights[1].Enabled = true; //打开灯光            
  103.             device.RenderState.Ambient = Color.SlateGray;
  104.             
  105.             device.RenderState.CullMode = Cull.None;
  106.                        
  107.             //以实体形式绘制茶壶模型
  108.             device.RenderState.FillMode = FillMode.Solid;
  109.             /*
  110.             device.Material = meshMaterials;//设置当前材质
  111.             meshObj.DrawSubset(0);
  112.              */
  113.             for (int i = 0; i < meshObj.Length; i++)
  114.             {
  115.                 //设置当前世界矩阵
  116.                 device.Transform.World = meshPosition[i];
  117.                 //设置当前材质
  118.                 device.Material = meshMaterials[i];
  119.                 meshObj[i].DrawSubset(0);
  120.             }
  121.             /*
  122.             device.Transform.World = meshPosition[0];
  123.             device.Material = meshMaterials[0];//设置当前材质
  124.             meshObj[0].DrawSubset(0);
  125.             device.Transform.World = meshPosition[1];
  126.             device.Material = meshMaterials[1];//设置当前材质
  127.             meshObj[1].DrawSubset(0);
  128.             device.Transform.World = meshPosition[2];
  129.             device.Material = meshMaterials[2];//设置当前材质
  130.             meshObj[2].DrawSubset(0);
  131.             */
  132.             device.EndScene();
  133.             device.Present();
  134.         }
  135.         private void SetUpCamera()//摄像机
  136.         {
  137.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  138.             device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.ClientSize.Width / this.ClientSize.Height, 0.3f, 500f);
  139.             device.Transform.View = viewMatrix;
  140.         }
  141.         protected override void OnKeyDown(KeyEventArgs e)
  142.         {
  143.             Vector4 tempV4;
  144.             Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  145.             switch (e.KeyCode)
  146.             {
  147.                 case Keys.Left:
  148.                     CamPostion.Subtract(CamTarget);
  149.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  150.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), -angleY)));
  151.                     CamPostion.X = tempV4.X + CamTarget.X;
  152.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  153.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  154.                     break;
  155.                 case Keys.Right:
  156.                     CamPostion.Subtract(CamTarget);
  157.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  158.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), angleY)));
  159.                     CamPostion.X = tempV4.X + CamTarget.X;
  160.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  161.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  162.                     break;
  163.                 case Keys.Up:
  164.                     CamPostion.Subtract(CamTarget);
  165.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  166.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  167.                        , device.Transform.View.M21, device.Transform.View.M31), -angleY)));
  168.                     CamPostion.X = tempV4.X + CamTarget.X;
  169.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  170.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  171.                     break;
  172.                 case Keys.Down:
  173.                     CamPostion.Subtract(CamTarget);
  174.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  175.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  176.                        , device.Transform.View.M21, device.Transform.View.M31), angleY)));
  177.                     CamPostion.X = tempV4.X + CamTarget.X;
  178.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  179.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  180.                     break;
  181.                 case Keys.Add:
  182.                     CamPostion.Subtract(CamTarget);
  183.                     CamPostion.Scale(0.95f);
  184.                     CamPostion.Add(CamTarget);
  185.                     break;
  186.                 case Keys.Subtract:
  187.                     CamPostion.Subtract(CamTarget);
  188.                     CamPostion.Scale(1.05f);
  189.                     CamPostion.Add(CamTarget);
  190.                     break;
  191.             }
  192.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  193.             device.Transform.View = viewMatrix;
  194.         }
  195.         protected override void OnMouseDown(MouseEventArgs e)
  196.         {
  197.             if (e.Button == MouseButtons.Left)
  198.             {
  199.                 mouseLastX = e.X;
  200.                 mouseLastY = e.Y;
  201.                 isRotateByMouse = true;                
  202.             }
  203.             else if (e.Button == MouseButtons.Middle)
  204.             {
  205.                 mouseLastX = e.X;
  206.                 mouseLastY = e.Y;
  207.                 isMoveByMouse=true;
  208.             }
  209.         }
  210.         
  211.         protected override void OnMouseUp(MouseEventArgs e)
  212.         {
  213.             isRotateByMouse = false;
  214.             isMoveByMouse = false;
  215.         }
  216.         protected override void OnMouseMove(MouseEventArgs e)
  217.         {
  218.             //计算摄像机投影窗口上对应的点击位置坐标
  219.             Vector3 SVector = new Vector3();
  220.             SVector.X = 2 * (float)e.X / this.ClientSize.Width - 1;
  221.             SVector.Y = -2 * (float)e.Y / this.ClientSize.Height + 1;
  222.             SVector.Z = 1.0f / (float)Math.Tan(Math.PI / 8);
  223.             //视图矩阵
  224.             Matrix viewMatrix = device.Transform.View;
  225.             viewMatrix.Invert();//计算视图矩阵的逆矩阵
  226.             //射线位置
  227.             Vector3 rayPos = Vector3.TransformCoordinate(SVector, viewMatrix);
  228.             //射线方向
  229.             Vector3 rayDir = Vector3.Subtract(rayPos, CamPostion);
  230.             //碰撞检测            
  231.             for (int i = 0; i < meshObj.Length; i++)
  232.             {
  233.                 //将模型的世界矩阵进行逆变换
  234.                 Matrix inverseWorld = Matrix.Invert(meshPosition[i]);
  235.                 Vector3 localRayPos = Vector3.TransformCoordinate(rayPos, inverseWorld);
  236.                 Vector3 localRayDir = Vector3.TransformNormal(rayDir, inverseWorld);
  237.                 bool result = meshObj[i].Intersect(localRayPos, localRayDir);
  238.                 if (result)
  239.                 {
  240.                     meshMaterials[i].Diffuse = Color.Red;//相交时漫反射为红色
  241.                     meshMaterials[i].Ambient = Color.Red;//相交时环境色为红色
  242.                 }
  243.                 else
  244.                 {
  245.                     meshMaterials[i].Diffuse = Color.White;//不相交时漫反射为白色
  246.                     meshMaterials[i].Ambient = Color.White;//不相交时环境色为红色
  247.                 }
  248.             }
  249.             /*
  250.             bool result = meshObj.Intersect(rayPos, rayDir);
  251.             if (result)
  252.             {
  253.                 meshMaterials.Diffuse = Color.Red;//相交时漫反射为红色
  254.                 meshMaterials.Ambient = Color.Red;//相交时环境色为红色
  255.             }
  256.             else
  257.             {
  258.                 meshMaterials.Diffuse = Color.White;//不相交时漫反射为白色
  259.                 meshMaterials.Ambient = Color.White;//不相交时环境色为红色
  260.             }
  261.             */
  262.             if (isRotateByMouse)
  263.             {
  264.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  265.                 float tempAngleY = 2 * (float)(e.X - mouseLastX) / this.Width;
  266.                 CamPostion.Subtract(CamTarget);
  267.                 Vector4 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  268.                     Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), tempAngleY)));
  269.                 CamPostion.X = tempV4.X;
  270.                 CamPostion.Y = tempV4.Y;
  271.                 CamPostion.Z = tempV4.Z;
  272.                 float tempAngleX = 4 * (float)(e.Y - mouseLastY) / this.Height;
  273.                 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  274.                     Quaternion.RotationAxis(new Vector3(currentView.M11, currentView.M21, currentView.M31), tempAngleX)));
  275.                 CamPostion.X = tempV4.X + CamTarget.X;
  276.                 CamPostion.Y = tempV4.Y + CamTarget.Y;
  277.                 CamPostion.Z = tempV4.Z + CamTarget.Z;
  278.                 viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  279.                 device.Transform.View = viewMatrix;
  280.                 mouseLastX = e.X;
  281.                 mouseLastY = e.Y;
  282.             }
  283.             else if (isMoveByMouse)
  284.             {
  285.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  286.                 float moveFactor=0.01f;
  287.                 CamTarget.X += -moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  288.                 CamTarget.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  289.                 CamTarget.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  290.                 CamPostion.X +=- moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  291.                 CamPostion.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  292.                 CamPostion.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  293.              
  294.                 viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  295.                 device.Transform.View = viewMatrix;
  296.                 mouseLastX = e.X;
  297.                 mouseLastY = e.Y;
  298.             }
  299.         }
  300.         protected override void OnMouseWheel(MouseEventArgs e)
  301.         {
  302.             float scaleFactor = -(float)e.Delta / 2000 + 1f;
  303.             CamPostion.Subtract(CamTarget);
  304.             CamPostion.Scale(scaleFactor);
  305.             CamPostion.Add(CamTarget);
  306.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  307.             device.Transform.View = viewMatrix;
  308.         }
  309.         static void Main()
  310.         {
  311.             PickObject pickObject = new PickObject(); //创建窗体对象
  312.             if (pickObject.InitializeDirect3D() == false) //检查Direct3D是否启动
  313.             {
  314.                 MessageBox.Show("无法启动Direct3D!", "错误!");
  315.                 return;
  316.             }
  317.             pickObject.Show(); //如果一切都初始化成功,则显示窗体
  318.             while (pickObject.Created) //设置一个循环用于实时更新渲染状态
  319.             {
  320.                 pickObject.Render(); //保持device渲染,直到程序结束
  321.                 Application.DoEvents(); //处理键盘鼠标等输入事件
  322.             }
  323.         }
  324.     }
  325. }