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个顶点也弄得我头晕脑胀,有人第一次做就全做对吗?如果有的话这个人的头脑真的是很清楚。 单元测试截图如下:
文件下载(已下载 1871 次)
发布时间:2010/4/23 下午2:56:35 阅读次数:6856