• C#实现OBB碰撞算法


    原理在这里
    代码翻写自Simple Oriented Bounding Box OBB collision detection explaining的高赞答案(C++)

    向量类Vec3

    public class Vec3
    {
        public float X { get; set; }
        public float Y { get; set; }
        public float Z { get; set; }
        public Vec3()
        {
    
        }
    
        public Vec3(float _x,float _y,float _z)
        {
            X = _x;
            Y = _y;
            Z = _z;
        }
    
        #region 操作符
        public static Vec3 operator ^(Vec3 num1, Vec3 num2)
        {
            Vec3 v = new Vec3();
            v.X = num1.Y * num2.Z - num1.Z * num2.Y;
            v.Y = num1.Z * num2.X - num1.X * num2.Z;
            v.Z = num1.X * num2.Y - num1.Y * num2.X;
            return v;
        }
    
        public static Vec3 operator -(Vec3 num1, Vec3 num2)
        {
            Vec3 v = new Vec3();
            v.X = num1.X-num2.X;
            v.Y = num1.Y - num2.Y;
            v.Z = num1.Z - num2.Z;
            return v;
        }
    
        public static float operator *(Vec3 num1, Vec3 num2)
        {
            return num1.X* num2.X + num1.Y* num2.Y+ num1.Z* num2.Z;
        }
    
        public static Vec3 operator *(Vec3 num1, float num2)
        {
            Vec3 v = new Vec3();
            v.X = num1.X * num2;
            v.Y = num1.Y * num2;
            v.Z = num1.Z * num2;
            return v;
        }
        #endregion
    }
    

    定义OBB模型

    public class OBB
    {
        public Vec3 Pos { get; set; }
        public Vec3 AxisX { get; set; }
        public Vec3 AxisY { get; set; }
        public Vec3 AxisZ { get; set; }
        public Vec3 Half_size { get; set; }
    }
    

    OBB碰撞算法

    public class OBBCollision
    {
        /// <summary>
        /// check if there's a separating plane in between the selected axes
        /// </summary>
        /// <returns></returns>
        public static bool GetSeparatingPlane( Vec3 RPos,  Vec3 Plane,  OBB box1,  OBB box2)
        {
            return (Math.Abs(RPos* Plane) > 
                (Math.Abs((box1.AxisX* box1.Half_size.X)*Plane) +
                Math.Abs((box1.AxisY* box1.Half_size.Y)*Plane) +
                Math.Abs((box1.AxisZ* box1.Half_size.Z)*Plane) +
                Math.Abs((box2.AxisX* box2.Half_size.X)*Plane) +
                Math.Abs((box2.AxisY* box2.Half_size.Y)*Plane) +
                Math.Abs((box2.AxisZ* box2.Half_size.Z)*Plane)));
        }
    
        /// <summary>
        /// test for separating planes in all 15 axes
        /// </summary>
        /// <param name="box1"></param>
        /// <param name="box2"></param>
        /// <returns></returns>
        public static bool GetCollision(OBB  box1,  OBB box2)
        {
            Vec3 RPos;
            RPos = box2.Pos - box1.Pos;
    
            return !(GetSeparatingPlane(RPos, box1.AxisX, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisY, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisZ, box1, box2) ||
                GetSeparatingPlane(RPos, box2.AxisX, box1, box2) ||
                GetSeparatingPlane(RPos, box2.AxisY, box1, box2) ||
                GetSeparatingPlane(RPos, box2.AxisZ, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisX ^ box2.AxisX, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisX ^ box2.AxisY, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisX ^ box2.AxisZ, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisY ^ box2.AxisX, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisY ^ box2.AxisY, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisY ^ box2.AxisZ, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisZ ^ box2.AxisX, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisZ ^ box2.AxisY, box1, box2) ||
                GetSeparatingPlane(RPos, box1.AxisZ ^ box2.AxisZ, box1, box2));
        }
    }
    

    测试

    // create two obbs
    //两个OBB A和B
    OBB A, B;
    
    // set the first obb's properties
    A = new OBB();
    // set its center position
    //定义A的中心点为(0,0,0)
    A.Pos = new Vec3(0, 0, 0);
    
    // set the half size
    //定义A的1/2边长(10,1,1),即A的边长为(20,2,2)
    A.Half_size = new Vec3(10, 1, 1);
    
    // set the axes orientation
    //定义A的x,y,z轴方向
    A.AxisX = new Vec3(1, 0, 0);
    A.AxisY = new Vec3(0, 1, 0);
    A.AxisZ = new Vec3(0, 0, 1);
    
    // set the second obb's properties
    B = new OBB();
    // set its center position
    B.Pos = new Vec3(20, 0, 0);
    
    // set the half size
    B.Half_size = new Vec3(10, 1, 1);
    
    // set the axes orientation
    B.AxisX = new Vec3(1, 0, 0);
    B.AxisY = new Vec3(0, 1, 0);
    B.AxisZ = new Vec3(0, 0, 1);
    
    // run the code and get the result as a message
    if (OBBCollision.GetCollision(A, B))
    {
        //碰撞
        Console.WriteLine("Collision!!!");
    }
    else
    {
        //未碰撞
        Console.WriteLine("No collision.");
    }
    
  • 相关阅读:
    把VB.NET代码转换为C#代码的方法
    离散数学 第二章 谓词逻辑 26 前束范式
    离散数学 第二章 谓词逻辑 27 谓词演算的推理理论
    asp.net中怎样用Javascript控制RequiredFieldValidator控件什么时候启用,什么时候不启用验证?
    离散数学中的IFF标记
    BIRT Overview
    离散数学 第二章 谓词逻辑 25 谓词演算的等价式和蕴涵式
    getRemoteAddr()和getRemoteHost()的区别
    scp 不用密码
    利用spring实现javamail功能
  • 原文地址:https://www.cnblogs.com/Lulus/p/13914215.html
Copyright © 2020-2023  润新知