Se añadió un comando para alternar la actualización 3D en MainViewModel, permitiendo habilitar o deshabilitar esta función para mejorar el rendimiento. Se implementó la lógica correspondiente en la visualización 3D y se eliminaron propiedades redundantes en varias clases, optimizando la gestión de objetos en la simulación.

This commit is contained in:
Miguel 2025-07-01 23:08:05 +02:00
parent 3773da0ee3
commit 3e53a51e8b
9 changed files with 233 additions and 329 deletions

View File

@ -0,0 +1,33 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace CtrEditor.Converters
{
public class BooleanToLocalizedTextConverter : IValueConverter
{
public string TrueText { get; set; } = "True";
public string FalseText { get; set; } = "False";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolValue)
{
return boolValue ? TrueText : FalseText;
}
return FalseText;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string text)
{
if (text == TrueText)
return true;
if (text == FalseText)
return false;
}
return false;
}
}
}

View File

@ -419,6 +419,7 @@ namespace CtrEditor
TB3DViewSideCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Side)); TB3DViewSideCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Side));
TB3DViewFrontCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Front)); TB3DViewFrontCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Front));
TB3DViewIsometricCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Isometric)); TB3DViewIsometricCommand = new RelayCommand(() => Visualization3DManager?.SetCameraView(CameraView.Isometric));
TBToggle3DUpdateCommand = new RelayCommand(() => Is3DUpdateEnabled = !Is3DUpdateEnabled);
RenameImageCommand = new RelayCommand<string>(RenameImage); RenameImageCommand = new RelayCommand<string>(RenameImage);
stopwatch_Sim = new Stopwatch(); stopwatch_Sim = new Stopwatch();
@ -1195,6 +1196,20 @@ namespace CtrEditor
[ObservableProperty] [ObservableProperty]
private double plcUpdateSpeed; private double plcUpdateSpeed;
[ObservableProperty]
private bool is3DUpdateEnabled = true;
public ICommand TBToggle3DUpdateCommand { get; }
partial void OnIs3DUpdateEnabledChanged(bool value)
{
// Sincronizar la propiedad con el simulationManager
if (simulationManager != null)
{
simulationManager.Is3DUpdateEnabled = value;
}
}
private void OnDisplayUpdate(object? sender, EventArgs e) private void OnDisplayUpdate(object? sender, EventArgs e)
{ {
if (simSampleCount > 0) if (simSampleCount > 0)
@ -1348,9 +1363,9 @@ namespace CtrEditor
private void OnTick3DUpdate(object? sender, EventArgs e) private void OnTick3DUpdate(object? sender, EventArgs e)
{ {
// Solo actualizar Helix3D si la simulación está detenida // Solo actualizar Helix3D si la simulación está detenida y la actualización 3D está habilitada
// Cuando la simulación está corriendo, la sincronización se hace en simulationManager.Step() // Cuando la simulación está corriendo, la sincronización se hace en simulationManager.Step()
if (!IsSimulationRunning && Visualization3DManager != null) if (!IsSimulationRunning && Is3DUpdateEnabled && Visualization3DManager != null)
{ {
Visualization3DManager.SynchronizeWorld(); Visualization3DManager.SynchronizeWorld();
} }

View File

@ -202,6 +202,36 @@
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBToggle3DUpdateCommand}" ToolTip="Activar/Desactivar actualización Debug 3D para mejorar rendimiento">
<StackPanel>
<Image Source="Icons/app.png" Width="24" Height="24" />
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="Debug3D: {0}">
<Binding Path="Is3DUpdateEnabled">
<Binding.Converter>
<converters:BooleanToLocalizedTextConverter TrueText="Activado" FalseText="Desactivado" />
</Binding.Converter>
</Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Is3DUpdateEnabled}" Value="True">
<Setter Property="Background" Value="LightGreen" />
</DataTrigger>
<DataTrigger Binding="{Binding Is3DUpdateEnabled}" Value="False">
<Setter Property="Background" Value="LightCoral" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</ToolBar> </ToolBar>
</ToolBarTray> </ToolBarTray>

View File

@ -81,12 +81,6 @@ namespace CtrEditor.ObjetosSim
[property: Name("Inercia de Simulación")] [property: Name("Inercia de Simulación")]
private float inercia_desde_simulacion; private float inercia_desde_simulacion;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Conservar objeto cuando sale de transporte")]
[property: Name("Conservar Fuera de Transporte")]
private bool preserve_Outside_Transport;
[ObservableProperty] [ObservableProperty]
[property: Category("Información")] [property: Category("Información")]
[property: Description("Porcentaje de tracción con transporte")] [property: Description("Porcentaje de tracción con transporte")]
@ -136,7 +130,6 @@ namespace CtrEditor.ObjetosSim
Diametro = 0.10f; Diametro = 0.10f;
Mass = 1; Mass = 1;
ColorButton_oculto = Brushes.Gray; ColorButton_oculto = Brushes.Gray;
Preserve_Outside_Transport = true;
} }
public void UpdateAfterMove() public void UpdateAfterMove()
@ -190,9 +183,7 @@ namespace CtrEditor.ObjetosSim
if (SimGeometria.Descartar) if (SimGeometria.Descartar)
RemoverDesdeSimulacion = true; RemoverDesdeSimulacion = true;
// Eliminar la botella si esta fuera de un transporte // ✅ ELIMINADO: Lógica redundante - BEPU.cs ya elimina botellas que caen en Z automáticamente
if (!Preserve_Outside_Transport && !SimGeometria.IsOnAnyTransport())
RemoverDesdeSimulacion = true;
Velocidad_desde_simulacion = SimGeometria.GetLinearVelocity().ToString(); Velocidad_desde_simulacion = SimGeometria.GetLinearVelocity().ToString();
Inercia_desde_simulacion = SimGeometria.Mass; // En BEPU usamos masa en lugar de inercia directa Inercia_desde_simulacion = SimGeometria.Mass; // En BEPU usamos masa en lugar de inercia directa

