DirectX9 3D 快速上手 7

这里我想继续写点和Mesh有关的东西,毕竟我们可能还需要对它有很多别的要求。在3D游戏的实际运用中,一般来说都是运用低多边形模型,简称低模。这样才能有更加好的速度来运行游戏,恰好DX中有提供给我们这样的函数让我们来控制读入的Mesh的复杂程度。

public void WeldVertices (

Microsoft.DirectX.Direct3D.WeldEpsilonsFlags flags ,//标志

    Microsoft.DirectX.Direct3D.WeldEpsilons epsilons ,

    Microsoft.DirectX.Direct3D.GraphicsStream adjacencyIn ,

    Microsoft.DirectX.Direct3D.GraphicsStream adjacencyOut ,

    out int[] faceRemap ,

    Microsoft.DirectX.Direct3D.GraphicsStream vertexRemap )

这个方法能实现简化模型的目的,前2个参数用来确定怎么简化模型,

第一个标志一共包括以下几个:

Member

Value

Description

DoNotSplit

8

Instructs the weld to allow vertices to be modified only, not removed. This flag is valid only if WeldPartialMatches is set. It is useful to modify vertices so that they are equal, but not to allow vertices to be removed.

只有当WeldPartialMatches参数指定时才能生效,不允许分离定点

DoNotRemoveVertices

4

Instructs the weld to allow vertices to be modified only, not removed. This flag is valid only if WeldPartialMatches is set. It is useful to modify vertices to be equal, but not to allow vertices to be removed.

只有当WeldPartialMatches参数指定时才能生效,不能移除定点,只能修改

WeldPartialMatches

2

If a given vertex component is within epsilon, instructs the weld to modify partially matched vertices so that both components are equal. If all components are equal, one of the vertices is removed.

修改符合在WeldEpsilons结构中给定的顶点的条件

WeldAll

1

Welds all vertices that are marked by adjacency as being overlapping.

焊接所有的adjacency指定的定点

例如我们可以这样简单的调用这个方法

mesh.WeldVertices(WeldEpsilonsFlags.WeldAll, new WeldEpsilons(), null, null);

当然 前提是你必须在这之前对变量mesh进行付值。

到程序里面看看,效果还是不错的,已经简化了很多顶点。

 

或许你还觉得不够简化,没关系这里我们还可以把复杂的模型拆成小块,用下面这个函数:

public static Microsoft.DirectX.Direct3D.Mesh[]
Split
(

Mesh mesh , //要拆分的mesh

int[] adjacencyIn ,

System.Int32 maxSize ,// 拆分后新的Mesh的最大顶点数量

MeshFlags options , //标志

    out GraphicsStream adjacencyArrayOut , //这三个out 参数返回新mesh的一些信息

    out GraphicsStream faceRemapArrayOut ,

    out GraphicsStream vertRemapArrayOut )

 

我们也可以使用简单的重载版本的函数。

在拆分前,我们需要建立保存拆分后的各个mesh的容器,数组不错。

我们这么写:

Mesh  splitmeshes[]=meshes = Mesh.Split(mesh, null, 500, mesh.Options.Value);

 

这样我们就把mesh根据顶点的树木分成了很多个部分

在我们这个事例程序里面,通过控制对数组的遍历来实现对所有拆分出来的mesh的遍历。

完整代码如下:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

 

namespace Chapter7Code

{

     /// <summary>

     /// Summary description for Form1.

     /// </summary>

     public class Form1 : System.Windows.Forms.Form

     {

        private Device device = null;

        private Mesh mesh = null;

        private Material[] meshMaterials;

        private Texture[] meshTextures;

 

        // Split information

        private Mesh[] meshes = null;

        private bool drawSplit = false;

        private bool drawAllSplit = false;

        private int index = 0;

        private int lastIndexTick = System.Environment.TickCount;

 

        /// <summary>

         /// Required designer variable.

         /// </summary>

         private System.ComponentModel.Container components = null;

        private float angle = 0.0f;

 

         public Form1()

         {

              //

              // Required for Windows Form Designer support

              //

              InitializeComponent();

 

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

         }

 

        /// <summary>

        /// We will initialize our graphics device here

        /// </summary>

        public void InitializeGraphics()

        {

            // Set our presentation parameters

            PresentParameters presentParams = new PresentParameters();

 

            presentParams.Windowed = true;

            presentParams.SwapEffect = SwapEffect.Discard;

            presentParams.AutoDepthStencilFormat = DepthFormat.D16;

            presentParams.EnableAutoDepthStencil = true;

 

            // Create our device

            device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);

 

            // Load our mesh

            LoadMesh(@"..\..\tiny.x");

 

