Ejemplo n.º 1
0
 // 规范地讲 round时其实只需要一个半径
 public static void Round(ref CornerInfo cornerInfo, Vector3 center, Vector3 arcPoint1, Vector3 arcPoint2)
 {
     cornerInfo.isRounded = true;
     cornerInfo.arcCenter = center;
     cornerInfo.arcPoint1 = arcPoint1;
     cornerInfo.arcPoint2 = arcPoint2;
 }
Ejemplo n.º 2
0
        private static void AnglesToArcs(CornerRounderContext context)
        {
            PrepareRadiusInfo(context);

            CornerRounderConfig config = context.config;

            RadiusStrategy strategy = config.radiusStrategy;

            if (strategy == RadiusStrategy.Never)
            {
                return;
            }

            LinkedList <CornerInfo> cornerInfo = context.cornerInfo;

            LinkedListNode <CornerInfo> current = cornerInfo.First;

            while (current != null)
            {
                if (current.Previous != null && current.Next != null)
                {
                    CornerInfo c0 = current.Previous.Value;
                    CornerInfo c1 = current.Value;
                    CornerInfo c2 = current.Next.Value;

                    Vector3 p0 = c0.vertex;
                    Vector3 p1 = c1.vertex;
                    Vector3 p2 = c2.vertex;

                    float radius = c1.radiusAdjusted;

                    if (radius != 0)
                    {
                        float halfAngle = c1.angle * 0.5f;
                        float tan       = Mathf.Tan(halfAngle);
                        float cutLen    = radius / tan;

                        // 截断点
                        Vector3 cut1 = p1 + (p0 - p1).normalized * cutLen;
                        Vector3 cut2 = p1 + (p2 - p1).normalized * cutLen;

                        // 顶点到圆心距离
                        float vertexToCenter = radius / Mathf.Sin(halfAngle);

                        // 圆心
                        Vector3    center = ((cut1 - p1) + (cut2 - p1)).normalized * vertexToCenter + p1;
                        CornerInfo value  = current.Value;
                        CornerInfo.Round(ref value, center, cut1, cut2);
                        current.Value = value;
                    }
                }

                current = current.Next;
            }
        }
Ejemplo n.º 3
0
 public static void EnsureNeighbourInfo(ref CornerInfo first, ref CornerInfo second)
 {
     //if (first.toNext.dirty || second..toPrevious.dirty)
     {
         float dist = Vector3.Distance(first.vertex, second.vertex);
         first.toNext.distance       = second.toPrevious.distance = dist;
         first.toNext.direction      = second.vertex - first.vertex;
         second.toPrevious.direction = first.vertex - second.vertex;
         first.toNext.dirty          = false;
         second.toPrevious.dirty     = false;
     }
 }
Ejemplo n.º 4
0
        private static bool RadiusAdjust(ref CornerInfo c0, ref CornerInfo c1, ref CornerInfo c2)
        {
            float radiusExpected = c1.radiusExpected;

            CornerInfo.EnsureNeighbourInfo(ref c0, ref c1);
            CornerInfo.EnsureNeighbourInfo(ref c1, ref c2);

            float angle          = c1.angle;
            float tanHalf        = Mathf.Tan(angle * 0.5f);
            float radiusAdjusted = Mathf.Min(
                radiusExpected,
                c1.toPrevious.distance * 0.5f * tanHalf,
                c1.toNext.distance * 0.5f * tanHalf);

            c1.radiusAdjusted = Mathf.Max(radiusAdjusted, 0);

            /*
             *
             * bool isEnough0 = c1.previous.distance > c0.radiusExpected + c1.radiusExpected;
             * bool isEnough2 = c1.next.distance > c2.radiusExpected + c1.radiusExpected;
             *
             *
             * // 两边的距离都充足
             * if (isEnough0 && isEnough2)
             * {
             *  c1.radiusAdjusted = c1.radiusExpected;
             *  return false;
             * }
             *
             * float radiusCorner0 = (c0.radiusAdjusted == CornerInfo.Uninitiated) ? 0 : c0.radiusAdjusted;
             * float radiusCorner2 = (c2.radiusAdjusted == CornerInfo.Uninitiated) ? 0 : c2.radiusAdjusted;
             *
             * float radiusP = Mathf.Clamp(radiusExpected, 0, c1.previous.distance - radiusCorner0);
             * float radiusN = Mathf.Clamp(radiusExpected, 0, c1.next.distance - radiusCorner2);
             *
             * float radiusAdjusted = Mathf.Min(radiusP, radiusN);
             * c1.radiusAdjusted = radiusAdjusted;
             * c0.radiusAdjusted = (c0.radiusAdjusted == CornerInfo.Uninitiated) ? radiusAdjusted : c0.radiusAdjusted;
             * c2.radiusAdjusted = (c2.radiusAdjusted == CornerInfo.Uninitiated) ? radiusAdjusted : c2.radiusAdjusted;
             *
             */

            return(false);
        }
