DirectX 3D Mesh类

来源:互联网 发布:山西省软件开发企业 编辑:程序博客网 时间:2024/04/30 12:08

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();        }    }}



1 0
原创粉丝点击