private void InitScene()
        {
            BitmapImage mapImg = new BitmapImage(new Uri("Images/map.jpg", UriKind.Relative));

            mapSizeX = mapImg.Width;
            mapSizeZ = mapImg.Height;

            viewport            = new Viewport3D();
            viewport.MouseDown += ViewportMouseDown;

            // Add camera
            camera                   = new PerspectiveCamera();
            camera.FieldOfView       = 60.0;
            camera.NearPlaneDistance = 1.0;
            camera.FarPlaneDistance  = 10000.0;
            camera.LookDirection     = new Vector3D(0, -1, 0);
            camera.UpDirection       = new Vector3D(0, 0, -1);
            camera.Position          = new Point3D(0, 2000, 0);

            viewport.Camera = camera;

            // Create map quad
            Geometry3D      quadMesh     = MeshFactory.Quad(new Point3D(), new Vector(mapImg.Width, mapImg.Height));
            Material        quadMaterial = new DiffuseMaterial(new ImageBrush(mapImg));
            GeometryModel3D quad         = new GeometryModel3D(quadMesh, quadMaterial);

            // Create directional & ambient light
            DirectionalLight dirLight = new DirectionalLight();

            dirLight.Color     = Colors.White;
            dirLight.Direction = new Vector3D(0, -1, 0);

            AmbientLight ambientLight = new AmbientLight();

            ambientLight.Color = Color.FromRgb(62, 73, 89);

            modelGroup = new Model3DGroup();
            modelGroup.Children.Add(dirLight);
            modelGroup.Children.Add(ambientLight);
            modelGroup.Children.Add(quad);

            ModelVisual3D modelVisual = new ModelVisual3D();

            modelVisual.Content = modelGroup;

            viewport.Children.Add(modelVisual);
            Content = viewport;

            lightRedMat  = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(255, 130, 130)));
            redMat       = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(255, 80, 80)));
            brightRedMat = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(240, 0, 0)));
            lineMat      = new DiffuseMaterial(Brushes.Black);
        }
        private void DrawNodes()
        {
            foreach (PowerNode node in nodeMap.Nodes)
            {
                double xNormalized = MathUtility.InverseLerp(SW_LON, NE_LON, node.X);
                double yNormalized = MathUtility.InverseLerp(SW_LAT, NE_LAT, node.Y);

                double xPos = MathUtility.Lerp(-mapSizeX / 2, mapSizeX / 2, xNormalized);
                double zPos = MathUtility.Lerp(-mapSizeZ / 2, mapSizeZ / 2, yNormalized);

                double     cubeHeight = CUBE_SIZE / 2 + 0.1;
                bool       intersectsWithNode;
                Geometry3D cubeMesh;

                // Check AABB intersections
                do
                {
                    cubeMesh           = MeshFactory.Cube(new Point3D(xPos, cubeHeight, -zPos), new Vector3D(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
                    intersectsWithNode = false;

                    foreach (Model3D cubeModel in modelGroup.Children)
                    {
                        if (cubeMesh.Bounds.IntersectsWith(cubeModel.Bounds))
                        {
                            cubeHeight        += CUBE_SIZE + 0.1;
                            intersectsWithNode = true;
                            break;
                        }
                    }
                } while (intersectsWithNode);

                Material material;
                if (node.ConnectionCount <= 3)
                {
                    material = lightRedMat;
                }
                else if (node.ConnectionCount <= 5)
                {
                    material = redMat;
                }
                else
                {
                    material = brightRedMat;
                }

                GeometryModel3D cube = new GeometryModel3D(cubeMesh, material);
                nodeModels.Add(cube, node);

                modelGroup.Children.Add(cube);
            }
        }