欢迎光临
我们一直在努力

DirectX9 3D 快速上手 4-.NET教程,报表/图形/Office

建站超值云服务器,限时71元/月

接下来我们要使用mesh读入.x文件,关于.x文件,其实可以说很多,我们可以用外部的工具例如3ds max来建立.3ds文件,然后利用微软提供给我们的工具转换成.x文件,如果你同时会用3ds你也许会问,那材质怎么办? 你不用担心,.x文件能自动的包含材质,和动画,所以利用mesh我们可以方便的八我们在3ds max的做品用在游戏中。

.x文件允许自定义的扩展,当然这个我们在以后的内容也会讲到,我们先看怎么使用,顺便提一句,还有一种用得比较多的文件格式.md3格式的文件,也就是quake3使用的文件,如果有机会我也会讲到。

关于3ds文件和.x转换可以参看gameres网站的文章http://www.gameres.com/articles/program/visual/3d/3dinapp.htm

 

接下来的过程简单的让你无法相信,请看:

        private mesh mesh = null; //建立mesh对象

        private material[] meshmaterials;  //用于保存材质

        private texture[] meshtextures;   //用于保存纹理

        private void loadmesh(string file)

        {

            extendedmaterial[] mtrl; //保存mesh子集信息,保存material信息

            // 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);

                    }

                }

            }

        }

如果你觉得这里代码比较混乱,没有关系,我们来理一理,首先要说的是mesh类还有两个主要的静态方法可以加载外部模型。这两个方法分别是mesh.formfile和mesh.fromstream。两个方法本质上来说都是一样的,stream方法有更多的重载以适应不同大小的流。mesh.formfile最简单,我们就先只介绍这个,这个方法有很多重载的版本,我们用的是参数最多的一个,这样其他的也都好理解了:

public static mesh fromfile(
    string filename, //文件名
    meshflags options,// 控制着去哪里以及如何加载数据
    device device,// 渲染mesh的device
    out graphicsstream adjacency,//保存每个面相邻的3个面
    out extendedmaterial materials,// 保存了普通的direct3d材质和一个加载为纹理的字符串,常是使用的纹理或资源文件名
    out effectinstance effects //描述了用于mesh的hlsl材质文件和值。
);

我们使用的是一个有4参数的方法:

public static mesh fromfile(
    string filename,
    meshflags options,
    device device,
    out extendedmaterial materials
);

接下来,如果读入的这个.x文件有材质或者纹理,就根据材质和纹理的大小建立数组以保存这些纹理和材质。因为mesh中可能有许多不同的子集,所以需要分别创建一个材质和纹理的数组以满足每一个子集的需要。mesh会自动地把每一个子集和这些子集的材质纹理一一对座。

这样我们就完成了一个loadmesh函数,这个函数我们可以用在以后任何需要读入.x文件的地方,十分的方便。

下面我们来看看我们的成果,当然我们还需要在绘图的地方加几句:

            for (int i = 0; i < meshmaterials.length; i++)

            {

                device.material = meshmaterials[i];// 把保存的材质赋予device;

                device.settexture(0, meshtextures[i]);// 把纹理赋予device,如果没有就为null

                mesh.drawsubset(i);// 根据子集的id调用drawsubset方法

            }

好了,现在我们可以在以往的框架的基础上编译一下了,我们可以看到已经读入了一个.x文件,不管怎么样 都是值得庆贺的。我们再看看sdk tutorial6的例子后,发现这个程序的结果可以旋转,其实也很好实现,我们只需要设置一下旋转矩阵就可以了,就像上一张我们讲的那样,在上面那段for前面加上一句就可以了:

device.transform.world = matrix.rotationyawpitchroll(yaw, pitch, roll) * matrix.translation(x, y, z);

好了这样我们也就达到目的了,你也可以随自己的意思设置变换矩阵,很cool吧?

好了,下面是完整的代码,如果大家有什么意见,发到我的blog上吧。大家一起进步。

 

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 chapter5code

{

     /// <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;

 

         /// <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”);

        }

 

        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.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.cornflowerblue, 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;

 

            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]);

                mesh.drawsubset(i);

            }

        }

 

        /// <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);

            }

        }

     }

}

其实我们都已经发现,到目前为止我们的程序都是遵循一个固定的框架,有时候你发现程序很长,其实从框架角度来看,就没那么长了,怕看长代码的人可以注意一下,同时很多代码都是通用的。下次学习怎么操控mesh。

by sssa2000

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » DirectX9 3D 快速上手 4-.NET教程,报表/图形/Office
分享到: 更多 (0)