zoukankan      html  css  js  c++  java
  • 梦想成真 XNA (10) 3D 模型的碰撞检测

    [索引页]
    [源码下载] 


    梦想成真 XNA (10) - 3D 模型的碰撞检测



    作者:webabcd


    介绍
    XNA: 3D 模型的碰撞检测。通过包围球(Bounding Sphere)算法实现碰撞检测



    示例
    演示 3D 模型的碰撞检测,“上下左右”键控制 3D 模型的旋转,“LeftShift”和“LeftControl”键控制 3D 模型的前后移动(按键盘 S 键加载此 Demo)
    3D/Collision/RotationDirection.cs

    namespace XNA.Component._3D.Collision
    {
        /// <summary>
        /// 旋转方向
        /// </summary>
        public enum RotationDirection
        {
            Up,
            Down,
            Left,
            Right
        }
    }
    


    3D/Collision/TranslationDirection.cs

    namespace XNA.Component._3D.Collision
    {
        /// <summary>
        /// 位移方向
        /// </summary>
        public enum TranslationDirection
        {
            Forward,
            Backward
        }
    }
    


    3D/Collision/MyCamera.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    
    namespace XNA.Component._3D.Collision
    {
        /// <summary>
        /// 自定义摄像机类
        /// </summary>
        public class MyCamera : Microsoft.Xna.Framework.GameComponent
        {
            // View 矩阵,用于设置摄像机的位置和方向
            public Matrix View { get; protected set; }
            // Projection 矩阵,用于将 3D 物体投影到 2D 屏幕上
            public Matrix Projection { get; protected set; }
    
            public MyCamera(Game game, Vector3 pos, Vector3 target, Vector3 up)
                : base(game)
            {
                /*
                 * Matrix CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector) - 实例化视图矩阵
                 *     Vector3 cameraPosition - 摄像机的位置坐标
                 *     Vector3 cameraTarget - 摄像机镜头的朝向向量
                 *     Vector3 cameraUpVector - 摄像机机身的顶部的上方的向量
                 */
                View = Matrix.CreateLookAt(pos, target, up);
    
                /*
                 * CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) - 实例化投影矩阵
                 *     float fieldOfView - Y 轴方向上的视角弧度,一般是四分之一个 PI
                 *     float aspectRatio - 可视区的长宽比,一般就是游戏窗口的宽除以游戏窗口的高
                 *     float nearPlaneDistance - 当物体离摄像机多近时无法看清
                 *     float farPlaneDistance - 当物体离摄像机多远时无法看清
                 */
                Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.PiOver4, // 四分之一个 PI(MathHelper 里有很多实用的功能)
                    (float)Game.Window.ClientBounds.Width /
                    (float)Game.Window.ClientBounds.Height,
                    1, 
                    3000
                );
            }
    
            public override void Initialize()
            {
                base.Initialize();
            }
    
            public override void Update(GameTime gameTime)
            {
                base.Update(gameTime);
            }
        }
    }
    


    3D/Collision/MyModel.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    
    namespace XNA.Component._3D.Collision
    {
        /// <summary>
        /// 自定义 3D 模型类
        /// </summary>
        public class MyModel
        {
            // Model - 代表 3D 模型。代表 2D 对象的是 Texture2D
            private Model _model;
    
            // 旋转矩阵
            private Matrix _rotation = Matrix.Identity;
    
            // 位移矩阵
            private Matrix _translation = Matrix.Identity;
    
            // 初始矩阵
            private Matrix _world = Matrix.Identity;
    
            public MyModel(Model model, Matrix world)
            {
                _model = model;
                _world = world;
            }
    
            /// <summary>
            /// 绘制 3D 模型
            /// </summary>
            public void Draw(MyCamera camera)
            {
                /*
                 * 一个 Model 对象里有多个 ModelMesh 对象,每个 ModelMesh 对象包含了此网格的纹理、颜色等信息
                 */
                foreach (ModelMesh mesh in _model.Meshes)
                {
                    /*
                     * 一个 ModelMesh 对象里有多个用于绘制 ModelMesh 的 Effect
                     */
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        //  使用默认光源效果
                        effect.EnableDefaultLighting();
    
                        effect.Projection = camera.Projection;
                        effect.View = camera.View;
                        effect.World = GetWorld();
                    }
    
                    // 绘制 ModelMesh
                    mesh.Draw();
                }
            }
    
            /// <summary>
            /// 根据方向(上下左右)计算旋转矩阵
            /// </summary>
            public void Rotate(RotationDirection direction)
            {
                switch (direction)
                {
                    case RotationDirection.Up:
                        _rotation *= Matrix.CreateRotationX(-MathHelper.Pi / 180); // 绕 X 轴旋转的弧度
                        break;
                    case RotationDirection.Down:
                        _rotation *= Matrix.CreateRotationX(MathHelper.Pi / 180);
                        break;
                    case RotationDirection.Left:
                        _rotation *= Matrix.CreateRotationY(-MathHelper.Pi / 180); // 绕 Y 轴旋转的弧度
                        break;
                    case RotationDirection.Right:
                        _rotation *= Matrix.CreateRotationY(MathHelper.Pi / 180);
                        break;
                }
            }
    
            /// <summary>
            /// 计算位移矩阵(前进或后退)
            /// </summary>
            public void Move(TranslationDirection direction)
            {
                switch (direction)
                {
                    case TranslationDirection.Forward:
                        _translation *= Matrix.CreateTranslation(_rotation.Backward);
                        break;
                    case TranslationDirection.Backward:
                        _translation *= Matrix.CreateTranslation(_rotation.Forward);
                        break;
                }
            }
    
            /// <summary>
            /// 获取世界矩阵,即初始矩阵乘以旋转矩阵
            /// </summary>
            public Matrix GetWorld()
            {
                return _world * _rotation * _translation;
            }
            
            /// <summary>
            /// 返回自定义 3D 模型的 Model 对象
            /// </summary>
            public Model GetModel()
            {
                return _model;
            }
    
            /// <summary>
            /// 检测另一个 Model 是否与本 Model 发生了碰撞
            /// </summary>
            /// <param name="model2">另一个 3D 模型的 Model</param>
            /// <param name="world2">另一个 3D 模型的世界矩阵</param>
            /// <returns></returns>
            public bool CheckCollision(Model model2, Matrix world2)
            {
                foreach (ModelMesh mesh in _model.Meshes)
                {
                    foreach (ModelMesh mesh2 in model2.Meshes)
                    {
                        // 每个 ModelMesh 对象都有一个 BoundingSphere 属性
                        if (mesh.BoundingSphere.Transform(GetWorld()).Intersects(mesh2.BoundingSphere.Transform(world2)))
                            return true;
                    }
                }
                return false;
            }
        }
    }
    


    3D/Collision/Demo.cs

    /*
     * 本例演示:3D 模型的碰撞检测,通过包围球(Bounding Sphere)算法(XNA 已经内置了这种算法)
     * “上下左右”键控制 3D 模型的旋转,“LeftShift”和“LeftControl”键控制 3D 模型的前后移动
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    
    namespace XNA.Component._3D.Collision
    {
        public class Demo : Microsoft.Xna.Framework.DrawableGameComponent
        {
            private MyCamera _camera;
    
            // 计算机控制的模型
            private MyModel _modelSystem;
    
            // 用户控制的模型
            private MyModel _modelUser;
    
            // 是否发生了碰撞
            bool _collided = false;
    
            public Demo(Game game)
                : base(game)
            {
    
            }
    
            public override void Initialize()
            {
                // 添加摄像机组件
                _camera = new MyCamera(Game, new Vector3(0, 0, 50), Vector3.Zero, Vector3.Up);
                Game.Components.Add(_camera);
    
                base.Initialize();
            }
    
            protected override void LoadContent()
            {
                _modelSystem = new MyModel(Game.Content.Load<Model>(@"3DModel\Spaceship"), Matrix.Identity * Matrix.CreateTranslation(0, 0, -200));
                _modelUser = new MyModel(Game.Content.Load<Model>(@"3DModel\Spaceship"), Matrix.Identity * Matrix.CreateTranslation(0, -10, 0));
    
                base.LoadContent();
            }
    
            public override void Update(GameTime gameTime)
            {
                // 判断两个 3D 模型是否发生了碰撞
                _collided = _modelUser.CheckCollision(_modelSystem.GetModel(), _modelSystem.GetWorld());
                if (_collided)
                    return;
    
    
                KeyboardState keyboardState = Keyboard.GetState();
    
                // 根据用户的按键(上下左右),旋转 3D 模型
                if (keyboardState.IsKeyDown(Keys.Up))
                    _modelUser.Rotate(RotationDirection.Up);
                else if (keyboardState.IsKeyDown(Keys.Down))
                    _modelUser.Rotate(RotationDirection.Down);
                else if (keyboardState.IsKeyDown(Keys.Left))
                    _modelUser.Rotate(RotationDirection.Left);
                else if (keyboardState.IsKeyDown(Keys.Right))
                    _modelUser.Rotate(RotationDirection.Right);
    
                // 根据用户的按键移动 3D 模型:LeftShift - 向前移动;LeftControl - 向后移动
                if (keyboardState.IsKeyDown(Keys.LeftShift))
                    _modelUser.Move(TranslationDirection.Forward);
                else if (keyboardState.IsKeyDown(Keys.LeftControl))
                    _modelUser.Move(TranslationDirection.Backward);
    
                base.Update(gameTime);
            }
    
            public override void Draw(GameTime gameTime)
            {
                if (_collided)
                    Game.GraphicsDevice.Clear(Color.IndianRed);
                else
                    Game.GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // 绘制 3D 模型
                _modelSystem.Draw(_camera);
                _modelUser.Draw(_camera);
    
                base.Update(gameTime);
            }
        }
    }
    



    OK 
    [源码下载]

  • 相关阅读:
    logstash Codec
    mysql 插入前 锁表问题
    数据统一管理--企业决策分析之刚需
    数据统一管理--企业决策分析之刚需
    MySQL RR隔离 读一致性
    java HashTable
    mysl lock table read
    mysql DBI 事务控制
    Fiddler模拟http请求
    haproxy hdr_beg 配置
  • 原文地址:https://www.cnblogs.com/webabcd/p/2152891.html
Copyright © 2011-2022 走看看