private static List <ScanResultLOD> GetCenterPointList( Transform transform, GameObjectShape shape) { // Single ScanResultLOD for lowest LOD. var result = ScanResultLOD.CreateList(1); Matrix4x4 matrix = transform.worldToLocalMatrix; bool flatten = shape.Flatten; foreach (Volume vol in s_Volumes) { Vector3 localPoint = matrix.MultiplyPoint3x4(vol.Bounds.center); if (flatten) { localPoint.y = 0; } result[0].LocalPoints.Add(localPoint); } return(result); }
private static List <ScanResultLOD> GetLODPointLists( PhysicsScene scene, Transform transform, GameObjectShape shape) { SplitVolumesIntoCells(shape.ScanLOD); int mask = 1 << transform.gameObject.layer; bool flatten = shape.Flatten; var result = ScanResultLOD.CreateList(flatten ? 1 : s_GlobalMaxLOD + 1); foreach (Volume vol in s_Volumes) { ToggleActiveColliders(vol); bool isConcave = vol.IsConcave; Vector3 cellSize = vol.CellSize; Vector3Int gridSize = vol.GridSize; Vector3 offset = vol.Bounds.min + cellSize * 0.5f; Vector3 boundsCenter = vol.Bounds.center; float boundsMagnitude = vol.Bounds.size.magnitude; int nx = gridSize.x - 1; int ny = gridSize.y - 1; int nz = gridSize.z - 1; // Find cells occupied by colliders. Clear(gridSize); for (int x = 0; x <= nx; x++) { for (int y = 0; y <= ny; y++) { for (int z = 0; z <= nz; z++) { Vector3 worldPoint = Vector3.Scale( new Vector3(x, y, z), cellSize) + offset; bool isInside = isConcave ? IsInsideCollider( scene, mask, worldPoint, vol.Bounds) : IsInsideCollider( scene, mask, worldPoint, vol.Colliders); s_HollowGrid[x, y, z] = isInside; s_FilledGrid[x, y, z] = isInside; } } } // Reduce cell count, hollow out filled grid. for (int x = 1; x < nx; x++) { for (int y = 1; y < ny; y++) { for (int z = 1; z < nz; z++) { if (s_FilledGrid[x, y, z]) { s_HollowGrid[x, y, z] &= !(s_FilledGrid[x - 1, y, z] & s_FilledGrid[x + 1, y, z] & s_FilledGrid[x, y - 1, z] & s_FilledGrid[x, y + 1, z] & s_FilledGrid[x, y, z - 1] & s_FilledGrid[x, y, z + 1]); } } } } // Downsample cells for generating LODs // and store points in corresponding groups. int level = flatten ? 0 : vol.MaxLOD; float yFlat = transform.position.y; for (int x = 0; x <= nx; x++) { for (int y = 0; y <= ny; y++) { for (int z = 0; z <= nz; z++) { if (s_HollowGrid[x, y, z]) { Cell cell = new Cell(level, x, y, z); Vector3 worldPoint = cell.Scale(cellSize) + offset; if (flatten) { cell.y = 0; worldPoint.y = yFlat; } // Highest LOD. AddPoint(cell, worldPoint); for (int i = level; i > 0; i--) { cell = cell.Downsample(); AddPoint(cell, worldPoint); } } } } } // Write centroids to result. Matrix4x4 matrix = transform.worldToLocalMatrix; float projection = shape.Projection; bool project = projection > 0; foreach (var kvp in s_PointGroupsByCell) { // KeyValuePair, Key: Cell, Value: PointGroup. int i = kvp.Key.level; Vector3 worldPoint = kvp.Value.Centroid; if (project && i > 0) { // Project outward from volume bounds center, // unless lowest LOD or flattened points -> i == 0. // NOTE Doesn't work well with compound or concave colliders. Vector3 normal = (worldPoint - boundsCenter).normalized; if (scene.Raycast(boundsCenter + normal * boundsMagnitude, -normal, out RaycastHit hit, boundsMagnitude, mask)) { worldPoint = Vector3.Lerp(worldPoint, hit.point, projection); } } // World -> local. result[i].LocalPoints.Add(matrix.MultiplyPoint3x4(worldPoint)); } } ToggleActiveColliders(); return(result); }