private bool IsPositionInTriangle(Vector3 pos, NavMeshTriangle triangle) { // Compute vectors Vector3 v0 = triangle.vertex2.Position - triangle.vertex1.Position; Vector3 v1 = triangle.vertex3.Position - triangle.vertex1.Position; Vector3 v2 = pos - triangle.vertex1.Position; // Compute dot products float dot00 = Vector3.Dot(v0, v0); float dot01 = Vector3.Dot(v0, v1); float dot02 = Vector3.Dot(v0, v2); float dot11 = Vector3.Dot(v1, v1); float dot12 = Vector3.Dot(v1, v2); // Compute barycentric coordinates float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); float u = (dot11 * dot02 - dot01 * dot12) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle if ((u >= 0) && (v >= 0) && (u + v < 1)) { return(true); } return(false); }
private void Start() { navMesh = new AStarNavMeshNavigation(navMeshHolder); SelectedTriangle = navMeshHolder.GetRandomTriangle(); if (SelectedTriangle != null) { SelectedTriangle.isSelected = true; } }
public bool IsAdjacent(NavMeshTriangle tri) { // Check Vertex 1 bool vert1 = tri.vertex1.Equals(vertex1) || tri.vertex2.Equals(vertex1) || tri.vertex3.Equals(vertex1); bool vert2 = tri.vertex1.Equals(vertex2) || tri.vertex2.Equals(vertex2) || tri.vertex3.Equals(vertex2); bool vert3 = tri.vertex1.Equals(vertex3) || tri.vertex2.Equals(vertex3) || tri.vertex3.Equals(vertex3); return(vert1 || vert2 || vert3); }
public override void OnInspectorGUI() { serializedObject.Update(); if (GUILayout.Button("Update Generator Values")) { navMesh.UpdateInformation(); } if (GUILayout.Button("Update Adjacent Triangles")) { navMesh.UpdateAdjacentTriangles(); } SerializedProperty prop = serializedObject.FindProperty("m_Script"); EditorGUILayout.PropertyField(prop, true, new GUILayoutOption[0]); showPosition = EditorGUILayout.Foldout(showPosition, "triangles"); if (showPosition) { GUIContent ShowButtonGUIContent = new GUIContent("Show Buttons"); showButton = EditorGUILayout.Toggle(ShowButtonGUIContent, showButton); EditorGUI.indentLevel++; for (int i = 0; i < navMesh.Triangles.Length; i++) { SerializedProperty triangle = triangles.GetArrayElementAtIndex(i); GUIContent gUIContent = new GUIContent(triangle.FindPropertyRelative("ID").intValue + (triangle.FindPropertyRelative("isSelected").boolValue ? " Selected" : "")); EditorGUILayout.PropertyField(triangle, gUIContent, true); // draw property with it's children if (showButton && GUILayout.Button("Select Vertex")) { currentVertex = 0; if (selectedTriangle != null) { selectedTriangle.isSelected = false; } selectedTriangle = navMesh.Triangles[i]; selectedTriangle.isSelected = true; } } EditorGUI.indentLevel--; if (GUILayout.Button("Insert Triangle")) { navMesh.AddNewTriangle(); } } if (GUI.changed) { EditorUtility.SetDirty(navMesh); EditorSceneManager.MarkSceneDirty(navMesh.gameObject.scene); } ////EditorGUILayout.LabelField(Selection.activeGameObject.name); //EditorGUILayout.Space(); //DrawDefaultInspector(); EditorGUILayout.PropertyField(entrancePoints, true); serializedObject.ApplyModifiedProperties(); }
public void CreateTriangle(Vertex vert1, Vertex vert2, Vertex vert3) { NavMeshTriangle tri = AddNewTriangle(); tri.vertex1 = vert1; tri.vertex2 = vert2; tri.vertex3 = vert3; AddTriangleVertexesToAdjacencyList(tri); AddAdjacentTriangles(tri); }
private static void AddTriangleVertexesToAdjacencyList(NavMeshTriangle triangle) { AddVertexesToAdjacentList(triangle.vertex1, triangle.vertex2); AddVertexesToAdjacentList(triangle.vertex1, triangle.vertex3); AddVertexesToAdjacentList(triangle.vertex2, triangle.vertex1); AddVertexesToAdjacentList(triangle.vertex2, triangle.vertex3); AddVertexesToAdjacentList(triangle.vertex3, triangle.vertex1); AddVertexesToAdjacentList(triangle.vertex3, triangle.vertex2); }
public NavMeshTriangle AddNewTriangle() { NavMeshTriangle[] newTriangles = new NavMeshTriangle[triangles.Length + 1]; for (int i = 0; i < triangles.Length; i++) { newTriangles[i] = triangles[i]; } newTriangles[newTriangles.Length - 1] = new NavMeshTriangle(); newTriangles[newTriangles.Length - 1].adjacentTriangles = new List <int>(); triangles = newTriangles; return(newTriangles[newTriangles.Length - 1]); }
private void Update() { if (getRandomPoint) { SelectedTriangle.isSelected = false; SelectedTriangle = navMeshHolder.GetRandomTriangle(); if (SelectedTriangle != null) { SelectedTriangle.isSelected = true; } } path = navMesh.GetPathFromTo(this.transform.position, getRandomPoint ? navMeshHolder.GetRandomPointInTriangle(SelectedTriangle) : end.position); }
public Vector3 GetRandomPointInTriangle(NavMeshTriangle triangle) { float x = Random.value; float y = Random.value; while (x + y > 1) { x = Random.value; y = Random.value; } Vector3 insideTriangle = (triangle.vertex2.Position - triangle.vertex1.Position) * x + (triangle.vertex3.Position - triangle.vertex1.Position) * y; return(triangle.vertex1.Position + insideTriangle); }
public List <NavMeshMovementLine> SmoothPath(List <NavMeshMovementLine> oldPath) { if (oldPath.Count <= 2) { return(oldPath); } NavMeshTriangle triangle = null; for (int i = 0; i < oldPath.Count - 2; i++) { if (oldPath[i] == null) { continue; } currentPoint = oldPath[i]; for (int j = i + 2; j - (i + 2) <= 5 && j < oldPath.Count; j++) { if (oldPath[j] == null) { continue; } bool canRemove = true; Vector3 nextStep = Vector3.Lerp(currentPoint.point, oldPath[j].point, 0); for (int k = 1; k < numberOfSteps; k++) { triangle = navMesh.GetContainingTriangle(nextStep); if (triangle == null) { canRemove = false; break; } nextStep = Vector3.Lerp(currentPoint.point, oldPath[j].point, k / (float)numberOfSteps); } if (canRemove) { oldPath[j - 1] = null; } } } List <NavMeshMovementLine> newPath = new List <NavMeshMovementLine>(); oldPath.ForEach((item) => { if (item != null) { newPath.Add(item); } }); //List<NavMeshMovementLine> newPath = AvoidWalls(newPath); return(newPath); }
public override void OnInspectorGUI() { serializedObject.Update(); // Add script drawer SerializedProperty prop = serializedObject.FindProperty("m_Script"); EditorGUILayout.PropertyField(prop, true, new GUILayoutOption[0]); //if (GUILayout.Button("Add Adjacent Tris")) //{ // navMesh.UpdateAdjacentTris(); // EditorUtility.SetDirty(navMesh); // EditorSceneManager.MarkSceneDirty(navMesh.gameObject.scene); //} showPosition = EditorGUILayout.Foldout(showPosition, "triangles"); if (showPosition) { EditorGUI.indentLevel++; for (int i = 0; i < navMesh.Triangles.Length; i++) { SerializedProperty triangle = triangles.GetArrayElementAtIndex(i); GUIContent gUIContent = new GUIContent(triangle.FindPropertyRelative("ID").intValue + (triangle.FindPropertyRelative("isSelected").boolValue ? " Selected" : "")); EditorGUILayout.PropertyField(triangle, gUIContent, true); // draw property with it's children if (GUILayout.Button("Select Triangle")) { currentVertex = 0; if (selectedTriangle != null) { selectedTriangle.isSelected = false; } selectedTriangle = navMesh.Triangles[i]; selectedTriangle.isSelected = true; } } EditorGUI.indentLevel--; } serializedObject.ApplyModifiedProperties(); }
private void AddAdjacentTriangles(NavMeshTriangle tri) { tri.adjacentTriangles.Clear(); // Check if a duo of verts share more than 1 adjacent vertex NavMeshTriangle triangle = GetAdjacentTriangle(tri.vertex1, tri.vertex2, tri.vertex3); if (triangle != null) { tri.adjacentTriangles.Add(triangle.ID); } triangle = GetAdjacentTriangle(tri.vertex2, tri.vertex3, tri.vertex1); if (triangle != null) { tri.adjacentTriangles.Add(triangle.ID); } triangle = GetAdjacentTriangle(tri.vertex3, tri.vertex1, tri.vertex2); if (triangle != null) { tri.adjacentTriangles.Add(triangle.ID); } }
// override object.Equals public override bool Equals(object obj) { // // See the full list of guidelines at // http://go.microsoft.com/fwlink/?LinkID=85237 // and also the guidance for operator== at // http://go.microsoft.com/fwlink/?LinkId=85238 // if (obj == null || GetType() != obj.GetType()) { return(false); } NavMeshTriangle tri = obj as NavMeshTriangle; if (tri == null) { return(false); } return((tri.vertex1 != null && tri.vertex1.Equals(this.vertex1)) && (tri.vertex2 != null && tri.vertex2.Equals(this.vertex2)) && (tri.vertex3 != null && tri.vertex3.Equals(this.vertex3))); }
public List <NavMeshMovementLine> GetPathFromTo(Vector3 from, Vector3 to) { if (actualPoints.Length == 0) { return(new List <NavMeshMovementLine>()); } for (int i = 0; i < actualPoints.Length; i++) { actualPoints[i].inClosed = false; actualPoints[i].f = 0; actualPoints[i].g = 0; actualPoints[i].h = 0; actualPoints[i].parent = null; } triStart = navMesh.GetContainingTriangle(from); if (triStart == null) { return(new List <NavMeshMovementLine>()); } triEnd = navMesh.GetContainingTriangle(to); if (triEnd == null) { return(new List <NavMeshMovementLine>()); } path.Clear(); // If the points are on the same triangle, send back a straight line between both points if (triStart.ID == triEnd.ID) { path.Add(new NavMeshMovementLine { point = from }); path.Add(new NavMeshMovementLine { point = to }); return(path); } open.Clear(); // Add the starting triangle vertexes to the open list open.Add(UpdateAStarPoint(GetPointValue(triStart.vertex1.ID), 0, 0, to)); open.Add(UpdateAStarPoint(GetPointValue(triStart.vertex2.ID), 0, 0, to)); open.Add(UpdateAStarPoint(GetPointValue(triStart.vertex3.ID), 0, 0, to)); // The starting point does not need to be kept in the closed list while (open.Count > 0) { open.Sort((a, b) => a.f.CompareTo(b.f)); current = open[0]; if (current.vert.ID == (triEnd.vertex1.ID) || current.vert.ID == (triEnd.vertex2.ID) || current.vert.ID == (triEnd.vertex3.ID)) { return(ReconstructPath(current, to, from)); } open.RemoveAt(0); current.inClosed = true; if (open.Count > 4000) { break; } for (int i = 0; i < current.vert.Count; i++) { AStarPoint aStarPointExisting = GetPointValue(current.vert.GetAdjacentVertex(i).ID); if (aStarPointExisting.inClosed) { continue; } float cost = current.g + (current.vert.Position - current.vert.GetAdjacentVertex(i).Position).magnitude; AStarPoint aStarPoint = open.Find((item) => item.vert.Equals(current.vert.GetAdjacentVertex(i))); if (aStarPoint == null) { aStarPoint = UpdateAStarPoint(aStarPointExisting, current.g, (Mathf.Pow((current.vert.Position.x - current.vert.GetAdjacentVertex(i).Position.x), 2) + Mathf.Pow((current.vert.Position.y - current.vert.GetAdjacentVertex(i).Position.y), 2)), to, current); open.Add(aStarPoint); } else { if (cost < aStarPoint.g) { aStarPoint.g = cost; aStarPoint.f = aStarPoint.g + aStarPoint.h; aStarPoint.parent = current; } } } } return(path); }
private void HandleKeyboard() { Event current = Event.current; if (current.type != EventType.KeyDown) { return; } EditorGUI.BeginChangeCheck(); switch (current.keyCode) { case KeyCode.DownArrow: switch (currentVertex) { case 0: selectedTriangle.vertex1 = Selection.activeGameObject.GetComponent <Vertex>(); break; case 1: selectedTriangle.vertex2 = Selection.activeGameObject.GetComponent <Vertex>(); break; case 2: selectedTriangle.vertex3 = Selection.activeGameObject.GetComponent <Vertex>(); break; default: break; } currentVertex++; if (currentVertex >= 3) { currentVertex = 0; } current.Use(); break; case KeyCode.UpArrow: currentVertex = 0; if (selectedTriangle != null) { selectedTriangle.isSelected = false; } selectedTriangle = navMesh.AddNewTriangle(); selectedTriangle.isSelected = true; current.Use(); break; case KeyCode.Return: case KeyCode.KeypadEnter: current.Use(); break; case KeyCode.LeftArrow: case KeyCode.Backspace: //current.Use(); break; case KeyCode.RightArrow: //current.Use(); break; case KeyCode.Escape: current.Use(); break; } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Changed triangle Vertex"); } }