Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using BEPUphysics.Entities.Prefabs;
- namespace CharacterControllerTest
- {
- /// <summary>
- /// A physics box that can also be drawn, with textures on each side.
- /// </summary>
- class TexturedBox : Box
- {
- /// <summary>
- /// The names of each side of a box.
- /// </summary>
- public enum BoxSideName { Top, Bottom, Front, Back, Right, Left };
- /// <summary>
- /// Nested class for storing information about each side of the box.
- /// </summary>
- public class BoxSide
- {
- /// <summary>
- /// Fires when the orientation of a texture is changed.
- /// </summary>
- public event EventHandler TextureOrientationChanged;
- /// <summary>
- /// Called when the texture on the side is flipped.
- /// </summary>
- private void OnTextureOrientationChanged()
- {
- EventArgs e = new EventArgs();
- TextureOrientationChanged(this, e);
- }
- /// <summary>
- /// The name of this side.
- /// </summary>
- public BoxSideName Name { get; private set; }
- /// <summary>
- /// The texture of this side.
- /// </summary>
- public Texture2D Texture { get; set; }
- /// <summary>
- /// Is the texture on this side flipped horizontally?
- /// </summary>
- private bool flipHorizontal;
- /// <summary>
- /// Sets wheter the texture on this side should be flipped horizontally.
- /// </summary>
- public bool FlipTextureHorizontal
- {
- get { return flipHorizontal; }
- set
- {
- flipHorizontal = value;
- // Texture orientation has changed.
- OnTextureOrientationChanged();
- }
- }
- /// <summary>
- /// Is the texture on this side flipped vertically?
- /// </summary>
- private bool flipVertical;
- /// <summary>
- /// Sets whether the texture on this side should be flipped vertically.
- /// </summary>
- public bool FlipTextureVertical
- {
- get { return flipVertical; }
- set
- {
- flipVertical = value;
- // Texture orientation has changed.
- OnTextureOrientationChanged();
- }
- }
- /// <summary>
- /// Constructor for holding information about the side of a box.
- /// </summary>
- /// <param name="name">The name of this side.</param>
- /// <param name="texture">The texture of this side.</param>
- public BoxSide(BoxSideName name, Texture2D texture)
- {
- Name = name;
- Texture = texture;
- // By default, don't flip the texture.
- flipHorizontal = false;
- flipVertical = false;
- }
- }
- /// <summary>
- /// The top side of the box.
- /// </summary>
- public BoxSide Top { get; private set; }
- /// <summary>
- /// The bottom side of the box.
- /// </summary>
- public BoxSide Bottom { get; private set; }
- /// <summary>
- /// The front side of the box.
- /// </summary>
- public BoxSide Front { get; private set; }
- /// <summary>
- /// The back side of the box.
- /// </summary>
- public BoxSide Back { get; private set; }
- /// <summary>
- /// The right side of the box.
- /// </summary>
- public BoxSide Right { get; private set; }
- /// <summary>
- /// The left side of the box.
- /// </summary>
- public BoxSide Left { get; private set; }
- /// <summary>
- /// The BasicEffect used to draw the box.
- /// </summary>
- private BasicEffect effect;
- /// <summary>
- /// An array holding the vertices of the box.
- /// </summary>
- private VertexPositionNormalTexture[] verts;
- /// <summary>
- /// An array holding the indices of the box.
- /// </summary>
- private short[] indices;
- /// <summary>
- /// An array holding the corner positions of the box.
- /// </summary>
- private Vector3[] corners;
- /// <summary>
- /// The GraphicsDevice used to draw the box.
- /// </summary>
- private readonly GraphicsDevice graphicsDevice;
- /// <summary>
- /// Constructs a nondynamic TexturedBox.
- /// </summary>
- /// <param name="pos">The position of the box.</param>
- /// <param name="width">The width of the box.</param>
- /// <param name="height">The height of the box.</param>
- /// <param name="length">The length of the box.</param>
- /// <param name="texture">The texture to apply to all sides of the box.</param>
- /// <param name="graphicsDevice">The graphics device of the game.</param>
- public TexturedBox(Vector3 pos, float width, float height, float length,
- Texture2D texture, GraphicsDevice graphicsDevice)
- : base(pos, width, height, length)
- {
- this.graphicsDevice = graphicsDevice;
- effect = new BasicEffect(graphicsDevice);
- effect.EnableDefaultLighting();
- effect.VertexColorEnabled = false;
- effect.TextureEnabled = true;
- // Apply the texture to all sides of the box.
- // Also, wire up the BoxSide's TextureChanged event to the event handler
- // so that the textures can be modified if any changes are made.
- Top = new BoxSide(BoxSideName.Top, texture);
- Top.TextureOrientationChanged += TextureChangedHandler;
- Bottom = new BoxSide(BoxSideName.Bottom, texture);
- Bottom.TextureOrientationChanged += TextureChangedHandler;
- Front = new BoxSide(BoxSideName.Front, texture);
- Front.TextureOrientationChanged += TextureChangedHandler;
- Back = new BoxSide(BoxSideName.Back, texture);
- Back.TextureOrientationChanged += TextureChangedHandler;
- Right = new BoxSide(BoxSideName.Right, texture);
- Right.TextureOrientationChanged += TextureChangedHandler;
- Left = new BoxSide(BoxSideName.Left, texture);
- Left.TextureOrientationChanged += TextureChangedHandler;
- // Now set up the box.
- InitializeBox();
- }
- /// <summary>
- /// Constructs a physically simulated TexturedBox.
- /// </summary>
- /// <param name="pos">The position of the box.</param>
- /// <param name="width">The width of the box.</param>
- /// <param name="height">The height of the box.</param>
- /// <param name="length">The length of the box.</param>
- /// <param name="mass">The mass of the box.</param>
- /// <param name="texture">The texture to apply to all sides of the box.</param>
- /// <param name="graphicsDevice">The graphics device of the game.</param>
- public TexturedBox(Vector3 pos, float width, float height, float length,
- float mass, Texture2D texture, GraphicsDevice graphicsDevice)
- : base(pos, width, height, length, mass)
- {
- this.graphicsDevice = graphicsDevice;
- effect = new BasicEffect(graphicsDevice);
- effect.EnableDefaultLighting();
- effect.VertexColorEnabled = false;
- effect.TextureEnabled = true;
- // Apply the texture to all sides of the box.
- // Also, wire up the BoxSide's TextureChanged event to the event handler
- // so that the textures can be modified if any changes are made.
- Top = new BoxSide(BoxSideName.Top, texture);
- Top.TextureOrientationChanged += TextureChangedHandler;
- Bottom = new BoxSide(BoxSideName.Bottom, texture);
- Bottom.TextureOrientationChanged += TextureChangedHandler;
- Front = new BoxSide(BoxSideName.Front, texture);
- Front.TextureOrientationChanged += TextureChangedHandler;
- Back = new BoxSide(BoxSideName.Back, texture);
- Back.TextureOrientationChanged += TextureChangedHandler;
- Right = new BoxSide(BoxSideName.Right, texture);
- Right.TextureOrientationChanged += TextureChangedHandler;
- Left = new BoxSide(BoxSideName.Left, texture);
- Left.TextureOrientationChanged += TextureChangedHandler;
- // Now set up the box.
- InitializeBox();
- }
- /// <summary>
- /// Sets up the vertices and indices of the box.
- /// </summary>
- private void InitializeBox()
- {
- // If we haven't already, get the corner positions of the box.
- if (corners == null)
- corners = GetCorners();
- // When working with normals, it's not enough to hold just 8 vertices.
- // We need to hold 4 vertices with unique normals for each side of the box.
- verts = new VertexPositionNormalTexture[24];
- // The bottom/top corners are as if you are looking directly at that face of the box
- // At the top from above, the bottom from below, from the left of the left side, etc.
- // Initialize the vertices for each side of the box.
- InitializeSideVertices(Top);
- InitializeSideVertices(Bottom);
- InitializeSideVertices(Front);
- InitializeSideVertices(Back);
- InitializeSideVertices(Right);
- InitializeSideVertices(Left);
- // Initialize the indices that will be used to draw the triangles of the box.
- indices = new short[]
- {
- // TOP
- 0, 1, 2,
- 1, 3, 2,
- // BOTTOM
- 7, 4, 5,
- 6, 4, 7,
- // FRONT
- 8, 9, 10,
- 9, 11, 10,
- // BACK
- 12, 13, 14,
- 13, 15, 14,
- // RIGHT
- 16, 17, 18,
- 17, 19, 18,
- // LEFT
- 21, 23, 22,
- 20, 21, 22
- };
- }
- /// <summary>
- /// Handler for dealing with a change in texture orientation on a side of the box.
- /// </summary>
- /// <param name="sender">The object that fired the event.</param>
- /// <param name="e">The event arguments.</param>
- private void TextureChangedHandler(object sender, EventArgs e)
- {
- // Cast the sender object as a BoxSide
- BoxSide boxSide = sender as BoxSide;
- // Reset the vertices for that side of the box.
- InitializeSideVertices(boxSide);
- }
- /// <summary>
- /// Sets up the vertices for a certain side of the box.
- /// </summary>
- /// <param name="side">The side to set the vertices for.</param>
- private void InitializeSideVertices(BoxSide side)
- {
- // Create a Vector2 array to hold the 4 texture coordinates of the side.
- Vector2[] textureCorners;
- // Now, check to see which side will get its vertices set.
- // Also, we need to get the texture coordinates for each side
- // via the DetermineTextureCoords function to see if any flipping is needed.
- if (side.Name == BoxSideName.Top)
- {
- // TOP OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Top);
- // Top left corner
- verts[0] = new VertexPositionNormalTexture(
- corners[4], Vector3.Up, textureCorners[0]);
- // Top right corner
- verts[1] = new VertexPositionNormalTexture(
- corners[5], Vector3.Up, textureCorners[1]);
- // Bottom left corner
- verts[2] = new VertexPositionNormalTexture(
- corners[0], Vector3.Up, textureCorners[3]);
- // Bottom right corner
- verts[3] = new VertexPositionNormalTexture(
- corners[1], Vector3.Up, textureCorners[2]);
- //---------------------------------------
- }
- else if (side.Name == BoxSideName.Bottom)
- {
- // BOTTOM OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Bottom);
- // Top left corner
- verts[4] = new VertexPositionNormalTexture(
- corners[3], Vector3.Down, textureCorners[0]);
- // Top right corner
- verts[5] = new VertexPositionNormalTexture(
- corners[2], Vector3.Down, textureCorners[1]);
- // Bottom left corner
- verts[6] = new VertexPositionNormalTexture(
- corners[7], Vector3.Down, textureCorners[3]);
- // Bottom right corner
- verts[7] = new VertexPositionNormalTexture(
- corners[6], Vector3.Down, textureCorners[2]);
- //---------------------------------------
- }
- else if (side.Name == BoxSideName.Front)
- {
- // FRONT OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Front);
- // Top left corner
- verts[8] = new VertexPositionNormalTexture(
- corners[0], Vector3.Backward, textureCorners[0]);
- // Top right corner
- verts[9] = new VertexPositionNormalTexture(
- corners[1], Vector3.Backward, textureCorners[1]);
- // Bottom left corner
- verts[10] = new VertexPositionNormalTexture(
- corners[3], Vector3.Backward, textureCorners[3]);
- // Bottom right corner
- verts[11] = new VertexPositionNormalTexture(
- corners[2], Vector3.Backward, textureCorners[2]);
- //---------------------------------------
- }
- else if (side.Name == BoxSideName.Back)
- {
- // BACK OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Back);
- // Top left corner
- verts[12] = new VertexPositionNormalTexture(
- corners[5], Vector3.Forward, textureCorners[0]);
- // Top right corner
- verts[13] = new VertexPositionNormalTexture(
- corners[4], Vector3.Forward, textureCorners[1]);
- // Bottom left corner
- verts[14] = new VertexPositionNormalTexture(
- corners[6], Vector3.Forward, textureCorners[3]);
- // Bottom right corner
- verts[15] = new VertexPositionNormalTexture(
- corners[7], Vector3.Forward, textureCorners[2]);
- //---------------------------------------
- }
- else if (side.Name == BoxSideName.Right)
- {
- // RIGHT OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Right);
- // Top left corner
- verts[16] = new VertexPositionNormalTexture(
- corners[1], Vector3.Right, textureCorners[0]);
- // Top right corner
- verts[17] = new VertexPositionNormalTexture(
- corners[5], Vector3.Right, textureCorners[1]);
- // Bottom left corner
- verts[18] = new VertexPositionNormalTexture(
- corners[2], Vector3.Right, textureCorners[3]);
- // Bottom right corner
- verts[19] = new VertexPositionNormalTexture(
- corners[6], Vector3.Right, textureCorners[2]);
- //---------------------------------------
- }
- else if (side.Name == BoxSideName.Left)
- {
- // LEFT OF THE BOX
- //---------------------------------------
- textureCorners = DetermineTextureCoords(Left);
- // Top left corner
- verts[20] = new VertexPositionNormalTexture(
- corners[4], Vector3.Left, textureCorners[0]);
- // Top right corner
- verts[21] = new VertexPositionNormalTexture(
- corners[0], Vector3.Left, textureCorners[1]);
- // Bottom left corner
- verts[22] = new VertexPositionNormalTexture(
- corners[7], Vector3.Left, textureCorners[3]);
- // Bottom right corner
- verts[23] = new VertexPositionNormalTexture(
- corners[3], Vector3.Left, textureCorners[2]);
- //---------------------------------------
- }
- }
- /// <summary>
- /// Gets the corner positions of the box.
- /// </summary>
- /// <returns>An array holding the corner positions of the box.</returns>
- private Vector3[] GetCorners()
- {
- // The corner positions will be centered around the world origin.
- // Any transformations needed can be applied in the world matrix when it's time to draw.
- float maxX = this.HalfLength;
- float minX = -maxX;
- float maxY = this.HalfHeight;
- float minY = -maxY;
- float maxZ = this.HalfWidth;
- float minZ = -maxZ;
- // Now we need to set up the array that will hold the positions of the corners.
- // This array is ordered like in the MSDN samples:
- // ZMax ZMin
- // 0----1 4----5
- // | | | |
- // | | | |
- // 3----2 7----6
- Vector3[] corners = new Vector3[]
- {
- new Vector3(minX, maxY, maxZ),
- new Vector3(maxX, maxY, maxZ),
- new Vector3(maxX, minY, maxZ),
- new Vector3(minX, minY, maxZ),
- new Vector3(minX, maxY, minZ),
- new Vector3(maxX, maxY, minZ),
- new Vector3(maxX, minY, minZ),
- new Vector3(minX, minY, minZ)
- };
- return corners;
- }
- /// <summary>
- /// Draws the box.
- /// </summary>
- /// <param name="view">The camera's view matrix.</param>
- /// <param name="projection">The camera's projection matrix.</param>
- public void Draw(Matrix view, Matrix projection)
- {
- // The box is currently centered at the origin.
- // The world matrix will transform it to the correct position and orientation.
- Matrix world = Matrix.Identity;
- world *= Matrix.CreateFromQuaternion(this.Orientation);
- world *= Matrix.CreateTranslation(this.Position);
- // Set the values for the WVP matrices.
- effect.World = world;
- effect.View = view;
- effect.Projection = projection;
- // Now draw the box.
- foreach (EffectPass pass in effect.CurrentTechnique.Passes)
- {
- // To account for different textures on each side of the box,
- // We need to set the effect's texture and reapply the pass before drawing
- // each side.
- // Top
- effect.Texture = Top.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 0, 2);
- // Bottom
- effect.Texture = Bottom.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 6, 2);
- // Front
- effect.Texture = Front.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 12, 2);
- // Back
- effect.Texture = Back.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 18, 2);
- // Right
- effect.Texture = Right.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 24, 2);
- // Left
- effect.Texture = Left.Texture;
- pass.Apply();
- graphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
- verts, 0, verts.Length, indices, 30, 2);
- }
- }
- /// <summary>
- /// Sets all the textures on the sides of the box to the given texture.
- /// </summary>
- /// <param name="texture">The texture to be applied to the sides of the box.</param>
- public void SetAllTextures(Texture2D texture)
- {
- Top.Texture = texture;
- Bottom.Texture = texture;
- Front.Texture = texture;
- Back.Texture = texture;
- Right.Texture = texture;
- Left.Texture = texture;
- }
- /// <summary>
- /// Gets the texture coordinates for the side of a box.
- /// </summary>
- /// <param name="side">The side to get texture coordinates from.</param>
- /// <returns>An array holding the 4 texture coordinates of the box from the top left coordinate
- /// in clockwise order.</returns>
- private Vector2[] DetermineTextureCoords(BoxSide side)
- {
- // Create the 4 Vector2's that will hold each corner's texture coordinate.
- Vector2 topLeft, topRight, bottomLeft, bottomRight;
- // Do this if only a horizontal flipping is needed.
- if (side.FlipTextureHorizontal && !side.FlipTextureVertical)
- {
- topLeft = new Vector2(1f, 0f);
- topRight = Vector2.Zero;
- bottomLeft = Vector2.One;
- bottomRight = new Vector2(0f, 1f);
- }
- // Do this if only a vertical flipping is needed.
- else if (side.FlipTextureVertical && !side.FlipTextureHorizontal)
- {
- topLeft = new Vector2(0f, 1f);
- topRight = Vector2.One;
- bottomLeft = Vector2.Zero;
- bottomRight = new Vector2(1f, 0f);
- }
- // Do this if both a horizontal and vertical flipping are needed.
- else if (side.FlipTextureHorizontal && side.FlipTextureVertical)
- {
- topLeft = Vector2.One;
- topRight = new Vector2(0f, 1f);
- bottomLeft = new Vector2(1f, 0f);
- bottomRight = Vector2.Zero;
- }
- // If we've come to here, then no flipping was needed at all.
- // Just set the default texture coordinates.
- else
- {
- topLeft = Vector2.Zero;
- topRight = new Vector2(1f, 0f);
- bottomLeft = new Vector2(0f, 1f);
- bottomRight = Vector2.One;
- }
- return new Vector2[]
- {
- topLeft,
- topRight,
- bottomRight,
- bottomLeft
- };
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement