public int SharedEdge(NavmeshTriangle other) { int a, b; GetPortal(other, out a, out b); return(a); }
void Buildsegments() { segments.Clear(); for (int i = 0; i < ObsTriangles.Length; i++) { NavmeshTriangle node = ObsTriangles [i]; for (int j = 0; j < node.shared.Count; ++j) { if (node.shared[j] == false) { segments.Add(node.GetSegment(j)); } } ShowProgress("构建单边列表", (float)i / (ObsTriangles.Length)); } DefineIDforSegments(segments); }
public bool isSharedEdge(NavmeshTriangle other, out int idx) { for (int i = 0; i < 3; ++i) { KInt2 p1 = GetXZVertex(i); KInt2 p2 = GetXZVertex((i + 1) % 3); for (int k = 0; k < 3; ++k) { KInt2 p3 = other.GetXZVertex(k); KInt2 p4 = other.GetXZVertex((k + 1) % 3); if ((p1 == p3 && p2 == p4) || (p1 == p4 && p2 == p3)) { idx = i; return(true); } } } idx = -1; return(false); }
public void GetPortal(NavmeshTriangle other, out int aIndex, out int bIndex) { int first = -1; int second = -1; for (int a = 0; a < 3; a++) { int va = GetVertexIndex(a); for (int b = 0; b < 3; b++) { if (va == other.GetVertexIndex((b + 1) % 3) && GetVertexIndex((a + 1) % 3) == other.GetVertexIndex(b)) { first = a; second = b; a = 3; break; } } } aIndex = first; bIndex = second; }
bool Mesh2Obstacle() { if (mesh.vertexCount == 0 || mesh.triangles.Length == 0) { LogMgr.LogError("Convert Error"); return(false); } BeginSample("Mesh2Obstacle"); //old Vector3[] vectorVertices = mesh.vertices; int[] triangles = mesh.triangles; //create new KInt3[] vertices = new KInt3[mesh.vertexCount]; Dictionary <KInt3, int> hashedVerts = new Dictionary <KInt3, int> (mesh.vertexCount); int[] newVertices = new int[vertices.Length]; //从模型坐标系转换到世界坐标系 for (int i = 0; i < vertices.Length; i++) { vertices [i] = (KInt3)MeshMatrix.MultiplyPoint3x4(vectorVertices [i]); ShowProgress("从模型坐标系转换到世界坐标系", (float)i / vertices.Length); } //旧顶点在新顶点中的索引 int newVerIdx = 0; for (int i = 0; i < vertices.Length; i++) { //当hash 顶点集合不包含这个顶点的时候,把这个点加入进去,去除共点 if (!hashedVerts.ContainsKey(vertices [i])) { newVertices [newVerIdx] = i; hashedVerts.Add(vertices [i], newVerIdx); newVerIdx++; } ShowProgress("构建映射", (float)i / vertices.Length); } for (int x = 0; x < triangles.Length; x++) { //把老的顶点索引映射到新的顶点索引上 KInt3 vertex = vertices [triangles [x]]; triangles [x] = hashedVerts [vertex]; ShowProgress("三角映射", (float)x / triangles.Length); } KInt3[] totalIntVertices = vertices; vertices = new KInt3[newVerIdx]; for (int i = 0; i < newVerIdx; i++) { vertices [i] = totalIntVertices [newVertices [i]]; ShowProgress("顶点索引转换", (float)i / newVerIdx); } //顶点创建结束 #if UNITY_EDITOR this.ObsVertices = vertices; #endif if (triangles.Length % 3 != 0) { LogMgr.LogErrorFormat("triangle lenth error :{0}", triangles.Length); } //创建三角 ObsTriangles = new NavmeshTriangle[triangles.Length / 3]; for (int i = 0; i < ObsTriangles.Length; i++) { NavmeshTriangle tri = new NavmeshTriangle(); ObsTriangles [i] = tri; #if UNITY_EDITOR //init tri.uid = i; #endif // tri.v0 = triangles [i * 3]; tri.v1 = triangles [i * 3 + 1]; tri.v2 = triangles [i * 3 + 2]; if (RVOMath.IsClockwiseXZ(vertices [tri.v0], vertices [tri.v1], vertices [tri.v2]) == false) { int tmp = tri.v0; tri.v0 = tri.v2; tri.v2 = tmp; } //finish position tri.v03 = vertices [tri.v0]; tri.v13 = vertices [tri.v1]; tri.v23 = vertices [tri.v2]; tri.v03xz = new KInt2(tri.v03.x, tri.v03.z); tri.v13xz = new KInt2(tri.v13.x, tri.v13.z); tri.v23xz = new KInt2(tri.v23.x, tri.v23.z); tri.averagePos = (tri.v03 + tri.v13 + tri.v23) / 3; if (this.ExactMode >= ExactType.TWO) { tri.xzPos = new KInt2(tri.averagePos.x, tri.averagePos.z); if (point2triangle.ContainsKey(tri.xzPos)) { point2triangle [tri.xzPos].Add(tri); } else { point2triangle [tri.xzPos] = new List <NavmeshTriangle> (); point2triangle [tri.xzPos].Add(tri); } } ShowProgress("构建三角形", (float)i / ObsTriangles.Length); } Dictionary <KInt2, NavmeshTriangle> sides = new Dictionary <KInt2, NavmeshTriangle> (triangles.Length * 3); //创建三角形的边 for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3) { sides [KInt2.ToInt2(triangles [i + 0], triangles [i + 1])] = ObsTriangles [j]; sides [KInt2.ToInt2(triangles [i + 1], triangles [i + 2])] = ObsTriangles [j]; sides [KInt2.ToInt2(triangles [i + 2], triangles [i + 0])] = ObsTriangles [j]; } HashSet <NavmeshTriangle> connections = new HashSet <NavmeshTriangle> (); for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3) { connections.Clear(); NavmeshTriangle node = ObsTriangles [j]; for (int q = 0; q < 3; q++) { NavmeshTriangle other; //如果是mesh中的边,则加入 if (sides.TryGetValue(KInt2.ToInt2(triangles [i + ((q + 1) % 3)], triangles [i + q]), out other)) { connections.Add(other); } } //拷贝当前的一份连接点,而不是赋值引用过去 node.connections = new List <NavmeshTriangle> (); node.connections.AddRange(connections); node.CreateSharedInfo(); ShowProgress("构建连接点", (float)i / (triangles.Length / 3)); } ClearProgressBar(); EndSample(); return(true); }
void TriangleCheck(List <NavmeshTriangle> testtriangles, Dictionary <KInt2, HashSet <Segment> > IntersectCache, List <Segment> removeList, Segment TestSegment) { HashSet <Segment> hitCache = null; if (IntersectCache.ContainsKey(TestSegment.start)) { hitCache = IntersectCache [TestSegment.start]; } if (IntersectCache.ContainsKey(TestSegment.end)) { HashSet <Segment> cache = IntersectCache [TestSegment.end]; if (cache != null) { if (hitCache == null) { hitCache = cache; } else { var en = cache.GetEnumerator(); while (en.MoveNext()) { hitCache.Add(en.Current); } } } } for (int PassedTricnt = 0; PassedTricnt < testtriangles.Count; ++PassedTricnt) { NavmeshTriangle targettriangle = testtriangles [PassedTricnt]; int insidecnt = 0; int hitcnt = 0; int concnt = 0; KInt2 result; for (int j = 0; j < 3; ++j) { Segment side = targettriangle.GetSegment(j); bool h1 = hitCache != null && hitCache.Contains(side); bool h2 = Segment.Intersect(TestSegment.start, TestSegment.end, side.start, side.end, out result); if (h1 || h2) { hitcnt++; } if (side.ContainsSegment(TestSegment)) { insidecnt++; } if (TestSegment.isConnect(side)) { concnt++; } } if (insidecnt == 0 && concnt == 0) { int b1 = isInside(targettriangle.v03xz, targettriangle.v13xz, targettriangle.v23xz, TestSegment.start, ErrorRadius); int b2 = isInside(targettriangle.v03xz, targettriangle.v13xz, targettriangle.v23xz, TestSegment.end, ErrorRadius); if (b1 == 2 && b2 == 2) { removeList.Add(TestSegment); break; } else if ((b1 == 1 && b2 == 2) || (b1 == 2 && b2 == 1)) { removeList.Add(TestSegment); break; } else if ((b1 <= 1 && b2 <= 1) && hitcnt == 2) { removeList.Add(TestSegment); break; } else if ((b1 == 2 || b2 == 2) && hitcnt > 0) { removeList.Add(TestSegment); break; } } ShowProgress("三角相交检测 移除相交线段", (float)PassedTricnt / testtriangles.Count); } }
void Add2Rvo() { BeginSample("Add2Rvo"); float firsttime = Time.realtimeSinceStartup; if (ExactMode == ExactType.ZERO) { BeginSample("ZERO COST"); int[] uses = new int[20]; for (int i = 0; i < ObsTriangles.Length; i++) { NavmeshTriangle node = ObsTriangles [i]; uses [0] = uses [1] = uses [2] = 0; if (node != null) { for (int j = 0; j < node.connections.Count; j++) { NavmeshTriangle other = node.connections [j]; if (other != null) { int a = node.SharedEdge(other); if (a != -1) { uses [a] = 1; } } } for (int j = 0; j < 3; j++) { if (uses [j] == 0) { var v1 = node.GetVertex(j); var v2 = node.GetVertex((j + 1) % 3); Simulator.Instance.addObstacle(v1, v2); } } } ShowProgress("插入障碍点", (float)i / (ObsTriangles.Length)); } EndSample(); } if (ExactMode >= ExactType.ONE) { BeginSample("Buildsegments"); Buildsegments(); EndSample(); BeginSample("RemoveUnused"); RemoveUnused(); EndSample(); BeginSample("PushSegmentstoObstacles"); PushSegmentstoObstacles(); EndSample(); } ShowProgress("准备构建ObstacleTree", 0); float time = Time.realtimeSinceStartup; BeginSample("processObstacles"); if (processObstacles) { Simulator.Instance.processObstacles(); } EndSample(); LogMgr.LogFormat("Add2Rvo cost :{0} processObstacles cost :{1} ", Time.realtimeSinceStartup - firsttime, Time.realtimeSinceStartup - time); ShowProgress("构建ObstacleTree 完成", 1); this.ClearProgressBar(); EndSample(); #if !UNITY_EDITOR ObsTriangles = null; segments = null; tree = null; point2triangle = null; #else if (ObstacleDebug >= DebugMode.ShowAll && UnityEditor.EditorUtility.DisplayDialog("tips", "export kdtree asset or not ?", "OK", "NO")) { string assetpath = UnityEditor.EditorUtility.SaveFilePanelInProject("save", "kdtree", "asset", "please enter a filename"); if (!string.IsNullOrEmpty(assetpath)) { KdtreeAsset node = ScriptableObject.CreateInstance <KdtreeAsset> (); ScriptCommand cmd = ScriptCommand.Create((int)FrameWorkCmdDefine.GET_KDTREE); cmd.Excute(); ScriptCommand obscmd = ScriptCommand.Create((int)FrameWorkCmdDefine.GET_OBSTACLES); obscmd.Excute(); KdTree tree = cmd.ReturnParams.ReadObject() as KdTree; IList <Obstacle> obstacles = obscmd.ReturnParams.ReadObject() as IList <Obstacle>; node.CreateKdtree(tree, obstacles); cmd.Release(true); obscmd.Release(true); UnityEditor.AssetDatabase.CreateAsset(node, assetpath); } } #endif }
void OnDrawGizmos() { if (ObsTriangles == null || !DrawGizmos) { return; } bool show = !Drawsegments && !DrawRmovelist && !DrawNearstTriangles && DrawGizmos; if (DrawRmovelist) { for (int i = 0; i < willremoveList.Count; ++i) { Gizmos.color = Color.red; Segment seg = willremoveList [i]; KInt3 start = new KInt3(seg.start.x, 0, seg.start.y); KInt3 end = new KInt3(seg.end.x, 0, seg.end.y); Gizmos.DrawLine(start, end); UnityEditor.Handles.Label((start + end) / 2, "序号 [" + seg.uid + "]"); } } if (Drawsegments) { for (int i = 0; i < segments.Count; ++i) { Gizmos.color = (i % 2 == 0) ? Color.green : Color.blue; Segment seg = segments [i]; KInt3 start = new KInt3(seg.start.x, 0, seg.start.y); KInt3 end = new KInt3(seg.end.x, 0, seg.end.y); Gizmos.DrawLine(start, end); UnityEditor.Handles.Label((start + end) / 2, "序号 [" + seg.uid + "]"); } } if (DrawNearstTriangles) { if (tree != null && lastpoint != targetPoint) { if (SeekedTriangleList == null) { SeekedTriangleList = new List <NavmeshTriangle> (); } SeekedTriangleList.Clear(); List <KInt2> startidxs = ListPool.TrySpawn <List <KInt2> > (); tree.ball_queryPoints((KInt2)targetPoint, Seekrange, startidxs); for (int k = 0; k < startidxs.Count; ++k) { var trianglelist = point2triangle [startidxs [k]]; for (int v = 0; v < trianglelist.Count; ++v) { SeekedTriangleList.Add(trianglelist [v]); } } ListPool.TryDespawn(startidxs); lastpoint = targetPoint; } Gizmos.DrawWireCube(new Vector3(targetPoint.x, 0, targetPoint.y), Vector3.one); if (SeekedTriangleList != null) { for (int i = 0; i < SeekedTriangleList.Count; i++) { NavmeshTriangle node = SeekedTriangleList [i]; Gizmos.color = Color.cyan; for (int q = 0; q < node.connections.Count; q++) { Gizmos.DrawLine(node.averagePos, Vector3.Lerp(node.averagePos, node.connections [q].averagePos, 0.45f)); } Gizmos.color = Color.black; Gizmos.DrawLine(ObsVertices [node.v0], ObsVertices [node.v1]); Gizmos.DrawLine(ObsVertices [node.v1], ObsVertices [node.v2]); Gizmos.DrawLine(ObsVertices [node.v2], ObsVertices [node.v0]); UnityEditor.Handles.Label(node.averagePos, "序号 [" + node.uid + "]"); } } } if (show) { for (int i = 0; i < ObsTriangles.Length; i++) { NavmeshTriangle node = ObsTriangles [i]; Gizmos.color = Color.cyan; for (int q = 0; q < node.connections.Count; q++) { Gizmos.DrawLine(node.averagePos, Vector3.Lerp(node.averagePos, node.connections [q].averagePos, 0.45f)); } Gizmos.color = Color.black; Gizmos.DrawLine(ObsVertices [node.v0], ObsVertices [node.v1]); Gizmos.DrawLine(ObsVertices [node.v1], ObsVertices [node.v2]); Gizmos.DrawLine(ObsVertices [node.v2], ObsVertices [node.v0]); } } }