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

首頁 > 開發 > 綜合 > 正文

DirectX9 3D 快速上手 5

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

directx9 3d 快速上手  5
by sssa2000




    這一章的內容相對很簡單,控制mesh的移動,旋轉等等,其實這一切都是在對矩陣進行操作。在 dx中,用到的變換有3種,一種是基于word坐標系的,一種是基于view坐標系的,還有一種是基于投影的變換。而這些變換都是通過矩陣的運算來實現的,在.net的托管環境下,實現這些操作相對于非托管來說簡單一寫,不用對矩陣的每個值運算。

關于矩陣的運算和變換的關系,很多文章都有分析,gameres也有很多這樣的好文章,例如:http://dev.gameres.com/program/visual/3d/3dgame.mht 這里就有很詳細的介紹。

我們這篇文章不研究細節,因為畢竟是快速開發,我們的目標就是用鍵盤控制讀入的mesh的運動。

其實在前面一篇文章中我們就有提到幾個函數,只是沒有介紹。我們來看看我們這一篇中要用到的幾個簡單的函數,從字面我們就可以判斷出這些函數有什么用:


 


matrix.rotatex方法:public void rotatex(    float angle);

matrix. rotatey方法:public void rotatey(    float angle);

matrix.rotatex方法:public void rotatez(    float angle);

matrix.translation方法:public static matrix translation(float offsetx, float offsety, float offsetz);


 


好,我們現在重新打開上一次的讀入mesh的那個工程,我們現在要加入新的部分,既然是用鍵盤控制那么就要首先對鍵盤的狀態進行分析:

         string status=null;//用于保存狀態



protected override void onkeydown(system.windows.forms.keyeventargs e)



         {



              // handle the escape key for quiting



              if (e.keycode == keys.escape)



              {



                   // close the form and return



                   this.close();



                   return;



              }



              // handle left and right keys



              else if ((e.keycode == keys.left) || (e.keycode == keys.numpad4))



              {



                   status="left";  //向左旋轉



              }



              else if ((e.keycode == keys.right) || (e.keycode == keys.numpad6))



              {



                   status="right";//向右旋轉



              }



              else if((e.keycode ==keys.up )||(e.keycode ==keys.numpad8 ))



              {



                   status="up";//向上旋轉



              }



              else if((e.keycode ==keys.down  )||(e.keycode ==keys.numpad2 ))



              {



                   status="down";//向下旋轉



              }



              else if(e.keycode ==keys.enter)



              {



                   status="stop";//停止旋轉



              }



              else if(e.keycode ==keys.w  )



              {



                   status="goahead";//向前




 


              }



              else if(e.keycode ==keys.s )



              {



                   status="goback";//向后



              }



              else if(e.keycode ==keys.a)



              {



                   status="goleft";//向左



              }



              else if(e.keycode ==keys.d )



              {



                   status="goright";//向右



              }



             



         }

很簡單,以至于沒什么可說的,下面就要對mesh進行移動,由于我們觀察的運動都是相對運動,所以無論你是對攝像機進行操作還是進行世界變換都是可以的,隨你所好。我們對drawmesh函數進行修改,主要是對狀態的判斷,然后對相應的矩陣進行變換:

        private void drawmesh(string stat)



              if(stat=="left")



              {



                   angle=angle+0.1f;



                   device.transform.world = matrix.rotationy (angle);



              }



              else if(stat=="right")



              {



                   angle=angle-0.1f;



                   device.transform.world = matrix.rotationy (angle);



              }



              else if(stat=="up")



              {



                   angle=angle+0.1f;



                   device.transform.world = matrix.rotationx (angle);




 



 


              }



              else if(stat=="down")



              {



                   angle=angle-0.1f;



                   device.transform.world = matrix.rotationx (angle);




 


              }



              else if(stat=="stop")



              {



                   angle=0.0f;



                   //device.reset ()



              }



              else if(stat=="goahead")



              {



                   v=v+0.1f;



              }



              else if(stat=="goback")



              {



                   v=v-0.1f;



              }



              else if(stat=="goleft")



              {



                   offsetx=offsetx+0.01f;




 


                   device.transform.world = matrix.translation(offsetx,0,0);



              }



              else if(stat=="goright")



              {



                   offsetx=offsetx-0.01f;



                   device.transform.world = matrix.translation(offsetx,0,0);




 


              }




 


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



            {



                device.material = meshmaterials[i];



                device.settexture(0, meshtextures[i]);



                mesh.drawsubset(i);



            }



        }

public: void rotatex(
    float angle
);



public function rotatex(
    angle : float
);



這里我們處理小車前后移動的時候,沒有直接使用世界變換,而是對攝影機進行了操作,這也很好理解,為了達到這個目的,我把setupcamera函數小小的修改了一下:



  private void setupcamera(float deep )



        {



            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, 10.0f+deep), new vector3(), new vector3(0,1,0));



            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;



        }

