3
votes

I've been experimenting with drawing lines in XNA. I've got no trouble drawing lines in the X and Y directions, but whenever I try and add Z data to the points, there seems to be no effect.

Here's what I was hoping I could do by adding Z information (which I've simulated here by altering the Y and averaging the X points with the midpoint)

enter image description here

And here's what I'm actually getting (I've translated the 2nd line upwards to verify that there are, in fact, two lines getting drawn - when I only change the Z, the two lines get drawn on top of each other) enter image description here

Am I messing up something basic with my perspective matrix? Skipping an important step? Code below is for the 2nd picture.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WindowsGame3
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        BasicEffect baseEffect;
        VertexPositionColor[] vertices;
        VertexPositionColor[] verticesTop;
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        float AspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
        baseEffect = new BasicEffect(graphics.GraphicsDevice);
        baseEffect.World = Matrix.Identity;
        baseEffect.View = Matrix.Identity;

        baseEffect.VertexColorEnabled = true;
        baseEffect.Projection = Matrix.CreateOrthographicOffCenter
           (0, graphics.GraphicsDevice.Viewport.Width,     // left, right
            graphics.GraphicsDevice.Viewport.Height, 0,    // bottom, top
            -100, 100);                                     // near, far plane

        vertices = new VertexPositionColor[7];
        verticesTop = new VertexPositionColor[7];

        vertices[0].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 1/8, graphics.GraphicsDevice.Viewport.Height * 5/7, 0);
        vertices[0].Color = Color.Black;
        vertices[1].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 2/8, graphics.GraphicsDevice.Viewport.Height * 5/7, 1/8);
        vertices[1].Color = Color.Red;
        vertices[2].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 3 / 8, graphics.GraphicsDevice.Viewport.Height * 5 / 7, -2/8);
        vertices[2].Color = Color.Black;
        vertices[3].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 4 / 8, graphics.GraphicsDevice.Viewport.Height * 5 / 7, 3/8);
        vertices[3].Color = Color.Red;
        vertices[4].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 5 / 8, graphics.GraphicsDevice.Viewport.Height * 5 / 7, -4/8);
        vertices[4].Color = Color.Black;
        vertices[5].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 6 / 8, graphics.GraphicsDevice.Viewport.Height * 5 / 7, 5/8);
        vertices[5].Color = Color.Red;
        vertices[6].Position = new Vector3(graphics.GraphicsDevice.Viewport.Width * 7 / 8, graphics.GraphicsDevice.Viewport.Height * 5 / 7, -6/8);
        vertices[6].Color = Color.Black; 



        for (int i = 0; i < 7; i++)
        {
            verticesTop[i] = vertices[i];
            verticesTop[i].Position.Y -= 200; // remove this line once perspective is working
            verticesTop[i].Position.Z += 100;

        }
        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // TODO: use this.Content to load your game content here
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        baseEffect.CurrentTechnique.Passes[0].Apply();
        graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, vertices, 0, 6);
        graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, verticesTop, 0, 6);


        base.Draw(gameTime);
    }
}

}

1
I don't know XNA, but it seems to me you're not applying any perspective projection. baseEffect.View = Matrix.Identity; seems to indicate that.Bart
@Bart View is just where you're looking from, i.e., the camera.Raven Dreamer
Ah yes, of course it does. I was too fast for my own good. But I think baseEffect.Projection is your culprit. See @Coincoin's answer.Bart

1 Answers

3
votes

The function you are using Matrix.CreateOrthographicOffCenter() creates an orthogonal projection matrix which have no perspective.

Try using Matrix.CreatePerspectiveOffCenter() or Matrix.CreatePerspectiveFieldOfView() instead.

baseEffect.Projection = Matrix.CreatePerspectiveFieldOfView (
    1.57f,          // 90 degrees field of view
    width / height, // aspect ratio
    1.0f,           // near plane, you want that as far as possible
    10000.0f);      // far plane, you want that as near as possible