Rotating Wireframe Cube using VB.NET and GDI+

Today I will show you how to simulate the rotation of a wireframe cube using VB.NET and GDI+. I assume the reader has at least a basic understanding of Visual Basic. See below a video of the wireframe cube in action.

So, what is GDI+? GDI+ is an API that consists of a set of classes that enable applications to draw graphics on video displays and printers. GDI+ is defined in the System.Drawing namespace.

I have created this simulation using Visual Studio Express 2010 which is freely downloadable from Microsoft. However, you can use any IDE for .NET of your choice.

THE FULL SOURCE CODE IS HERE.

The Code

First of all, create the Point3D class. This class will represent points in 3D space. Below is the code of  for the class. For better organization, save it in a file named Point3D.vb.

'
' Defines the Point3D class that represents points in 3D space.
' Developed by leonelmachava <[email protected]>
' http://codentronix.com
'
' Copyright (c) 2011 Leonel Machava
'
Public Class Point3D
    Protected m_x As Double, m_y As Double, m_z As Double

    Public Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)
        Me.X = x
        Me.Y = y
        Me.Z = z
    End Sub

    Public Property X() As Double
        Get
            Return m_x
        End Get
        Set(ByVal value As Double)
            m_x = value
        End Set
    End Property

    Public Property Y() As Double
        Get
            Return m_y
        End Get
        Set(ByVal value As Double)
            m_y = value
        End Set
    End Property

    Public Property Z() As Double
        Get
            Return m_z
        End Get
        Set(ByVal value As Double)
            m_z = value
        End Set
    End Property

    Public Function RotateX(ByVal angle As Integer) As Point3D
        Dim rad As Double, cosa As Double, sina As Double, yn As Double, zn As Double

        rad = angle * Math.PI / 180
        cosa = Math.Cos(rad)
        sina = Math.Sin(rad)
        yn = Me.Y * cosa - Me.Z * sina
        zn = Me.Y * sina + Me.Z * cosa
        Return New Point3D(Me.X, yn, zn)
    End Function

    Public Function RotateY(ByVal angle As Integer) As Point3D
        Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Zn As Double

        rad = angle * Math.PI / 180
        cosa = Math.Cos(rad)
        sina = Math.Sin(rad)
        Zn = Me.Z * cosa - Me.X * sina
        Xn = Me.Z * sina + Me.X * cosa

        Return New Point3D(Xn, Me.Y, Zn)
    End Function

    Public Function RotateZ(ByVal angle As Integer) As Point3D
        Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Yn As Double

        rad = angle * Math.PI / 180
        cosa = Math.Cos(rad)
        sina = Math.Sin(rad)
        Xn = Me.X * cosa - Me.Y * sina
        Yn = Me.X * sina + Me.Y * cosa
        Return New Point3D(Xn, Yn, Me.Z)
    End Function

    Public Function Project(ByVal viewWidth As Integer, ByVal viewHeight As Integer, ByVal fov As Integer, ByVal viewDistance As Integer)
        Dim factor As Double, Xn As Double, Yn As Double
        factor = fov / (viewDistance + Me.Z)
        Xn = Me.X * factor + viewWidth / 2
        Yn = Me.Y * factor + viewHeight / 2
        Return New Point3D(Xn, Yn, Me.Z)
    End Function
End Class

The methods RotateX(), RotateY(), and RotateZ(), rotate a point, respectively, around X, Y and Z axis. The method Project(), transforms a point from 3D space to 2D space. This is fundamental in order to draw a 3D point in our 2D screens.

You should not bother with the details of the implementation of these methods because they are just based on formulas that can be easily found on the internet.

Next, create a Windows Form, and name it Main. After that, copy the code below to the form.

'
' Simulation of a Wireframe Cube using GDI+
' Developed by leonelmachava <[email protected]>
' http://codentronix.com
'
' Copyright (c) 2011 Leonel Machava
'
Imports System.Drawing.Graphics
Imports System.Drawing.Pen
Imports System.Drawing.Color
Imports System.Drawing.Brush
Imports System.Drawing.Point