我給它加了一個參數,這個參數就是攝像機在z軸的位置,我們只需要修改攝像機在z軸的位置就可以實現透視效果,用這個方法實現我們這個簡單的需求是很恰當的

這里再來對這里面的2個函數分析一下:

device.transform.projection用來獲取或者設置投影變換矩陣,它本身也是一個matrix型的變量。matrix.perspectivefovlh方法:



public static matrix perspectivefovlh(
    float fieldofviewy, //y方向的視覺范圍,弧度表示,即y方向的視域角
    float aspectratio, //視覺范圍的長寬比
    float znearplane, //近裁減平面      
    float zfarplane//遠裁減平面
);



和非托管的相比,僅僅少了一個參數。定義寬高比的作用是,如果用戶改變了窗口的大小,那么仍然就可以正確的顯示物體的大小。最后兩個參數是 近遠裁減平面,必須為這兩個平面指定2個z值,一般來說,假設物體將在z軸的1.0f和1000f之間運動時,就分別把這兩個參數設為1.0f,1000.0f。

再來看看另外方法:matrix.lookatlh方法。 在使用觀察矩陣來建立一個立體的照相機模型后,允許玩家通過一系列不同的觀察點來看世界,使用matrix.lookatlh方法建立的照相機模型,是一種十分高效的照相機模型,但是注意,這一種模型不能繞所有的軸做三維轉動。



public static matrix lookatlh(
    vector3 cameraposition,//相機位置
    vector3 cameratarget,   //相機的方向
    vector3 cameraupvector  //相機的up向量
);



其中第二個參數為相機的面對方向,假設相機面對的是z軸的方向,那么就設置為(0,0,1)。好,現在也許有人要問,那如果面對的是z軸的負方向呢?這也就是第3個參數的目的,第三個參數定一個up向量,所以如果相機是正著放的,那么第3個參數就應該是(0,1,0),如果是倒著放的就是(0,-1,0)。所以如果面對的是z的負方向,第三個參數就是(0,-1,0)。



利用這個方法我們可以輕易的建立一個跟隨式的相機(follow-up camera),例如實現第一人稱視角,只需要把第2個參數指向跟隨物體的方向,把相機位置設置為這個物體的周圍。前面我們提過,這類相機不能繞自身旋轉。



好,讓我們來簡單實現這個功能,我們想讓汽車前進后退的時候能讓攝像機來跟隨它,首先,我們必須得到讀入的mesh的x,y,z這樣才能給攝像機提供第一個參數,其次我們要確定朝向,在這里,很好確定,因為汽車就是朝z方向開的,好了,都確定下來我們就可以寫代碼了。為了得到mesh的位置,就要使用mesh內置的定點緩沖。



……………………………………..



             loadmesh(@"../.. r.x");



             vb=mesh.vertexbuffer; //取得讀入mesh的中心



              try



              {



                   vector3 max;



                   vector3 min;



                   graphicsstream gs = vb.lock(0, 0, lockflags.none);



                   geometry.computeboundingbox(gs, mesh.numbervertices, mesh.vertexformat, out min, out max); //取得mesh的邊框



                   float tx = (max.x - min.x)/2;



                   float ty =( max.y - min.y)/2;



                   float tz =( max.z - min.z);



                   pos.x =tx-0.9f;  //試出來的,這樣才能使攝像機近似在車子中心



                   pos.y =ty+0.6f;



                   pos.z =tz-1.8f;



                   //float cameraheadingh=



                   lookat = new vector3 (0,0,1);



              }



              finally



              {



                   vb.unlock();



                   vb.dispose();



              }



修改keydown并且修改setupcamera函數判斷攝像機的選擇。



private void setupcamera(float deep )



        {



            device.transform.projection = matrix.perspectivefovlh((float)math.pi / 4, this.width / this.height, 1.0f, 10000.0f);



              if(camera%2!=0)



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



              else



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




 


            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;



        }




 


