Пример #1
0
        public void DrawDebug(Color col)
        {
            OffsetShapeLog.DrawLine(_nodes[0].position, _nodes[1].position, col);
            OffsetShapeLog.DrawLine(_nodes[1].position, _nodes[2].position, col);
            OffsetShapeLog.DrawLine(_nodes[2].position, _nodes[0].position, col);
            Vector3 center = Utils.ToV3((_nodes[0].position + _nodes[1].position + _nodes[2].position) / 3f);

            OffsetShapeLog.DrawDirection(center, _tangentV3, "tangent", col);
            OffsetShapeLog.DrawLabel(_centre, "\nTriangle ID " + id);
            //            Vector3 p0 = JMath.ToV3(_nodes[0].position);
            //            Vector3 p1 = JMath.ToV3(_nodes[1].position);
            //            Vector3 p2 = JMath.ToV3(_nodes[2].position);
            //
            //            Debug.DrawLine(p0, p1, col);
            //            Debug.DrawLine(p1, p2, col);
            //            Debug.DrawLine(p2, p0, col);
            ////
            //
            //            Color a = new Color(col.r, col.g, col.b, 0.25f);
            //            Vector3 v0 = p0 + Vector3.up * _nodes[0].height * 20;
            //            Vector3 v1 = p1 + Vector3.up * _nodes[1].height * 20;
            //            Vector3 v2 = p2 + Vector3.up * _nodes[2].height * 20;
            //
            //            Debug.DrawLine(positions[0], positions[1], col);
            //            Debug.DrawLine(positions[1], positions[2], col);
            //            Debug.DrawLine(positions[2], positions[0], col);
            //            GizmoLabel.Label("Node" + _nodes[0].id, v0);
            //            GizmoLabel.Label("Node" + _nodes[1].id, v1);
            //            GizmoLabel.Label("Node" + _nodes[2].id, v2);
        }
Пример #2
0
        private void CalculateUVs(SkeletonTri tri)
        {
            int baseIndex = FindBaseIndex(tri);

            OffsetShapeLog.DrawLine(tri.centre, tri.positions[baseIndex], Color.red);
            Vector2 baseUV = Vector2.zero;

            OffsetShapeLog.AddLine("============");
            OffsetShapeLog.AddLine("triangle uv node find! ", tri.id, " base node id ", tri[baseIndex].id, " tangent ", tri.tangentV3);
            OffsetShapeLog.AddLine("============");
            foreach (UVNode uvnode in _uvnodes)
            {
                OffsetShapeLog.AddLine("uvnode! ", uvnode.node.id, uvnode.tangent);
                if (uvnode.node != tri[baseIndex])
                {
                    continue;
                }
                if (!uvnode.TangentCheck(tri.tangentV3))
                {
                    continue;
                }
                baseUV = uvnode.uv;
            }
            OffsetShapeLog.AddLine("!!!!!!!!!!!!");
            OffsetShapeLog.DrawLabel(tri.centre, baseUV.ToString());

            int indexB = (baseIndex + 1) % 3;
            int indexC = (baseIndex + 2) % 3;

            Vector3 p0 = tri.positions[baseIndex];
            Vector3 p1 = tri.positions[indexB];
            Vector3 p2 = tri.positions[indexC];

            Vector3 vA = p1 - p0;
            Vector3 vB = p2 - p0;

            Vector3 right   = tri.tangentV3;
            Vector3 up      = Vector3.Cross(right, tri.normal);
            Vector3 upVA    = Vector3.Project(vA, up);
            Vector3 rightVA = Vector3.Project(vA, right);
            Vector3 upVB    = Vector3.Project(vB, up);
            Vector3 rightVB = Vector3.Project(vB, right);

            float   apexUVAX = rightVA.magnitude * Mathf.Sign(Vector3.Dot(right, rightVA));
            float   apexUVAY = upVA.magnitude * Mathf.Sign(Vector3.Dot(up, upVA));
            Vector2 apexUVA  = baseUV + new Vector2(apexUVAX, apexUVAY);
            float   apexUVBX = rightVB.magnitude * Mathf.Sign(Vector3.Dot(right, rightVB));
            float   apexUVBY = upVB.magnitude * Mathf.Sign(Vector3.Dot(up, upVB));
            Vector2 apexUVB  = baseUV + new Vector2(apexUVBX, apexUVBY);

            _uvnodes.Add(new UVNode(tri[indexB], apexUVA, right));
            _uvnodes.Add(new UVNode(tri[indexC], apexUVB, right));

            Vector2[] uvs = new Vector2[3];
            uvs[baseIndex] = baseUV;
            uvs[indexB]    = apexUVA;
            uvs[indexC]    = apexUVB;
            tri.uvs        = uvs;
        }
