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

DirextX编程

开发平台:

C#

  1. ////////////////////////////////////////////////////////////////////////
  2. //      ■■■■     ■■■■■       ■■■■       ■       ■      //
  3. //    ■                 ■         ■               ■       ■      //
  4. //    ■                 ■         ■    ■■■     ■       ■      //
  5. //    ■                 ■         ■       ■      ■       ■      //
  6. //      ■■■■         ■           ■■■■         ■■■■       //
  7. // Copyright (c) 三峡大学水利与环境学院 肖泽云. All rights reserved.  //
  8. ////////////////////////////////////////////////////////////////////////
  9. using System;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Data;
  13. using System.Drawing;
  14. using System.Text;
  15. using System.Windows.Forms;
  16. using Microsoft.DirectX;
  17. using Microsoft.DirectX.Direct3D;
  18. namespace 地形
  19. {
  20.     public partial class TerrainForm : Form
  21.     {
  22.         private Device device = null;//定义绘图设备
  23.         public Vector3 CamPostion = new Vector3(0, 100, 100);//定义摄像机位置
  24.         public Vector3 CamTarget = new Vector3(125, 30, 125);//定义摄像机目标位置
  25.         private float angleY = 0.01f;//定义绕Y轴旋转变量
  26.         private int mouseLastX, mouseLastY;//记录鼠标按下时的坐标位置
  27.         private bool isRotateByMouse = false;//记录是否由鼠标控制旋转
  28.         private bool isMoveByMouse = false;//记录是否由鼠标控制移动
  29.         private CustomVertex.PositionTextured[] vertices;//定义顶点变量
  30.         private Texture texture;//定义贴图变量
  31.         private Material material;//定义材质变量
  32.         private VertexBuffer vertexBuffer;//定义顶点缓冲变量
  33.         private IndexBuffer indexBuffer;//定义索引缓冲变量
  34.         private int[] indices;//定义索引号变量
  35.         private int xCount=5, yCount=4;//定义横向和纵向网格数目
  36.         private float cellHeight = 1f, cellWidth = 1f;//定义单元的宽度和长度
  37.         
  38.         public TerrainForm()
  39.         {
  40.             this.ClientSize = new Size(800, 600);//指定窗体尺寸
  41.             this.Text = "地形";//指定窗体标题
  42.         }
  43.         public bool InitializeDirect3D()
  44.         {
  45.             try
  46.             {
  47.                 PresentParameters presentParams = new PresentParameters();
  48.                 presentParams.Windowed = true; //指定以Windows窗体形式显示
  49.                 presentParams.SwapEffect = SwapEffect.Discard; //当前屏幕绘制后它将自动从内存中删除
  50.                 presentParams.AutoDepthStencilFormat = DepthFormat.D16;
  51.                 presentParams.EnableAutoDepthStencil = true;
  52.                 presentParams.PresentationInterval = PresentInterval.Immediate;
  53.                 device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); //实例化device对象
  54.                 VertexDeclaration();//定义顶点
  55.                 IndicesDeclaration();//定义索引缓冲
  56.                 LoadTexturesAndMaterials();//导入贴图和材质
  57.                 return true;
  58.             }
  59.             catch (DirectXException e)
  60.             {
  61.                 MessageBox.Show(e.ToString(), "Error"); //处理异常
  62.                 return false;
  63.             }
  64.         }
  65.         private void VertexDeclaration()//定义顶点
  66.         {
  67.             string bitmapPath = @"E:DirectXDirectX_C#MediaheightMap.BMP";
  68.             Bitmap bitmap = new Bitmap(bitmapPath);
  69.             xCount= (bitmap.Width-1)/2;
  70.             yCount = (bitmap.Height-1)/2;
  71.             cellWidth = bitmap.Width / xCount;
  72.             cellHeight = bitmap.Height / yCount;
  73.             vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionTextured), (xCount + 1) * (yCount + 1), device,
  74.                 Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
  75.             vertices = new CustomVertex.PositionTextured[(xCount + 1) * (yCount + 1)];//定义顶点
  76.             for(int i=0;i<yCount+1;i++)
  77.             {
  78.                 for (int j = 0; j < xCount+1; j++)
  79.                 {
  80.                     Color color = bitmap.GetPixel((int)(j * cellWidth), (int)(i * cellHeight));
  81.                     float height = float.Parse(color.R.ToString()) + float.Parse(color.G.ToString()) + float.Parse(color.B.ToString());
  82.                     height /= 10;
  83.                     vertices[j + i * (xCount + 1)].Position = new Vector3(j * cellWidth, height, i * cellHeight);
  84.                     vertices[j + i * (xCount + 1)].Tu = (float)j / (xCount + 1);
  85.                     vertices[j + i * (xCount + 1)].Tv = (float)i / (yCount + 1);
  86.                 }
  87.             }
  88.             vertexBuffer.SetData(vertices, 0, LockFlags.None);
  89.             CamTarget = new Vector3(bitmap.Width / 2, 0f, bitmap.Height / 2);//设置摄像机目标位置
  90.         }
  91.         private void IndicesDeclaration()//定义索引
  92.         {
  93.             indexBuffer = new IndexBuffer(typeof(int), 6*xCount * yCount, device, Usage.WriteOnly, Pool.Default);
  94.             indices = new int[6 * xCount * yCount];
  95.             for (int i = 0; i < yCount; i++)
  96.             {
  97.                 for (int j = 0; j < xCount; j++)
  98.                 {
  99.                     indices[6 * (j + i * xCount)] = j + i * (xCount+1);
  100.                     indices[6 * (j + i * xCount) + 1] = j + (i+1) * (xCount + 1);
  101.                     indices[6 * (j + i * xCount) + 2] = j + i * (xCount + 1) + 1;
  102.                     indices[6 * (j + i * xCount) + 3] = j + i * (xCount + 1) + 1;
  103.                     indices[6 * (j + i * xCount) + 4] = j + (i + 1) * (xCount + 1);
  104.                     indices[6 * (j + i * xCount) + 5] = j + (i + 1) * (xCount + 1) + 1;
  105.                 }
  106.             }
  107.             indexBuffer.SetData(indices, 0, LockFlags.None);
  108.         }
  109.         
  110.         private void LoadTexturesAndMaterials()//导入贴图和材质
  111.         {
  112.             material = new Material();
  113.             material.Diffuse = Color.White;
  114.             material.Specular = Color.LightGray;
  115.             material.SpecularSharpness = 15.0F;
  116.             device.Material = material;
  117.             texture = TextureLoader.FromFile(device, @"E:DirectXDirectX_C#MediacolorMap.jpg");
  118.         }
  119.         public void Render()
  120.         {
  121.             if (device == null)   //如果device为空则不渲染
  122.             {
  123.                 return;
  124.             }
  125.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  126.             device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 0.3f, 500f);
  127.             device.Transform.View = viewMatrix;
  128.             device.Clear(ClearFlags.Target|ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0);  //清除windows界面为深蓝色
  129.             device.BeginScene();
  130.             //在此添加渲染图形代码
  131.             device.RenderState.CullMode = Cull.None;
  132.             device.RenderState.FillMode = FillMode.Solid;
  133.             device.RenderState.Lighting = false;
  134.             device.SetTexture(0, texture);//设置贴图
  135.  
  136.             device.VertexFormat = CustomVertex.PositionTextured.Format;
  137.             device.SetStreamSource(0, vertexBuffer, 0);
  138.             device.Indices = indexBuffer;
  139.             device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, (xCount + 1) * (yCount + 1), 0, indices.Length / 3);
  140.             device.EndScene();
  141.             device.Present();
  142.         }
  143.         protected override void OnKeyDown(KeyEventArgs e)
  144.         {
  145.             Vector4 tempV4;
  146.             Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  147.             switch (e.KeyCode)
  148.             {
  149.                 case Keys.Left:
  150.                     CamPostion.Subtract(CamTarget);
  151.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  152.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), -angleY)));
  153.                     CamPostion.X = tempV4.X + CamTarget.X;
  154.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  155.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  156.                     break;
  157.                 case Keys.Right:
  158.                     CamPostion.Subtract(CamTarget);
  159.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  160.                             Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), angleY)));
  161.                     CamPostion.X = tempV4.X + CamTarget.X;
  162.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  163.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  164.                     break;
  165.                 case Keys.Up:
  166.                     CamPostion.Subtract(CamTarget);
  167.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  168.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  169.                        , device.Transform.View.M21, device.Transform.View.M31), -angleY)));
  170.                     CamPostion.X = tempV4.X + CamTarget.X;
  171.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  172.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  173.                     break;
  174.                 case Keys.Down:
  175.                     CamPostion.Subtract(CamTarget);
  176.                     tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  177.                        Quaternion.RotationAxis(new Vector3(device.Transform.View.M11
  178.                        , device.Transform.View.M21, device.Transform.View.M31), angleY)));
  179.                     CamPostion.X = tempV4.X + CamTarget.X;
  180.                     CamPostion.Y = tempV4.Y + CamTarget.Y;
  181.                     CamPostion.Z = tempV4.Z + CamTarget.Z;
  182.                     break;
  183.                 case Keys.Add:
  184.                     CamPostion.Subtract(CamTarget);
  185.                     CamPostion.Scale(0.95f);
  186.                     CamPostion.Add(CamTarget);
  187.                     break;
  188.                 case Keys.Subtract:
  189.                     CamPostion.Subtract(CamTarget);
  190.                     CamPostion.Scale(1.05f);
  191.                     CamPostion.Add(CamTarget);
  192.                     break;
  193.             }
  194.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  195.             device.Transform.View = viewMatrix;
  196.             Render();
  197.         }
  198.         protected override void OnMouseDown(MouseEventArgs e)
  199.         {
  200.             if (e.Button == MouseButtons.Left)
  201.             {
  202.                 mouseLastX = e.X;
  203.                 mouseLastY = e.Y;
  204.                 isRotateByMouse = true;
  205.             }
  206.             else if (e.Button == MouseButtons.Middle)
  207.             {
  208.                 mouseLastX = e.X;
  209.                 mouseLastY = e.Y;
  210.                 isMoveByMouse = true;
  211.             }
  212.         }
  213.         protected override void OnMouseUp(MouseEventArgs e)
  214.         {
  215.             isRotateByMouse = false;
  216.             isMoveByMouse = false;
  217.         }
  218.         protected override void OnMouseMove(MouseEventArgs e)
  219.         {
  220.             if (isRotateByMouse)
  221.             {
  222.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  223.                 float tempAngleY = 2 * (float)(e.X - mouseLastX) / this.Width;
  224.                 CamPostion.Subtract(CamTarget);
  225.                 Vector4 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  226.                     Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), tempAngleY)));
  227.                 CamPostion.X = tempV4.X;
  228.                 CamPostion.Y = tempV4.Y;
  229.                 CamPostion.Z = tempV4.Z;
  230.                 float tempAngleX = 4 * (float)(e.Y - mouseLastY) / this.Height;
  231.                 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
  232.                     Quaternion.RotationAxis(new Vector3(currentView.M11, currentView.M21, currentView.M31), tempAngleX)));
  233.                 CamPostion.X = tempV4.X + CamTarget.X;
  234.                 CamPostion.Y = tempV4.Y + CamTarget.Y;
  235.                 CamPostion.Z = tempV4.Z + CamTarget.Z;
  236.                 Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  237.                 device.Transform.View = viewMatrix;
  238.                 mouseLastX = e.X;
  239.                 mouseLastY = e.Y;
  240.                 Render();
  241.             }
  242.             else if (isMoveByMouse)
  243.             {
  244.                 Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵
  245.                 float moveFactor = 0.01f;
  246.                 CamTarget.X += -moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  247.                 CamTarget.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  248.                 CamTarget.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  249.                 CamPostion.X += -moveFactor * ((e.X - mouseLastX) * currentView.M11 - (e.Y - mouseLastY) * currentView.M12);
  250.                 CamPostion.Y += -moveFactor * ((e.X - mouseLastX) * currentView.M21 - (e.Y - mouseLastY) * currentView.M22);
  251.                 CamPostion.Z += -moveFactor * ((e.X - mouseLastX) * currentView.M31 - (e.Y - mouseLastY) * currentView.M32);
  252.                 Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  253.                 device.Transform.View = viewMatrix;
  254.                 mouseLastX = e.X;
  255.                 mouseLastY = e.Y;
  256.                 Render();
  257.             }
  258.         }
  259.         protected override void OnMouseWheel(MouseEventArgs e)
  260.         {
  261.             float scaleFactor = -(float)e.Delta / 2000 + 1f;
  262.             CamPostion.Subtract(CamTarget);
  263.             CamPostion.Scale(scaleFactor);
  264.             CamPostion.Add(CamTarget);
  265.             Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
  266.             device.Transform.View = viewMatrix;
  267.             Render();
  268.         }
  269.         static void Main()
  270.         {
  271.             TerrainForm terrainForm = new TerrainForm(); //创建窗体对象
  272.             if (terrainForm.InitializeDirect3D() == false) //检查Direct3D是否启动
  273.             {
  274.                 MessageBox.Show("无法启动Direct3D!", "错误!");
  275.                 return;
  276.             }
  277.             terrainForm.Show(); //如果一切都初始化成功,则显示窗体
  278.             while (terrainForm.Created) //设置一个循环用于实时更新渲染状态
  279.             {
  280.                 terrainForm.Render(); //保持device渲染,直到程序结束
  281.                 Application.DoEvents(); //处理键盘鼠标等输入事件
  282.             }
  283.         }
  284.     }
  285. }