Public Class Main
    Protected m_pen As Pen
    Protected m_timer As Timer
    Protected m_vertices(8) As Point3D
    Protected m_faces(6, 4) As Integer
    Protected m_angle As Integer

    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Create a GDI+ Pen. This will be used to draw lines.
        m_pen = New Pen(Color.Red)

        InitCube()

        ' Create the timer.
        m_timer = New Timer()

        ' Set the timer interval to 33 milliseconds. This will give us 1000/34 ~ 30 frames per second.
        m_timer.Interval = 33

        ' Set the callback for the timer.
        AddHandler m_timer.Tick, AddressOf AnimationLoop

        ' Start the timer.
        m_timer.Start()
    End Sub

    Private Sub InitCube()
        ' Create an array with 8 points.
        m_vertices = New Point3D() {
                     New Point3D(-1, 1, -1),
                     New Point3D(1, 1, -1),
                     New Point3D(1, -1, -1),
                     New Point3D(-1, -1, -1),
                     New Point3D(-1, 1, 1),
                     New Point3D(1, 1, 1),
                     New Point3D(1, -1, 1),
                     New Point3D(-1, -1, 1)}

        ' Create an array representing the 6 faces of a cube. Each face is composed by indices to the vertex array
        ' above.
        m_faces = New Integer(,) {{0, 1, 2, 3}, {1, 5, 6, 2}, {5, 4, 7, 6}, {4, 0, 3, 7}, {0, 4, 5, 1}, {3, 2, 6, 7}}
    End Sub

    Private Sub AnimationLoop()
        ' Forces the Paint event to be called.
        Me.Invalidate()

        ' Update the variable after each frame.
        m_angle += 1
    End Sub

    Private Sub Main_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim t(8) As Point3D
        Dim f(4) As Integer
        Dim v As Point3D

        ' Clear the window
        e.Graphics.Clear(Color.LightBlue)

        ' Transform all the points and store them on the "t"- array.
        For i = 0 To 7
            v = m_vertices(i)
            t(i) = v.RotateX(m_angle).RotateY(m_angle).RotateZ(Me.m_angle)
            t(i) = t(i).Project(Me.ClientSize.Width, Me.ClientSize.Height, 256, 4)
        Next

        ' Draw the wireframe cube. Uses the "m_faces" array to find the vertices that compose each face.
        For i = 0 To 5
            e.Graphics.DrawLine(m_pen, CInt(t(m_faces(i, 0)).X), CInt(t(m_faces(i, 0)).Y), CInt(t(m_faces(i, 1)).X), CInt(t(m_faces(i, 1)).Y))
            e.Graphics.DrawLine(m_pen, CInt(t(m_faces(i, 1)).X), CInt(t(m_faces(i, 1)).Y), CInt(t(m_faces(i, 2)).X), CInt(t(m_faces(i, 2)).Y))
            e.Graphics.DrawLine(m_pen, CInt(t(m_faces(i, 2)).X), CInt(t(m_faces(i, 2)).Y), CInt(t(m_faces(i, 3)).X), CInt(t(m_faces(i, 3)).Y))
            e.Graphics.DrawLine(m_pen, CInt(t(m_faces(i, 3)).X), CInt(t(m_faces(i, 3)).Y), CInt(t(m_faces(i, 0)).X), CInt(t(m_faces(i, 0)).Y))
        Next
    End Sub
End Class

When the form is loaded, we first create a Pen that is later used to draw the lines of the cube. Next, we call InitCube() to initialize data about the cube. Finally, we create and setup a timer to drive the animation at 30 frames per second.

The AnimationLoop() method handles the timer event, triggering a Paint event each time it is invoked. Main_Paint() rotates and draws the wireframe cube while handling the Paint event.

THE FULL SOURCE CODE IS HERE.

Conclusion

Today, we have seen how to simulate a rotating wireframe cube. In the next tutorial, I will show you how to adapt this code to simulate a rotating solid cube.

