private void OnDrawGizmos() { Gizmos.matrix = transform.localToWorldMatrix; Gizmos.color = Colors.VolumeOutline; Gizmos.DrawWireCube(0.5f * ContainerSize, ContainerSize); Gizmos.color = Colors.VolumeSolid; if (SolidRegions != null) { foreach (var solid in SolidRegions) { Gizmos.DrawCube(0.5f * (solid.Max + solid.Min), solid.Max - solid.Min); } } Gizmos.color = Colors.CellSource; if (Sources != null) { foreach (var source in Sources) { Gizmos.DrawCube(GridStepSize * ((Vector3)Vec3Int.FloorToInt(source.Position / GridStepSize) + Vector3.one * 0.5f), Vector3.one * GridStepSize); } } Gizmos.color = Colors.CellSink; if (Sinks != null) { foreach (var sink in Sinks) { Gizmos.DrawCube(GridStepSize * ((Vector3)Vec3Int.FloorToInt(sink / GridStepSize) + Vector3.one * 0.5f), Vector3.one * GridStepSize); } } }
public void AddSink(Vector3 pos) { var p = Vec3Int.FloorToInt(pos / StepSize); if (!ValidIndex(p)) { throw new IndexOutOfRangeException($"pos {pos} => p {p} is out of bounds"); } CellType[Idx(p)] = CTYPE_SINK; }
public void AddSource(Source source) { var p = Vec3Int.FloorToInt(source.Position / StepSize); if (!ValidIndex(p)) { throw new IndexOutOfRangeException($"pos {source.Position} => p {p} is out of bounds"); } CellType[Idx(p)] = CTYPE_SOURCE; sources.Add(p, source); }
public static float LerpCenters(MacGrid g, float[] q, Vector3 pos) { Vec3Int p0 = Vec3Int.FloorToInt(pos); // Because we're using grid coordinates here, not fluid space, we can rely on the // fact the spacing (on one axis) between two samples values is always 1. Vector3 alpha = pos - p0; // This is just simple trilinear interpolation, written out in full. float q00 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y, p0.z)] + alpha.x * q[g.Idx(p0.x + 1, p0.y, p0.z)]; float q10 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y + 1, p0.z)] + alpha.x * q[g.Idx(p0.x + 1, p0.y + 1, p0.z)]; float q01 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y, p0.z + 1)] + alpha.x * q[g.Idx(p0.x + 1, p0.y, p0.z + 1)]; float q11 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y + 1, p0.z + 1)] + alpha.x * q[g.Idx(p0.x + 1, p0.y + 1, p0.z + 1)]; float q0 = (1f - alpha.y) * q00 + alpha.y * q10; float q1 = (1f - alpha.y) * q01 + alpha.y * q11; return((1f - alpha.z) * q0 + alpha.z * q1); }
public MacGrid(Vector3 size, float step) { Size = size; StepSize = step; GridSize = Vec3Int.FloorToInt(Size / StepSize); Pressure = new float[GridSize.x * GridSize.y * GridSize.z]; VelocityX = new float[(GridSize.x + 1) * GridSize.y * GridSize.z]; VelocityY = new float[GridSize.x * (GridSize.y + 1) * GridSize.z]; VelocityZ = new float[GridSize.x * GridSize.y * (GridSize.z + 1)]; CellType = new byte[GridSize.x * GridSize.y * GridSize.z]; sources = new Dictionary <Vec3Int, Source>(); PressureNext = new float[GridSize.x * GridSize.y * GridSize.z]; VelocityNextX = new float[(GridSize.x + 1) * GridSize.y * GridSize.z]; VelocityNextY = new float[GridSize.x * (GridSize.y + 1) * GridSize.z]; VelocityNextZ = new float[GridSize.x * GridSize.y * (GridSize.z + 1)]; }
// Only one of the stagger flags can be set! public static float Lerp(MacGrid g, float[] q, Vector3 pos, bool staggerX = false, bool staggerY = false, bool staggerZ = false) { Vec3Int staggerAdjustment; if (staggerX) { staggerAdjustment = Vec3Int.right; } else if (staggerY) { staggerAdjustment = Vec3Int.up; } else if (staggerZ) { staggerAdjustment = Vec3Int.forward; } else { staggerAdjustment = Vec3Int.zero; } // p0 gives us the array-coordinates of lower-back-left sample point next to the given pos. Vec3Int p0 = Vec3Int.FloorToInt(pos - staggerAdjustment * 0.5f) + staggerAdjustment; // The actual position in grid coordinates is as above but with 0.5f * staggerAdjustment added on the end: // p0 is correct for indexing to the array, but the staggering causes a mismatch between indices and coordinates. // Because we're using grid based coordinates here, not fluid space, we can rely on the // fact the spacing (on one axis) between two samples values is always 1. Vector3 alpha = pos - p0 - staggerAdjustment * 0.5f; // This is just simple trilinear interpolation, written out in full. float q00 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y, p0.z)] + alpha.x * q[g.Idx(p0.x + 1, p0.y, p0.z)]; float q10 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y + 1, p0.z)] + alpha.x * q[g.Idx(p0.x + 1, p0.y + 1, p0.z)]; float q01 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y, p0.z + 1)] + alpha.x * q[g.Idx(p0.x + 1, p0.y, p0.z + 1)]; float q11 = (1f - alpha.x) * q[g.Idx(p0.x, p0.y + 1, p0.z + 1)] + alpha.x * q[g.Idx(p0.x + 1, p0.y + 1, p0.z + 1)]; float q0 = (1f - alpha.y) * q00 + alpha.y * q10; float q1 = (1f - alpha.y) * q01 + alpha.y * q11; return((1f - alpha.z) * q0 + alpha.z * q1); }