/// <summary> /// 所有共用vertex的三角形 /// </summary> private static void GetAllNodesByVert(ref List <CheckNodeInfo> nodeInfos, NavMeshNode startNode, Int3 vertex) { if (nodeInfos == null) { nodeInfos = new List <CheckNodeInfo>(); } for (int i = 0; i < nodeInfos.Count; i++) { CheckNodeInfo info2 = nodeInfos[i]; if (info2.node == startNode) { return; } } int num2 = -1; if (startNode.v0 == vertex) { num2 = 0; } else if (startNode.v1 == vertex) { num2 = 1; } else if (startNode.v2 == vertex) { num2 = 2; } else { return; } CheckNodeInfo item = new CheckNodeInfo(); item.vi = num2; item.node = startNode; item.v0 = startNode.GetVertex(num2 % 3); item.v1 = startNode.GetVertex((num2 + 1) % 3); item.v2 = startNode.GetVertex((num2 + 2) % 3); nodeInfos.Add(item); if (startNode.connections != null) { for (int j = 0; j < startNode.connections.Length; j++) { NavMeshNode node = startNode.graph.GetNode(startNode.connections[j]) as NavMeshNode; if (node != null) { GetAllNodesByVert(ref nodeInfos, node, vertex); } } } }
/// <summary> /// /// </summary> /// <param name="node"></param> /// <param name="startEdge"></param> /// <param name="srcLoc"></param> /// <param name="destLoc"></param> /// <param name="state"></param> /// <param name="result">实际可移动到的点</param> private static void MoveFromNode(NavMeshNode node, int startEdge, Int3 srcLoc, Int3 destLoc, out Int3 result) { result = srcLoc; while (node != null) { int num; int num10; int count = 2; // 当前在顶点上 if (node.IsVertex(srcLoc, out num)) { // 找到所有包含srcLoc这顶点的三角形 Int3 vertex = node.GetVertex(num); List <CheckNodeInfo> nodeInfos = null; GetAllNodesByVert(ref nodeInfos, node, vertex); // 找到其中将要穿过的三角形 NavMeshNode node2 = null; int vi = -1; for (int i = 0; i < nodeInfos.Count; i++) { CheckNodeInfo info = nodeInfos[i]; if ((!checkedNodes.Contains(info.node) && !VectorMath.RightXZ(info.v0, info.v2, destLoc)) && VectorMath.RightOrColinearXZ(info.v0, info.v1, destLoc)) { node2 = info.node; vi = info.vi; break; } } if (node2 != null) { node = node2; // 将要穿过的边 startEdge = (vi + 1) % 3; count = 1; } else { int num6 = -1; VFactor factor3 = new VFactor(); factor3.nom = -2L; factor3.den = 1L; VFactor factor = factor3; for (int j = 0; j < nodeInfos.Count; j++) { CheckNodeInfo info2 = nodeInfos[j]; if (!checkedNodes.Contains(info2.node)) { int num8; VFactor factor2 = info2.GetCosineAngle(destLoc, out num8); if (factor2 > factor) { factor = factor2; num6 = num8; node2 = info2.node; } } } if (node2 != null) { MoveAlongEdge(node2, num6, srcLoc, destLoc, out result, true); break; } } } // 将要穿过的边 int edge = -1; if (startEdge == -1) { edge = node.EdgeIntersect(srcLoc, destLoc); } else { edge = node.EdgeIntersect(srcLoc, destLoc, startEdge, count); } // 不会穿越边 if (edge == -1) { if (node.ContainsPoint(destLoc)) { // 三角形内移动 result = destLoc; if (MoveAxisY) { CalculateY(ref result, node); } } else { // 沿边所在直线移动 edge = node.GetColinearEdge(srcLoc, destLoc); if (edge != -1) { MoveAlongEdge(node, edge, srcLoc, destLoc, out result, true); } } break; } // 会穿过边,则看相邻三角形 NavMeshNode neighborByEdge = node.GetNeighborByEdge(edge, out num10); if (neighborByEdge != null) { node = neighborByEdge; startEdge = num10 + 1; count = 2; } else { MoveAlongEdge(node, edge, srcLoc, destLoc, out result, true); break; } } }
/// <summary> /// /// </summary> /// <param name="node">所在node</param> /// <param name="edge">所沿着的边</param> /// <param name="srcLoc">from</param> /// <param name="destLoc">to</param> /// <param name="result">实际可到达的点</param> private static void MoveAlongEdge(NavMeshNode node, int edge, Int3 srcLoc, Int3 destLoc, out Int3 result, bool checkAnotherEdge = true) { bool flag; //DebugHelper.Assert((edge >= 0) && (edge <= 2)); Int3 vertex = node.GetVertex(edge); Int3 num2 = node.GetVertex((edge + 1) % 3); Int3 a = destLoc - srcLoc; a.y = 0; Int3 lhs = num2 - vertex; lhs.y = 0; lhs.NormalizeTo(1000); int num5 = 0; // 点乘移动向量和边向量 num5 = (lhs.x * a.x) + (lhs.z * a.z); // 移动向量和边向量的交点 Int3 rhs = Polygon.IntersectionPoint(ref vertex, ref num2, ref srcLoc, ref destLoc, out flag); // 不相交? if (!flag) { // 边和from to存在不共线,则不能移动 if (!VectorMath.IsColinearXZ(vertex, num2, srcLoc) || !VectorMath.IsColinearXZ(vertex, num2, destLoc)) { result = srcLoc; return; } // 计算本三角形内可移动到的点 rhs // 移动向量和边向量 同向 if (num5 >= 0) { int num8 = (lhs.x * (num2.x - vertex.x)) + (lhs.z * (num2.z - vertex.z)); int num9 = (lhs.x * (destLoc.x - vertex.x)) + (lhs.z * (destLoc.z - vertex.z)); rhs = (num8 <= num9) ? num2 : destLoc; //DebugHelper.Assert((num8 >= 0) && (num9 >= 0)); } else { // 移动向量和边向量 异向 int num10 = (-lhs.x * (vertex.x - num2.x)) - (lhs.z * (vertex.z - num2.z)); int num11 = (-lhs.x * (destLoc.x - num2.x)) - (lhs.z * (destLoc.z - num2.z)); rhs = (Mathf.Abs(num10) <= Mathf.Abs(num11)) ? vertex : destLoc; //DebugHelper.Assert((num10 >= 0) && (num11 >= 0)); } } // 计算交点到边的顶点的距离1000倍 int num12 = -IntMath.Sqrt(vertex.XZSqrMagnitude(rhs) * 0xf4240L); // 一百万 int num13 = IntMath.Sqrt(num2.XZSqrMagnitude(rhs) * 0xf4240L); // num5是在边上的投影 if ((num5 >= num12) && (num5 <= num13)) { result = IntMath.Divide(lhs, (long)num5, 0xf4240L) + rhs; if (!node.ContainsPoint(result)) { int num16; int num17; int num18; int num19; Vector3 vector = (Vector3)(num2 - vertex); vector.y = 0f; vector.Normalize(); Int3 num14 = num2 - vertex; num14.y = 0; num14 *= 10000; long magnitude = num14.magnitude; VFactor factor = new VFactor(); factor.nom = num5; factor.den = magnitude * 1000L; getMinMax(out num16, out num18, (long)num14.x, ref factor); getMinMax(out num17, out num19, (long)num14.z, ref factor); if (!MakePointInTriangle(ref result, node, num16, num18, num17, num19, srcLoc) && !MakePointInTriangle(ref result, node, num16 - 4, num18 + 4, num17 - 4, num19 + 4, srcLoc)) { result = srcLoc; } } if (MoveAxisY) { CalculateY(ref result, node); } } else { int num20; int num21; Int3 num22; int num24; if (num5 < num12) { num20 = num5 - num12; num21 = (edge + 2) % 3; num22 = vertex; } else { num20 = num5 - num13; num21 = (edge + 1) % 3; num22 = num2; } Int3 num23 = (Int3)((lhs * num20) / 1000000f); NavMeshNode neighborByEdge = node.GetNeighborByEdge(num21, out num24); if (neighborByEdge != null) { checkedNodes.Add(node); MoveFromNode(neighborByEdge, num24, num22, num23 + num22, out result); } else { if (checkAnotherEdge) { Int3 num27 = node.GetVertex((edge + 2) % 3) - num22; if (Int3.Dot(num27.NormalizeTo(1000), num23) > 0) { checkedNodes.Add(node); MoveAlongEdge(node, num21, num22, num23 + num22, out result, false); return; } } result = num22; } } }