Se eliminaron archivos de documentación innecesarios en el proyecto y se realizaron ajustes en la visibilidad de métodos en la clase osBase, cambiando de privado a protegido. Se implementó un nuevo método para verificar las dimensiones de los descartes y se mejoró la lógica de actualización de geometrías en ucDescarte y ucGuia, utilizando un sistema inteligente para optimizar el rendimiento. Además, se corrigieron errores en la conversión de coordenadas y se restauró el factor de conversión de velocidad en BEPU.
This commit is contained in:
parent
fd215bc677
commit
e38adc9f56
|
@ -35,6 +35,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Remove="Documentation\BEPU Forces.cs" />
|
||||||
<Compile Remove="Documentation\PlantillaEstandarizacion.cs" />
|
<Compile Remove="Documentation\PlantillaEstandarizacion.cs" />
|
||||||
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
|
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -84,6 +85,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="Documentation\BEPU Forces.cs" />
|
||||||
<None Include="Documentation\PlantillaEstandarizacion.cs" />
|
<None Include="Documentation\PlantillaEstandarizacion.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -41,7 +41,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
partial void OnDiametroChanged(float value)
|
partial void OnDiametroChanged(float value)
|
||||||
{
|
{
|
||||||
SimGeometria?.SetDiameter(Diametro);
|
ActualizarGeometrias();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 GetCentro()
|
public Vector2 GetCentro()
|
||||||
|
@ -73,8 +73,15 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
if (SimGeometria != null)
|
if (SimGeometria != null)
|
||||||
{
|
{
|
||||||
SimGeometria.SetDiameter(Diametro);
|
// ✅ SISTEMA INTELIGENTE: Solo recrear si el diámetro cambió
|
||||||
SimGeometria.SetPosition(GetCentro());
|
if (HasDiscardDimensionsChanged(SimGeometria, Diametro))
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[osDescarte] Recreando descarte por cambio de diámetro");
|
||||||
|
SimGeometria.SetDiameter(Diametro);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ USAR MÉTODO COORDINATECONVERTER
|
||||||
|
SimGeometria.UpdateFromWpfCenter(GetCentro());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,16 +37,30 @@ namespace CtrEditor.ObjetosSim
|
||||||
[property: Name("Grosor de la Guía")]
|
[property: Name("Grosor de la Guía")]
|
||||||
public float altoGuia;
|
public float altoGuia;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void ActualizarGeometrias()
|
private void ActualizarGeometrias()
|
||||||
{
|
{
|
||||||
if (_visualRepresentation is ucGuia uc)
|
if (_visualRepresentation is ucGuia uc && SimGeometria != null)
|
||||||
{
|
{
|
||||||
// Actualizar las propiedades del objeto de simulación
|
var topLeft = new Vector2(Left, Top);
|
||||||
if (SimGeometria != null)
|
|
||||||
|
// ✅ SISTEMA INTELIGENTE: Solo recrear si las dimensiones han cambiado
|
||||||
|
if (HasGuideDimensionsChanged(SimGeometria, Ancho, AltoGuia))
|
||||||
{
|
{
|
||||||
SimGeometria.UpdateProperties(Ancho, AltoGuia, Angulo);
|
System.Diagnostics.Debug.WriteLine($"[osGuia] Recreando guía por cambio de dimensiones: {Ancho}x{AltoGuia}");
|
||||||
|
|
||||||
|
// ✅ RECREAR COMPLETAMENTE: Las dimensiones cambiaron
|
||||||
|
SimGeometria.Create(Ancho, AltoGuia, topLeft, Angulo);
|
||||||
|
SimGeometria.SetDimensions(Ancho, AltoGuia);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[osGuia] Solo actualizando posición/rotación: Left={Left}, Top={Top}, Angulo={Angulo}");
|
||||||
|
|
||||||
|
// ✅ SOLO ACTUALIZAR POSICIÓN/ROTACIÓN: Usar dimensiones reales para conversión correcta
|
||||||
|
SimGeometria.UpdateFromWpfParameters(topLeft, Angulo, Ancho, AltoGuia);
|
||||||
}
|
}
|
||||||
UpdateOrCreateLine(SimGeometria, uc.Guia);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,15 +258,15 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Actualizar posición en BEPU cuando cambia la posición del objeto
|
/// ✅ CORREGIDO: Actualizar posición en BEPU usando métodos de conversión apropiados
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ActualizarPosicionBEPU()
|
private void ActualizarPosicionBEPU()
|
||||||
{
|
{
|
||||||
if (Simulation_TransporteCurvaGuias != null)
|
if (Simulation_TransporteCurvaGuias != null)
|
||||||
{
|
{
|
||||||
// Recrear la curva con nueva posición usando el mismo patrón que ucTransporteCurva
|
// ✅ USAR MÉTODOS DE COORDINATECONVERTER
|
||||||
var topLeft = new Vector2(Left, Top);
|
var topLeft = new Vector2(Left, Top);
|
||||||
Simulation_TransporteCurvaGuias.Create(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados, topLeft, 0);
|
Simulation_TransporteCurvaGuias.UpdateFromWpfParameters(topLeft, 0f, RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
|
||||||
|
|
||||||
// Recrear las guías en la nueva posición
|
// Recrear las guías en la nueva posición
|
||||||
ActualizarGuiasCurvas();
|
ActualizarGuiasCurvas();
|
||||||
|
@ -286,7 +286,12 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
if (_visualRepresentation is ucTransporteCurvaGuias uc)
|
if (_visualRepresentation is ucTransporteCurvaGuias uc)
|
||||||
{
|
{
|
||||||
Simulation_TransporteCurvaGuias?.UpdateCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
|
// ✅ USAR MÉTODO DE COORDINATECONVERTER PARA ACTUALIZACIÓN COMPLETA
|
||||||
|
if (Simulation_TransporteCurvaGuias != null)
|
||||||
|
{
|
||||||
|
var topLeft = new Vector2(Left, Top);
|
||||||
|
Simulation_TransporteCurvaGuias.UpdateFromWpfParameters(topLeft, 0f, RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
|
||||||
|
}
|
||||||
ActualizarGuiasCurvas();
|
ActualizarGuiasCurvas();
|
||||||
SetSpeed();
|
SetSpeed();
|
||||||
}
|
}
|
||||||
|
@ -327,7 +332,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
if (radioGuiaInferior < 0.01f)
|
if (radioGuiaInferior < 0.01f)
|
||||||
radioGuiaInferior = 0.01f;
|
radioGuiaInferior = 0.01f;
|
||||||
|
|
||||||
// Convertir ángulos a radianes
|
// ✅ CORREGIDO: Convertir ángulos a radianes usando método estándar
|
||||||
float anguloInicioRad = simBase.GradosARadianes(Angulo);
|
float anguloInicioRad = simBase.GradosARadianes(Angulo);
|
||||||
float anguloFinalRad = simBase.GradosARadianes(AnguloFinal);
|
float anguloFinalRad = simBase.GradosARadianes(AnguloFinal);
|
||||||
float rangoAngular = anguloFinalRad - anguloInicioRad;
|
float rangoAngular = anguloFinalRad - anguloInicioRad;
|
||||||
|
@ -390,7 +395,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Método helper para crear una guía desde dos puntos
|
/// ✅ CORREGIDO: Método helper para crear una guía desde dos puntos usando conversiones apropiadas
|
||||||
/// Convierte dos puntos Vector2 a los parámetros requeridos por AddLine
|
/// Convierte dos puntos Vector2 a los parámetros requeridos por AddLine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private simGuia CrearGuiaDesdeDosPuntos(Vector2 punto1, Vector2 punto2)
|
private simGuia CrearGuiaDesdeDosPuntos(Vector2 punto1, Vector2 punto2)
|
||||||
|
@ -404,10 +409,10 @@ namespace CtrEditor.ObjetosSim
|
||||||
if (longitud < 0.001f) // Evitar líneas de longitud cero
|
if (longitud < 0.001f) // Evitar líneas de longitud cero
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Calcular el ángulo de la línea
|
// ✅ CORREGIDO: Calcular el ángulo de la línea correctamente para WPF
|
||||||
float angulo = (float)Math.Atan2(direccion.Y, direccion.X) * 180f / (float)Math.PI;
|
float angulo = (float)Math.Atan2(direccion.Y, direccion.X) * 180f / (float)Math.PI;
|
||||||
|
|
||||||
// Usar punto1 como topLeft y la longitud como width
|
// ✅ USAR punto1 como topLeft - simulationManager.AddLine ya maneja las conversiones WPF->BEPU
|
||||||
return simulationManager.AddLine(longitud, GrosorGuias, punto1, angulo);
|
return simulationManager.AddLine(longitud, GrosorGuias, punto1, angulo);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -532,7 +537,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
if (_visualRepresentation is ucTransporteCurvaGuias uc)
|
if (_visualRepresentation is ucTransporteCurvaGuias uc)
|
||||||
{
|
{
|
||||||
// ✅ CORRIGIDO: Usar simulationManager?.AddCurve con todos los parámetros requeridos
|
// ✅ CORREGIDO: Usar simulationManager?.AddCurve con conversión WPF correcta
|
||||||
var topLeft = new Vector2(Left, Top);
|
var topLeft = new Vector2(Left, Top);
|
||||||
Simulation_TransporteCurvaGuias = simulationManager?.AddCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados, topLeft, 0);
|
Simulation_TransporteCurvaGuias = simulationManager?.AddCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados, topLeft, 0);
|
||||||
CrearGuiasCurvas(); // Crear las guías curvas
|
CrearGuiasCurvas(); // Crear las guías curvas
|
||||||
|
|
|
@ -1747,7 +1747,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifica si las dimensiones de un transporte han cambiado
|
/// Verifica si las dimensiones de un transporte han cambiado
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool HasTransportDimensionsChanged(simTransporte transport, float newWidth, float newHeight)
|
protected bool HasTransportDimensionsChanged(simTransporte transport, float newWidth, float newHeight)
|
||||||
{
|
{
|
||||||
if (transport == null) return true;
|
if (transport == null) return true;
|
||||||
|
|
||||||
|
@ -1780,7 +1780,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifica si las dimensiones de una barrera han cambiado
|
/// Verifica si las dimensiones de una barrera han cambiado
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool HasBarrierDimensionsChanged(simBarrera barrier, float newWidth, float newHeight)
|
protected bool HasBarrierDimensionsChanged(simBarrera barrier, float newWidth, float newHeight)
|
||||||
{
|
{
|
||||||
if (barrier == null) return true;
|
if (barrier == null) return true;
|
||||||
|
|
||||||
|
@ -1813,7 +1813,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifica si las dimensiones de una guía han cambiado
|
/// Verifica si las dimensiones de una guía han cambiado
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool HasGuideDimensionsChanged(simGuia guide, float newWidth, float newHeight)
|
protected bool HasGuideDimensionsChanged(simGuia guide, float newWidth, float newHeight)
|
||||||
{
|
{
|
||||||
if (guide == null) return true;
|
if (guide == null) return true;
|
||||||
|
|
||||||
|
@ -1843,6 +1843,41 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO - Sistema inteligente de verificación de dimensiones de descartes
|
||||||
|
/// Verifica si el diámetro de un descarte ha cambiado
|
||||||
|
/// </summary>
|
||||||
|
protected bool HasDiscardDimensionsChanged(simDescarte discard, float newDiameter)
|
||||||
|
{
|
||||||
|
if (discard == null) return true;
|
||||||
|
|
||||||
|
var newDimensions = new SimObjectDimensions
|
||||||
|
{
|
||||||
|
Width = newDiameter,
|
||||||
|
Height = newDiameter,
|
||||||
|
Radius = newDiameter / 2f,
|
||||||
|
ObjectType = 4 // Tipo 4 = Descarte
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_lastKnownDimensions.TryGetValue(discard, out var lastDimensions))
|
||||||
|
{
|
||||||
|
bool changed = !newDimensions.Equals(lastDimensions);
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
_lastKnownDimensions[discard] = newDimensions;
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Dimensions] Discard dimensions CHANGED: Ø{newDiameter}");
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Primera vez - consideramos como cambio
|
||||||
|
_lastKnownDimensions[discard] = newDimensions;
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Dimensions] Discard first time: Ø{newDiameter}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Limpia las dimensiones almacenadas para un objeto específico
|
/// Limpia las dimensiones almacenadas para un objeto específico
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -231,8 +231,8 @@ namespace CtrEditor.Simulacion
|
||||||
public Simulation _simulation;
|
public Simulation _simulation;
|
||||||
protected bool _bodyCreated = false; // Bandera para saber si hemos creado un cuerpo
|
protected bool _bodyCreated = false; // Bandera para saber si hemos creado un cuerpo
|
||||||
|
|
||||||
// ✅ NUEVA CONSTANTE - unificar conversión de velocidad
|
// ✅ CORREGIDO: Restaurar factor de conversión correcto
|
||||||
public const float SPEED_CONVERSION_FACTOR = 1f; //18.5f; // Factor de conversión de velocidad interna a m/s
|
public const float SPEED_CONVERSION_FACTOR = 1/2f; // Factor de conversión de velocidad interna a m/s - Para LinearAxisMotor es 0.5f
|
||||||
|
|
||||||
// Constantes para las posiciones Z de los objetos 3D
|
// Constantes para las posiciones Z de los objetos 3D
|
||||||
public const float zPos_Transporte = 0f; // Z de la parte baja
|
public const float zPos_Transporte = 0f; // Z de la parte baja
|
||||||
|
@ -390,6 +390,20 @@ namespace CtrEditor.Simulacion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ SOBRESCRITO: SetRotation que actualiza automáticamente las propiedades cacheadas
|
||||||
|
/// </summary>
|
||||||
|
public new void SetRotation(float wpfAngle)
|
||||||
|
{
|
||||||
|
base.SetRotation(wpfAngle);
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Actualizar propiedades cacheadas después del cambio de rotación
|
||||||
|
UpdateCachedProperties();
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Disparar evento para actualizar motores activos con nueva dirección
|
||||||
|
OnSpeedChanged?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
public new void SetPosition(float x, float y, float z = 0)
|
public new void SetPosition(float x, float y, float z = 0)
|
||||||
{
|
{
|
||||||
base.SetPosition(x, y, z);
|
base.SetPosition(x, y, z);
|
||||||
|
@ -398,7 +412,7 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Actualiza posición desde Top-Left WPF con dimensiones y ángulo actuales
|
/// ✅ NUEVO: Actualiza posición desde Top-Left WPF con dimensiones y ángulo actuales
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetPositionFromWpfTopLeft(Vector2 wpfTopLeft)
|
internal void SetPositionFromWpfTopLeft(Vector2 wpfTopLeft)
|
||||||
{
|
{
|
||||||
var currentWpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
var currentWpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
||||||
var zPosition = GetPosition().Z; // Mantener Z actual
|
var zPosition = GetPosition().Z; // Mantener Z actual
|
||||||
|
@ -409,7 +423,7 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Obtiene Top-Left WPF desde la posición actual
|
/// ✅ NUEVO: Obtiene Top-Left WPF desde la posición actual
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 GetWpfTopLeft()
|
internal Vector2 GetWpfTopLeft()
|
||||||
{
|
{
|
||||||
var bepuCenter = GetPosition();
|
var bepuCenter = GetPosition();
|
||||||
var wpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
var wpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
||||||
|
@ -419,22 +433,53 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF
|
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle)
|
internal void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle)
|
||||||
{
|
{
|
||||||
var zPosition = GetPosition().Z; // Mantener Z actual
|
var zPosition = GetPosition().Z; // Mantener Z actual
|
||||||
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, Width, Height, wpfAngle, zPosition);
|
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, Width, Height, wpfAngle, zPosition);
|
||||||
CoordinateConverter.UpdateBepuBodyPose(_simulation, BodyHandle, bepuCenter, wpfAngle);
|
CoordinateConverter.UpdateBepuBodyPose(_simulation, BodyHandle, bepuCenter, wpfAngle);
|
||||||
|
|
||||||
// Actualizar propiedades cacheadas después del cambio
|
// ✅ CRÍTICO: Actualizar propiedades cacheadas después del cambio de orientación
|
||||||
UpdateCachedProperties();
|
UpdateCachedProperties();
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Disparar evento para actualizar motores activos con nueva dirección
|
||||||
|
OnSpeedChanged?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ NUEVO MÉTODO - actualizar propiedades cacheadas
|
// ✅ NUEVO MÉTODO - actualizar propiedades cacheadas
|
||||||
public void UpdateCachedProperties()
|
internal void UpdateCachedProperties()
|
||||||
{
|
{
|
||||||
// Calcular dirección basada en rotación actual
|
// ✅ CORREGIDO: La dirección siempre es UnitX rotado por el ángulo del transporte
|
||||||
var angle = GetRotationZ();
|
// NO depende de las dimensiones (Width >= Height) sino solo de la rotación
|
||||||
DirectionVector = new Vector3((float)Math.Cos(angle), (float)Math.Sin(angle), 0);
|
if (_simulation != null && _simulation.Bodies.BodyExists(BodyHandle))
|
||||||
|
{
|
||||||
|
var bodyReference = _simulation.Bodies.GetBodyReference(BodyHandle);
|
||||||
|
var bepuQuaternion = bodyReference.Pose.Orientation;
|
||||||
|
|
||||||
|
// ✅ SIEMPRE usar UnitX y aplicar la rotación
|
||||||
|
DirectionVector = Vector3.Transform(Vector3.UnitX, bepuQuaternion);
|
||||||
|
|
||||||
|
// 🔍 DEBUG: Agregar información detallada
|
||||||
|
var wpfAngle = GetRotationZ();
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[UpdateCached] WPF Angle: {wpfAngle}°, DirectionVector: {DirectionVector}, Length: {DirectionVector.Length()}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ✅ CORREGIDO: Aplicar conversión de coordenadas WPF→BEPU en el vector
|
||||||
|
var wpfAngle = GetRotationZ(); // Ángulo WPF en grados
|
||||||
|
var wpfAngleRadians = GradosARadianes(wpfAngle);
|
||||||
|
|
||||||
|
// Calcular el vector en coordenadas WPF
|
||||||
|
var wpfX = (float)Math.Cos(wpfAngleRadians);
|
||||||
|
var wpfY = (float)Math.Sin(wpfAngleRadians);
|
||||||
|
|
||||||
|
// ✅ APLICAR CONVERSIÓN Y: En WPF Y+ es abajo, en BEPU Y+ es arriba
|
||||||
|
DirectionVector = new Vector3(wpfX, -wpfY, 0); // Invertir Y para conversión WPF→BEPU
|
||||||
|
|
||||||
|
// 🔍 DEBUG: Agregar información detallada
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[UpdateCached-Fallback] WPF Angle: {wpfAngle}°, WPF Vector: ({wpfX:F3}, {wpfY:F3}), BEPU DirectionVector: {DirectionVector}, Length: {DirectionVector.Length()}");
|
||||||
|
}
|
||||||
|
|
||||||
SpeedMetersPerSecond = Speed / SPEED_CONVERSION_FACTOR;
|
SpeedMetersPerSecond = Speed / SPEED_CONVERSION_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,6 +530,12 @@ namespace CtrEditor.Simulacion
|
||||||
var shapeIndex = _simulation.Shapes.Add(box);
|
var shapeIndex = _simulation.Shapes.Add(box);
|
||||||
ChangeBodyShape(shapeIndex);
|
ChangeBodyShape(shapeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Actualizar propiedades cacheadas después del cambio de dimensiones
|
||||||
|
UpdateCachedProperties();
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Disparar evento para actualizar motores activos con nueva dirección
|
||||||
|
OnSpeedChanged?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(float width, float height, Vector2 wpfTopLeft, float wpfAngle = 0)
|
public void Create(float width, float height, Vector2 wpfTopLeft, float wpfAngle = 0)
|
||||||
|
@ -549,6 +600,9 @@ namespace CtrEditor.Simulacion
|
||||||
|
|
||||||
BodyHandle = _simulation.Bodies.Add(bodyDescription);
|
BodyHandle = _simulation.Bodies.Add(bodyDescription);
|
||||||
_bodyCreated = true; // Marcar que hemos creado un cuerpo
|
_bodyCreated = true; // Marcar que hemos creado un cuerpo
|
||||||
|
|
||||||
|
// ✅ CRÍTICO: Actualizar propiedades cacheadas después de crear el body
|
||||||
|
UpdateCachedProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +652,7 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Actualiza posición desde Top-Left WPF con dimensiones y ángulo actuales
|
/// ✅ NUEVO: Actualiza posición desde Top-Left WPF con dimensiones y ángulo actuales
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetPositionFromWpfTopLeft(Vector2 wpfTopLeft)
|
internal void SetPositionFromWpfTopLeft(Vector2 wpfTopLeft)
|
||||||
{
|
{
|
||||||
var currentWpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
var currentWpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
||||||
var zPosition = GetPosition().Z; // Mantener Z actual
|
var zPosition = GetPosition().Z; // Mantener Z actual
|
||||||
|
@ -609,7 +663,7 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Obtiene Top-Left WPF desde la posición actual
|
/// ✅ NUEVO: Obtiene Top-Left WPF desde la posición actual
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 GetWpfTopLeft()
|
internal Vector2 GetWpfTopLeft()
|
||||||
{
|
{
|
||||||
var bepuCenter = GetPosition();
|
var bepuCenter = GetPosition();
|
||||||
var wpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
var wpfAngle = GetRotationZ(); // Ya usa CoordinateConverter
|
||||||
|
@ -619,7 +673,7 @@ namespace CtrEditor.Simulacion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF
|
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle)
|
internal void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle)
|
||||||
{
|
{
|
||||||
var zPosition = GetPosition().Z; // Mantener Z actual
|
var zPosition = GetPosition().Z; // Mantener Z actual
|
||||||
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, Width, Height, wpfAngle, zPosition);
|
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, Width, Height, wpfAngle, zPosition);
|
||||||
|
@ -735,20 +789,39 @@ namespace CtrEditor.Simulacion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO - Actualiza solo la posición sin recrear el objeto usando CoordinateConverter
|
/// ✅ CORREGIDO - Actualiza solo la posición sin recrear el objeto usando CoordinateConverter
|
||||||
|
/// Requiere las dimensiones reales para conversión correcta Top-Left → Center
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetPosition(Vector2 wpfTopLeft, float wpfAngle = 0)
|
public void SetPosition(Vector2 wpfTopLeft, float wpfAngle, float actualWidth, float actualHeight)
|
||||||
{
|
{
|
||||||
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada con dimensiones reales
|
||||||
var zPosition = zAltura_Guia / 2 + zPos_Guia;
|
var zPosition = zAltura_Guia / 2 + zPos_Guia;
|
||||||
// Usar las dimensiones actuales de la guía
|
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, actualWidth, actualHeight, wpfAngle, zPosition);
|
||||||
var width = GuideThickness; // Para guías, el ancho puede ser derivado del espesor
|
|
||||||
var height = GuideThickness;
|
|
||||||
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, width, height, wpfAngle, zPosition);
|
|
||||||
|
|
||||||
// Actualizar posición y rotación simultáneamente
|
// Actualizar posición y rotación simultáneamente
|
||||||
CoordinateConverter.UpdateBepuBodyPose(_simulation, BodyHandle, bepuCenter, wpfAngle);
|
CoordinateConverter.UpdateBepuBodyPose(_simulation, BodyHandle, bepuCenter, wpfAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF (sobrecarga para compatibilidad)
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle, float width, float height)
|
||||||
|
{
|
||||||
|
// Usar el método SetPosition con dimensiones correctas
|
||||||
|
SetPosition(wpfTopLeft, wpfAngle, width, height);
|
||||||
|
|
||||||
|
// Actualizar propiedades internas
|
||||||
|
GuideThickness = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ LEGACY - Mantener compatibilidad con versión anterior (usar dimensiones almacenadas)
|
||||||
|
/// </summary>
|
||||||
|
public void SetPosition(Vector2 wpfTopLeft, float wpfAngle = 0)
|
||||||
|
{
|
||||||
|
// Fallback: usar GuideThickness como aproximación si no se proporcionan dimensiones
|
||||||
|
SetPosition(wpfTopLeft, wpfAngle, GuideThickness * 10f, GuideThickness);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class simBotella : simBase
|
public class simBotella : simBase
|
||||||
|
@ -785,9 +858,8 @@ namespace CtrEditor.Simulacion
|
||||||
_neckRadius = neckRadius;
|
_neckRadius = neckRadius;
|
||||||
ListOnTransports = new List<simBase>();
|
ListOnTransports = new List<simBase>();
|
||||||
|
|
||||||
// Convertir Vector2 a Vector3 con Z=0.2 (altura estándar para botellas)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
// Invertir Y para convertir de WPF (Y hacia abajo) a 3D (Y hacia arriba)
|
var position3D = new Vector3(position.X, CoordinateConverter.WpfYToBepuY(position.Y), Radius + zPos_Transporte + zAltura_Transporte);
|
||||||
var position3D = new Vector3(position.X, -position.Y, Radius + zPos_Transporte + zAltura_Transporte);
|
|
||||||
Create(position3D);
|
Create(position3D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,14 +880,14 @@ namespace CtrEditor.Simulacion
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// Invertir Y de vuelta para convertir de 3D (Y hacia arriba) a WPF (Y hacia abajo)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
return -GetPosition().Y;
|
return CoordinateConverter.BepuYToWpfY(GetPosition().Y);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var pos = GetPosition();
|
var pos = GetPosition();
|
||||||
// Invertir Y para convertir de WPF (Y hacia abajo) a 3D (Y hacia arriba)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
SetPosition(pos.X, -value, pos.Z);
|
SetPosition(pos.X, CoordinateConverter.WpfYToBepuY(value), pos.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,15 +896,15 @@ namespace CtrEditor.Simulacion
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var pos3D = GetPosition();
|
var pos3D = GetPosition();
|
||||||
// Invertir Y de vuelta para convertir de 3D (Y hacia arriba) a WPF (Y hacia abajo)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
return new Vector2(pos3D.X, -pos3D.Y);
|
return CoordinateConverter.BepuVector3ToWpfVector2(pos3D);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
// Mantener la Z actual, solo cambiar X, Y
|
// Mantener la Z actual, solo cambiar X, Y
|
||||||
var currentPos = GetPosition();
|
var currentPos = GetPosition();
|
||||||
// Invertir Y para convertir de WPF (Y hacia abajo) a 3D (Y hacia arriba)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
SetPosition(value.X, -value.Y, currentPos.Z);
|
SetPosition(value.X, CoordinateConverter.WpfYToBepuY(value.Y), currentPos.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1022,8 +1094,8 @@ namespace CtrEditor.Simulacion
|
||||||
|
|
||||||
public float InnerRadius => _innerRadius;
|
public float InnerRadius => _innerRadius;
|
||||||
public float OuterRadius => _outerRadius;
|
public float OuterRadius => _outerRadius;
|
||||||
public float StartAngle => _startAngle;
|
public float StartAngle => RadianesAGrados(_startAngle); // Convertir de radianes BEPU internos a grados WPF
|
||||||
public float EndAngle => _endAngle;
|
public float EndAngle => RadianesAGrados(_endAngle); // Convertir de radianes BEPU internos a grados WPF
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ✅ NUEVO: Expone los triángulos originales para visualización debug
|
/// ✅ NUEVO: Expone los triángulos originales para visualización debug
|
||||||
|
@ -1037,9 +1109,9 @@ namespace CtrEditor.Simulacion
|
||||||
_simulationManager = simulationManager; // ✅ NUEVA REFERENCIA
|
_simulationManager = simulationManager; // ✅ NUEVA REFERENCIA
|
||||||
_innerRadius = innerRadius;
|
_innerRadius = innerRadius;
|
||||||
_outerRadius = outerRadius;
|
_outerRadius = outerRadius;
|
||||||
// ✅ SENTIDO HORARIO: Convertir ángulos para que vayan en sentido horario
|
// ✅ CORREGIDO: Usar conversión WPF a BEPU y luego a radianes para consistencia
|
||||||
_startAngle = GradosARadianes(startAngle);
|
_startAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(startAngle));
|
||||||
_endAngle = GradosARadianes(endAngle);
|
_endAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(endAngle));
|
||||||
_triangleBodyHandles = new List<BodyHandle>();
|
_triangleBodyHandles = new List<BodyHandle>();
|
||||||
_originalTriangles = new List<List<Vector3>>(); // ✅ NUEVO: Inicializar lista de triángulos
|
_originalTriangles = new List<List<Vector3>>(); // ✅ NUEVO: Inicializar lista de triángulos
|
||||||
|
|
||||||
|
@ -1059,14 +1131,57 @@ namespace CtrEditor.Simulacion
|
||||||
{
|
{
|
||||||
_innerRadius = innerRadius;
|
_innerRadius = innerRadius;
|
||||||
_outerRadius = outerRadius;
|
_outerRadius = outerRadius;
|
||||||
_startAngle = GradosARadianes(startAngle);
|
// ✅ CORREGIDO: Usar conversión WPF a BEPU consistente
|
||||||
_endAngle = GradosARadianes(endAngle);
|
_startAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(startAngle));
|
||||||
|
_endAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(endAngle));
|
||||||
|
|
||||||
// Recrear la curva con nuevos parámetros manteniendo posición actual
|
// Recrear la curva con nuevos parámetros manteniendo posición actual
|
||||||
var currentPosition = GetPosition();
|
var currentPosition = GetPosition();
|
||||||
Create(currentPosition);
|
Create(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Actualiza tanto posición como rotación desde parámetros WPF
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateFromWpfParameters(Vector2 wpfTopLeft, float wpfAngle, float innerRadius, float outerRadius, float startAngle, float endAngle)
|
||||||
|
{
|
||||||
|
// Actualizar parámetros de la curva
|
||||||
|
_innerRadius = innerRadius;
|
||||||
|
_outerRadius = outerRadius;
|
||||||
|
// ✅ CORREGIDO: Usar conversión WPF a BEPU consistente
|
||||||
|
_startAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(startAngle));
|
||||||
|
_endAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(endAngle));
|
||||||
|
|
||||||
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
|
var curveSize = outerRadius * 2f;
|
||||||
|
var zPosition = zAltura_Curve / 2f + zPos_Curve;
|
||||||
|
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, curveSize, curveSize, 0f, zPosition);
|
||||||
|
|
||||||
|
Create(bepuCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Actualiza posición desde Top-Left WPF manteniendo parámetros actuales
|
||||||
|
/// </summary>
|
||||||
|
internal void SetPositionFromWpfTopLeft(Vector2 wpfTopLeft)
|
||||||
|
{
|
||||||
|
var curveSize = _outerRadius * 2f;
|
||||||
|
var zPosition = GetPosition().Z; // Mantener Z actual
|
||||||
|
var bepuCenter = CoordinateConverter.CalculateBepuCenterFromWpfTopLeft(wpfTopLeft, curveSize, curveSize, 0f, zPosition);
|
||||||
|
|
||||||
|
Create(bepuCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Obtiene Top-Left WPF desde la posición actual
|
||||||
|
/// </summary>
|
||||||
|
internal Vector2 GetWpfTopLeft()
|
||||||
|
{
|
||||||
|
var bepuCenter = GetPosition();
|
||||||
|
var curveSize = _outerRadius * 2f;
|
||||||
|
return CoordinateConverter.CalculateWpfTopLeftFromBepuCenter(bepuCenter, curveSize, curveSize, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
public new void RemoverBody()
|
public new void RemoverBody()
|
||||||
{
|
{
|
||||||
// ✅ CRÍTICO: Limpiar todos los motors conectados a esta curva ANTES de eliminar los bodies
|
// ✅ CRÍTICO: Limpiar todos los motors conectados a esta curva ANTES de eliminar los bodies
|
||||||
|
@ -1135,8 +1250,9 @@ namespace CtrEditor.Simulacion
|
||||||
// Actualizar parámetros internos
|
// Actualizar parámetros internos
|
||||||
_innerRadius = innerRadius;
|
_innerRadius = innerRadius;
|
||||||
_outerRadius = outerRadius;
|
_outerRadius = outerRadius;
|
||||||
_startAngle = GradosARadianes(startAngle);
|
// ✅ CORREGIDO: Usar conversión WPF a BEPU consistente
|
||||||
_endAngle = GradosARadianes(endAngle);
|
_startAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(startAngle));
|
||||||
|
_endAngle = GradosARadianes(CoordinateConverter.WpfAngleToBepuAngle(endAngle));
|
||||||
|
|
||||||
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
// Para curvas, el "tamaño" es el diámetro del radio exterior
|
// Para curvas, el "tamaño" es el diámetro del radio exterior
|
||||||
|
@ -1343,9 +1459,8 @@ namespace CtrEditor.Simulacion
|
||||||
_radius = diameter / 2f;
|
_radius = diameter / 2f;
|
||||||
ListSimBotellaContact = new List<simBotella>();
|
ListSimBotellaContact = new List<simBotella>();
|
||||||
|
|
||||||
// Convertir Vector2 a Vector3 con Z=0.3 (altura para detectar botellas)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
// Invertir Y para convertir de WPF (Y hacia abajo) a 3D (Y hacia arriba)
|
var position3D = new Vector3(position.X, CoordinateConverter.WpfYToBepuY(position.Y), zPos_Descarte + _radius);
|
||||||
var position3D = new Vector3(position.X, -position.Y, zPos_Descarte + _radius);
|
|
||||||
Create(position3D);
|
Create(position3D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1373,12 +1488,22 @@ namespace CtrEditor.Simulacion
|
||||||
|
|
||||||
public void Create(Vector2 position)
|
public void Create(Vector2 position)
|
||||||
{
|
{
|
||||||
// Convertir Vector2 a Vector3 con Z=0.3 (altura para detectar botellas)
|
// ✅ USAR COORDINATECONVERTER para conversión centralizada
|
||||||
// Invertir Y para convertir de WPF (Y hacia abajo) a 3D (Y hacia arriba)
|
var position3D = new Vector3(position.X, CoordinateConverter.WpfYToBepuY(position.Y), zPos_Descarte + _radius);
|
||||||
var position3D = new Vector3(position.X, -position.Y, zPos_Descarte + _radius);
|
|
||||||
Create(position3D);
|
Create(position3D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ✅ NUEVO: Actualiza posición usando coordenadas WPF apropiadas
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateFromWpfCenter(Vector2 wpfCenter)
|
||||||
|
{
|
||||||
|
var position3D = new Vector3(wpfCenter.X, CoordinateConverter.WpfYToBepuY(wpfCenter.Y), zPos_Descarte + _radius);
|
||||||
|
|
||||||
|
// Actualizar solo posición manteniendo orientación
|
||||||
|
CoordinateConverter.UpdateBepuBodyPosition(_simulation, BodyHandle, position3D);
|
||||||
|
}
|
||||||
|
|
||||||
private void Create(Vector3 position)
|
private void Create(Vector3 position)
|
||||||
{
|
{
|
||||||
RemoverBody();
|
RemoverBody();
|
||||||
|
@ -1674,16 +1799,25 @@ namespace CtrEditor.Simulacion
|
||||||
if (transport.DirectionVector.Length() < 0.001f)
|
if (transport.DirectionVector.Length() < 0.001f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// ✅ SIMPLIFICAR - Usar LinearAxisMotor básico
|
// ✅ CORREGIDO - LocalAxis debe estar en coordenadas locales del transporte
|
||||||
|
// Para transportes, el eje local de movimiento es siempre UnitX (eje largo)
|
||||||
|
var localAxis = Vector3.UnitX; // Siempre UnitX en coordenadas locales del transporte
|
||||||
|
|
||||||
var motor = new LinearAxisMotor()
|
var motor = new LinearAxisMotor()
|
||||||
{
|
{
|
||||||
LocalOffsetA = Vector3.Zero,
|
LocalOffsetA = Vector3.Zero,
|
||||||
LocalOffsetB = Vector3.Zero,
|
LocalOffsetB = Vector3.Zero,
|
||||||
LocalAxis = transport.DirectionVector,
|
LocalAxis = localAxis, // ✅ Usar eje local, no mundial
|
||||||
TargetVelocity = transport.SpeedMetersPerSecond,
|
TargetVelocity = transport.SpeedMetersPerSecond,
|
||||||
Settings = new MotorSettings(Math.Max(bottle.Mass * 30f, 10f), 5f)
|
Settings = new MotorSettings(Math.Max(bottle.Mass * 30f, 10f), 5f)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🔍 DEBUG: Comparar eje local vs mundial
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Motor] Transport angle: {transport.GetRotationZ()}°");
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Motor] World DirectionVector: {transport.DirectionVector}");
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Motor] Local Axis: {localAxis}");
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[Motor] Target Velocity: {transport.SpeedMetersPerSecond}");
|
||||||
|
|
||||||
var motorHandle = _simulationManager.simulation.Solver.Add(
|
var motorHandle = _simulationManager.simulation.Solver.Add(
|
||||||
transport.BodyHandle,
|
transport.BodyHandle,
|
||||||
bottle.BodyHandle,
|
bottle.BodyHandle,
|
||||||
|
|
Loading…
Reference in New Issue