254 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			254 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | namespace Fusion.Addons.InterestManagement | |||
|  | { | |||
|  | 	using System.Collections.Generic; | |||
|  | 	using UnityEngine; | |||
|  | 
 | |||
|  | 	/// <summary> | |||
|  | 	/// Contains helper methods related to interest cone. | |||
|  | 	/// </summary> | |||
|  | 	public static class InterestConeUtility | |||
|  | 	{ | |||
|  | 		// PUBLIC METHODS | |||
|  | 
 | |||
|  | 		/// <summary> | |||
|  | 		/// Converts cone to Fusion interest cell coordinate system. | |||
|  | 		/// </summary> | |||
|  | 		public static void GetCells(Vector3 position, Quaternion rotation, float length, Vector2 startSize, Vector2 endSize, Vector2 minSize, Vector2 maxSize, HashSet<int> cells) | |||
|  | 		{ | |||
|  | 			if (length <= 0.0f) | |||
|  | 				return; | |||
|  | 
 | |||
|  | 			if (startSize.x < 0.0f) startSize.x = 0.0f; | |||
|  | 			if (startSize.y < 0.0f) startSize.y = 0.0f; | |||
|  | 
 | |||
|  | 			if (endSize.x < 0.0f) endSize.x = 0.0f; | |||
|  | 			if (endSize.y < 0.0f) endSize.y = 0.0f; | |||
|  | 
 | |||
|  | 			if (minSize.x <= 0.0f) { minSize.x = Mathf.Min(startSize.x, endSize.x); } | |||
|  | 			if (minSize.y <= 0.0f) { minSize.y = Mathf.Min(startSize.y, endSize.y); } | |||
|  | 
 | |||
|  | 			if (maxSize.x <= 0.0f) { maxSize.x = Mathf.Max(startSize.x, endSize.x); } | |||
|  | 			if (maxSize.y <= 0.0f) { maxSize.y = Mathf.Max(startSize.y, endSize.y); } | |||
|  | 
 | |||
|  | 			if (maxSize.x < minSize.x) { maxSize.x = minSize.x; } | |||
|  | 			if (maxSize.y < minSize.y) { maxSize.y = minSize.y; } | |||
|  | 
 | |||
|  | 			var   gridSize    = Simulation.AreaOfInterest.GetGridSize(); | |||
|  | 			int   gridSizeX   = gridSize.Item1; | |||
|  | 			int   gridSizeY   = gridSize.Item2; | |||
|  | 			int   gridSizeZ   = gridSize.Item3; | |||
|  | 			int   gridHalfX   = gridSizeX / 2; | |||
|  | 			int   gridHalfY   = gridSizeY / 2; | |||
|  | 			int   gridHalfZ   = gridSizeZ / 2; | |||
|  | 			int   cellSize    = Simulation.AreaOfInterest.GetCellSize(); | |||
|  | 			int   cellHalf    = cellSize / 2; | |||
|  | 			float cellInv     = 1.0f / cellSize; | |||
|  | 			float maxStepSize = cellHalf * InterestUtility.SQRT2; | |||
|  | 
 | |||
|  | 			Vector3 forward = rotation * Vector3.forward; | |||
|  | 			Vector3 right   = rotation * Vector3.right; | |||
|  | 			Vector3 up      = rotation * Vector3.up; | |||
|  | 
 | |||
|  | 			int     zSteps = (int)(length / maxStepSize) + 1; | |||
|  | 			Vector3 zStep  = forward * length / zSteps; | |||
|  | 			float   zInv   = 1.0f / zSteps; | |||
|  | 
 | |||
|  | 			for (int z = 0; z <= zSteps; ++z) | |||
|  | 			{ | |||
|  | 				float zAlpha = z * zInv; | |||
|  | 
 | |||
|  | 				float   yLength = Mathf.Clamp(Mathf.LerpUnclamped(startSize.y, endSize.y, zAlpha), minSize.y, maxSize.y); | |||
|  | 				int     ySteps  = (int)(yLength / maxStepSize) + 1; | |||
|  | 				Vector3 yStep   = up * yLength / ySteps; | |||
|  | 
 | |||
|  | 				float   xLength = Mathf.Clamp(Mathf.LerpUnclamped(startSize.x, endSize.x, zAlpha), minSize.x, maxSize.x); | |||
|  | 				int     xSteps  = (int)(xLength / maxStepSize) + 1; | |||
|  | 				Vector3 xStep   = right * xLength / xSteps; | |||
|  | 
 | |||
|  | 				Vector3 basePosition = position + zStep * z - 0.5f * (yStep * ySteps + xStep * xSteps); | |||
|  | 
 | |||
|  | 				for (int y = 0; y <= ySteps; ++y) | |||
|  | 				{ | |||
|  | 					Vector3 checkPosition = basePosition + yStep * y; | |||
|  | 
 | |||
|  | 					for (int x = 0; x <= xSteps; ++x) | |||
|  | 					{ | |||
|  | 						int x1 = gridHalfX + (int)(checkPosition.x * cellInv); | |||
|  | 						int y1 = gridHalfY + (int)(checkPosition.y * cellInv); | |||
|  | 						int z1 = gridHalfZ + (int)(checkPosition.z * cellInv); | |||
|  | 
 | |||
|  | 						if (checkPosition.x < 0.0f) { x1 -= 1; } | |||
|  | 						if (checkPosition.y < 0.0f) { y1 -= 1; } | |||
|  | 						if (checkPosition.z < 0.0f) { z1 -= 1; } | |||
|  | 
 | |||
|  | 						if (x1 < 0) { x1 = 0; } else if (x1 >= gridSizeX) { x1 = gridSizeX - 1; } | |||
|  | 						if (y1 < 0) { y1 = 0; } else if (y1 >= gridSizeY) { y1 = gridSizeY - 1; } | |||
|  | 						if (z1 < 0) { z1 = 0; } else if (z1 >= gridSizeZ) { z1 = gridSizeZ - 1; } | |||
|  | 
 | |||
|  | 						int cell = z1 * gridSizeY * gridSizeX + y1 * gridSizeX + x1 + 1; | |||
|  | 						cells.Add(cell); | |||
|  | 
 | |||
|  | 						checkPosition += xStep; | |||
|  | 					} | |||
|  | 				} | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		/// <summary> | |||
|  | 		/// Draws interest cone gizmo. | |||
|  | 		/// </summary> | |||
|  | 		public static void DrawGizmo(Vector3 position, Quaternion rotation, float length, Vector2 startSize, Vector2 endSize, Vector2 minSize, Vector2 maxSize, Color color, bool drawIcon = true) | |||
|  | 		{ | |||
|  | 			if (length <= 0.0f) | |||
|  | 				return; | |||
|  | 
 | |||
|  | 			Color gizmoColor = Gizmos.color; | |||
|  | 			Gizmos.color = color; | |||
|  | 
 | |||
|  | 			if (drawIcon == true) | |||
|  | 			{ | |||
|  | 				Gizmos.DrawIcon(position, "d_ViewToolOrbit On@2x"); | |||
|  | 			} | |||
|  | 
 | |||
|  | 			Vector3 centerPosition = position; | |||
|  | 
 | |||
|  | 			Vector3 forward = rotation * Vector3.forward; | |||
|  | 			Vector3 right   = rotation * Vector3.right; | |||
|  | 			Vector3 up      = rotation * Vector3.up; | |||
|  | 
 | |||
|  | 			Vector3 rightOffset = right * startSize.x * 0.5f; | |||
|  | 			Vector3 upOffset    = up    * startSize.y * 0.5f; | |||
|  | 
 | |||
|  | 			Vector3 point00 = centerPosition + upOffset - rightOffset; | |||
|  | 			Vector3 point01 = centerPosition + upOffset + rightOffset; | |||
|  | 			Vector3 point02 = centerPosition - upOffset - rightOffset; | |||
|  | 			Vector3 point03 = centerPosition - upOffset + rightOffset; | |||
|  | 
 | |||
|  | 			centerPosition += forward * length; | |||
|  | 
 | |||
|  | 			rightOffset = right * endSize.x * 0.5f; | |||
|  | 			upOffset    = up    * endSize.y * 0.5f; | |||
|  | 
 | |||
|  | 			Vector3 point10 = centerPosition + upOffset - rightOffset; | |||
|  | 			Vector3 point11 = centerPosition + upOffset + rightOffset; | |||
|  | 			Vector3 point12 = centerPosition - upOffset - rightOffset; | |||
|  | 			Vector3 point13 = centerPosition - upOffset + rightOffset; | |||
|  | 
 | |||
|  | 			Gizmos.DrawLine(point10, point11); | |||
|  | 			Gizmos.DrawLine(point11, point13); | |||
|  | 			Gizmos.DrawLine(point13, point12); | |||
|  | 			Gizmos.DrawLine(point12, point10); | |||
|  | 
 | |||
|  | 			Gizmos.DrawLine(point00, point10); | |||
|  | 			Gizmos.DrawLine(point01, point11); | |||
|  | 			Gizmos.DrawLine(point02, point12); | |||
|  | 			Gizmos.DrawLine(point03, point13); | |||
|  | 
 | |||
|  | 			Gizmos.DrawLine(point00, point01); | |||
|  | 			Gizmos.DrawLine(point01, point03); | |||
|  | 			Gizmos.DrawLine(point03, point02); | |||
|  | 			Gizmos.DrawLine(point02, point00); | |||
|  | 
 | |||
|  | 			if (InterestUtility.DrawSamplePositions == true) | |||
|  | 			{ | |||
|  | 				DrawSamplePositions(position, rotation, length, startSize, endSize, minSize, maxSize); | |||
|  | 			} | |||
|  | 
 | |||
|  | 			Gizmos.color = gizmoColor; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		/// <summary> | |||
|  | 		/// Draws positions that are sampled when resolving interest cells. | |||
|  | 		/// </summary> | |||
|  | 		public static void DrawSamplePositions(Vector3 position, Quaternion rotation, float length, Vector2 startSize, Vector2 endSize, Vector2 minSize, Vector2 maxSize) | |||
|  | 		{ | |||
|  | 			if (length <= 0.0f) | |||
|  | 				return; | |||
|  | 
 | |||
|  | 			if (startSize.x < 0.0f) startSize.x = 0.0f; | |||
|  | 			if (startSize.y < 0.0f) startSize.y = 0.0f; | |||
|  | 
 | |||
|  | 			if (endSize.x < 0.0f) endSize.x = 0.0f; | |||
|  | 			if (endSize.y < 0.0f) endSize.y = 0.0f; | |||
|  | 
 | |||
|  | 			if (minSize.x <= 0.0f) { minSize.x = Mathf.Min(startSize.x, endSize.x); } | |||
|  | 			if (minSize.y <= 0.0f) { minSize.y = Mathf.Min(startSize.y, endSize.y); } | |||
|  | 
 | |||
|  | 			if (maxSize.x <= 0.0f) { maxSize.x = Mathf.Max(startSize.x, endSize.x); } | |||
|  | 			if (maxSize.y <= 0.0f) { maxSize.y = Mathf.Max(startSize.y, endSize.y); } | |||
|  | 
 | |||
|  | 			if (maxSize.x < minSize.x) { maxSize.x = minSize.x; } | |||
|  | 			if (maxSize.y < minSize.y) { maxSize.y = minSize.y; } | |||
|  | 
 | |||
|  | 			var   gridSize    = Simulation.AreaOfInterest.GetGridSize(); | |||
|  | 			int   gridSizeX   = gridSize.Item1; | |||
|  | 			int   gridSizeY   = gridSize.Item2; | |||
|  | 			int   gridSizeZ   = gridSize.Item3; | |||
|  | 			int   gridHalfX   = gridSizeX / 2; | |||
|  | 			int   gridHalfY   = gridSizeY / 2; | |||
|  | 			int   gridHalfZ   = gridSizeZ / 2; | |||
|  | 			int   cellSize    = Simulation.AreaOfInterest.GetCellSize(); | |||
|  | 			int   cellHalf    = cellSize / 2; | |||
|  | 			float cellInv     = 1.0f / cellSize; | |||
|  | 			float maxStepSize = cellHalf * InterestUtility.SQRT2; | |||
|  | 
 | |||
|  | 			Vector3 forward = rotation * Vector3.forward; | |||
|  | 			Vector3 right   = rotation * Vector3.right; | |||
|  | 			Vector3 up      = rotation * Vector3.up; | |||
|  | 
 | |||
|  | 			int     zSteps = (int)(length / maxStepSize) + 1; | |||
|  | 			Vector3 zStep  = forward * length / zSteps; | |||
|  | 			float   zInv   = 1.0f / zSteps; | |||
|  | 
 | |||
|  | 			Color gizmoColor = Gizmos.color; | |||
|  | 			Gizmos.color = Color.red; | |||
|  | 
 | |||
|  | 			for (int z = 0; z <= zSteps; ++z) | |||
|  | 			{ | |||
|  | 				float zAlpha = z * zInv; | |||
|  | 
 | |||
|  | 				float   yLength = Mathf.Clamp(Mathf.LerpUnclamped(startSize.y, endSize.y, zAlpha), minSize.y, maxSize.y); | |||
|  | 				int     ySteps  = (int)(yLength / maxStepSize) + 1; | |||
|  | 				Vector3 yStep   = up * yLength / ySteps; | |||
|  | 
 | |||
|  | 				float   xLength = Mathf.Clamp(Mathf.LerpUnclamped(startSize.x, endSize.x, zAlpha), minSize.x, maxSize.x); | |||
|  | 				int     xSteps  = (int)(xLength / maxStepSize) + 1; | |||
|  | 				Vector3 xStep   = right * xLength / xSteps; | |||
|  | 
 | |||
|  | 				Vector3 basePosition = position + zStep * z - 0.5f * (yStep * ySteps + xStep * xSteps); | |||
|  | 
 | |||
|  | 				for (int y = 0; y <= ySteps; ++y) | |||
|  | 				{ | |||
|  | 					Vector3 checkPosition = basePosition + yStep * y; | |||
|  | 
 | |||
|  | 					for (int x = 0; x <= xSteps; ++x) | |||
|  | 					{ | |||
|  | 						Gizmos.DrawSphere(checkPosition, cellSize * 0.05f); | |||
|  | 
 | |||
|  | 						int x1 = gridHalfX + (int)(checkPosition.x * cellInv); | |||
|  | 						int y1 = gridHalfY + (int)(checkPosition.y * cellInv); | |||
|  | 						int z1 = gridHalfZ + (int)(checkPosition.z * cellInv); | |||
|  | 
 | |||
|  | 						if (checkPosition.x < 0.0f) { x1 -= 1; } | |||
|  | 						if (checkPosition.y < 0.0f) { y1 -= 1; } | |||
|  | 						if (checkPosition.z < 0.0f) { z1 -= 1; } | |||
|  | 
 | |||
|  | 						if (x1 < 0) { x1 = 0; } else if (x1 >= gridSizeX) { x1 = gridSizeX - 1; } | |||
|  | 						if (y1 < 0) { y1 = 0; } else if (y1 >= gridSizeY) { y1 = gridSizeY - 1; } | |||
|  | 						if (z1 < 0) { z1 = 0; } else if (z1 >= gridSizeZ) { z1 = gridSizeZ - 1; } | |||
|  | 
 | |||
|  | 						Vector3 cellPosition = default; | |||
|  | 						cellPosition.x = (x1 - gridHalfX) * cellSize + cellHalf; | |||
|  | 						cellPosition.y = (y1 - gridHalfY) * cellSize + cellHalf; | |||
|  | 						cellPosition.z = (z1 - gridHalfZ) * cellSize + cellHalf; | |||
|  | 
 | |||
|  | 						checkPosition += xStep; | |||
|  | 					} | |||
|  | 				} | |||
|  | 			} | |||
|  | 
 | |||
|  | 			Gizmos.color = gizmoColor; | |||
|  | 		} | |||
|  | 	} | |||
|  | } |