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); } }