191 lines
7.1 KiB
C#
191 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using nkast.Aether.Physics2D.Common;
|
|
using tainicom.Aether.Physics2D.Fluids;
|
|
using CtrEditor.Simulacion.Fluids.Components;
|
|
|
|
namespace CtrEditor.Simulacion.Fluids
|
|
{
|
|
/// <summary>
|
|
/// Clase principal que gestiona la simulación de fluidos basada en FluidSystem2
|
|
/// </summary>
|
|
public class SimulacionFluidos
|
|
{
|
|
public FluidSystem2 SistemaFluido { get; private set; }
|
|
private List<IContenedorFluido> _contenedores = new List<IContenedorFluido>();
|
|
private int _worldWidth;
|
|
private int _worldHeight;
|
|
|
|
public int ParticlesCount => SistemaFluido?.ParticlesCount ?? 0;
|
|
|
|
/// <summary>
|
|
/// Constructor para el sistema de simulación de fluidos
|
|
/// </summary>
|
|
/// <param name="ancho">Ancho del área de simulación en metros</param>
|
|
/// <param name="alto">Alto del área de simulación en metros</param>
|
|
/// <param name="maxParticulas">Número máximo de partículas</param>
|
|
/// <param name="gravedad">Vector de gravedad</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Método para agregar una partícula al sistema
|
|
/// </summary>
|
|
/// <param name="posicion">Posición en metros</param>
|
|
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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Agrega múltiples partículas en un área rectangular
|
|
/// </summary>
|
|
/// <param name="centro">Centro del área</param>
|
|
/// <param name="ancho">Ancho del área</param>
|
|
/// <param name="alto">Alto del área</param>
|
|
/// <param name="cantidad">Cantidad de partículas a agregar</param>
|
|
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));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Agrega un contenedor al sistema de fluidos
|
|
/// </summary>
|
|
/// <param name="contenedor">Implementación de IContenedorFluido</param>
|
|
public void AgregarContenedor(IContenedorFluido contenedor)
|
|
{
|
|
_contenedores.Add(contenedor);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina un contenedor del sistema de fluidos
|
|
/// </summary>
|
|
/// <param name="contenedor">Contenedor a eliminar</param>
|
|
public void RemoverContenedor(IContenedorFluido contenedor)
|
|
{
|
|
_contenedores.Remove(contenedor);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Actualiza la simulación avanzando un paso de tiempo
|
|
/// </summary>
|
|
/// <param name="deltaTime">Tiempo transcurrido en segundos</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtiene la densidad del fluido en una posición específica
|
|
/// </summary>
|
|
/// <param name="posicion">Posición en metros</param>
|
|
/// <returns>Densidad relativa de fluido (0-1)</returns>
|
|
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 posAjustadaRef = posAjustada;
|
|
Vector2 positionRef = p.Position;
|
|
Vector2.Distance(ref posAjustadaRef, ref positionRef, out distancia);
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ajusta la gravedad del sistema
|
|
/// </summary>
|
|
/// <param name="gravedad">Nuevo vector de gravedad</param>
|
|
public void AjustarGravedad(Vector2 gravedad)
|
|
{
|
|
SistemaFluido.Gravity = gravedad;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Limpia todas las partículas del sistema
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Interfaz para contenedores de fluido personalizados como tubos, tanques, etc.
|
|
/// </summary>
|
|
public interface IContenedorFluido
|
|
{
|
|
/// <summary>
|
|
/// Aplica restricciones a una partícula para mantenerla dentro o fuera del contenedor
|
|
/// </summary>
|
|
void RestringirParticula(Particle particula);
|
|
}
|
|
}
|