Пример #1
0
        /// <summary>
        /// 获取8个顶点,注意用完dispose
        /// </summary>
        /// <param name="self"></param>
        /// <param name="realPos"></param>
        /// <param name="realRot"></param>
        /// <returns></returns>
        public static ListComponent <Vector3> GetAllVertex(this OBBComponent self, Vector3 realPos, Quaternion realRot)
        {
            ListComponent <Vector3> res = ListComponent <Vector3> .Create();

            for (float i = -0.5f; i < 0.5f; i++)
            {
                for (float j = -0.5f; j < 0.5f; j++)
                {
                    for (float k = -0.5f; k < 0.5f; k++)
                    {
                        Vector3 temp = new Vector3(self.Scale.x * i, self.Scale.y * j, self.Scale.z * k);
                        temp = realPos + realRot * temp;
                        res.Add(temp);
                    }
                }
            }

            return(res);
        }
Пример #2
0
 /// <summary>
 /// 判断触发器是否在触发器移到指定位置后之相交
 /// </summary>
 /// <param name="trigger1"></param>
 /// <param name="trigger2"></param>
 /// <param name="pos1"></param>
 /// <param name="rotation1"></param>
 /// <param name="pos2"></param>
 /// <param name="rotation2"></param>
 /// <returns></returns>
 public static bool IsInTrigger(this OBBComponent trigger1, OBBComponent trigger2, Vector3 pos1,
                                Quaternion rotation1, Vector3 pos2, Quaternion rotation2)
 {
     // Log.Info("判断OBB触发");
     //第一种情况一方有一个点在对方内部即为触发
     using (var list = trigger1.GetAllVertex(pos1, rotation1))
     {
         for (int i = 0; i < list.Count; i++)
         {
             if (IsPointInTrigger(trigger2, list[i], pos2, rotation2))
             {
                 return(true);
             }
         }
     }
     using (var list = trigger2.GetAllVertex(pos2, rotation2))
     {
         for (int i = 0; i < list.Count; i++)
         {
             if (IsPointInTrigger(trigger1, list[i], pos1, rotation1))
             {
                 return(true);
             }
         }
     }
     //第二种情况,没有点在对方内部,但边和对方面相交了
     using (var list = trigger1.GetAllSide(pos1, rotation1))
     {
         for (int i = 0; i < list.Count; i++)
         {
             if (trigger2.IsRayInTrigger(list[i], pos2, rotation2))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Пример #3
0
        /// <summary>
        /// 获取12条边,注意用完dispose
        /// </summary>
        /// <param name="self"></param>
        /// <param name="realPos"></param>
        /// <param name="realRot"></param>
        /// <returns></returns>
        public static ListComponent <Ray> GetAllSide(this OBBComponent self, Vector3 realPos, Quaternion realRot)
        {
            ListComponent <Ray> res = ListComponent <Ray> .Create();

            Vector3 temp = realPos + realRot * new Vector3(self.Scale.x, self.Scale.y, self.Scale.z);
            Ray     ray  = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.left,
                Distance = self.Scale.x
            };

            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.down,
                Distance = self.Scale.y
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.back,
                Distance = self.Scale.z
            };
            res.Add(ray);

            temp = realPos + realRot * new Vector3(-self.Scale.x, -self.Scale.y, -self.Scale.z);
            ray  = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.right,
                Distance = self.Scale.x
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.up,
                Distance = self.Scale.y
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.forward,
                Distance = self.Scale.z
            };
            res.Add(ray);

            temp = realPos + realRot * new Vector3(-self.Scale.x, self.Scale.y, self.Scale.z);
            ray  = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.up,
                Distance = self.Scale.y
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.forward,
                Distance = self.Scale.z
            };
            res.Add(ray);


            temp = realPos + realRot * new Vector3(self.Scale.x, self.Scale.y, -self.Scale.z);
            ray  = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.right,
                Distance = self.Scale.x
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.up,
                Distance = self.Scale.y
            };
            res.Add(ray);

            temp = realPos + realRot * new Vector3(self.Scale.x, -self.Scale.y, self.Scale.z);
            ray  = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.right,
                Distance = self.Scale.x
            };
            res.Add(ray);
            ray = new Ray()
            {
                Start    = temp,
                Dir      = realRot * Vector3.forward,
                Distance = self.Scale.z
            };
            res.Add(ray);

            return(res);
        }
