Ask a questionAsk a question
 

AnswerOrthographic Perspective/Drawing in 2D

  • Friday, March 02, 2007 12:33 AMNick Gravelyn Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    This should be simple, but I'm having trouble getting it to work. I sort of understand matrices. I understand them enough to use projection matrices and I have before, but for some reason I'm unable to get the right orthographic projection. All I want is an orthographic projection matrix that uses the same coordinates as the viewport so that placing a point at (0,0,0) is the top left and (screenWidth, screenHeight, 0) is the bottom right. I've tried two different ones (both orthographic matrix creation methods), but neither yielded proper results.

    b.effect.View = Matrix.CreateLookAt(
                    new Vector3(
                        (float)graphics.GraphicsDevice.Viewport.Width / 2f,
                        (float)graphics.GraphicsDevice.Viewport.Height / 2f,
                        -5f
                    ),
                    Vector3.UnitZ,
                    Vector3.Up
                );

    //b.effect.Projection = Matrix.CreateOrthographic(
        // (float)graphics.GraphicsDevice.Viewport.Width,
        // (float)graphics.GraphicsDevice.Viewport.Height,
        // .01f,
        // 100f
    //);
    b.effect.Projection = Matrix.CreateOrthographicOffCenter(
        0f,
        (float)graphics.GraphicsDevice.Viewport.Width,
        (float)graphics.GraphicsDevice.Viewport.Height,
        0f,
        .01f,
        1000f
    );

    If those are correct perhaps my drawing code is incorrect. I know I'm generating the proper vertices, but I'm not 100% sure if I'm drawing them properly:

    public override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Vertices[0].SetSource(vb, 0, VertexPositionColor.SizeInBytes);

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();
            GraphicsDevice.VertexDeclaration = vd;
            GraphicsDevice.DrawPrimitives(
                ((DrawType == BezierDrawType.Line) ? PrimitiveType.LineStrip : PrimitiveType.PointList),
                0,
                verts.Length
            );
            pass.End();
        }

        effect.End();
    }


Answers

  • Friday, March 02, 2007 6:12 AMKris Nye Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Nick-  I do the exact same thing, use these matrices:

                Matrix world = Matrix.Identity;
                Matrix view = new Matrix(
                    1.0f, 0.0f, 0.0f, 0.0f,
                    0.0f, -1.0f, 0.0f, 0.0f,
                    0.0f, 0.0f, -1.0f, 0.0f,
                    0.0f, 0.0f, 0.0f, 1.0f);
                Matrix projection = Matrix.CreateOrthographicOffCenter(
                    0, this.Width, -this.Height, 0, 0, 1);


    //   The view flips the Y axis so it's going down instead of the default up.
    //   The view also flips the Z axis, (so that we remain right-handed.)
    //   The projection is choosing to render the bottom right quadrant, so it uses -height.


    --   View matrix flips the y (and z)
              -Y
                |
                |
    -------0,0---------->X(800)
                |///////////////////////////////
                |///////////////////////////////  <- Ortho projection part, specified as (0, Width, -Height, 0)
                |///////////////////////////////
             +Y(600)


All Replies

  • Friday, March 02, 2007 1:30 AMShawn Hargreaves - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    What are you using as the Z coordinate in your vertices?

    Your matrix sets the clip planes to 0.01 and 1000, so if your vertices have 0 z, they will be culled.
  • Friday, March 02, 2007 1:36 AMNick Gravelyn Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    That should've been something I thought of. Even after fixing that though, I still get nothing. Maybe I am creating the vertices wrong. I'm trying to implement a bezier curve, so not seeing it might be because my method is incorrect. Here's my loading and computation (for the example my Steps is set to 10000 I believe and compute is initially at true):


            protected override void LoadGraphicsContent(bool loadAllContent)
            {
                if (loadAllContent)
                {
                    effect = new BasicEffect(GraphicsDevice, null);
                    effect.DiffuseColor = new Vector3(1f, 1f, 1f);
                    effect.World = Matrix.Identity;

                    vd = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);

                    if (compute)
                    {
                        generateCurve();
                        compute = false;
                    }
                }

                base.LoadGraphicsContent(loadAllContent);
            }
           
            void generateCurve()
            {
                verts = new VertexPositionColor[steps + 1];
                vb = new VertexBuffer(
                    GraphicsDevice,
                    VertexPositionColor.SizeInBytes * (steps + 1),
                    ResourceUsage.None,
                    ResourceManagementMode.Automatic
                );
                float step = 1f / (float)steps;

                Vector2 a, b, c;
                c.X = 3f * (start.ControlPoint1.X - start.Point.X);
                b.X = 3f * (end.ControlPoint2.X - start.ControlPoint1.X) - c.X;
                a.X = end.Point.X - end.ControlPoint2.X - b.X - c.X;

                c.Y = 3f * (start.ControlPoint1.Y - start.Point.Y);
                b.Y = 3f * (end.ControlPoint2.Y - start.ControlPoint1.Y) - c.Y;
                a.Y = end.Point.Y - end.ControlPoint2.Y - b.Y - c.Y;

                int j = 0;
                for (float i = 0f; i <= 1f; i += step)
                {
                    float i3 = (float)Math.Pow(i, 3f);
                    float i2 = (float)Math.Pow(i, 2f);

                    float x = a.X * i3 + b.X * i2 + c.X * i + start.Point.X;
                    float y = a.Y * i3 + b.Y * i2 + c.Y * i + start.Point.Y;

                    verts[j++] = new VertexPositionColor(new Vector3(x, y, 0f), Color.White);
                }

                vb.SetData<VertexPositionColor>(verts);
            }
  • Friday, March 02, 2007 2:14 AMShawn Hargreaves - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    This is where I'd pull out PIX for Windows. Looking at a capture of the frame in question, you can debug your draw calls to easily see if they're failing entirely, or drawing just off the screen, or maybe drawing in the right place but coming out black for some reason. Armed with that information, it's usually a lot easier to find which bit in the code is going wrong.
  • Friday, March 02, 2007 2:28 AMNick Gravelyn Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    It's drawing, just off screen. I think a tiny bit is actually hitting the top left corner, but all the vertices in the draw call are the same that I set, so I don't know why it'd be off the screen like that.
  • Friday, March 02, 2007 6:02 AMNick Gravelyn Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I found one error, not the main one, in that I was having XNA draw one more vertex than I had in the array, but that's not causing it to be offscreen.

    I've uploaded the whole project so if anyone wants to download it to help me out (just 28k), I'd appreciate it.

    http://cis.gvsu.edu/~gravelyn/BezierCurves.zip
  • Friday, March 02, 2007 6:12 AMKris Nye Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Nick-  I do the exact same thing, use these matrices:

                Matrix world = Matrix.Identity;
                Matrix view = new Matrix(
                    1.0f, 0.0f, 0.0f, 0.0f,
                    0.0f, -1.0f, 0.0f, 0.0f,
                    0.0f, 0.0f, -1.0f, 0.0f,
                    0.0f, 0.0f, 0.0f, 1.0f);
                Matrix projection = Matrix.CreateOrthographicOffCenter(
                    0, this.Width, -this.Height, 0, 0, 1);


    //   The view flips the Y axis so it's going down instead of the default up.
    //   The view also flips the Z axis, (so that we remain right-handed.)
    //   The projection is choosing to render the bottom right quadrant, so it uses -height.


    --   View matrix flips the y (and z)
              -Y
                |
                |
    -------0,0---------->X(800)
                |///////////////////////////////
                |///////////////////////////////  <- Ortho projection part, specified as (0, Width, -Height, 0)
                |///////////////////////////////
             +Y(600)


  • Friday, March 02, 2007 6:40 AMNick Gravelyn Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks a ton. Now I just have to figure out how to get the curve to draw right...