ผลต่างระหว่างรุ่นของ "418383/418587 ภาคปลาย 2553/การเขียนเกมสามมิติด้วย XNA 4.0"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 4 รุ่นระหว่างกลางโดยผู้ใช้ 2 คน)
แถว 52: แถว 52:
  
 
* อธิบาย
 
* อธิบาย
** โค้ดสองบรรทัดที่เกี่ยวข้องกับเมตริกส์สองบรรทัด
+
:* โค้ดสองบรรทัดที่เกี่ยวข้องกับเมตริกส์สองบรรทัด
 
<geshi lang="C#">
 
<geshi lang="C#">
 
             Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
 
             Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
แถว 58: แถว 58:
 
</geshi>
 
</geshi>
 
:: มีไว้สำหรับสร้าง view matrix และ projection matrix สำหรับเซตมุมกล้อง
 
:: มีไว้สำหรับสร้าง view matrix และ projection matrix สำหรับเซตมุมกล้อง
** โค้ดสองบรรทัดต่อไป
+
:* โค้ดสองบรรทัดต่อไป
 
<geshi lang="C#">
 
<geshi lang="C#">
 
             Matrix[] transforms = new Matrix[model.Bones.Count];
 
             Matrix[] transforms = new Matrix[model.Bones.Count];
 
             model.CopyAbsoluteBoneTransformsTo(transforms);
 
             model.CopyAbsoluteBoneTransformsTo(transforms);
 
</geshi>
 
</geshi>
:: จำเป็นต้องมีเนื่องจาก
+
:* จำเป็นต้องมีเนื่องจาก
::* Model ใน XNA สามารถแบ่งออกเป็นหลายๆ ส่วน ที่แต่ละส่วนใช้ material (สี, texture, diffuse, ambient, ฯลฯ) เดียวกัน
+
::* Model ใน XNA สามารถแบ่งออกเป็นหลายๆ ส่วน
 +
::* แต่ละส่วนนี้แทนด้วย object ชนิด <tt>ModelMesh</tt>
 
::* แต่ละส่วนของ Model นี้ถูกยึดเข้าด้วยกันด้วยกระุดูก (bone) เพื่อให้ทำ skeletal animation แบบง่ายๆ ได้
 
::* แต่ละส่วนของ Model นี้ถูกยึดเข้าด้วยกันด้วยกระุดูก (bone) เพื่อให้ทำ skeletal animation แบบง่ายๆ ได้
 
::* แต่ละ bone จะมี transform ของตัวมันเอง
 
::* แต่ละ bone จะมี transform ของตัวมันเอง
 
::* สองบรรทัดข้างบนทำหน้าที่ไปดึง transform ของกระดูกแต่ละตัวออกมาใส่ในอะเรย์ <tt>transforms</tt>
 
::* สองบรรทัดข้างบนทำหน้าที่ไปดึง transform ของกระดูกแต่ละตัวออกมาใส่ในอะเรย์ <tt>transforms</tt>
 +
:* ในลูปหลัก
 +
<geshi lang="C#">
 +
            foreach (ModelMesh mesh in model.Meshes)
 +
            {
 +
                foreach (BasicEffect effect in mesh.Effects)
 +
                {
 +
                    effect.EnableDefaultLighting();
 +
                    effect.World = transforms[mesh.ParentBone.Index];
 +
                    effect.View = viewMatrix;
 +
                    effect.Projection = projectMatrix;
 +
                }
 +
                // Draw the mesh, using the effects set above.
 +
                mesh.Draw();
 +
            }
 +
</geshi>
 +
::* เราลูปวนเข้าไปดู <tt>ModelMesh</tt> แต่ละตัวใน Model
 +
::* ใน ModelMesh แต่ละส่วนอาจสามารถแบ่งออกเป็นหลายๆ ส่วนย่อยๆ ที่แต่ละส่วนใช้ effect (สี, texture, transform, shader ฯลฯ) แบบเดียวกันในการวาดรูป
 +
::* ดังนั้นใน ModelMesh อันหนึ่งจะมี object ชนิด Effect ที่ใช้แทน shader ที่ใช้ในการวาดส่วนต่างๆ ของโมเดลอยู่หลายๆ อัน
 +
