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,128 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.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Graphics;
using System.Windows.Media.Imaging;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SolarWind
{
    public class ContentManager
    {
        /// <summary>
        /// Gets the stream for a resource in the current assembly at a relative path
        /// </summary>
        /// <param name="relativePath">The relative path to the resource</param>
        /// <returns>The resource stream</returns>
        static public Stream GetResourceStream(string relativePath)
        {
            var assembly = System.Reflection.Assembly.GetCallingAssembly();
            var assemblyName = new System.Reflection.AssemblyName(assembly.FullName).Name;
            var stream = Application.GetResourceStream(new Uri("/" + assemblyName + ";component/" + relativePath, UriKind.Relative)).Stream;
            return stream;
        }

        /// <summary>
        /// Loads a vertex shader from the current assembly
        /// </summary>
        /// <param name="shaderPath">The relative path to the vertex shader</param>
        /// <returns>The vertex shader</returns>
        static public VertexShader LoadVertexShader(string shaderPath)
        {
            return VertexShader.FromStream(
                GraphicsDeviceManager.Current.GraphicsDevice,
                ContentManager.GetResourceStream(shaderPath));
        }

        /// <summary>
        /// Loads a pixel shader from the current assembly
        /// </summary>
        /// <param name="shaderPath">The relative path to the pixel shader</param>
        /// <returns>The pixel shader</returns>
        static public PixelShader LoadPixelShader(string shaderPath)
        {
            return PixelShader.FromStream(
                GraphicsDeviceManager.Current.GraphicsDevice,
                ContentManager.GetResourceStream(shaderPath));
        }

        /// <summary>
        /// Create a Texture2D from an image in the current assembly
        /// </summary>
        /// <param name="imagePath">The relative path to the image</param>
        /// <param name="mipmap">Whether to generate mipmap chain</param>
        /// <returns>The Texture2D representing the image</returns>
        static public Texture2D LoadTexture(string imagePath, bool mipmap = false)
        {
            if(mipmap)
                return ContentManager.LoadTextureAndMip(imagePath);

            // Load a bitmap image so that we can populate the device texture
            Stream stream = ContentManager.GetResourceStream(imagePath);
            BitmapImage bitmap = new BitmapImage();
            bitmap.SetSource(stream);

            Texture2D texture = new Texture2D(GraphicsDeviceManager.Current.GraphicsDevice,
                bitmap.PixelWidth, bitmap.PixelHeight, false, SurfaceFormat.Color);
            bitmap.CopyTo(texture);

            return texture;
        }

        /// <summary>
        /// Create a Texture2D of the specified width and height from an image in the current assembly
        /// </summary>
        /// <param name="imagePath">The relative path to the source image</param>
        /// <param name="w">The width of the final texture</param>
        /// <param name="h">The height of the final texture</param>
        /// <returns>The Texture2D of the specified size representing the image</returns>
        static public Texture2D LoadTexture(string imagePath, int w, int h)
        {
            // Load a bitmap image through writeablebitmap so that we can scale and populate the device texture            

            // Load bitmap
            Stream stream = ContentManager.GetResourceStream(imagePath);
            BitmapImage bitmap = new BitmapImage();
            bitmap.SetSource(stream);

            // Create writeable bitmap
            var wb = new WriteableBitmap(w, h);

            // Determine scale transform
            ScaleTransform t = new ScaleTransform();
            t.ScaleX = (double)w / (double)bitmap.PixelWidth;
            t.ScaleY = (double)h / (double)bitmap.PixelHeight;

            // Add the bitmap to a control, then render at scale to the writeable bitmap
            Image image = new Image();
            image.Source = bitmap;
            wb.Render(image, t);
            wb.Invalidate();

            // Copy the scaled image from the writeable bitmap to the texture
            Texture2D texture = new Texture2D(GraphicsDeviceManager.Current.GraphicsDevice, 
                wb.PixelWidth, wb.PixelHeight, false, SurfaceFormat.Color);
            wb.CopyTo(texture);

            return texture;
        }

        /// <summary>
        /// Loads an image into a texture and generates mipmaps
        /// </summary>
        /// <param name="imagePath">Relative path to the image</param>
        /// <returns>The Texture2D representing the image with mipmap chain</returns>
        static private Texture2D LoadTextureAndMip(string imagePath)
        {
            // Load bitmap
            Stream stream = ContentManager.GetResourceStream(imagePath);
            BitmapImage bitmap = new BitmapImage();
            bitmap.SetSource(stream);

            // Get dimensions        
            int w = bitmap.PixelWidth;
            int h = bitmap.PixelHeight;

            if ((w % 2 != 0 && w != 1) || (h % 2 != 0 && h != 1))
                throw new InvalidOperationException("Bitmap must be power of 2.");

            // Calculate mip levels
            int mipLevels = 1;
            int maxDimension = Math.Max(w, h);
            while (maxDimension > 1)
            {
                mipLevels++;
                maxDimension /= 2;
            }

            // Create the chain
            Texture2D texture = new Texture2D(GraphicsDeviceManager.Current.GraphicsDevice, w, h, true, SurfaceFormat.Color);

            // Put bitmap into a renderable image
            Image image = new Image();
            image.Source = bitmap;

            // Generate mip level data
            for (int level = 0; level < mipLevels; level++)
            {
                var wb = new WriteableBitmap(w, h);

                // Scale to current mip level
                ScaleTransform t = new ScaleTransform();
                t.ScaleX = (double)w / (double)bitmap.PixelWidth;
                t.ScaleY = (double)h / (double)bitmap.PixelHeight;

                // Black out the image
                for (int c = 0; c < w * h; c++)
                    wb.Pixels[c] = 0;

                // Small mip levels are rendering as white, so don't render
                if (w > 1 && h > 1)
                    wb.Render(image, t);

                // Update WB
                wb.Invalidate();

                // Grab pixel data
                wb.CopyTo(texture, level, null, 0, 0);

                // Shrink for the next level
                if (w != 1)
                    w /= 2;
                if (h != 1)
                    h /= 2;
            }

            return texture;
        }
    }
}