Пример #3
0
        public void DrawDebug(Color col)
        {
            Vector2 center = Vector2.zero;

            for (int i = 0; i < size; i++)
            {
                int ib = (i + 1) % size;
                OffsetShapeLog.DrawLine(_nodes[i].position, _nodes[ib].position, col);
                center += _nodes[i].position;
            }
            center /= size;

            OffsetShapeLog.DrawEdge(_liveEdge, Color.magenta);
            OffsetShapeLog.DrawDirection(Utils.ToV3(center), _tangent, "tangent", col);
        }
Пример #4
0
        private bool ShapeIntersection(Vector2[] points)
        {
            int pointCount = points.Length;

            for (int i = 0; i < pointCount; i++)
            {
                int ib = (i + 1) % pointCount;
                for (int j = 0; j < pointCount; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (ib == j)
                    {
                        continue;
                    }

                    int jb = (j + 1) % pointCount;

                    if (i == jb)
                    {
                        continue;
                    }
                    if (ib == jb)
                    {
                        continue;
                    }

                    Vector2 intersection;
                    if (Utils.Intersects(points[i], points[ib], points[j], points[jb], out intersection))
                    {
                        OffsetShapeLog.DrawLine(JMath.ToV3(points[i]), JMath.ToV3(points[ib]), Color.magenta);
                        OffsetShapeLog.DrawLine(JMath.ToV3(points[j]), JMath.ToV3(points[jb]), Color.yellow);
                        OffsetShapeLog.DrawLine(JMath.ToV3(intersection), JMath.ToV3(intersection) + Vector3.up * 10, Color.red);
                        return(true);
                    }
                }
            }
            return(false);
        }
