Se realizaron ajustes significativos en la configuración de fricción y recuperación en la simulación de botellas, mejorando la estabilidad y el comportamiento en contactos. Se implementaron nuevas funciones para limitar fuerzas Z y calcular la profundidad de penetración, optimizando la respuesta de las botellas en situaciones de contacto. Además, se ajustaron los parámetros de amortiguamiento y velocidad de separación para lograr un comportamiento más realista en la simulación.
This commit is contained in:
parent
62b45ebf1c
commit
6887ede5e0
|
@ -87,12 +87,12 @@ namespace CtrEditor.Simulacion
|
|||
|
||||
public bool ConfigureContactManifold<TManifold>(int workerIndex, CollidablePair pair, ref TManifold manifold, out PairMaterialProperties pairMaterial) where TManifold : unmanaged, IContactManifold<TManifold>
|
||||
{
|
||||
// ✅ CONFIGURACIÓN BÁSICA de materiales físicos
|
||||
// ✅ CONFIGURACIÓN BÁSICA de materiales físicos con valores rígidos pero estables
|
||||
pairMaterial = new PairMaterialProperties
|
||||
{
|
||||
FrictionCoefficient = 0.3f,
|
||||
MaximumRecoveryVelocity = 1f,
|
||||
SpringSettings = new SpringSettings(80, 6)
|
||||
MaximumRecoveryVelocity = 0.8f, // ✅ AJUSTADO: Velocidad de separación moderada
|
||||
SpringSettings = new SpringSettings(120, 8) // ✅ AJUSTADO: Más rígido pero bien amortiguado
|
||||
};
|
||||
|
||||
if (_simulationManager != null)
|
||||
|
@ -165,16 +165,16 @@ namespace CtrEditor.Simulacion
|
|||
|
||||
botella.isOnBrakeTransport = true;
|
||||
pairMaterial.FrictionCoefficient = 2f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.5f; // ✅ AJUSTADO: Velocidad de separación controlada
|
||||
pairMaterial.SpringSettings = new SpringSettings(80, 6f); // ✅ AJUSTADO: Rígido para frenado
|
||||
}
|
||||
else
|
||||
{
|
||||
botella.isOnBrakeTransport = false;
|
||||
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
||||
pairMaterial.FrictionCoefficient = 0.3f; // CalculateTransportFriction(botella, transport, botellaCollidable);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f);
|
||||
pairMaterial.FrictionCoefficient = CalculateTransportFriction(botella, transport, botellaCollidable);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.6f; // ✅ AJUSTADO: Velocidad de separación más natural
|
||||
pairMaterial.SpringSettings = new SpringSettings(100, 8f); // ✅ AJUSTADO: Rígido para transportes
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -193,26 +193,40 @@ namespace CtrEditor.Simulacion
|
|||
|
||||
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
||||
var curve = curveA ?? curveB;
|
||||
pairMaterial.FrictionCoefficient = 0.3f; // CalculateCurveFriction(botella, curve, botellaCollidable);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f); // Colision con la cinta por gravedad
|
||||
pairMaterial.FrictionCoefficient = CalculateCurveFriction(botella, curve, botellaCollidable);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.6f; // ✅ AJUSTADO: Velocidad de separación más natural
|
||||
pairMaterial.SpringSettings = new SpringSettings(100, 8f); // ✅ AJUSTADO: Rígido para curvas
|
||||
}
|
||||
// ✅ CONTACTO BOTELLA-GUÍA: Configuración específica de fricción
|
||||
else if (botella != null && (GetGuiaFromCollidable(pair.A) != null || GetGuiaFromCollidable(pair.B) != null))
|
||||
{
|
||||
// Fricción baja para las guías, deben deslizar, no arrastrar.
|
||||
pairMaterial.FrictionCoefficient = 0.1f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.8f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(50, 1f); // Rebote lateral moderado
|
||||
pairMaterial.FrictionCoefficient = 0.01f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.5f; // ✅ AJUSTADO: Velocidad de separación normal
|
||||
pairMaterial.SpringSettings = new SpringSettings(120, 10f); // ✅ AJUSTADO: Rígido para guías
|
||||
}
|
||||
// ✅ NUEVO: CONTACTO BOTELLA-BOTELLA: Lógica de presión proactiva basada en la penetración.
|
||||
else if (botellaA != null && botellaB != null)
|
||||
{
|
||||
// ✅ NUEVO: Usar método especializado para contactos botella-botella
|
||||
CalculateBottlePression(ref manifold, botellaA, botellaB);
|
||||
pairMaterial.FrictionCoefficient = 0.1f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.03f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f); // Rebote lateral moderado
|
||||
|
||||
// ✅ NUEVO: Limitar fuerzas basadas en profundidad de penetración
|
||||
var maxPenetrationDepth = GetMaxPenetrationDepth(ref manifold);
|
||||
if (maxPenetrationDepth > 0.005f) // Penetración profunda (reducido umbral)
|
||||
{
|
||||
// Fuerzas controladas para penetraciones profundas - evitar explosiones pero mantener rigidez
|
||||
pairMaterial.FrictionCoefficient = 0.01f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.3f; // ✅ AUMENTADO: Más velocidad de separación
|
||||
pairMaterial.SpringSettings = new SpringSettings(60, 12f); // ✅ AUMENTADO: Más rígido pero bien amortiguado
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fuerzas normales para contactos superficiales - botellas rígidas
|
||||
pairMaterial.FrictionCoefficient = 0.02f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.5f; // ✅ AUMENTADO: Velocidad normal de separación
|
||||
pairMaterial.SpringSettings = new SpringSettings(150, 10f); // ✅ AUMENTADO: Muy rígido para contactos normales
|
||||
}
|
||||
}
|
||||
// Ajustes básicos para otras botellas
|
||||
else if (botella != null)
|
||||
|
@ -220,8 +234,8 @@ namespace CtrEditor.Simulacion
|
|||
System.Diagnostics.Debug.WriteLine($"[ConfigureContactManifold] ERROR: contacto no resuelto!");
|
||||
// Fricción moderada para colisiones entre botellas.
|
||||
pairMaterial.FrictionCoefficient = 0.3f;
|
||||
pairMaterial.MaximumRecoveryVelocity = 1f;
|
||||
pairMaterial.SpringSettings = new SpringSettings(30, 1);
|
||||
pairMaterial.MaximumRecoveryVelocity = 0.6f; // ✅ AJUSTADO: Velocidad de separación normal
|
||||
pairMaterial.SpringSettings = new SpringSettings(120, 8); // ✅ AJUSTADO: Rígido pero controlado
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,8 +345,8 @@ namespace CtrEditor.Simulacion
|
|||
|
||||
float slipSpeedThreshold = transportVelocity.Length()*0.85f; // m/s - umbral para cambiar de fricción estática a dinámica
|
||||
const float heatupRate = 1f; // Qué tan rápido sube HighSlippery
|
||||
const float cooldownRate = 0.5f; // Qué tan rápido baja HighSlippery
|
||||
const float staticFriction = 0.25f;
|
||||
const float cooldownRate = 0.2f; // Qué tan rápido baja HighSlippery
|
||||
const float staticFriction = 0.30f;
|
||||
const float dynamicFriction = 0.10f;
|
||||
|
||||
// Sistema de heatup/cooldown para HighSlippery
|
||||
|
@ -382,8 +396,8 @@ namespace CtrEditor.Simulacion
|
|||
|
||||
float slipSpeedThreshold = curveVelocityAtPoint.Length() * 0.85f; // m/s
|
||||
const float heatupRate = 1f; // Qué tan rápido sube HighSlippery en curvas
|
||||
const float cooldownRate = 0.5f; // Qué tan rápido baja HighSlippery en curvas
|
||||
const float staticFriction = 0.20f;
|
||||
const float cooldownRate = 0.2f; // Qué tan rápido baja HighSlippery en curvas
|
||||
const float staticFriction = 0.30f;
|
||||
const float dynamicFriction = 0.10f;
|
||||
|
||||
// Sistema de heatup/cooldown para HighSlippery
|
||||
|
@ -440,6 +454,31 @@ namespace CtrEditor.Simulacion
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ✅ NUEVA FUNCIÓN: Obtiene la profundidad máxima de penetración en un manifold
|
||||
/// </summary>
|
||||
private float GetMaxPenetrationDepth<TManifold>(ref TManifold manifold) where TManifold : unmanaged, IContactManifold<TManifold>
|
||||
{
|
||||
try
|
||||
{
|
||||
float maxDepth = 0f;
|
||||
for (int i = 0; i < manifold.Count; ++i)
|
||||
{
|
||||
var depth = manifold.GetDepth(i);
|
||||
if (depth > maxDepth)
|
||||
{
|
||||
maxDepth = depth;
|
||||
}
|
||||
}
|
||||
return maxDepth;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[GetMaxPenetrationDepth] Error: {ex.Message}");
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConfigureContactManifold(int workerIndex, CollidablePair pair, int childIndexA, int childIndexB, ref ConvexContactManifold manifold)
|
||||
{
|
||||
return true;
|
||||
|
@ -938,6 +977,9 @@ namespace CtrEditor.Simulacion
|
|||
botella.ContactPressure = 0f;
|
||||
}
|
||||
|
||||
// ✅ NUEVO: APLICAR LIMITACIÓN DE FUERZAS Z ANTES DEL TIMESTEP
|
||||
ApplyZForceLimitation();
|
||||
|
||||
// ✅ CONSERVAR - validación de deltaTime
|
||||
var currentTime = stopwatch.Elapsed.TotalMilliseconds;
|
||||
var deltaTime = (float)((currentTime - stopwatch_last) / 1000.0);
|
||||
|
@ -1498,6 +1540,70 @@ namespace CtrEditor.Simulacion
|
|||
return lineStart + lineDirection * projectionLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ✅ NUEVA FUNCIÓN: Limita las fuerzas Z para evitar que las botellas se eleven
|
||||
/// Esta función se ejecuta ANTES del timestep para controlar fuerzas de separación excesivas
|
||||
/// </summary>
|
||||
private void ApplyZForceLimitation()
|
||||
{
|
||||
try
|
||||
{
|
||||
const float maxZVelocity = 0.3f; // ✅ AJUSTADO: Velocidad Z máxima permitida más realista (m/s)
|
||||
const float zVelocityDamping = 0.8f; // ✅ AJUSTADO: Amortiguamiento menos agresivo para Z
|
||||
|
||||
foreach (var botella in Cuerpos.OfType<simBotella>())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Verificar que la botella aún existe en la simulación
|
||||
if (botella?.BodyHandle.Value >= 0 && simulation?.Bodies?.BodyExists(botella.BodyHandle) == true)
|
||||
{
|
||||
var body = simulation.Bodies.GetBodyReference(botella.BodyHandle);
|
||||
var velocity = body.Velocity;
|
||||
|
||||
// ✅ LIMITACIÓN DIRECTA DE VELOCIDAD Z
|
||||
if (velocity.Linear.Z > maxZVelocity)
|
||||
{
|
||||
velocity.Linear.Z = maxZVelocity;
|
||||
body.Velocity = velocity;
|
||||
}
|
||||
|
||||
// ✅ AMORTIGUAMIENTO ADICIONAL EN Z
|
||||
if (velocity.Linear.Z > 0)
|
||||
{
|
||||
velocity.Linear.Z *= zVelocityDamping;
|
||||
body.Velocity = velocity;
|
||||
}
|
||||
|
||||
// ✅ LIMITACIÓN DE FUERZAS EXTREMAS POR PENETRACIÓN
|
||||
// Si la botella está muy por encima del nivel normal, aplicar fuerza hacia abajo
|
||||
var position = body.Pose.Position;
|
||||
var maxAllowedZ = simBase.zPos_Transporte + simBase.zAltura_Transporte + botella.Radius * 2;
|
||||
|
||||
if (position.Z > maxAllowedZ)
|
||||
{
|
||||
// Aplicar fuerza hacia abajo proporcional a la elevación excesiva
|
||||
var excessHeight = position.Z - maxAllowedZ;
|
||||
var downwardForce = new Vector3(0, 0, -excessHeight * 20f); // ✅ AJUSTADO: Fuerza menos agresiva
|
||||
|
||||
// Aplicar impulso para corregir la posición
|
||||
velocity.Linear += downwardForce * (1f / 60f); // Asumir 60 FPS
|
||||
body.Velocity = velocity;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[ApplyZForceLimitation] Error procesando botella {botella?.BodyHandle}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[ApplyZForceLimitation] Error crítico: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Clear();
|
||||
|
|
Loading…
Reference in New Issue