Advertisement
Guest User

Untitled

a guest
Jul 10th, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 19.47 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Audio;
  6. using Microsoft.Xna.Framework.Content;
  7. using Microsoft.Xna.Framework.GamerServices;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using Microsoft.Xna.Framework.Input;
  10. using Microsoft.Xna.Framework.Media;
  11.  
  12. namespace DrawingTriangles
  13. {
  14.     /// <summary>
  15.     /// This is the main type for your game
  16.     /// </summary>
  17.     public class Game1 : Microsoft.Xna.Framework.Game
  18.     {
  19.         GraphicsDeviceManager graphics;
  20.  
  21.         VertexBuffer vertexBuffer;
  22.         VertexBuffer vertexBuffer2;
  23.  
  24.         int modelindexes = 0;
  25.  
  26.         short[] indexElements;
  27.  
  28.         IEnumerable<TriangleVertices> triverts = new List<TriangleVertices> { };
  29.  
  30.         TriangleVertices[] trisvertss;
  31.         TriangleVertices[] tristext;
  32.         VertexPositionColor[] vertices;
  33.         VertexPositionColor[] vertices2;
  34.         VertexPositionColor[] vertices3;
  35.         VertexPositionColor[] vertices4;
  36.         VertexPositionColor[] vertices5;
  37.  
  38.         int finder;
  39.  
  40.         Vector3 lightDir = new Vector3(-0.3333333f, 0.6666667f, -0.6666667f); //directional light parameter. its a vector 3 that you draw a line from 0,0,0 to - and get an arrow.
  41.  
  42.         BasicEffect basicEffect;
  43.         Matrix world = Matrix.CreateTranslation(0, 0, -625) * Matrix.CreateScale(new Vector3(0.005f, 0.005f, 0.004f)) * Matrix.CreateRotationX(MathHelper.ToRadians(-90));
  44.         Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 3), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
  45.         Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(60), 800f / 480f, 0.01f, 100f);
  46.  
  47.         Model testModel;
  48.         List<TriangleVertices> triverts2;
  49.  
  50.         Vector3[] allVertex;
  51.         TriangleVertices[] number1;
  52.         List<Edge> edgelist;
  53.         List<Edge> edgelist2;
  54.  
  55.  
  56.         double angle = 0;
  57.  
  58.         public Game1()
  59.         {
  60.             graphics = new GraphicsDeviceManager(this);
  61.             graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8;
  62.             Content.RootDirectory = "Content";
  63.         }
  64.  
  65.         /// <summary>
  66.         /// Allows the game to perform any initialization it needs to before starting to run.
  67.         /// This is where it can query for any required services and load any non-graphic
  68.         /// related content.  Calling base.Initialize will enumerate through any components
  69.         /// and initialize them as well.
  70.         /// </summary>
  71.         protected override void Initialize()
  72.         {
  73.             base.Initialize();
  74.         }
  75.  
  76.         public struct TriangleVertices
  77.         {
  78.  
  79.             /// <summary>Initializes a new triangle vertices instance</summary>
  80.             /// <param name="a">First vertex of the triangle</param>
  81.             /// <param name="b">Second vertex of the triangle</param>
  82.             /// <param name="c">Third vertex of the triangle</param>
  83.             public TriangleVertices(Vector3 a, Vector3 b, Vector3 c)
  84.             {
  85.                 this.A = a;
  86.                 this.B = b;
  87.                 this.C = c;
  88.             }
  89.             /// <summary>The triangle's first vertex</summary>
  90.             public Vector3 A;
  91.             /// <summary>The triangle's second vertex</summary>
  92.             public Vector3 B;
  93.             /// <summary>The triangle's third vertex</summary>
  94.             public Vector3 C;
  95.  
  96.         }
  97.  
  98.         public class Face
  99.         {
  100.             /// <summary>Initializes a new face</summary>
  101.             /// <param name="normal"></param>
  102.             public Face(Vector3 normal)
  103.             {
  104.                 this.Normal = normal;
  105.             }
  106.             /// <summary>Normal vector of the face</summary>
  107.             public Vector3 Normal;
  108.         }
  109.  
  110.  
  111.         public class Edge
  112.         {
  113.             /// <summary>Initializes a new edge</summary>
  114.             /// <param name="leftVertex">Vertex on the left side of the edge</param>
  115.             /// <param name="rightVertex">Vertex on the right side of the edge</param>
  116.             public Edge(Vector3 leftVertex, Vector3 rightVertex)
  117.             {
  118.                 this.LeftVertex = leftVertex;
  119.                 this.RightVertex = rightVertex;
  120.             }
  121.             /// <summary>The vertex on the left side of the edge</summary>
  122.             public Vector3 LeftVertex;
  123.             /// <summary>The vertex on the right side of the edge</summary>
  124.             public Vector3 RightVertex;
  125.             /// <summary>The face to the top of the edge</summary>
  126.             public Face UpperFace;
  127.             /// <summary>The face to the bottom of the edge</summary>
  128.             public Face LowerFace;
  129.         }
  130.  
  131.         /// <summary>
  132.         /// LoadContent will be called once per game and is the place to load
  133.         /// all of your content.
  134.         /// </summary>
  135.         protected override void LoadContent()
  136.         {
  137.  
  138.             testModel = Content.Load<Model>("teststage2");
  139.             basicEffect = new BasicEffect(GraphicsDevice);
  140.  
  141.             foreach (ModelMesh mesh in testModel.Meshes)
  142.             {
  143.                 foreach (ModelMeshPart part in mesh.MeshParts)
  144.                 {
  145.                     modelindexes += part.IndexBuffer.IndexCount;
  146.                 }
  147.             }
  148.  
  149.             vertices = new VertexPositionColor[modelindexes];
  150.             triverts = new TriangleVertices[0];
  151.  
  152.  
  153.             int offset = 0;
  154.  
  155.             foreach (ModelMesh mesh in testModel.Meshes)
  156.             {
  157.                 foreach (ModelMeshPart part in mesh.MeshParts)
  158.                 {
  159.                     VertexDeclaration declaration = part.VertexBuffer.VertexDeclaration;
  160.                     VertexElement vertexPosition = new VertexElement();
  161.  
  162.                     // This where we store the vertices until transformed  
  163.                     allVertex = new Vector3[part.NumVertices];
  164.                     // Read the vertices from the buffer in to the array  
  165.                     part.VertexBuffer.GetData<Vector3>(
  166.                         part.VertexOffset * declaration.VertexStride + vertexPosition.Offset,
  167.                         allVertex,
  168.                         0,
  169.                         part.NumVertices,
  170.                         declaration.VertexStride);
  171.  
  172.                     // Each primitive is a triangle  
  173.                     indexElements = new short[part.PrimitiveCount * 3];
  174.                     part.IndexBuffer.GetData<short>(
  175.                         part.StartIndex * 2,
  176.                         indexElements,
  177.                         0,
  178.                         part.PrimitiveCount * 3);
  179.  
  180.  
  181.                     VertexPositionColor[] borrowVerts = new VertexPositionColor[indexElements.Length];
  182.  
  183.  
  184.                     for (int i = 0; i < indexElements.Length; i++)
  185.                     {
  186.                         borrowVerts[i].Position.X = allVertex[indexElements[i]].X;
  187.                         borrowVerts[i].Position.Y = allVertex[indexElements[i]].Y;
  188.                         borrowVerts[i].Position.Z = allVertex[indexElements[i]].Z;
  189.        
  190.                         vertices[offset + i].Position = borrowVerts[i].Position;
  191.                     }
  192.  
  193.                     offset += indexElements.Length;
  194.  
  195.                 }
  196.             }
  197.  
  198.  
  199.  
  200.             Vector3 vert = new Vector3();
  201.             Vector3 vert2 = new Vector3();
  202.             Vector3 vert3 = new Vector3();
  203.  
  204.             trisvertss = new TriangleVertices[vertices.Length / 3];
  205.  
  206.             TriangleVertices number0;
  207.  
  208.             number0.A = vertices[0].Position;
  209.             number0.B = vertices[1].Position;
  210.             number0.C = vertices[2].Position;
  211.  
  212.             number1 = new TriangleVertices[vertices.Length / 3];
  213.  
  214.             for (int i = 0; i < vertices.Length / 3; i += 3)
  215.             {
  216.                 number1[i].A = vertices[i].Position;
  217.                 number1[i].B = vertices[i + 1].Position;
  218.                 number1[i].C = vertices[i + 2].Position;
  219.             }
  220.  
  221.  
  222.             triverts2 = new List<TriangleVertices> { number0 };
  223.  
  224.             int j = vertices.Length / 3; //number of triangles
  225.             int k = 0; //counter
  226.            
  227.  
  228.             //method to make 3 vertices triangle format for each triangle and add them to a list.
  229.             for (int i = 0; i < j; i++)
  230.             {
  231.                 vert = vertices[(i * 3)].Position;
  232.                 vert2 = vertices[(i * 3) + 1].Position;
  233.                 vert3 = vertices[(i * 3) + 2].Position;
  234.  
  235.                 if (k < j)
  236.                 {
  237.                     trisvertss[k].A = vert;
  238.                     trisvertss[k].B = vert2;
  239.                     trisvertss[k].C = vert3;
  240.  
  241.                     TriangleVertices tristorage = new TriangleVertices(vert, vert2, vert3);
  242.                     if (k > 0)
  243.                     {
  244.                         triverts2.Add(tristorage);
  245.                     }
  246.                     Enumerable.Concat<TriangleVertices>(triverts, triverts2);
  247.  
  248.                     k++;
  249.                 }
  250.             }
  251.  
  252.             triverts = triverts.Concat(triverts2);
  253.             edgelist = new List<Edge>(trisvertss.Length * 3);
  254.  
  255.  
  256.             //method for breaking up the triangles into edges.
  257.             foreach (TriangleVertices triangle in trisvertss)
  258.             {
  259.                 Face face = new Face(Vector3.Cross(triangle.B - triangle.A, triangle.C - triangle.A));
  260.                 Edge edge;
  261.                 edge = new Edge(triangle.A, triangle.B);
  262.                 edge.UpperFace = face;
  263.                 edgelist.Add(edge);
  264.                 edge = new Edge(triangle.B, triangle.C);
  265.                 edge.UpperFace = face;
  266.                 edgelist.Add(edge);
  267.                 edge = new Edge(triangle.C, triangle.A);
  268.                 edge.UpperFace = face;
  269.                 edgelist.Add(edge);
  270.             }
  271.  
  272.             vertices4 = new VertexPositionColor[vertices.Length];
  273.             vertices5 = new VertexPositionColor[vertices.Length];
  274.  
  275.             for(int i = 0; i < trisvertss.Length; i++)
  276.             {
  277.                 Face face = new Face(Vector3.Cross(trisvertss[i].B - trisvertss[i].A, trisvertss[i].C - trisvertss[i].A));
  278.                 float upperFaceDot = Vector3.Dot(face.Normal, lightDir);
  279.  
  280.                 //these are cap triangles.
  281.                 if (upperFaceDot > 0)
  282.                 {
  283.                     vertices4[i * 3] = new VertexPositionColor(trisvertss[i].A, new Color(0, 0, 0, 0));
  284.                     vertices4[i * 3 + 1] = new VertexPositionColor(trisvertss[i].B, new Color(0, 0, 0, 0));
  285.                     vertices4[i * 3 + 2] = new VertexPositionColor(trisvertss[i].C, new Color(0, 0, 0, 0));
  286.                 }
  287.             }
  288.  
  289.             //whatever is left is the other cap! since we're splitting the model in 2 and adding quads to extend the shape out.
  290.             for (int i = 0; i < trisvertss.Length; i++)
  291.             {
  292.                 vertices5[i * 3] = new VertexPositionColor(trisvertss[i].A, Color.Gray);
  293.                 vertices5[i * 3 + 1] = new VertexPositionColor(trisvertss[i].B, Color.Gray);
  294.                 vertices5[i * 3 + 2] = new VertexPositionColor(trisvertss[i].C, Color.Gray);
  295.             }
  296.            
  297.  
  298.             edgelist2 = new List<Edge>(edgelist.Count / 2);
  299.  
  300.  
  301.  
  302.             //method for adding only non-repeating edges to a new edgelist. using the variable finder to find duplicates to discard.
  303.             for (int i = 0; i < edgelist.Count; i++)
  304.             {
  305.                 finder = edgelist.FindIndex(item => item.RightVertex == edgelist[i].LeftVertex && item.LeftVertex == edgelist[i].RightVertex);
  306.                 edgelist[i].LowerFace = edgelist[finder].UpperFace;
  307.                 if (i < finder)
  308.                 {
  309.                     edgelist2.Add(edgelist[i]);
  310.                 }
  311.             }
  312.  
  313.             edgelist.Clear(); //no longer need this.
  314.  
  315.             foreach (Edge edge in edgelist2)
  316.             {
  317.                 float upperFaceDot = Vector3.Dot(edge.UpperFace.Normal, lightDir);
  318.                 float lowerFaceDot = Vector3.Dot(edge.LowerFace.Normal, lightDir);
  319.                 bool upperFaceVisible = (upperFaceDot > 0);
  320.                 bool lowerFacevisible = (lowerFaceDot > 0);
  321.                 Edge nuEdge;
  322.  
  323.                 if (lowerFacevisible)
  324.                 {
  325.                     if (!upperFaceVisible)
  326.                     {
  327.                         nuEdge = new Edge(edge.RightVertex, edge.LeftVertex);
  328.                         edgelist.Add(nuEdge);
  329.                     }
  330.                 }
  331.                 else
  332.                 {
  333.                     if (upperFaceVisible)
  334.                     {
  335.                         nuEdge = new Edge(edge.LeftVertex, edge.RightVertex);
  336.                         edgelist.Add(nuEdge);
  337.                     }
  338.                 }
  339.  
  340.  
  341.             }
  342.  
  343.  
  344.  
  345.             vertices2 = new VertexPositionColor[edgelist.Count * 3 * 2];
  346.  
  347.  
  348.  
  349.             Vector3 extrusion = lightDir * 4000;
  350.  
  351.  
  352.             for (int i = 0; i < edgelist.Count ; i++)            
  353.             {
  354.                 Plane planar = new Plane(edgelist[i].LeftVertex, edgelist[i].LeftVertex + extrusion, edgelist[i].RightVertex);
  355.  
  356.                 //BUILD QUADS
  357.                 vertices2[(i * 6) + 5] = new VertexPositionColor(edgelist[i].LeftVertex, new Color(0, 0, 0, 0));
  358.                 vertices2[(i * 6) + 4] = new VertexPositionColor(edgelist[i].LeftVertex + extrusion, new Color(0, 0, 0, 0));
  359.                 vertices2[(i * 6) + 3] = new VertexPositionColor(edgelist[i].RightVertex + extrusion, new Color(0, 0, 0, 0));
  360.                 vertices2[(i * 6) + 2] = new VertexPositionColor(edgelist[i].LeftVertex, new Color(0, 0, 0, 0));
  361.                 vertices2[(i * 6) + 1] = new VertexPositionColor(edgelist[i].RightVertex + extrusion, new Color(0, 0, 0, 0));
  362.                 vertices2[(i * 6)] = new VertexPositionColor(edgelist[i].RightVertex, new Color(0, 0, 0, 0));
  363.               }
  364.  
  365.  
  366.  
  367.             vertices3 = new VertexPositionColor[(vertices4.Length * 2) + vertices2.Length];
  368.  
  369.  
  370.             int backfaces = vertices4.Length;
  371.  
  372.             //add triangles flipped.
  373.             for (int i = 0; i < vertices4.Length; i++)
  374.             {
  375.                 vertices3[i] = new VertexPositionColor(vertices4[backfaces - 1].Position + extrusion, new Color(0, 0, 0, 0));
  376.                 backfaces--;
  377.             }
  378.             //add more triangles from the shadow volume
  379.             for (int i = vertices4.Length; i < vertices4.Length + vertices2.Length; i++)
  380.             {
  381.                 vertices3[i] = vertices2[i - vertices4.Length];
  382.             }
  383.             //finish adding the other cap here.
  384.             for (int i = vertices2.Length + vertices4.Length; i < (vertices4.Length * 2) + vertices2.Length; i++)
  385.             {
  386.                 vertices3[i] = new VertexPositionColor(vertices4[i - (vertices2.Length + vertices4.Length)].Position, new Color(0, 0, 0, 0));
  387.             }
  388.  
  389.  
  390.  
  391.  
  392.             tristext = new TriangleVertices[trisvertss.Count()];
  393.  
  394.             vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), vertices3.Length, BufferUsage.WriteOnly);
  395.             vertexBuffer.SetData<VertexPositionColor>(vertices3);
  396.  
  397.             vertexBuffer2 = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), vertices5.Length, BufferUsage.WriteOnly);
  398.             vertexBuffer2.SetData<VertexPositionColor>(vertices5);
  399.  
  400.  
  401.         }
  402.  
  403.  
  404.         protected override void UnloadContent()
  405.         {
  406.  
  407.         }
  408.  
  409.  
  410.         protected override void Update(GameTime gameTime)
  411.         {
  412.             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  413.                 this.Exit();
  414.  
  415.             angle += 0.01f;
  416.             view = Matrix.CreateLookAt(
  417.                 new Vector3(5 * (float)Math.Sin(angle), -2, 5 * (float)Math.Cos(angle)),
  418.                 new Vector3(0, 0, 0),
  419.                 Vector3.UnitY);
  420.  
  421.             base.Update(gameTime);
  422.         }
  423.  
  424.  
  425.         DepthStencilState addIfMirror = new DepthStencilState()
  426.         {
  427.             DepthBufferEnable = true,
  428.             DepthBufferWriteEnable = false,
  429.             StencilEnable = true,
  430.             //TwoSidedStencilMode = true,
  431.             StencilFunction = CompareFunction.Always,
  432.  
  433.             StencilPass = StencilOperation.Increment,
  434.             //CounterClockwiseStencilPass = StencilOperation.Decrement
  435.         };
  436.  
  437.         DepthStencilState addIfMirror2 = new DepthStencilState()
  438.         {
  439.             DepthBufferEnable = true,
  440.             DepthBufferWriteEnable = false,
  441.             StencilEnable = true,
  442.             StencilFunction = CompareFunction.Always,
  443.             StencilPass = StencilOperation.Decrement,
  444.         };
  445.  
  446.         DepthStencilState checkMirror = new DepthStencilState()
  447.         {
  448.  
  449.             StencilEnable = true,
  450.             StencilFunction = CompareFunction.Equal,
  451.             ReferenceStencil = 1,
  452.             StencilPass = StencilOperation.Keep
  453.         };
  454.  
  455.  
  456.         /// <summary>
  457.         /// This is called when the game should draw itself.
  458.         /// </summary>
  459.         /// <param name="gameTime">Provides a snapshot of timing values.</param>
  460.         protected override void Draw(GameTime gameTime)
  461.         {
  462.             GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer | ClearOptions.Stencil, Color.CornflowerBlue, 1, 0);
  463.             DepthStencilState depthStencil = new DepthStencilState();
  464.  
  465.             depthStencil.DepthBufferEnable = true;
  466.             depthStencil.DepthBufferWriteEnable = true;
  467.             //depthStencil.
  468.             depthStencil.StencilEnable = true;
  469.  
  470.             GraphicsDevice.DepthStencilState = depthStencil;
  471.  
  472.              
  473.             GraphicsDevice.Clear(Color.CornflowerBlue);
  474.  
  475.             basicEffect.World = world;
  476.             basicEffect.View = view;
  477.             basicEffect.Projection = projection;
  478.             basicEffect.VertexColorEnabled = true;
  479.  
  480.             //RENDER LEVEL IN GRAY COLOR.
  481.             GraphicsDevice.SetVertexBuffer(vertexBuffer2);
  482.             GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  483.             basicEffect.CurrentTechnique.Passes[0].Apply();
  484.             GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexBuffer2.VertexCount / 3);
  485.  
  486.             //DO STENCIL OPERATIONS RENDERING FRONT AND BACK FACES OF SHADOW VOLUME!
  487.             GraphicsDevice.BlendState = BlendState.AlphaBlend;
  488.             GraphicsDevice.DepthStencilState = addIfMirror; //increment stencil
  489.  
  490.             GraphicsDevice.SetVertexBuffer(vertexBuffer);
  491.             basicEffect.CurrentTechnique.Passes[0].Apply();
  492.  
  493.             GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  494.             GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexBuffer.VertexCount / 3);
  495.  
  496.             GraphicsDevice.DepthStencilState = addIfMirror2; //decrement stencil
  497.             GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
  498.             GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexBuffer.VertexCount / 3);
  499.  
  500.             //RENDER THE SHADOW ITSELF
  501.             GraphicsDevice.BlendState = BlendState.Opaque;
  502.             GraphicsDevice.DepthStencilState = checkMirror;
  503.  
  504.             GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.CornflowerBlue, 1, 0); //need to clear the depth buffer. not sure why that is but it's the way it's done.
  505.             GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  506.             GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexBuffer.VertexCount / 3);
  507.             base.Draw(gameTime);
  508.         }
  509.  
  510.     }
  511. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement