国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

DirectX9 3D 快速上手 8

2024-07-21 02:15:55
字體:
來源:轉載
供稿:網友


 
上一次中途結束了本來應該講到的控制mesh的細節程度的方法的,這一次補上。
我們這里使用的是簡單的方法,并沒有涉及到場景剔出等等復雜的方法,我這里主要還是用dx9提供給我們的類庫,progressive meshe。
progressive meshes主要的優點就是允許我們控制頂點和面的數目,這樣我們就可以靈活的控制mesh細節的顯示程度。
和mesh一樣,progressive meshe也都是繼承自basemesh這個類。比較重要的屬性主要有2個numberfaces和numbervertices。從字面我們就可以看出兩個屬性的含義。
有了前面的基礎在使用progressive mesh上也變得十分的簡單,首先我們需要聲明一個progressive mesh的變量,然后我們看看progressive mesh的構造函數:
public progressivemesh(
    mesh mesh,
    graphicsstream adjacency,
    graphicsstream vertexweights, //頂點的權值,越高越不容易被剔出,如果設為null就全部被設為1
    int minvalue, //設定被簡化的最小值
    meshflags options
);
以下就是核心的代碼:
private void loadmesh(string file)
{
    extendedmaterial[] mtrl;
    graphicsstream adj;
 
    // load our mesh
    using(mesh mesh = mesh.fromfile(file, meshflags.managed, device,
                out adj, 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);
                }
            }
        }
 
        // clean our main mesh
        using(mesh tempmesh = mesh.clean(mesh, adj, adj))
        {
            // create our progressive mesh
            progressivemesh = new progressivemesh(tempmesh, adj,
                null, 1, meshflags.simplifyvertex);
 
            // set the initial mesh to the max
            progressivemesh.numberfaces = progressivemesh.maxfaces;
            progressivemesh.numbervertices = progressivemesh.maxvertices;
        }
    }
}
其實這里大部分代碼和前面的關于mesh那一節的代碼差不多,關于progressivemesh,微軟的sdk也有一個例子,不過那個例子太過于龐大,大部分都是在處理ui方面,真正涉及到progressivemesh的部分還是很少的。
以下是代碼的事例圖和完整代碼:

 

這個例子里可以切換線框渲染模式和實體作色模式。
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 progressivemesh
{
     /// <summary>
     /// summary description for form1.
     /// </summary>
     public class form1 : system.windows.forms.form
     {
        private device device = null;
        private progressivemesh progressivemesh = null;
        private material[] meshmaterials;
        private texture[] meshtextures;


 
        private microsoft.directx.direct3d.font font = null;
        private float camerapos = 8.0f;
        private const int moveamount = 2;


 
        /// <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(@"../.. printracer.x");


 
            // create our font
            font = new microsoft.directx.direct3d.font(device, new system.drawing.font
                ("arial", 14.0f, fontstyle.bold | fontstyle.italic));
        }


 
        private void loadmesh(string file)
        {
            extendedmaterial[] mtrl;
            graphicsstream adj;


 
            // load our mesh
            using(mesh mesh = mesh.fromfile(file, meshflags.managed, device,
                        out adj, 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);
                        }
                    }
                }


 
                // clean our main mesh
                using(mesh tempmesh = mesh.clean(cleantype.simplification ,mesh, adj, adj))
                {
                    // create our progressive mesh
                    progressivemesh = new progressivemesh(tempmesh, adj,
                        null, 1, meshflags.simplifyvertex);


 
                    // set the initial mesh to the max
                    progressivemesh.numberfaces = progressivemesh.maxfaces;
                    progressivemesh.numbervertices = progressivemesh.maxvertices;
                }
            }
        }


 
        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, camerapos),
                new vector3(), new vector3(0,1,0));


 
            device.renderstate.ambient = color.blue;
            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.blue , 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);


 
            font.drawtext(null, string.format("number vertices in mesh: {0}",
                ((basemesh)progressivemesh).numbervertices), new rectangle(10, 10, 0, 0),
                drawtextformat.noclip, color.blanchedalmond);


 
            font.drawtext(null, string.format("number faces in mesh: {0}",
                ((basemesh)progressivemesh).numberfaces), new rectangle(10, 30, 0, 0),
                drawtextformat.noclip, color.blanchedalmond);


 
            device.endscene();


 
            device.present();


 
            this.invalidate();
        }


 
        private void drawmesh(float yaw, float pitch, float roll, float x, float y, float z)
        {
            angle += 0.11f;


 
            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]);
                progressivemesh.drawsubset(i);
            }
        }
        protected override void onkeypress(keypresseventargs e)
        {
            if (e.keychar == '+')
            {
                camerapos += (moveamount * 2);
                progressivemesh.numbervertices =
                    ((basemesh)progressivemesh).numbervertices - moveamount;


 
                progressivemesh.numberfaces =
                    ((basemesh)progressivemesh).numberfaces - moveamount;
            }
            if (e.keychar == '-')
            {
                camerapos -= (moveamount * 2);
                progressivemesh.numbervertices =
                    ((basemesh)progressivemesh).numbervertices + moveamount;


 
                progressivemesh.numberfaces =
                    ((basemesh)progressivemesh).numberfaces + moveamount;
            }
            if (e.keychar == 'w')
                device.renderstate.fillmode = fillmode.wireframe;


 
            if (e.keychar == 's')
                device.renderstate.fillmode = fillmode.solid;
        }


 
        /// <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);
            }
        }
     }
}
 
這里我們已經實現了能自由控制顯示的細節問題,通過progressivemesh 我們可以很方便的完成這一點,接下來,順著這個話題我們來討論一下如何增加細節的顯示程度,也就是說我們將要把讀入的mesh的細節程度增多。這里我們部探討原理,因為我數學也是很差,我們可以借助patch meshes 來實現。
patch meshes通過增加讀入的mesh的頂點來對細節程度進行增加。
public patchmesh(id3dxpatchmesh); 這就是pathmesh的構造函數,只要傳入一個讀入的mesh就可以了。接下來我們將用一個例子展示怎么增加顯示的細節程度
private void createpatchmesh(string file, float tesslevel)
{
    if (tesslevel < 1.0f) //如果小于默認的值,不再增加,直接返回
        return;
 
    if (mesh != null)
        mesh.dispose();
 
    using (mesh tempmesh = loadmesh(file))
    {
        using (patchmesh patch = patchmesh.createnpatchmesh(tempmesh))
        {
            // calculate the new number of faces/vertices
            int numberfaces = (int)(tempmesh.numberfaces
                * math.pow(tesslevel, 3));
            int numberverts = (int)(tempmesh.numbervertices
                * math.pow(tesslevel, 3));
 
            mesh = new mesh(numberfaces, numberverts, meshflags.managed
                | meshflags.use32bit, tempmesh.vertexformat, device);
 
            // tessellate the patched mesh
            patch.tessellate(tesslevel, mesh); //在tesslevel的基礎上把mesh分成小方格
        }
    }
}
 
