示例#1
0
    //returns a list of the segments of the path and then the segment on the other shape which ended the path, also ends when it reaches the start
    public Tuple <List <CSGsegment>, CSGsegment> ridePathUntilIntersection(CSGshape shapeToIntersect, List <CSGsegment> externalSegments, bool isMovingForward, CSGsegment first, bool isStart = false)
    {
        var retr     = new Tuple <List <CSGsegment>, CSGsegment>();
        var curr     = this;
        var retrList = new List <CSGsegment>();

        retr.first  = retrList;
        retr.second = null;
        while (curr != first || isStart)
        {
            //Debug.Log(curr.Letter);
            isStart = false;
            retrList.Add(curr);
            if (externalSegments.Contains(curr))//slow linear search
            {
                externalSegments.Remove(curr);
            }
            var intersection = curr.getClosestIntersectingSegment(shapeToIntersect, isMovingForward);
            if (intersection == null)
            {
                curr = curr.next(isMovingForward);
            }
            else
            {
                retr.second = intersection;
                return(retr);
            }
        }
        return(retr);
    }
示例#2
0
    //returns null for no intersection
    public CSGsegment getClosestIntersectingSegment(CSGshape shape, bool isMovingForward)
    {
        var candidates = new List <CSGsegment>();

        foreach (var i in shape.segments)
        {
            if (i.doesIntersect(this))
            {
                candidates.Add(i);
            }
        }
        float      currBestDist = float.PositiveInfinity;
        CSGsegment currBest     = null;

        foreach (var i in candidates)
        {
            var point = i.intersectionPoint(this);
            var dist  = (this.getPoint(isMovingForward) - point).magnitude;
            if (dist < currBestDist)
            {
                currBestDist = dist;
                currBest     = i;
            }
        }
        return(currBest);
    }
示例#3
0
    Vector2[] collisionHullToVector2(CSGshape h)
    {
        var foo = new Vector2[h.segments.Count];
        int c   = 0;

        foreach (var i in h.segments)
        {
            foo[c] = i.start;
            c++;
        }
        return(foo);
    }
示例#4
0
    //external segments must ALWAYS be in order
    private List <CSGsegment> getExternalSegments(CSGshape other)
    {
        var retr = new List <CSGsegment>();

        foreach (var i in this.segments)
        {
            if (!other.isPointInside(i.start))
            {
                retr.Add(i);
            }
        }
        return(retr);
    }
示例#5
0
    // Update is called once per frame
    void Update()
    {
        foreach (var i in segments)
        {
            Debug.DrawLine(i.start, i.end);
        }
        if (Input.GetMouseButtonDown(0))
        {
            var item = Instantiate(redX);
            objs.Add(item);
            Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            item.transform.position = pos;
            baseShape.Add(pos);
        }
        if (Input.GetMouseButtonDown(1))
        {
            var item = Instantiate(blueX);
            objs.Add(item);
            Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            item.transform.position = pos;
            notShape.Add(pos);
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            bool none;
            var  retr = CSGshape.not(new CSGshape(baseShape), new CSGshape(notShape), false, out none);
            foreach (var i in objs)
            {
                Destroy(i);
            }
            baseShape.Clear();
            notShape.Clear();
            segments.Clear();
            foreach (var j in retr)
            {
                foreach (var i in j.externalHull.segments)
                {
                    var item = Instantiate(redX);
                    objs.Add(item);
                    item.transform.position = i.start;
                    baseShape.Add(i.start);
                    segments.Add(i);
                    //Debug.DrawLine(i.start,i.end);

                    /*item = Instantiate(redX);
                     * item.transform.position = i.end;
                     * baseShape.Add(i.end);*/
                }
            }
        }
    }
示例#6
0
    private void ShapeOp(CSGshape other, bool isNot)
    {
        List <CollisionHull> hulls = new List <CollisionHull>();
        bool isShapeUsedUp         = false;

        foreach (var coll in colliders)
        {
            if (!isShapeUsedUp || isNot == false)
            {
                var result = CSGshape.not(coll.externalHull, other, isNot, out isShapeUsedUp, coll.holes);
                hulls.AddRange(result);
            }
        }
        if (!isShapeUsedUp && !isNot)
        {
            var foo = new CollisionHull();
            foo.externalHull = other;
            hulls.Add(foo);
        }
        colliders = hulls;
    }
