diff --git a/Simulacion/BEPU.cs b/Simulacion/BEPU.cs index 7fc90d8..2fcc8b1 100644 --- a/Simulacion/BEPU.cs +++ b/Simulacion/BEPU.cs @@ -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) diff --git a/Simulacion/BEPUVisualization3D.cs b/Simulacion/BEPUVisualization3D.cs index 389d925..26a5bbb 100644 --- a/Simulacion/BEPUVisualization3D.cs +++ b/Simulacion/BEPUVisualization3D.cs @@ -72,7 +72,7 @@ namespace CtrEditor.Simulacion private Dictionary 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 } /// - /// ✅ 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 /// 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 } } - /// - /// Método fallback que recrea la geometría (mantener por compatibilidad) - /// - 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))