DirectX 3D Mesh类

Mesh类中定义了若干个3D模型,比如说立方体、圆柱、茶壶等。对于一些复杂的模型可以使用专业的软件比如说3D Max等设计,再利用DirectX提供的插件,将复杂的3D模型保存为.x文件。用Mesh类对象可以加载.x文件,并显示.x文件中的3D模型。Mesh类位于Direct 3D的扩展库中,为了使用Mesh类必须引用Microsoft.DirectX.Direct3DX组件。

可以用Mesh类创建一个茶壶,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace 显示茶壶
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        Mesh mesh = null;
        Material meshMaterials;
        float Angle = 0, ViewZ = -5.0f;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏显示,在一个窗口显示
                presentParams.SwapEffect = SwapEffect.Discard;		 //后备缓存交换的方式
                presentParams.EnableAutoDepthStencil = true;			 //允许使用自动深度模板测试
                //深度缓冲区单元为16位二进制数
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立设备类对象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //设置设备重置事件(device.DeviceReset)事件函数为this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定义方法,初始化Device的工作放到这个方法中
                this.OnResetDevice(device, null);//调用设备重置事件(device.DeviceReset)事件函数
            }		//设备重置事件函数要设置Device参数,初始函数中必须调用该函数
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            mesh = Mesh.Teapot(device);
            meshMaterials = new Material();
            meshMaterials.Ambient = System.Drawing.Color.White;		//材质如何反射环境光
            meshMaterials.Diffuse = System.Drawing.Color.White;		//材质如何反射灯光

        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.ZBufferEnable = true;		 	//允许使用深度缓冲
            dev.RenderState.Ambient = Color.Black;	 	 	//环境光为深蓝色
            dev.Lights[0].Type = LightType.Directional;  	//设置灯光类型
            dev.Lights[0].Diffuse = Color.White;			//设置灯光颜色
            dev.Lights[0].Direction = new Vector3(0, -1, 1);	//设置灯光位置
            dev.Lights[0].Update();						//更新灯光设置,创建第一盏灯光
            dev.Lights[0].Enabled = true;					//使设置有效
            dev.Material = meshMaterials;					//指定设备的材质

        }

        public void Render()		//渲染方法,本方法没有任何渲染代码,可认为是渲染方法的框架
        {
            if (device == null) 			//如果未建立设备对象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            device.BeginScene();			//开始渲染
            SetupMatrices();				//矩阵变换
            mesh.DrawSubset(0);			//显示茶壶,见5.12.6节
            device.EndScene();			//渲染结束
            device.Present();	//更新显示区域,把后备缓存的3D图形送到图形卡的屏幕显示区中显示

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }
        void SetupMatrices()
        {
            device.Transform.World = Matrix.RotationYawPitchRoll(Angle, Angle, 0);//世界变换
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 1.0f, ViewZ),//观察变换矩阵
                    new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH(	//设置投影变换矩阵
                        (float)(Math.PI / 4), 1.33f, 1.0f, 100.0f);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)				//e.KeyCode是键盘每个键的编号
            {
                case Keys.Left:			//Keys.Left是左箭头键编号,茶壶左移
                    Angle += 0.1F;
                    break;
                case Keys.Right:			//茶壶右移
                    Angle -= 0.1F;
                    break;
                case Keys.Down:			//茶壶下移
                    ViewZ += 1;
                    break;
                case Keys.Up:				//茶壶上移
                    ViewZ -= 1;
                    break;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}


