namespace Fusion.Addons.InterestManagement { using System.Collections.Generic; using UnityEngine; /// /// Contains helper methods related to interest cone. /// public static class InterestConeUtility { // PUBLIC METHODS /// /// Converts cone to Fusion interest cell coordinate system. /// public static void GetCells(Vector3 position, Quaternion rotation, float length, Vector2 startSize, Vector2 endSize, Vector2 minSize, Vector2 maxSize, HashSet 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; } } } } /// /// Draws interest cone gizmo. /// 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; } /// /// Draws positions that are sampled when resolving interest cells. /// 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; } } }