using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Media; namespace TexturedQuad { /// /// This is the main type for your game /// public class TexturedQuadGame : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; private SpriteFont font; VertexPositionNormalTexture[] cubeVertices; short[] cubeIndices; VertexBuffer vertexBuffer; IndexBuffer indexBuffer; int[] faceTextureIndices = new int[6]; VertexDeclaration vertexDeclaration; Matrix View, Projection; Texture2D[] textures; BasicEffect cubeEffect; float rotation = 0f; KeyboardState previousKeyboardState; /// /// Initializes a new instance of the class and sets up the graphics device manager and content root. /// public TexturedQuadGame() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } /// /// Initializes the game, sets up the cube geometry, view, and projection matrices. /// protected override void Initialize() { // Set up cube geometry (24 vertices, 36 indices) cubeVertices = new VertexPositionNormalTexture[24]; cubeIndices = new short[36]; CreateCubeGeometry(); vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, 24, BufferUsage.WriteOnly); vertexBuffer.SetData(cubeVertices); indexBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, 36, BufferUsage.WriteOnly); indexBuffer.SetData(cubeIndices); for (int i = 0; i < 6; i++) faceTextureIndices[i] = i % 4; View = Matrix.CreateLookAt(new Vector3(0, 0, 3), Vector3.Zero, Vector3.Up); Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4.0f / 3.0f, 1, 500); base.Initialize(); } /// /// Loads all game content, including the four textures and sets up the effect and vertex declaration. /// protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); font = Content.Load("font"); textures = new Texture2D[4]; textures[0] = Content.Load("Glass"); textures[1] = Content.Load("GlassPane"); textures[2] = Content.Load("GlassPane1"); textures[3] = Content.Load("GlassPane2"); cubeEffect = new BasicEffect(graphics.GraphicsDevice); cubeEffect.World = Matrix.Identity; cubeEffect.View = View; cubeEffect.Projection = Projection; cubeEffect.TextureEnabled = true; vertexDeclaration = new VertexDeclaration(new VertexElement[] { new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) } ); } /// /// Updates the game logic, handles input for exiting, switching textures, and rotates the cube. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { #if !__IOS__ if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); if (Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit(); #endif // Change texture on Space key release KeyboardState state = Keyboard.GetState(); if ((state.IsKeyUp(Keys.Space) && previousKeyboardState.IsKeyDown(Keys.Space)) || (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed)) { // Advance the current texture index for all faces int next = (faceTextureIndices[0] + 1) % textures.Length; for (int i = 0; i < faceTextureIndices.Length; i++) faceTextureIndices[i] = next; } previousKeyboardState = state; // Rotate the cube rotation += (float)gameTime.ElapsedGameTime.TotalSeconds; base.Update(gameTime); } /// /// Draws the current frame, rendering the rotating cube with the selected texture on all faces. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.MonoGameOrange); Matrix world = Matrix.CreateRotationY(rotation) * Matrix.CreateRotationX(rotation * 0.7f); cubeEffect.View = View; cubeEffect.Projection = Projection; // All faces use the same texture (current index) int currentTexture = faceTextureIndices[0]; cubeEffect.World = world; cubeEffect.Texture = textures[currentTexture]; GraphicsDevice.SetVertexBuffer(vertexBuffer); GraphicsDevice.Indices = indexBuffer; foreach (EffectPass pass in cubeEffect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 12); } spriteBatch.Begin(); spriteBatch.DrawString(font, "Press Space to change texture", new Vector2(20, 20), Color.Black); spriteBatch.End(); base.Draw(gameTime); } /// /// Creates the geometry for a unit cube centered at the origin. /// private void CreateCubeGeometry() { // 24 vertices (4 per face) so each face can have its own texture coordinates Vector3[] faceNormals = new Vector3[] { Vector3.Forward, Vector3.Backward, Vector3.Left, Vector3.Right, Vector3.Up, Vector3.Down }; Vector3[][] faceVerts = new Vector3[][] { // Front new Vector3[] { new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0.5f, 0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }, // Back new Vector3[] { new Vector3(0.5f, 0.5f, -0.5f), new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0.5f, -0.5f, -0.5f) }, // Left new Vector3[] { new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, -0.5f) }, // Right new Vector3[] { new Vector3(0.5f, 0.5f, 0.5f), new Vector3(0.5f, 0.5f, -0.5f), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(0.5f, -0.5f, 0.5f) }, // Top new Vector3[] { new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0.5f, 0.5f, -0.5f), new Vector3(0.5f, 0.5f, 0.5f), new Vector3(-0.5f, 0.5f, 0.5f) }, // Bottom new Vector3[] { new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f) } }; Vector2[] texCoords = new Vector2[] { new Vector2(0,0), new Vector2(1,0), new Vector2(1,1), new Vector2(0,1) }; for (int face = 0; face < 6; face++) { for (int v = 0; v < 4; v++) { cubeVertices[face * 4 + v] = new VertexPositionNormalTexture( faceVerts[face][v], faceNormals[face], texCoords[v]); } } // Indices for 12 triangles (2 per face) short[] inds = new short[] { 0,1,2, 0,2,3, // Front 4,5,6, 4,6,7, // Back 8,9,10, 8,10,11, // Left 12,13,14, 12,14,15,// Right 16,17,18, 16,18,19,// Top 20,21,22, 20,22,23 // Bottom }; for (int i = 0; i < 36; i++) cubeIndices[i] = inds[i]; } } }