建模时创建的3D模型可以多次使用,在渲染前按照3D模型在世界空间中的摆放位置修改为Device类的世界变换矩阵,然后调用3D模型的渲染函数,就可以把3D模型场景中的不同位置。使用Mesh类也可以创建立方体模型,但是立方体模型顶点并不具有纹理坐标,为了给立方体的六个面增加纹理,可以克隆一个新的立方体模型,让这个克隆的立方体模型具有纹理坐标,然后为纹理坐标赋值,在渲染函数中渲染这个克隆的3D模型,就可以实现纹理的效果。利用Mesh类还可以创建3D字体。也可以利用Mesh类对象从.x文件中读入模型,下面给出一个从.x文件读取立体化老虎的例子。立体老虎保存在tiger.x中,纹理保存在tiger.bmp中。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Mesh读取x文件
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        Mesh mesh = null;
        Material meshMaterials;
        Texture[] meshTextures;
        Microsoft.DirectX.Direct3D.Material[] meshMaterials1;
        float Angle = 0, ViewZ = -5.0f;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏显示,在一个窗口显示
                presentParams.SwapEffect = SwapEffect.Discard;		 //后备缓存交换的方式
                presentParams.EnableAutoDepthStencil = true;			 //允许使用自动深度模板测试
                //深度缓冲区单元为16位二进制数
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立设备类对象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //设置设备重置事件(device.DeviceReset)事件函数为this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定义方法,初始化Device的工作放到这个方法中
                this.OnResetDevice(device, null);//调用设备重置事件(device.DeviceReset)事件函数
            }		//设备重置事件函数要设置Device参数,初始函数中必须调用该函数
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            meshMaterials = new Material();
            meshMaterials.Ambient = System.Drawing.Color.White;		//材质如何反射环境光
            meshMaterials.Diffuse = System.Drawing.Color.White;		//材质如何反射灯光
            ExtendedMaterial[] materials = null;
            //下句从tiger.x文件中读入3D图形(立体老虎)
            mesh = Mesh.FromFile(@"..\..\..\tiger.x", MeshFlags.SystemMemory, device, out materials);
            if (meshTextures == null)//如果还未设置纹理,为3D图形增加纹理和材质
            {
                meshTextures = new Texture[materials.Length];//纹理数组
                meshMaterials1 = new Microsoft.DirectX.Direct3D.Material[materials.Length];//材质数组
                for (int i = 0; i < materials.Length; i++)//读入纹理和材质
                {
                    meshMaterials1[i] = materials[i].Material3D;
                    meshMaterials1[i].Ambient = meshMaterials1[i].Diffuse;
                    meshTextures[i] = TextureLoader.FromFile(device,
                                       @"..\..\..\" + materials[i].TextureFilename);
                }
            }

        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.ZBufferEnable = true;		 	//允许使用深度缓冲
            dev.RenderState.Ambient = System.Drawing.Color.White;//设定环境光为白色
            dev.Lights[0].Type = LightType.Directional;  	//设置灯光类型
            dev.Lights[0].Diffuse = Color.White;			//设置灯光颜色
            dev.Lights[0].Direction = new Vector3(0, -1, 0);	//设置灯光位置
            dev.Lights[0].Update();						//更新灯光设置,创建第一盏灯光
            dev.Lights[0].Enabled = true;					//使设置有效
            dev.Material = meshMaterials;					//指定设备的材质

        }

        public void Render()		//渲染方法,本方法没有任何渲染代码,可认为是渲染方法的框架
        {
            if (device == null)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            device.BeginScene();
            SetupMatrices();
            for (int i = 0; i < meshMaterials1.Length; i++)//Mesh中可能有多个3D图形,逐一显示
            {
                device.Material = meshMaterials1[i];//设定3D图形的材质
                device.SetTexture(0, meshTextures[i]);//设定3D图形的纹理
                mesh.DrawSubset(i);//显示该3D图形
            }
            device.EndScene();
            device.Present();

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        void SetupMatrices()
        {
            device.Transform.World = Matrix.RotationY(Angle);//世界变换,下条为观察变换矩阵
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 3.0f, ViewZ),
         new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)(Math.PI / 4),
         1.0f, 1.0f, 100.0f);   //设置投影变换矩阵
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)		//e.KeyCode是键盘每个键的编号
            {
                case Keys.Left:		//Keys.Left是左箭头键编号,老虎左移
                    Angle += 0.1F;
                    break;
                case Keys.Right:		//老虎右移
                    Angle -= 0.1F;
                    break;
                case Keys.Down:		//老虎变小
                    ViewZ += 1;
                    break;
                case Keys.Up:		//老虎变大
                    ViewZ -= 1;
                    break;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}