這樣就完成了這個功能,不過這里只是簡單模擬一下,只有在前進后退的時候才有效果,不過由于沒有參照物,在前進后退的時候看不出畫面的變化。下面貼出完整的代碼:



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;



         presentparameters presentparams =null;



        private mesh mesh = null;



        private material[] meshmaterials;



        private texture[] meshtextures;




 


         private mesh mesh2=null;



         material[] meshmaterials2;



         texture[] meshtextures2;




 


        string status=null; //小車狀態,向左轉動還是向右轉動,或者停止



         private vertexbuffer vb = null;



         vector3 pos;



         vector3 lookat;




 


         int camera=1;



         float angle=0.0f;



         float v=0.1f;



         float offsetx=0.1f;




 


         /// <summary>



         /// required designer variable.



         /// </summary>



         private system.componentmodel.container components = null;




 


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




 


              vb=mesh.vertexbuffer; //取得讀入mesh的中心



              try



              {



                   vector3 max;



                   vector3 min;



                   graphicsstream gs = vb.lock(0, 0, lockflags.none);



                   geometry.computeboundingbox(gs, mesh.numbervertices, mesh.vertexformat, out min, out max);



                   float tx = (max.x - min.x)/2;



                   float ty =( max.y - min.y)/2;



                   float tz =( max.z - min.z);



                   pos.x =tx-0.9f;



                   pos.y =ty+0.6f;



                   pos.z =tz-1.8f;



                   //float cameraheadingh=



                   lookat = new vector3 (0,0,1);




 


              }



              finally



              {



                   vb.unlock();



                   vb.dispose();



              }



        }




 


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



                    }



                }



            }



        }




 


 




 


         protected override void onkeydown(system.windows.forms.keyeventargs e)



         {



              // handle the escape key for quiting



              if (e.keycode == keys.escape)



              {



                   // close the form and return



                   this.close();



                   return;



              }



              // handle left and right keys



              else if ((e.keycode == keys.left) || (e.keycode == keys.numpad4))



              {



                   status="left";



              }



              else if ((e.keycode == keys.right) || (e.keycode == keys.numpad6))



              {



                   status="right";



              }



              else if((e.keycode ==keys.up )||(e.keycode ==keys.numpad8 ))



              {



                   status="up";



              }



              else if((e.keycode ==keys.down  )||(e.keycode ==keys.numpad2 ))



              {



                   status="down";



              }



              else if(e.keycode ==keys.enter)



              {



                   status="stop";



              }



              else if(e.keycode ==keys.w  )



              {



                   status="goahead";




 


              }



              else if(e.keycode ==keys.s )



              {



                   status="goback";



              }



              else if(e.keycode ==keys.a)



              {



                   status="goleft";



              }



              else if(e.keycode ==keys.d )



              {



                   status="goright";



              }



              else if(e.keycode ==keys.c)



              {



                   camera++;



              }




 


             




 


         }




 


        private void setupcamera(float deep )



        {



            device.transform.projection = matrix.perspectivefovlh((float)math.pi / 4, this.width / this.height, 1.0f, 10000.0f);



              if(camera%2!=0)



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



              else



                   device.transform .view =matrix.lookatlh (pos,new vector3 (0,1,0),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(v );




 


            device.beginscene();




 


            // draw our mesh



            drawmesh(status);




 


            device.endscene();




 


            device.present();




 


            this.invalidate();



        }




 


        private void drawmesh(string stat)



        {



         //   angle += 0.01f;




 


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



              if(stat=="left")



              {



                   angle=angle+0.1f;



                   device.transform.world = matrix.rotationy (angle);



              }



              else if(stat=="right")



              {



                   angle=angle-0.1f;



                   device.transform.world = matrix.rotationy (angle);



              }



              else if(stat=="up")



              {



                   angle=angle+0.1f;



                   device.transform.world = matrix.rotationx (angle);




 



 


              }



              else if(stat=="down")



              {



                   angle=angle-0.1f;



                   device.transform.world = matrix.rotationx (angle);




 


              }



              else if(stat=="stop")



              {



                   angle=0.0f;



                   //device.reset ()



              }



              else if(stat=="goahead")



              {



                   v=v+0.1f;



              }



              else if(stat=="goback")



              {



                   v=v-0.1f;



              }



              else if(stat=="goleft")



              {



                   offsetx=offsetx+0.001f;




 


                   device.transform.world = matrix.translation(offsetx,0,0);



                   //device.transform .view =matrix.translation(offsetx,0,0);



              //   pos.x -=offsetx;



              //   device.transform .view =matrix.lookatlh(pos,new vector3 (0,0,1),new vector3 (0,1,0));



              }



              else if(stat=="goright")



              {



                   offsetx=offsetx-0.001f;



                   device.transform.world = matrix.translation(offsetx,0,0);



 




 


              }




 


 



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



            }



        }



     }



}




 


好幸庫,結束。



  • 本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 松原市| 陵水| 维西| 民勤县| 三门县| 璧山县| 沙坪坝区| 深州市| 浑源县| 汤阴县| 稷山县| 都安| 瑞昌市| 苍梧县| 新昌县| 瑞丽市| 阳曲县| 桦南县| 治县。| 武定县| 昔阳县| 太原市| 青铜峡市| 崇明县| 肇东市| 神木县| 乃东县| 德化县| 正镶白旗| 图片| 龙川县| 西乌珠穆沁旗| 永顺县| 卓资县| 萝北县| 辽宁省| 丽江市| 南陵县| 惠东县| 玉龙| 九寨沟县|