Se implementó un sistema para controlar la presión y evitar que las botellas floten en la simulación. Ahora, las botellas registran su última altura de contacto con transportes y ajustan su posición Z si no están en contacto durante varios frames. Además, se centraron las botellas en el eje longitudinal de los transportes al entrar en contacto con transportes de frenado. Se añadieron nuevas propiedades en simBotella para gestionar la presión y el estado de contacto.

This commit is contained in:
Miguel 2025-07-05 18:43:28 +02:00
parent 71c08d8047
commit c91b1419b4
4 changed files with 125 additions and 5 deletions

View File

@ -1,4 +1,4 @@
---
alwaysApply: true
---
Quisiera que con los conocimientos importantes y desiciones importantes que hemos adquirido y utilizado los agregues a @MemoriadeEvolucion.md manteniendo el estilo que ya tenemos de texto simple sin demasiado codigo y una semantica resumida.
Quisiera que con los conocimientos importantes y desiciones importantes que hemos adquirido y utilizado los agregues a Documentation\MemoriadeEvolucion.md manteniendo el estilo que ya tenemos de texto simple sin demasiado codigo y una semantica resumida.

View File

@ -6,6 +6,9 @@ simBase : Clase base que da un marco a el resto de los objetos
simBarrera : Simula una fotocelula con un espejo usando RayCast
simBotella : Simula una botella que puede transitar por los transportes simTransporte o simCurve
simCurve : Simula una curva o arco de curva de transporte
simDescarte : Permite la eliminacion localizada de botellas en un punto del mundo
simGuia : Es un box con el que las botellas pueden colisionar y cambiar de direccion.
simTransporte : Es un box por donde las botellas pueden desplazarse usando un truco de aplicar la Velocity.Linear pero sin integrar esta velocidad para que no se mueva el objeto transporte.
* Se usaron esferas en vez de cilindros para mejorar la eficiencia. En el Debug3D si se usan cilindros. **Revertido**: Se ha vuelto a usar `Cylinder` para las `simBotella` ya que el nuevo sistema de fricción debería prevenir la rotación indeseada que ocurría con los `LinearAxisMotor`.
@ -17,3 +20,7 @@ simCurve : Simula una curva o arco de curva de transporte
* La unica clase que se ha terminado de refactorizar respecto a el cambio de coordenadas es simBarrera y ucPhotocell. El concepto es poder separar usando metodos de SimulationManagerBEPU y estructuras como BarreraData la conversion de coordenadas de WPF a coordenadas BEPU. Para esto se usa CoordinateConverter que permite bidireccionalmente convertir las coordenadas pero esto solo se debe usar en SimulationManagerBEPU las clases derivadas de osBase solo deben manejar coordenadas WPF, mientras que las clases dervadas de simBase solo deben almacenar y usar coordenadas BEPU. La z tambien es algo que se debe transferir a SimulationManagerBEPU ya que los objetos simBase deberian recibir tambien sus coordenadas de Z desde SimulationManagerBEPU y ser SimulationManagerBEPU el que gestione las Z.
* Se ha implementado un sistema para evitar que las botellas (`simBotella`) "floten" o se eleven de manera irreal por la acumulación de presión en la simulación. Cada botella ahora registra si está en contacto con un transporte y almacena la última coordenada Z válida durante dicho contacto. Si la botella deja de tener contacto con transportes por varios frames consecutivos, se incrementa un contador de "presión". Al superar un umbral, el sistema reestablece la posición Z de la botella a su última altura conocida, previniendo la flotación. Este contador de presión se decrementa rápidamente al volver a hacer contacto con un transporte.
* Cuando una botella (`simBotella`) entra en contacto con un transporte de frenado (`simTransporte` con `isBrake = true`), su posición se ajusta automáticamente para centrarla en el eje longitudinal del transporte. Esto se realiza una única vez, en el primer contacto, para asegurar un acoplamiento suave y predecible. La posición de la botella se proyecta sobre la línea central del transporte y su velocidad lateral se anula, evitando que la botella se desvíe mientras frena y se alinea con el flujo de salida.