也可以Mesh类模拟地形图。地形的模拟分为两类,一类是真实地形,另一类是模拟地形。必须使用采集自真实世界的具体数据来构造。要生成地形图,首先在XZ平面上生成一副平面图,然后根据数字高程数据,逐点修改XZ平面上每一点的Y坐标。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace 地形
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        Mesh mesh = null;
        Material[] meshMaterials1;
        Texture[] meshTextures;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏显示,在一个窗口显示
                presentParams.SwapEffect = SwapEffect.Discard;		 //后备缓存交换的方式
                presentParams.EnableAutoDepthStencil = true;			 //允许使用自动深度模板测试
                //深度缓冲区单元为16位二进制数
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立设备类对象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //设置设备重置事件(device.DeviceReset)事件函数为this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定义方法,初始化Device的工作放到这个方法中
                this.OnResetDevice(device, null);//调用设备重置事件(device.DeviceReset)事件函数
            }		//设备重置事件函数要设置Device参数,初始函数中必须调用该函数
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            ExtendedMaterial[] materials = null;
            mesh = Mesh.FromFile(@"..\..\..\seafloor.x",
         MeshFlags.SystemMemory, device, out materials);
            if (meshTextures == null)			//如果还未设置纹理,为D图形增加纹理和材质
            {
                meshTextures = new Texture[materials.Length];				//纹理数组
                meshMaterials1 = new Material[materials.Length];	        //材质数组
                for (int i = 0; i < materials.Length; i++)					//读入纹理和材质
                {
                    meshMaterials1[i] = materials[i].Material3D;
                    meshMaterials1[i].Ambient = meshMaterials1[i].Diffuse;
                    meshTextures[i] = TextureLoader.FromFile(device, @"..\..\..\" +
                                               materials[i].TextureFilename);
                }
            }			//下条语句克隆mesh对象,使其包含位置、法线和纹理坐标
            Mesh mesh1 = mesh.Clone(mesh.Options.Value, VertexFormats.Position | VertexFormats.Normal |
                             VertexFormats.Texture0 | VertexFormats.Texture1, mesh.Device);
            using (VertexBuffer vb = mesh1.VertexBuffer)	//得到mesh1记录顶点的缓冲区引用
            {
                CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])
          vb.Lock(0, typeof(CustomVertex.PositionNormalTextured),
          LockFlags.None, mesh1.NumberVertices);
                try
                {
                    for (int i = 0; i < verts.Length; i++)
                    {
                        verts[i].Y = HeightField(verts[i].X, verts[i].Z);
                    }
                    mesh = mesh1;
                }
                finally
                {
                    vb.Unlock();
                }
            }
        }
        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.ZBufferEnable = true;		 //允许使用深度缓冲,意义见.12.5节
            dev.RenderState.Ambient = Color.FromArgb(255, 200, 200, 200);	     //环境光为黑色 
            dev.RenderState.Lighting = true;
            dev.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
            dev.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
            dev.SamplerState[0].MinFilter = TextureFilter.Linear;
            dev.SamplerState[0].MagFilter = TextureFilter.Linear;
            SetupMatrices();
        }

        public void Render()		//渲染方法,本方法没有任何渲染代码,可认为是渲染方法的框架
        {
            if (device == null) //如果未建立设备对象,退出
                return;
            int iTime = Environment.TickCount % 100000;
            float Angle = iTime * (2.0f * (float)Math.PI) / 100000.0f;
            device.Transform.World = Matrix.RotationY(Angle);
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0f, 0);
            device.BeginScene();//开始渲染
            for (int i = 0; i < meshMaterials1.Length; i++)		//Mesh中可能有多个D图形,逐一显示
            {
                device.Material = meshMaterials1[i];		//设定D图形的材质
                device.SetTexture(0, meshTextures[i]);		//设定D图形的纹理
                mesh.DrawSubset(i);						//显示该D图形
            }
            device.EndScene();//渲染结束
            device.Present();//更新显示区域,把后备缓存的D图形送到显卡的显存中显示
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        private void SetupMatrices()
        {
            device.Transform.World = Matrix.Identity;		//世界坐标
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 30.0f, -100.0f), //观察变换
            new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 200.0f);		//投影变换
        }

        float HeightField(float x, float z)		//参数为图形某点的X、Z轴坐标
        {
            float y = 0.0f;
            y += (float)(10.0f * Math.Cos(0.051f * x + 0.0f) * Math.Sin(0.055f * x + 0.0f));
            y += (float)(10.0f * Math.Cos(0.053f * z + 0.0f) * Math.Sin(0.057f * z + 0.0f));
            y += (float)(2.0f * Math.Cos(0.101f * x + 0.0f) * Math.Sin(0.105f * x + 0.0f));
            y += (float)(2.0f * Math.Cos(0.103f * z + 0.0f) * Math.Sin(0.107f * z + 0.0f));
            y += (float)(2.0f * Math.Cos(0.251f * x + 0.0f) * Math.Sin(0.255f * x + 0.0f));
            y += (float)(2.0f * Math.Cos(0.253f * z + 0.0f) * Math.Sin(0.257f * z + 0.0f));
            return y;		//返回修改后的Y轴方向上的坐标
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}


