Results 1 to 1 of 1

Thread: Drawing Primitives using XNA in VB.Net

  1. #1

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,698

    Drawing Primitives using XNA in VB.Net

    A few prerequisites:
    • Visual Basic.Net 2010 or higher
    • Microsoft XNA 4.0 or higher


    Following my prior tutorial, go ahead and add the correct XNA references and Import:
    1. Microsoft.Xna.Framework
    2. Microsoft.Xna.Framework.Graphics


    For this tutorial, start by declaring and initializing the GraphicsDevice. If you're unsure on how to do that follow the link I posted above.

    Next we will declare a BasicEffect and initialize that. A BasicEffect is the basic rendering effect class, perfect for primitives. The code for initializing the BasicEffect is:
    Code:
        Private effect As BasicEffect
        Private Function InitializeEffect(ByVal graphics As GraphicsDevice) As Boolean
            effect = New BasicEffect(graphics)
    
            Try
                effect.VertexColorEnabled = True
                effect.Projection = Matrix.CreateOrthographicOffCenter(0, graphics.Viewport.Width, graphics.Viewport.Height, 0, 0, 1)
    
                InitializeEffect = True
            Catch ex As Exception
                InitializeEffect = False
            End Try
        End Function
    Basically what we're doing is setting up our BasicEffect class off of our GraphicsDevice, then setting some properties. The most important property I will discuss is the CreateOrthographicOffCenter. Whenever drawing primitives in XNA essentially what we're doing is drawing a 3d image, but making it appear 2d. This is the way that XNA is designed.

    The form's load event will appear similar to the last tutorial on drawing an image, only it will appear a bit differently. First we will change the name of Initialize to InitializeGraphics, then when we use the conditional statement to try to set up the graphics, we will do the same for the BasicEffect. Here is how the code should look like for the Form_Load:

    Code:
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            'Set up the initialize function found above
            If InitializeGraphics(pbGame) AndAlso InitializeEffect(grafix) Then
                BackgroundWorker1.RunWorkerAsync()
            Else
                MessageBox.Show("There was a problem initializing XNA.")
                Me.Close()
            End If
        End Sub
    Next I will put two(2) functions that will be able to draw a line and a triangle:
    Code:
        Private Function Set2dLine(ByVal x1 As Integer, ByVal y1 As Integer, ByVal z1 As Integer, _
                                     ByVal x2 As Integer, ByVal y2 As Integer, ByVal z2 As Integer, _
                                     ByVal color As Color) As VertexPositionColor()
            Dim vertices1, vertices2 As New VertexPositionColor
    
            vertices1.Position = New Vector3(x1, y1, z1)
            vertices1.Color = color
            vertices2.Position = New Vector3(x2, y2, z2)
            vertices2.Color = color
    
            Return {vertices1, vertices2}
        End Function
    
        Private Function Set2dTriangle(ByVal x1 As Integer, ByVal y1 As Integer, ByVal z1 As Integer, _
            ByVal x2 As Integer, ByVal y2 As Integer, ByVal z2 As Integer, _
            ByVal x3 As Integer, ByVal y3 As Integer, ByVal z3 As Integer, _
            ByVal color As Color) As VertexPositionColor()
    
            Dim vertices1, vertices2, vertices3 As New VertexPositionColor
    
            vertices1.Position = New Vector3(x1, y1, z1)
            vertices1.Color = color
            vertices2.Position = New Vector3(x2, y2, z2)
            vertices2.Color = color
            vertices3.Position = New Vector3(x3, y3, z3)
            vertices3.Color = color
    
            Return {vertices1, vertices2, vertices3}
        End Function
    These two functions are almost identical, the only difference is that the triangle has one more vertices, and that's because a line has two points and a triangle has three. Remember earlier I explained that the way 2d primitives are shown are actually 3d Images only being manipulated to appear 2d? Well we do that by setting the Z coordinate of the Vector3 to 0. Consider the graphics class in System.Drawing, we have our X and Y coordinates and to draw a line we just set two points, essentially we're doing the same thing by setting the Z coordinate to 0.

    Finally in our backgroundworker's DoWork event we set up our primitives and draw them:
    Code:
        Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Do Until quit = True
                grafix.Clear(Color.CornflowerBlue)
    
                effect.CurrentTechnique.Passes(0).Apply()
    
                Dim newline() As VertexPositionColor = Set2dLine(50, 10, 0, 150, 10, 0, Color.Black)
                Dim newtri() As VertexPositionColor = Set2dTriangle(25, 100, 0, 50, 50, 0, 75, 100, 0, Color.Black)
    
                grafix.DrawUserPrimitives(PrimitiveType.LineList, newline, 0, 1)
                grafix.DrawUserPrimitives(PrimitiveType.TriangleList, newtri, 0, 1)
    
                grafix.Present()
            Loop
        End Sub
    In that example I draw a line at 50, 10 and at 150, 10. I also draw a triangle at 25, 100 and 50, 50 and 75, 100. To get them to appear on the screen we call DrawUserPrimitives. All in all the code should look like this in the end:

    Code:
    Option Strict On
    Option Explicit On
    
    Imports Microsoft.Xna.Framework
    Imports Microsoft.Xna.Framework.Graphics
    Public Class Form1
    
        Private grafix As GraphicsDevice
        Private Function InitializeGraphics(ByRef surface As PictureBox) As Boolean
            Try
                Dim pparam As New PresentationParameters
                pparam.DeviceWindowHandle = surface.Handle
                pparam.IsFullScreen = False
    
                Dim grafixAdapt As GraphicsAdapter = GraphicsAdapter.DefaultAdapter
    
                grafix = New GraphicsDevice(grafixAdapt, GraphicsProfile.HiDef, pparam)
    
    
                InitializeGraphics = True
            Catch ex As Exception
                InitializeGraphics = False
            End Try
        End Function
    
        Private effect As BasicEffect
        Private Function InitializeEffect(ByVal graphics As GraphicsDevice) As Boolean
            effect = New BasicEffect(graphics)
    
            Try
                effect.VertexColorEnabled = True
                effect.Projection = Matrix.CreateOrthographicOffCenter(0, graphics.Viewport.Width, graphics.Viewport.Height, 0, 0, 1)
    
                InitializeEffect = True
            Catch ex As Exception
                InitializeEffect = False
            End Try
        End Function
    
        Private quit As Boolean = False
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            'Set up the initialize function found above
            If InitializeGraphics(pbGame) AndAlso InitializeEffect(grafix) Then
                BackgroundWorker1.RunWorkerAsync()
            Else
                MessageBox.Show("There was a problem initializing XNA.")
                Me.Close()
            End If
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Do Until quit = True
                grafix.Clear(Color.CornflowerBlue)
    
                effect.CurrentTechnique.Passes(0).Apply()
    
                Dim newline() As VertexPositionColor = Set2dLine(50, 10, 0, 150, 10, 0, Color.Black)
                Dim newtri() As VertexPositionColor = Set2dTriangle(25, 100, 0, 50, 50, 0, 75, 100, 0, Color.Black)
    
                grafix.DrawUserPrimitives(PrimitiveType.LineList, newline, 0, 1)
                grafix.DrawUserPrimitives(PrimitiveType.TriangleList, newtri, 0, 1)
    
                grafix.Present()
            Loop
        End Sub
    
        Private Function Set2dLine(ByVal x1 As Integer, ByVal y1 As Integer, ByVal z1 As Integer, _
                                     ByVal x2 As Integer, ByVal y2 As Integer, ByVal z2 As Integer, _
                                     ByVal color As Color) As VertexPositionColor()
            Dim vertices1, vertices2 As New VertexPositionColor
    
            vertices1.Position = New Vector3(x1, y1, z1)
            vertices1.Color = color
            vertices2.Position = New Vector3(x2, y2, z2)
            vertices2.Color = color
    
            Return {vertices1, vertices2}
        End Function
    
        Private Function Set2dTriangle(ByVal x1 As Integer, ByVal y1 As Integer, ByVal z1 As Integer, _
            ByVal x2 As Integer, ByVal y2 As Integer, ByVal z2 As Integer, _
            ByVal x3 As Integer, ByVal y3 As Integer, ByVal z3 As Integer, _
            ByVal color As Color) As VertexPositionColor()
    
            Dim vertices1, vertices2, vertices3 As New VertexPositionColor
    
            vertices1.Position = New Vector3(x1, y1, z1)
            vertices1.Color = color
            vertices2.Position = New Vector3(x2, y2, z2)
            vertices2.Color = color
            vertices3.Position = New Vector3(x3, y3, z3)
            vertices3.Color = color
    
            Return {vertices1, vertices2, vertices3}
        End Function
    
    End Class
    I plan on adding more primitive objects such as a square and an ellipse in the future.

    UPDATE

    Here is the function for adding an ellipse:
    Code:
        'This function simply draws an ellipse
        Private Function Set2dEllipse(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer, _
                                      ByVal size As Size, ByVal color As Color) As VertexPositionColor()
    
            Dim vertices(100) As VertexPositionColor
    
            For i As Integer = 0 To 100
                Dim angle As Double = CDbl(i / 100 * Math.PI * 2)
                vertices(i).Position = New Vector3(CSng(x + CDbl(Math.Cos(angle)) * size.Width), CSng(y + Math.Sin(angle) * size.Height), z)
                vertices(i).Color = color
            Next
    
            Return vertices
        End Function
    Here is it being used in an example:
    Code:
    Dim ellipse() As VertexPositionColor = Set2dEllipse(10, 10, 0, New Size(25, 25), Color.Black)
    grafix.DrawUserPrimitives(PrimitiveType.LineStrip, ellipse, 0, 99)
    UPDATE #2

    Here is the function for adding a rectangle:
    Code:
        Private Function Set2dRect(ByVal pt As Point, ByVal size As Size, ByVal color As Color) As VertexPositionColor()
            Dim vertices1, vertices2, vertices3, vertices4 As New VertexPositionColor
    
            vertices1.Position = New Vector3(pt.X, pt.Y, 0)
            vertices1.Color = color
            vertices2.Position = New Vector3(pt.X + size.Width, pt.Y, 0)
            vertices2.Color = color
            vertices3.Position = New Vector3(pt.X + size.Width, pt.Y + size.Height, 0)
            vertices3.Color = color
            vertices4.Position = New Vector3(pt.X, pt.Y + size.Height, 0)
            vertices4.Color = color
    
            Return {vertices1, vertices2, vertices3, vertices4, vertices1}
        End Function
    Here is an example of it being used:
    Code:
                Dim foo_rect() As VertexPositionColor = Set2dRect(New Point(5, 5), New Size(50, 50), Color.Black)
                grafix.DrawUserPrimitives(PrimitiveType.LineStrip, foo_rect, 0, 4)
    Last edited by dday9; Oct 10th, 2013 at 02:04 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width