Solar Wind 3D Sample

This sample for Silverilght 5 uses the new 3D features to draw the Earth with day and night transitions, atmosphere layers, and population density overlays. It demonstrates advanced concepts like mipmaps, texture blending, multiple drawing passes, sampler states...

C# (10.4 MB)
 
 
 
 
 
4.4 Star
(8)
9,133 times
Add to favorites
9/12/2011
E-mail Twitter del.icio.us Digg Facebook
// ===================================================================================
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
//  OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
//  LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS FOR A PARTICULAR PURPOSE.
// ===================================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Graphics;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using SolarWind;
using System.Windows.Media.Imaging;

namespace SolarWind
{
    public partial class MainPage : UserControl
    {
        // Scene
        Scene scene = new Scene();
        SceneTime sceneTime = new SceneTime();

        // Earth
        double rotationSpeed = 1.0;

        // Camera
        float orbitY = 0;
        float orbitX = 0;

        // Mouse
        System.Windows.Point mouseDownPoint;
        System.Windows.Point mouseMoveDelta;
        double mouseDeltaScale;

        public MainPage()
        {
            InitializeComponent();
        }

        void DrawingSurface_Loaded(object sender, RoutedEventArgs e)
        {
            // load scene content
            scene.LoadContent();
        }
        
        void DrawingSurface_Draw(object sender, DrawEventArgs e)
        {
            // update data model from input
            ProcessInput();
            
            // scale time by the rotation speed factor
            double scaledDeltaSeconds = e.DeltaTime.TotalSeconds * rotationSpeed;
            sceneTime.DeltaTime = TimeSpan.FromSeconds(scaledDeltaSeconds);
            sceneTime.TotalTime += sceneTime.DeltaTime;

            // draw the scene
            scene.Draw(GraphicsDeviceManager.Current.GraphicsDevice, 
				sceneTime);

            // draw again next frame
            e.InvalidateSurface();
        }

        /// <summary>
        /// Update the projection when the control changes size
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DrawingSurface_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            scene.Camera.AspectRatio = (float)ds.ActualWidth / (float)ds.ActualHeight;
            mouseDeltaScale = 300.0 / Math.Min(ds.ActualWidth, ds.ActualHeight);
        }

        //
        // Per frame update
        //
        static readonly Vector3 zoomInVector = new Vector3(0.0f, 0.0f, -0.1f);
        static readonly Vector3 zoomOutVector = new Vector3(0.0f, 0.0f, 0.1f);

        void ProcessInput()
        {            
            // Zoom
            if (Keyboard.IsKeyDown(Key.Up))
            {
                if (scene.Camera.Position.Z > 0.75f)
                {
                    scene.Camera.Position += zoomInVector;
                }
            }

            if (Keyboard.IsKeyDown(Key.Down))
                scene.Camera.Position += zoomOutVector;

            // Orbit
            if (Keyboard.IsKeyDown(Key.Right))
            {
                orbitY += Microsoft.Xna.Framework.MathHelper.ToRadians(2);
            }

            if (Keyboard.IsKeyDown(Key.Left))
            {
                orbitY -= Microsoft.Xna.Framework.MathHelper.ToRadians(2);
            }

            if (Keyboard.IsKeyDown(Key.PageDown))
            {
                orbitX += MathHelper.ToRadians(2);
            }

            if (Keyboard.IsKeyDown(Key.PageUp))
            {
                orbitX -= MathHelper.ToRadians(2);
            }

            if (mouseMoveDelta.X != 0 || mouseMoveDelta.Y != 0)
            {
                orbitX += Microsoft.Xna.Framework.MathHelper.ToRadians((float)(mouseMoveDelta.Y * mouseDeltaScale));
                orbitY += Microsoft.Xna.Framework.MathHelper.ToRadians((float)(mouseMoveDelta.X * mouseDeltaScale));
            }

            orbitX = MathHelper.Clamp(orbitX, MathHelper.ToRadians(-80), MathHelper.ToRadians(80));

            scene.Camera.OrbitRotation = Microsoft.Xna.Framework.Matrix.CreateFromYawPitchRoll(orbitY, orbitX, 0);
        }

        //
        // Keyboard
        //
        void OnKeyDown(object sender, KeyEventArgs e)
        {
            Keyboard.SetKeyDown(e.Key, true);
        }

        void OnKeyUp(object sender, KeyEventArgs e)
        {
            Keyboard.SetKeyDown(e.Key, false);
        }

        //
        // Checkboxes
        //
        void OnAtmosphereChecked(object sender, EventArgs e)
        {
            scene.Earth.AtmosphereVisible = true;

            if(PopulationDensityCheck != null)
                PopulationDensityCheck.IsChecked = false;

            if(WireFrameCheck != null)
                WireFrameCheck.IsChecked = false;
        }

        void OnAtmosphereUnchecked(object sender, EventArgs e)
        {
            scene.Earth.AtmosphereVisible = false;            
        }

        void OnMagneticFieldChecked(object sender, EventArgs e)
        {
            scene.Earth.MagneticFieldVisible = true;            
        }

        void OnMagneticFieldUnchecked(object sender, EventArgs e)
        {
            scene.Earth.MagneticFieldVisible = false;            
        }

        void OnPopulationDensityChecked(object sender, EventArgs e)
        {
            scene.Earth.PopulationDensityVisible = true;

            if(AtmosphereCheck != null)
                AtmosphereCheck.IsChecked = false;

            if(WireFrameCheck != null)
                WireFrameCheck.IsChecked = false;            
        }

        void OnPopulationDensityUnchecked(object sender, EventArgs e)
        {
            scene.Earth.PopulationDensityVisible = false;            
        }

        void OnWireframeChecked(object sender, EventArgs args)
        {
            scene.Earth.ShowWireframe = true;

            if(AtmosphereCheck != null)
                AtmosphereCheck.IsChecked = false;

            if(PopulationDensityCheck != null)
                PopulationDensityCheck.IsChecked = false;            
        }

        void OnWireframeUnchecked(object sender, EventArgs args)
        {
            scene.Earth.ShowWireframe = false;            
        }

        void OnRotationSpeedChanged(object sender, RoutedEventArgs args)
        {
            Slider rotationSpeedSlider = (Slider)sender;
            rotationSpeed = (float)rotationSpeedSlider.Value;
        }

        void ShowCredits(object sender, EventArgs e)
        {
            aboutPopup.IsOpen = !aboutPopup.IsOpen;
        }

        //
        // Mouse orbit support
        //

        void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (mouseDownPoint.X == 0 && mouseDownPoint.Y == 0)
            {
                mouseMoveDelta.X = mouseMoveDelta.Y = 0;
                return;
            }

            // Calculate move delta
            System.Windows.Point current = e.GetPosition(null);
            mouseMoveDelta.X = (int)(mouseDownPoint.X - current.X);
            mouseMoveDelta.Y = (int)(mouseDownPoint.Y - current.Y);
      
            // Reset the mouse down point so the next delta we process is relative to the current mouse position
            mouseDownPoint = current;
        }

        void OnMouseDown(object sender, MouseEventArgs e)
        {
            mouseDownPoint = e.GetPosition(null);
            mouseMoveDelta.X = mouseMoveDelta.Y = 0;

            rotationSpeed = 0.0f;

            CaptureMouse();
        }

        void OnMouseUp(object sender, MouseEventArgs e)
        {
            mouseDownPoint = new System.Windows.Point();
            mouseMoveDelta.X = mouseMoveDelta.Y = 0;

            rotationSpeed = (float)RotationSpeedSlider.Value;

            ReleaseMouseCapture();
        }
    }
}