当观察者距离物体较远时,3D物体需要较少的细节,也就是说这个3D物体所需的顶点数和面数应该较少。使用Direct 3D中的ProgressiveMesh类可以解决这个问题。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;

namespace 层次细节Mesh
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        Mesh mesh = null;
        Material meshMaterials;
        Texture[] meshTextures;
        Microsoft.DirectX.Direct3D.Material[] meshMaterials1;
        float Angle = 0, ViewZ = -5.0f;
        Mesh mesh1 = null;
        int key;
        ProgressiveMesh mesh2;


        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏显示,在一个窗口显示
                presentParams.SwapEffect = SwapEffect.Discard;		 //后备缓存交换的方式
                presentParams.EnableAutoDepthStencil = true;			 //允许使用自动深度模板测试
                //深度缓冲区单元为16位二进制数
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立设备类对象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //设置设备重置事件(device.DeviceReset)事件函数为this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定义方法,初始化Device的工作放到这个方法中
                this.OnResetDevice(device, null);//调用设备重置事件(device.DeviceReset)事件函数
            }		//设备重置事件函数要设置Device参数,初始函数中必须调用该函数
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            ExtendedMaterial[] materials = null;
            //设定运行程序所在目录的上两级目录为当前默认目录
            Directory.SetCurrentDirectory(Application.StartupPath + @"\..\..\..\");
            //下句从tiger.x文件中读入3D图形(立体老虎)
            GraphicsStream adjacency;
            mesh = Mesh.FromFile("tiger.x", MeshFlags.Managed, device, out adjacency, out materials);
            if (meshTextures == null)			//如果还未设置纹理,为3D图形增加纹理和材质
            {
                meshTextures = new Texture[materials.Length];				//纹理数组
                meshMaterials1 = new Material[materials.Length];	//材质数组
                for (int i = 0; i < materials.Length; i++)					//读入纹理和材质
                {
                    meshMaterials1[i] = materials[i].Material3D;
                    meshMaterials1[i].Ambient = meshMaterials1[i].Diffuse;
                    meshTextures[i] = TextureLoader.FromFile(device,
                                        materials[i].TextureFilename);
                }
            }	//下边首先清理Mesh,然后简化Mesh

            mesh1 = Mesh.Clean(CleanType.Simplification, mesh, adjacency, adjacency);
            mesh2 = new ProgressiveMesh(mesh1, adjacency, null, 1, MeshFlags.SimplifyVertex);

            mesh2.NumberVertices = 1000;
            mesh2.NumberFaces = 1000;
        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.ZBufferEnable = true;						//允许深度缓冲
            dev.RenderState.Ambient = System.Drawing.Color.White;
            dev.RenderState.FillMode = FillMode.WireFrame;	  //只显示3D图形顶点之间的连线


        }

        public void Render()		//渲染方法,本方法没有任何渲染代码,可认为是渲染方法的框架
        {
            if (device == null)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            device.BeginScene();
            SetupMatrices();
            for (int i = 0; i < meshMaterials1.Length; i++)		//Mesh中可能有多个3D图形,逐一显示
            {
                device.Material = meshMaterials1[i];		//设定3D图形的材质
                device.SetTexture(0, meshTextures[i]);	//设定3D图形的纹理
                mesh2.DrawSubset(i);					//显示该3D图形          
            }
            device.EndScene();
            device.Present();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        void SetupMatrices()
        {
            device.Transform.World = Matrix.RotationY(Angle);//世界变换,下条为观察变换矩阵
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 3.0f, ViewZ),
         new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)(Math.PI / 4),
         1.0f, 1.0f, 100.0f);   //设置投影变换矩阵
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)				//e.KeyCode是键盘每个键的编号
            {
                case Keys.Left:			//Keys.Left是左箭头键编号,老虎顺时针转动
                    Angle += 0.1F;
                    break;
                case Keys.Right:			//老虎逆时针转动
                    Angle -= 0.1F;
                    break;
                case Keys.Down:			//老虎变近
                    ViewZ += 1;
                    break;
                case Keys.Up:				//老虎变远
                    ViewZ -= 1;
                    break;
                case Keys.D0:				//使用未优化Mesh
                    mesh2.NumberVertices = 1000;
                    mesh2.NumberFaces = 1000;
                    break;
                case Keys.D1:				//使用优化Mesh
                    mesh2.NumberVertices = 100;
                    mesh2.NumberFaces = 100;
                    break;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}