            meshes = Mesh.Split(mesh, null, 10, mesh.Options.Value);

        }

 

        private void LoadMesh(string file)

        {

            ExtendedMaterial[] mtrl;

 

            // Load our mesh

            mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

 

            // If we have any materials, store them

            if ((mtrl != null) && (mtrl.Length > 0))

            {

                meshMaterials = new Material[mtrl.Length];

                meshTextures = new Texture[mtrl.Length];

 

                // Store each material and texture

                for (int i = 0; i < mtrl.Length; i++)

                {

                    meshMaterials[i] = mtrl[i].Material3D;

                    if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))

                    {

                        // We have a texture, try to load it

                        meshTextures[i] = TextureLoader.FromFile(device, @"..\..\" + mtrl[i].TextureFilename);

                    }

                }

            }

        }

 

        private void SetupCamera()

        {

            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 10000.0f);

            device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, 580.0f), new Vector3(), new Vector3(0,1,0));

            //device.RenderState.FillMode = FillMode.WireFrame;

            device.RenderState.Ambient = Color.DarkBlue;

            device.Lights[0].Type = LightType.Directional;

            device.Lights[0].Diffuse = Color.White;

            device.Lights[0].Direction = new Vector3(0, -1, -1);

            device.Lights[0].Update();

            device.Lights[0].Enabled = true;

 

        }

 

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

        {

            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);

 

            SetupCamera();

 

            device.BeginScene();

 

            // Draw our Mesh

            DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f, angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f);

 

            device.EndScene();

 

            device.Present();

 

            this.Invalidate();

        }

 

        private void DrawMesh(float yaw, float pitch, float roll, float x, float y, float z)

        {

            angle += 0.01f;

 

        if ((System.Environment.TickCount - lastIndexTick) > 500)

        {

            index++;

            if (index >= meshes.Length)

                index = 0;

 

            lastIndexTick = System.Environment.TickCount;

        }

        device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, roll) * Matrix.Translation(x, y, z);

        for (int i = 0; i < meshMaterials.Length; i++)

        {

            device.Material = meshMaterials[i];

            device.SetTexture(0, meshTextures[i]);

            if (drawSplit)

            {

                if (drawAllSplit)

                {

                    foreach(Mesh m in meshes)

                        m.DrawSubset(i);

                }

                else

                {

                    meshes[index].DrawSubset(i);

                }

            }

            else

            {

                mesh.DrawSubset(i);

            }

        }

        }

        protected override void OnKeyPress(KeyPressEventArgs e)

        {

            if (e.KeyChar == ' ')

            {

                drawSplit = !drawSplit;

            }

            else if (e.KeyChar == 'm')

            {

                drawAllSplit = !drawAllSplit;

            }

        }

 

        /// <summary>

         /// Clean up any resources being used.

         /// </summary>

         protected override void Dispose( bool disposing )

         {

              if( disposing )

              {

                   if (components != null)

                   {

                       components.Dispose();

                   }

              }

              base.Dispose( disposing );

         }

 

         #region Windows Form Designer generated code

         /// <summary>

         /// Required method for Designer support - do not modify

         /// the contents of this method with the code editor.

         /// </summary>

         private void InitializeComponent()

         {

              this.components = new System.ComponentModel.Container();

              this.Size = new Size(800,600);

              this.Text = "Form1";

         }

         #endregion

 

         /// <summary>

         /// The main entry point for the application.

         /// </summary>

        static void
Main
()

        {

            using (Form1 frm = new Form1())

            {

                // Show our form and initialize our graphics engine

                frm.Show();

                frm.InitializeGraphics();

                Application.Run(frm);

            }

        }

     }

}

当然我们这里并不能任意的控制模型的细节程度,明天要期中答辩,突然发现自己的周记没写完,所以今天先草草结束,细节控制的下一次我们再讲吧。

 

时间: 2024-10-27 19:31:45

DirectX9 3D 快速上手 7的相关文章

DirectX9 3D 快速上手 5

DirectX9 3D 快速上手  5By sssa2000     这一章的内容相对很简单,控制Mesh的移动,旋转等等,其实这一切都是在对矩阵进行操作.在 DX中,用到的变换有3种,一种是基于Word坐标系的,一种是基于View坐标系的,还有一种是基于投影的变换.而这些变换都是通过矩阵的运算来实现的,在.Net的托管环境下,实现这些操作相对于非托管来说简单一写,不用对矩阵的每个值运算. 关于矩阵的运算和变换的关系,很多文章都有分析,GameRes也有很多这样的好文章,例如:http://de

DirectX9 3D快速上手 3