示例#7
0
 // Update is called once per frame
 void Update()
 {
     Draw();
     if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
     {
         try
         {
             doNotRender.Clear();
             Vector2                 center     = Camera.main.ScreenToWorldPoint(Input.mousePosition);
             List <Vector2[]>        newShapes  = new List <Vector2[]>();
             List <List <CSGshape> > shapeHoles = new List <List <CSGshape> >();
             List <Vector2>          square     = getCircle(center, 1, 20);
             //List<CollisionHull> shapesSoFar = new List<CollisionHull>();//#garbagelife
             //Debug.Log("shapesofarleng:" + shapesSoFar.Count);
             bool isShapesUsedUp = false;                //prevents applying positive and to multiple
             for (int path = 0; path < baseCollider.pathCount; path++)
             {
                 if (!isShapesUsedUp || Input.GetMouseButtonDown(0))
                 {
                     var b = new CSGshape(new List <Vector2>(baseCollider.GetPath(path)));
                     //List<Vector2> square = getCircle();//getSquare(center);
                     {
                         var retr = CSGshape.not(b, new CSGshape(square), Input.GetMouseButtonDown(0), out isShapesUsedUp, null);
                         //retr = CSGshape.prune(shapesSoFar,retr);
                         //shapesSoFar.AddRange(retr);
                         foreach (var returnVal in retr)
                         {
                             newShapes.Add(collisionHullToVector2(returnVal.externalHull));
                             doNotRender.Add(false);
                             if (returnVal.holes != null)
                             {
                                 newShapes.AddRange(returnVal.holes.Select(a => collisionHullToVector2(a)));
                                 for (var i = 0; i < returnVal.holes.Count; i++)
                                 {
                                     doNotRender.Add(true);
                                 }
                             }
                             //shapeHoles.Add(returnVal.holes);
                         }
                     }
                 }
                 else
                 {
                     newShapes.Add(baseCollider.GetPath(path));
                     doNotRender.Add(false);
                 }
             }
             if (!isShapesUsedUp && Input.GetMouseButtonDown(1))
             {
                 newShapes.Add(square.ToArray());
                 doNotRender.Add(false);
             }
             if (newShapes.Count != doNotRender.Count)
             {
                 throw new Exception("F**K");
             }
             baseCollider.pathCount = newShapes.Count();
             int counter = 0;
             foreach (var i in newShapes)
             {
                 baseCollider.SetPath(counter, i);
                 counter++;
             }
         }
         catch (NotImplementedException e)//(Exception e)
         {
             //Debug.Log("EXCEPTION:" + e.ToString());
         }
     }
 }
