flypp3r

I already asked Derek this question, but as request- I'm reposting the question publicly so we all can learn

anyway- the question is how to draw lines/2D primitives in XNA.  essentially- how would i construct a series of lines from point a to b to c to d to etc...

ive read solutions from back in beta1 here that stated its a very long/tedious amount of code compared to textures that take only about 3-4 lines to draw.  i was wondering if by now they added somethign like the simplicity in Java where its just graphic.drawLine(x1, y1, x2, y2);   and theres a line from (x1, y1) to (x2, y2)

i checked the documentation and only found primitives in 3D

what would be the closest in XNA



Re: XNA Game Studio Express Drawing 2D primitives?

Jim Perry

2D primitives are simply 3D primitives with the z value set to 0. I haven't had a chance to look at the primitives stuff much.

Have you looked at the How to: Draw Points, Lines, and Other 3D Primitives in the Help






Re: XNA Game Studio Express Drawing 2D primitives?

flypp3r

Jim Perry wrote:

2D primitives are simply 3D primitives with the z value set to 0. I haven't had a chance to look at the primitives stuff much.

Have you looked at the How to: Draw Points, Lines, and Other 3D Primitives in the Help

I've tried reading it, but it seems a little "advanced" for me yet. Its slightly odd that to draw a sprite it only takes a couple lines of very readable code, but to draw something as simple as a line theres lots of code (for what it does) that is not easily understandable for a beginning game programmer. Sort of defeats the purpose of managed code. Unless I'm missing something and the documentation itself is confusing and its actually just as simple- it should be a thing to consider to be able to draw shapes just as simple as drawing textures.




Re: XNA Game Studio Express Drawing 2D primitives?

Fluxtah

Managed code does not imply simplicity, it just means that the memory is managed.

The docs provide adequate examples of how to achieve what you want to do, just type the code from the docs, run it and see what happens, I am sure it will seem easy once you have done this!

you can always abstract the complexity into something more instantly usable.





Re: XNA Game Studio Express Drawing 2D primitives?

Jim Perry

The complete example at the bottom of the page draws all the primitives, not just lines. So eliminate 2/3 of the code and you have your line drawing. It's actually pretty simple if you've got a handle on your geometry. Here's the code with just the line drawing (both types):

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

public class Game1 : Microsoft.Xna.Framework.Game
{
    Matrix viewMatrix;
    Matrix projectionMatrix;
    BasicEffect basicEffect;

    VertexDeclaration vertexDeclaration;
    VertexPositionNormalTexture[] pointList;
    VertexBuffer vertexBuffer;
    PrimitiveType typeToDraw = PrimitiveType.PointList;
    int points = 8;

    IndexBuffer lineListIndexBuffer;
    IndexBuffer lineStripIndexBuffer;
   
