public override void OnInspectorGUI() { GUIStyle bold_wrap = EditorStyles.boldLabel; bold_wrap.wordWrap = true; GUILayout.Label("Navmesh Preprocessor for HTC Vive Locomotion", bold_wrap); GUILayout.Label("Adrian Biagioli 2016", EditorStyles.miniLabel); GUILayout.Label("Before Using", bold_wrap); GUIStyle wrap = EditorStyles.label; wrap.wordWrap = true; GUILayout.Label( "Change your navmesh settings (Window > Navigation) to where you want the player to be able to navigate and bake the navmesh. " + "Then click \"Update Navmesh Data\" below. You may change the navigation settings back and rebake after you have updated.\n\nRecommended Settings:\n" + "Agent Radius: 0.25\nAgent Height: 2\nMax Slope: 0\nStep Height: 0\nDrop Height: 0\nJump Distance: 0\n", wrap); ViveNavMesh mesh = (ViveNavMesh)target; if (GUILayout.Button("Update Navmesh Data")) { mesh.SelectableMesh = ConvertNavmeshToMesh(NavMesh.CalculateTriangulation(), 0); mesh.SelectableMeshBorder = FindBorderEdges(mesh.SelectableMesh); } EditorGUILayout.LabelField("Render Settings", EditorStyles.boldLabel); mesh.GroundMaterial = (Material)EditorGUILayout.ObjectField("Ground Material", mesh.GroundMaterial, typeof(Material), false); mesh.GroundAlpha = EditorGUILayout.Slider("Ground Alpha", mesh.GroundAlpha, 0, 1); }
// Sample a bunch of points along a parabolic curve until you hit gnd. At that point, cut off the parabola // p0: starting point of parabola // v0: initial parabola velocity // a: initial acceleration // dist: distance between sample points // points: number of sample points // gnd: height of the ground, in meters above y=0 // outPts: List that will be populated by new points private static bool CalculateParabolicCurve(Vector3 p0, Vector3 v0, Vector3 a, float dist, int points, ViveNavMesh nav, List<Vector3> outPts) { outPts.Clear(); outPts.Add(p0); Vector3 last = p0; float t = 0; for(int i=0; i< points; i++) { t += dist / ParabolicCurveDeriv(v0, a, t).magnitude; Vector3 next = ParabolicCurve(p0, v0, a, t); Vector3 castHit; bool endOnNavmesh; bool cast = nav.Linecast(last, next, out endOnNavmesh, out castHit); if (cast) { outPts.Add(castHit); return endOnNavmesh; } else outPts.Add(next); last = next; } return false; }
public void UpdateNavMesh() { ViveNavMesh mesh = (ViveNavMesh)target; Undo.RecordObject(mesh, "Update Navmesh Data"); NavMeshTriangulation tri = NavMesh.CalculateTriangulation(); Vector3[] verts = tri.vertices; int[] tris = tri.indices; int[] areas = tri.areas; int vert_size = verts.Length; int tri_size = tris.Length; RemoveMeshDuplicates(verts, tris, out vert_size, 0.01f); DewarpMesh(verts, mesh.DewarpingMethod, mesh.SampleRadius); CullNavmeshTriangulation(verts, tris, areas, p_area.intValue, mesh.IgnoreSlopedSurfaces, ref vert_size, ref tri_size); Mesh m = ConvertNavmeshToMesh(verts, tris, vert_size, tri_size); // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object mesh.SelectableMeshBorder = FindBorderEdges(m); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure that setter is called }
private IEnumerator Start() { yield return(null); ToggleGosForPreview(true, _gosToHideInPreview); ToggleGosForPreview(false, _gosToShowInPreview); //If user has checked the "Is Test Scene" checkbox load the current scene if (_isTestScene) { //make sure we have a navmesh if (_navMesh == null) { _navMesh = FindObjectOfType <ViveNavMesh>(); if (_navMesh != null) { _navMeshAnimator = _navMesh.GetComponent <Animator>(); ParabolicPointer pointer = FindObjectOfType <ParabolicPointer>(); if (pointer != null) { pointer.NavMesh = _navMesh; } TeleportVive teleporter = FindObjectOfType <TeleportVive>(); if (teleporter != null) { teleporter.NavAnimator = _navMeshAnimator; } } } LoadTestScene(); } }
// Sample a bunch of points along a parabolic curve until you hit gnd. At that point, cut off the parabola // p0: starting point of parabola // v0: initial parabola velocity // a: initial acceleration // dist: distance between sample points // points: number of sample points // gnd: height of the ground, in meters above y=0 // outPts: List that will be populated by new points private static bool CalculateParabolicCurve(Vector3 p0, Vector3 v0, Vector3 a, float dist, int points, ViveNavMesh nav, List <Vector3> outPts) { outPts.Clear(); outPts.Add(p0); Vector3 last = p0; float t = 0; for (int i = 0; i < points; i++) { t += dist / ParabolicCurveDeriv(v0, a, t).magnitude; Vector3 next = ParabolicCurve(p0, v0, a, t); Vector3 castHit; bool endOnNavmesh; bool cast = nav.Linecast(last, next, out endOnNavmesh, out castHit); if (cast) { outPts.Add(castHit); return(endOnNavmesh); } else { outPts.Add(next); } last = next; } return(false); }
public override void OnInspectorGUI() { GUIStyle bold_wrap = EditorStyles.boldLabel; bold_wrap.wordWrap = true; GUILayout.Label("Navmesh Preprocessor for HTC Vive Locomotion", bold_wrap); GUILayout.Label("Adrian Biagioli 2016", EditorStyles.miniLabel); GUILayout.Label("Before Using", bold_wrap); GUIStyle wrap = EditorStyles.label; wrap.wordWrap = true; GUILayout.Label( "Make sure you bake a Navigation Mesh (NavMesh) in Unity before continuing (Window > Navigation). When you " + "are done, click \"Update Navmesh Data\" below. This will update the graphic of the playable area " + "that the player will see in-game.\n", wrap); ViveNavMesh mesh = (ViveNavMesh)target; serializedObject.Update(); // Area Mask // string[] areas = GameObjectUtility.GetNavMeshAreaNames(); int[] area_index = new int[areas.Length]; int temp_mask = 0; for (int x = 0; x < areas.Length; x++) { area_index[x] = GameObjectUtility.GetNavMeshAreaFromName(areas[x]); temp_mask |= ((p_area.intValue >> area_index[x]) & 1) << x; } EditorGUI.BeginChangeCheck(); temp_mask = EditorGUILayout.MaskField("Area Mask", temp_mask, areas); if (EditorGUI.EndChangeCheck()) { p_area.intValue = 0; for (int x = 0; x < areas.Length; x++) { p_area.intValue |= (((temp_mask >> x) & 1) == 1 ? 0 : 1) << area_index[x]; } p_area.intValue = ~p_area.intValue; } serializedObject.ApplyModifiedProperties(); // Sanity check for Null properties // bool HasMesh = (mesh.SelectableMesh != null && mesh.SelectableMesh.vertexCount != 0) || (mesh.SelectableMeshBorder != null && mesh.SelectableMeshBorder.Length != 0); // Fixes below error message popping up with prefabs. Kind of hacky but gets the job done bool isPrefab = EditorUtility.IsPersistent(target); if (isPrefab && mesh.SelectableMesh == null) { mesh.SelectableMesh = new Mesh(); } bool MeshNull = mesh.SelectableMesh == null; bool BorderNull = mesh.SelectableMeshBorder == null; if (MeshNull || BorderNull) { string str = "Internal Error: "; if (MeshNull) { str += "Selectable Mesh == null. "; } if (BorderNull) { str += "Border point array == null. "; } str += "This may lead to strange behavior or serialization. Try updating the mesh or delete and recreate the Navmesh object. "; str += "If you are able to consistently get a Vive Nav Mesh object into this state, please submit a bug report."; EditorGUILayout.HelpBox(str, MessageType.Error); } // Update / Clear Navmesh Data // if (GUILayout.Button("Update Navmesh Data")) { Undo.RecordObject(mesh, "Update Navmesh Data"); UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation(); int vert_size, tri_size; CullNavmeshTriangulation(ref tri, p_area.intValue, out vert_size, out tri_size); Mesh m = ConvertNavmeshToMesh(tri, vert_size, tri_size); // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object mesh.SelectableMeshBorder = FindBorderEdges(m); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure that setter is called } GUI.enabled = HasMesh; if (GUILayout.Button("Clear Navmesh Data")) { Undo.RecordObject(mesh, "Clear Navmesh Data"); // Note: Unity does not serialize "null" correctly so we set everything to empty objects Mesh m = new Mesh(); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure setter is called mesh.SelectableMeshBorder = new BorderPointSet[0]; } GUI.enabled = true; GUILayout.Label(HasMesh ? "Status: NavMesh Loaded" : "Status: No NavMesh Loaded"); // Render Settings // EditorGUILayout.LabelField("Render Settings", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(p_material); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(mesh, "Change Ground Material"); serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.GroundMaterial = mesh.GroundMaterial; // Reload material } EditorGUILayout.PropertyField(p_alpha); serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { GUIStyle bold_wrap = EditorStyles.boldLabel; bold_wrap.wordWrap = true; GUILayout.Label("Navmesh Preprocessor for HTC Vive Locomotion", bold_wrap); GUILayout.Label("Adrian Biagioli 2017", EditorStyles.miniLabel); GUILayout.Label("Before Using", bold_wrap); GUIStyle wrap = EditorStyles.label; wrap.wordWrap = true; GUILayout.Label( "Make sure you bake a Navigation Mesh (NavMesh) in Unity before continuing (Window > Navigation). When you " + "are done, click \"Update Navmesh Data\" below. This will update the graphic of the playable area " + "that the player will see in-game.\n", wrap); ViveNavMesh mesh = (ViveNavMesh)target; serializedObject.Update(); // Area Mask // string[] areaNames = GameObjectUtility.GetNavMeshAreaNames(); int[] area_index = new int[areaNames.Length]; int temp_mask = 0; for (int x = 0; x < areaNames.Length; x++) { area_index[x] = GameObjectUtility.GetNavMeshAreaFromName(areaNames[x]); temp_mask |= ((p_area.intValue >> area_index[x]) & 1) << x; } EditorGUI.BeginChangeCheck(); temp_mask = EditorGUILayout.MaskField("Area Mask", temp_mask, areaNames); if (EditorGUI.EndChangeCheck()) { p_area.intValue = 0; for (int x = 0; x < areaNames.Length; x++) { p_area.intValue |= (((temp_mask >> x) & 1) == 1 ? 0 : 1) << area_index[x]; } p_area.intValue = ~p_area.intValue; } serializedObject.ApplyModifiedProperties(); // Sanity check for Null properties // bool HasMesh = (mesh.SelectableMesh != null && mesh.SelectableMesh.vertexCount != 0) || (mesh.SelectableMeshBorder != null && mesh.SelectableMeshBorder.Length != 0); // Fixes below error message popping up with prefabs. Kind of hacky but gets the job done bool isPrefab = EditorUtility.IsPersistent(target); if (isPrefab && mesh.SelectableMesh == null) { mesh.SelectableMesh = new Mesh(); } bool MeshNull = mesh.SelectableMesh == null; bool BorderNull = mesh.SelectableMeshBorder == null; if (MeshNull || BorderNull) { string str = "Internal Error: "; if (MeshNull) { str += "Selectable Mesh == null. "; } if (BorderNull) { str += "Border point array == null. "; } str += "This may lead to strange behavior or serialization. Try updating the mesh or delete and recreate the Navmesh object. "; str += "If you are able to consistently get a Vive Nav Mesh object into this state, please submit a bug report."; EditorGUILayout.HelpBox(str, MessageType.Error); } // Update / Clear Navmesh Data // if (GUILayout.Button("Update Navmesh Data")) { Undo.RecordObject(mesh, "Update Navmesh Data"); NavMeshTriangulation tri = NavMesh.CalculateTriangulation(); Vector3[] verts = tri.vertices; int[] tris = tri.indices; int[] areas = tri.areas; int vert_size = verts.Length; int tri_size = tris.Length; RemoveMeshDuplicates(verts, tris, out vert_size, 0.01f); DewarpMesh(verts, mesh.DewarpingMethod, mesh.SampleRadius); CullNavmeshTriangulation(verts, tris, areas, p_area.intValue, mesh.IgnoreSlopedSurfaces, ref vert_size, ref tri_size); Mesh m = ConvertNavmeshToMesh(verts, tris, vert_size, tri_size); // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object mesh.SelectableMeshBorder = FindBorderEdges(m); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure that setter is called } GUI.enabled = HasMesh; if (GUILayout.Button("Clear Navmesh Data")) { Undo.RecordObject(mesh, "Clear Navmesh Data"); // Note: Unity does not serialize "null" correctly so we set everything to empty objects Mesh m = new Mesh(); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure setter is called mesh.SelectableMeshBorder = new BorderPointSet[0]; } GUI.enabled = true; GUILayout.Label(HasMesh ? "Status: NavMesh Loaded" : "Status: No NavMesh Loaded"); // Render Settings // EditorGUILayout.LabelField("Render Settings", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(p_material); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(mesh, "Change Ground Material"); serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.GroundMaterial = new Material((Material)p_material.objectReferenceValue); // Reload material } EditorGUILayout.PropertyField(p_alpha); serializedObject.ApplyModifiedProperties(); // Raycast Settings // EditorGUILayout.LabelField("Raycast Settings", EditorStyles.boldLabel); int temp_layer_mask = p_layer_mask.intValue; bool temp_ignore_layer_mask = p_ignore_layer_mask.boolValue; EditorGUI.BeginChangeCheck(); temp_layer_mask = LayerMaskField("Layer Mask", temp_layer_mask); if (EditorGUI.EndChangeCheck()) { p_layer_mask.intValue = temp_layer_mask; } serializedObject.ApplyModifiedProperties(); EditorGUI.BeginChangeCheck(); temp_ignore_layer_mask = EditorGUILayout.Toggle("Ignore Layer Mask", temp_ignore_layer_mask); if (EditorGUI.EndChangeCheck()) { p_ignore_layer_mask.boolValue = temp_ignore_layer_mask; } serializedObject.ApplyModifiedProperties(); QueryTriggerInteraction temp_query_trigger_interaction = (QueryTriggerInteraction)p_query_trigger_interaction.intValue; EditorGUI.BeginChangeCheck(); temp_query_trigger_interaction = (QueryTriggerInteraction)EditorGUILayout.EnumPopup("Query Trigger Interaction", temp_query_trigger_interaction); if (EditorGUI.EndChangeCheck()) { p_query_trigger_interaction.intValue = (int)temp_query_trigger_interaction; } serializedObject.ApplyModifiedProperties(); // Navmesh Settings // EditorGUILayout.LabelField("Navmesh Settings", EditorStyles.boldLabel); GUILayout.Label( "Make sure the sample radius below is equal to your Navmesh Voxel Size (see Advanced > Voxel Size " + "in the navigation window). Increase this if the selection disk is not appearing.", wrap); EditorGUILayout.PropertyField(p_sample_radius); EditorGUILayout.PropertyField(p_ignore_sloped_surfaces); EditorGUILayout.PropertyField(p_dewarp_method); serializedObject.ApplyModifiedProperties(); }