I have some sort of a problem. I'm new to XNA and want to draw a polygon shape that looks something like this (In the end, I want these point to be random):
So I read some articles and this is what I ended up with:
private VertexPositionColor[] vertices;
public TextureClass()
{
setupVertices();
}
public override void Render(SpriteBatch spriteBatch)
{
Texture2D texture = createTexture(spriteBatch);
spriteBatch.Draw(texture, new Rectangle((int)vertices[0].Position.X, (int)vertices[0].Position.Y, 30, 30), Color.Brown);
}
private Texture2D createTexture(SpriteBatch spriteBatch)
{
Texture2D texture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
texture.SetData<Color>(new Color[] { Color.Brown });
return texture;
}
When I call Render
it's starts drawing some squares as if it where in a loop. I'm just guessing I'm doing it all wrong. I would love it if someones points me into the right direction. Just creating a polygon and drawing it. It seemed so simple...
Here it what I have right now.
A class that generates a BasicEffect with some desired asignments.
public class StandardBasicEffect : BasicEffect
{
public StandardBasicEffect(GraphicsDevice graphicsDevice)
: base(graphicsDevice)
{
this.VertexColorEnabled = true;
this.Projection = Matrix.CreateOrthographicOffCenter(
0, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 0, 0, 1);
}
public StandardBasicEffect(BasicEffect effect)
: base(effect) { }
public BasicEffect Clone()
{
return new StandardBasicEffect(this);
}
}
Here is my PolygonShape class
/// <summary>
/// A Polygon object that you will be able to draw.
/// Animations are being implemented as we speak.
/// </summary>
/// <param name="graphicsDevice">The graphicsdevice from a Game object</param>
/// <param name="vertices">The vertices in a clockwise order</param>
public PolygonShape(GraphicsDevice graphicsDevice, VertexPositionColor[] vertices)
{
this.graphicsDevice = graphicsDevice;
this.vertices = vertices;
this.triangulated = false;
triangulatedVertices = new VertexPositionColor[vertices.Length * 3];
indexes = new int[vertices.Length];
}
/// <summary>
/// Triangulate the set of VertexPositionColors so it will be drawn correcrly
/// </summary>
/// <returns>The triangulated vertices array</returns>}
public VertexPositionColor[] Triangulate()
{
calculateCenterPoint();{
setupIndexes();
for (int i = 0; i < indexes.Length; i++)
{
setupDrawableTriangle(indexes[i]);
}
triangulated = true;
return triangulatedVertices;
}
/// <summary>
/// Calculate the center point needed for triangulation.
/// The polygon will be irregular, so this isn't the actual center of the polygon
/// but it will do for now, as we only need an extra point to make the triangles with</summary>
private void calculateCenterPoint()
{
float xCount = 0, yCount = 0;
foreach (VertexPositionColor vertice in vertices)
{
xCount += vertice.Position.X;
yCount += vertice.Position.Y;
}
centerPoint = new Vector3(xCount / vertices.Length, yCount / vertices.Length, 0);
}
private void setupIndexes()
{
for (int i = 1; i < triangulatedVertices.Length; i = i + 3)
{
indexes[i / 3] = i - 1;
}
}
private void setupDrawableTriangle(int index)
{
triangulatedVertices[index] = vertices[index / 3]; //No DividedByZeroException?...
if (index / 3 != vertices.Length - 1)
triangulatedVertices[index + 1] = vertices[(index / 3) + 1];
else
triangulatedVertices[index + 1] = vertices[0];
triangulatedVertices[index + 2].Position = centerPoint;
}
/// <summary>
/// Draw the polygon. If you haven't called Triangulate yet, I wil do it for you.
/// </summary>
/// <param name="effect">The BasicEffect needed for drawing</param>
public void Draw(BasicEffect effect)
{
try
{
if (!triangulated)
Triangulate();
draw(effect);
}
catch (Exception exception)
{
throw exception;
}
}
private void draw(BasicEffect effect)
{
effect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawUserPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList, triangulatedVertices, 0, vertices.Length);
}
Sorry, it's kind of alot. Now for my next quest. Animation my polygon.
Hope it helped fellow people with the same problem.
this code is useful to draw 2D lines, some calcs can be done into an initilization call, but i prefer for this example to keep all together.
public void DrawLine(VertexPositionColor[] Vertices)
{
Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Vector2 center;
center.X = Game.GraphicsDevice.Viewport.Width * 0.5f;
center.Y = Game.GraphicsDevice.Viewport.Height * 0.5f;
Matrix View = Matrix.CreateLookAt( new Vector3( center, 0 ), new Vector3( center, 1 ), new Vector3( 0, -1, 0 ) );
Matrix Projection = Matrix.CreateOrthographic( center.X * 2, center.Y * 2, -0.5f, 1 );
Effect EffectLines = Game.Content.Load<Effect>( "lines" );
EffectLines.CurrentTechnique = EffectLines.Techniques["Lines"];
EffectLines.Parameters["xViewProjection"].SetValue( View * Projection );
EffectLines.Parameters["xWorld"].SetValue( Matrix.Identity );
foreach ( EffectPass pass in EffectLines.CurrentTechnique.Passes )
{
pass.Apply( );
Game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
( PrimitiveType.LineList, Vertices, 0, Vertices.Length/2 );
}
}
LINES.FX
uniform float4x4 xWorld;
uniform float4x4 xViewProjection;
void VS_Basico(in float4 inPos : POSITION, in float4 inColor: COLOR0, out float4 outPos: POSITION, out float4 outColor:COLOR0 )
{
float4 tmp = mul (inPos, xWorld);
outPos = mul (tmp, xViewProjection);
outColor = inColor;
}
float4 PS_Basico(in float4 inColor:COLOR) :COLOR
{
return inColor;
}
technique Lines
{
pass Pass0
{
VertexShader = compile vs_2_0 VS_Basico();
PixelShader = compile ps_2_0 PS_Basico();
FILLMODE = SOLID;
CULLMODE = NONE;
}
}
I worked with XNA in the past on a physics simulation where I had to draw bounding boxes with GraphicsDevice.DrawIndexedPrimitives (You should google or MSDN for this function for more worked examples.)
The below code is what I used in my project for drawing a 3D geometry.
/// <summary>
/// Draw the primitive.
/// </summary>
/// <param name="world">World Matrix</param>
/// <param name="view">View Matrix</param>
/// <param name="projection">Projection Matrix</param>
/// <param name="color">Color of the primitive</param>
public void Draw(Matrix world, Matrix view, Matrix projection, Color color)
{
_mGraphicsDevice.VertexDeclaration = _mVertexDeclaration;
_mGraphicsDevice.Vertices[0].SetSource(_mVertexBuffer, 0, VertexPositionNormal.SizeInBytes);
_mGraphicsDevice.Indices = _mIndexBuffer;
_mBasicEffect.DiffuseColor = color.ToVector3();
_mBasicEffect.World = _mTransform * world;
_mBasicEffect.View = view;
_mBasicEffect.Projection = projection;
int primitiveCount = _mIndex.Count / 3;
_mBasicEffect.Begin();
foreach (EffectPass pass in _mBasicEffect.CurrentTechnique.Passes)
{
pass.Begin();
_mGraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _mVertex.Count, 0, primitiveCount);
pass.End();
}
_mBasicEffect.End();
}
This function is a member method of a geometry object (class) and is called from the Game class' Draw(GameTime)
method
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With