您的位置:首页 > 其它

梦想成真 XNA (9) - 3D 模型

2011-08-23 08:51 330 查看
[索引页]
[源码下载]

[align=center]梦想成真 XNA (9) - 3D 模型[/align]

作者:webabcd

介绍
XNA: 3D 模型。通过键盘的“上下左右”键旋转 3D 模型

示例
绘制一个 3D 模型,并通过“上下左右”键控制它的旋转(按键盘 R 键加载此 Demo)

3D/3DModel/RotationDirection.cs

namespace XNA.Component._3D._3DModel
{
/// <summary>
/// 旋转方向
/// </summary>
public enum RotationDirection
{
Up,
Down,
Left,
Right
}
}


3D/3DModel/MyCamera.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA.Component._3D._3DModel
{
/// <summary>
/// 自定义摄像机类
/// </summary>
public class MyCamera : Microsoft.Xna.Framework.GameComponent
{
// View 矩阵,用于设置摄像机的位置和方向
public Matrix View { get; protected set; }
// Projection 矩阵,用于将 3D 物体投影到 2D 屏幕上
public Matrix Projection { get; protected set; }

public MyCamera(Game game, Vector3 pos, Vector3 target, Vector3 up)
: base(game)
{
/*
* Matrix CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector) - 实例化视图矩阵
*     Vector3 cameraPosition - 摄像机的位置坐标
*     Vector3 cameraTarget - 摄像机镜头的朝向向量
*     Vector3 cameraUpVector - 摄像机机身的顶部的上方的向量
*/
View = Matrix.CreateLookAt(pos, target, up);

/*
* CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) - 实例化投影矩阵
*     float fieldOfView - Y 轴方向上的视角弧度,一般是四分之一个 PI
*     float aspectRatio - 可视区的长宽比,一般就是游戏窗口的宽除以游戏窗口的高
*     float nearPlaneDistance - 当物体离摄像机多近时无法看清
*     float farPlaneDistance - 当物体离摄像机多远时无法看清
*/
Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4, // 四分之一个 PI(MathHelper 里有很多实用的功能)
(float)Game.Window.ClientBounds.Width /
(float)Game.Window.ClientBounds.Height,
1,
3000
);
}

public override void Initialize()
{
base.Initialize();
}

public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
}
}


3D/3DModel/MyModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA.Component._3D._3DModel
{
/// <summary>
/// 自定义 3D 模型类
/// </summary>
public class MyModel
{
// Model - 代表 3D 模型。代表 2D 对象的是 Texture2D
private Model _model;

// 旋转矩阵
private Matrix _rotation = Matrix.Identity;

// 初始矩阵
private Matrix _world = Matrix.Identity;

public MyModel(Model model, Matrix world)
{
_model = model;
_world = world;
}

/// <summary>
/// 绘制 3D 模型
/// </summary>
public void Draw(MyCamera camera)
{
/*
* 一个 Model 对象里有多个 ModelMesh 对象,每个 ModelMesh 对象包含了此网格的纹理、颜色等信息
*/
foreach (ModelMesh mesh in _model.Meshes)
{
/*
* 一个 ModelMesh 对象里有多个用于绘制 ModelMesh 的 Effect
*/
foreach (BasicEffect effect in mesh.Effects)
{
//  使用默认光源效果
effect.EnableDefaultLighting();

effect.Projection = camera.Projection;
effect.View = camera.View;
effect.World = GetWorld();
}

// 绘制 ModelMesh
mesh.Draw();
}
}

/// <summary>
/// 根据方向(上下左右)计算旋转矩阵
/// </summary>
public void Rotate(RotationDirection direction)
{
switch (direction)
{
case RotationDirection.Up:
_rotation *= Matrix.CreateRotationX(-MathHelper.Pi / 180); // 绕 X 轴旋转的弧度
break;
case RotationDirection.Down:
_rotation *= Matrix.CreateRotationX(MathHelper.Pi / 180);
break;
case RotationDirection.Left:
_rotation *= Matrix.CreateRotationY(-MathHelper.Pi / 180); // 绕 Y 轴旋转的弧度
break;
case RotationDirection.Right:
_rotation *= Matrix.CreateRotationY(MathHelper.Pi / 180);
break;
}
}

/// <summary>
/// 获取世界矩阵,即初始矩阵乘以旋转矩阵
/// </summary>
public Matrix GetWorld()
{
return _world * _rotation;
}
}
}


3D/3DModel/Demo.cs

/*
* XNA 只支持 .x 和 .fbx 格式的 3D 模型文件
* 本例所用 3D 模型的位置在:XNAContent/3DModel/Spaceship.x
*
* 本例演示:通过键盘的“上下左右”键旋转 3D 模型
*/

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA.Component._3D._3DModel
{
public class Demo : Microsoft.Xna.Framework.DrawableGameComponent
{
private MyCamera _camera;
private List<MyModel> _models = new List<MyModel>();

public Demo(Game game)
: base(game)
{

}

public override void Initialize()
{
// 添加摄像机组件
_camera = new MyCamera(Game, new Vector3(0, 0, 50), Vector3.Zero, Vector3.Up);
Game.Components.Add(_camera);

base.Initialize();
}

protected override void LoadContent()
{
// 添加两个不同位置的 3D 模型
_models.Add(new MyModel(Game.Content.Load<Model>(@"3DModel\Spaceship"), Matrix.Identity * Matrix.CreateTranslation(-10, -5, -20)));
_models.Add(new MyModel(Game.Content.Load<Model>(@"3DModel\Spaceship"), Matrix.Identity * Matrix.CreateTranslation(10, 5, 0)));

base.LoadContent();
}

public override void Update(GameTime gameTime)
{
// 根据用户的按键(上下左右),旋转 3D 模型
KeyboardState keyboardState = Keyboard.GetState();

foreach (MyModel model in _models)
{
if (keyboardState.IsKeyDown(Keys.Up))
model.Rotate(RotationDirection.Up);
else if (keyboardState.IsKeyDown(Keys.Down))
model.Rotate(RotationDirection.Down);
else if (keyboardState.IsKeyDown(Keys.Left))
model.Rotate(RotationDirection.Left);
else if (keyboardState.IsKeyDown(Keys.Right))
model.Rotate(RotationDirection.Right);
}

base.Update(gameTime);
}

public override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// 绘制 3D 模型
foreach (MyModel model in _models)
{
model.Draw(_camera);
}

base.Update(gameTime);
}
}
}


OK
[源码下载]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: