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); }
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; }
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); }
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); }
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); } } }
public void DebugDrawMovement(Color col) { OffsetShapeLog.DrawLine(previousPosition, position, col); OffsetShapeLog.DrawLabel(position, "Node " + id); }