Se ajustaron los coeficientes de fricción y configuraciones de resorte en la simulación de botellas, diferenciando entre transportes con y sin freno. Además, se modificó la visibilidad de triángulos en la visualización 3D, mejorando la iluminación y corrigiendo la creación de mallas continuas a partir de triángulos de BEPU. Se eliminaron métodos obsoletos relacionados con la geometría de curvas, optimizando la lógica de creación de mallas.

This commit is contained in:
Miguel 2025-07-05 17:53:22 +02:00
parent eb6ed62d5b
commit 71c08d8047
2 changed files with 64 additions and 104 deletions

View File

@ -127,9 +127,22 @@ namespace CtrEditor.Simulacion
// en la clase simTransporte. El motor de físicas se encarga del resto.
// ✅ Fricción ajustada para un arrastre firme pero no excesivo.
pairMaterial.FrictionCoefficient = 1.2f;
pairMaterial.MaximumRecoveryVelocity = 1.0f;
pairMaterial.SpringSettings = new SpringSettings(80, 1);
var transport = transportA ?? transportB;
if (transport.isBrake)
{
botella.isOnBrakeTransport = true;
pairMaterial.FrictionCoefficient = 14f;
pairMaterial.MaximumRecoveryVelocity = 1.0f;
pairMaterial.SpringSettings = new SpringSettings(80, 8);
}
else
{
botella.isOnBrakeTransport = false;
pairMaterial.FrictionCoefficient = 1.2f;
pairMaterial.MaximumRecoveryVelocity = 1.0f;
pairMaterial.SpringSettings = new SpringSettings(80, 1);
}
}
// ✅ CONTACTO BOTELLA-CURVA: USAR FRICCIÓN Y VELOCIDAD CINEMÁTICA
else if (botella != null && (curveA != null || curveB != null))
@ -153,9 +166,18 @@ namespace CtrEditor.Simulacion
// ✅ NUEVO: CONTACTO BOTELLA-BOTELLA: Configuración más suave para evitar el comportamiento "pegajoso".
else if (botellaA != null && botellaB != null)
{
pairMaterial.FrictionCoefficient = 0.01f; // Un poco menos de fricción.
pairMaterial.MaximumRecoveryVelocity = 1.5f; // Menos rebote.
pairMaterial.SpringSettings = new SpringSettings(20, 0.5f); // Muelle MUCHO más suave y críticamente amortiguado.
if (botella.isOnBrakeTransport)
{
pairMaterial.FrictionCoefficient = 2.0f; // Un poco menos de fricción.
pairMaterial.MaximumRecoveryVelocity = 1.5f; // Menos rebote.
pairMaterial.SpringSettings = new SpringSettings(80, 1f); // Muelle MUCHO más suave y críticamente amortiguado.
}
else
{
pairMaterial.FrictionCoefficient = 0.01f; // Un poco menos de fricción.
pairMaterial.MaximumRecoveryVelocity = 1.5f; // Menos rebote.
pairMaterial.SpringSettings = new SpringSettings(20, 0.5f); // Muelle MUCHO más suave y críticamente amortiguado.
}
}
// Ajustes básicos para otras botellas
else if (botella != null)

View File