示例#8
0
    //collision hull.hull or whatever is null if nothing is left
    public static List <CollisionHull> not(CSGshape shape, CSGshape other, bool isNot, out bool usedFlag, List <CSGshape> holes = null)
    {
        //start with a point on me thats not in the other shape
        //List<CSGshape> retr = new List<CSGshape>();
        List <CollisionHull> hulls            = new List <CollisionHull>();
        List <CSGsegment>    externalSegments = shape.getExternalSegments(other);

        usedFlag = !isNot;
        if (other.segments.TrueForAll(i => !shape.doesIntersect(i)) && !isNot)
        {
            var foo = new CollisionHull();
            foo.externalHull = shape;
            foo.holes        = holes;

            /*var bar = new CollisionHull();
             * bar.externalHull = other;*/
            hulls.Add(foo);
            //hulls.Add(bar);
            usedFlag = false;
            return(hulls);
        }
        else if (externalSegments.Count == 0)        //other completely surrounds this
        {
            if (isNot)
            {
                return(hulls);
            }
            else
            {
                hulls.Add(new CollisionHull());
                hulls[0].externalHull = other;
                return(hulls);
            }
        }
        else if (externalSegments.Count == shape.segments.Count && other.segments.TrueForAll(a => shape.isPointInside(a.start)))        //this completely surrounds other
        {
            if (isNot)
            {
                var foo = new List <CSGshape>();
                foo.Add(other);
                if (holes != null)
                {
                    foo.AddRange(holes);
                }
                foo = andAll(foo);
                var hull = new CollisionHull();
                hull.externalHull = shape;
                hull.holes.Add(other);
                hulls.Add(hull);
            }
            else
            {
                hulls.Add(new CollisionHull());
                hulls[0].externalHull = shape;
            }
            return(hulls);
            //throw new NotImplementedException();

            /*float closestDist = float.PositiveInfinity;
             * CSGsegment closestItem = null;
             * CSGsegment closestInnerItem = null;
             * if (!other.isClockwise())
             * {
             * other.antiRotate();
             * }
             * foreach (var i in shape.segments)
             * {
             * foreach (var j in other.segments)
             * {
             * var dist = (i.end - j.start).magnitude;
             * if (dist < closestDist)
             * {
             * closestItem = i;
             * closestInnerItem = j;
             * closestDist = dist;
             * }
             * }
             * }
             * var enter = new CSGsegment(closestItem.end, closestInnerItem.start);
             * var exit = new CSGsegment(closestInnerItem.start, closestItem.end);
             * var oldnext = closestItem.endSegment;
             * var oldinnernext = closestInnerItem.startSegment;
             * oldnext.startSegment = exit;
             * closestItem.endSegment = enter;
             * enter.endSegment = closestInnerItem;
             * exit.endSegment = oldnext;
             * oldinnernext.endSegment = exit;
             * enter.startSegment = closestItem;
             * closestInnerItem.startSegment = enter;
             * exit.startSegment = oldinnernext;
             *
             * CSGsegment curr = enter;
             * List<Vector2> newPoints = new List<Vector2>();
             * do
             * {
             * newPoints.Add(curr.getPoint(true));
             * curr = curr.next(true);
             * } while (curr!=enter);
             * retr.Add(new CSGshape(newPoints));
             * return retr;*/
        }
        else
        {
            while (externalSegments.Count > 0)
            {
                List <Vector2> newPoints       = new List <Vector2>();
                bool           isMovingForward = true;
                var            first           = externalSegments[0];//better to remove at start or end? look this up
                var            curr            = first;
                var            isStart         = true;
                externalSegments.RemoveAt(0);
                int counter = 0;
                while (true)
                {
                    if (counter > 100)                    //remove this?
                    {
                        throw new Exception("Linerider exceeded 100 steps");
                        //break;
                    }
                    counter++;
                    var partialPath = curr.ridePathUntilIntersection(other, externalSegments, isMovingForward, first, isStart);
                    foreach (var i in partialPath.first)
                    {
                        newPoints.Add(i.getPoint(isMovingForward));
                    }
                    if (partialPath.second == null)
                    {
                        break;
                    }
                    var intersectionPoint = partialPath.first[partialPath.first.Count - 1].intersectionPoint(partialPath.second);
                    isMovingForward = shape.getDirection(partialPath.second, isNot, intersectionPoint);                    //toggle this to add instead of subtract
                    isStart         = false;
                    //now we must enter this shape, so test the two points
                    var exitPoint     = partialPath.second.getPoint(!isMovingForward);                //!isMovingForward so we get end instead of start
                    var entrancePoint = intersectionPoint + smallDelta * (exitPoint - intersectionPoint).normalized;
                    if (isMovingForward)
                    {
                        curr = new CSGsegment(entrancePoint, exitPoint);
                    }
                    else
                    {
                        curr = new CSGsegment(exitPoint, entrancePoint);
                    }
                    curr.startSegment = partialPath.second.startSegment;
                    curr.endSegment   = partialPath.second.endSegment;
                    ////////////////////////now inside this
                    partialPath = curr.ridePathUntilIntersection(shape, externalSegments, isMovingForward, null);                    //null because it can't end inside
                    foreach (var i in partialPath.first)
                    {
                        newPoints.Add(i.getPoint(isMovingForward));
                    }
                    intersectionPoint = partialPath.first[partialPath.first.Count - 1].intersectionPoint(partialPath.second);
                    isMovingForward   = other.getDirection(partialPath.second, false, intersectionPoint);
                    //now we gotta leave this shape
                    exitPoint     = partialPath.second.getPoint(!isMovingForward);                //!isMovingForward so we get end instead of start
                    entrancePoint = intersectionPoint + smallDelta * (exitPoint - intersectionPoint).normalized;
                    if (isMovingForward)
                    {
                        curr = new CSGsegment(entrancePoint, exitPoint);
                    }
                    else
                    {
                        curr = new CSGsegment(exitPoint, entrancePoint);
                    }
                    curr.startSegment = partialPath.second.startSegment;
                    curr.endSegment   = partialPath.second.endSegment;
                }
                var foo      = new CollisionHull();
                var newShape = new CSGshape(newPoints);
                foo.externalHull = newShape;
                hulls.Add(foo);
            }
            return(hulls);
        }
    }
示例#9
0
 public void AddShape(CSGshape other)
 {
     ShapeOp(other, false);
 }
示例#10
0
 public void RemoveShape(CSGshape other)
 {
     ShapeOp(other, true);
 }