View File

@ -80,12 +80,6 @@ namespace CtrEditor.ObjetosSim
[property: Name("Inercia Simulación")] [property: Name("Inercia Simulación")]
private float inercia_desde_simulacion; private float inercia_desde_simulacion;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Conservar objeto cuando sale de transporte")]
[property: Name("Conservar Fuera de Transporte")]
private bool preserve_Outside_Transport;
[ObservableProperty] [ObservableProperty]
[property: Category("Información")] [property: Category("Información")]
[property: Description("Porcentaje de tracción con transporte")] [property: Description("Porcentaje de tracción con transporte")]
@ -173,9 +167,7 @@ namespace CtrEditor.ObjetosSim
if (SimGeometria.Descartar) if (SimGeometria.Descartar)
RemoverDesdeSimulacion = true; RemoverDesdeSimulacion = true;
// Eliminar la botella si esta fuera de un transporte // ✅ ELIMINADO: Lógica redundante - BEPU.cs ya elimina botellas que caen en Z automáticamente
if (!Preserve_Outside_Transport && !SimGeometria.IsOnAnyTransport())
RemoverDesdeSimulacion = true;
Velocidad_desde_simulacion = SimGeometria.GetLinearVelocity().ToString(); Velocidad_desde_simulacion = SimGeometria.GetLinearVelocity().ToString();
Inercia_desde_simulacion = SimGeometria.Mass; // En BEPU usamos masa en lugar de inercia directa Inercia_desde_simulacion = SimGeometria.Mass; // En BEPU usamos masa en lugar de inercia directa

View File

