418383/418587 ภาคปลาย 2553/การเขียนเกมสามมิติด้วย XNA 4.0
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 ให้เรา