Ejemplo n.º 5
0
        private static void RemoveAcuteAngle(CornerRounderContext context)
        {
            CornerRounderConfig config = context.config;

            if (config.acuteAngleStrategy == AcuteAngleStrategy.Keep)
            {
                return;
            }

            LinkedList <CornerInfo>     cornerInfo = context.cornerInfo;
            LinkedListNode <CornerInfo> current    = cornerInfo.First;

            float acuteAngle = Mathf.Deg2Rad * config.acuteAngleThreshold;

            // 填充corner 同时填充angle
            while (current != null)
            {
                if (current.Previous == null || current.Next == null)
                {
                    current = current.Next;
                    continue;
                }

                CornerInfo corner = current.Value;
                corner.angle = MathUtils.Angle(
                    current.Previous.Value.vertex,
                    current.Value.vertex,
                    current.Next.Value.vertex);
                current.Value = corner;

                if (corner.angle <= acuteAngle)
                {
                    var toRemove = current;
                    current = current.Previous;
                    cornerInfo.Remove(toRemove);
                    continue;
                }

                current = current.Next;
            }
        }
Ejemplo n.º 6
0
        public static void Round(ref CornerInfo cornerInfo, float radius)
        {
            float angle     = cornerInfo.angle;
            float halfAngle = angle * 0.5f;
            float tan       = Mathf.Tan(halfAngle);
            float cutLen    = radius / tan;

            /*
             *
             * // 截断点
             * Vector3 cut1 = p1 + (p0 - p1).normalized * cutLen;
             * Vector3 cut2 = p1 + (p2 - p1).normalized * cutLen;
             *
             * // 顶点到圆心距离
             * float vertexToCenter = radius / Mathf.Sin(halfAngle);
             *
             * // 圆心
             * Vector3 center = ((cut1 - p1) + (cut2 - p1)).normalized * vertexToCenter + p1;
             * CornerInfo value = current.Value;
             * CornerInfo.Round(ref value, center, cut1, cut2);
             *
             */
        }
Ejemplo n.º 7
0
        public static void ArcToPoints(CornerInfo corner, float step, IList <Vector3> points)
        {
            Vector3 cut1   = corner.arcPoint1;
            Vector3 cut2   = corner.arcPoint2;
            Vector3 center = corner.arcCenter;

            Vector3 vec1 = cut1 - center;
            Vector3 vec2 = cut2 - center;

            step = Mathf.Clamp(step, 0.001f, 1);

            float t = 0;

            while (true)
            {
                points.Add(Vector3.Slerp(vec1, vec2, t) + center);
                t += step;
                if (t > 1)
                {
                    points.Add(Vector3.Slerp(vec1, vec2, t) + center);
                    break;
                }
            }
        }
Ejemplo n.º 8
0
        private static void PrepareRadiusInfo(CornerRounderContext context)
        {
            CornerRounderConfig config = context.config;

            RadiusStrategy strategy = config.radiusStrategy;

            if (strategy == RadiusStrategy.Never)
            {
                return;
            }

            LinkedList <CornerInfo> cornerInfo = context.cornerInfo;

            LinkedListNode <CornerInfo> current = cornerInfo.First;

            while (current != null)
            {
                if (current.Previous != null && current.Next != null)
                {
                    CornerInfo info  = current.Value;
                    float      angle = MathUtils.Angle(current.Previous.Value, current.Value, current.Next.Value);
                    info.angle = angle;
                    switch (strategy)
                    {
                    case RadiusStrategy.Unified:
                        info.radiusExpected = config.radiusTarget;
                        break;

                    case RadiusStrategy.Adaptive:
                        info.radiusExpected = Mathf.Lerp(config.radiusMin, config.radiusMax, angle / 3.14f);
                        break;
                    }

                    current.Value = info;
                }

                current = current.Next;
            }

            // 重置 再循环一遍
            current = cornerInfo.First;
            while (current != null)
            {
                if (current.Previous != null && current.Next != null)
                {
                    CornerInfo c0 = current.Previous.Value;
                    CornerInfo c1 = current.Value;
                    CornerInfo c2 = current.Next.Value;
                    bool       previousIsDirty = RadiusAdjust(ref c0, ref c1, ref c2);
                    current.Previous.Value = c0;
                    current.Value          = c1;
                    current.Next.Value     = c2;

                    if (previousIsDirty)
                    {
                        current = current.Previous;
                    }
                }

                current = current.Next;
            }
        }