public void Add(FluidCell cell) { var cellHash = m_mappingFunction(cell.X, cell.Y, cell.Z); if (CellDictionary.ContainsKey(cellHash)) { var existingCell = CellDictionary[cellHash]; if (existingCell.Type != FluidCell.CellType.Solid) { existingCell.Level += cell.Level; existingCell.LevelNextStep += cell.Level; if (existingCell.LevelNextStep > FluidCell.MinLevel && existingCell.Type == FluidCell.CellType.Air) { existingCell.Type = FluidCell.CellType.Water; Cells.Add(existingCell); BuildNeighborhood(existingCell); RecalculateBounds(existingCell); } } } else { cell.UpdateCells = Updated; Cells.Add(cell); CellDictionary.Add(cellHash, cell); BuildNeighborhood(cell); RecalculateBounds(cell); } Update = true; }
//TODO : make a physics thread and put this on it public FluidSimulation(MappingFunction mappingFunction, Block[] blocks) { m_mappingFunction = mappingFunction; m_blocks = blocks; m_containers = new List<FluidContainer>(); m_solidCell = new FluidCell(FluidCell.CellType.Solid); m_addQueue = new Queue<List<FluidCell>>(); m_cellAccumulator = new List<FluidCell>(); }
public FluidContainer(MappingFunction mappingFunction, Block[] blocks, FluidCell solidCellReference) { m_mappingFunction = mappingFunction; m_blocks = blocks; m_solidCellReference = solidCellReference; Update = true; Alive = true; m_min = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue); m_max = new Vector3Int(-int.MaxValue, -int.MaxValue, -int.MaxValue); Cells = new List<FluidCell>(); CellDictionary = new Dictionary<long, FluidCell>(); Updated = new List<FluidCell>(); }
public void BuildNeighborhood(FluidCell cell) { cell.Up = GetOrCreateCell(cell.X, cell.Y + 1, cell.Z); cell.Up.Down = cell; cell.Down = GetOrCreateCell(cell.X, cell.Y - 1, cell.Z); cell.Down.Up = cell; cell.North = GetOrCreateCell(cell.X, cell.Y, cell.Z + 1); cell.North.South = cell; cell.East = GetOrCreateCell(cell.X + 1, cell.Y, cell.Z); cell.East.West = cell; cell.South = GetOrCreateCell(cell.X, cell.Y, cell.Z - 1); cell.South.North = cell; cell.West = GetOrCreateCell(cell.X - 1, cell.Y, cell.Z); cell.West.East = cell; }
public void AddFluidAt(int x, int y, int z,float amount, bool isSource) { if (!(amount > 0)) { return; } var cell = new FluidCell(x, y, z, FluidCell.CellType.Water, amount) {IsSource = isSource}; foreach (var existing in m_cellAccumulator) { if (existing.X != cell.X || existing.Y != cell.Y || existing.Z != cell.Z) { continue; } existing.LevelNextStep = MathHelper.Clamp(existing.LevelNextStep + amount, 0 , 1); existing.Level = existing.LevelNextStep; cell = null; break; } if (cell != null) { m_cellAccumulator.Add(cell); } }
public bool Contains(FluidCell cell) { return Contains(cell.X, cell.Y, cell.Z); }
private void RecalculateBounds(FluidCell cell) { if (cell.X > m_max.X) { m_max.X = cell.X + 1; } if (cell.X < m_min.X) { m_min.X = cell.X - 1; } if (cell.Y > m_max.Y) { m_max.Y = cell.Y + 1; } if (cell.Y < m_min.Y) { m_min.Y = cell.Y - 1; } if (cell.Z > m_max.Z) { m_max.Z = cell.Z + 1; } if (cell.Z < m_min.Z) { m_min.Z = cell.Z - 1; } }
private FluidCell GetOrCreateCell(int x, int y, int z) { FluidCell cell; var cellHash = m_mappingFunction(x, y, z); var block = m_blocks[cellHash].Type; if (block != 0) { cell = m_solidCellReference; } else { if (CellDictionary.ContainsKey(cellHash)) { cell = CellDictionary[cellHash]; } else { cell = new FluidCell(x, y, z, FluidCell.CellType.Air, 0) {UpdateCells = Updated}; CellDictionary.Add(cellHash, cell); } } return cell; }