    GraphicsDeviceManager graphics;
    ContentManager content;


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        content = new ContentManager(Services);
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        InitializeTransform();
        if (loadAllContent)
        {
            InitializeEffect();
            InitializePointList();
            InitializeLineList();
            InitializeLineStrip();
        }
    }

    private void InitializeTransform()
    {

        viewMatrix = Matrix.CreateLookAt(
            new Vector3(0, 0, 5),
            Vector3.Zero,
            Vector3.Up
            );

        projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.ToRadians(45),
            (float)graphics.GraphicsDevice.Viewport.Width /
            (float)graphics.GraphicsDevice.Viewport.Height,
            1.0f, 100.0f);


    }

    private void InitializeEffect()
    {

        vertexDeclaration = new VertexDeclaration(
            graphics.GraphicsDevice,
            VertexPositionNormalTexture.VertexElements);

        basicEffect = new BasicEffect(graphics.GraphicsDevice, null);
        basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f);

        basicEffect.View = viewMatrix;
        basicEffect.Projection = projectionMatrix;

    }

    private void InitializePointList()
    {
        vertexDeclaration = new VertexDeclaration(
            graphics.GraphicsDevice,
            VertexPositionNormalTexture.VertexElements);

        double angle = MathHelper.TwoPi / points;

        pointList = new VertexPositionNormalTexture[points + 1];

        pointList[0] = new VertexPositionNormalTexture(
            Vector3.Zero, Vector3.Forward, Vector2.One);

        for (int i = 1; i <= points; i++)
        {
            pointListIdea = new VertexPositionNormalTexture(
                new Vector3(
                             (float)Math.Round(Math.Sin(angle * i), 4),
                             (float)Math.Round(Math.Cos(angle * i), 4),
                              0.0f),
                Vector3.Forward,
                new Vector2());
        }

        // Initialize the vertex buffer, allocating memory for each vertex
        vertexBuffer = new VertexBuffer(graphics.GraphicsDevice,
            VertexPositionNormalTexture.SizeInBytes * (pointList.Length),
            ResourceUsage.None,
            ResourceManagementMode.Automatic);

        // Set the vertex buffer data to the array of vertices
        vertexBuffer.SetData<VertexPositionNormalTexture>(pointList);

    }

    private void InitializeLineList()
    {
        // Initialize an array of indices of type short
        short[] lineListIndices = new short[(points * 2)];

        // Populate the array with references to indices in the vertex buffer
        for (int i = 0; i < points; i++)
        {
            lineListIndices[i * 2] = (short)(i + 1);
            lineListIndices[(i * 2) + 1] = (short)(i + 2);
        }

        lineListIndices[(points * 2) - 1] = 1;

        // Initialize the index buffer, allocating memory for each index
        lineListIndexBuffer = new IndexBuffer(
            graphics.GraphicsDevice,
            sizeof(short) * lineListIndices.Length,
            ResourceUsage.None,
            ResourceManagementMode.Automatic,
            IndexElementSize.SixteenBits
            );

        // Set the data in the index buffer to our array
        lineListIndexBuffer.SetData<short>(lineListIndices);

    }

    private void InitializeLineStrip()
    {
        // Initialize an array of indices of type short
        short[] lineStripIndices = new short[points + 1];

        // Populate the array with references to indices in the vertex buffer
        for (int i = 0; i < points; i++)
        {
            lineStripIndicesIdea = (short)(i + 1);
        }

        lineStripIndices[points] = 1;

        // Initialize the index buffer, allocating memory for each index
        lineStripIndexBuffer = new IndexBuffer(
            graphics.GraphicsDevice,
            sizeof(short) * lineStripIndices.Length,
            ResourceUsage.None,
            ResourceManagementMode.Automatic,
            IndexElementSize.SixteenBits
            );

        // Set the data in the index buffer to our array
        lineStripIndexBuffer.SetData<short>(lineStripIndices);

    }

    protected override void UnloadGraphicsContent(bool unloadAllContent)
    {
        if (unloadAllContent == true)
        {
            content.Unload();
        }
    }

    protected override void Update(GameTime gameTime)
    {
        // Allows the default game to exit on Xbox 360 and Windows
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        CheckInput();
        base.Update(gameTime);
    }

    private void CheckInput()
    {
        KeyboardState newState = Keyboard.GetState();

        if (newState.IsKeyDown(Keys.NumPad1))
        {
            typeToDraw = PrimitiveType.LineList;
        }
        else if (newState.IsKeyDown(Keys.NumPad2))
        {
            typeToDraw = PrimitiveType.LineStrip;
        }
    }

    protected override void Draw(GameTime gameTime)
    {

        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;

        // effect is a compiled effect created and compiled elsewhere
        // in the application
        basicEffect.Begin();
        foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
        {
            pass.Begin();

            switch (typeToDraw)
            {
                case PrimitiveType.LineList:
                    DrawLineList();
                    break;
                case PrimitiveType.LineStrip:
                    DrawLineStrip();
                    break;
            }


            pass.End();
        }
        basicEffect.End();

        base.Draw(gameTime);

    }

    private void DrawLineList()
    {

        graphics.GraphicsDevice.Vertices[0].SetSource(
            vertexBuffer, 0,
            VertexPositionNormalTexture.SizeInBytes);

        graphics.GraphicsDevice.Indices = lineListIndexBuffer;

        graphics.GraphicsDevice.DrawIndexedPrimitives(
            PrimitiveType.LineList,
            0,  // vertex buffer offset to add to each element of the index buffer
            0,  // minimum vertex index
            16, // number of vertices
            0,  // first index element to read
            8); // number of primitives to draw

    }

    private void DrawLineStrip()
    {
        graphics.GraphicsDevice.Vertices[0].SetSource(
            vertexBuffer, 0,
            VertexPositionNormalTexture.SizeInBytes);

        graphics.GraphicsDevice.Indices = lineStripIndexBuffer;

        graphics.GraphicsDevice.DrawIndexedPrimitives(
            PrimitiveType.LineStrip,
            0, // vertex buffer offset to add to each element of the index buffer
            0, // minimum vertex index
            9, // number of vertices
            0, // first index element to read
            8);// number of primitives to draw

    }
}

 

That's not really a lot of code. It would be probably 4 times that much in C++. You're looking at 3 lines of code to draw the lines, the rest is setup and handling input.