Se implementaron mejoras en la gestión de imágenes de fondo en el viewport 3D, permitiendo agregar, remover y sincronizar imágenes de fondo con la visualización 3D. Se corrigieron las convenciones de posicionamiento y escalado para asegurar coherencia visual entre el canvas 2D y la representación 3D. Además, se ajustaron los coeficientes de fricción en la simulación de botellas, optimizando el comportamiento en contactos y curvas.
This commit is contained in:
parent
f7f49d5df0
commit
62b45ebf1c
|
@ -107,6 +107,18 @@ namespace CtrEditor
|
||||||
|
|
||||||
// Conectar el manager 3D con el simulation manager (orden correcto de inicialización)
|
// Conectar el manager 3D con el simulation manager (orden correcto de inicialización)
|
||||||
viewModel.simulationManager.Visualization3DManager = _visualization3DManager;
|
viewModel.simulationManager.Visualization3DManager = _visualization3DManager;
|
||||||
|
|
||||||
|
// ✅ NUEVO: Si ya hay una imagen de fondo cargada, agregarla al viewport 3D
|
||||||
|
if (imagenDeFondo?.Source is BitmapImage existingImage)
|
||||||
|
{
|
||||||
|
// Necesitamos la ruta original de la imagen, usar el UriSource si está disponible
|
||||||
|
var imageUri = existingImage.UriSource?.LocalPath ?? existingImage.UriSource?.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(imageUri))
|
||||||
|
{
|
||||||
|
_visualization3DManager.SetBackgroundImage(imageUri, existingImage.PixelWidth, existingImage.PixelHeight);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ✅ Imagen existente agregada al viewport 3D: {imageUri}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +180,12 @@ namespace CtrEditor
|
||||||
Canvas.SetLeft(imagenDeFondo, 0);
|
Canvas.SetLeft(imagenDeFondo, 0);
|
||||||
Canvas.SetTop(imagenDeFondo, 0);
|
Canvas.SetTop(imagenDeFondo, 0);
|
||||||
|
|
||||||
|
// ✅ NUEVO: Agregar la imagen de fondo al viewport 3D con la misma escala
|
||||||
|
if (_visualization3DManager != null)
|
||||||
|
{
|
||||||
|
_visualization3DManager.SetBackgroundImage(imagePath, bitmap.Width, bitmap.Height);
|
||||||
|
}
|
||||||
|
|
||||||
// Eliminar solo los ROIs, no la imagen de fondo ni el área de panning
|
// Eliminar solo los ROIs, no la imagen de fondo ni el área de panning
|
||||||
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
|
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
@ -367,8 +385,6 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
// Only force canvas focus if PanelEdicion doesn't have focus
|
// Only force canvas focus if PanelEdicion doesn't have focus
|
||||||
|
@ -539,6 +555,59 @@ namespace CtrEditor
|
||||||
_objectManager.ClearUndoHistory();
|
_objectManager.ClearUndoHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Establece la imagen de fondo en el viewport 3D
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imagePath">Ruta de la imagen de fondo</param>
|
||||||
|
public void SetBackgroundImage3D(string imagePath)
|
||||||
|
{
|
||||||
|
if (_visualization3DManager != null && imagenDeFondo?.Source is BitmapImage bitmap)
|
||||||
|
{
|
||||||
|
_visualization3DManager.SetBackgroundImage(imagePath, bitmap.Width, bitmap.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Remueve la imagen de fondo del viewport 3D
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveBackgroundImage3D()
|
||||||
|
{
|
||||||
|
_visualization3DManager?.RemoveBackgroundImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Sincroniza la imagen de fondo existente con el viewport 3D
|
||||||
|
/// Útil cuando se necesita actualizar la imagen 3D basándose en la imagen 2D actual
|
||||||
|
/// </summary>
|
||||||
|
public void SyncBackgroundImage3D()
|
||||||
|
{
|
||||||
|
if (_visualization3DManager == null) return;
|
||||||
|
|
||||||
|
if (imagenDeFondo?.Source is BitmapImage existingImage)
|
||||||
|
{
|
||||||
|
// Intentar obtener la ruta de la imagen desde diferentes fuentes
|
||||||
|
var imageUri = existingImage.UriSource?.LocalPath ??
|
||||||
|
existingImage.UriSource?.ToString() ??
|
||||||
|
existingImage.BaseUri?.LocalPath;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(imageUri))
|
||||||
|
{
|
||||||
|
_visualization3DManager.SetBackgroundImage(imageUri, existingImage.PixelWidth, existingImage.PixelHeight);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ✅ Imagen sincronizada con viewport 3D");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ⚠️ No se pudo obtener la ruta de la imagen para sincronizar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si no hay imagen cargada, remover la imagen de fondo 3D
|
||||||
|
_visualization3DManager.RemoveBackgroundImage();
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ✅ Imagen de fondo 3D removida (no hay imagen 2D)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
// Aceptar el evento si viene del canvas o de la imagen de fondo
|
// Aceptar el evento si viene del canvas o de la imagen de fondo
|
||||||
|
|
|
@ -164,15 +164,15 @@ namespace CtrEditor.Simulacion
|
||||||
}
|
}
|
||||||
|
|
||||||
botella.isOnBrakeTransport = true;
|
botella.isOnBrakeTransport = true;
|
||||||
pairMaterial.FrictionCoefficient = 4f;
|
pairMaterial.FrictionCoefficient = 2f;
|
||||||
pairMaterial.MaximumRecoveryVelocity = 0f;
|
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||||
pairMaterial.SpringSettings = new SpringSettings(120, 8f);
|
pairMaterial.SpringSettings = new SpringSettings(80, 1f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
botella.isOnBrakeTransport = false;
|
botella.isOnBrakeTransport = false;
|
||||||
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
||||||
pairMaterial.FrictionCoefficient = CalculateTransportFriction(botella, transport, botellaCollidable);
|
pairMaterial.FrictionCoefficient = 0.3f; // CalculateTransportFriction(botella, transport, botellaCollidable);
|
||||||
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f);
|
pairMaterial.SpringSettings = new SpringSettings(80, 1f);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ namespace CtrEditor.Simulacion
|
||||||
|
|
||||||
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
// ✅ NUEVO: Usar fricción dinámica basada en deslizamiento
|
||||||
var curve = curveA ?? curveB;
|
var curve = curveA ?? curveB;
|
||||||
pairMaterial.FrictionCoefficient = CalculateCurveFriction(botella, curve, botellaCollidable);
|
pairMaterial.FrictionCoefficient = 0.3f; // CalculateCurveFriction(botella, curve, botellaCollidable);
|
||||||
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
pairMaterial.MaximumRecoveryVelocity = 0.1f;
|
||||||
pairMaterial.SpringSettings = new SpringSettings(80, 1f); // Colision con la cinta por gravedad
|
pairMaterial.SpringSettings = new SpringSettings(80, 1f); // Colision con la cinta por gravedad
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Linq;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media.Animation;
|
using System.Windows.Media.Animation;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
namespace CtrEditor.Simulacion
|
namespace CtrEditor.Simulacion
|
||||||
{
|
{
|
||||||
|
@ -80,6 +81,9 @@ namespace CtrEditor.Simulacion
|
||||||
// ✅ NUEVO: Diccionario para gestionar animaciones activas
|
// ✅ NUEVO: Diccionario para gestionar animaciones activas
|
||||||
private Dictionary<simBase, Storyboard> activeAnimations;
|
private Dictionary<simBase, Storyboard> activeAnimations;
|
||||||
|
|
||||||
|
// ✅ NUEVO: Referencia al modelo visual de la imagen de fondo
|
||||||
|
private ModelVisual3D? _backgroundImageVisual;
|
||||||
|
|
||||||
// ✅ CORREGIDO: Flag de debug para mostrar triángulos individuales de curvas (true temporalmente para verificar)
|
// ✅ CORREGIDO: Flag de debug para mostrar triángulos individuales de curvas (true temporalmente para verificar)
|
||||||
public static bool DebugShowIndividualTriangles { get; set; } = false;
|
public static bool DebugShowIndividualTriangles { get; set; } = false;
|
||||||
|
|
||||||
|
@ -847,6 +851,9 @@ namespace CtrEditor.Simulacion
|
||||||
}
|
}
|
||||||
simBaseToModelMap.Clear();
|
simBaseToModelMap.Clear();
|
||||||
lastKnownDimensions.Clear();
|
lastKnownDimensions.Clear();
|
||||||
|
|
||||||
|
// ✅ NUEVO: También limpiar la imagen de fondo
|
||||||
|
RemoveBackgroundImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1578,6 +1585,117 @@ namespace CtrEditor.Simulacion
|
||||||
System.Diagnostics.Debug.WriteLine($"[3D Barrera] ❌ ERROR recreando geometría: {ex.Message}");
|
System.Diagnostics.Debug.WriteLine($"[3D Barrera] ❌ ERROR recreando geometría: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Agrega la imagen de fondo como un plano 2D estático en el viewport 3D
|
||||||
|
/// con la misma escala que el canvas WPF usando las convenciones WPF-BEPU correctas
|
||||||
|
///
|
||||||
|
/// Esta funcionalidad permite tener coherencia visual entre el canvas 2D WPF y la visualización 3D:
|
||||||
|
/// - La imagen se posiciona en el plano XY con Z=0
|
||||||
|
/// - Usa el sistema de conversión PixelToMeter para mantener la escala correcta
|
||||||
|
/// - Aplica las conversiones WPF-BEPU: WPF (x,y) -> BEPU (x,-y)
|
||||||
|
/// - Se aplica como textura difusa en un rectángulo plano
|
||||||
|
/// - Respeta las convenciones: WPF Y hacia abajo, BEPU Y hacia arriba
|
||||||
|
///
|
||||||
|
/// Ejemplo de uso:
|
||||||
|
/// SetBackgroundImage(@"C:\imagen.png", 1920, 1080);
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imagePath">Ruta absoluta de la imagen de fondo</param>
|
||||||
|
/// <param name="canvasWidth">Ancho del canvas WPF en píxeles</param>
|
||||||
|
/// <param name="canvasHeight">Alto del canvas WPF en píxeles</param>
|
||||||
|
public void SetBackgroundImage(string imagePath, double canvasWidth, double canvasHeight)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Remover imagen de fondo anterior si existe
|
||||||
|
RemoveBackgroundImage();
|
||||||
|
|
||||||
|
// Convertir dimensiones de píxeles a metros usando el sistema de conversión
|
||||||
|
float widthInMeters = PixelToMeter.Instance.calc.PixelsToMeters((float)canvasWidth);
|
||||||
|
float heightInMeters = PixelToMeter.Instance.calc.PixelsToMeters((float)canvasHeight);
|
||||||
|
|
||||||
|
// Crear la geometría del plano
|
||||||
|
var meshBuilder = new MeshBuilder();
|
||||||
|
|
||||||
|
// ✅ CORREGIDO: Usar convenciones WPF-BEPU correctas
|
||||||
|
// En WPF: (0,0) = esquina superior izquierda, Y hacia abajo
|
||||||
|
// En BEPU: Y hacia arriba, entonces convertimos WPF (x,y) -> BEPU (x,-y)
|
||||||
|
|
||||||
|
// Definir las esquinas en coordenadas WPF
|
||||||
|
var wpfTopLeft = new System.Numerics.Vector2(0, 0);
|
||||||
|
var wpfTopRight = new System.Numerics.Vector2(widthInMeters, 0);
|
||||||
|
var wpfBottomRight = new System.Numerics.Vector2(widthInMeters, heightInMeters);
|
||||||
|
var wpfBottomLeft = new System.Numerics.Vector2(0, heightInMeters);
|
||||||
|
|
||||||
|
// Convertir a coordenadas BEPU usando CoordinateConverter
|
||||||
|
var bepuTopLeft = CoordinateConverter.WpfToBepuVector2(wpfTopLeft);
|
||||||
|
var bepuTopRight = CoordinateConverter.WpfToBepuVector2(wpfTopRight);
|
||||||
|
var bepuBottomRight = CoordinateConverter.WpfToBepuVector2(wpfBottomRight);
|
||||||
|
var bepuBottomLeft = CoordinateConverter.WpfToBepuVector2(wpfBottomLeft);
|
||||||
|
|
||||||
|
// Crear los puntos 3D con Z=0
|
||||||
|
var p1 = new Point3D(bepuTopLeft.X, bepuTopLeft.Y, 0); // Esquina superior izquierda WPF
|
||||||
|
var p2 = new Point3D(bepuTopRight.X, bepuTopRight.Y, 0); // Esquina superior derecha WPF
|
||||||
|
var p3 = new Point3D(bepuBottomRight.X, bepuBottomRight.Y, 0); // Esquina inferior derecha WPF
|
||||||
|
var p4 = new Point3D(bepuBottomLeft.X, bepuBottomLeft.Y, 0); // Esquina inferior izquierda WPF
|
||||||
|
|
||||||
|
// ✅ CORREGIDO: Crear quad con orientación correcta
|
||||||
|
// Orden antihorario para normal hacia arriba (visible desde arriba)
|
||||||
|
meshBuilder.AddQuad(p1, p2, p3, p4);
|
||||||
|
|
||||||
|
// Crear el material con la imagen como textura
|
||||||
|
var imageSource = new BitmapImage(new Uri(imagePath, UriKind.Absolute));
|
||||||
|
var imageBrush = new ImageBrush(imageSource)
|
||||||
|
{
|
||||||
|
Stretch = Stretch.Fill,
|
||||||
|
TileMode = TileMode.None
|
||||||
|
};
|
||||||
|
|
||||||
|
var frontMaterial = new DiffuseMaterial(imageBrush);
|
||||||
|
var backMaterial = new DiffuseMaterial(imageBrush); // ✅ NUEVO: Material para la cara trasera
|
||||||
|
|
||||||
|
// Crear el modelo 3D con material en ambas caras
|
||||||
|
var geometry = meshBuilder.ToMesh();
|
||||||
|
var model = new GeometryModel3D(geometry, frontMaterial)
|
||||||
|
{
|
||||||
|
BackMaterial = backMaterial // ✅ NUEVO: Hace visible desde ambos lados
|
||||||
|
};
|
||||||
|
|
||||||
|
// Crear el visual 3D
|
||||||
|
_backgroundImageVisual = new ModelVisual3D { Content = model };
|
||||||
|
|
||||||
|
// Agregar al viewport
|
||||||
|
viewport3D.Children.Add(_backgroundImageVisual);
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ✅ Imagen de fondo agregada con convenciones WPF-BEPU: {widthInMeters:F2}m x {heightInMeters:F2}m");
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] WPF (0,0) -> BEPU ({bepuTopLeft.X:F2},{bepuTopLeft.Y:F2})");
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] WPF ({widthInMeters:F2},{heightInMeters:F2}) -> BEPU ({bepuBottomRight.X:F2},{bepuBottomRight.Y:F2})");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ❌ ERROR agregando imagen de fondo: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Remueve la imagen de fondo del viewport 3D
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveBackgroundImage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_backgroundImageVisual != null && viewport3D.Children.Contains(_backgroundImageVisual))
|
||||||
|
{
|
||||||
|
viewport3D.Children.Remove(_backgroundImageVisual);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ✅ Imagen de fondo removida");
|
||||||
|
}
|
||||||
|
_backgroundImageVisual = null;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[3D Background] ❌ ERROR removiendo imagen de fondo: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CameraView
|
public enum CameraView
|
||||||
|
|
Loading…
Reference in New Issue