P.S.这里给出光照的另外一个例子,加载DirectX下面的一个.x模型的例子,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;

namespace 光照立方体
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        VertexBuffer vertexBuffer = null;
        Material mtrl;
        Mesh mesh = null;
        float Angle = 0, ViewZ = -6.0f;

        //额外对象
        private List<Material[]> m_meshMaterials = new List<Material[]>(); //定义网格材质对象
        private List<Texture[]> m_meshTextures = new List<Texture[]>(); // 定义网格贴图对象
        private List<Mesh> m_meshLst = new List<Mesh>();


        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏显示,在一个窗口显示
                presentParams.SwapEffect = SwapEffect.Discard;		 //后备缓存交换的方式
                presentParams.EnableAutoDepthStencil = true;			 //允许使用自动深度模板测试
                //深度缓冲区单元为16位二进制数
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立设备类对象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                
               
                //设置设备重置事件(device.DeviceReset)事件函数为this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定义方法,初始化Device的工作放到这个方法中
                this.OnResetDevice(device, null);//调用设备重置事件(device.DeviceReset)事件函数
            }		//设备重置事件函数要设置Device参数,初始函数中必须调用该函数
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }
        //添加网格
        public long AddMesh(string filePath)
        {
            if (device == null)
                return 0;

            if (File.Exists(filePath) == false)
                return 0;
            //加载顶点集合
            ExtendedMaterial[] materials = null;
            Mesh meshObj = Mesh.FromFile(filePath, MeshFlags.SystemMemory, device, out materials);
            if (meshObj == null)
                return 0;

            //加载纹理和材质
            Texture[] meshTextures = new Texture[materials.Length];
            Material[] meshMaterials = new Material[materials.Length];
            for (int i = 0; i < materials.Length; i++)
            {
                meshMaterials[i] = materials[i].Material3D;
                meshMaterials[i].Ambient = meshMaterials[i].Diffuse;
                // 创建贴图
                if (materials[i].TextureFilename != null)
                    meshTextures[i] = TextureLoader.FromFile(device,
                        filePath.Substring(0, filePath.LastIndexOf('\\')) +
                    "\\" + materials[i].TextureFilename);
                else
                    meshTextures[i] = null;
            }

            //加入缓冲
            m_meshMaterials.Add(meshMaterials);
            m_meshTextures.Add(meshTextures);
            m_meshLst.Add(meshObj);
            return m_meshLst.Count;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;		//注意阴影部分,正方形有6个顶点
            vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormal), 6,
            dev, 0, CustomVertex.PositionNormal.Format, Pool.Default);
            vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
            this.OnCreateVertexBuffer(vertexBuffer, null);
            mtrl = new Material();
            mtrl.Diffuse = System.Drawing.Color.Yellow;		//物体的颜色
            mtrl.Ambient = System.Drawing.Color.Red;			//反射环境光的颜色 
            //mesh = Mesh.FromFile(@"..\..\..\Dwarf.x", MeshFlags.SystemMemory, device);
            AddMesh(@"D:\\Microsoft DirectX SDK (June 2010)\\Samples\\Media\\Dwarf\\Dwarf.x");
        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.CullMode = Cull.CounterClockwise;		//背面剔除
            device.RenderState.ZBufferEnable = true;				//打开Z缓冲
            device.RenderState.Lighting = true;					//打开灯光
            mtrl = new Material();
            mtrl.Diffuse = System.Drawing.Color.Yellow;			//物体的颜色
            mtrl.Ambient = System.Drawing.Color.Red;				//反射环境光的颜色
            SetupLights();
            Render();
        }

        public void Render()		//渲染方法,本方法没有任何渲染代码,可认为是渲染方法的框架
        {
            if (device == null) //如果未建立设备对象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            device.BeginScene();		//开始渲染
             SetupMatrices();
//             device.SetStreamSource(0, vertexBuffer, 0);
//             device.VertexFormat = CustomVertex.PositionNormal.Format;
//             device.Transform.World = Matrix.Translation(0, 0, -1);
//             //以下和6.6节例子渲染方法Render中内容相同
//             device.Transform.World = Matrix.Translation(0, 0, -1);//沿Z轴向观察者方向移动1个单位
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);    //绘制正前面
//             //旋转180度是为了从外侧看,按顺时针方向绘制三角形,因背面剔除打开,内侧不被看到
//             device.Transform.World = Matrix.RotationY((float)Math.PI) * Matrix.Translation(0, 0, 1);
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);    //绘制正后面
//             device.Transform.World =
//             Matrix.RotationY(-(float)Math.PI / 2) * Matrix.Translation(1, 0, 0);
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);		//绘制右侧面
//             device.Transform.World =
//         Matrix.RotationY((float)Math.PI / 2) * Matrix.Translation(-1, 0, 0);
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);		//绘制左侧面
//             device.Transform.World =
//         Matrix.RotationX((float)Math.PI / 2) * Matrix.Translation(0, 1, 0);
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);		//绘制下面
//             device.Transform.World =
//         Matrix.RotationX(-(float)Math.PI / 2) * Matrix.Translation(0, -1, 0);
//             device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);   	//绘制上面


            //渲染Mesh
            for (int i = 0; i < m_meshLst.Count; i++)
            {
                for (int j = 0; j < m_meshMaterials[i].Length; j++)
                {
                    //                         m_device.Transform.World = Matrix.Scaling(0.2f, 0.2f, 0.2f) * 
                    //                             Matrix.RotationX((float)Math.PI / 2) * 
                    //                             Matrix.Translation(300, 100, 200);

                    //设置网格子集的材质和贴图
                    device.Material = m_meshMaterials[i][j];
                    device.SetTexture(0, m_meshTextures[i][j]);
                    //绘制网格子集
                    m_meshLst[i].DrawSubset(j);
                }
            }



            device.EndScene();										//渲染结束
            device.Present();	//更新显示区域,把后备缓存的D图形送到图形卡的显存中显示

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        public void OnCreateVertexBuffer(object sender, EventArgs e)
        {
            CustomVertex.PositionNormal[] verts =
                            (CustomVertex.PositionNormal[])vertexBuffer.Lock(0, 0);
            verts[0].Position = new Vector3(-1.0f, -1.0f, 0.0f); //顶点0位置,注意为Vector3
            verts[0].Normal = new Vector3(0, 0, -1);    	  			  //顶点0法线
            verts[1].Position = new Vector3(1.0f, 1.0f, 0.0f);	  	  //顶点1位置
            verts[1].Normal = new Vector3(0, 0, -1);					  //顶点1法线
            verts[2].Position = new Vector3(1.0f, -1.0f, 0.0f);	      //顶点2位置
            verts[2].Normal = new Vector3(0, 0, -1);
            verts[3].Position = new Vector3(-1.0f, -1.0f, 0.0f);	  //顶点3位置
            verts[3].Normal = new Vector3(0, 0, -1);    	  			  //顶点3法线
            verts[4].Position = new Vector3(-1.0f, 1.0f, 0.0f);	  	  //顶点4位置
            verts[4].Normal = new Vector3(0, 0, -1);
            verts[5].Position = new Vector3(1.0f, 1.0f, 0.0f);	      //顶点5位置
            verts[5].Normal = new Vector3(0, 0, -1);
            vertexBuffer.Unlock();
        }

        private void SetupMatrices()		//注意世界变换和观察变换参数可能要改变
        {
            device.Transform.World = Matrix.RotationY(0);	//世界变换矩阵
            Vector3 v1 = new Vector3(0.0f, 0.0f, -5.0f);		//下句使v1点分别沿Y轴和X轴旋转
            v1.TransformCoordinate(Matrix.RotationYawPitchRoll(Angle, ViewZ, 0));
//             device.Transform.View = Matrix.LookAtLH(v1, new Vector3(0.0f, 0.0f, 0.0f),
//             new Vector3(0.0f, 1.0f, 0.0f));	//观察变换矩阵
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f,-5.0f), 
                new Vector3(0.0f, 0.0f, 0.0f),
            new Vector3(0.0f, 1.0f, 0.0f));	//观察变换矩阵
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
                            (float)this.Width/(float)this.Height, 1.0f, 100.0f);			//投影变换矩阵
        }//需要实时计算(float)this.Width/(float)this.Height

        private void SetupLights()
        {
            device.Material = mtrl;
            device.Lights[0].Type = LightType.Directional;
            device.Lights[0].Diffuse = System.Drawing.Color.White;	//光的颜色为白色
            device.Lights[0].Direction = new Vector3(0, -2, 4);//灯光方向从观察者上方指向屏幕下方
            device.Lights[0].Update();			//更新灯光设置,创建第一盏灯光
            device.Lights[0].Enabled = true;		//使设置有效,下句设置环境光为白色
            device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x808080);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)				//e.KeyCode是键盘每个键的编号
            {
                case Keys.Left:			//Keys.Left是左箭头键编号,三角形沿Y轴左转
                    Angle += 0.1F;
                    break;
                case Keys.Right:			//三角形沿Y轴右转
                    Angle -= 0.1F;
                    break;
                case Keys.Down:			//三角形离观察者越来越远
                    ViewZ += 0.1F;
                    break;
                case Keys.Up:				//三角形离观察者越来越近
                    ViewZ -= 0.1F;
                    break;
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值