# 稳扎稳打Silverlight(68) - 5.0 XNA 之绘制 3D 图形

Silverlight 5.0 XNA

• XNA 绘制 3D 图形的 Demo
using System;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 Microsoft.Xna.Framework;namespace Silverlight50.XNA{    /// <summary>    /// 描述正方体的相关信息    /// </summary>    public static class Cube    {        /// <summary>        /// 正方体的每个顶点的位置（正方体一共 8 个顶点）        /// </summary>        public static Vector3[] Corners = new Vector3[]        {            new Vector3(1f, 1f, 1f),            new Vector3(1f, -1f, 1f),            new Vector3(-1f, -1f, 1f),            new Vector3(-1f, 1f, 1f),            new Vector3(1f, 1f, -1f),            new Vector3(1f, -1f, -1f),            new Vector3(-1f, -1f, -1f),            new Vector3(-1f, 1f, -1f)        };        /// <summary>        /// 指定 Corners 里的 4 个顶点组成一个面（正方体一共 4 个面）        /// </summary>        public static int[][] Faces = new int[][]        {            new int[] { 0, 1, 2, 3 },             new int[] { 0, 3, 7, 4 },             new int[] { 0, 4, 5, 1 },             new int[] { 1, 5, 6, 2 },             new int[] { 2, 6, 7, 3 },             new int[] { 4, 7, 6, 5 }        };    }}

PolygonHelper.cs

using System;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.Animation;using System.Windows.Shapes;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;using System.Windows.Graphics;namespace Silverlight50.XNA{    /// <summary>    /// 绘制多边体的帮助类    /// </summary>    public class PolygonHelper    {        // 顶点缓冲器，可以将顶点信息以流的方式输出到图形设备中        protected VertexBuffer vb;        // 纹理        protected Texture2D texture;        /*         * BasicEffect - 基础效果，可以通过简单的属性设置来实现包含光照、纹理、变换等效果的物体的呈现         *     BasicEffect.View - 视图矩阵（View 矩阵）         *     BasicEffect.Projection - 投影矩阵（Projection 矩阵）         *     BasicEffect.VertexColorEnabled - 是否允许在此效果中启用顶点信息中的颜色数据         */        protected BasicEffect be;        protected Matrix world;        public Matrix World { get { return world; } set { world = value; } }        /// <summary>        /// 初始化多变形体        /// </summary>        /// <param name="corners">顶点位置信息数组</param>        /// <param name="faces">组成每个面的点集合数组</param>        /// <param name="color">多变形体的颜色</param>        public PolygonHelper(Vector3[] corners, int[][] faces, Color color)        {            GraphicsDevice g = GraphicsDeviceManager.Current.GraphicsDevice;            VertexPositionNormalTexture[] vertices = CreateVertices(corners, faces);            vb = new VertexBuffer(g, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);            vb.SetData(0, vertices, 0, vertices.Length, VertexPositionNormalTexture.VertexDeclaration.VertexStride);            texture = new Texture2D(g, 1, 1, false, SurfaceFormat.Color);            texture.SetData<Color>(new Color[1] { color });            be = new BasicEffect(g);            be.EnableDefaultLighting(); // 使用默认光源效果            be.LightingEnabled = true;            be.Texture = texture;            be.TextureEnabled = true;        }        /// <summary>        /// 绘制多变形体        /// </summary>        /// <param name="view">视图矩阵</param>        /// <param name="projection">投影矩阵</param>        public void Draw(Matrix view, Matrix projection)        {            GraphicsDevice g = GraphicsDeviceManager.Current.GraphicsDevice;            g.SetVertexBuffer(vb); // 绑定顶点缓冲器到图形设备中            be.World = world;            be.View = view;            be.Projection = projection;            be.CurrentTechnique.Passes[0].Apply();            g.DrawPrimitives(PrimitiveType.TriangleList, 0, vb.VertexCount / 3); // 绘制基元        }        /// <summary>        /// 返回一个 VertexPositionNormalTexture 数组        /// </summary>        /// <param name="corners">顶点位置信息数组</param>        /// <param name="faces">组成每个面的点集合数组</param>        private static VertexPositionNormalTexture[] CreateVertices(Vector3[] corners, int[][] faces)        {            int triangleCount = 0;            // 组成一个面所用的顶点数-2就是所用的三角形数            foreach (int[] face in faces)            {                triangleCount += face.Length - 2;            }            // 用到的顶点数 = 用到的三角形数 * 3            VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[triangleCount * 3];            int i = 0;            foreach (int[] face in faces)            {                // 定义每个三角形的顶点信息                for (int j = 0; j < face.Length - 2; j++)                {                    vertices[i++] = new VertexPositionNormalTexture(corners[face[0]], Vector3.Zero, Vector2.Zero);                    vertices[i++] = new VertexPositionNormalTexture(corners[face[j + 1]], Vector3.Zero, Vector2.Zero);                    vertices[i++] = new VertexPositionNormalTexture(corners[face[j + 2]], Vector3.Zero, Vector2.Zero);                }                Vector3 vectorA = vertices[i - 1].Position - vertices[i - 3].Position;                Vector3 vectorB = vertices[i - 1].Position - vertices[i - 2].Position;                Vector3 normal = Vector3.Cross(vectorB, vectorA);                for (int j = 0; j < (face.Length - 2) * 3; j++)                    vertices[i - 1 - j].Normal = normal;            }            return vertices;        }    }}

XNA/Demo.xaml

<navigation:Page x:Class="Silverlight50.XNA.Demo"            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"           mc:Ignorable="d"           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"           d:DesignWidth="640" d:DesignHeight="480"           Title="Demo Page">        <Grid x:Name="LayoutRoot" Background="White">        <DrawingSurface Name="drawingSurface" Loaded="drawingSurface_Loaded" Draw="drawingSurface_Draw" SizeChanged="drawingSurface_SizeChanged" />    </Grid>    </navigation:Page>

XNA/Demo.xaml.cs

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.Animation;using System.Windows.Shapes;using System.Windows.Navigation;using System.Windows.Graphics;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;namespace Silverlight50.XNA{    public partial class Demo : Page    {        // 可视区的长宽比，一般就是游戏窗口的宽除以游戏窗口的高        private float _aspectRatio = 1f;        // 用于绘制多边体的对象        private PolygonHelper _polygonHelper;        public Demo()        {            InitializeComponent();        }        private void drawingSurface_Loaded(object sender, System.Windows.RoutedEventArgs e)        {        }        /// <summary>        /// 检查 GPU 渲染模式是否可用        /// </summary>        private bool CheckAvailable()        {            // 检查当前是否是 GPU 渲染模式            if (GraphicsDeviceManager.Current.RenderMode == RenderMode.Hardware)                return true;            // 无法启用 GPU 渲染模式时，显示其原因            string errorMsg = "";            switch (GraphicsDeviceManager.Current.RenderModeReason)            {                case RenderModeReason.Not3DCapable:                    errorMsg = "显卡不支持 Shader Model 2.0 +";                    break;                case RenderModeReason.GPUAccelerationDisabled:                    errorMsg = "请设置 <param name=\"EnableGPUAcceleration\" value=\"true\" />";                    break;                case RenderModeReason.TemporarilyUnavailable:                    errorMsg = "显卡有问题，请重启后再试";                    break;                case RenderModeReason.SecurityBlocked:                    errorMsg = "请通过右键配置 Silverlight，在权限选项卡中允许此站点进行 3D 图形加速";                    break;            }            MessageBox.Show(errorMsg);            return false;        }        private void drawingSurface_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)        {            // DrawingSurface 就相当于游戏窗口，所以 DrawingSurface 的宽高比就是 aspectRatio            _aspectRatio = (float)(drawingSurface.ActualWidth / drawingSurface.ActualHeight);        }        private void drawingSurface_Draw(object sender, DrawEventArgs e)        {            if (_polygonHelper == null && CheckAvailable())                _polygonHelper = new PolygonHelper(Cube.Corners, Cube.Faces, new Color(1f, 0f, 0f));            GraphicsDevice g = GraphicsDeviceManager.Current.GraphicsDevice;            /*             * Matrix CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector) - 实例化视图矩阵             *     Vector3 cameraPosition - 摄像机的位置坐标             *     Vector3 cameraTarget - 摄像机镜头的朝向向量             *     Vector3 cameraUpVector - 摄像机机身的顶部的上方的向量             */            Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 8.0f), Vector3.Zero, Vector3.Up);            /*             * CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) - 实例化投影矩阵             *     float fieldOfView - Y 轴方向上的视角弧度，一般是四分之一个 PI             *     float aspectRatio - 可视区的长宽比，一般就是游戏窗口的宽除以游戏窗口的高             *     float nearPlaneDistance - 当物体离摄像机多近时无法看清             *     float farPlaneDistance - 当物体离摄像机多远时无法看清             */            Matrix projection = Matrix.CreatePerspectiveFieldOfView(0.85f, _aspectRatio, 0.01f, 1000.0f);            // 指定旋转轴            Vector3 axis = new Vector3(-0.5f, 1, -0.5f);            axis.Normalize();            // 通过四元数旋转            _polygonHelper.World = Matrix.CreateFromQuaternion(Quaternion.CreateFromAxisAngle(axis, (float)e.TotalTime.TotalSeconds * 3));            // 清除游戏窗口上的所有对象，然后以指定的颜色作为背景            g.Clear(new Color(0.8f, 0.8f, 0.8f, 1.0f));            // 绘制图像            _polygonHelper.Draw(view, projection);            // 结束本次 Draw ，并再次触发 Draw 事件            e.InvalidateSurface();        }    }}

OK
[源码下载]

posted @ 2012-03-26 08:29  webabcd  阅读(5480)  评论(12编辑  收藏  举报