private mesh loadmesh(string file)
{
……………………….略
if ((mesh.vertexformat & vertexformats.normal) != vertexformats.normal)
//如果沒有法線信息,就要計算法線,發現信息會在上面的tessellate方法中被用到。
    {
        // we must have normals for our patch meshes
        mesh tempmesh = mesh.clone(mesh.options.value,
            mesh.vertexformat | vertexformats.normal, device);
 
        tempmesh.computenormals();
 
        mesh.dispose();
        mesh = tempmesh;
    }
    return 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 pathmesh
{
     /// <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;


 
        private float tesslevel = 1.0f;
        private const float tessincrement = 1.0f;
        private string filename = @"../.. phere.x";


 
        private microsoft.directx.direct3d.font font = null;


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


 
            // create our patch mesh
            createpatchmesh(filename, tesslevel);


 
            // create our font
            font = new microsoft.directx.direct3d.font(device, new system.drawing.font
                ("arial", 14.0f, fontstyle.bold | fontstyle.italic));


 
            // default to wireframe mode first
            device.renderstate.fillmode = fillmode.wireframe;
        }


 
        /// <summary>
        /// creates a temporary mesh object, and a patch mesh from it
        /// </summary>
        /// <param name="file">the original mesh to use</param>
        /// <param name="tesslevel">the tesselation level</param>
        private void createpatchmesh(string file, float tesslevel)
        {
            if (tesslevel < 1.0f) // nothing to do
                return;


 
            if (mesh != null)
                mesh.dispose();


 
            using (mesh tempmesh = loadmesh(file))
            {
                using (patchmesh patch = patchmesh.createnpatchmesh(tempmesh))
                {
                    // calculate the new number of faces/vertices
                    int numberfaces = (int)(tempmesh.numberfaces
                        * math.pow(tesslevel, 3));
                    int numberverts = (int)(tempmesh.numbervertices
                        * math.pow(tesslevel, 3));


 
                    mesh = new mesh(numberfaces, numberverts, meshflags.managed
                        | meshflags.use32bit, tempmesh.vertexformat, device);


 
                    // tessellate the patched mesh
                    patch.tessellate(tesslevel, mesh);
                }
            }
        }


 
        /// <summary>
        /// load a mesh from a file and return it
        /// </summary>
        /// <param name="file">the file to load</param>
        /// <returns>the created mesh</returns>
        private mesh loadmesh(string file)
        {
            extendedmaterial[] mtrl;


 
            // load our mesh
            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);
                    }
                }
            }


 
            if ((mesh.vertexformat & vertexformats.normal) != vertexformats.normal)
            {
                // we must have normals for our patch meshes
                mesh tempmesh = mesh.clone(mesh.options.value,
                    mesh.vertexformat | vertexformats.normal, device);


 
                tempmesh.computenormals();


 
                mesh.dispose();
                mesh = tempmesh;
            }
            return mesh;
        }


 
        private void setupcamera()
        {
            device.transform.projection = matrix.perspectivefovlh(
                (float)math.pi / 4, this.width / this.height, 1.0f, 100.0f);


 
            device.transform.view = matrix.lookatlh(new vector3(0,0, 5.0f),
                new vector3(), new vector3(0,1,0));


 
            device.lights[0].type = lighttype.directional;
            device.lights[0].diffuse = color.darkkhaki;
            device.lights[0].direction = new vector3(0, 0, -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);


 
            font.drawtext(null, string.format
                ("number vertices: {0}/r/nnumber faces: {1}",
                mesh.numbervertices, mesh.numberfaces),
                new rectangle(10,10,0,0),
                drawtextformat.noclip, color.black);


 
            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);
            }
        }
        protected override void onkeypress(keypresseventargs e)
        {
            if (e.keychar == '+')
            {
                tesslevel += tessincrement;
                createpatchmesh(filename, tesslevel);
            }
            if (e.keychar == '-')
            {
                tesslevel -= tessincrement;
                createpatchmesh(filename, tesslevel);
            }
            if (e.keychar == 'c')
            {
                filename = @"../../cube.x";
                tesslevel = 1.0f;
                createpatchmesh(filename, tesslevel);
            }
            if (e.keychar == 'o')
            {
                filename = @"../.. phere.x";
                tesslevel = 1.0f;
                createpatchmesh(filename, tesslevel);
            }
            if (e.keychar == 't')
            {
                filename = @"../../tiger.x";
                tesslevel = 1.0f;
                createpatchmesh(filename, tesslevel);
            }
            if (e.keychar == 'w')
                device.renderstate.fillmode = fillmode.wireframe;


 
            if (e.keychar == 's')
                device.renderstate.fillmode = fillmode.solid;


 
        }


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

注冊會員,創建你的web開發資料庫,
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平乡县| 湟源县| 招远市| 容城县| 黎城县| 兴化市| 垣曲县| 中牟县| 莫力| 临夏市| 湟中县| 吉木萨尔县| 唐海县| 黑河市| 微博| 仲巴县| 资源县| 龙泉市| 皮山县| 福泉市| 突泉县| 贵溪市| 渭源县| 寿光市| 独山县| 新竹市| 怀仁县| 容城县| 三门县| 穆棱市| 河池市| 洪雅县| 阳山县| 泰和县| 衡水市| 平江县| 定兴县| 沭阳县| 七台河市| 罗山县| 嵩明县|