Пример #4
0
        /// <summary>
        /// 判断射线是否在触发器移到指定位置后之内
        /// </summary>
        /// <param name="self"></param>
        /// <param name="ray"></param>
        /// <param name="center"></param>
        /// <param name="rotation"></param>
        /// <returns></returns>
        public static bool IsRayInTrigger(this OBBComponent self, Ray ray, Vector3 center, Quaternion rotation, out Vector3 hit)
        {
            hit = Vector3.zero;
            //转换到模型空间
            ray = Ray.WorldToModel(ray, rotation, center);
            var xMax = self.Scale.x / 2;
            var yMax = self.Scale.y / 2;
            var zMax = self.Scale.z / 2;

            //起点在范围内
            if (-xMax <= ray.Start.x && ray.Start.x <= xMax && -yMax <= ray.Start.y && ray.Start.y <= yMax &&
                -zMax <= ray.Start.z && ray.Start.z <= zMax)
            {
                hit = rotation * ray.Start + center;
                return(true);
            }

            #region 方向向量只有一个轴有值
            else if (ray.Dir.x == 0 && ray.Dir.y == 0 && ray.Dir.z != 0)
            {
                if (ray.Start.z < 0)
                {
                    if (ray.Dir.z < 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(ray.Start.x, ray.Start.y, -zMax);
                }
                else
                {
                    if (ray.Dir.z > 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(ray.Start.x, ray.Start.y, zMax);
                }
                hit = rotation * ray.Start + center;
                if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                {
                    return(false);
                }
                return(-xMax <= ray.Start.x && ray.Start.x <= xMax &&
                       -yMax <= ray.Start.y && ray.Start.y <= yMax);
            }
            else if (ray.Dir.x == 0 && ray.Dir.y != 0 && ray.Dir.z == 0)
            {
                if (ray.Start.y < 0)
                {
                    if (ray.Dir.y < 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(ray.Start.x, -yMax, ray.Start.z);
                }
                else
                {
                    if (ray.Dir.y > 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(ray.Start.x, yMax, ray.Start.z);
                }
                hit = rotation * ray.Start + center;
                if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                {
                    return(false);
                }
                return(-xMax <= ray.Start.x && ray.Start.x <= xMax &&
                       -zMax <= ray.Start.z && ray.Start.z <= zMax);
            }
            else if (ray.Dir.x != 0 && ray.Dir.y == 0 && ray.Dir.z == 0)
            {
                if (ray.Start.x < 0)
                {
                    if (ray.Dir.x < 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(-xMax, ray.Start.y, ray.Start.z);
                }
                else
                {
                    if (ray.Dir.x > 0)
                    {
                        return(false);
                    }
                    hit = new Vector3(xMax, ray.Start.y, ray.Start.z);
                }
                hit = rotation * ray.Start + center;
                if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                {
                    return(false);
                }
                return(-yMax <= ray.Start.y && ray.Start.y <= yMax &&
                       -zMax <= ray.Start.z && ray.Start.z <= zMax);
            }
            #endregion

            #region 方向向量有两个轴有值
            else if (ray.Dir.x == 0 && ray.Dir.y != 0 && ray.Dir.z != 0)
            {
                //简化为平面直角坐标系
                if (-xMax <= ray.Start.x && ray.Start.x <= xMax)
                {
                    if (IsRayInTrigger2D(ray.Start.y, ray.Start.z, ray.Dir.y, ray.Dir.z, yMax, zMax, out var hit2d))
                    {
                        hit = new Vector3(ray.Start.x, hit2d.x, hit2d.y);
                        hit = rotation * ray.Start + center;
                        if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                        {
                            return(false);
                        }
                        return(true);
                    }
                }
                return(false);
            }
            else if (ray.Dir.x != 0 && ray.Dir.y == 0 && ray.Dir.z != 0)
            {
                //简化为平面直角坐标系
                if (-yMax <= ray.Start.y && ray.Start.y <= yMax)
                {
                    if (IsRayInTrigger2D(ray.Start.x, ray.Start.z, ray.Dir.x, ray.Dir.z, xMax, zMax, out var hit2d))
                    {
                        hit = new Vector3(hit2d.x, ray.Start.y, hit2d.y);
                        hit = rotation * ray.Start + center;
                        if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                        {
                            return(false);
                        }
                        return(true);
                    }
                }
                return(false);
            }
            else if (ray.Dir.x != 0 && ray.Dir.y != 0 && ray.Dir.z == 0)
            {
                //简化为平面直角坐标系
                if (-zMax <= ray.Start.z && ray.Start.z <= zMax)
                {
                    if (IsRayInTrigger2D(ray.Start.x, ray.Start.y, ray.Dir.x, ray.Dir.y, xMax, yMax, out var hit2d))
                    {
                        hit = new Vector3(hit2d.x, hit2d.y, ray.Start.z);
                        hit = rotation * ray.Start + center;
                        if (Vector3.Distance(hit, ray.Start) > ray.Distance)
                        {
                            return(false);
                        }
                        return(true);
                    }
                }
                return(false);
            }
            #endregion

            //正常情况
            //判断3个面的投影是否都相交
            if (!IsRayInTrigger2D(ray.Start.y, ray.Start.z, ray.Dir.y, ray.Dir.z, yMax, zMax, out var hit2d1))
            {
                return(false);
            }
            if (!IsRayInTrigger2D(ray.Start.x, ray.Start.z, ray.Dir.x, ray.Dir.z, xMax, zMax, out var hit2d2))
            {
                return(false);
            }
            if (!IsRayInTrigger2D(ray.Start.x, ray.Start.y, ray.Dir.x, ray.Dir.y, xMax, yMax, out var hit2d3))
            {
                return(false);
            }
            if (Mathf.Abs(Mathf.Abs(hit2d1.y) - zMax) < Mathf.Abs(Mathf.Abs(hit2d1.x) - yMax))
            {
                if (Mathf.Abs(Mathf.Abs(hit2d3.y) - yMax) < Mathf.Abs(Mathf.Abs(hit2d3.x) - xMax))
                {
                    hit = new Vector3(hit2d3.x, hit2d1.y, hit2d1.x);
                }
                else
                {
                    hit = new Vector3(hit2d3.x, hit2d1.y, hit2d2.y);
                }
            }
            else
            {
                if (Mathf.Abs(Mathf.Abs(hit2d2.x) - xMax) < Mathf.Abs(Mathf.Abs(hit2d2.y) - zMax))
                {
                    hit = new Vector3(hit2d2.x, hit2d1.x, hit2d2.y);
                }
                else
                {
                    hit = new Vector3(hit2d2.x, hit2d3.y, hit2d2.y);
                }
            }
            hit = rotation * hit + center;
            if (Vector3.Distance(hit, ray.Start) > ray.Distance)
            {
                return(false);
            }
            return(true);
        }
Пример #5
0
 /// <summary>
 /// 判断某个点是否在触发器移到指定位置后之内
 /// </summary>
 /// <param name="trigger"></param>
 /// <param name="position"></param>
 /// <param name="center"></param>
 /// <param name="rotation"></param>
 /// <returns></returns>
 public static bool IsPointInTrigger(this OBBComponent trigger, Vector3 position, Vector3 center, Quaternion rotation)
 {
     return(AOIHelper.IsPointInTrigger(position, center, rotation, trigger.Scale));
 }