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

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