diff --git a/AGXUnity/Collide/Shape.cs b/AGXUnity/Collide/Shape.cs
index 54d3c53e..b4087c0d 100644
--- a/AGXUnity/Collide/Shape.cs
+++ b/AGXUnity/Collide/Shape.cs
@@ -153,6 +153,30 @@ public ShapeMaterial Material
}
}
+ [SerializeField]
+ private bool m_isPulley = false;
+
+ ///
+ /// When enabled, Wires will snap onto this geometry to simulate a sheave or pulley geometry without having to rely on contacts
+ ///
+ [Tooltip( "When enabled, Wires will snap onto this geometry to simulate a sheave or pulley geometry without having to rely on contacts" )]
+ [InspectorGroupBegin( Name = "Extra Properties" )]
+ [InspectorGroupEnd]
+ public bool IsPulley
+ {
+ get => m_isPulley;
+ set
+ {
+ m_isPulley = value;
+ if ( NativeGeometry != null ) {
+ if ( m_isPulley )
+ NativeGeometry.getPropertyContainer().addPropertyBool( "Pulley", true );
+ else
+ NativeGeometry.getPropertyContainer().removePropertyBool( "Pulley" );
+ }
+ }
+ }
+
///
/// Native geometry object, if initialized.
///
diff --git a/AGXUnity/IO/OpenPLX/OpenPLXImporter.cs b/AGXUnity/IO/OpenPLX/OpenPLXImporter.cs
index 79503e06..258e3dab 100644
--- a/AGXUnity/IO/OpenPLX/OpenPLXImporter.cs
+++ b/AGXUnity/IO/OpenPLX/OpenPLXImporter.cs
@@ -119,6 +119,7 @@ public UnityEngine.Object ImportOpenPLXFile( string path, string model = null )
else
ErrorCallback?.Invoke();
+ GC.Collect();
return importedObject;
}
diff --git a/AGXUnity/Model/DeformableTerrain.cs b/AGXUnity/Model/DeformableTerrain.cs
index 7450e1bb..2b89c505 100644
--- a/AGXUnity/Model/DeformableTerrain.cs
+++ b/AGXUnity/Model/DeformableTerrain.cs
@@ -85,7 +85,7 @@ protected override bool Initialize()
LicenseManager.LicenseInfo.HasModuleLogError( LicenseInfo.Module.AGXTerrain | LicenseInfo.Module.AGXGranular, this );
m_initialHeights = TerrainData.GetHeights( 0, 0, TerrainDataResolution, TerrainDataResolution );
-
+ Terrain.terrainData = Instantiate( Terrain.terrainData );
InitializeNative();
Simulation.Instance.StepCallbacks.PostStepForward += OnPostStepForward;
@@ -144,13 +144,6 @@ private void ResetTerrainDataHeightsAndTransform()
TerrainData.SetHeights( 0, 0, m_initialHeights );
transform.position = transform.position + MaximumDepth * Vector3.up;
-
-#if UNITY_EDITOR
- // If the editor is closed during play the modified height
- // data isn't saved, this resolves corrupt heights in such case.
- UnityEditor.EditorUtility.SetDirty( TerrainData );
- UnityEditor.AssetDatabase.SaveAssets();
-#endif
}
private void OnPostStepForward()
diff --git a/AGXUnity/Model/DeformableTerrainConnector.cs b/AGXUnity/Model/DeformableTerrainConnector.cs
index 942ba262..71938237 100644
--- a/AGXUnity/Model/DeformableTerrainConnector.cs
+++ b/AGXUnity/Model/DeformableTerrainConnector.cs
@@ -26,6 +26,8 @@ public Vector3 GetOffsetPosition()
if ( InitialHeights != null )
return needsReturnData ? Terrain.terrainData.GetHeights( 0, 0, resolution, resolution ) : null;
+ Terrain.terrainData = Instantiate( Terrain.terrainData );
+
if ( float.IsNaN( MaximumDepth ) ) {
Debug.LogError( "Writing terrain offset without first setting depth!" );
MaximumDepth = 0;
@@ -41,12 +43,6 @@ internal void OnReset()
transform.position += MaximumDepth * Vector3.up;
Terrain.terrainData.SetHeights( 0, 0, InitialHeights );
-#if UNITY_EDITOR
- // If the editor is closed during play the modified height
- // data isn't saved, this resolves corrupt heights in such case.
- UnityEditor.EditorUtility.SetDirty( Terrain.terrainData );
- UnityEditor.AssetDatabase.SaveAssets();
-#endif
InitialHeights = null;
}
}
diff --git a/AGXUnity/Model/DeformableTerrainPager.cs b/AGXUnity/Model/DeformableTerrainPager.cs
index bbe19945..d4f0d5c1 100644
--- a/AGXUnity/Model/DeformableTerrainPager.cs
+++ b/AGXUnity/Model/DeformableTerrainPager.cs
@@ -411,8 +411,7 @@ private void InitializeNative()
foreach ( var rb in m_rigidbodies )
Native.add( rb.Body.GetInitialized().Native, rb.requiredRadius, rb.preloadRadius );
- if ( MaterialPatches.Length != 0 )
- Debug.LogWarning( "Nonhomogenous terrain is not yet supported for DeformableTerrainPager.", this );
+ GetSimulation().add( Native );
}
protected override void OnDestroy()
@@ -444,7 +443,7 @@ private void UpdateHeights()
private void UpdateTerrain( agxTerrain.TerrainPager.TileAttachments tile )
{
- var terrain = tile.m_terrainTile;
+ var terrain = tile.m_terrainTile.get();
var modifications = terrain.getModifiedVertices();
if ( modifications.Count == 0 )
return;
@@ -456,12 +455,12 @@ private void UpdateTerrain( agxTerrain.TerrainPager.TileAttachments tile )
var result = new float[,] { { 0.0f } };
agx.Vec2i index = new agx.Vec2i(0,0);
- Vector2Int tileIndex = GetTileIndex(terrain.get());
+ Vector2Int tileIndex = GetTileIndex(terrain);
UnityTerrainAdapter.UnityModificationCallback modCallbackFn = ( Terrain tile, Vector2Int unityIndex ) =>
{
tile.terrainData.SetHeightsDelayLOD( unityIndex.x, unityIndex.y, result );
- OnModification?.Invoke( terrain.get(), index, tile, unityIndex );
+ OnModification?.Invoke( terrain, index, tile, unityIndex );
m_updatedTerrains.Add( tile );
};
@@ -845,17 +844,33 @@ public override void TriggerModifyAllCells()
public override bool ReplaceTerrainMaterial( DeformableTerrainMaterial oldMat, DeformableTerrainMaterial newMat )
{
- throw new NotImplementedException( "Terrain pager does not yet support Inhomogeneous terrain" );
+ if ( Native == null )
+ return true;
+
+ if ( oldMat == null || newMat == null )
+ return false;
+
+ var success = m_terrainDataSource.exchangeTerrainMaterial(oldMat.GetInitialized().Native, newMat.GetInitialized().Native);
+ return success;
}
public override void SetAssociatedMaterial( DeformableTerrainMaterial terrMat, ShapeMaterial shapeMat )
{
- throw new NotImplementedException( "Terrain pager does not yet support Inhomogeneous terrain" );
+ if ( Native == null )
+ return;
+
+ m_terrainDataSource.setAssociatedMaterial( shapeMat.GetInitialized().Native, terrMat.GetInitialized().Native );
}
public override void AddTerrainMaterial( DeformableTerrainMaterial terrMat, Shape shape = null )
{
- throw new NotImplementedException( "Terrain pager does not yet support Inhomogeneous terrain" );
+ if ( Native == null )
+ return;
+
+ if ( shape != null )
+ m_terrainDataSource.addTerrainMaterial( terrMat.GetInitialized().Native, shape.GetInitialized().NativeGeometry );
+ else
+ m_terrainDataSource.addTerrainMaterial( terrMat.GetInitialized().Native );
}
protected override bool IsNativeNull() { return Native == null; }
@@ -867,8 +882,9 @@ protected override void SetShapeMaterial( agx.Material material, agxTerrain.Terr
protected override void SetTerrainMaterial( agxTerrain.TerrainMaterial material )
{
- Native?.getTemplateTerrain().setTerrainMaterial( material );
- OnPropertiesUpdated();
+ m_terrainDataSource.setDefaultTerrainMaterial( material );
+ if ( Material != null )
+ m_terrainDataSource.setAssociatedMaterial( Material.Native, material );
}
protected override void SetEnable( bool enable )
diff --git a/AGXUnity/Model/MovableTerrain.cs b/AGXUnity/Model/MovableTerrain.cs
index f69358d8..2c265fcd 100644
--- a/AGXUnity/Model/MovableTerrain.cs
+++ b/AGXUnity/Model/MovableTerrain.cs
@@ -450,6 +450,15 @@ public override void EditorUpdate()
#endif
}
+ protected override bool PerformMigration()
+ {
+ if ( m_serializationVersion < 2 ) {
+ PlacementMode = Placement.Manual;
+ return true;
+ }
+ return false;
+ }
+
protected override bool Initialize()
{
// Only printing the errors if something is wrong.
diff --git a/AGXUnity/Model/TerrainMaterialPatch.cs b/AGXUnity/Model/TerrainMaterialPatch.cs
index 035b92eb..e6365b48 100644
--- a/AGXUnity/Model/TerrainMaterialPatch.cs
+++ b/AGXUnity/Model/TerrainMaterialPatch.cs
@@ -38,7 +38,11 @@ public DeformableTerrainMaterial TerrainMaterial
return;
}
- if ( (bool)ParentTerrain?.ReplaceTerrainMaterial( m_terrainMaterial, value ) )
+ if ( m_terrainMaterial == null ) {
+ ParentTerrain?.AddTerrainMaterial( value );
+ m_terrainMaterial = value;
+ }
+ else if ( (bool)ParentTerrain?.ReplaceTerrainMaterial( m_terrainMaterial, value ) )
m_terrainMaterial = value;
}
}
@@ -51,7 +55,8 @@ public DeformableTerrainMaterial TerrainMaterial
public void AddShape( Shape shape )
{
shape.enabled &= !DisableShapes;
- shape.Visual.GetComponent().enabled &= !DisableVisuals;
+ if ( shape.Visual != null )
+ shape.Visual.GetComponent().enabled &= !DisableVisuals;
ParentTerrain?.AddTerrainMaterial( m_terrainMaterial, shape.GetInitialized() );
}
diff --git a/AGXUnity/Model/Track.cs b/AGXUnity/Model/Track.cs
index 038e4623..ca16ef72 100644
--- a/AGXUnity/Model/Track.cs
+++ b/AGXUnity/Model/Track.cs
@@ -1,3 +1,4 @@
+using AGXUnity.Collide;
using AGXUnity.Utils;
using agxVehicle;
using System.Collections.Generic;
@@ -266,19 +267,7 @@ public ShapeMaterial Material
/// Registered track wheel instances.
///
[HideInInspector]
- public TrackWheel[] Wheels
- {
- get { return m_wheels.ToArray(); }
- }
-
- protected override bool PerformMigration()
- {
- if ( m_serializationVersion < 2 ) {
- FullDoF = true;
- return true;
- }
- return false;
- }
+ public TrackWheel[] Wheels => m_wheels.ToArray();
///
/// Associate track wheel instance to this track.
@@ -313,18 +302,77 @@ public bool Remove( TrackWheel wheel )
///
/// Track wheel instance.
/// True if is associated to this track.
- public bool Contains( TrackWheel wheel )
+ public bool Contains( TrackWheel wheel ) => m_wheels.Contains( wheel );
+
+ ///
+ /// Verifies so that all added track wheels still exists. Wheels that
+ /// has been deleted are removed.
+ ///
+ public void RemoveInvalidWheels() => m_wheels.RemoveAll( wheel => wheel == null );
+
+ [SerializeField]
+ private List m_supportGeometries = new List();
+
+ ///
+ /// Registered support geometry instances.
+ ///
+ [HideInInspector]
+ public Shape[] SupportGeometries => m_supportGeometries.ToArray();
+
+ ///
+ /// Associate support geometry instance to this track.
+ ///
+ /// support geometry instance to add.
+ /// True if added, false if null or already added.
+ public bool Add( Shape supportGeometry )
{
- return m_wheels.Contains( wheel );
+ if ( supportGeometry == null || m_supportGeometries.Contains( supportGeometry ) )
+ return false;
+
+ m_supportGeometries.Add( supportGeometry );
+
+ if ( Native != null )
+ Native.addSupportGroupId( supportGeometry.GetInitialized().NativeGeometry );
+
+ return true;
}
///
- /// Verifies so that all added track wheels still exists. Wheels that
+ /// Disassociate support geometry instance from this track.
+ ///
+ /// Support geometry instance to remove.
+ /// True if removed, false if null or not associated to this track.
+ public bool Remove( Shape supportGeometry )
+ {
+ if ( supportGeometry == null )
+ return false;
+
+ if ( Native != null )
+ Native.removeSupportGroupId( supportGeometry.GetInitialized().NativeGeometry );
+
+ return m_supportGeometries.Remove( supportGeometry );
+ }
+
+ ///
+ /// True if is associated to this track.
+ ///
+ /// Support geometry instance.
+ /// True if is associated to this track.
+ public bool Contains( Shape supportGeometry ) => m_supportGeometries.Contains( supportGeometry );
+
+ ///
+ /// Verifies so that all added support geometries still exists. Geometries that
/// has been deleted are removed.
///
- public void RemoveInvalidWheels()
+ public void RemoveInvalidSupportGeometries() => m_supportGeometries.RemoveAll( geom => geom == null );
+
+ protected override bool PerformMigration()
{
- m_wheels.RemoveAll( wheel => wheel == null );
+ if ( m_serializationVersion < 2 ) {
+ FullDoF = true;
+ return true;
+ }
+ return false;
}
private class OnInitializeAdapter : TrackNodeOnInitializeCallback
@@ -354,6 +402,7 @@ protected override bool Initialize()
return false;
RemoveInvalidWheels();
+ RemoveInvalidSupportGeometries();
if ( m_wheels.Count == 0 ) {
Debug.LogError( "Component: Track requires at least one wheel to initialize.", this );
@@ -389,6 +438,9 @@ protected override bool Initialize()
foreach ( var wheel in Wheels )
Native.add( wheel.Native );
+ foreach ( var geom in SupportGeometries )
+ Native.addSupportGroupId( geom.GetInitialized().NativeGeometry );
+
if ( WidthVariation != null || ThicknessVariation != null )
Native.initialize( new OnInitializeAdapter( Width, Thickness, WidthVariation, ThicknessVariation ) );
else
diff --git a/AGXUnity/Model/TrackProperties.cs b/AGXUnity/Model/TrackProperties.cs
index c3a434d4..1ab727f8 100644
--- a/AGXUnity/Model/TrackProperties.cs
+++ b/AGXUnity/Model/TrackProperties.cs
@@ -37,6 +37,8 @@ protected override bool PerformMigration()
HingeStiffnessRotational = new Vector3( convertCompliance( m_hingeComplianceRotational.x ), convertCompliance( m_hingeComplianceRotational.y ), 100.0f );
HingeAttenuationRotational = new Vector3( convertDamping( m_hingeDampingRotational.x ), convertDamping( m_hingeDampingRotational.y ), 2.0f );
+ FullDoF = true;
+
return true;
}
diff --git a/AGXUnity/Rendering/TerrainPatchRenderer.cs b/AGXUnity/Rendering/TerrainPatchRenderer.cs
index b3220f99..2188198a 100644
--- a/AGXUnity/Rendering/TerrainPatchRenderer.cs
+++ b/AGXUnity/Rendering/TerrainPatchRenderer.cs
@@ -7,28 +7,12 @@
namespace AGXUnity.Rendering
{
- ///
- /// Wrapper class for storing/resetting initial state of TerrainData.
- /// This is by no means a complete store/restore, only the parts used by .
- ///
- class InitialTerrainData
+ class TileData
{
- private float[,,] m_alphamaps;
- private TerrainLayer[] m_layers;
-
- public InitialTerrainData( TerrainData td )
- {
- m_alphamaps = td.GetAlphamaps( 0, 0, td.alphamapWidth, td.alphamapHeight );
- m_layers = td.terrainLayers;
- }
-
- public void Reset( TerrainData td )
- {
- if ( td != null ) {
- td.terrainLayers = m_layers;
- td.SetAlphamaps( 0, 0, m_alphamaps );
- }
- }
+ public float[,,] alphamap;
+ public Dictionary m_materialMapping;
+ public int m_layerCount;
+ public int m_defaultLayerIndex;
}
[RequireComponent( typeof( DeformableTerrainBase ) )]
@@ -38,11 +22,9 @@ public void Reset( TerrainData td )
public class TerrainPatchRenderer : ScriptComponent
{
private DeformableTerrainBase terrain;
- private float[,,] alphamap;
- private Dictionary m_materialMapping;
- private InitialTerrainData m_initialData;
- private int m_layerCount;
- private int m_defaultLayerIndex;
+
+ private Dictionary m_perTileData;
+ private List m_shouldUpdate;
[SerializeField]
private TerrainLayer m_defaultLayer;
@@ -57,7 +39,7 @@ public TerrainLayer DefaultLayer
get => m_defaultLayer;
set
{
- if ( m_initialData != null )
+ if ( State == States.INITIALIZED )
Debug.LogError( "Setting material TerrainLayers during runtime is not supported!" );
else
m_defaultLayer = value;
@@ -78,7 +60,7 @@ public SerializableDictionary ExplicitM
get => m_explicitMaterialRenderMap;
set
{
- if ( m_initialData != null )
+ if ( State == States.INITIALIZED )
Debug.LogError( "Setting material TerrainLayers during runtime is not supported!" );
else
m_explicitMaterialRenderMap = value;
@@ -110,37 +92,18 @@ public Dictionary MaterialRenderMap
public TerrainMaterialPatch[] RenderedPatches => gameObject.GetComponentsInChildren();
- protected override bool Initialize()
+ private void InitializeTile( Terrain tile )
{
- terrain = gameObject.GetInitializedComponent();
- if ( terrain is not DeformableTerrain ) {
- Debug.LogError( "Terrain Patch Renderer currently only supports DeformableTerrain!", this );
- return false;
- }
-
- // The patches need to be initialized before the initial update pass, otherwise the materials might not yet have been added.
- foreach ( var patch in RenderedPatches )
- patch.GetInitialized();
-
- var uTerr = GetComponent();
- var td = uTerr.terrainData;
-
- m_initialData = new InitialTerrainData( td );
+ TileData tileData = new TileData();
+ var td = tile.terrainData;
var layers = td.terrainLayers.ToList();
- if ( DefaultLayer == null ) {
- Debug.LogWarning( "No DefaultLayer provided. Using first layer present in terrain.", this );
- m_defaultLayer = td.terrainLayers[ 0 ];
- m_defaultLayerIndex = 0;
- }
- else {
- if ( !layers.Contains( DefaultLayer ) )
- layers.Add( DefaultLayer );
- m_defaultLayerIndex = layers.IndexOf( DefaultLayer );
- }
+ if ( !layers.Contains( DefaultLayer ) )
+ layers.Add( DefaultLayer );
+ tileData.m_defaultLayerIndex = layers.IndexOf( DefaultLayer );
// Initialize terrain layers: 0 is default, 1+ are mapped.
- m_materialMapping = new Dictionary();
+ tileData.m_materialMapping = new Dictionary();
foreach ( var (mat, tl) in MaterialRenderMap ) {
var terrMat = mat.GetInitialized().Native;
if ( terrMat != null ) {
@@ -151,34 +114,50 @@ protected override bool Initialize()
if ( !layers.Contains( tl ) )
layers.Add( tl );
- m_materialMapping.Add( mat.GetInitialized().Native, layers.IndexOf( tl ) );
+ tileData.m_materialMapping.Add( mat.GetInitialized().Native, layers.IndexOf( tl ) );
}
}
td.terrainLayers = layers.ToArray();
- m_layerCount = layers.Count;
+ tileData.m_layerCount = layers.Count;
- alphamap = td.GetAlphamaps( 0, 0, td.alphamapWidth, td.alphamapHeight );
+ tileData.alphamap = td.GetAlphamaps( 0, 0, td.alphamapWidth, td.alphamapHeight );
- Simulation.Instance.StepCallbacks.SimulationPost += PostStep;
- terrain.OnModification += UpdateTextureAt;
+ m_perTileData.Add( tile, tileData );
+ }
- terrain.TriggerModifyAllCells();
+ protected override bool Initialize()
+ {
+ terrain = gameObject.GetInitializedComponent();
+ if ( terrain is MovableTerrain ) {
+ Debug.LogError( "Terrain Patch Renderer does not support MovableTerrain!", this );
+ return false;
+ }
- td.SetAlphamaps( 0, 0, alphamap );
+ // The patches need to be initialized before the initial update pass, otherwise the materials might not yet have been added.
+ foreach ( var patch in RenderedPatches )
+ patch.GetInitialized();
- return true;
- }
+ var uTerr = GetComponent();
+ var td = uTerr.terrainData;
- protected override void OnApplicationQuit()
- {
- m_initialData?.Reset( GetComponent().terrainData );
- }
+ m_perTileData = new Dictionary();
+ m_shouldUpdate = new List();
- protected override void OnDestroy()
- {
- m_initialData?.Reset( GetComponent().terrainData );
+ if ( DefaultLayer == null ) {
+ Debug.LogWarning( "No DefaultLayer provided. Using first layer present in terrain.", this );
+ m_defaultLayer = td.terrainLayers[ 0 ];
+ }
+
+ Simulation.Instance.StepCallbacks.SimulationPost += PostStep;
+ terrain.OnModification += UpdateTextureAt;
+
+ if ( terrain is DeformableTerrain ) {
+ InitializeTile( uTerr );
+ terrain.TriggerModifyAllCells();
+ td.SetAlphamaps( 0, 0, m_perTileData[ uTerr ].alphamap );
+ }
- base.OnDestroy();
+ return true;
}
protected override void OnDisable()
@@ -202,13 +181,20 @@ protected override void OnEnable()
private void PostStep()
{
- var td = GetComponent().terrainData;
+ foreach ( var terr in m_shouldUpdate )
+ terr.terrainData.SetAlphamaps( 0, 0, m_perTileData[ terr ].alphamap );
- td.SetAlphamaps( 0, 0, alphamap );
+ m_shouldUpdate.Clear();
}
private void UpdateTextureAt( agxTerrain.Terrain aTerr, agx.Vec2i aIdx, Terrain uTerr, Vector2Int uIdx )
{
+ if ( !m_perTileData.ContainsKey( uTerr ) )
+ InitializeTile( uTerr );
+
+ if ( !m_shouldUpdate.Contains( uTerr ) )
+ m_shouldUpdate.Add( uTerr );
+
var td = uTerr.terrainData;
var alphamapRes = td.alphamapResolution;
var heightsRes = td.heightmapResolution - 1;
@@ -216,9 +202,11 @@ private void UpdateTextureAt( agxTerrain.Terrain aTerr, agx.Vec2i aIdx, Terrain
var modPos = aTerr.getSurfacePositionWorld( aIdx );
var mat = aTerr.getTerrainMaterial( modPos );
- var index = m_materialMapping.GetValueOrDefault(mat,m_defaultLayerIndex);
+ var data = m_perTileData[uTerr];
+
+ var index = data.m_materialMapping.GetValueOrDefault(mat,data.m_defaultLayerIndex);
- if ( index == m_defaultLayerIndex && State != States.INITIALIZED )
+ if ( index == data.m_defaultLayerIndex && State != States.INITIALIZED )
return;
var modAlphaX = Mathf.RoundToInt((uIdx.x - 0.5f)/heightsRes * alphamapRes);
@@ -232,8 +220,8 @@ private void UpdateTextureAt( agxTerrain.Terrain aTerr, agx.Vec2i aIdx, Terrain
for ( int x = modAlphaX; x < modAlphaXend; x++ ) {
if ( x < 0 || x >= alphamapRes )
continue;
- for ( int i = 0; i < m_layerCount; i++ )
- alphamap[ y, x, i ] = i == index ? 1.0f : 0.0f;
+ for ( int i = 0; i < data.m_layerCount; i++ )
+ data.alphamap[ y, x, i ] = i == index ? 1.0f : 0.0f;
}
}
}
diff --git a/AGXUnity/RigidBody.cs b/AGXUnity/RigidBody.cs
index 0fe697b2..b90b32dc 100644
--- a/AGXUnity/RigidBody.cs
+++ b/AGXUnity/RigidBody.cs
@@ -269,6 +269,7 @@ public void UpdateMassProperties()
}
MassProperties.SetDefaultCalculated( rb );
+ PropertySynchronizer.Synchronize( MassProperties );
} );
}
diff --git a/AGXUnity/ScriptAsset.cs b/AGXUnity/ScriptAsset.cs
index 4dc288cc..2dc9f857 100644
--- a/AGXUnity/ScriptAsset.cs
+++ b/AGXUnity/ScriptAsset.cs
@@ -24,11 +24,9 @@ public abstract class ScriptAsset : ScriptableObject, IPropertySynchronizable, I
private const int CurrentSerializationVersion = 2;
// Serialization version is currently unused
-#pragma warning disable 0414
[SerializeField]
[HideInInspector]
protected int m_serializationVersion = -1;
-#pragma warning restore 0414
public void OnBeforeSerialize()
{
diff --git a/AGXUnity/ScriptComponent.cs b/AGXUnity/ScriptComponent.cs
index d90df71e..e78906b5 100644
--- a/AGXUnity/ScriptComponent.cs
+++ b/AGXUnity/ScriptComponent.cs
@@ -40,6 +40,7 @@ protected ScriptComponent()
// 1 - Migrate shovel cutting direction to tooth direction
// 2 - Migrate Range, Beam Divergence, and Beam Exit Radius into the LiDAR model
// - Migrate old tracks into FullDoF tracks
+ // - Add automatic positioning mode
private const int CurrentSerializationVersion = 2;
[SerializeField]
diff --git a/Editor/AGXUnityEditor/Tools/BuiltInToolsTool.cs b/Editor/AGXUnityEditor/Tools/BuiltInToolsTool.cs
index 324483c3..76a19033 100644
--- a/Editor/AGXUnityEditor/Tools/BuiltInToolsTool.cs
+++ b/Editor/AGXUnityEditor/Tools/BuiltInToolsTool.cs
@@ -83,7 +83,7 @@ public BuiltInToolsTool()
AddKeyHandler( "SelectObject", SelectGameObjectKeyHandler );
AddKeyHandler( "SelectRigidBody", SelectRigidBodyKeyHandler );
AddKeyHandler( "PickHandler", PickHandlerKeyHandler );
-#if UNITY_6000_3_OR_NEWER
+#if UNITY_6000_4_OR_NEWER
EditorApplication.hierarchyWindowItemByEntityIdOnGUI += HandleHierarchyDragDrop;
#else
EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyDragDrop;
@@ -227,7 +227,7 @@ private static void AssignMaterial( GameObject go, AGXUnity.ShapeMaterial materi
assignAll();
}
-#if UNITY_6000_3_OR_NEWER
+#if UNITY_6000_4_OR_NEWER
private void HandleHierarchyDragDrop( EntityId entityId, Rect pos )
{
InspectorGUI.HandleDragDrop( pos,
@@ -239,7 +239,8 @@ private void HandleHierarchyDragDrop( EntityId entityId, Rect pos )
material );
} );
}
-#else
+#else
+#pragma warning disable CS0618
private void HandleHierarchyDragDrop( int instanceId, Rect pos )
{
InspectorGUI.HandleDragDrop( pos,
@@ -251,6 +252,7 @@ private void HandleHierarchyDragDrop( int instanceId, Rect pos )
material );
} );
}
+#pragma warning restore
#endif
private void HandleSceneViewDragDrop( Event current, SceneView sceneView )
diff --git a/Editor/AGXUnityEditor/Tools/ContactMaterialManagerTool.cs b/Editor/AGXUnityEditor/Tools/ContactMaterialManagerTool.cs
index 436ea79f..cf1369c0 100644
--- a/Editor/AGXUnityEditor/Tools/ContactMaterialManagerTool.cs
+++ b/Editor/AGXUnityEditor/Tools/ContactMaterialManagerTool.cs
@@ -53,7 +53,7 @@ private Action PreContactMaterialEditor( ContactMaterialEn
entries[ index ].IsOriented );
if ( entries[ index ].IsOriented ) {
using ( InspectorGUI.IndentScope.Single ) {
- if ( entries[ index ].ContactMaterial.FrictionModel.TrackFrictionModel ) {
+ if ( entries[ index ].ContactMaterial.FrictionModel != null && entries[ index ].ContactMaterial.FrictionModel.TrackFrictionModel ) {
EditorGUILayout.HelpBox( "Contact Materials with a Track friction model cannot be oriented. " +
"These models automatically construct the friction frame from the tracks. " +
"This option will be ignored",
diff --git a/Editor/AGXUnityEditor/Tools/TrackTool.cs b/Editor/AGXUnityEditor/Tools/TrackTool.cs
index 04156e89..fa769571 100644
--- a/Editor/AGXUnityEditor/Tools/TrackTool.cs
+++ b/Editor/AGXUnityEditor/Tools/TrackTool.cs
@@ -18,6 +18,7 @@ public TrackTool( Object[] targets )
public override void OnAdd()
{
Track.RemoveInvalidWheels();
+ Track.RemoveInvalidSupportGeometries();
}
public override void OnRemove()
@@ -28,6 +29,7 @@ public override void OnRemove()
public override void OnPreTargetMembersGUI()
{
Track.RemoveInvalidWheels();
+ Track.RemoveInvalidSupportGeometries();
bool toggleSelectWheel = false;
bool toggleDisableCollisions = false;
@@ -78,6 +80,14 @@ public override void OnPostTargetMembersGUI()
"Wheels",
wheel => Track.Add( wheel ),
wheel => Track.Remove( wheel ) );
+
+ if ( !Track.FullDoF ) {
+ InspectorGUI.ToolListGUI( this,
+ Track.SupportGeometries,
+ "Support Geometries",
+ geom => Track.Add( geom ),
+ geom => Track.Remove( geom ) );
+ }
}
private TrackNodeVariation VariationGUI( string name, TrackNodeVariation variation )
diff --git a/Plugins/x86_64/agxDotNet.dll b/Plugins/x86_64/agxDotNet.dll
index 51be13f1..42dc4f39 100644
Binary files a/Plugins/x86_64/agxDotNet.dll and b/Plugins/x86_64/agxDotNet.dll differ
diff --git a/Tests/Runtime/ImuAndEncoderTests.cs b/Tests/Runtime/ImuAndEncoderTests.cs
index 9d6223ac..ac6b2259 100644
--- a/Tests/Runtime/ImuAndEncoderTests.cs
+++ b/Tests/Runtime/ImuAndEncoderTests.cs
@@ -6,59 +6,15 @@
using UnityEngine;
using UnityEngine.TestTools;
-using GOList = System.Collections.Generic.List;
-
namespace AGXUnityTesting.Runtime
{
public class ImuAndEncoderTests : AGXUnityFixture
{
- private GOList m_keep = new GOList();
-
- [OneTimeSetUp]
+ [SetUp]
public void SetupSensorScene()
{
- Simulation.Instance.PreIntegratePositions = true;
- m_keep.Add( Simulation.Instance.gameObject );
-
SensorEnvironment.Instance.FieldType = SensorEnvironment.MagneticFieldType.Uniform;
SensorEnvironment.Instance.MagneticFieldVector = Vector3.one;
- m_keep.Add( SensorEnvironment.Instance.gameObject );
- }
-
- [UnityTearDown]
- public IEnumerator CleanSensorScene()
- {
-#if UNITY_2022_2_OR_NEWER
- var objects = Object.FindObjectsByType( FindObjectsSortMode.None );
-#else
- var objects = Object.FindObjectsOfType( );
-#endif
- GOList toDestroy = new GOList();
-
- foreach ( var obj in objects ) {
- var root = obj.gameObject;
- while ( root.transform.parent != null )
- root = root.transform.parent.gameObject;
- if ( !m_keep.Contains( root ) )
- toDestroy.Add( root );
- }
-
- yield return TestUtils.DestroyAndWait( toDestroy.ToArray() );
- }
-
- [OneTimeTearDown]
- public void TearDownSensorScene()
- {
-#if UNITY_2022_2_OR_NEWER
- var geoms = Object.FindObjectsByType( FindObjectsSortMode.None );
-#else
- var geoms = Object.FindObjectsOfType( );
-#endif
-
- foreach ( var g in geoms )
- GameObject.Destroy( g.gameObject );
-
- GameObject.Destroy( SensorEnvironment.Instance.gameObject );
}
private (AGXUnity.RigidBody, ImuSensor) CreateDefaultTestImu( Vector3 position = default )
diff --git a/Tests/Runtime/LidarTests.cs b/Tests/Runtime/LidarTests.cs
index c9cc6c27..0413d586 100644
--- a/Tests/Runtime/LidarTests.cs
+++ b/Tests/Runtime/LidarTests.cs
@@ -9,14 +9,11 @@
using UnityEngine;
using UnityEngine.TestTools;
-using GOList = System.Collections.Generic.List;
-
namespace AGXUnityTesting.Runtime
{
+ [Ignore( "TEMP: No runners have sufficient GPU support currently" )]
public class LidarTests : AGXUnityFixture
{
- private GOList m_keep = new GOList();
-
private GameObject CreateShape( Vector3 transform = new Vector3() )
where T : Shape
{
@@ -43,57 +40,18 @@ private LidarSurfaceMaterialLambertianOpaque AddLambertianMaterial( GameObject o
return material;
}
- [OneTimeSetUp]
+ [SetUp]
public void SetupLidarScene()
{
- m_keep.Add( CreateShape( new Vector3( 3, 0, 3 ) ) );
- m_keep.Add( CreateShape( new Vector3( -3, 0, 3 ) ) );
- m_keep.Add( CreateShape( new Vector3( -3, 0, -3 ) ) );
- m_keep.Add( CreateShape( new Vector3( 3, 0, -3 ) ) );
- Simulation.Instance.PreIntegratePositions = true;
- m_keep.Add( Simulation.Instance.gameObject );
- m_keep.Add( SensorEnvironment.Instance.gameObject );
+ CreateShape( new Vector3( 3, 0, 3 ) );
+ CreateShape( new Vector3( -3, 0, 3 ) );
+ CreateShape( new Vector3( -3, 0, -3 ) );
+ CreateShape( new Vector3( 3, 0, -3 ) );
// Lidar ray intervals are sensitive to time step so ensure that the timestep is exact here
Simulation.Instance.Native.setTimeStep( 0.02 );
}
- [UnityTearDown]
- public IEnumerator CleanLidarScene()
- {
-#if UNITY_2022_2_OR_NEWER
- var objects = Object.FindObjectsByType( FindObjectsSortMode.None );
-#else
- var objects = Object.FindObjectsOfType( );
-#endif
- GOList toDestroy = new GOList();
-
- foreach ( var obj in objects ) {
- var root = obj.gameObject;
- while ( root.transform.parent != null )
- root = root.transform.parent.gameObject;
- if ( !m_keep.Contains( root ) )
- toDestroy.Add( root );
- }
-
- yield return TestUtils.DestroyAndWait( toDestroy.ToArray() );
- }
-
- [OneTimeTearDown]
- public void TearDownLidarScene()
- {
-#if UNITY_2022_2_OR_NEWER
- var geoms = Object.FindObjectsByType( FindObjectsSortMode.None );
-#else
- var geoms = Object.FindObjectsOfType( );
-#endif
-
- foreach ( var g in geoms )
- GameObject.Destroy( g.gameObject );
-
- GameObject.Destroy( SensorEnvironment.Instance.gameObject );
- }
-
private (LidarSensor, GenericSweepData) CreateDefaultTestLidar( Vector3 position = default )
{
var lidarGO = new GameObject("Lidar");
diff --git a/Tests/Runtime/MovableTerrainTests.cs b/Tests/Runtime/MovableTerrainTests.cs
index d687f647..eeb002da 100644
--- a/Tests/Runtime/MovableTerrainTests.cs
+++ b/Tests/Runtime/MovableTerrainTests.cs
@@ -3,7 +3,6 @@
using AGXUnity.Model;
using NUnit.Framework;
using System.Collections;
-using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.TestTools;
@@ -12,21 +11,6 @@ namespace AGXUnityTesting.Runtime
{
public class MovableTerrainTests : AGXUnityFixture
{
-
- [UnityTearDown]
- public IEnumerator CleanScene()
- {
-#if UNITY_2022_2_OR_NEWER
- var objects = Object.FindObjectsByType( FindObjectsSortMode.None );
-#else
- var objects = Object.FindObjectsOfType( );
-#endif
-
- var toDelete = objects.Where(x => x is not Simulation).Select(x => x.gameObject).ToArray();
-
- yield return TestUtils.DestroyAndWait( toDelete );
- }
-
[Test]
public void TestCreateMovable()
{
diff --git a/Tests/Runtime/OpenPLXTests.cs b/Tests/Runtime/OpenPLXTests.cs
index 30bf3189..bb3b4626 100644
--- a/Tests/Runtime/OpenPLXTests.cs
+++ b/Tests/Runtime/OpenPLXTests.cs
@@ -34,12 +34,6 @@ private void AssertAnglesEqual( double expected, double actual, double delta, st
Assert.AreEqual( expected, normalized, delta, message );
}
- [UnityTearDown]
- public IEnumerator RemoveLoadedObjects()
- {
- yield return TestUtils.DestroyAndWait( Object.FindObjectsByType( FindObjectsSortMode.None ).Select( r => r.gameObject ).ToArray() );
- }
-
public OpenPLXRoot LoadOpenPLX( string source, string modelName = null )
{
var openPLXObj = OpenPLXImporter.ImportOpenPLXFile( System.IO.Path.Combine( TestDataFolder, source ), default, null, modelName );
@@ -651,6 +645,7 @@ public void TestValidLidarOK()
}
[Test]
+ [Ignore( "TEMP: No runners have sufficient GPU support currently" )]
public void TestDoubleDistanceDistortionLidarError()
{
var go = OpenPLXImporter.ImportOpenPLXFile(
diff --git a/Tests/Runtime/OrientedFrictionTests.cs b/Tests/Runtime/OrientedFrictionTests.cs
index 69f3b453..4334f7c3 100644
--- a/Tests/Runtime/OrientedFrictionTests.cs
+++ b/Tests/Runtime/OrientedFrictionTests.cs
@@ -2,7 +2,6 @@
using AGXUnity.Collide;
using NUnit.Framework;
using System.Collections;
-using System.Linq;
using UnityEngine;
using UnityEngine.TestTools;
@@ -38,16 +37,6 @@ public IEnumerator SetupFrictionScene()
yield return TestUtils.WaitUntilLoaded();
}
- [UnityTearDown]
- public IEnumerator TearDownFrictionScene()
- {
- var objects = Object.FindObjectsByType( FindObjectsSortMode.None );
-
- var toDelete = objects.Where(x => x is not Simulation).Select(x => x.gameObject).ToArray();
-
- yield return TestUtils.DestroyAndWait( toDelete );
- }
-
private (ShapeMaterial, RigidBody, Shape, ObserverFrame) CreateSlidingBox()
{
var rbGO = new GameObject("Sliding box");
diff --git a/Tests/Runtime/RuntimeFixture.cs b/Tests/Runtime/RuntimeFixture.cs
index 0b2481aa..d35113fa 100644
--- a/Tests/Runtime/RuntimeFixture.cs
+++ b/Tests/Runtime/RuntimeFixture.cs
@@ -1,5 +1,6 @@
using AGXUnity;
-using NUnit.Framework;
+using System.Collections;
+using System.Linq;
using UnityEngine;
using UnityEngine.TestTools;
@@ -9,8 +10,8 @@ namespace AGXUnityTesting.Runtime
{
public class AGXUnityFixture
{
- [OneTimeSetUp]
- public void SetupSimulationInstance()
+ [UnitySetUp]
+ public IEnumerator SetupSimulationInstance()
{
Simulation.Instance.GetInitialized();
Simulation.Instance.PreIntegratePositions = true;
@@ -18,13 +19,14 @@ public void SetupSimulationInstance()
Simulation.Instance.AGXUnityLogLevel = LogLevel.Warning;
Simulation.Instance.LogToUnityConsole = true;
Simulation.Instance.AutoSteppingMode = Simulation.AutoSteppingModes.Disabled;
+
+ yield return TestUtils.WaitUntilLoaded();
}
- [OneTimeTearDown]
- public void TeardownSimulationInstance()
+ [UnityTearDown]
+ public IEnumerator TeardownSimulationInstance()
{
- GameObject.Destroy( ContactMaterialManager.Instance.gameObject );
- GameObject.Destroy( Simulation.Instance.gameObject );
+ yield return TestUtils.DestroyAndWait( Object.FindObjectsByType( FindObjectsSortMode.None ).Select( c => c.gameObject ).ToArray() );
}
}
}
diff --git a/Tests/Runtime/TerrainTests.cs b/Tests/Runtime/TerrainTests.cs
index 64a24278..97b9bf22 100644
--- a/Tests/Runtime/TerrainTests.cs
+++ b/Tests/Runtime/TerrainTests.cs
@@ -1,8 +1,10 @@
using AGXUnity;
+using AGXUnity.Collide;
using AGXUnity.Model;
-
using NUnit.Framework;
+using System;
using System.Collections;
+using System.Reflection;
using UnityEngine;
using UnityEngine.TestTools;
@@ -50,12 +52,6 @@ public IEnumerator SetupTerrainScene()
yield return TestUtils.WaitUntilLoaded();
}
- [UnityTearDown]
- public IEnumerator TearDownTerrainScene()
- {
- yield return TestUtils.DestroyAndWait( unityTerrain.gameObject );
- }
-
[Test]
public void TestTerrainGetSingleHeight()
{
@@ -158,9 +154,48 @@ public void TestClampedTerrainGivesWarning()
LogAssert.Expect( LogType.Warning, $"Terrain heights were clamped! Max allowed: 10, Max Encountered: 15 and AGXUnity.Model.DeformableTerrain.MaximumDepth = 10. Resolve this by increasing max height and lower the terrain or decrease Maximum Depth." );
testTerrain.GetInitialized();
}
+
+ [UnityTest]
+ [TestMustExpectAllLogs( false )]
+ public IEnumerator TestPagerDifferentMaterials()
+ {
+ var patchGO = new GameObject("Material Patch");
+ var patch = patchGO.AddComponent();
+
+ var patchGeom = new GameObject("Patch Geometry");
+ patchGeom.AddComponent().HalfExtents = new Vector3( 2.5f, 2, 2.5f );
+
+ patchGeom.transform.parent = patchGO.transform;
+ patchGO.transform.parent = testTerrain.transform;
+ patchGO.transform.position = new Vector3( 15, 2, 15 );
+
+ var patchTM = DeformableTerrainMaterial.CreateInstance();
+ patchTM.name = "Patch terrain material";
+ patchTM.GetInitialized().Native.setDescription( "Material patch Terrain Material" );
+ var defaultTM = DeformableTerrainMaterial.CreateInstance();
+ defaultTM.name = "Default terrain material";
+ defaultTM.GetInitialized().Native.setDescription( "Default Terrain Material" );
+
+ patch.TerrainMaterial = patchTM;
+ testTerrain.DefaultTerrainMaterial = defaultTM;
+
+ yield return TestUtils.SimulateSeconds( 0.5f );
+
+ var tile = testTerrain.Native;
+
+ var probedMat = tile.getTerrainMaterial( tile.getWorldPositionFromVoxelIndex( tile.getSurfaceVoxelIndexFromTerrainIndex( new agx.Vec2i( 15, 15 ) ) ) );
+ Assert.That( probedMat, Is.EqualTo( patchTM.Native ) );
+
+ probedMat = tile.getTerrainMaterial( tile.getWorldPositionFromVoxelIndex( tile.getSurfaceVoxelIndexFromTerrainIndex( new agx.Vec2i( 2, 2 ) ) ) );
+ Assert.That( probedMat.getDescription(), Is.EqualTo( defaultTM.Native.getDescription() ) );
+ }
}
+
+
public class PagerTests : AGXUnityFixture
{
+ private class NoInitAttribute : Attribute { }
+
private DeformableTerrainPager testTerrain;
private Terrain unityTerrain;
private GameObject pagerProbe;
@@ -203,16 +238,12 @@ public IEnumerator SetupTerrainScene()
testTerrain.Add( pagerProbe.GetComponent() );
- // Ensure that the middle tile is paged in
- yield return TestUtils.SimulateSeconds( 0.2f );
- }
+ var method = this.GetType().GetMethod( TestContext.CurrentContext.Test.MethodName );
- [UnityTearDown]
- public IEnumerator TearDownTerrainScene()
- {
- GameObject.Destroy( unityTerrain.gameObject );
- GameObject.Destroy( pagerProbe );
- yield return null;
+ if ( method.GetCustomAttribute() == null ) {
+ // Ensure that the middle tile is paged in
+ yield return TestUtils.SimulateSeconds( 0.2f );
+ }
}
[Test]
@@ -316,5 +347,41 @@ public IEnumerator TestPagerReset()
for ( int x = 0; x < 10; x++ )
Assert.AreEqual( initial[ y, x ], results[ y, x ], HEIGHT_DELTA );
}
+
+ [UnityTest]
+ [NoInit]
+ [TestMustExpectAllLogs( false )]
+ public IEnumerator TestPagerDifferentMaterials()
+ {
+ var patchGO = new GameObject("Material Patch");
+ var patch = patchGO.AddComponent();
+
+ var patchGeom = new GameObject("Patch Geometry");
+ patchGeom.AddComponent().HalfExtents = new Vector3( 2.5f, 2, 2.5f );
+
+ patchGeom.transform.parent = patchGO.transform;
+ patchGO.transform.parent = testTerrain.transform;
+ patchGO.transform.position = new Vector3( 15, 2, 15 );
+
+ var patchTM = DeformableTerrainMaterial.CreateInstance();
+ patchTM.name = "Patch terrain material";
+ patchTM.GetInitialized().Native.setDescription( "Material patch Terrain Material" );
+ var defaultTM = DeformableTerrainMaterial.CreateInstance();
+ defaultTM.name = "Default terrain material";
+ defaultTM.GetInitialized().Native.setDescription( "Default Terrain Material" );
+
+ patch.TerrainMaterial = patchTM;
+ testTerrain.DefaultTerrainMaterial = defaultTM;
+
+ yield return TestUtils.SimulateSeconds( 0.5f );
+
+ var tile = testTerrain.Native.getActiveTileAttachments()[ 0 ].m_terrainTile;
+
+ var probedMat = tile.getTerrainMaterial( tile.getWorldPositionFromVoxelIndex( tile.getSurfaceVoxelIndexFromTerrainIndex( new agx.Vec2i( 15, 15 ) ) ) );
+ Assert.That( probedMat, Is.EqualTo( patchTM.Native ) );
+
+ probedMat = tile.getTerrainMaterial( tile.getWorldPositionFromVoxelIndex( tile.getSurfaceVoxelIndexFromTerrainIndex( new agx.Vec2i( 2, 2 ) ) ) );
+ Assert.That( probedMat.getDescription(), Is.EqualTo( defaultTM.Native.getDescription() ) );
+ }
}
}
diff --git a/Tests/Runtime/VehicleTests.cs b/Tests/Runtime/VehicleTests.cs
index eb09dc9d..85c7085e 100644
--- a/Tests/Runtime/VehicleTests.cs
+++ b/Tests/Runtime/VehicleTests.cs
@@ -5,12 +5,10 @@
using NUnit.Framework;
using System;
using System.Collections;
-using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.TestTools.Utils;
-using Object = UnityEngine.Object;
namespace AGXUnityTesting.Runtime
{
@@ -74,22 +72,6 @@ private BasicVehicle CreateBasicVehicle( System.Func( FindObjectsSortMode.None );
-#else
- var objects = Object.FindObjectsOfType( );
-#endif
-
- var toDelete = objects.Where(x => x is not Simulation).Select(x => x.gameObject).ToArray();
-
- yield return TestUtils.DestroyAndWait( toDelete );
-
- yield return TestUtils.DestroyAndWait( GameObject.Find( "Simple Track" ) );
- }
-
[Test]
public void TestBasicVehicleInitializes()
{
@@ -499,7 +481,48 @@ public IEnumerator TestBoxTrackFriction()
yield return TestUtils.SimulateSeconds( 3f );
Assert.That( box.transform.position.y, Is.GreaterThan( 0 ), "Conveyor should carry the box" );
- Assert.That( box.transform.position.x, Is.LessThan( -0.5 ), "Conveyor should not move the box" );
+ Assert.That( box.transform.position.x, Is.LessThan( -0.5 ), "Conveyor should move the box" );
+ }
+
+ [UnityTest]
+ public IEnumerator TestTrackSupportGeometry()
+ {
+ var track = CreateSimpleTrack();
+
+ yield return TestUtils.SimulateSeconds( 1f );
+
+ double distSum = 0;
+ foreach ( var node in track.Native.nodes() )
+ distSum += node.getCenterPosition().length();
+
+ var box = CreateBox(Vector3.down * 0.24f);
+ box.GetComponent().MotionControl = agx.RigidBody.MotionControl.KINEMATICS;
+
+ var boxGeom = box.GetComponentInChildren().HalfExtents = Vector3.one * 0.1f;
+
+ track.Add( box.GetComponentInChildren() );
+
+ yield return TestUtils.SimulateSeconds( 1f );
+
+ double supportDistSum = 0.0f;
+ foreach ( var node in track.Native.nodes() )
+ supportDistSum += node.getCenterPosition().length();
+
+ Assert.That( supportDistSum, Is.GreaterThan( distSum + 0.5f ) );
+
+ track.Remove( box.GetComponentInChildren() );
+
+ yield return TestUtils.SimulateSeconds( 1f );
+
+ double noSupportDistSum = 0.0f;
+ foreach ( var node in track.Native.nodes() )
+ noSupportDistSum += node.getCenterPosition().length();
+
+ Assert.That( noSupportDistSum, Is.LessThan( distSum - 0.5f ) );
+
+ // Sanity check that tracks have not blown up
+ Assert.That( supportDistSum, Is.EqualTo( distSum ).Within( 1f ) );
+ Assert.That( noSupportDistSum, Is.EqualTo( distSum ).Within( 1f ) );
}
}
}
diff --git a/Tests/Runtime/WireCutMergeTests.cs b/Tests/Runtime/WireTests.cs
similarity index 71%
rename from Tests/Runtime/WireCutMergeTests.cs
rename to Tests/Runtime/WireTests.cs
index 5673c525..702ce2c7 100644
--- a/Tests/Runtime/WireCutMergeTests.cs
+++ b/Tests/Runtime/WireTests.cs
@@ -1,4 +1,6 @@
using AGXUnity;
+using AGXUnity.Collide;
+using AGXUnity.Rendering;
using NUnit.Framework;
using System.Collections;
using System.Text.RegularExpressions;
@@ -7,17 +9,63 @@
namespace AGXUnityTesting.Runtime
{
- public class WireCutMergeTests : AGXUnityFixture
+ public class PulleyTests : AGXUnityFixture
{
private Wire SourceWire;
+ private Cylinder Pulley;
+ private GameObject Weight1;
+ private GameObject Weight2;
+
+ private GameObject CreateWeight( Vector3 pos )
+ {
+ var weight = new GameObject( "Weight" );
+ weight.AddComponent();
+ var wireWeightBoxGO = new GameObject("Box");
+
+ var wireWeightBox = wireWeightBoxGO.AddComponent();
+ wireWeightBox.HalfExtents = new Vector3( 0.1f, 0.1f, 0.1f );
+ wireWeightBoxGO.transform.parent = weight.transform;
+
+ weight.transform.position = pos;
+
+ ShapeVisual.Create( wireWeightBox );
+
+ return weight;
+ }
+
[UnitySetUp]
public IEnumerator SetupWireScene()
{
var wireObject = new GameObject("Source Wire");
SourceWire = wireObject.AddComponent();
- SourceWire.Route.Add( Wire.NodeType.WinchNode, null, Vector3.left );
- SourceWire.Route.Add( Wire.NodeType.WinchNode, null, Vector3.right );
+ Weight1 = CreateWeight( Vector3.left );
+ Weight2 = CreateWeight( Vector3.right );
+
+ SourceWire.Route.Add( Wire.NodeType.BodyFixedNode, Weight1, Vector3.right * 0.1f );
+ SourceWire.Route.Add( Wire.NodeType.BodyFixedNode, Weight2, Vector3.left * 0.1f );
+
+ SourceWire.Diameter = 0.01f;
+ SourceWire.ResolutionPerUnitLength = 10;
+ SourceWire.gameObject.AddComponent();
+
+ SourceWire.Material = ShapeMaterial.CreateInstance();
+
+ var pulleyGO = new GameObject( "Pulley" );
+ Pulley = pulleyGO.AddComponent();
+ pulleyGO.transform.rotation = Quaternion.AngleAxis( 70, Vector3.left );
+ pulleyGO.transform.position = Vector3.down * 0.2f;
+ Pulley.Radius = 0.2f;
+ Pulley.Material = ShapeMaterial.CreateInstance();
+
+ var cm = ContactMaterial.CreateInstance();
+ cm.Material1 = SourceWire.Material;
+ cm.Material2 = Pulley.Material;
+ cm.FrictionCoefficients = Vector2.zero;
+ cm.WireFrictionCoefficients = Vector2.zero;
+ ContactMaterialManager.Instance.Add( cm );
+
+ ShapeVisual.Create( Pulley );
yield return TestUtils.WaitUntilLoaded();
}
@@ -31,11 +79,47 @@ private Wire[] FindWires()
#endif
}
- [TearDown]
- public void TearDownWireScene()
+ [UnityTest]
+ public IEnumerator SlipsWithoutPulleyProperty()
+ {
+ yield return TestUtils.SimulateSeconds( 5 );
+
+ Assert.That( Weight1.transform.position.y, Is.LessThan( -2 ) );
+ }
+
+ [UnityTest]
+ public IEnumerator SticksWithPulleyProperty()
+ {
+ Pulley.IsPulley = true;
+
+ yield return TestUtils.SimulateSeconds( 5 );
+
+ Assert.That( Weight1.transform.position.y, Is.GreaterThan( -2 ) );
+ }
+ }
+
+ public class WireCutMergeTests : AGXUnityFixture
+ {
+ private Wire SourceWire;
+ [UnitySetUp]
+ public IEnumerator SetupWireScene()
{
- foreach ( var wire in FindWires() )
- Object.Destroy( wire.gameObject );
+ var wireObject = new GameObject("Source Wire");
+ SourceWire = wireObject.AddComponent();
+
+ SourceWire.Route.Add( Wire.NodeType.WinchNode, null, Vector3.left );
+ SourceWire.Route.Add( Wire.NodeType.WinchNode, null, Vector3.right );
+
+ yield return TestUtils.WaitUntilLoaded();
+ }
+
+ private Wire[] FindWires()
+ {
+#if UNITY_2022_2_OR_NEWER
+ return UnityEngine.Object.FindObjectsByType( FindObjectsSortMode.None );
+#else
+ return UnityEngine.Object.FindObjectsOfType();
+#endif
}
[Test]
diff --git a/Tests/Runtime/WireCutMergeTests.cs.meta b/Tests/Runtime/WireTests.cs.meta
similarity index 100%
rename from Tests/Runtime/WireCutMergeTests.cs.meta
rename to Tests/Runtime/WireTests.cs.meta
diff --git a/package.json b/package.json
index c5f7df14..4de4408c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "com.algoryx.agxunity",
- "version": "5.5.1+7ff02d5",
+ "version": "5.6.0-beta+3+39db3a4",
"platform": "windows",
"platformName": "Microsoft Windows",
"displayName": "AGX Dynamics for Unity",