Пример #5
0
        public void OffsetPoly(float direction)
        {
            if (!_init)
            {
                return;
            }

            float amount        = _shape.shrinkLength * SHINK_MULTIPLIER * Mathf.Sign(direction);
            int   liveEdgeCount = _shape.liveEdges.Count;
            int   liveNodeCount = _shape.liveNodes.Count;

            if (liveNodeCount == 0 || liveEdgeCount == 0)//nothing more to calculate
            {
                OffsetShapeLog.AddLine("Skeleton Complete");
                _complete = true;
                if (OnCompleteEvent != null)
                {
                    OnCompleteEvent();
                }
                return;
            }

            bool  earlyTermination = false;
            float directionSign    = Mathf.Sign(direction);
            float maxOffsetSign    = Mathf.Sign(maxOffset);
            float useMaxOffset     = (directionSign == maxOffsetSign) ? maxOffset : -maxOffset;

            for (int l = 0; l < liveNodeCount; l++)
            {
                Node node = _shape.liveNodes[l];
                //                if(l==0)Debug.Log(node.height+" "+amount+" "+useMaxOffset);
                if (useMaxOffset > 0)
                {
                    if (node.height + amount >= useMaxOffset)//terminate nodes that have reached a defined maximum
                    {
                        amount           = useMaxOffset - node.height;
                        earlyTermination = true;
                    }
                }
                else if (useMaxOffset < 0)
                {
                    if (node.height + amount <= useMaxOffset)//terminate nodes that have reached a defined maximum
                    {
                        amount           = useMaxOffset - node.height;
                        earlyTermination = true;
                    }
                }
            }

            float maxMovement = 0;

            liveNodeCount = _shape.liveNodes.Count;
            float[] angleNodeMovements = new float[liveNodeCount];
            for (int l = 0; l < _shape.liveNodes.Count; l++)
            {
//                Debug.Log(l);
                Node node = _shape.liveNodes[l];//TODO out of range error
                angleNodeMovements[l] = amount / Mathf.Sin(node.angle * 0.5f * Mathf.Deg2Rad);
                if (Mathf.Abs(angleNodeMovements[l]) > Mathf.Abs(maxMovement) && Mathf.Abs(angleNodeMovements[l]) > 0)
                {
                    maxMovement = angleNodeMovements[l];

                    if (node.angle > 350)
                    {
                        Edge[] edges = Utils.GetABEdge(shape, node);
                        if (edges[0] == null || edges[1] == null)
                        {
                            continue;
                        }
                        float shortestLength = (edges[0].length + edges[1].length) * 0.5f;
                        //                        Debug.Log(Mathf.Abs(shortestLength / amount));
                        maxMovement /= Mathf.Abs(shortestLength / amount);
                    }

                    //                    Debug.Log(node.id+" "+node.angle);
                }
            }

            float angleScale = amount / maxMovement;

            if (angleScale == Mathf.Infinity)
            {
                angleScale = 1;
            }
            OffsetShapeLog.AddLine(angleScale);

            for (int l = 0; l < _shape.liveNodes.Count; l++)
            {
                Node node = _shape.liveNodes[l];
                if (node.direction.magnitude < Mathf.Epsilon)//directionless node
                {
                    _shape.liveNodes.Remove(node);
                    liveNodeCount--;
                    l--;
                    continue;
                }
                node.MoveForward(angleNodeMovements[l] * angleScale, amount * angleScale);
            }

            Vector2[] edgeMovements = new Vector2[liveEdgeCount];
            if (calculateInteractions)
            {
                //Event log will collect all events and sort them for us for use once we're happy everything has been processed
                EventLog eventLog = new EventLog();
                EventLog.pointAccuracy   = pointAccuracy;
                EventLog.percentAccuracy = percentAccuracy;

                //flip events
                for (int e = 0; e < liveEdgeCount; e++)//TODO check laters
                {
                    Edge edge = _shape.liveEdges[e];
                    edge.DebugDraw(Color.cyan);
                    edge.UpdateValues();//update the edge values to reflect the new node positions
                    Node nodeA = edge.nodeA;
                    Node nodeB = edge.nodeB;
                    edgeMovements[e] = (nodeA.movement + nodeB.movement) * 0.5f;
                    Vector2 intersectionPoint;
                    if (Utils.Intersects(edge.nodeA.previousPosition, edge.nodeA.position, edge.nodeB.previousPosition, edge.nodeB.position, out intersectionPoint))
                    {
                        eventLog.AddEvent(eventLog.CreateFlipEvent(edge, intersectionPoint));
                    }
                }

                //

                //split events
                for (int n = 0; n < _shape.liveNodeCount; n++)
                {
                    Node node   = _shape.liveNodes[n];
                    int  nodeID = node.id;

                    //find connecting nodes of splitting node
                    Node nodeA = null, nodeB = null;
                    for (int e = 0; e < liveEdgeCount; e++)
                    {
                        Edge edge = _shape.liveEdges[e];
                        if (edge.Contains(node))
                        {
                            if (edge.nodeA == node)
                            {
                                nodeB = edge.nodeB;
                            }
                            if (edge.nodeB == node)
                            {
                                nodeA = edge.nodeA;
                            }
                        }
                    }


                    for (int e = 0; e < liveEdgeCount; e++)
                    {
                        Edge edge = _shape.liveEdges[e];
                        if (edge.Contains(node))
                        {
                            continue;                     //nodes can't split their own edges - carry on!
                        }
                        if (nodeA != null && edge.Contains(nodeA))
                        {
                            continue;                                       //nodes can't split adjacent edges - carry on!
                        }
                        if (nodeB != null && edge.Contains(nodeB))
                        {
                            continue;                          //nodes can't split adjacent edges - carry on!
                        }
                        if (currentSplits.ContainsKey(nodeID)) //previous splits should never intersect - ingore
                        {
                            if (currentSplits[nodeID].Contains(edge.nodeA.id))
                            {
                                continue;
                            }
                            if (currentSplits[nodeID].Contains(edge.nodeB.id))
                            {
                                continue;
                            }
                        }

                        //                        if(!isPartOfShape(node, edge)) continue;

                        Vector2 edgeMovement = edgeMovements[e];
                        Vector2 nodeMovement = node.direction * node.distance - edgeMovement; //simulate collision by moving the point by the vectors of both the point and the edge,
                        //note: collisions are simpler if only one body is moving so we're going to add the edge vector onto the point vector, making the edge remain stationary
                        Vector2 calculationPoint = node.previousPosition + nodeMovement;      //calculate the point vector by adding the edge one to it
                        Vector2 edgePosA         = edge.nodeA.previousPosition;
                        Vector2 edgePosB         = edge.nodeB.previousPosition;
//                        float intersectionalDot = Vector2.Dot(edgeMovement.normalized, node.direction.normalized);

                        //                        OffsetShapeLog.DrawLine(node.previousPosition, calculationPoint,new Color(1,0,0,0.4f));
                        //                        OffsetShapeLog.DrawLine(edgePosA, edgePosB, new Color(1, 0, 1, 0.4f));

                        Vector2 intersectionPoint;
                        float   percent    = 0;
                        bool    intersects = false;
                        //                        if (intersectionalDot < -10.75f)
                        //                        {
                        //                            Debug.DrawLine(Utils.ToV3(node.previousPosition), Utils.ToV3(calculationPoint), Color.red);
                        //                            intersects = Utils.Intersects(node.previousPosition, calculationPoint, edgePosA, edgePosB, out intersectionPoint);
                        //                            if (intersects)
                        //                            {
                        //                                Debug.DrawLine(Utils.ToV3(calculationPoint), Utils.ToV3(calculationPoint) + Vector3.up * 5, Color.magenta);
                        //                            }
                        //                            Vector2 a = node.previousPosition;
                        //                            Vector2 b = node.position;
                        //                            float movementMag = nodeMovement.magnitude;
                        //                            float intersectionMag = (intersectionPoint - a).magnitude;
                        //                            percent = intersectionMag / movementMag;
                        //                            intersectionPoint = Vector2.Lerp(a, b, percent);//translate the point to the real movement point
                        //                        }
                        //                        else
                        //                        {
                        bool dbi = false;//node.id == 14;
                        intersects       = Utils.SweepIntersects2(edge.nodeA.previousPosition, edge.nodeB.previousPosition, edge.nodeA.position, edge.nodeB.position, node.previousPosition, node.position, out intersectionPoint, out percent, 0.1f, dbi);
                        calculationPoint = node.position;
                        //                        }
                        //                        if(Utils.Intersects(node.previousPosition, calculationPoint, edgePosA, edgePosB, out intersectionPoint))
                        //                        if (Utils.SweepIntersects(edge.nodeA.previousPosition , edge.nodeB.previousPosition, edge.nodeA.position, edge.nodeB.position, node.previousPosition, node.position, out intersectionPoint, out percent))
                        if (intersects)
                        {
                            for (int be = 0; be < shape.baseEdges.Count; be++)
                            {
                                Edge baseEdge = shape.edges[be];
                                if (Utils.FastLineIntersection(node.previousPosition, node.position, baseEdge.positionA, baseEdge.positionB))
                                {
                                    intersects = false;
                                }
                                if (Utils.FastLineIntersection(edge.nodeA.position, edge.nodeB.position, baseEdge.positionA, baseEdge.positionB))
                                {
                                    intersects = false;
                                }
                            }
                        }
                        if (intersects)
                        {
                            OffsetShapeLog.AddLine("Split event detected");
                            SplitEvent splitEvent = new SplitEvent();
                            splitEvent.node = node;
                            splitEvent.edge = edge;
                            OffsetShapeLog.AddLine("node " + node.id);
                            OffsetShapeLog.AddLine("splits edge " + edge.ToString());

                            OffsetShapeLog.DrawLine(node.previousPosition, calculationPoint, Color.red);
                            OffsetShapeLog.DrawLine(edgePosA, edgePosB, Color.magenta);

                            //                            Vector2 a = node.previousPosition;
                            //                            Vector2 b = node.position;
                            //                            Vector2 x = intersectionPoint;//intersectionInfo.Point0;

                            //                            float movementMag = nodeMovement.magnitude;
                            //                            float intersectionMag = (x - a).magnitude;
                            //                            float percent = intersectionMag / movementMag;
                            OffsetShapeLog.AddLine("at percent " + percent);
                            //                            Vector2 actualIntersectionPoint = Vector2.Lerp(a, b, percent);//translate the point to the real movement point

                            float newLengthA = (intersectionPoint - edge.positionA).magnitude;
                            float newLengthB = (intersectionPoint - edge.positionB).magnitude;
                            OffsetShapeLog.AddLine("line a length ", newLengthA);
                            OffsetShapeLog.AddLine("line b length ", newLengthB);

                            SplitEvent sEvent = eventLog.CreateSplitEvent(_shape, node, edge, intersectionPoint, percent, calculationPoint);
                            if (sEvent == null)
                            {
                                continue;
                            }
                            if (newLengthA > pointAccuracy && newLengthB > pointAccuracy)
                            {
                                eventLog.AddEvent(sEvent);//can split - split point not close to either edge nodes
                            }
                            else
                            {
                                Node[] nodes = null;
                                if (newLengthA < pointAccuracy && newLengthB < pointAccuracy)
                                {
                                    nodes = new[] { node, edge.nodeA, edge.nodeB }
                                }
                                ;                                                  //point will split the edge into two edges that can't exist - collapse all nodes
                                else if (newLengthA < pointAccuracy)
                                {
                                    nodes = new[] { node, edge.nodeA }
                                }
                                ;                                      //split point close to node a - collapse split node into edge.nodea
                                else if (newLengthB < pointAccuracy)
                                {
                                    nodes = new[] { node, edge.nodeB }
                                }
                                ;                                      //split point close to node b - collapse split node into edge.nodeb
                                if (nodes != null)
                                {
                                    MergedEvent mEvent = eventLog.CreateMergeEvent(nodes, intersectionPoint, percent, calculationPoint);
                                    mEvent.Merge(sEvent);
                                    eventLog.AddEvent(mEvent);
                                }
                            }
                        }
                    }
                }

                currentSplits.Clear();
                int eventCount = eventLog.count;
                OffsetShapeLog.AddLine("event count: ", eventCount);
                if (eventCount > 0)
                {
                    float percent = eventLog.percent;
                    earlyTermination = false;
                    foreach (Node node in _shape.liveNodes)
                    {
                        node.MoveBack(percent);//move all nodes back to the position of the event
                    }
                    foreach (Edge edge in _shape.liveEdges)
                    {
                        edge.UpdateValues();//update all edges to reflect this
                    }
                    foreach (Node node in _shape.liveNodes)
                    {
                        if (_shape.formingEdges.ContainsKey(node))
                        {
                            _shape.formingEdges[node].UpdateValues();
                        }
                    }
                    for (int e = 0; e < eventCount; e++)
                    {
                        IEvent sevent = eventLog[e];
                        sevent.DrawDebug();
                        OffsetShapeLog.AddLine(string.Format("Event {0} of type {4} at {1} percent and {2},{3}", e, sevent.percent, sevent.point.x, sevent.point.y, sevent.GetType()));
                        switch (sevent.GetType().ToString())
                        {
                        case "BuildR2.ShapeOffset.FlipEvent":
                            FlipEvent fEvent = (FlipEvent)sevent;
                            OffsetShapeLog.AddLine(fEvent.ToString());
                            if (OnFlipEvent != null)
                            {
                                OnFlipEvent(fEvent);
                            }
                            //                            CollapseEdge(fEvent.edge, fEvent.point, fEvent.height);
                            break;

                        case "BuildR2.ShapeOffset.SplitEvent":
                            SplitEvent sEvent = (SplitEvent)sevent;
                            OffsetShapeLog.AddLine(sevent.ToString());
                            if (OnSplitEvent != null)
                            {
                                OnSplitEvent(sEvent);
                            }
                            //                            SplitEdge(sEvent);
                            break;

                        case "BuildR2.ShapeOffset.MergedEvent":
                            MergedEvent mEvent = (MergedEvent)sevent;
                            OffsetShapeLog.AddLine(mEvent.ToString());
                            if (OnMergedEvent != null)
                            {
                                OnMergedEvent(mEvent);
                            }
                            //                            MergeEvent(mEvent);
                            break;
                        }
                    }
                }
                else
                {
                    if (!earlyTermination)
                    {
                        float percent = 1.0f - percentAccuracy;
                        earlyTermination = false;
                        foreach (Node node in _shape.liveNodes)
                        {
                            node.MoveBack(percent);//move all nodes back to the position of the event
                        }
                        foreach (Edge edge in _shape.liveEdges)
                        {
                            edge.UpdateValues();//update all edges to reflect this
                        }
                    }
                    foreach (Node node in _shape.liveNodes)
                    {
                        if (_shape.formingEdges.ContainsKey(node))
                        {
                            _shape.formingEdges[node].UpdateValues();
                        }
                    }
                }
            }

            if (earlyTermination)
            {
                _complete = true;
                _shape.TerminateAllNodes();
                if (OnCompleteEvent != null)
                {
                    OnCompleteEvent();
                }
                return;
            }
            else
            {
                //recalculate node directions
                foreach (Node node in _shape.liveNodes)
                {
                    Utils.CalculateNodeDirAng(_shape, node);
                }
            }
        }
Пример #6
0
 public void DebugDrawMovement(Color col)
 {
     OffsetShapeLog.DrawLine(previousPosition, position, col);
     OffsetShapeLog.DrawLabel(position, "Node " + id);
 }