using System;
using System.Collections.Generic;
using nkast.Aether.Physics2D.Common;
using tainicom.Aether.Physics2D.Fluids;
namespace CtrEditor.Simulacion.Fluids
{
///
/// Clase principal que gestiona la simulación de fluidos basada en FluidSystem2
///
public class SimulacionFluidos
{
public FluidSystem2 SistemaFluido { get; private set; }
private List _contenedores = new List();
private int _worldWidth;
private int _worldHeight;
public int ParticlesCount => SistemaFluido?.ParticlesCount ?? 0;
///
/// Constructor para el sistema de simulación de fluidos
///
/// Ancho del área de simulación en metros
/// Alto del área de simulación en metros
/// Número máximo de partículas
/// Vector de gravedad
public SimulacionFluidos(float ancho, float alto, int maxParticulas, Vector2 gravedad)
{
// Convertir parámetros a unidades internas de FluidSystem2
_worldWidth = (int)(ancho * 100); // Convertir a cm
_worldHeight = (int)(alto * 100); // Convertir a cm
// Inicializar el sistema
SistemaFluido = new FluidSystem2(
gravedad,
maxParticulas,
_worldWidth,
_worldHeight
);
// Configurar comportamiento del fluido
SistemaFluido.ElasticityEnabled = true;
SistemaFluido.PlasticityEnabled = true;
}
///
/// Método para agregar una partícula al sistema
///
/// Posición en metros
public void AgregarParticula(Vector2 posicion)
{
// Convertir a sistema de coordenadas de FluidSystem2
float xAjustado = posicion.X * 100 - _worldWidth/2;
float yAjustado = posicion.Y * 100;
SistemaFluido.AddParticle(new Vector2(xAjustado, yAjustado));
}
///
/// Agrega múltiples partículas en un área rectangular
///
/// Centro del área
/// Ancho del área
/// Alto del área
/// Cantidad de partículas a agregar
public void AgregarParticulasEnArea(Vector2 centro, float ancho, float alto, int cantidad)
{
Random rnd = new Random();
for (int i = 0; i < cantidad; i++)
{
float x = centro.X - ancho/2 + (float)rnd.NextDouble() * ancho;
float y = centro.Y - alto/2 + (float)rnd.NextDouble() * alto;
AgregarParticula(new Vector2(x, y));
}
}
///
/// Agrega un contenedor al sistema de fluidos
///
/// Implementación de IContenedorFluido
public void AgregarContenedor(IContenedorFluido contenedor)
{
_contenedores.Add(contenedor);
}
///
/// Elimina un contenedor del sistema de fluidos
///
/// Contenedor a eliminar
public void RemoverContenedor(IContenedorFluido contenedor)
{
_contenedores.Remove(contenedor);
}
///
/// Actualiza la simulación avanzando un paso de tiempo
///
/// Tiempo transcurrido en segundos
public void Actualizar(float deltaTime)
{
// Aplicar restricciones de contenedores personalizados
foreach (var contenedor in _contenedores)
{
for (int i = 0; i < SistemaFluido.ParticlesCount; i++)
{
var particula = SistemaFluido.Particles[i];
contenedor.RestringirParticula(particula);
}
}
// Actualizar la física del sistema de fluidos
SistemaFluido.Update(deltaTime);
}
///
/// Obtiene la densidad del fluido en una posición específica
///
/// Posición en metros
/// Densidad relativa de fluido (0-1)
public float ObtenerDensidadEnPosicion(Vector2 posicion)
{
// Convertir a sistema de coordenadas de FluidSystem2
float xAjustado = posicion.X * 100 - _worldWidth/2;
float yAjustado = posicion.Y * 100;
Vector2 posAjustada = new Vector2(xAjustado, yAjustado);
float densidadTotal = 0;
int particulasCercanas = 0;
// Buscar partículas cercanas y sumar sus densidades
foreach (var p in SistemaFluido.Particles)
{
float distancia = Vector2.Distance(posAjustada, p.Position);
if (distancia < FluidSystem2.InfluenceRadius)
{
densidadTotal += p.Density;
particulasCercanas++;
}
}
// Calcular densidad promedio, normalizada
if (particulasCercanas > 0)
return Math.Min(1.0f, densidadTotal / (particulasCercanas * FluidSystem2.DensityRest * 1.5f));
return 0;
}
///
/// Ajusta la gravedad del sistema
///
/// Nuevo vector de gravedad
public void AjustarGravedad(Vector2 gravedad)
{
SistemaFluido.Gravity = gravedad;
}
///
/// Limpia todas las partículas del sistema
///
public void LimpiarParticulas()
{
// No hay método clear() directo en FluidSystem2, recreamos el sistema
SistemaFluido = new FluidSystem2(
SistemaFluido.Gravity,
SistemaFluido.MaxParticleLimit,
_worldWidth,
_worldHeight
);
// Restaurar configuración
SistemaFluido.ElasticityEnabled = true;
SistemaFluido.PlasticityEnabled = true;
}
}
///
/// Interfaz para contenedores de fluido personalizados como tubos, tanques, etc.
///
public interface IContenedorFluido
{
///
/// Aplica restricciones a una partícula para mantenerla dentro o fuera del contenedor
///
void RestringirParticula(Particle particula);
}
}