@ -72,7 +72,7 @@ namespace CtrEditor.Simulacion
private Dictionary<simBase, ShapeDimensions> lastKnownDimensions;
// ✅ CORREGIDO: Flag de debug para mostrar triángulos individuales de curvas (true temporalmente para verificar)
public static bool DebugShowIndividualTriangles { get; set; } = true;
public static bool DebugShowIndividualTriangles { get; set; } = false;
public HelixViewport3D Viewport3D
{
@ -112,14 +112,14 @@ namespace CtrEditor.Simulacion
// Agregar luces
var directionalLight = new DirectionalLight
{
Color = Colors.White,
Direction = new Vector3D(0, 0, -1)
Color = Color.FromRgb(150, 150, 150), // Luz direccional menos intensa
Direction = new Vector3D(-0.2, -0.3, -1) // Ligeramente angulada para evitar reflejos directos
};
viewport3D.Children.Add(new ModelVisual3D { Content = directionalLight });
var ambientLight = new AmbientLight
{
Color = Color.FromRgb(64, 64, 64)
Color = Color.FromRgb(120, 120, 120) // Más luz ambiente para suavizar sombras
};
viewport3D.Children.Add(new ModelVisual3D { Content = ambientLight });
@ -397,7 +397,7 @@ namespace CtrEditor.Simulacion
}
else
{
// ✅ Usar directamente los triángulos originales de BEPU (superficie continua)
// ✅ CORREGIDO: Crea un arco de mesh continuo y simple desde los triángulos de BEPU
CreateCurveMeshFromBEPUTriangles(meshBuilder, curve);
}
@ -422,44 +422,57 @@ namespace CtrEditor.Simulacion
}
/// <summary>
/// ✅ CORREGIDO: Crea mesh desde los triángulos locales de BEPU
/// Extrae la geometría exacta en coordenadas locales para evitar transformación duplicada
/// ✅ CORREGIDO: Crea un arco de mesh continuo y simple desde los triángulos de BEPU
/// Genera una superficie plana que forma un arco suave y eficiente
/// </summary>
private void CreateCurveMeshFromBEPUTriangles(MeshBuilder meshBuilder, simCurve curve)
{
try
{
// ✅ EXTRAER TRIÁNGULOS LOCALES DE BEPU (sin transformación duplicada)
// Obtener los triángulos de BEPU
var localTriangles = curve.GetRealBEPUTriangles();
System.Diagnostics.Debug.WriteLine($"[3D Curve] Creating continuous arc mesh from {localTriangles.Length} BEPU triangles");
if (localTriangles.Length == 0)
{
System.Diagnostics.Debug.WriteLine($"[3D BEPU] WARNING: No se pudieron extraer triángulos locales, usando fallback");
CreateCurveMeshFallback(meshBuilder, curve);
System.Diagnostics.Debug.WriteLine($"[3D Curve] WARNING: No triangles found in BEPU curve");
return;
}
System.Diagnostics.Debug.WriteLine($"[3D BEPU] Creando mesh desde {localTriangles.Length} triángulos locales de BEPU");
// ✅ CORREGIDO: Usar altura más visible y verificar coordenadas
const float curveHeight = 0.02f; // 2cm de altura para que sea claramente visible
int triangleCount = 0;
// ✅ USAR TRIÁNGULOS LOCALES DE BEPU (la transformación se aplicará automáticamente en UpdateVisualization)
foreach (var triangle in localTriangles)
{
// Convertir triángulos de BEPU a puntos 3D de Helix
var pointA = new Point3D(triangle.A.X, triangle.A.Y, triangle.A.Z);
var pointB = new Point3D(triangle.B.X, triangle.B.Y, triangle.B.Z);
var pointC = new Point3D(triangle.C.X, triangle.C.Y, triangle.C.Z);
// ✅ LOGGING: Verificar las coordenadas del primer triángulo
if (triangleCount == 0)
{
System.Diagnostics.Debug.WriteLine($"[3D Curve] First triangle: A({triangle.A.X:F3}, {triangle.A.Y:F3}, {triangle.A.Z:F3})");
System.Diagnostics.Debug.WriteLine($"[3D Curve] First triangle: B({triangle.B.X:F3}, {triangle.B.Y:F3}, {triangle.B.Z:F3})");
System.Diagnostics.Debug.WriteLine($"[3D Curve] First triangle: C({triangle.C.X:F3}, {triangle.C.Y:F3}, {triangle.C.Z:F3})");
}
// Crear triángulo en la superficie superior con altura visible
var pointA = new Point3D(triangle.A.X, triangle.A.Y, triangle.A.Z + curveHeight);
var pointB = new Point3D(triangle.B.X, triangle.B.Y, triangle.B.Z + curveHeight);
var pointC = new Point3D(triangle.C.X, triangle.C.Y, triangle.C.Z + curveHeight);
// Agregar triángulo en coordenadas locales al mesh
// ✅ CORREGIDO: Probar ambos órdenes de vértices para asegurar normales correctas
meshBuilder.AddTriangle(pointA, pointB, pointC);
// También agregar el triángulo con orden inverso para que sea visible desde ambos lados
meshBuilder.AddTriangle(pointA, pointC, pointB);
triangleCount++;
}
System.Diagnostics.Debug.WriteLine($"[3D BEPU] ✅ Mesh creado usando triángulos locales de BEPU (transformación aplicada automáticamente)");
System.Diagnostics.Debug.WriteLine($"[3D Curve] ✅ Continuous arc mesh created with {triangleCount} triangles (height: {curveHeight})");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[3D BEPU] ERROR extrayendo triángulos locales: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"[3D BEPU] Fallback a geometría recreada");
CreateCurveMeshFallback(meshBuilder, curve);
System.Diagnostics.Debug.WriteLine($"[3D Curve] ERROR creating continuous arc mesh: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"[3D Curve] Stack trace: {ex.StackTrace}");
}
}
@ -477,7 +490,7 @@ namespace CtrEditor.Simulacion
if (localTriangles.Length == 0)
{
System.Diagnostics.Debug.WriteLine($"[3D Debug] WARNING: No hay triángulos locales para debug, usando fallback");
CreateCurveMeshFallback(meshBuilder, curve);
CreateBasicDebugGeometry(meshBuilder, curve);
return;
}
@ -574,81 +587,6 @@ namespace CtrEditor.Simulacion
}
}
/// <summary>
/// Método fallback que recrea la geometría (mantener por compatibilidad)
/// </summary>
private void CreateCurveMeshFallback(MeshBuilder meshBuilder, simCurve curve)
{
// Obtener parámetros de la curva
float innerRadius = curve.InnerRadius;
float outerRadius = curve.OuterRadius;
float startAngle = curve.StartAngle;
float endAngle = curve.EndAngle;
System.Diagnostics.Debug.WriteLine($"[3D Fallback] Parameters - Inner: {innerRadius}, Outer: {outerRadius}, Start: {startAngle}, End: {endAngle}");
// Configuración de segmentos
const float SegmentationFactor = 32f / 3f;
const int MinSegments = 8;
const int MaxSegments = 64;
// Calcular número de segmentos basado en el tamaño del arco
float arcLength = (endAngle - startAngle) * ((innerRadius + outerRadius) / 2f);
int segments = (int)(arcLength * SegmentationFactor);
segments = Math.Max(MinSegments, Math.Min(segments, MaxSegments));
float angleStep = (endAngle - startAngle) / segments;
// Altura muy pequeña para simular triángulos planos
const float curveHeight = 0.05f;
// Generar vértices para el arco interior y exterior
var innerBottomPoints = new Point3D[segments + 1];
var innerTopPoints = new Point3D[segments + 1];
var outerBottomPoints = new Point3D[segments + 1];
var outerTopPoints = new Point3D[segments + 1];
for (int i = 0; i <= segments; i++)
{
float angle = startAngle + i * angleStep;
float cosAngle = (float)Math.Cos(angle);
float sinAngle = (float)Math.Sin(angle);
// Puntos en la parte inferior (Z = 0)
innerBottomPoints[i] = new Point3D(innerRadius * cosAngle, innerRadius * sinAngle, 0);
outerBottomPoints[i] = new Point3D(outerRadius * cosAngle, outerRadius * sinAngle, 0);
// Puntos en la parte superior (Z = curveHeight)
innerTopPoints[i] = new Point3D(innerRadius * cosAngle, innerRadius * sinAngle, curveHeight);
outerTopPoints[i] = new Point3D(outerRadius * cosAngle, outerRadius * sinAngle, curveHeight);
}
// Crear la superficie superior de la curva
for (int i = 0; i < segments; i++)
{
meshBuilder.AddTriangle(innerTopPoints[i], outerTopPoints[i], outerTopPoints[i + 1]);
meshBuilder.AddTriangle(innerTopPoints[i], outerTopPoints[i + 1], innerTopPoints[i + 1]);
}
// Crear la superficie inferior de la curva
for (int i = 0; i < segments; i++)
{
meshBuilder.AddTriangle(innerBottomPoints[i], outerBottomPoints[i + 1], outerBottomPoints[i]);
meshBuilder.AddTriangle(innerBottomPoints[i], innerBottomPoints[i + 1], outerBottomPoints[i + 1]);
}
// Crear las paredes laterales
for (int i = 0; i < segments; i++)
{
meshBuilder.AddQuad(innerBottomPoints[i], innerBottomPoints[i + 1], innerTopPoints[i + 1], innerTopPoints[i]);
meshBuilder.AddQuad(outerBottomPoints[i], outerTopPoints[i], outerTopPoints[i + 1], outerBottomPoints[i + 1]);
}
// Crear las paredes de los extremos
meshBuilder.AddQuad(innerBottomPoints[0], innerTopPoints[0], outerTopPoints[0], outerBottomPoints[0]);
meshBuilder.AddQuad(outerBottomPoints[segments], outerTopPoints[segments], innerTopPoints[segments], innerBottomPoints[segments]);
}
private void UpdateVisualizationFromSimBase(simBase simObj)
{
if (!simBaseToModelMap.TryGetValue(simObj, out var visual))