예제 #1
0
        public virtual bool CreateMetaball(float radius1, Vector2 center1)
        {
            var distance = Vector2.Distance(center1, Center);

            float u1;
            float u2;

            //    Check if balls are intersecting

            if (distance > (Attached ? 100 : distanceBeforeDissolve) ||
                distance <= Mathf.Abs(radius1 - ballRadius))
            {
                return(false);
            }

            if (distance < radius1 + ballRadius)
            {
                // case circles are overlapping
                u1 = Mathf.Acos((radius1 * radius1 + distance * distance - ballRadius * ballRadius) /
                                (2 * radius1 * distance));
                u2 = Mathf.Acos((ballRadius * ballRadius + distance * distance - radius1 * radius1) /
                                (2 * ballRadius * distance));
            }
            else
            {
                u1 = 0;
                u2 = 0;
            }

            //    Calculate all angles needed

            var angleBetweenCenters = AngleBetweenCenters(Center, center1);
            var maxSpread           = Mathf.Acos((radius1 - ballRadius) / distance);

            // Circle 1 (left)
            var angle1 = angleBetweenCenters + u1 + (maxSpread - u1) * v;
            var angle2 = angleBetweenCenters - (u1 + (maxSpread - u1) * v);
            // Circle 2 (right)
            var angle3 = angleBetweenCenters + Mathf.PI - u2 - (Mathf.PI - u2 - maxSpread) * v;
            var angle4 = angleBetweenCenters - (Mathf.PI - u2 - (Mathf.PI - u2 - maxSpread) * v);

            //    Calculate the four bezier points

            var point1 = GetPoint(center1, angle1, radius1);
            var point2 = GetPoint(center1, angle2, radius1);
            var point3 = GetPoint(Center, angle3, ballRadius);
            var point4 = GetPoint(Center, angle4, ballRadius);

            //    Calculate the four handles

            var totalRadius = radius1 + ballRadius;

            var d2 = Mathf.Min(v * 10, Vector2.Distance(point1, point3) / totalRadius);

            var r1 = radius1 * d2;
            var r2 = ballRadius * d2;

            var handle1 = GetPoint(point1, angle1 - Mathf.PI / 2, r1);
            var handle2 = GetPoint(point2, angle2 + Mathf.PI / 2, r1);
            var handle3 = GetPoint(point3, angle3 + Mathf.PI / 2, r2);
            var handle4 = GetPoint(point4, angle4 - Mathf.PI / 2, r2);

            //    Define the bezier segments

            if (BezierCurveUtils.CheckIBezierCurveIntersection(
                    new BezierSegment {
                P0 = point1, P1 = handle1, P2 = handle3, P3 = point3
            },
                    new BezierSegment {
                P0 = point2, P1 = handle2, P2 = handle4, P3 = point4
            }))
            {
                return(false);
            }

            var bezierSegments = new[]
            {
                new BezierPathSegment
                {
                    P0 = point1 - (Vector2)transform.parent.position,
                    P1 = handle1 - (Vector2)transform.parent.position,
                    P2 = handle3 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point3 - (Vector2)transform.parent.position,
                    P1 = point3 - (Vector2)transform.parent.position,
                    P2 = point4 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point4 - (Vector2)transform.parent.position,
                    P1 = handle4 - (Vector2)transform.parent.position,
                    P2 = handle2 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point2 - (Vector2)transform.parent.position,
                    P1 = point2 - (Vector2)transform.parent.position,
                    P2 = point1 - (Vector2)transform.parent.position
                }
            };

            //    Define the bezier contour for the shape

            var bezierContour = new BezierContour
            {
                Segments = bezierSegments,
                Closed   = false
            };

            //    Unite everything together

            GenerateBezierCurve(new[] { bezierContour });

            return(true);
        }
