//List<Vector2> hits = new List<Vector2>(); public MeshData[] GenerateViewMeshData(Vector2 ViewSource) { //Vector2 _viewSource = Camera.main.ScreenToWorldPoint(Input.mousePosition); /*if(_viewSource==ViewSource) * return;*/ #if UNITY_EDITOR debugHit.Clear(); debugText.Clear(); #endif //ViewSource = _viewSource; hits.Clear(); foreach (RoomVisiblility room in allRooms) { room.SetEdgesState(false); } SetEdgesState(true); if (!staticRoomShape) // If true, update the room-shape each update I guess. Not supported { UpdateCornersAndDoors(GetComponent <PolygonCollider2D>()); } foreach (Vector2 corner in roomCorners) // { CornerHitInfo cornerHit = CheckCorner(ViewSource, corner); if (cornerHit.cornerIsVisible && !cornerHit.canSeeBeyondCorner) // No relevant hit after hitting a corner { hits.Add(cornerHit.radian, cornerHit.corner); } else if (cornerHit.cornerIsVisible && cornerHit.canSeeBeyondCorner) // Relevant hit after hitting a corner { float c = -0.001f; //Shoot at the corner at a slight angle, sort based on if it hits RaycastHit2D hit1 = Physics2D.Raycast(ViewSource, positiveAdjustAngle * cornerHit.dir, Vector2.Distance(ViewSource, cornerHit.collisionPoint) + 1, ViewLayerMask); if (Vector2.Distance(hit1.point, cornerHit.collisionPoint) < 0.01f) { c = -c; } #if UNITY_EDITOR debugHit.Addd(cornerHit.collisionPoint, Color.blue); debugHit.Addd(cornerHit.corner, Color.magenta); #endif hits.Add(cornerHit.radian + c, cornerHit.collisionPoint); hits.Add(cornerHit.radian, cornerHit.corner); } } Vector2[] partHits = hits.Values.ToArray(); Vector2[] sortedHits = new Vector2[hits.Values.ToArray().Length + 1]; sortedHits[0] = ViewSource; for (int i = 1; i < sortedHits.Length; i++) { sortedHits[i] = partHits[i - 1]; } List <Door> visibleDoors = GetVisibleDoors(ViewSource); List <MeshData> doorViews = new List <MeshData>(); Dictionary <RoomVisiblility, int> previousRooms = new Dictionary <RoomVisiblility, int>() { { this, 1 } }; foreach (Door door in visibleDoors) { RayInfo ray1, ray2; GetDoorRays(door, ViewSource, partHits, out ray1, out ray2); SetEdgesState(false); door.adjecentRoom.GetViewsTroughDoor(ViewSource, ray1, ray2, new Door[1] { door }, ref doorViews, ref debugHit, ref debugText, ref previousRooms); SetEdgesState(true); } //================== MeshData roomView; roomView.vertices = System.Array.ConvertAll <Vector2, Vector3>(sortedHits, ve => ve); roomView.triangles = new int[3 * (roomView.vertices.Length - 1)]; int C1 = 0; int C2 = 1; int C3 = 2; for (int x = 0; x < roomView.triangles.Length - 3; x += 3) { roomView.triangles[x] = C1; roomView.triangles[x + 1] = C3++; roomView.triangles[x + 2] = C2++; } roomView.triangles[roomView.triangles.Length - 3] = 0; roomView.triangles[roomView.triangles.Length - 2] = 1; roomView.triangles[roomView.triangles.Length - 1] = C3 - 1; //================== MeshData[] views = new MeshData[doorViews.Count() + 1]; views[0] = roomView; for (int i = 1; i <= doorViews.Count(); i++) { views[i] = doorViews[i - 1]; } foreach (RoomVisiblility room in allRooms) { room.SetEdgesState(true); } return(views); }
/// <summary> /// Outputs all view meshes trough doors, also checks trough doors in the room you're looking in /// </summary> /// <param name="viewPoint">Point from which to view</param> /// <param name="viewRay1">First ray-direction trough door, origin from the door</param> /// <param name="viewRay2">Second ray-direction trough door, origin from the door</param> /// <param name="doors">Doors trough which to view (TODO)</param> /// <param name="viewMeshes">The resulting meshes</param> public void GetViewsTroughDoor(Vector2 viewPoint, RayInfo viewRay1, RayInfo viewRay2, Door[] doors, ref List <MeshData> viewMeshes, ref Dictionary <Vector2, Color> debugHit, ref Dictionary <Vector3, string> debugText, ref Dictionary <RoomVisiblility, int> previousRooms) { foreach (RoomVisiblility room in previousRooms.Keys) // TODO Find out why light want's to go back and prevent it from happening instead of this lazy hack { if (room.gameObject == this.gameObject && previousRooms[room] > 3) { #if UNITY_EDITOR && DEBUG_MODE Debug.Log("Prevented eternal light loop trough doors in room " + room.name, room); Debug.Break(); #endif return; } } if (previousRooms.ContainsKey(this)) { previousRooms[this]++; } else { previousRooms.Add(this, 1); } SetEdgesState(true); SortedDictionary <float, VertexInfo> vertices = new SortedDictionary <float, VertexInfo>(); foreach (Door door in doors) { RaycastHit2D hit1 = Physics2D.Raycast(viewRay1.origin + viewRay1.direction / 10, viewRay1.direction, RayLength, ViewLayerMask); RaycastHit2D hit2 = Physics2D.Raycast(viewRay2.origin + viewRay2.direction / 10, viewRay2.direction, RayLength, ViewLayerMask); float str, end; str = Mathf.Atan2(viewRay1.direction.y, viewRay1.direction.x); end = Mathf.Atan2(viewRay2.direction.y, viewRay2.direction.x); float firstAngle = DirectionToRadius(viewRay1.direction); VertexInfo vertexInfo; vertexInfo.Vertex = hit1.point; vertexInfo.DoorVertex = viewRay1.origin; vertexInfo.check = AngleIsBetween(str, end, firstAngle) ? 0 : 2; //TODO the angle between stuff can probably be replaced with a position based solution. It's a remnant of a different approach. But it works so ehh vertices.Add(firstAngle, vertexInfo); //debugText.Add(vertices[firstAngle].Vertex, vertices[firstAngle].check.ToString()); int lastHit = vertexInfo.check; bool allSame = true; foreach (Vector2 corner in roomCorners) { Vector2 dir = (corner - viewPoint).normalized; if (AngleIsBetween(viewRay1.direction, viewRay2.direction, dir)) //If a corner of the room is between the two outer view angles { RaycastHit2D doorHit = Physics2D.Linecast(viewPoint, corner, ViewLayerMask); //Point on the line from the viewsource towards the corner that is on the door. if (doorHit.point == Vector2.zero) { #if UNITY_EDITOR && DEBUG_MODE Debug.DrawRay(viewPoint, viewRay1.direction, Color.yellow); Debug.DrawRay(viewPoint, viewRay2.direction, Color.yellow); Debug.DrawRay(viewPoint, dir, Color.red); //print(viewRay1.direction.x + " | " + viewRay2.direction.x); #endif continue; } CornerHitInfo cornerHit = CheckCorner(doorHit.point + (dir * 0.001f), corner); if (allSame) { vertexInfo.check = AngleIsBetween(str, end, cornerHit.radian) ? 0 : 2; if (vertexInfo.check != lastHit) { allSame = false; lastHit = vertexInfo.check; } } if (cornerHit.cornerIsVisible && !cornerHit.canSeeBeyondCorner) // No relevant hit after hitting a corner { vertexInfo.Vertex = corner; vertexInfo.DoorVertex = doorHit.point; vertices.Add(cornerHit.radian, vertexInfo); #if UNITY_EDITOR debugHit.Addd(vertices[cornerHit.radian].Vertex, Color.red); #endif //debugText.Add(vertices[cornerHit.radian].Vertex, vertices[cornerHit.radian].check.ToString()); } else if (cornerHit.cornerIsVisible && cornerHit.canSeeBeyondCorner) // Relevant hit after hitting a corner { vertexInfo.Vertex = corner; vertexInfo.DoorVertex = doorHit.point; vertices.Add(cornerHit.radian, vertexInfo); //debugText.Add(vertices[cornerHit.radian].Vertex, vertices[cornerHit.radian].check.ToString()); float c = -0.001f; //Shoot at the corner at a slight angle, sort based on if it hits RaycastHit2D sortTest = Physics2D.Raycast(doorHit.point + (dir * 0.1f), positiveAdjustAngle * cornerHit.dir, Vector2.Distance(viewPoint, cornerHit.collisionPoint) + .3f, ViewLayerMask); if (Vector2.Distance(sortTest.point, cornerHit.collisionPoint) < 0.1f) { c = -c; } vertexInfo.Vertex = cornerHit.collisionPoint; vertexInfo.DoorVertex = doorHit.point; vertices.Add(cornerHit.radian + c, vertexInfo); //debugText.Add(vertices[cornerHit.radian + c].Vertex, vertices[cornerHit.radian + c].check.ToString()); #if UNITY_EDITOR debugHit.Addd(vertices[cornerHit.radian].Vertex, Color.magenta); debugHit.Addd(vertices[cornerHit.radian + c].Vertex, Color.yellow); #endif } } } float lastRadius = DirectionToRadius(viewRay2.direction); //r = vertices.ContainsKey(r) ? r+0.0001f : r; vertexInfo.Vertex = hit2.point; vertexInfo.DoorVertex = viewRay2.origin; vertexInfo.check = AngleIsBetween(str, end, lastRadius) ? 0 : 2; if (!vertices.ContainsKey(lastRadius) && vertexInfo.Vertex != Vector2.zero) { vertices.Add(lastRadius, vertexInfo); //debugText.Add(vertices[lastRadius].Vertex, vertices[lastRadius].check.ToString()); } else { //print("ArgumentException: key already present in dictionary. lastRadius: " + lastRadius); return; } if (allSame) { if (vertexInfo.check != lastHit) { allSame = false; lastHit = vertexInfo.check; } } // allSame==false at this point means one part of the vertices is on the start of the radius and the other is at the end if (!allSame) { SortedDictionary <float, VertexInfo> vertices2 = new SortedDictionary <float, VertexInfo>(); foreach (KeyValuePair <float, VertexInfo> kvp in vertices) { if (kvp.Value.Vertex.y > viewPoint.y) { vertices2.Add(kvp.Key + TAU, kvp.Value); } else { vertices2.Add(kvp.Key, kvp.Value); } } vertices = vertices2; } //VertexInfo[] partHits = vertices.Values.ToArray(); Vector3[] Vertices3D = new Vector3[vertices.Values.Count() * 2]; Vector2[] Vertices2D = new Vector2[vertices.Values.Count() * 2]; int i = 0; foreach (VertexInfo info in vertices.Values) { Vertices2D[i] = info.DoorVertex; Vertices3D[i++] = info.DoorVertex; Vertices2D[i] = info.Vertex; Vertices3D[i++] = info.Vertex; } viewMeshes.Add(CreateDoorViewMeshData(Vertices3D)); List <Door> visibleDoors = GetVisibleDoors(viewPoint, viewRay1.direction, viewRay2.direction); foreach (Door nextDoor in visibleDoors) { RayInfo ray1, ray2; GetDoorRays(nextDoor, viewPoint, Vertices2D, out ray1, out ray2, viewRay1.direction, viewRay2.direction, debugHit); #if UNITY_EDITOR debugHit.Addd(ray1.origin, Color.cyan); debugHit.Addd(ray2.origin, Color.blue); #endif if ((ray1.origin == Vector2.zero && ray1.direction == Vector2.zero) || (ray2.origin == Vector2.zero && ray2.direction == Vector2.zero)) { continue; } SetEdgesState(false); nextDoor.adjecentRoom.GetViewsTroughDoor(viewPoint, ray1, ray2, new Door[1] { nextDoor }, ref viewMeshes, ref debugHit, ref debugText, ref previousRooms); SetEdgesState(true); } /*#if UNITY_EDITOR * //if(!allSame) * foreach(KeyValuePair<float, VertexInfo> kvp in vertices){ * if(!debugText.ContainsKey(kvp.Value.Vertex)) * debugText.Add(kvp.Value.Vertex, kvp.Value.check.ToString()+!allSame+kvp.Key); * else * debugText[kvp.Value.Vertex] += kvp.Value.check.ToString()+!allSame+kvp.Key; * } * Debug.DrawLine(viewRay1.origin + viewRay1.direction/10, hit1.point, Color.cyan); * Debug.DrawLine(viewRay2.origin + viewRay2.direction/10, hit2.point, Color.cyan); #endif*/ } //viewMeshes.Add(CreateDoorViewMesh(vertices.Values)); SetEdgesState(false); }