@ -40,11 +40,8 @@ namespace CtrEditor.ObjetosSim
[property: Name("Offset Vertical")] [property: Name("Offset Vertical")]
private float offsetTopSalida; private float offsetTopSalida;
[ObservableProperty] // ✅ ELIMINADO: preserve_Outside_Transport - Redundante con ProcessCleanupSystem de BEPU
[property: Description("Las botellas se destruirán si caen fuera del transporte")] // Las botellas que caen en Z son eliminadas automáticamente por BEPU.cs
[property: Category("Configuración")]
[property: Name("Conservar Fuera de Transporte")]
private bool preserve_Outside_Transport;
[ObservableProperty] [ObservableProperty]
[property: Description("Tag PLC para habilitar funcionamiento. 1 => siempre activo")] [property: Description("Tag PLC para habilitar funcionamiento. 1 => siempre activo")]
[property: Category("Enlace PLC")] [property: Category("Enlace PLC")]
@ -185,7 +182,7 @@ namespace CtrEditor.ObjetosSim
{ {
var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y); var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y);
((osBotella)nuevaBotella).Diametro = Diametro_botella; ((osBotella)nuevaBotella).Diametro = Diametro_botella;
((osBotella)nuevaBotella).Preserve_Outside_Transport = Preserve_Outside_Transport; // ✅ ELIMINADO: Preserve_Outside_Transport - Ya no es necesario
nuevaBotella.AutoCreated = true; nuevaBotella.AutoCreated = true;
// Recalcular el tiempo entre botellas por si cambió la velocidad // Recalcular el tiempo entre botellas por si cambió la velocidad

View File