View File

@ -126,10 +126,49 @@ namespace CtrEditor.Simulacion
// La velocidad del cuerpo cinemático del transporte se establece directamente
// en la clase simTransporte. El motor de físicas se encarga del resto.
// ✅ NUEVO: Lógica de control de presión/flotación
botella.IsTouchingTransport = true;
var botellaCollidable = GetBotellaFromCollidable(pair.A) != null ? pair.A : pair.B;
if (botellaCollidable.BodyHandle.Value >= 0 && _simulationManager.simulation.Bodies.BodyExists(botellaCollidable.BodyHandle))
{
var body = _simulationManager.simulation.Bodies.GetBodyReference(botellaCollidable.BodyHandle);
botella.LastTransportCollisionZ = body.Pose.Position.Z;
}
// Decrementamos la presión acumulada al tocar un transporte. Se reduce más rápido de lo que aumenta.
botella.PressureBuildup = Math.Max(0, botella.PressureBuildup - 5);
// ✅ Fricción ajustada para un arrastre firme pero no excesivo.
var transport = transportA ?? transportB;
if (transport.isBrake)
{
// ✅ NUEVO: Centrar la botella en el transporte de frenado la primera vez que entra.
// if (!botella.isOnBrakeTransport)
{
if (botella.BodyHandle.Value >= 0 && _simulationManager.simulation.Bodies.BodyExists(botella.BodyHandle) &&
transport.BodyHandle.Value >= 0 && _simulationManager.simulation.Bodies.BodyExists(transport.BodyHandle))
{
var bottleBody = _simulationManager.simulation.Bodies.GetBodyReference(botella.BodyHandle);
var transportBody = _simulationManager.simulation.Bodies.GetBodyReference(transport.BodyHandle);
var bottlePose = bottleBody.Pose;
var transportPose = transportBody.Pose;
// Proyectar la posición de la botella sobre el eje longitudinal del transporte.
Vector3 transportForward = transport.DirectionVector;
Vector3 vectorToBottle = bottlePose.Position - transportPose.Position;
float projectionLength = Vector3.Dot(vectorToBottle, transportForward);
Vector3 newPositionOnCenterline = transportPose.Position + transportForward * projectionLength;
// Crear la nueva pose manteniendo la Z original de la botella para no hundirla.
var newBottlePosition = new Vector3(newPositionOnCenterline.X, newPositionOnCenterline.Y, bottlePose.Position.Z);
bottleBody.Pose.Position = newBottlePosition;
// Opcional: Anular la velocidad lateral para un acoplamiento más suave.
var lateralVelocity = Vector3.Dot(bottleBody.Velocity.Linear, transport.DirectionVector);
bottleBody.Velocity.Linear = transport.DirectionVector * lateralVelocity;
}
}
botella.isOnBrakeTransport = true;
pairMaterial.FrictionCoefficient = 14f;
pairMaterial.MaximumRecoveryVelocity = 1.0f;
@ -150,6 +189,17 @@ namespace CtrEditor.Simulacion
// El motor de físicas usará la velocidad angular del cuerpo cinemático de la curva
// para calcular las fuerzas de fricción y arrastrar la botella.
// ✅ NUEVO: Lógica de control de presión/flotación
botella.IsTouchingTransport = true;
var botellaCollidable = GetBotellaFromCollidable(pair.A) != null ? pair.A : pair.B;
if (botellaCollidable.BodyHandle.Value >= 0 && _simulationManager.simulation.Bodies.BodyExists(botellaCollidable.BodyHandle))
{
var body = _simulationManager.simulation.Bodies.GetBodyReference(botellaCollidable.BodyHandle);
botella.LastTransportCollisionZ = body.Pose.Position.Z;
}
// Decrementamos la presión acumulada al tocar una curva.
botella.PressureBuildup = Math.Max(0, botella.PressureBuildup - 5);
// ✅ Fricción ajustada para un arrastre firme pero no excesivo.
pairMaterial.FrictionCoefficient = 1f;
pairMaterial.MaximumRecoveryVelocity = 1.0f;
@ -718,6 +768,12 @@ namespace CtrEditor.Simulacion
{
_frameCount++;
// ✅ NUEVO: Resetear el estado de contacto para el sistema de presión
foreach (var botella in Cuerpos.OfType<simBotella>())
{
botella.IsTouchingTransport = false;
}
// ✅ CONSERVAR - validación de deltaTime
var currentTime = stopwatch.Elapsed.TotalMilliseconds;
var deltaTime = (float)((currentTime - stopwatch_last) / 1000.0);
@ -794,6 +850,7 @@ namespace CtrEditor.Simulacion
// ✅ CONSERVAR - sistemas que funcionan bien
ProcessBarreraContacts();
ProcessDescarteContacts();
ProcessPressureSystem();
ProcessCleanupSystem();
// ✅ SIMPLIFICAR - limpiar solo contactos que usamos
@ -820,6 +877,60 @@ namespace CtrEditor.Simulacion
/// <summary>
/// ✅ NUEVO: Sistema para controlar la "presión" y evitar que las botellas floten
/// Si una botella no toca un transporte por varios frames, se reestablece su altura.
/// </summary>
private void ProcessPressureSystem()
{
try
{
var botellas = Cuerpos.OfType<simBotella>().ToList();
foreach (var botella in botellas)
{
try
{
if (botella == null || !simulation.Bodies.BodyExists(botella.BodyHandle))
continue;
if (!botella.IsTouchingTransport && botella.LastTransportCollisionZ.HasValue)
{
var body = simulation.Bodies.GetBodyReference(botella.BodyHandle);
var currentZ = body.Pose.Position.Z;
// ✅ NUEVA CONDICIÓN: Solo actuar si la botella ha subido
if (currentZ > botella.LastTransportCollisionZ.Value)
{
// Incrementar el contador de presión.
botella.PressureBuildup++;
// Si se acumula suficiente presión (más de 2 frames sin contacto y subiendo),
// es un indicio de que está flotando. La reestablecemos a su última Z conocida.
if (botella.PressureBuildup > 2)
{
var pose = body.Pose;
pose.Position.Z = botella.LastTransportCollisionZ.Value;
body.Pose = pose;
// Opcional: resetear el contador para no aplicarlo constantemente en cada frame
// botella.PressureBuildup = 0;
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[ProcessPressureSystem] Error processing bottle {botella?.BodyHandle}: {ex.Message}");
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[ProcessPressureSystem] Critical error: {ex.Message}");
}
}
/// <summary>
/// ✅ NUEVO: Marca un objeto para eliminación diferida (más seguro)
/// </summary>
@ -1035,9 +1146,6 @@ namespace CtrEditor.Simulacion
}
}
// ✅ ELIMINADO: CalculateBarreraDetectionGeometric - ya no se usa
// El nuevo sistema usa RayCast nativo de BEPU a través de simBarrera.PerformRaycast()
/// <summary>
/// Procesa contactos de descarte para eliminar botellas marcadas usando detección geométrica
/// </summary>

View File

@ -31,6 +31,11 @@ namespace CtrEditor.Simulacion
public bool isOnBrakeTransport; // Nueva propiedad para marcar si está en un transporte con freno
public simTransporte CurrentBrakeTransport { get; set; } // ✅ NUEVA: Referencia al transporte de freno actual
// ✅ NUEVO: Propiedades para control de flotación/presión
public float? LastTransportCollisionZ { get; set; }
public int PressureBuildup { get; set; } = 0;
public bool IsTouchingTransport { get; set; } = false;
// ✅ NUEVO: Propiedades para la física personalizada
public float BaseInverseMass { get; private set; }
public Vector3 InitialPosition3D { get; private set; }