예제 #2
0
        public override bool CreateMetaball(float radius1, Vector2 center1)
        {
            var distance = Vector2.Distance(center1, center);

            float u1;

            var point1 = GameFieldManager.Instance.GetPointOnWall(point1Index);
            var point2 = GameFieldManager.Instance.GetPointOnWall(point2Index);

            var perpendicularLine = Vector2.Perpendicular(point1 - point2);

            var point5 = center1 + perpendicularLine.normalized * radius1;

            //    Check if balls are intersecting

            if (distance > (Attached ? 100 : distanceBeforeDissolve))
            {
                return(false);
            }

            if (distance < radius1 + ballRadius)
            {
                if (CheckSide(point2, point1, point5) > 0)
                {
                    return(false);
                }

                // case circles are overlapping
                u1 = Mathf.Acos((radius1 * radius1 + distance * distance - ballRadius * ballRadius) /
                                (2 * radius1 * distance));
            }
            else
            {
                if (CheckSide(point2, point1, point5) > 0)
                {
                    return(false);
                }

                u1 = 0;
            }

            //    Calculate all angles needed

            var angleBetweenCenters = AngleBetweenCenters(center, center1);
            var maxSpread           = Mathf.Acos((radius1 - ballRadius) / distance);

            // Circle 1 (left)
            var angle1 = angleBetweenCenters + u1 + (maxSpread - u1) * v;
            var angle2 = angleBetweenCenters - (u1 + (maxSpread - u1) * v);

            //    Calculate the four bezier points

            var point3 = GetPoint(center1, angle1, radius1);
            var point4 = GetPoint(center1, angle2, radius1);


            var tangentPoint1 = GameFieldManager.Instance.GetPointOnWall(point1Index - 1);
            var tangentPoint2 = GameFieldManager.Instance.GetPointOnWall(point2Index + 1);
            //    Calculate the four handles

            var totalRadius = radius1 + ballRadius;

            var d2 = Mathf.Min(v * 10f, Vector2.Distance(point1, point3) / totalRadius);

            if (float.IsNaN(d2))
            {
                d2 = lastD2;
            }

            lastD2 = d2;

            var r1 = radius1 * d2;
            var r2 = ballRadius * d2;

            //    Handle point 1 Right surface
            var handle1 = GetPoint(point1, AngleBetweenCenters(tangentPoint1, point1), r1);
            //    Handle point 2 Left surface
            var handle2 = GetPoint(point2, AngleBetweenCenters(tangentPoint2, point2), r1);
            //    Handle point 3 Right Ball
            var handle3 = GetPoint(point3, angle1 - Mathf.PI / 2, r2);
            //    Handle point 4 Left Ball
            var handle4 = GetPoint(point4, angle2 + Mathf.PI / 2, r2);

            //    Handle point 5 Right
            var handle5 = point5 + Vector2.Perpendicular(point5).normalized *radius1;
            //    Handle point 5 Left
            var handle6 = point5 - Vector2.Perpendicular(point5).normalized *radius1;

            //    Define the bezier segments
            var numberOfPoints = point1Index - point2Index;

            int index;

            BezierPathSegment[] bezierSegments;

            if (distance <= Mathf.Abs(radius1 - ballRadius))
            {
                bezierSegments = new BezierPathSegment[2 + numberOfPoints];
//                return true;
                bezierSegments[0] = new BezierPathSegment
                {
                    P0 = point1,
                    P1 = handle1,
                    P2 = handle5
                };
                bezierSegments[1] = new BezierPathSegment
                {
                    P0 = point5,
                    P1 = handle6,
                    P2 = handle2
                };
                index = 2;
            }
            else
            {
                if (BezierCurveUtils.CheckIBezierCurveIntersection(
                        new BezierSegment {
                    P0 = point1, P1 = handle1, P2 = handle3, P3 = point3
                },
                        new BezierSegment {
                    P0 = point2, P1 = handle2, P2 = handle4, P3 = point4
                }))
                {
                    return(false);
                }
                bezierSegments    = new BezierPathSegment[3 + numberOfPoints];
                bezierSegments[0] = new BezierPathSegment
                {
                    P0 = point1,
                    P1 = handle1,
                    P2 = handle3
                };
                bezierSegments[1] = new BezierPathSegment
                {
                    P0 = point3,
                    P1 = point3,
                    P2 = point4
                };
                bezierSegments[2] = new BezierPathSegment
                {
                    P0 = point4,
                    P1 = handle4,
                    P2 = handle2
                };
                index = 3;
            }

            for (var i = 0; i < numberOfPoints; i++)
            {
                var bezierPointToAdd = GameFieldManager.Instance.GetPointOnWall(point2Index + i);
                var nextBezierPoint  = GameFieldManager.Instance.GetPointOnWall(point2Index + i + 1);
                bezierSegments[index++] = new BezierPathSegment
                {
                    P0 = bezierPointToAdd,
                    P1 = bezierPointToAdd,
                    P2 = nextBezierPoint
                };
            }

            var bezierContour = new BezierContour
            {
                Segments = bezierSegments,
                Closed   = false
            };

            //    Draw the bezier curve

            GenerateBezierCurve(new[] { bezierContour });

            return(true);
        }