I’m trying to draw a square in XNA and simply move it around with the keyboard, based on user input. Unfortunately, I haven’t even been able to get the square to show – I’m positive I’m missing something here, but I can’t figure out exactly what it is. I plan to create a complicated hierarchy of primitive shapes which I can use in my game. The main components of the Shape class are initialized, and the deriving class (in this case Rect) utilizes these components for further use, and configures them.
What am I doing wrong here?
Code
Shape.cs
public abstract class Shape
{
public Vector3 Center;
public Color[] Colors;
public bool SetColorsOnUpdate;
public virtual Rectangle BoundingBox { get; set; }
public float Radius { get { return mRadius; } }
protected VertexBuffer mVertexBuf;
protected IndexBuffer mIndexBuf;
protected float mRadius;
protected BasicEffect mShader;
public Shape(Vector3 center, Color[] colors, int numVertices, float radius)
{
Colors = colors;
Center = center;
mVertexBuf = new VertexBuffer(Graphics.MainDevice, typeof(VertexPositionColor), numVertices, BufferUsage.WriteOnly);
mIndexBuf = new IndexBuffer(Graphics.MainDevice, IndexElementSize.SixteenBits, numVertices, BufferUsage.WriteOnly);
SetColorsOnUpdate = true;
mShader = new BasicEffect(Graphics.MainDevice);
mRadius = radius;
}
public abstract void Update();
public abstract void Draw();
}
Rect.cs
public class Rect : Shape
{
public override Rectangle BoundingBox
{
get
{
int x = (int)Center.X, y = (int)Center.Y;
int diameter = (int)mRadius * 2;
return new Rectangle(
x, y,
x + diameter,
y + diameter
);
}
}
const float TestRectZCoordinate = 0;
const int NumVertices = 4;
public Rect(Vector3 center, Color[] colors, float radius)
: base(center, colors, NumVertices, radius)
{
if (colors.Length < NumVertices)
throw new IndexOutOfRangeException(string.Format("Color array passed to Rect constructor MUST have an element index size of 4. Current length passed is {0}", colors.Length));
mShader.VertexColorEnabled = true;
mVertexBuf.SetData<VertexPositionColor>(
new VertexPositionColor[]
{
new VertexPositionColor(new Vector3(Center.X + mRadius, Center.Y + mRadius, TestRectZCoordinate), Colors[0]),
new VertexPositionColor(new Vector3(Center.X + mRadius, Center.Y - mRadius, TestRectZCoordinate), Colors[1]),
new VertexPositionColor(new Vector3(Center.X - mRadius, Center.Y - mRadius, TestRectZCoordinate), Colors[2]),
new VertexPositionColor(new Vector3(Center.X - mRadius, Center.Y + mRadius, TestRectZCoordinate), Colors[3])
}
);
mIndexBuf.SetData<short>(new short[] { 0, 1, 2, 3 });
}
public override void Update()
{
//TODO
}
public override void Draw()
{
mShader.World = Matrix.CreateWorld(Center, Vector3.Forward, Vector3.Up);
mShader.CurrentTechnique.Passes[0].Apply();
Graphics.MainDevice.SetVertexBuffer(mVertexBuf);
Graphics.MainDevice.Indices = mIndexBuf;
Graphics.MainDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, NumVertices, 0, 1);
}
}
Update
Here is the latest Rect.Draw() implementation.
public override void Draw()
{
Viewport viewport = Graphics.MainDevice.Viewport;
mShader.World = Matrix.CreateWorld(Center, Vector3.Forward, Vector3.Up);
mShader.View = Matrix.CreateLookAt(new Vector3(viewport.Width / 2, viewport.Height / 2, -5f), Center, Vector3.Up);
mShader.CurrentTechnique.Passes[0].Apply();
Graphics.MainDevice.SetVertexBuffer(mVertexBuf);
Graphics.MainDevice.Indices = mIndexBuf;
Graphics.MainDevice.DrawIndexedPrimitives(PrimitiveType.LineStrip, 0, 0, NumVertices, 0, 2);
}
Ah – I think I see at least one of your problem(s). You’re drawing a TriangleList (see PrimitiveType) and you need 6 indices, not 4.
Got it. It looks like your vertex/index order was wrong. I also didn’t see a projection matrix.
Here’s the code that worked great for me – all I did was to add a projection matrix, reorder the vertices, change the indices and fix the primitive count.
http://pastebin.com/tMKCxBLL
Hope this helps!