zoukankan      html  css  js  c++  java
  • 稳扎稳打Silverlight(68) 5.0 XNA 之绘制 3D 图形

    [索引页]
    [源码下载]


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



    作者:webabcd


    介绍
    Silverlight 5.0 XNA

    • XNA 绘制 3D 图形的 Demo



    在线DEMO
    http://www.cnblogs.com/webabcd/archive/2012/03/05/2379862.html


    示例
    Cube.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;
    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
    [源码下载]

  • 相关阅读:
    count(1)、count(*)与count(列名)的执行区别
    解析Json字符串中的指定的值
    消息队列的好处与弊端
    17 ~ express ~ 分类的显示 ,修改 和 删除
    Express ~ 获取表单 get 和 post 提交方式传送参数的对比
    16 ~ express ~ 添加博客分类
    JS ~ Promise 对象
    JS ~ Promise.reject()
    JS ~ 返回上一步
    PHP ~ 通过程序删除图片,同时删除数据库中的图片数据 和 图片文件
  • 原文地址:https://www.cnblogs.com/webabcd/p/2417334.html
Copyright © 2011-2022 走看看