DirectX9 3D快速上手 3 By sssa2000 4/15/2005 我们这里暂时先跳过,乏味的索引缓冲和深度缓冲的内容,先看看怎么在3D空间中实现一个东西,给自己来点成就感. 正好SDK的向导也是这么安排的,呵呵,那我们就继续从向导出发吧,以Tutorial 3为例子. 这个例子主要讲解运用变换矩阵来实现物体的变换,学过图形学或者线性代数的肯定就很容易理解,没学过的,找点这方面的资料看看就可以了. 先看看这个例子实现了什么,编译运行,噢,相比前面两个例子,有耳目一新的感觉,一个三角形

DirectX9 3D 快速上手 4

接下来我们要使用Mesh读入.X文件,关于.X文件,其实可以说很多,我们可以用外部的工具例如3DS MAX来建立.3ds文件,然后利用微软提供给我们的工具转换成.X文件,如果你同时会用3DS你也许会问,那材质怎么办? 你不用担心,.X文件能自动的包含材质,和动画,所以利用Mesh我们可以方便的八我们在3DS MAX的做品用在游戏中. .X文件允许自定义的扩展,当然这个我们在以后的内容也会讲到,我们先看怎么使用,顺便提一句,还有一种用得比较多的文件格式.Md3格式的文件,也就是Quake3使用的文

DirectX9 3D 快速上手 6

讲了很多,最基础的部分就剩下纹理没有讲到了.Texture是Directx里面非常重要的一部分.为了简便起见,我们还是以SDK的Tutorial5为例子. 纹理就像一张墙纸,用来贴在物体的表面,当然,如果足够大,贴一次就能覆盖整个物体的表面,也可以用适当的方法让纹理排列成你要的效果. 来看看纹理的比较重要的函数:Device.SetTexture public void SetTexture(    int stage, //纹理混合阶段序号,从0开始    BaseTexture textur

DirectX9 3D 快速上手 8

 上一次中途结束了本来应该讲到的控制Mesh的细节程度的方法的,这一次补上.我们这里使用的是简单的方法,并没有涉及到场景剔出等等复杂的方法,我这里主要还是用DX9提供给我们的类库,progressive meshe.progressive meshes主要的优点就是允许我们控制顶点和面的数目,这样我们就可以灵活的控制mesh细节的显示程度.和Mesh一样,progressive meshe也都是继承自BaseMesh这个类.比较重要的属性主要有2个NumberFaces和NumberVertic

19条小技巧让你快速上手Ubuntu 11.04

Ubuntu 11.04在4月底正式发布了,新版本首次采用Unity界面,很多操作和GNOME都不相同,也许你在使用过程中会出现手足无措,不过新鲜事物总是要花费一段时间适应,之后你会发现Ubuntu 11.04还是很不错的. 下面我们为大家收集了19个小技巧,能让你快速上手Ubuntu 11.04,新手们不妨看看: 1.不喜欢Unity?切换到Ubuntu GNOME经典桌面 注销unity桌面环境,然后选择登录环境为"经典桌面"即可进入. 若是你喜欢Unity,可是你的显卡不给力3D

Win8强大兼容性无需适应快速上手

  如果说使用Win7是在一个我们熟悉的环境中操作,那么Win8就是给我们带来了两个激动人心的环境,一个是新颖的"开始"屏幕及它的应用生态,还有一个就是我们熟悉的跟Win7一样的桌面系统.这也就意味着Win8具有很强的兼容性,可以毫不费力地运行Win7的程序,轻松上手无压力. 其实一个操作系统做到Windows这样,基本也不用太多的在意兼容性问题了.作为一个使用最广泛的操作系统,任何软件厂商都会千方百计地向其靠拢,以便能在新系统上运行它们的程序,这是一个向上兼容的过程. Win8不仅仅

Eclipse快速上手Hibernate--4. 继承映射(3)

继承     前两篇文章<Eclipse快速上手Hibernate--4. 继承映射(1) >和<继承映射(2)>中已经谈了每个类层次结构一个表(table per class hierarchy)与每个子类一个表(table per subclass)的策略,这篇文章主要说的是每个具体类一个表(table per concrete class).一些重复的部分这里就不说了,请参考前两篇文章.    这个策略很简单,抽象的基类不参与映射,具体子类参与映射.  1. 创建项目 · 

Eclipse快速上手Hibernate--4. 继承映射(1)

继承    前面的<Eclipse快速上手Hibernate--1. 入门实例 >等三篇文章已经谈了Hibernate的入门以及利用工具创建的方法.这篇文章主要说说在Hibernate中的继承映射.相关配置请参考前三篇文章.    如果程序中的对象含有继承的关系,在Hibernate中有以下三种策略将这种关系映射到数据表上:· 每个类层次结构一个表(table per class hierarchy)· 每个子类一个表(table per subclass) · 每个具体类一个表(table