source: 2013/30/MiskaK/MW2(My Warfare 2)/Krypton/ShadowHull.cs @ 4507

Revision 4507, 8.1 KB checked in by anlakane, 6 years ago (diff)

Talletus.

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Microsoft.Xna.Framework;
6using Microsoft.Xna.Framework.Graphics;
7using Krypton.Common;
8
9namespace Krypton
10{
11    /// <summary>
12    /// A hull used for casting shadows from a light source
13    /// </summary>
14    public class ShadowHull
15    {
16        #region Orientation
17
18        /// <summary>
19        /// The position of the shadow hull
20        /// </summary>
21        public Vector2 Position;
22
23        /// <summary>
24        /// The angle of the shadow hull
25        /// </summary>
26        public float Angle;
27
28        #endregion
29
30        #region Shape
31
32        /// <summary>
33        /// The maximum radius in which all of the shadow hull's vertices are contained, originating from the hull's position
34        /// </summary>
35        public float MaxRadius;
36
37        /// <summary>
38        /// The vertices comprising the shadow hull
39        /// </summary>
40        public ShadowHullPoint[] Points;
41
42        /// <summary>
43        /// The number of vertices comprising the shadow hull
44        /// </summary>
45        public int NumPoints;
46
47        /// <summary>
48        /// The indicies used to render the shadow hull
49        /// </summary>
50        public Int32[] Indicies;
51
52        /// <summary>
53        /// The number of indicies used to render the shadow hull
54        /// </summary>
55        public int NumIndicies;
56
57        /// <summary>
58        /// A value indicating if the hull should cast a shadow
59        /// </summary>
60        public bool Visible = true;
61
62        /// <summary>
63        /// A value indicating how much to stretch the hull
64        /// </summary>
65        public Vector2 Scale = Vector2.One;
66
67        #endregion
68
69        private ShadowHull(){}
70
71        #region Factory Methods
72
73        /// <summary>
74        /// Creates a rectangular shadow hull
75        /// </summary>
76        /// <param name="size">The dimensions of the rectangle</param>
77        /// <returns>A rectangular shadow hull</returns>
78        public static ShadowHull CreateRectangle(Vector2 size)
79        {
80            ShadowHull hull = new ShadowHull();
81
82            size *= 0.5f;
83
84            hull.MaxRadius = (float)Math.Sqrt(size.X * size.X + size.Y * size.Y);
85
86            hull.NumPoints = 4 * 2;
87            var numTris = hull.NumPoints - 2;
88            hull.NumIndicies = numTris * 3;
89
90            hull.Points = new ShadowHullPoint[hull.NumPoints];
91            hull.Indicies = new Int32[hull.NumIndicies];
92
93            // Vertex position
94            var posTR = new Vector2(+size.X, +size.Y);
95            var posBR = new Vector2(+size.X, -size.Y);
96            var posBL = new Vector2(-size.X, -size.Y);
97            var posTL = new Vector2(-size.X, +size.Y);
98
99            // Right
100            hull.Points[0] = new ShadowHullPoint(posTR, Vector2.UnitX);
101            hull.Points[1] = new ShadowHullPoint(posBR, Vector2.UnitX);
102                                                             
103            // Bottom                                         
104            hull.Points[2] = new ShadowHullPoint(posBR, -Vector2.UnitY);
105            hull.Points[3] = new ShadowHullPoint(posBL, -Vector2.UnitY);
106                                                             
107            // Left                                           
108            hull.Points[4] = new ShadowHullPoint(posBL, -Vector2.UnitX);
109            hull.Points[5] = new ShadowHullPoint(posTL, -Vector2.UnitX);
110
111            // Top
112            hull.Points[6] = new ShadowHullPoint(posTL, Vector2.UnitY);
113            hull.Points[7] = new ShadowHullPoint(posTR, Vector2.UnitY);
114
115            // Create tris
116            for (int i = 0; i < numTris; i++)
117            {
118                hull.Indicies[i * 3 + 0] = 0;
119                hull.Indicies[i * 3 + 1] = i + 1;
120                hull.Indicies[i * 3 + 2] = i + 2;
121            }
122
123            return hull;
124        }
125
126        /// <summary>
127        /// Creates a circular shadow hull
128        /// </summary>
129        /// <param name="radius">radius of the circle</param>
130        /// <param name="sides">number of sides the circle will be comprised of</param>
131        /// <returns>A circular shadow hull</returns>
132        public static ShadowHull CreateCircle(float radius, int sides)
133        {
134            // Validate input
135            if (sides < 3) { throw new ArgumentException("Shadow hull must have at least 3 sides."); }
136
137            ShadowHull hull = new ShadowHull();
138
139            hull.MaxRadius = radius;
140
141            // Calculate number of sides
142            hull.NumPoints = sides * 2;
143            var numTris = hull.NumPoints - 2;
144            hull.NumIndicies = numTris * 3;
145           
146            hull.Points = new ShadowHullPoint[hull.NumPoints];
147            hull.Indicies = new Int32[hull.NumIndicies];
148
149            var angle = (float)(-Math.PI * 2) / sides; // XNA Renders Clockwise
150            var angleOffset = angle / 2;
151
152            for (int i = 0; i < sides; i++)
153            {
154                // Create vertices
155                var v1 = new ShadowHullPoint();
156                var v2 = new ShadowHullPoint();
157
158                // Vertex Position
159                v1.Position.X = (float)Math.Cos(angle * i) * radius;
160                v1.Position.Y = (float)Math.Sin(angle * i) * radius;
161
162                v2.Position.X = (float)Math.Cos(angle * (i + 1)) * radius;
163                v2.Position.Y = (float)Math.Sin(angle * (i + 1)) * radius;
164
165                // Vertex Normal
166                v1.Normal.X = (float)Math.Cos(angle * i + angleOffset);
167                v1.Normal.Y = (float)Math.Sin(angle * i + angleOffset);
168
169                v2.Normal.X = (float)Math.Cos(angle * i + angleOffset);
170                v2.Normal.Y = (float)Math.Sin(angle * i + angleOffset);
171
172                // Copy vertices
173                hull.Points[i * 2 + 0] = v1;
174                hull.Points[i * 2 + 1] = v2;
175            }
176
177            for (int i = 0; i < numTris; i++)
178            {
179                hull.Indicies[i * 3 + 0] = 0;
180                hull.Indicies[i * 3 + 1] = (Int32)(i + 1);
181                hull.Indicies[i * 3 + 2] = (Int32)(i + 2);
182            }
183
184            return hull;
185        }
186
187        /// <summary>
188        /// Creates a custom shadow hull based on a series of vertices
189        /// </summary>
190        /// <param name="points">The points which the shadow hull will be comprised of</param>
191        /// <returns>A custom shadow hulll</returns>
192        public static ShadowHull CreateConvex(ref Vector2[] points)
193        {
194            // Validate input
195            if (points == null) { throw new ArgumentNullException("Points cannot be null."); }
196            if (points.Length < 3) { throw new ArgumentException("Need at least 3 points to create shadow hull."); }
197
198            var numPoints = points.Length;
199
200            ShadowHull hull = new ShadowHull();
201
202            hull.NumPoints = numPoints * 2;
203            var numTris = hull.NumPoints - 2;
204            hull.NumIndicies = numTris * 3;
205
206            hull.Points = new ShadowHullPoint[hull.NumPoints];
207            hull.Indicies = new Int32[hull.NumIndicies];
208
209            Vector2 pointMin = points[0];
210            Vector2 pointMax = points[0];
211
212            for (int i = 0; i < numPoints; i++)
213            {
214                var p1 = points[(i + 0) % numPoints];
215                var p2 = points[(i + 1) % numPoints];
216
217                hull.MaxRadius = Math.Max(hull.MaxRadius, p1.Length());
218
219                var line = p2 - p1;
220
221                var normal = new Vector2(-line.Y, +line.X);
222
223                normal.Normalize();
224
225                hull.Points[i * 2 + 0] = new ShadowHullPoint(p1, normal);
226                hull.Points[i * 2 + 1] = new ShadowHullPoint(p2, normal);
227            }
228
229            for (Int32 i = 0; i < numTris; i++)
230            {
231                hull.Indicies[i * 3 + 0] = 0;
232                hull.Indicies[i * 3 + 1] = (Int32)(i + 1);
233                hull.Indicies[i * 3 + 2] = (Int32)(i + 2);
234            }
235
236            return hull;
237        }
238
239        #endregion
240    }
241}
Note: See TracBrowser for help on using the repository browser.