If you liked this article, please consider leaving a comment, or sharing this post using one of the buttons below, or even subscribing to the blog.

  1. ‘See Comments at end of code
    Option Strict On
    Public Class Form1
    #Region “Declarations”
    Public cube1 As New Cube
    Public cube2 As New Cube
    Public SelectedCube As Integer = 2
    Public Controller1 As New CubeController
    Dim CubePoller As New Timer
    #End Region
    #Region “Form Events”
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    ‘Link Cubes To Form
    cube1.ParentForm = Me : cube2.ParentForm = Me
    ‘Specify Initial Location of each cube
    cube1.Location.X = Me.Width / 2 : cube1.Location.Y = Me.Height / 2 : cube1.Location.Z = 2.5
    cube2.Location.X = Me.Width : cube2.Location.Y = Me.Height : cube2.Location.Z = 2.1
    ‘Setup Each Cube’s Wireframe Color
    cube1.WireColor = Color.Red : cube2.WireColor = Color.Blue
    ‘Select The Startup Cube in the combobox
    Select Case SelectedCube
    Case 1
    ComboBox1.SelectedIndex = 0
    Case 2
    ComboBox1.SelectedIndex = 1
    End Select
    ‘Progam Cube1′s Input Controller
    cube1.Controls.Up = Keys.Up : cube1.Controls.Down = Keys.Down : cube1.Controls.Left = Keys.Left
    cube1.Controls.Right = Keys.Right : cube1.Controls.SlideTowards = Keys.Oemplus
    cube1.Controls.SlideAway = Keys.OemMinus : cube1.Controls.AngleLeft = Keys.A
    cube1.Controls.AngleRight = Keys.D : cube1.Controls.AngleUp = Keys.W
    cube1.Controls.AngleDown = Keys.S : cube1.Controls.AngleBack = Keys.Q
    cube1.Controls.AngleForward = Keys.E
    ‘Program cube2′s Input Controller
    cube2.Controls.Up = Keys.Up : cube2.Controls.Down = Keys.Down : cube2.Controls.Left = Keys.Left
    cube2.Controls.Right = Keys.Right : cube2.Controls.SlideTowards = Keys.Oemplus
    cube2.Controls.SlideAway = Keys.OemMinus : cube2.Controls.AngleLeft = Keys.A
    cube2.Controls.AngleRight = Keys.D : cube2.Controls.AngleUp = Keys.W
    cube2.Controls.AngleDown = Keys.S : cube2.Controls.AngleBack = Keys.Q
    cube2.Controls.AngleForward = Keys.E
    ‘Create a timer that polls for input and changes to cube properties
    CubePoller.Interval = 1 : CubePoller.Enabled = True
    ‘Add a handler for the timer
    AddHandler CubePoller.Tick, AddressOf CubePoller_Tick
    End Sub
    Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    ‘Clear the form
    e.Graphics.Clear(Color.White)
    ‘Update The Form’s Graphics
    cube1.Graphics = e.Graphics
    cube2.Graphics = e.Graphics
    End Sub
    Private Sub CubePoller_Tick(sender As System.Object, e As System.EventArgs)
    ‘Select a cube based on the selected item in the combobox
    Select Case ComboBox1.SelectedIndex
    Case 0
    ‘Syncronize the values in the textboxes to the
    ‘cube properties
    ‘Update cube
    cube1.Update()
    TextBox1.Text = CStr(cube1.Location.X)
    TextBox2.Text = CStr(cube1.Location.Y)
    TextBox3.Text = CStr(cube1.Location.Z)
    TextBox4.Text = CStr(cube1.Xangle)
    TextBox5.Text = CStr(CDbl(cube1.Yangle))
    TextBox6.Text = CStr(CDbl(cube1.Zangle))
    Case 1
    ‘Syncronize the values in the textboxes to the
    ‘cube properties
    ‘Update cube
    cube2.Update()
    TextBox1.Text = CStr(cube2.Location.X)
    TextBox2.Text = CStr(cube2.Location.Y)
    TextBox3.Text = CStr(cube2.Location.Z)
    TextBox4.Text = CStr(cube2.Xangle)
    TextBox5.Text = CStr(CDbl(cube2.Yangle))
    TextBox6.Text = CStr(CDbl(cube2.Zangle))
    End Select

    End Sub
    Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
    ‘set focus to textbox1
    TextBox1.Focus()
    End Sub
    #End Region
    #Region “Structures”
    Public Structure Cube
    #Region “Cube Properties”
    Public Location As Cooridinate3D
    Public Dimensions As Sizes
    Private t() As Point3D
    Private V As Point3D
    Public _Graphics As Graphics
    Private m_vertices() As Point3D
    Private _PenColor As Color
    Private _m_pen As Pen
    Private _ParentForm As Form
    Private IsInitialized As Boolean
    Private m_x As Double, m_y As Double, m_z As Double
    Public Xangle As Double
    Public Yangle As Double
    Public Zangle As Double
    Public Controls As CubeController
    Private m_faces(,) As Integer
    Private f() As Integer
    Public Property ParentForm As Form
    Get
    Return _ParentForm
    End Get
    Set(value As Form)
    _ParentForm = value
    Location.MainForm = value
    Initialize()
    End Set
    End Property

    Public Property Graphics As Graphics
    Get
    Return _Graphics
    End Get
    Set(value As Graphics)
    Transform()
    _Graphics = value
    DrawCube()
    End Set
    End Property
    Public ReadOnly Property m_pen As Pen
    Get
    Return _m_pen
    End Get
    End Property
    Public Property WireColor As Color
    Get
    Return _PenColor
    End Get
    Set(value As Color)
    _PenColor = value
    _m_pen = New Pen(value)
    Initialize()
    End Set
    End Property
    #End Region
    #Region “Cube Functions”
    Public Sub Transform()
    Dim tt(8) As Point3D
    Dim ff(4) As Integer
    Dim vv As Point3D = Nothing
    For i = 0 To 7
    vv = m_vertices(i)
    tt(i) = vv.RotateX(CInt(Xangle)).RotateY(CInt(Yangle)).RotateZ(CInt(Zangle))
    tt(i) = CType(tt(i).Project(CDbl(Me.Location.X), CDbl(Me.Location.Y), 100, CDbl(Me.Location.Z)), Point3D)
    Next
    Me.t = tt
    Me.f = ff
    Me.V = vv
    End Sub
    Public Sub RotateX(ByVal Angle As Double)
    Xangle = Angle
    If IsInitialized = True Then
    Animate()
    End If
    End Sub
    Public Sub RotateY(ByVal Angle As Double)
    Yangle = Angle
    If IsInitialized = True Then
    Animate()
    End If
    End Sub
    Public Sub RotateZ(ByVal Angle As Double)
    Zangle = Angle
    If IsInitialized = True Then
    Animate()
    End If
    End Sub
    Public Sub DrawCube()
    For i = 0 To 5
    Me.Graphics.DrawLine(Me.m_pen, CInt(Me.t(Me.m_faces(i, 0)).X), CInt(Me.t(Me.m_faces(i, 0)).Y), CInt(Me.t(Me.m_faces(i, 1)).X), CInt(Me.t(Me.m_faces(i, 1)).Y))
    Me.Graphics.DrawLine(Me.m_pen, CInt(Me.t(Me.m_faces(i, 1)).X), CInt(Me.t(Me.m_faces(i, 1)).Y), CInt(Me.t(Me.m_faces(i, 2)).X), CInt(Me.t(Me.m_faces(i, 2)).Y))
    Me.Graphics.DrawLine(Me.m_pen, CInt(Me.t(Me.m_faces(i, 2)).X), CInt(Me.t(Me.m_faces(i, 2)).Y), CInt(Me.t(Me.m_faces(i, 3)).X), CInt(Me.t(Me.m_faces(i, 3)).Y))
    Me.Graphics.DrawLine(Me.m_pen, CInt(Me.t(Me.m_faces(i, 3)).X), CInt(Me.t(Me.m_faces(i, 3)).Y), CInt(Me.t(Me.m_faces(i, 0)).X), CInt(Me.t(Me.m_faces(i, 0)).Y))
    Next
    End Sub
    Public Sub Update()
    Controls.Initialize()
    If Controls.KeyIsDown(CType(Controls.Up, Keys)) Then
    Me.Location.Y = CDbl(Me.Location.Y) – Controls.XYMove
    End If
    If Controls.KeyIsDown(CType(Controls.Down, Keys)) Then
    Me.Location.Y = CDbl(Me.Location.Y) + Controls.XYMove
    End If
    If Controls.KeyIsDown(CType(Controls.Left, Keys)) Then
    Me.Location.X = CDbl(Me.Location.X) – Controls.XYMove
    End If
    If Controls.KeyIsDown(CType(Controls.Right, Keys)) Then
    Me.Location.X = CDbl(Me.Location.X) + Controls.XYMove
    End If
    If Controls.KeyIsDown(CType(Controls.SlideAway, Keys)) Then
    Me.Location.Z = CDbl(Me.Location.Z) + Controls.SlideIncrement
    End If
    If Controls.KeyIsDown(CType(Controls.SlideTowards, Keys)) Then
    If CDbl(Me.Location.Z) > 1.1 Then
    Me.Location.Z = CDbl(Me.Location.Z) – Controls.SlideIncrement
    End If
    End If
    If Controls.KeyIsDown(CType(Controls.AngleLeft, Keys)) Then
    Me.RotateY(Me.Yangle + Controls.RotationIncrement)
    End If
    If Controls.KeyIsDown(CType(Controls.AngleRight, Keys)) Then
    Me.RotateY(Me.Yangle – Controls.RotationIncrement)
    End If
    If Controls.KeyIsDown(CType(Controls.AngleBack, Keys)) Then
    Me.RotateX(Me.Xangle – Controls.RotationIncrement)
    End If
    If Controls.KeyIsDown(CType(Controls.AngleForward, Keys)) Then
    Me.RotateX(Me.Xangle + Controls.RotationIncrement)
    End If

    If Controls.KeyIsDown(CType(Controls.AngleUp, Keys)) Then
    Me.RotateZ(Me.Zangle – Controls.RotationIncrement)
    End If
    If Controls.KeyIsDown(CType(Controls.AngleDown, Keys)) Then
    Me.RotateZ(Me.Zangle + Controls.RotationIncrement)
    End If
    End Sub
    Public Sub Initialize()
    m_vertices = New Point3D() {
    New Point3D(-1, 1, -1),
    New Point3D(1, 1, -1),
    New Point3D(1, -1, -1),
    New Point3D(-1, -1, -1),
    New Point3D(-1, 1, 1),
    New Point3D(1, 1, 1),
    New Point3D(1, -1, 1),
    New Point3D(-1, -1, 1)}
    m_faces = New Integer(,) {{0, 1, 2, 3}, {1, 5, 6, 2}, {5, 4, 7, 6}, {4, 0, 3, 7}, {0, 4, 5, 1}, {3, 2, 6, 7}}
    If WireColor = Nothing Then
    WireColor = Color.Red
    End If
    IsInitialized = True
    End Sub
    Public Sub Animate()
    ParentForm.Invalidate()
    End Sub
    #End Region
    End Structure
    Public Structure Cooridinate3D
    Dim _X As Double
    Dim _Y As Double
    Dim _Z As Double
    Dim MainForm As Form
    Public Property X As Double
    Get
    Return _X
    End Get
    Set(value As Double)
    _X = CDbl(value)
    MainForm.Invalidate()
    End Set
    End Property
    Public Property Y As Double
    Get
    Return _Y
    End Get
    Set(value As Double)
    _Y = CDbl(value)
    MainForm.Invalidate()
    End Set
    End Property
    Public Property Z As Double
    Get
    Return _Z
    End Get
    Set(value As Double)
    _Z = CDbl(value)
    MainForm.Invalidate()
    End Set
    End Property
    End Structure
    Public Structure Sizes
    Dim X As Double
    Dim Y As Double
    Dim Z As Double
    End Structure
    Public Structure Point3D
    Private m_x As Double, m_y As Double, m_z As Double
    Public Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)
    Me.X = x
    Me.Y = y
    Me.Z = z
    End Sub
    Public Property X() As Double
    Get
    Return m_x
    End Get
    Set(ByVal value As Double)
    m_x = value
    End Set
    End Property
    Public Property Y() As Double
    Get
    Return m_y
    End Get
    Set(ByVal value As Double)
    m_y = value
    End Set
    End Property
    Public Property Z() As Double
    Get
    Return m_z
    End Get
    Set(ByVal value As Double)
    m_z = value
    End Set
    End Property
    Public Function RotateX(ByVal angle As Integer) As Point3D
    Dim rad As Double, cosa As Double, sina As Double, yn As Double, zn As Double
    rad = angle * Math.PI / 180
    cosa = Math.Cos(rad)
    sina = Math.Sin(rad)
    yn = Me.Y * cosa – Me.Z * sina
    zn = Me.Y * sina + Me.Z * cosa
    Return New Point3D(Me.X, yn, zn)
    End Function
    Public Function RotateY(ByVal angle As Integer) As Point3D
    Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Zn As Double
    rad = angle * Math.PI / 180
    cosa = Math.Cos(rad)
    sina = Math.Sin(rad)
    Zn = Me.Z * cosa – Me.X * sina
    Xn = Me.Z * sina + Me.X * cosa
    Return New Point3D(Xn, Me.Y, Zn)
    End Function
    Public Function RotateZ(ByVal angle As Integer) As Point3D
    Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Yn As Double
    rad = angle * Math.PI / 180
    cosa = Math.Cos(rad)
    sina = Math.Sin(rad)
    Xn = Me.X * cosa – Me.Y * sina
    Yn = Me.X * sina + Me.Y * cosa
    Return New Point3D(Xn, Yn, Me.Z)
    End Function
    Public Function Project(ByVal viewWidth As Double, ByVal viewHeight As Double, ByVal fov As Double, ByVal viewDistance As Double) As Point3D
    Dim factor As Double, Xn As Double, Yn As Double
    factor = fov / (viewDistance + Me.Z)
    Xn = Me.X * factor + viewWidth / 2
    Yn = Me.Y * factor + viewHeight / 2
    Return New Point3D(Xn, Yn, Me.Z)
    End Function
    End Structure
    Public Structure CubeController
    Dim Up As Integer
    Dim Down As Integer
    Dim Left As Integer
    Dim Right As Integer
    Dim SlideTowards As Integer
    Dim SlideAway As Integer
    Dim AngleLeft As Integer
    Dim AngleRight As Integer
    Dim AngleUp As Integer
    Dim AngleDown As Integer
    Dim AngleBack As Integer
    Dim AngleForward As Integer
    Public XYMove As Double
    Public SlideIncrement As Double
    Public RotationIncrement As Double
    Public Declare Function GetAsyncKeyState Lib “user32.dll” (ByVal vKey As Int32) As UShort
    Public ReadOnly Property KeyIsDown(ByVal Key As Keys) As Boolean
    Get
    Return CBool(GetAsyncKeyState(Key) And &H8000US)
    End Get
    End Property
    Public Sub Initialize()
    XYMove = 2
    SlideIncrement = 0.01
    RotationIncrement = 0.3
    End Sub
    End Structure
    #End Region

    End Class

    #Region “Comments”
    ’3D Wireframe Cube Example Modified By:
    ‘ Paul Ishak 2011
    [email protected]

    ‘Changes:

    ‘add the textboxes & combobox in a right side docked panel

    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘———————————————————————————————
    ‘ Simulation of a Wireframe Cube using GDI+
    ‘ Developed by leonelmachava
    http://codentronix.com

    ‘ Copyright (c) 2011 Leonel Machava

    ‘ Permission is hereby granted, free of charge, to any person obtaining a copy of this
    ‘ software and associated documentation files (the “Software”), to deal in the Software
    ‘ without restriction, including without limitation the rights to use, copy, modify,
    ‘ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
    ‘ permit persons to whom the Software is furnished to do so, subject to the following
    ‘ conditions:

    ‘ The above copyright notice and this permission notice shall be included in all copies
    ‘ or substantial portions of the Software.

    ‘ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    ‘ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    ‘ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
    ‘ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
    ‘ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    ‘ DEALINGS IN THE SOFTWARE.
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    ‘——————————————————————————————–
    #End Region

  2. Hi lefam,

    I found this program of you for a rotating wireframe cube over a web search to this topic. After the content of you had awakened my interest I downloaded the source code you have offered and gave it a try in my visual basic 2010 express program on my computer and it ran right away. Thank you very much. I am really looking forward to explore your code and try to understand everything as a basis for further experiments by myself. I also found your program for a rotating solid cube out of this site and it also ran right away on my pc. Also a very intersting program to me that is waiting for its exploration now. Thank you very much for both source codes and your explanations. I appreciate it a lot. :)

    Bye,
    John D. Blue

  3. If somebody may tell me the brands of a few dependable vision skincare items it’d be truly
    useful.

Reply to John D. Blue ¬
Cancel reply

Notify me of followup comments via e-mail. You can also subscribe without commenting.