25. 绘制立方体的CubeSceneNode类
有了上一个教程创建平面QuadSceneNode类的基础,创建立方体就比较容易理解了,CubeSceneNode类的代码如下,也很简单:
namespace StunEngine.SceneNodes
{
///
/// 创建一个立方体
///
public class CubeSceneNode : GenericMaterialSceneNode
{
#region 构造函数和成员变量
///
/// 创建一个新CubeSceneNode对象,不使用细节纹理。
///
/// 引擎
/// 所属场景
/// 立方体使用的漫反射纹理
public CubeSceneNode(StunXnaGE engine, Scene setScene, string setDiffuseTextureName) : this(engine, setScene, setDiffuseTextureName,Vector2 .One ,null ,Vector2 .Zero ) { }
///
/// 创建一个新CubeSceneNode对象,使用细节纹理。
///
/// 引擎
/// 所属场景
/// 立方体使用的漫反射纹理
/// 漫反射纹理UV重复次数
/// 立方体使用的细节纹理
/// 细节纹理UV重复次数
public CubeSceneNode(StunXnaGE engine, Scene setScene, string setDiffuseTextureName, Vector2 setDiffuseTiles, string setDetailTextureName, Vector2 setDetailTiles)
: base(engine, setScene,setDiffuseTextureName ,setDiffuseTiles ,setDetailTextureName ,setDetailTiles)
{
}
#endregion
///
/// 初始化CubeSceneNode对象。注意不要使用Initialize,它只被引擎调用。
///
public override void Initialize()
{
this.UpdateOrder = SceneManagement.SceneNodeOrdering.SceneNode.GetValue();
base.Initialize();
this.mesh =MeshBuilder.CreateCube (engine .GraphicsDevice);
}
#region 单元测试
#if DEBUG
///
/// 测试CubeSceneNode类
///
public static void TestCubeSceneNode()
{
CubeSceneNode cube1 = null;
CubeSceneNode cube2 = null;
TestGame.Start("测试CubeSceneNode类",
delegate
{
//添加一个覆盖有岩石纹理的长方体
cube1 = new CubeSceneNode(TestGame.engine, TestGame.scene, "Textures\\Rock", new Vector2(2.0f, 2.0f), "Textures\\dirty", Vector2.One );
TestGame.scene.AddNode(cube1);
Vector3 scale = new Vector3(4.0f, 2.0f, 4.0f);
cube1.Pose.SetScale(ref scale);
Vector3 position = new Vector3(-4f, 1.0f, -4.0f);
cube1.Pose.SetPosition (ref position);
cube1.Material.SpecularColor = new Vector3(1.0f, 1.0f, 1.0f);
cube1.Material.SpecularPower = 50;
//添加一个只有顶点颜色的立方体
cube2 = new CubeSceneNode(TestGame.engine, TestGame.scene, null);
TestGame.scene.AddNode(cube2);
scale = new Vector3(4.0f, 4.0f, 4.0f);
cube2.Pose.SetScale(ref scale);
position = new Vector3(4f, 2.0f, -4.0f);
cube2.Pose.SetPosition(ref position);
cube2.Material.DiffuseColor = new Vector3(1.0f, 0.0f, 0.0f);
cube2.Material.SpecularColor = new Vector3(1.0f, 1.0f, 1.0f);
cube2.Material.SpecularPower = 50;
//不显示光标
TestGame.scene.IsShowMouse = false;
TestGame.scene.Camera.MovementSpeed = 30.0f;
},
delegate
{
//按数字1键则切换使用的technique
if (Input.KeyboardKeyJustPressed(Keys.D1))
{
if (cube1.Material.CurrentTechniqueName == "SimpleTextured")
cube1.Material.CurrentTechniqueName = "TexturedLights";
else
cube1.Material.CurrentTechniqueName = "SimpleTextured";
}
//按数字2键则切换平面上的纹理
if (Input.KeyboardKeyJustPressed(Keys.D2))
{
if (cube1.Material.DiffuseTextureName == "Textures\\Grass")
cube1.Material.DiffuseTextureName = "Textures\\Rock";
else
cube1.Material.DiffuseTextureName = "Textures\\Grass";
}
//按数字3键切换漫反射纹理平铺值
if (Input.KeyboardKeyJustPressed(Keys.D3))
{
if (cube1.Material.DiffuseUVTile == Vector2.One)
cube1.Material.DiffuseUVTile = new Vector2(2.0f, 2.0f);
else
cube1.Material.DiffuseUVTile = Vector2.One;
}
});
}
#endif
#endregion
}
}
关键还是在于创建立方体顶点和索引的方法,它位于MeshBuilder类的静态方法CreateCube中:
////// 创建一个立方体。 /// /// 图形设备 ///public static Mesh CreateCube(GraphicsDevice g) { // 创建24个顶点。正方体有8个顶点,但是因为需要设置法线数据,所以必须定义24个顶点,每个面4个共24个,否则光照是不正确的 VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[24]; // 设置8个顶点的位置 Vector3 forwardBottomLeft = new Vector3(-HALF, -HALF, HALF); Vector3 forwardBottomRight = new Vector3(HALF, -HALF, HALF); Vector3 forwardUpperLeft = new Vector3(-HALF, HALF, HALF); Vector3 forwardUpperRight = new Vector3(HALF, HALF, HALF); Vector3 backBottomLeft = new Vector3(-HALF, -HALF, -HALF); Vector3 backBottomRight = new Vector3(HALF, -HALF, -HALF); Vector3 backUpperLeft = new Vector3(-HALF, HALF, -HALF); Vector3 backUpperRight = new Vector3(HALF, HALF, -HALF); #region 前面的顶点 // 左下角顶点 - 0 vertices[0].Position = forwardBottomLeft; vertices[0].TextureCoordinate = new Vector2(0, 1); vertices[0].Normal = Vector3.Backward; // 左上角顶点 - 1 vertices[1].Position = forwardUpperLeft; vertices[1].TextureCoordinate = new Vector2(0, 0); vertices[1].Normal = Vector3.Backward; // 右下角顶点 - 2 vertices[2].Position = forwardBottomRight; vertices[2].TextureCoordinate = new Vector2(1, 1); vertices[2].Normal = Vector3.Backward; // 右上角顶点 - 3 vertices[3].Position = forwardUpperRight; vertices[3].TextureCoordinate = new Vector2(1, 0); vertices[3].Normal = Vector3.Backward; #endregion #region 后面的顶点 // 左下角顶点-4 vertices[4].Position = backBottomLeft; vertices[4].TextureCoordinate = new Vector2(0, 1); vertices[4].Normal = Vector3.Forward; // 左上角顶点-5 vertices[5].Position = backUpperLeft; vertices[5].TextureCoordinate = new Vector2(0, 0); vertices[5].Normal = Vector3.Forward; // 右下角顶点-6 vertices[6].Position = backBottomRight; vertices[6].TextureCoordinate = new Vector2(1, 1); vertices[6].Normal = Vector3.Forward; // 右上角顶点-7 vertices[7].Position = backUpperRight; vertices[7].TextureCoordinate = new Vector2(1, 0); vertices[7].Normal = Vector3.Forward; #endregion #region 左面的顶点 // 左下角顶点-0 vertices[8].Position = forwardBottomLeft; vertices[8].TextureCoordinate = new Vector2(0, 1); vertices[8].Normal = Vector3.Left ; // 左上角顶点-1 vertices[9].Position = forwardUpperLeft; vertices[9].TextureCoordinate = new Vector2(0, 0); vertices[9].Normal = Vector3.Left ; // 右下角顶点-4 vertices[10].Position = backBottomLeft; vertices[10].TextureCoordinate = new Vector2(1, 1); vertices[10].Normal = Vector3.Left ; // 右上角顶点-5 vertices[11].Position = backUpperLeft; vertices[11].TextureCoordinate = new Vector2(1, 0); vertices[11].Normal = Vector3.Left ; #endregion #region 右面的顶点 // 左下角顶点-2 vertices[12].Position = forwardBottomRight; vertices[12].TextureCoordinate = new Vector2(0, 1); vertices[12].Normal = Vector3.Right ; // 左上角顶点-3 vertices[13].Position = forwardUpperRight; vertices[13].TextureCoordinate = new Vector2(0, 0); vertices[13].Normal = Vector3.Right; // 右下角顶点-6 vertices[14].Position = backBottomRight; vertices[14].TextureCoordinate = new Vector2(1, 1); vertices[14].Normal = Vector3.Right; // 右上角顶点-7 vertices[15].Position = backUpperRight; vertices[15].TextureCoordinate = new Vector2(1, 0); vertices[15].Normal = Vector3.Right; #endregion #region 上面的顶点 // 左下角顶点-1 vertices[16].Position = forwardUpperLeft; vertices[16].TextureCoordinate = new Vector2(0, 1); vertices[16].Normal = Vector3.Up; // 左上角顶点-5 vertices[17].Position = backUpperLeft; vertices[17].TextureCoordinate = new Vector2(0, 0); vertices[17].Normal = Vector3.Up; // 右下角顶点-3 vertices[18].Position = forwardUpperRight; vertices[18].TextureCoordinate = new Vector2(1, 1); vertices[18].Normal = Vector3.Up; // 右上角顶点-7 vertices[19].Position = backUpperRight; vertices[19].TextureCoordinate = new Vector2(1, 0); vertices[19].Normal = Vector3.Up; #endregion #region 下面的顶点 // 左下角顶点-0 vertices[20].Position = forwardBottomLeft; vertices[20].TextureCoordinate = new Vector2(0, 1); vertices[20].Normal = Vector3.Down; // 左上角顶点-4 vertices[21].Position = backBottomLeft; vertices[21].TextureCoordinate = new Vector2(0, 0); vertices[21].Normal = Vector3.Down; // 右下角顶点-2 vertices[22].Position = forwardBottomRight; vertices[22].TextureCoordinate = new Vector2(1, 1); vertices[22].Normal = Vector3.Down; // 右上角顶点-6 vertices[23].Position = backBottomRight; vertices[23].TextureCoordinate = new Vector2(1, 0); vertices[23].Normal = Vector3.Down; #endregion //36个索引,每个面有两个三角形,每个三角形有3个索引,所以共36个索引,因为索引数量不会超过65536个,所以它的数据类型为ushort,可以减少发送到显卡的数据量 ushort[] indices = { // 前面的正方形 0, 1, 2, 1, 3, 2, // 后面的正方形 4, 6, 5, 6, 7, 5, // 左面的正方形 9, 8, 10, 9, 10, 11, // 右面的正方形 12, 13, 14, 13, 15, 14, // 上面的正方形 16, 17, 18, 18, 17, 19, // 下面的正方形 20, 22, 21, 22, 23, 21 }; //创建顶点缓冲 VertexBuffer vb = new VertexBuffer(g, typeof(VertexPositionNormalTexture), vertices.Length, BufferUsage.None); vb.SetData(vertices,0,24); //设置顶点声明 VertexDeclaration vxDeclaration = new VertexDeclaration(g, VertexPositionNormalTexture.VertexElements); //创建索引缓冲 IndexBuffer ib = new IndexBuffer(g, typeof(ushort), indices.Length, BufferUsage.None); ib.SetData(indices); return new Mesh(PrimitiveType.TriangleList, vb, vxDeclaration, ib, 24, 12); }
创建顶点数据的示意图如下图所示,第一个数字表示顶点序号,括号中数字表示坐标:

不知道如何使用TriangleStrip形式定义顶点,就用TriangleList吧,毕竟TriangleList容易理解。只有8个顶点也弄得我头晕脑胀,有人第一次做就全做对吗?如果有的话这个人的头脑真的是很清楚。 单元测试截图如下:

发布时间:2010/4/23 下午2:56:35 阅读次数:7383