@ -93,7 +93,7 @@ namespace CtrEditor.ObjetosSim
[property: Category("Enlace PLC")] [property: Category("Enlace PLC")]
[property: Description("Motor enlazado al transporte")] [property: Description("Motor enlazado al transporte")]
[property: Name("Motor Enlazado")] [property: Name("Motor Enlazado")]
//[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))] [property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor; string id_Motor;
[JsonIgnore] [JsonIgnore]
@ -101,24 +101,24 @@ namespace CtrEditor.ObjetosSim
partial void OnId_MotorChanged(string value) partial void OnId_MotorChanged(string value)
{ {
//if (Motor != null && motorPropertyChangedHandler != null) if (Motor != null && motorPropertyChangedHandler != null)
// Motor.PropertyChanged -= motorPropertyChangedHandler; Motor.PropertyChanged -= motorPropertyChangedHandler;
//if (_mainViewModel != null && !string.IsNullOrEmpty(value)) if (_mainViewModel != null && !string.IsNullOrEmpty(value))
//{ {
// Motor = (osVMmotorSim)_mainViewModel.ObjetosSimulables.FirstOrDefault(s => s is osVMmotorSim motor && motor.Nombre == value); Motor = (osVMmotorSim)_mainViewModel.ObjetosSimulables.FirstOrDefault(s => s is osVMmotorSim motor && motor.Nombre == value);
// if (Motor != null) if (Motor != null)
// { {
// motorPropertyChangedHandler = (sender, e) => motorPropertyChangedHandler = (sender, e) =>
// { {
// if (e.PropertyName == nameof(osVMmotorSim.Nombre)) if (e.PropertyName == nameof(osVMmotorSim.Nombre))
// { {
// Id_Motor = ((osVMmotorSim)sender).Nombre; Id_Motor = ((osVMmotorSim)sender).Nombre;
// } }
// }; };
// Motor.PropertyChanged += motorPropertyChangedHandler; Motor.PropertyChanged += motorPropertyChangedHandler;
// } }
//} }
} }
public override void AltoChanged(float value) public override void AltoChanged(float value)
@ -337,12 +337,12 @@ namespace CtrEditor.ObjetosSim
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds) public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{ {
//if (Motor != null) if (Motor != null)
// if (Motor is osVMmotorSim id_motor) if (Motor is osVMmotorSim id_motor)
// if (LeerBitTag(Tag_ReleActivatedMotor)) if (LeerBitTag(Tag_ReleActivatedMotor))
// VelocidadActual = id_motor.Velocidad; VelocidadActual = id_motor.Velocidad;
// else else
// VelocidadActual = 0; VelocidadActual = 0;
// Actualizar información de botellas en tiempo real si es un transporte con freno // Actualizar información de botellas en tiempo real si es un transporte con freno
if (EsFreno) if (EsFreno)

View File

@ -696,33 +696,7 @@ namespace CtrEditor.Simulacion
public void SetSpeed(float speed) public void SetSpeed(float speed)
{ {
Speed = speed; Speed = -speed;
}
/// <summary>
/// Configura la velocidad de la curva en metros por segundo
/// Valores positivos mueven en sentido horario, negativos en sentido antihorario
/// </summary>
/// <param name="speedMeterPerSecond">Velocidad en m/s (típicamente entre -5.0 y 5.0)</param>
public void SetCurveSpeed(float speedMeterPerSecond)
{
Speed = speedMeterPerSecond;
}
/// <summary>
/// Detiene completamente la curva
/// </summary>
public void StopCurve()
{
Speed = 0f;
}
/// <summary>
/// Invierte la dirección de la curva manteniendo la misma velocidad
/// </summary>
public void ReverseCurve()
{
Speed = -Speed;
} }
public void UpdateCurve(float innerRadius, float outerRadius, float startAngle, float endAngle) public void UpdateCurve(float innerRadius, float outerRadius, float startAngle, float endAngle)
@ -1514,6 +1488,9 @@ namespace CtrEditor.Simulacion
// Referencia al manager de visualización 3D // Referencia al manager de visualización 3D
public BEPUVisualization3DManager Visualization3DManager { get; set; } public BEPUVisualization3DManager Visualization3DManager { get; set; }
// Propiedad para controlar si la actualización 3D está habilitada
public bool Is3DUpdateEnabled { get; set; } = true;
// Sistema de contactos de transporte para aplicar fuerzas // Sistema de contactos de transporte para aplicar fuerzas
private Dictionary<simBotella, simTransporte> _transportContacts; private Dictionary<simBotella, simTransporte> _transportContacts;
// Sistema de contactos de barrera para detección de paso // Sistema de contactos de barrera para detección de paso
@ -1767,8 +1744,11 @@ namespace CtrEditor.Simulacion
_brakeTransportContacts.Clear(); _brakeTransportContacts.Clear();
} }
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D solo si está habilitado
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1804,7 +1784,10 @@ namespace CtrEditor.Simulacion
Cuerpos.Remove(Objeto); Cuerpos.Remove(Objeto);
// Actualizar visualización 3D tras eliminar objeto // Actualizar visualización 3D tras eliminar objeto
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
} }
public simBotella AddCircle(float diameter, Vector2 position, float mass) public simBotella AddCircle(float diameter, Vector2 position, float mass)
@ -1813,7 +1796,10 @@ namespace CtrEditor.Simulacion
Cuerpos.Add(botella); Cuerpos.Add(botella);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return botella; return botella;
} }
@ -1823,7 +1809,10 @@ namespace CtrEditor.Simulacion
var transporte = new simTransporte(simulation, _deferredActions, width, height, position, angle); var transporte = new simTransporte(simulation, _deferredActions, width, height, position, angle);
Cuerpos.Add(transporte); Cuerpos.Add(transporte);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return transporte; return transporte;
} }
@ -1833,7 +1822,10 @@ namespace CtrEditor.Simulacion
var barrera = new simBarrera(simulation, _deferredActions, width, height, position, angle, detectarCuello); var barrera = new simBarrera(simulation, _deferredActions, width, height, position, angle, detectarCuello);
Cuerpos.Add(barrera); Cuerpos.Add(barrera);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return barrera; return barrera;
} }
@ -1845,7 +1837,10 @@ namespace CtrEditor.Simulacion
var guia = new simGuia(simulation, _deferredActions, width, height, topLeft, angle); var guia = new simGuia(simulation, _deferredActions, width, height, topLeft, angle);
Cuerpos.Add(guia); Cuerpos.Add(guia);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return guia; return guia;
} }
@ -1855,7 +1850,10 @@ namespace CtrEditor.Simulacion
var descarte = new simDescarte(simulation, _deferredActions, diameter, position); var descarte = new simDescarte(simulation, _deferredActions, diameter, position);
Cuerpos.Add(descarte); Cuerpos.Add(descarte);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return descarte; return descarte;
} }
@ -1865,7 +1863,10 @@ namespace CtrEditor.Simulacion
var curve = new simCurve(simulation, _deferredActions, innerRadius, outerRadius, startAngle, endAngle, topLeft, unused); var curve = new simCurve(simulation, _deferredActions, innerRadius, outerRadius, startAngle, endAngle, topLeft, unused);
Cuerpos.Add(curve); Cuerpos.Add(curve);
// Sincronizar con la visualización 3D // Sincronizar con la visualización 3D
Visualization3DManager?.SynchronizeWorld(); if (Is3DUpdateEnabled)
{
Visualization3DManager?.SynchronizeWorld();
}
return curve; return curve;
} }

View File

@ -284,28 +284,7 @@ namespace CtrEditor.Simulacion
var meshBuilder = new MeshBuilder(); var meshBuilder = new MeshBuilder();
meshBuilder.AddSphere(new Point3D(0, 0, 0), (double)radius, 16, 16); meshBuilder.AddSphere(new Point3D(0, 0, 0), (double)radius, 16, 16);
Material material; var model = new GeometryModel3D(meshBuilder.ToMesh(), GetMaterialForSimBase(simObj));
if (simObj is simDescarte)
{
// Material semi-transparente para descartes (85% transparente = 15% opacidad)
var descarteBrush = new SolidColorBrush(Color.FromRgb(255, 100, 255)); // Magenta
descarteBrush.Opacity = 0.15; // 15% opacidad = 85% transparencia
material = MaterialHelper.CreateMaterial(
descarteBrush,
specularPower: 60,
ambient: 120
);
}
else
{
// Material plástico brillante para botellas (rojo)
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(255, 80, 80)),
specularPower: 120,
ambient: 200
);
}
var model = new GeometryModel3D(meshBuilder.ToMesh(), material);
return new ModelVisual3D { Content = model }; return new ModelVisual3D { Content = model };
} }
@ -315,47 +294,7 @@ namespace CtrEditor.Simulacion
var meshBuilder = new MeshBuilder(); var meshBuilder = new MeshBuilder();
meshBuilder.AddBox(new Point3D(0, 0, 0), (double)width, (double)height, (double)length); meshBuilder.AddBox(new Point3D(0, 0, 0), (double)width, (double)height, (double)length);
// Determinar el color según el tipo de simBase y crear material plástico brillante var model = new GeometryModel3D(meshBuilder.ToMesh(), GetMaterialForSimBase(simObj));
Material material;
if (simObj is simGuia)
{
// Material plástico brillante negro para guías
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(50, 50, 50)),
specularPower: 150,
ambient: 180
);
}
else if (simObj is simBarrera)
{
// Material semi-transparente amarillo para barreras (haz de luz)
var yellowBrush = new SolidColorBrush(Color.FromRgb(255, 255, 0));
yellowBrush.Opacity = 0.3; // 30% opacidad para simular haz de luz
material = MaterialHelper.CreateMaterial(
yellowBrush,
specularPower: 50,
ambient: 150
);
}
else if (simObj is simTransporte)
{
// Material plástico brillante verde para transportes
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 180, 80)),
specularPower: 140,
ambient: 200
);
}
else
{
// Material plástico brillante gris por defecto
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(128, 128, 128)),
specularPower: 100,
ambient: 190
);
}
var model = new GeometryModel3D(meshBuilder.ToMesh(), material);
return new ModelVisual3D { Content = model }; return new ModelVisual3D { Content = model };
} }
@ -385,58 +324,8 @@ namespace CtrEditor.Simulacion
var p2 = new Point3D(0, 0, length / 2); var p2 = new Point3D(0, 0, length / 2);
meshBuilder.AddCylinder(p1, p2, radius: (double)radius, thetaDiv: 16, cap1: true, cap2: true); meshBuilder.AddCylinder(p1, p2, radius: (double)radius, thetaDiv: 16, cap1: true, cap2: true);
// Determinar el color según el tipo de simBase - Material plástico con reflexión (valores originales)
Material material;
if (simObj is simBotella)
{
// Material plástico brillante rojo para botellas (cilindros)
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Colors.Red),
specularPower: 120,
ambient: 200
);
}
else if (simObj is simTransporte)
{
// Material plástico verde para transportes (valores originales)
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 180, 80)),
specularPower: 140,
ambient: 200
);
}
else if (simObj is simGuia)
{
// Material plástico gris oscuro para guías (valores originales)
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(50, 50, 50)),
specularPower: 150,
ambient: 180
);
}
else if (simObj is simBarrera)
{
// Material semi-transparente amarillo para barreras (haz de luz)
var yellowBrush = new SolidColorBrush(Color.FromRgb(255, 255, 0));
yellowBrush.Opacity = 0.3; // 30% opacidad para simular haz de luz
material = MaterialHelper.CreateMaterial(
yellowBrush,
specularPower: 50,
ambient: 150
);
}
else
{
// Material plástico gris estándar para objetos no identificados (valores originales)
material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(128, 128, 128)),
specularPower: 100,
ambient: 190
);
}
var geometry = meshBuilder.ToMesh(); var geometry = meshBuilder.ToMesh();
var model = new GeometryModel3D(geometry, material); var model = new GeometryModel3D(geometry, GetMaterialForSimBase(simObj));
var visual = new ModelVisual3D(); var visual = new ModelVisual3D();
visual.Content = model; visual.Content = model;
@ -452,15 +341,8 @@ namespace CtrEditor.Simulacion
// ✅ NUEVO: Usar directamente los triángulos originales de BEPU (debug real) // ✅ NUEVO: Usar directamente los triángulos originales de BEPU (debug real)
CreateCurveMeshFromBEPUTriangles(meshBuilder, curve); CreateCurveMeshFromBEPUTriangles(meshBuilder, curve);
// Material plástico brillante para curvas (azul verdoso)
var material = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 150, 200)),
specularPower: 130,
ambient: 190
);
var geometry = meshBuilder.ToMesh(); var geometry = meshBuilder.ToMesh();
var model = new GeometryModel3D(geometry, material); var model = new GeometryModel3D(geometry, GetMaterialForSimBase(curve));
var visual = new ModelVisual3D(); var visual = new ModelVisual3D();
visual.Content = model; visual.Content = model;
@ -781,13 +663,7 @@ namespace CtrEditor.Simulacion
meshBuilder.AddCylinder(p1, p2, radius: (double)botella.Radius, thetaDiv: 16, cap1: true, cap2: true); meshBuilder.AddCylinder(p1, p2, radius: (double)botella.Radius, thetaDiv: 16, cap1: true, cap2: true);
newGeometry = meshBuilder.ToMesh(); newGeometry = meshBuilder.ToMesh();
newMaterial = GetMaterialForSimBase(simObj);
// Material específico para botellas - rojo brillante
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Colors.Red),
specularPower: 120,
ambient: 200
);
} }
// Caso especial: simCurve necesita recreación completa de geometría // Caso especial: simCurve necesita recreación completa de geometría
else if (simObj is simCurve curve) else if (simObj is simCurve curve)
@ -800,13 +676,7 @@ namespace CtrEditor.Simulacion
CreateCurveMeshFromBEPUTriangles(meshBuilder, curve); CreateCurveMeshFromBEPUTriangles(meshBuilder, curve);
newGeometry = meshBuilder.ToMesh(); newGeometry = meshBuilder.ToMesh();
newMaterial = GetMaterialForSimBase(simObj);
// Material específico para curvas - azul verdoso brillante
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 150, 200)),
specularPower: 130,
ambient: 190
);
System.Diagnostics.Debug.WriteLine($"[3D Recreate] CURVE mesh created successfully with {newGeometry?.Positions?.Count ?? 0} vertices"); System.Diagnostics.Debug.WriteLine($"[3D Recreate] CURVE mesh created successfully with {newGeometry?.Positions?.Count ?? 0} vertices");
} }
@ -815,112 +685,14 @@ namespace CtrEditor.Simulacion
var meshBuilder = new MeshBuilder(); var meshBuilder = new MeshBuilder();
meshBuilder.AddSphere(new Point3D(0, 0, 0), dimensions.Radius); meshBuilder.AddSphere(new Point3D(0, 0, 0), dimensions.Radius);
newGeometry = meshBuilder.ToMesh(); newGeometry = meshBuilder.ToMesh();
newMaterial = GetMaterialForSimBase(simObj);
// Color según tipo de objeto - Material plástico con reflexión (valores originales)
if (simObj is simDescarte)
{
// Material semi-transparente para descartes (85% transparente = 15% opacidad)
var descarteBrush = new SolidColorBrush(Color.FromRgb(255, 100, 255)); // Magenta
descarteBrush.Opacity = 0.15; // 15% opacidad = 85% transparencia
newMaterial = MaterialHelper.CreateMaterial(
descarteBrush,
specularPower: 60,
ambient: 120
);
}
else if (simObj is simBotella)
{
// Material plástico brillante rojo para botellas
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Colors.Red),
specularPower: 120,
ambient: 200
);
}
else if (simObj is simTransporte)
{
// Material plástico verde para transportes (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 180, 80)),
specularPower: 140,
ambient: 200
);
}
else if (simObj is simGuia)
{
// Material plástico gris oscuro para guías (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(50, 50, 50)),
specularPower: 150,
ambient: 180
);
}
else if (simObj is simBarrera)
{
// Material semi-transparente amarillo para barreras (haz de luz)
var yellowBrush = new SolidColorBrush(Color.FromRgb(255, 255, 0));
yellowBrush.Opacity = 0.3; // 30% opacidad para simular haz de luz
newMaterial = MaterialHelper.CreateMaterial(
yellowBrush,
specularPower: 50,
ambient: 150
);
}
else
{
// Material plástico gris estándar para otras esferas (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(128, 128, 128)),
specularPower: 100,
ambient: 190
);
}
} }
else if (dimensions.ShapeType == BepuPhysics.Collidables.Box.Id) else if (dimensions.ShapeType == BepuPhysics.Collidables.Box.Id)
{ {
var meshBuilder = new MeshBuilder(); var meshBuilder = new MeshBuilder();
meshBuilder.AddBox(new Point3D(0, 0, 0), dimensions.Width, dimensions.Height, dimensions.Length); meshBuilder.AddBox(new Point3D(0, 0, 0), dimensions.Width, dimensions.Height, dimensions.Length);
newGeometry = meshBuilder.ToMesh(); newGeometry = meshBuilder.ToMesh();
newMaterial = GetMaterialForSimBase(simObj);
// Color según tipo de objeto - Material plástico con reflexión (valores originales)
if (simObj is simTransporte)
{
// Material plástico verde para transportes (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 180, 80)),
specularPower: 140,
ambient: 200
);
}
else if (simObj is simGuia)
{
// Material plástico gris oscuro para guías (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(50, 50, 50)),
specularPower: 150,
ambient: 180
);
}
else if (simObj is simBarrera)
{
// Material semi-transparente amarillo para barreras (haz de luz)
var yellowBrush = new SolidColorBrush(Color.FromRgb(255, 255, 0));
yellowBrush.Opacity = 0.3; // 30% opacidad para simular haz de luz
newMaterial = MaterialHelper.CreateMaterial(
yellowBrush,
specularPower: 50,
ambient: 150
);
}
else
{
// Material plástico gris estándar para otros boxes (valores originales)
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(128, 128, 128)),
specularPower: 100,
ambient: 190
);
}
} }
else if (dimensions.ShapeType == BepuPhysics.Collidables.Cylinder.Id) else if (dimensions.ShapeType == BepuPhysics.Collidables.Cylinder.Id)
{ {
@ -932,12 +704,7 @@ namespace CtrEditor.Simulacion
meshBuilder.AddCylinder(p1, p2, radius: (double)dimensions.Radius, thetaDiv: 16, cap1: true, cap2: true); meshBuilder.AddCylinder(p1, p2, radius: (double)dimensions.Radius, thetaDiv: 16, cap1: true, cap2: true);
newGeometry = meshBuilder.ToMesh(); newGeometry = meshBuilder.ToMesh();
newMaterial = GetMaterialForSimBase(simObj);
newMaterial = MaterialHelper.CreateMaterial(
new SolidColorBrush(Colors.Green),
specularPower: 135,
ambient: 205
);
} }
if (newGeometry != null) if (newGeometry != null)
@ -963,6 +730,84 @@ namespace CtrEditor.Simulacion
lastKnownDimensions.Clear(); lastKnownDimensions.Clear();
} }
/// <summary>
/// Función centralizada para obtener el material apropiado según el tipo de simBase
/// </summary>
/// <param name="simObj">Objeto de simulación para determinar el material</param>
/// <returns>Material configurado para el tipo de objeto</returns>
private Material GetMaterialForSimBase(simBase simObj)
{
if (simObj is simTransporte)
{
// Material plástico verde para transportes
return MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 180, 80)),
specularPower: 140,
ambient: 200
);
}
else if (simObj is simGuia)
{
// Material semitransparente gris oscuro para guías
var guiaBrush = new SolidColorBrush(Color.FromRgb(80, 80, 80));
guiaBrush.Opacity = 0.4; // 40% opacidad para mejor visualización semitransparente
return MaterialHelper.CreateMaterial(
guiaBrush,
specularPower: 30,
ambient: 100
);
}
else if (simObj is simBarrera)
{
// Material semi-transparente amarillo para barreras (haz de luz)
var yellowBrush = new SolidColorBrush(Color.FromRgb(255, 255, 0));
yellowBrush.Opacity = 0.3; // 30% opacidad para simular haz de luz
return MaterialHelper.CreateMaterial(
yellowBrush,
specularPower: 50,
ambient: 150
);
}
else if (simObj is simBotella)
{
// Material plástico brillante rojo para botellas
return MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(255, 80, 80)),
specularPower: 120,
ambient: 200
);
}
else if (simObj is simDescarte)
{
// Material semi-transparente magenta para descartes (85% transparente)
var descarteBrush = new SolidColorBrush(Color.FromRgb(255, 100, 255));
descarteBrush.Opacity = 0.15; // 15% opacidad = 85% transparencia
return MaterialHelper.CreateMaterial(
descarteBrush,
specularPower: 60,
ambient: 120
);
}
else if (simObj is simCurve)
{
// Material plástico brillante para curvas (azul verdoso)
return MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(80, 150, 200)),
specularPower: 130,
ambient: 190
);
}
else
{
// Material plástico gris estándar para objetos no identificados
return MaterialHelper.CreateMaterial(
new SolidColorBrush(Color.FromRgb(128, 128, 128)),
specularPower: 100,
ambient: 190
);
}
}
public void SetCameraView(CameraView view) public void SetCameraView(CameraView view)
{ {
if (viewport3D?.Camera is not PerspectiveCamera camera) return; if (viewport3D?.Camera is not PerspectiveCamera camera) return;