___________________________________________________________________ / ___ _ ___ _ _ _ _ \ / / __\ __ _ ___(_) ___ / _ \_ __(_)_ __ ___ (_) |_(_)__ _____ ___ \ / /__\/// _` / __| |/ __|/ /_)/ '__| | '_ ` _ \| | __| |\ \ / / _ | __| \ / / \/ \ (_| \__ \ | (__/ ___/| | | | | | | | | | |_| | \ V / __|__ \ \ / \_____/\__,_|___/_|\___\/ |_| |_|_| |_| |_|_|\__|_| \_/ \___|___/ \ /_____________________________________________________________________________\ \\ 2009-2010 | Jeffrey Feck | CentauriBoy | How-To Guide Simple Version 1.5 // \\=========================================================================// ______________________________________________________________________________ Table of Contents | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ 1. Introduction 2. Version History 3. Legal Stuff 4. How-To: --- 4a. Create a Basic Primitive --- 4b. Modify a Basic Primitive ------- 4b.1. Translate ------- 4b.2. Rotate ------- 4b.3. Scale --- 4c. Create a (Line, Triangle, Square, etc...) --- 4d. Rendering Primitives --- 4e. Create and Render Fill-In Shape 5. Frequently Asked Questions 6. Contact Info 7. Special Thanks ______________________________________________________________________________ 1. INTRODUCTION | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ Just like C#, XNA is an elegant and powerful language, giving us control to almost every aspect of game programming. Unfortunately there is a lack of 2D rendering in its' library. That is where this class comes into play. Giving programmers the ability to render shapes of all sizes. With its' arsenal of flexible members and functions, this class is evolving with every release. As with such libraries, the faster and larger it grows, the more complex it gets. Newcomers may not know how to even begin using it. So this guide will be the foundation for those in need, or help better understand how to use it. For more information visit the forum website: http://forums.xna.com/forums/t/7414.aspx ______________________________________________________________________________ 2. VERSION HISTORY | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ -------------------------------------------- [ Key: + Added, - Removed, * Fixed/Optimized ] -------------------------------------------- Version 1.5 (3/23/2010 - 134KB) + property.Centroid; Averages the center of the shape. + RenderCentroid(...); Render the center average of the shape. Version 1.4 (3/22/2010 - 132KB) + Fill In Shapes + Rotate(...); Fill in algorithm, allowing it to rotate in world space. * Rotate(...); Turned 3 "for" loops into a single loop for 2D rotation. * property.Colour; Sets both outline and fill in color. + property.OutlineColour; Sets only the outline color (2D shape). + property.FillInColour; Sets only the fill in color (3D shape). * property.Position; Sets both 2D and 3D positions for consistency. + Triangluation library by Nick Gravelyn Version 1.3 (3/17/2010 - 56KB) + Create Splines; Allows the ability to render 5 different splines: Bezier, Linear, Cosine, Cubic, Hermite. Version 1.2 (7/12/2009 - 25KB) + RenderPolygonPrimitive(...); Uses a line and point algorithm. Version 1.1 (4/6/2009 - 18KB) + Rotation(...); Rotate around a pivot, in screen space. Version 1.0 (4/3/2009 - 11KB) + Create Shapes; Lines, Triangles, Squares, Circles, Ellipses. + Render shapes; As points, lines, use a square or round algorithm. ______________________________________________________________________________ 3. LEGAL STUFF | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ This class and all of its contents is under the terms Microsoft Public License (Ms-PL). It may be used, modified, reproduced, removed, in any way shape or form as the user pleases. However, I have no control and/or not responsible for any damages this class may inflict, mentally, physically, and/or emotionally. Besides being a programmer, I am in no way affiliated with Microsoft, and any other parties involved and/or related to XNA. I have created this class from a collection of thoughts and ideals using references from different sources and my own knowledge, giving credit where credit is due. To put it simply, you have my permission to use this class for both commercial and educational purposes as long as you give credit to the XNA forum and/or everyone involved. ______________________________________________________________________________ 4. HOW TO | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ ______________________________________________________________________________ ::::::::::: 4a. Create a Basic Primitive | :::::::::::::::::::::::::::::::::::\ ==============================================================================/ 1) Create the primitive just like any other class. ----------------------------------------------------------------------------- BasicPrimitives myPrimitive = null; ----------------------------------------------------------------------------- 2) In the constructor or initialization, call the constructor and pass in the GraphicsDevice. ----------------------------------------------------------------------------- myPrimitive = new BasicPrimitives(GraphicsDevice); ----------------------------------------------------------------------------- ______________________________________________________________________________ ::::::::::: 4b. Modify a Basic Primitive | :::::::::::::::::::::::::::::::::::\ ==============================================================================/ There are a lot of properties to modify the primitive: Takes in a Color and sets both outline and fill in colors. ----------------------------------------------------------------------------- myPrimitive.Colour = Color.Red; ----------------------------------------------------------------------------- Takes in a Color and sets only the outline color. ----------------------------------------------------------------------------- myPrimitive.OutlineColour = Color.Black; ----------------------------------------------------------------------------- Takes in a Color and sets only the fill in color. ----------------------------------------------------------------------------- myPrimitive.FillInColour = Color.White; ----------------------------------------------------------------------------- Takes in a Vector2 and sets the 2D positions and 3D translation. ----------------------------------------------------------------------------- myPrimitive.Position = new Vector2(10f, 10f); ----------------------------------------------------------------------------- Takes in a float and sets the depth value (0 = front, 1 = back). ----------------------------------------------------------------------------- myPrimitive.Depth = 1f; ----------------------------------------------------------------------------- Takes in a float and sets the width or size of the primitive. ----------------------------------------------------------------------------- myPrimitive.Thickness = 1f; ----------------------------------------------------------------------------- All of these can be set during any initialization and/or rendering function. Also every frame if necessary. ______________________________________________________________________________ ::::::::::::::::::::::::: 4b.1. Translate | ::::::::::::::::::::::::::::::::::\ ==============================================================================/ Use the Position property to translate the shape, it will automatically set for both outline (2D) and fill in (3D) for you. ______________________________________________________________________________ ::::::::::::::::::::::::: 4b.2. Rotate | :::::::::::::::::::::::::::::::::::::\ ==============================================================================/ There are two ways to rotate the shape: 1) Call any of the 5 render functions and pass in the rotation value and pivot. ----------------------------------------------------------------------------- float myRotationValue = 1f; Vector2 myPivotVector = myPrimitive.GetVector(0); myPrimitive.RenderPolygonPrimitive(SpriteBatch, myRotationValue, myPivotVector); ----------------------------------------------------------------------------- In this case I chose a hard-coded rotation value and the first point of the shape for simplicity sake. You should use a timer for the rotation value and most likely the center of the shape by using myPrimitive.Centriod for the pivot. 2) Or you can call the Rotate functionality. ----------------------------------------------------------------------------- myPrimitive.Rotate(myRotationValue, myPivotVector); ----------------------------------------------------------------------------- ______________________________________________________________________________ ::::::::::::::::::::::::: 4b.3. Scale | ::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ Use the Thickness property to scale the shape, it will automatically set both outline (2D) and fill in (3D) for you. ______________________________________________________________________________ ::::::::::: 4c. Create a (Line, Triangle, Square, etc...) | ::::::::::::::::::\ ==============================================================================/ You can basically create any shape you can imagine, but this class has built in functionality for simple shapes such as lines, triangles, squares, circles, ellipses and even splines. ----------------------------------------------------------------------------- myPrimitive.CreateLine(new Vector2(1f, 1f), new Vector2(10f, 10.f)); ----------------------------------------------------------------------------- That's it! You can replace CreateLine with CreateSquare and passing in more parameters, but the same goes for everything else. It's simple and easy. For more advance shapes like a star, you will do something like this: ----------------------------------------------------------------------------- myPrimitive.AddVector(new Vector2(5f, 0f)); // Top myPrimitive.AddVector(new Vector2(3f, 3f)); // Inner TopLeft myPrimitive.AddVector(new Vector2(0f, 3f)); // Left myPrimitive.AddVector(new Vector2(2f, 4f)); // Inner BottomLeft myPrimitive.AddVector(new Vector2(1f, 5f)); // BottomLeft myPrimitive.AddVector(new Vector2(5f, 4f)); // Inner Bottom myPrimitive.AddVector(new Vector2(7f, 5f)); // BottomRight myPrimitive.AddVector(new Vector2(6f, 4f)); // Inner BottomRight myPrimitive.AddVector(new Vector2(9f, 3f)); // Right myPrimitive.AddVector(new Vector2(7f, 3f)); // Inner TopRight myPrimitive.AddVector(new Vector2(5f, 0f)); // Top ----------------------------------------------------------------------------- As you can see, when you create your shapes, a counter-clockwise order is usually the norm. You can create it manually clockwise, but just remember that the automatic create methods are counter-clockwise. Why is this important? Because when you make a fill in shape, a parameter will ask you the winding order. ______________________________________________________________________________ ::::::::::: 4d. Rendering Primitives | :::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ There are 5 ways to render the primitives. Points - Render ONLY the points. ----------------------------------------------------------------------------- myPrimitive.RenderPointPrimitive(SpriteBatch); ----------------------------------------------------------------------------- Lines - Render ONLY the lines. ----------------------------------------------------------------------------- myPrimitive.RenderLinePrimitive(SpriteBatch); ----------------------------------------------------------------------------- Square Algorithm - Per-pixel line rendering; Blocky shapes. ----------------------------------------------------------------------------- myPrimitive.RenderSquarePrimitive(SpriteBatch); ----------------------------------------------------------------------------- Circle Algorithm - Per-pixel point rendering; Smooth shapes. ----------------------------------------------------------------------------- myPrimitive.RenderCirclePrimitive(SpriteBatch); ----------------------------------------------------------------------------- Line & Point Algorithm - Renders the lines and end points to close off the shape. ----------------------------------------------------------------------------- myPrimitive.RenderPolygonPrimitive(SpriteBatch); ----------------------------------------------------------------------------- If necessary, the Line & Point Algorithm is recommended to render any shapes including splines. ______________________________________________________________________________ ::::::::::: 4e. Create and Render Fill-In Shape | ::::::::::::::::::::::::::::\ ==============================================================================/ 1) A fill in shape will use triangulation. First call any of the create methods or manually create them, just remember what the winding order is. ----------------------------------------------------------------------------- myPrimitive.CreateSquare(new Vector(1f, 1f), new Vector(10f, 10f)); ----------------------------------------------------------------------------- 2) Then call the calculate fill in shape, pass in the winding order. ----------------------------------------------------------------------------- myPrimitive.CalculateFillInShape(Triangulator.WindingOrder.CounterClockwise); ----------------------------------------------------------------------------- 3) And to render, simply call this function: ----------------------------------------------------------------------------- myPrimitive.RenderFillInPolygon(); ----------------------------------------------------------------------------- It's important to note that you should call this method "outside" or "before" any SpriteBatch calls. ----------------------------------------------------------------------------- // 3D Rendering. myPrimitive.RenderFillInPolygon(); SpriteBatch.Begin(); // Insert 2D rendering. SpriteBatch.End(); ----------------------------------------------------------------------------- ______________________________________________________________________________ 5. FREQUENTLY ASKED QUESTIONS | ::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ QUESTION : What Does This Class Do? ANSWER : This is an XNA Utility which allow rendering of 2D polygons including: Points, Lines, Concave & Convex Shapes, Splines, and Fill In Shapes. Each polygon can be scaled, rotated, and translated. QUESTION : How Do I Start Using This Class? ANSWER : Once you start a project, you can easily add this class. Just copy and paste both the BasicPrimitives.cs file and Triangulation folder into your project folder and then copy those into your solution explorer. You simply change the Namespace in BasicPrmitives.cs, compile and you're ready to go. QUESTION : Why Do I Need To Pass In The GraphicsDevice When I Call The Constructor? ANSWER : The class will use the GraphicsDevice to initialize its' members which includes the 1x1 pixel for rendering 2D shapes, the BasicEffect for rendering 3D shapes, and the ability to render fill-in shapes in world space. QUESTION : Why Does The Outline Shape Need A SpriteBatch, While The Fill In Shape Doesn't? ANSWER : Outline shapes render in screen space (2D) and the fill in shape renders in world space (3D). In XNA, all 2D need SpriteBatch to draw on screen. While all 3D objects need the GraphicsDevice, and if necessary, a BasicEffect or custom shader to render. QUESTION : What Is The Difference Between Render Functions? ANSWER : This class allows you to render your shapes using different functionality: RenderCentriod(...) = Only average center point, nothing else. RenderPointPrimitive(...) = Only points, no lines. RenderLinePrimitive(...) = Only lines, no end points. RenderSquarePrimitive(...) = Only blocky Concave/Convex shapes. (e.g. Triangles, Squares, Stars, Octagons, etc...) RenderCirclePrimitive(...) = Only smooth Concave/Convex shapes. (e.g. Circles, Ellipses, etc...) RenderPolygonPrimitive(...) = Render all Concave/Convex shapes. ______________________________________________________________________________ 6. CONTACT INFO | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ If the FREQUENTLY ASKED QUESTIONS does not answer your question, feel free to contact me via e-mail with any questions, comments, and/or problems with this class. Website: http://jtfeck.awardspace.com E-mail address: lightninggunner@hotmail.com I check my e-mail everyday and usually reply within 24 hours. If you receive no response, please understand that I may be on a busy schedule or receiving a lot of e-mails. Thank you for understanding. ______________________________________________________________________________ 7. SPECIAL THANKS | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ ==============================================================================/ MessiahAndrw - For starting the forum and inspiration for this class. KonaHart - Ideal for correct rotation around a pivot point. Brad Walton - Pointing out per-pixel rendering is time consuming, which causes lag. BGold - For naming the function RenderPolygonPrimitive. Gnomic Studios (Roonda) - Recommendation of using a paste bin to show the code. - Sample codes and references. markww - Ideal for rendering filling in shapes. RCade - Ideal for spline rendering. Nick Gravelyn - For the brilliant triangulation library. Jakester - Ideal for this How-To Guide. And everyone else who found and tested this class. May your days of coding be a happy one.