::* สิ่งที่เราทำกับ effect เหล่านี้คือ
 +
:::* เราเรียก effect.EnableDefaultLighting() เพื่อตั้งค่าแหล่งกำเนิดแสง
 +
:::* เราเซตมุมกล้องด้วยการกำหนด view (ด้วยคำสั่ง effect.View = viewMatrix;) และ projection matrix (ด้วยคำสั่ง (effect.Projection = projectMatrix;)
 +
:::* เรา transform ตัว mesh ด้วยการเซตค่าให้ world matrix ของ effect นั้น
 +
:::* เราเซตให้ effect.World มีค่าเท่ากับ transforms[mesh.ParentBone.Index] เพื่อให้ mesh ทั้ง mesh ถูกแปลงด้วย transform ของ bone ที่มันติดอยู่ (เรียกว่า parent bone ใน XNA)
 +
::* หลังจากเซตต่าแล้ว เราเรียก mesh.Draw(); เพื่อสั่งให้ XNA วาด mesh ให้เรา
 +
 +
== การเซตมุมกล้อง ==
 +
* การเซตมุมกล้องใน XNA ทำได้โดยการไปกำหนด World, View, และ Project matrix ของ effect ที่เราใช้
 +
* XNA มีเมธอดสำหรับสร้าง transform ที่ใช้สะดวกอยู่หลายเมธอด
 +
:* Matrix.CreatePerspctiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
 +
::* สร้าง perspective matrix
 +
::* fieldOfView = ความกว้างของมุมยอดของ frustum ที่ผู้ใช้มองเห็น '''มีหน่วยเป็น radian'''
 +
::* Argument ตัวอื่นมีความหมายเหมือนฟังก์ชัน [http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml gluPerspective ของ OpenGL]
 +
:* Matrix.CreateLoopAt(Vector3 cameraPostition, Vector3 cameraTarget, Vector3 cameraUpVector)
 +
::* สร้าง look-at matrix
 +
::* มีความหมายเหมือน [http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml gluLookAt ของ OpenGL]
 +
:* Matrix.CreateTranslation(Vector3 displacement)
 +
::* สร้าง translation matrix
 +
:* Matrix.CreateRotation(

รุ่นแก้ไขปัจจุบันเมื่อ 14:59, 27 มกราคม 2554

Model

  • ใน XNA มีีคลาส Model สำหรับโมเดลสามมิติพื้นฐาน
  • Content pipeline ที่ติดมากับ XNA สามารถอ่านไฟล์ .x (ไฟล์ของ DirectX) และไฟล์ .fbx (ไฟล์ของ Adobe ที่สามารถ export ได้จาก Maya และ 3D Studio Max) ได้
  • ตัวอย่างการอ่านไฟล์

<geshi lang="C#">

   public class Game1 : Microsoft.Xna.Framework.Game
   {
       Model model;
       protected override void LoadContent()
       {
           spriteBatch = new SpriteBatch(GraphicsDevice);
           model = Content.Load<Model>("teapot");
       }
   }

</geshi>

  • เวลาแสดงโมเดลให้ใช้โค้ดต่อไปนี้

<geshi lang="C#">

   public class Game1 : Microsoft.Xna.Framework.Game
   {
       protected override void Draw(GameTime gameTime)
       {
           GraphicsDevice.Clear(Color.CornflowerBlue);
           Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
           Matrix projectMatrix = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4, 1.0f, 0.1f, 100.0f);
           // Copy any parent transforms.
           Matrix[] transforms = new Matrix[model.Bones.Count];
           model.CopyAbsoluteBoneTransformsTo(transforms);
                     
           foreach (ModelMesh mesh in model.Meshes)
           {
               foreach (BasicEffect effect in mesh.Effects)
               {
                   effect.EnableDefaultLighting();
                   effect.World = transforms[mesh.ParentBone.Index];
                   effect.View = viewMatrix;
                   effect.Projection = projectMatrix;
               }
               // Draw the mesh, using the effects set above.
               mesh.Draw();
           }
           base.Draw(gameTime);
       }
   }

</geshi>

  • อธิบาย
  • โค้ดสองบรรทัดที่เกี่ยวข้องกับเมตริกส์สองบรรทัด

<geshi lang="C#">

           Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
           Matrix projectMatrix = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4, 1.0f, 0.1f, 100.0f);

</geshi>

มีไว้สำหรับสร้าง view matrix และ projection matrix สำหรับเซตมุมกล้อง
  • โค้ดสองบรรทัดต่อไป

<geshi lang="C#">

           Matrix[] transforms = new Matrix[model.Bones.Count];
           model.CopyAbsoluteBoneTransformsTo(transforms);

</geshi>

  • จำเป็นต้องมีเนื่องจาก
  • Model ใน XNA สามารถแบ่งออกเป็นหลายๆ ส่วน
  • แต่ละส่วนนี้แทนด้วย object ชนิด ModelMesh
  • แต่ละส่วนของ Model นี้ถูกยึดเข้าด้วยกันด้วยกระุดูก (bone) เพื่อให้ทำ skeletal animation แบบง่ายๆ ได้
  • แต่ละ bone จะมี transform ของตัวมันเอง
  • สองบรรทัดข้างบนทำหน้าที่ไปดึง transform ของกระดูกแต่ละตัวออกมาใส่ในอะเรย์ transforms
  • ในลูปหลัก

<geshi lang="C#">

           foreach (ModelMesh mesh in model.Meshes)
           {
               foreach (BasicEffect effect in mesh.Effects)
               {
                   effect.EnableDefaultLighting();
                   effect.World = transforms[mesh.ParentBone.Index];
                   effect.View = viewMatrix;
                   effect.Projection = projectMatrix;
               }
               // Draw the mesh, using the effects set above.
               mesh.Draw();
           }

</geshi>

  • เราลูปวนเข้าไปดู ModelMesh แต่ละตัวใน Model
  • ใน ModelMesh แต่ละส่วนอาจสามารถแบ่งออกเป็นหลายๆ ส่วนย่อยๆ ที่แต่ละส่วนใช้ effect (สี, texture, transform, shader ฯลฯ) แบบเดียวกันในการวาดรูป
  • ดังนั้นใน ModelMesh อันหนึ่งจะมี object ชนิด Effect ที่ใช้แทน shader ที่ใช้ในการวาดส่วนต่างๆ ของโมเดลอยู่หลายๆ อัน
  • สิ่งที่เราทำกับ effect เหล่านี้คือ
  • เราเรียก effect.EnableDefaultLighting() เพื่อตั้งค่าแหล่งกำเนิดแสง
  • เราเซตมุมกล้องด้วยการกำหนด view (ด้วยคำสั่ง effect.View = viewMatrix;) และ projection matrix (ด้วยคำสั่ง (effect.Projection = projectMatrix;)
  • เรา transform ตัว mesh ด้วยการเซตค่าให้ world matrix ของ effect นั้น
  • เราเซตให้ effect.World มีค่าเท่ากับ transforms[mesh.ParentBone.Index] เพื่อให้ mesh ทั้ง mesh ถูกแปลงด้วย transform ของ bone ที่มันติดอยู่ (เรียกว่า parent bone ใน XNA)
  • หลังจากเซตต่าแล้ว เราเรียก mesh.Draw(); เพื่อสั่งให้ XNA วาด mesh ให้เรา

การเซตมุมกล้อง

  • การเซตมุมกล้องใน XNA ทำได้โดยการไปกำหนด World, View, และ Project matrix ของ effect ที่เราใช้
  • XNA มีเมธอดสำหรับสร้าง transform ที่ใช้สะดวกอยู่หลายเมธอด
  • Matrix.CreatePerspctiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
  • สร้าง perspective matrix
  • fieldOfView = ความกว้างของมุมยอดของ frustum ที่ผู้ใช้มองเห็น มีหน่วยเป็น radian
  • Argument ตัวอื่นมีความหมายเหมือนฟังก์ชัน gluPerspective ของ OpenGL
  • Matrix.CreateLoopAt(Vector3 cameraPostition, Vector3 cameraTarget, Vector3 cameraUpVector)
  • Matrix.CreateTranslation(Vector3 displacement)
  • สร้าง translation matrix
  • Matrix.CreateRotation(