'***************************************************************************************
' 
' File name: M3dgra.cpp
' Location: See Matrox Example Launcher in the MIL Control Center
' 
'
' Synopsis: This program contains an example Of how To use 3D graphics In MIL.
'
' Copyright (C) Matrox Electronic Systems Ltd., 1992-2020.
' All Rights Reserved
'****************************************************************************

Imports Microsoft.VisualBasic
Imports System
Imports System.Threading

Imports Matrox.MatroxImagingLibrary

Module M3dgra
    '----------------------------------------------------------------------------
    'Example description.
    '----------------------------------------------------------------------------
    Sub PrintHeader()
        Console.WriteLine("[EXAMPLE NAME]")
        Console.WriteLine("M3dgra")
        Console.WriteLine()
        Console.WriteLine("[SYNOPSIS]")
        Console.WriteLine("This example demonstrates the usage of 3D graphics in MIL.")
        Console.WriteLine()

        Console.WriteLine("[MODULES USED]")
        Console.WriteLine("Modules used: application, system, buffer, 3D display, 3D graphics, 3D Geometry, 3D Image Processing.")
        Console.WriteLine("Press <Enter> to continue.")
        Console.WriteLine()
        Console.ReadKey()
    End Sub

    '*****************************************************************************
    ' Constants.
    '*****************************************************************************
    Private ReadOnly POINT_CLOUD_FILE As String = MIL.M_IMAGE_PATH + "M3dgra/MaskOrganized.mbufc"
    Private ReadOnly GLASSES_FILE As String = MIL.M_IMAGE_PATH + "M3dgra/Glasses.png"
    Private ReadOnly LOGO_FILE As String = MIL.M_IMAGE_PATH + "imaginglogo.mim"

    Private ReadOnly FADE_DELAY_MSEC As Integer = 750
    Private ReadOnly CONTROL_DELAY_MSEC As Integer = 2000
    Private ReadOnly CONTROL_GRANULARITY As Integer = 20

   '--------------------------------------------------------------
   Sub Main()
      ' Print example information in console.
      PrintHeader()

      Dim MilApplication As MIL_ID = MIL.M_NULL    ' MIL application identifier
      Dim MilSystem As MIL_ID = MIL.M_NULL         ' MIL system identifier
      Dim MilDisplay3d As MIL_ID = MIL.M_NULL      ' MIL display identifier
      Dim MilGraphicList3d As MIL_ID = MIL.M_NULL  ' MIL 3d graphic list.
      Dim MilContainerId As MIL_ID = MIL.M_NULL    ' Point cloud to display.
      Dim MilTextureId As MIL_ID = MIL.M_NULL      ' Polygon texture.

      ' Allocate the MIL application.
      MIL.MappAlloc(MIL.M_NULL, MIL.M_DEFAULT, MilApplication)

      ' Allocate MIL objects.
      MIL.MsysAlloc(MIL.M_DEFAULT, MIL.M_SYSTEM_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MilSystem)

      MIL.MappControl(MIL.M_DEFAULT, MIL.M_ERROR, MIL.M_PRINT_DISABLE)
      MIL.M3ddispAlloc(MilSystem, MIL.M_DEFAULT, "M_DEFAULT", MIL.M_DEFAULT, MilDisplay3d)
      MIL.MappControl(MIL.M_DEFAULT, MIL.M_ERROR, MIL.M_PRINT_ENABLE)

      ' Make sure we meet the minimum requirements for the 3d display.
      If MilDisplay3d = MIL.M_NULL Then
            Console.WriteLine("The current system does not support the 3D display.")
            Console.WriteLine("Press any key to end.")
            Console.ReadKey()

            MIL.MsysFree(MilSystem)
            MIL.MappFree(MilApplication)
            Return
        End If

        ' Show the display.
        MIL.M3ddispInquire(MilDisplay3d, MIL.M_3D_GRAPHIC_LIST_ID, MilGraphicList3d)
        MIL.M3ddispSetView(MilDisplay3d, MIL.M_VIEW_ORIENTATION, -2, -1.1, -1, MIL.M_DEFAULT)
        MIL.M3ddispSetView(MilDisplay3d, MIL.M_UP_VECTOR, 0, 0, 1, MIL.M_DEFAULT)
        MIL.M3ddispSelect(MilDisplay3d, MIL.M_NULL, MIL.M_OPEN, MIL.M_DEFAULT)


        ' Draw an axis And a grid.
        Console.WriteLine("The 3d display can show many point clouds at the same time.")
        Console.WriteLine("It can also show no point cloud and only the contents of a 3D graphics list.")
        Console.WriteLine("Here, it shows an axis and a grid.")

        Dim AxisLength As Double = 200
        Dim AxisLabel As Long = MIL.M3dgraAxis(MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_DEFAULT, AxisLength, "", MIL.M_DEFAULT, MIL.M_DEFAULT)

        Dim Matrix As MIL_ID = MIL.M3dgeoAlloc(MilSystem, MIL.M_TRANSFORMATION_MATRIX, MIL.M_DEFAULT, MIL.M_NULL)
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, AxisLength * 0.4, AxisLength * 0.4, 0, MIL.M_DEFAULT, MIL.M_DEFAULT)
        Dim GridLabel As Long = MIL.M3dgraGrid(MilGraphicList3d, AxisLabel, MIL.M_SIZE_AND_SPACING, Matrix, AxisLength * 0.8, AxisLength * 0.8, 16, 16, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, GridLabel, MIL.M_FILL_COLOR, MIL.M_COLOR_WHITE)
        MIL.M3dgraControl(MilGraphicList3d, GridLabel, MIL.M_COLOR, MIL.M_COLOR_BLACK)
        MIL.M3dgraControl(MilGraphicList3d, GridLabel, MIL.M_OPACITY, 30)

        Console.WriteLine("Press <Enter> to continue.")
        Console.WriteLine()
        Console.ReadKey()

        ' Restore And display the point cloud.
        MIL.MbufRestore(POINT_CLOUD_FILE, MilSystem, MilContainerId)
        Dim ContainerLabel As Long = MIL.M3dgraAdd(MilGraphicList3d, AxisLabel, MilContainerId, MIL.M_DEFAULT)

        ' Set various color modes.
        Console.WriteLine("A point cloud has been added to the display.")
        Console.WriteLine("By default, point clouds are colored using the reflectance or intensity component.")
        Console.WriteLine("However, you can use any band(s) of any component for the color, and optionally apply a LUT.")
        Console.WriteLine("Press <Enter> to view the coloring options.")
        Console.WriteLine()
        Console.ReadKey()

        Console.WriteLine("Range:                     The XYZ values are rescaled to RGB.")
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_COMPONENT, MIL.M_COMPONENT_RANGE)
        Console.Write("<Enter to continue>." + Chr(13))
        Console.ReadKey()

        Console.WriteLine("Range 3rd band with a LUT: Highlights elevation differences (Z).")
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_USE_LUT, MIL.M_TRUE)
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_COMPONENT_BAND, 2)
        Console.Write("<Enter to continue>." + Chr(13))
        Console.ReadKey()

        Console.WriteLine("Normals:                   Highlights details.")
        MIL.M3dimNormals(MIL.M_NORMALS_CONTEXT_ORGANIZED, MilContainerId, MilContainerId, MIL.M_DEFAULT)
        MIL.M3ddispControl(MilDisplay3d, MIL.M_UPDATE, MIL.M_DISABLE)
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_USE_LUT, MIL.M_FALSE)
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_COMPONENT_BAND, MIL.M_ALL_BANDS)
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_COMPONENT, MIL.M_COMPONENT_NORMALS_MIL)
        MIL.M3ddispControl(MilDisplay3d, MIL.M_UPDATE, MIL.M_ENABLE)
        Console.Write("<Enter to continue>." + Chr(13))
        Console.ReadKey()

        Console.WriteLine("Solid color:               Differentiates between multiple point clouds.")
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR, MIL.M_COLOR_BLUE)
        MIL.M3dgraControl(MilGraphicList3d, ContainerLabel, MIL.M_COLOR_COMPONENT, MIL.M_NULL)
        Console.Write("<Enter to continue>." + Chr(13))
        Console.ReadKey()

        ' Add a mesh.
        Console.WriteLine("Solid color (with a mesh): Similar to solid color while still showing details.")
        MIL.M3dimMesh(MIL.M_MESH_CONTEXT_ORGANIZED, MilContainerId, MilContainerId, MIL.M_DEFAULT)
        Console.WriteLine("<Enter to continue>.")
        Console.WriteLine()
        Console.ReadKey()

        ' Restore the matrox logo And draw it on a polygon.
        Console.WriteLine("2D images can be displayed in the 3D graphics list via textured polygons.")

        MIL.M3dgraRemove(MilGraphicList3d, ContainerLabel, MIL.M_DEFAULT)
        MIL.MbufRestore(LOGO_FILE, MilSystem, MilTextureId)
        Dim PolygonCenterX As Double = 100
        Dim PolygonCenterY As Double = 100
        Dim PolygonHalfSizeX As Double = MIL.MbufInquire(MilTextureId, MIL.M_SIZE_X, MIL.M_NULL) / 5
        Dim PolygonHalfSizeY As Double = MIL.MbufInquire(MilTextureId, MIL.M_SIZE_Y, MIL.M_NULL) / 5
        Dim PolygonX As Double() = New Double() {PolygonCenterX - PolygonHalfSizeY, PolygonCenterX + PolygonHalfSizeY, PolygonCenterX + PolygonHalfSizeY, PolygonCenterX - PolygonHalfSizeY}
        Dim PolygonY As Double() = New Double() {PolygonCenterY - PolygonHalfSizeX, PolygonCenterY - PolygonHalfSizeX, PolygonCenterY + PolygonHalfSizeX, PolygonCenterY + PolygonHalfSizeX}
        Dim PolygonZ As Double() = New Double() {30, 30, 30, 30}
        Dim PolygonLabel As Long = MIL.M3dgraPolygon(MilGraphicList3d, AxisLabel, MIL.M_DEFAULT, 4, PolygonX, PolygonY, PolygonZ, MIL.M_NULL, MIL.M_NULL, MilTextureId, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, PolygonLabel, MIL.M_SHADING, MIL.M_NONE)
        MIL.MbufFree(MilTextureId)

        ' Draw other graphics.
        Console.WriteLine("Press <Enter> to show other graphic primitives.")
        Console.WriteLine()
        Console.ReadKey()
        MIL.M3dgraRemove(MilGraphicList3d, PolygonLabel, MIL.M_DEFAULT)
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, 100, 100, 0, MIL.M_DEFAULT, MIL.M_DEFAULT)
        Dim NodeLabel As Long = MIL.M3dgraNode(MilGraphicList3d, AxisLabel, Matrix, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, MIL.M_DEFAULT_SETTINGS, MIL.M_OPACITY, 0)

        ' Plane.
        Dim PlaneLabel As Long = MIL.M3dgraPlane(MilGraphicList3d, NodeLabel, MIL.M_POINT_AND_NORMAL, 0, 0, 10, 0, 0, 1, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, 70, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, PlaneLabel, FADE_DELAY_MSEC)

        ' Box.
        Dim BoxLabel As Long = MIL.M3dgraBox(MilGraphicList3d, NodeLabel, MIL.M_CENTER_AND_DIMENSION, 0, 0, 40, 40, 40, 60, MIL.M_DEFAULT, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, BoxLabel, FADE_DELAY_MSEC)

        ' Cylinder.
        Dim CylinderLabel As Long = MIL.M3dgraCylinder(MilGraphicList3d, NodeLabel, MIL.M_TWO_POINTS, 0, 0, 70, 0, 0, 120, 20, MIL.M_DEFAULT, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, CylinderLabel, FADE_DELAY_MSEC)

        ' Sphere.
        Dim SphereLabel As Long = MIL.M3dgraSphere(MilGraphicList3d, NodeLabel, 0, 0, 140, 20, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, SphereLabel, FADE_DELAY_MSEC)

        ' Line.
        Dim LineLabel As Long = MIL.M3dgraLine(MilGraphicList3d, NodeLabel, MIL.M_TWO_POINTS, MIL.M_DEFAULT, 0, -20, 110, 0, -40, 70, MIL.M_DEFAULT, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, LineLabel, FADE_DELAY_MSEC)

        ' Arc.
        Dim ArcLabel As Long = MIL.M3dgraArc(MilGraphicList3d, NodeLabel, MIL.M_THREE_POINTS, MIL.M_DEFAULT, 0, 20, 110, 0, 40, 130, 0, 40, 150, MIL.M_DEFAULT, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, ArcLabel, FADE_DELAY_MSEC)

        ' Dots.
        Dim DotsX As Double() = New Double() {18, 18}
        Dim DotsY As Double() = New Double() {-10, 10}
        Dim DotsZ As Double() = New Double() {145, 145}
        Dim DotsLabel As Long = MIL.M3dgraDots(MilGraphicList3d, NodeLabel, 2, DotsX, DotsY, DotsZ, MIL.M_NULL, MIL.M_NULL, MIL.M_NULL, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, DotsLabel, MIL.M_THICKNESS, 3)
        FadeIn(MilGraphicList3d, DotsLabel, FADE_DELAY_MSEC)

        ' Polygon.
        MIL.MbufImport(GLASSES_FILE, MIL.M_PNG, MIL.M_RESTORE, MilSystem, MilTextureId)
        Dim GlassesX As Double() = New Double() {20, 20, 20, 20}
        Dim GlassesY As Double() = New Double() {-18, -18, 18, 18}
        Dim GlassesZ As Double() = New Double() {152, 137, 137, 152}
        Dim GlassesLabel As Long = MIL.M3dgraPolygon(MilGraphicList3d, NodeLabel, MIL.M_DEFAULT, 4, GlassesX, GlassesY, GlassesZ, MIL.M_NULL, MIL.M_NULL, MilTextureId, MIL.M_DEFAULT)
        MIL.MbufFree(MilTextureId)
        MIL.M3dgraControl(MilGraphicList3d, GlassesLabel, MIL.M_KEYING_COLOR, MIL.M_COLOR_BLACK)
        FadeIn(MilGraphicList3d, GlassesLabel, FADE_DELAY_MSEC)

        ' Text.
        MIL.M3dgeoMatrixSetWithAxes(Matrix, MIL.M_XY_AXES, 0, 0, 165, 0, 1, 0, 0, 0, 1, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, MIL.M_DEFAULT_SETTINGS, MIL.M_FONT_SIZE, 15)
        MIL.M3dgraControl(MilGraphicList3d, MIL.M_DEFAULT_SETTINGS, MIL.M_TEXT_ALIGN_HORIZONTAL, MIL.M_CENTER)
        MIL.M3dgraControl(MilGraphicList3d, MIL.M_DEFAULT_SETTINGS, MIL.M_TEXT_ALIGN_VERTICAL, MIL.M_BOTTOM)
        Dim TextLabel As Long = MIL.M3dgraText(MilGraphicList3d, NodeLabel, "Welcome to MIL!", Matrix, MIL.M_DEFAULT, MIL.M_DEFAULT)
        FadeIn(MilGraphicList3d, TextLabel, FADE_DELAY_MSEC)
        Console.WriteLine()

        MIL.M3dgraControl(MilGraphicList3d, MIL.M_DEFAULT_SETTINGS, MIL.M_OPACITY, 100)

        ' Print the contents of the 3D graphics list.
        Console.WriteLine("The contents of the graphics list can be inquired either in a flat list or recursively.")
        Console.WriteLine("Press <Enter> to view the graphics in a flat list with their absolute position.")
        Console.WriteLine()
        Console.ReadKey()

        Console.WriteLine("Graphic type          Position X      Position Y      Position Z")
        Console.WriteLine("-----------------------------------------------------------------")
        PrintGraphicListFlat(MilGraphicList3d)

        Console.WriteLine()
        Console.WriteLine("Press <Enter> to view the graphics in a tree and their position relative to their parent.")
        Console.WriteLine()
        Console.ReadKey()

        Console.WriteLine("Graphic type          Position X      Position Y      Position Z")
        Console.WriteLine("-----------------------------------------------------------------")
        PrintGraphicListTree(MilGraphicList3d)

        ' Perform various controls.
        Console.WriteLine()
        Console.WriteLine("The tree structure makes controlling groups of graphics easy.")
        Console.WriteLine("Here, the character's graphics are controlled all at once via their parent node.")
        Console.WriteLine("Press <Enter> see various controls.")
        Console.WriteLine()
        Console.ReadKey()

        ' Color.
        Console.WriteLine("Color:      Doesn't affect textured polygons.")
        Console.Write("<Enter to continue>." + Chr(13))
        Dim ColorLut As MIL_ID = MIL.MbufAllocColor(MilSystem, 3, CONTROL_GRANULARITY, 1, MIL.M_UNSIGNED + 8, MIL.M_LUT, MIL.M_NULL)
        MIL.MgenLutFunction(ColorLut, MIL.M_COLORMAP_HUE, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT)
        Dim i As Integer = 0
        While Not Console.KeyAvailable
            Dim Color(3) As Byte
            MIL.MbufGet1d(ColorLut, i Mod CONTROL_GRANULARITY, 1, Color)
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_COLOR + MIL.M_RECURSIVE, MIL.M_RGB888(Color(0), Color(1), Color(2)))
            Thread.Sleep(CONTROL_DELAY_MSEC \ CONTROL_GRANULARITY)
            i += 1
        End While
        MIL.MbufFree(ColorLut)
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_COLOR + MIL.M_RECURSIVE, MIL.M_COLOR_WHITE)
        Console.ReadKey()

        ' Opacity.
        Console.WriteLine("Opacity:    Graphics can be from fully opaque to fully transparent.")
        Console.Write("<Enter to continue>." + Chr(13))
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_OPACITY + MIL.M_RECURSIVE, 50 + 50 * Math.Sin(3.1415 * 2 * i / CONTROL_GRANULARITY))
            Thread.Sleep(CONTROL_DELAY_MSEC \ CONTROL_GRANULARITY)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_OPACITY + MIL.M_RECURSIVE, 100)
        Console.ReadKey()

        ' Resolution.
        Console.WriteLine("Resolution: Controls how fine the mesh is for cylinders, spheres and arcs.")
        Console.Write("<Enter to continue>." + Chr(13))
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_GRAPHIC_RESOLUTION + MIL.M_RECURSIVE, 3 + i Mod CONTROL_GRANULARITY)
            Thread.Sleep(CONTROL_DELAY_MSEC \ CONTROL_GRANULARITY)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_GRAPHIC_RESOLUTION + MIL.M_RECURSIVE, 16)
        Console.ReadKey()

        ' Shading.
        Console.WriteLine("Shading:    Graphics can choose between flat, Gouraud, Phong or no shading at all.")
        Console.Write("<Enter to continue>." + Chr(13))
        Dim SHADINGS As MIL_INT() = New MIL_INT() {MIL.M_NONE, MIL.M_FLAT, MIL.M_GOURAUD, MIL.M_PHONG}
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_SHADING + MIL.M_RECURSIVE, SHADINGS(i Mod 4))
            Thread.Sleep(CONTROL_DELAY_MSEC \ 4)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_SHADING + MIL.M_RECURSIVE, MIL.M_GOURAUD)
        Console.ReadKey()

        ' Thickness.
        Console.WriteLine("Thickness:  Controls how thick lines and points look.")
        Console.Write("<Enter to continue>." + Chr(13))
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_THICKNESS + MIL.M_RECURSIVE, 1 + i Mod CONTROL_GRANULARITY)
            Thread.Sleep(CONTROL_DELAY_MSEC \ CONTROL_GRANULARITY)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_THICKNESS + MIL.M_RECURSIVE, 1)
        Console.ReadKey()

        ' Movement.
        Console.WriteLine("Movement:   Graphics can be moved with rigid transformations.")
        Console.Write("<Enter to continue>." + Chr(13))
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, -100, -100, 0, MIL.M_DEFAULT, MIL.M_DEFAULT)
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_ROTATION_Z, 90.0 / CONTROL_GRANULARITY, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_COMPOSE_WITH_CURRENT)
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, 100, 100, 0, MIL.M_DEFAULT, MIL.M_COMPOSE_WITH_CURRENT)

        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraCopy(Matrix, MIL.M_DEFAULT, MilGraphicList3d, NodeLabel, MIL.M_TRANSFORMATION_MATRIX + MIL.M_COMPOSE_WITH_CURRENT, MIL.M_DEFAULT)
            Thread.Sleep(CONTROL_DELAY_MSEC \ CONTROL_GRANULARITY)
            i += 1
        End While
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, 100, 100, 0, MIL.M_DEFAULT, MIL.M_DEFAULT)
        MIL.M3dgraCopy(Matrix, MIL.M_DEFAULT, MilGraphicList3d, NodeLabel, MIL.M_TRANSFORMATION_MATRIX, MIL.M_DEFAULT)
        Console.ReadKey()

        ' Copy.
        Console.WriteLine("Copy:       Graphics can be copied across the same or different graphics lists.")
        Console.Write("<Enter to continue>." + Chr(13))
        Dim CopyLabel As Long = MIL.M3dgraCopy(MilGraphicList3d, NodeLabel, MilGraphicList3d, AxisLabel, MIL.M_GRAPHIC + MIL.M_RECURSIVE, MIL.M_DEFAULT)
        MIL.M3dgeoMatrixSetTransform(Matrix, MIL.M_TRANSLATION, 100, 250, 0, MIL.M_DEFAULT, MIL.M_DEFAULT)
        MIL.M3dgraCopy(Matrix, MIL.M_DEFAULT, MilGraphicList3d, CopyLabel, MIL.M_TRANSFORMATION_MATRIX, MIL.M_DEFAULT)
        Console.ReadKey()

        ' Visibility.
        Console.WriteLine("Visibility: Unneeded graphics can be hidden without deleting them.")
        Console.Write("<Enter to continue>." + Chr(13))
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_VISIBLE + MIL.M_RECURSIVE, If((i + 1) Mod 4 < 2, MIL.M_TRUE, MIL.M_FALSE))
            MIL.M3dgraControl(MilGraphicList3d, CopyLabel, MIL.M_VISIBLE + MIL.M_RECURSIVE, If(i Mod 4 < 2, MIL.M_TRUE, MIL.M_FALSE))
            Thread.Sleep(CONTROL_DELAY_MSEC \ 4)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, NodeLabel, MIL.M_VISIBLE + MIL.M_RECURSIVE, MIL.M_TRUE)
        MIL.M3dgraControl(MilGraphicList3d, CopyLabel, MIL.M_VISIBLE + MIL.M_RECURSIVE, MIL.M_FALSE)
        Console.ReadKey()

        ' Inquire And draw the bounding box.
        Console.WriteLine("                    ")
        Console.WriteLine("It may be useful to know the bounding box of the 3D graphics list.")

        Dim MilBoxGeometry As MIL_ID = MIL.M3dgeoAlloc(MilSystem, MIL.M_GEOMETRY, MIL.M_DEFAULT, MIL.M_NULL)
        MIL.M3dgraCopy(MilGraphicList3d, MIL.M_LIST, MilBoxGeometry, MIL.M_DEFAULT, MIL.M_BOUNDING_BOX, MIL.M_DEFAULT)
        Dim BoundingBoxLabel As Long = MIL.M3dgeoDraw3d(MIL.M_DEFAULT, MilBoxGeometry, MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_OPACITY, 30)
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_THICKNESS, 3)
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_FILL_COLOR, MIL.M_COLOR_WHITE)
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_COLOR, MIL.M_COLOR_BLACK)

        Console.WriteLine("Press <Enter> to continue.")
        Console.WriteLine()
        Console.ReadKey()

        ' Change the appearance of the bounding box.
        Console.WriteLine("Graphics can be displayed as either points, wireframe, or solid surfaces.")
        Console.WriteLine("Press <Enter> to continue.")
        Console.WriteLine()

        Dim Appearances As MIL_ID() = New MIL_ID() {MIL.M_POINTS, MIL.M_WIREFRAME, MIL.M_SOLID_WITH_WIREFRAME, MIL.M_SOLID}
        i = 0
        While Not Console.KeyAvailable
            MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_APPEARANCE, Appearances(i Mod 4))
            Thread.Sleep(CONTROL_DELAY_MSEC \ 4)
            i += 1
        End While
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_APPEARANCE, MIL.M_SOLID_WITH_WIREFRAME)
        Console.ReadKey()

        ' Clip a plane using the bounding box.
        Console.WriteLine("The bounding box is used to clip infinite geometries like planes, lines and cylinders.")
        Console.WriteLine("Press <Enter> to show plane clipping.")
        Console.WriteLine()
        Console.ReadKey()

        Dim InfinitePlaneLabel As Long = MIL.M3dgraPlane(MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_POINT_AND_NORMAL, 100, 100, 30, 0.5, 0.4, 3, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_INFINITE, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, InfinitePlaneLabel, MIL.M_COLOR, MIL.M_COLOR_BLUE)
        MIL.M3dgraControl(MilGraphicList3d, InfinitePlaneLabel, MIL.M_OPACITY, 60)

        ' Change the clipping box And clip a line.
        Console.WriteLine("The clipping box can also be set manually; it does not need to be the same as the bounding box.")
        Console.WriteLine("Press <Enter> to set a different clipping box.")
        Console.WriteLine()
        Console.ReadKey()

        ' Remove plane to focus on the clipped line.
        MIL.M3dgraRemove(MilGraphicList3d, InfinitePlaneLabel, MIL.M_DEFAULT)

        MIL.M3dgeoBox(MilBoxGeometry, MIL.M_CENTER_AND_DIMENSION, 0, 0, 0, 350, 350, 350, MIL.M_DEFAULT)
        MIL.M3dgraCopy(MilBoxGeometry, MIL.M_DEFAULT, MilGraphicList3d, MIL.M_LIST, MIL.M_CLIPPING_BOX, MIL.M_DEFAULT)
        MIL.M3dgraRemove(MilGraphicList3d, BoundingBoxLabel, MIL.M_DEFAULT)
        Dim ClippingBoxLabel As Long = MIL.M3dgeoDraw3d(MIL.M_DEFAULT, MilBoxGeometry, MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, BoundingBoxLabel, MIL.M_OPACITY, 30)
        MIL.M3dgraControl(MilGraphicList3d, ClippingBoxLabel, MIL.M_APPEARANCE, MIL.M_SOLID_WITH_WIREFRAME)
        MIL.M3dgraControl(MilGraphicList3d, ClippingBoxLabel, MIL.M_FILL_COLOR, MIL.M_COLOR_WHITE)
        MIL.M3dgraControl(MilGraphicList3d, ClippingBoxLabel, MIL.M_COLOR, MIL.M_COLOR_BLACK)
        MIL.M3dgraControl(MilGraphicList3d, ClippingBoxLabel, MIL.M_THICKNESS, 3)

        Console.WriteLine("Showing a clipped infinite line in cyan.")
        Console.WriteLine()

        Dim InfiniteLineLabel As Long = MIL.M3dgraLine(MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_POINT_AND_VECTOR, MIL.M_DEFAULT, 140, 50, 0, 0, 5, 7, MIL.M_INFINITE, MIL.M_DEFAULT)
        MIL.M3dgraControl(MilGraphicList3d, InfiniteLineLabel, MIL.M_COLOR, MIL.M_COLOR_CYAN)
        MIL.M3dgraControl(MilGraphicList3d, InfiniteLineLabel, MIL.M_THICKNESS, 5)

        Console.WriteLine("Press <Enter> to end.")
        Console.WriteLine()
        Console.ReadKey()

        MIL.M3dgeoFree(MilBoxGeometry)
        MIL.M3dgeoFree(Matrix)
        MIL.MbufFree(MilContainerId)
        MIL.M3ddispFree(MilDisplay3d)
        MIL.MsysFree(MilSystem)
        MIL.MappFree(MilApplication)
    End Sub

    Function GetGraphicTypeString(ByVal MilGraphicList3d As MIL_ID, ByVal GraphicLabel As Long) As String
        Dim Info As String
        If GraphicLabel = MIL.M_ROOT_NODE Then
            Info = "Root        "
        Else
            Dim Type As MIL_INT = MIL.M_NULL
            MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_GRAPHIC_TYPE, Type)
            Select Case Type
                Case MIL.M_GRAPHIC_TYPE_ARC
                    Info = "Arc         "
                Case MIL.M_GRAPHIC_TYPE_AXIS
                    Info = "Axis        "
                Case MIL.M_GRAPHIC_TYPE_BOX
                    Info = "Box         "
                Case MIL.M_GRAPHIC_TYPE_CYLINDER
                    Info = "Cylinder    "
                Case MIL.M_GRAPHIC_TYPE_DOTS
                    Info = "Dots        "
                Case MIL.M_GRAPHIC_TYPE_GRID
                    Info = "Grid        "
                Case MIL.M_GRAPHIC_TYPE_LINE
                    Info = "Line        "
                Case MIL.M_GRAPHIC_TYPE_NODE
                    Info = "Node        "
                Case MIL.M_GRAPHIC_TYPE_PLANE
                    Info = "Plane       "
                Case MIL.M_GRAPHIC_TYPE_POINT_CLOUD
                    Info = "Point cloud "
                Case MIL.M_GRAPHIC_TYPE_POLYGON
                    Info = "Polygon     "
                Case MIL.M_GRAPHIC_TYPE_SPHERE
                    Info = "Sphere      "
                Case MIL.M_GRAPHIC_TYPE_TEXT
                    Info = "Text        "
                Case Else
                    Info = "Unknown     "
            End Select
        End If

        Return Info
    End Function

    Sub PrintGraphicListFlat(ByVal MilGraphicList3d As MIL_ID)
        Dim NbChildren As MIL_INT = MIL.M_NULL
        MIL.M3dgraInquire(MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_NUMBER_OF_CHILDREN + MIL.M_RECURSIVE, NbChildren)
        Dim GraphicLabels(CInt(NbChildren + 1)) As Long
        MIL.M3dgraInquire(MilGraphicList3d, MIL.M_ROOT_NODE, MIL.M_CHILDREN + MIL.M_RECURSIVE, GraphicLabels)

        GraphicLabels(CInt(NbChildren)) = MIL.M_ROOT_NODE

        For i As Integer = 0 To CInt(NbChildren)
            Dim GraphicInfo As String = GetGraphicTypeString(MilGraphicList3d, GraphicLabels(i))

            Dim PosX As Double = 0
            Dim PosY As Double = 0
            Dim PosZ As Double = 0
            MIL.M3dgraInquire(MilGraphicList3d, GraphicLabels(i), MIL.M_POSITION_X + MIL.M_RELATIVE_TO_ROOT, PosX)
            MIL.M3dgraInquire(MilGraphicList3d, GraphicLabels(i), MIL.M_POSITION_Y + MIL.M_RELATIVE_TO_ROOT, PosY)
            MIL.M3dgraInquire(MilGraphicList3d, GraphicLabels(i), MIL.M_POSITION_Z + MIL.M_RELATIVE_TO_ROOT, PosZ)

            Console.WriteLine(" {0}" + vbTab + vbTab + "{1}" + vbTab + vbTab + "{2}" + vbTab + vbTab + "{3}", GraphicInfo, PosX, PosY, PosZ)
        Next
    End Sub

    Sub PrintGraphicListTree(ByVal MilGraphicList3d As MIL_ID, Optional ByVal GraphicLabel As Long = MIL.M_ROOT_NODE, Optional ByVal Prefix As String = "-")
        Dim GraphicInfo As String = GetGraphicTypeString(MilGraphicList3d, GraphicLabel)
        Console.Write("{0}{1}", Prefix, GraphicInfo)

        Dim Padding As Integer = 24 - (Prefix.Length + GraphicInfo.Length)
        For i As Integer = 0 To Padding - 1
            Console.Write(" ")
        Next

        Dim PosX As Double = 0
        Dim PosY As Double = 0
        Dim PosZ As Double = 0
        MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_POSITION_X, PosX)
        MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_POSITION_Y, PosY)
        MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_POSITION_Z, PosZ)

        Console.WriteLine("{0}" + vbTab + vbTab + "{1}" + vbTab + vbTab + "{2}", PosX, PosY, PosZ)

        Dim NbChildren As MIL_INT = MIL.M_NULL
        MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_NUMBER_OF_CHILDREN, NbChildren)
        Dim ChildrenLabels(CInt(NbChildren)) As Long
        MIL.M3dgraInquire(MilGraphicList3d, GraphicLabel, MIL.M_CHILDREN, ChildrenLabels)
        For i As Integer = 0 To CInt(NbChildren - 1)
            Dim ChildrenPrefix As String = Prefix.Replace("-", " ").Replace("'", " ")
            If i + 1 < NbChildren Then
                ChildrenPrefix += "|-"
            Else
                ChildrenPrefix += "'-"
            End If
            PrintGraphicListTree(MilGraphicList3d, ChildrenLabels(i), ChildrenPrefix)
        Next
    End Sub

    Sub FadeIn(ByVal MilGraphicList3d As MIL_ID, ByVal GraphicLabel As Long, ByVal Duration As Integer)
        Dim GraphicTypeStr As String = GetGraphicTypeString(MilGraphicList3d, GraphicLabel)
        Console.WriteLine("Adding {0}.", GraphicTypeStr.TrimEnd(" "c))

        Dim i As Integer = 0
        While (i < CONTROL_GRANULARITY) And (Not Console.KeyAvailable)
            MIL.M3dgraControl(MilGraphicList3d, GraphicLabel, MIL.M_OPACITY + MIL.M_RECURSIVE, 100.0 * i / CONTROL_GRANULARITY)
            Thread.Sleep(Duration \ CONTROL_GRANULARITY)
            i += 1
        End While

        MIL.M3dgraControl(MilGraphicList3d, GraphicLabel, MIL.M_OPACITY + MIL.M_RECURSIVE, 100.0)
    End Sub
End Module