Skip to content

Commit

Permalink
Merge pull request #179 from Algoryx/feature/shovel-refactor
Browse files Browse the repository at this point in the history
Support for refactored shovels
  • Loading branch information
FilipAlg authored Jan 28, 2025
2 parents e162227 + f5210a0 commit 1c3a68b
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 373 deletions.
132 changes: 0 additions & 132 deletions AGXUnity/Model/DeformableTerrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
using AGXUnity.Collide;
using AGXUnity.Utils;
using System;
using System.Collections.Generic;
using UnityEngine;
using GUI = AGXUnity.Utils.GUI;

namespace AGXUnity.Model
{
Expand Down Expand Up @@ -42,37 +40,6 @@ public Terrain Terrain
[HideInInspector]
public int TerrainDataResolution { get { return TerrainUtils.TerrainDataResolution( TerrainData ); } }

[SerializeField]
private List<DeformableTerrainShovel> m_shovels = new List<DeformableTerrainShovel>();

[SerializeField]
private bool m_tempDisplayShovelForces = false;

[HideInInspector]
public bool TempDisplayShovelForces
{
get { return m_tempDisplayShovelForces; }
set
{
m_tempDisplayShovelForces = value;

if ( !Application.isPlaying )
return;

if ( m_tempDisplayShovelForces &&
Shovels.Length > 0 &&
GUIWindowHandler.Instance.GetWindowData( ShowForces ) == null ) {
var windowSize = new Vector2( 750, 125 );
GUIWindowHandler.Instance.Show( ShowForces,
windowSize,
new Vector2( Screen.width - windowSize.x - 20, 20 ),
"Shovel forces" );
}
else if ( !m_tempDisplayShovelForces && GUIWindowHandler.HasInstance )
GUIWindowHandler.Instance.Close( ShowForces );
}
}

/// <summary>
/// Resets heights of the Unity terrain and recreate native instance.
/// </summary>
Expand Down Expand Up @@ -104,8 +71,6 @@ protected override bool Initialize()
// Only printing the errors if something is wrong.
LicenseManager.LicenseInfo.HasModuleLogError( LicenseInfo.Module.AGXTerrain | LicenseInfo.Module.AGXGranular, this );

RemoveInvalidShovels( true, true );

m_initialHeights = TerrainData.GetHeights( 0, 0, TerrainDataResolution, TerrainDataResolution );

InitializeNative();
Expand Down Expand Up @@ -135,9 +100,6 @@ protected override void OnDestroy()
}
Native = null;

if ( GUIWindowHandler.HasInstance )
GUIWindowHandler.Instance.Close( ShowForces );

base.OnDestroy();
}

Expand All @@ -156,10 +118,6 @@ private void InitializeNative()

Native.setTransform( Utils.TerrainUtils.CalculateNativeOffset( transform, TerrainData ) );


foreach ( var shovel in Shovels )
Native.add( shovel.GetInitialized<DeformableTerrainShovel>()?.Native );

GetSimulation().add( Native );
}

Expand Down Expand Up @@ -209,108 +167,18 @@ private void UpdateHeights( agxTerrain.ModifiedVerticesVector modifiedVertices )
TerrainData.SyncHeightmap();
}

private GUIStyle m_textLabelStyle = null;
private void ShowForces( EventType eventType )
{
if ( m_textLabelStyle == null ) {
m_textLabelStyle = new GUIStyle( GUI.Skin.label );
m_textLabelStyle.alignment = TextAnchor.MiddleLeft;

var fonts = Font.GetOSInstalledFontNames();
foreach ( var font in fonts ) {
if ( font == "Consolas" ) {
m_textLabelStyle.font = Font.CreateDynamicFontFromOSFont( font, 24 );
break;
}
}
}

var textColor = Color.Lerp( Color.black, Color.white, 1.0f );
var valueColor = Color.Lerp( Color.green, Color.white, 0.45f );
Func<string, agx.Vec3, GUIContent> Vec3Content = ( name, v ) =>
{
return GUI.MakeLabel( string.Format( "{0} [{1}, {2}, {3}] kN",
GUI.AddColorTag( name, textColor ),
GUI.AddColorTag( v.x.ToString( "0.00" ).PadLeft( 7, ' ' ), valueColor ),
GUI.AddColorTag( v.y.ToString( "0.00" ).PadLeft( 7, ' ' ), valueColor ),
GUI.AddColorTag( v.z.ToString( "0.00" ).PadLeft( 7, ' ' ), valueColor ) ) );
};

var shovel = m_shovels[ 0 ].Native;
var penetrationForce = new agx.Vec3();
var penetrationTorque = new agx.Vec3();
Native.getPenetrationForce( shovel, ref penetrationForce, ref penetrationTorque );
var separationForce = -Native.getSeparationContactForce( shovel );
var deformerForce = -Native.getDeformationContactForce( shovel );
var contactForce = -Native.getContactForce( shovel );

GUILayout.Label( Vec3Content( "Penetration force:", 1.0E-3 * penetrationForce ), m_textLabelStyle );
GUILayout.Space( 4 );
GUILayout.Label( Vec3Content( "Separation force: ", 1.0E-3 * separationForce ), m_textLabelStyle );
GUILayout.Space( 4 );
GUILayout.Label( Vec3Content( "Deformer force: ", 1.0E-3 * deformerForce ), m_textLabelStyle );
GUILayout.Space( 4 );
GUILayout.Label( Vec3Content( "Contact force: ", 1.0E-3 * contactForce ), m_textLabelStyle );
}

private Terrain m_terrain = null;
private float[,] m_initialHeights = null;

// -----------------------------------------------------------------------------------------------------------
// ------------------------------- Implementation of DeformableTerrainBase -----------------------------------
// -----------------------------------------------------------------------------------------------------------
public override float ElementSize => TerrainData.size.x / ( TerrainDataResolution - 1 );
public override DeformableTerrainShovel[] Shovels => m_shovels.ToArray();
public override agx.GranularBodyPtrArray GetParticles() { return Native?.getSoilSimulationInterface()?.getSoilParticles(); }
public override Uuid GetParticleMaterialUuid() => Native?.getMaterial( agxTerrain.Terrain.MaterialType.PARTICLE ).getUuid();
public override agxTerrain.SoilSimulationInterface GetSoilSimulationInterface() { return Native?.getSoilSimulationInterface(); }
public override agxTerrain.TerrainProperties GetProperties() { return Native?.getProperties(); }

public override bool Add( DeformableTerrainShovel shovel )
{
if ( shovel == null || m_shovels.Contains( shovel ) )
return false;

m_shovels.Add( shovel );

// Initialize shovel if we're initialized.
if ( Native != null )
Native.add( shovel.GetInitialized<DeformableTerrainShovel>().Native );

return true;
}

public override bool Remove( DeformableTerrainShovel shovel )
{
if ( shovel == null || !m_shovels.Contains( shovel ) )
return false;

if ( Native != null )
Native.remove( shovel.Native );

return m_shovels.Remove( shovel );
}

public override bool Contains( DeformableTerrainShovel shovel )
{
return shovel != null && m_shovels.Contains( shovel );
}

public override void RemoveInvalidShovels( bool removeDisabled = false, bool warn = false )
{
m_shovels.RemoveAll( shovel => shovel == null );
if ( removeDisabled ) {
int removed = m_shovels.RemoveAll( shovel => !shovel.isActiveAndEnabled );
if ( removed > 0 ) {
if ( warn )
Debug.LogWarning( $"Removed {removed} disabled shovels from terrain {gameObject.name}." +
" Disabled shovels should not be added to the terrain on play and should instead be added manually when enabled during runtime." +
" To fix this warning, please remove any disabled shovels from the terrain." );
else
Debug.Log( $"Removed {removed} disabled shovels from terrain {gameObject.name}." );
}
}
}
public override void ConvertToDynamicMassInShape( Shape failureVolume )
{
if ( !IsNativeNull() )
Expand Down
33 changes: 0 additions & 33 deletions AGXUnity/Model/DeformableTerrainBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,6 @@ public float MaximumDepth
/// </summary>
abstract public float ElementSize { get; }

/// <summary>
/// Shovels associated to this terrain.
/// </summary>
[HideInInspector]
abstract public DeformableTerrainShovel[] Shovels { get; }

protected override void OnEnable()
{
SetEnable( true );
Expand Down Expand Up @@ -183,33 +177,6 @@ protected override void OnDisable()
/// </summary>
virtual public void OnPropertiesUpdated() { }

/// <summary>
/// Associate shovel instance to this terrain.
/// </summary>
/// <param name="shovel">Shovel instance to add.</param>
/// <returns>True if added, false if null or already added.</returns>
abstract public bool Add( DeformableTerrainShovel shovel );

/// <summary>
/// Disassociate shovel instance to this terrain.
/// </summary>
/// <param name="shovel">Shovel instance to remove.</param>
/// <returns>True if removed, false if null or not associated to this terrain.</returns>
abstract public bool Remove( DeformableTerrainShovel shovel );

/// <summary>
/// Find if shovel has been associated to this terrain.
/// </summary>
/// <param name="shovel">Shovel instance to check.</param>
/// <returns>True if associated, otherwise false.</returns>
abstract public bool Contains( DeformableTerrainShovel shovel );

/// <summary>
/// Verifies so that all added shovels still exists. Shovels that
/// has been deleted are removed.
/// </summary>
abstract public void RemoveInvalidShovels( bool removeDisabled = false, bool warn = false );

/// <summary>
/// Converts any part of the terrain that overlaps the provided shape into dynamic mass
/// </summary>
Expand Down
70 changes: 26 additions & 44 deletions AGXUnity/Model/DeformableTerrainPager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class DeformableTerrainPager : DeformableTerrainBase
[SerializeField]
private List<PagingBody<DeformableTerrainShovel>> m_shovels = new List<PagingBody<DeformableTerrainShovel>>();


/// <summary>
/// Shovels along with their respective load radii that are associated with this terrainPager
/// </summary>
Expand All @@ -47,6 +48,12 @@ public class DeformableTerrainPager : DeformableTerrainBase
[HideInInspector]
public PagingBody<DeformableTerrainShovel>[] PagingShovels { get { return m_shovels.ToArray(); } }

/// <summary>
/// Rigidbodies associated to this terrain.
/// </summary>
[HideInInspector]
public DeformableTerrainShovel[] Shovels { get { return m_shovels.Select( rb => rb.Body ).ToArray(); } }

[SerializeField]
private List<PagingBody<RigidBody>> m_rigidbodies = new List<PagingBody<RigidBody>>();

Expand Down Expand Up @@ -178,6 +185,23 @@ public bool Add( DeformableTerrainShovel shovel, float requiredRadius = 5, float
return true;
}

/// <summary>
/// Disassociate shovel instance to this terrain.
/// </summary>
/// <param name="shovel">Shovel instance to remove.</param>
/// <returns>True if removed, false if null or not associated to this terrain.</returns>
public bool Remove( DeformableTerrainShovel shovel )
{
if ( shovel == null || m_shovels.Find( pagingRigidBody => pagingRigidBody.Body == shovel ) == null )
return false;

if ( Native != null )
Native.remove( shovel.Native );

m_shovels.RemoveAt( m_shovels.FindIndex( pagingRigidBody => pagingRigidBody.Body == shovel ) );
return true;
}

/// <summary>
/// Associates the given rigidbody instance to this terrain.
/// </summary>
Expand Down Expand Up @@ -316,8 +340,6 @@ protected override bool Initialize()
if ( AutoTileOnPlay )
RecalculateParameters();

RemoveInvalidShovels( true );

// Create a new adapter using the terrain attached to this gameobject as the root
// This attaches DeformableTerrainConnector components to each connected Unity terrain which must be done before InitializeNative is called
m_terrainDataSource = new UnityTerrainAdapter( Terrain, MaximumDepth );
Expand Down Expand Up @@ -370,6 +392,8 @@ private void InitializeNative()
Native.setTerrainDataSource( m_terrainDataSource );
Native.setShouldStoreCompaction( m_compactionStoreDepth.UseOverride, (uint)m_compactionStoreDepth.OverrideValue );

GetSimulation().add( Native );

// Add Rigidbodies and shovels to pager
foreach ( var shovel in m_shovels )
Native.add( shovel.Body.GetInitialized<DeformableTerrainShovel>().Native, shovel.requiredRadius, shovel.preloadRadius );
Expand All @@ -378,9 +402,6 @@ private void InitializeNative()

if ( MaterialPatches.Length != 0 )
Debug.LogWarning( "Nonhomogenous terrain is not yet supported for DeformableTerrainPager.", this );


GetSimulation().add( Native );
}

protected override void OnDestroy()
Expand Down Expand Up @@ -590,50 +611,11 @@ public static bool IsInteger( float v )
// -----------------------------------------------------------------------------------------------------------

public override float ElementSize => TerrainData.size.x / ( TerrainDataResolution - 1 );
public override DeformableTerrainShovel[] Shovels => m_shovels.Select( shovel => shovel.Body ).ToArray();
public override agx.GranularBodyPtrArray GetParticles() { return Native?.getSoilSimulationInterface()?.getSoilParticles(); }
public override agx.Uuid GetParticleMaterialUuid() => Native?.getTemplateTerrain()?.getMaterial( agxTerrain.Terrain.MaterialType.PARTICLE ).getUuid();
public override agxTerrain.TerrainProperties GetProperties() { return Native?.getTemplateTerrain()?.getProperties(); }
public override agxTerrain.SoilSimulationInterface GetSoilSimulationInterface() { return Native?.getSoilSimulationInterface(); }
public override void OnPropertiesUpdated() { Native?.applyChangesToTemplateTerrain(); }
public override bool Add( DeformableTerrainShovel shovel )
{
return Add( shovel, requiredRadius: default, preloadRadius: default );
}
public override bool Remove( DeformableTerrainShovel shovel )
{
if ( shovel == null || m_shovels.Find( pagingShovel => pagingShovel.Body == shovel ) == null )
return false;

if ( Native != null )
Native.remove( shovel.Native );

m_shovels.RemoveAt( m_shovels.FindIndex( pagingShovel => pagingShovel.Body == shovel ) );
return true;
}
public override bool Contains( DeformableTerrainShovel shovel )
{
return m_shovels.Find( s => s.Body == shovel ) != null;
}
public override void RemoveInvalidShovels( bool removeDisabled = false, bool warn = false )
{
m_shovels.RemoveAll( shovel => shovel.Body == null );
m_rigidbodies.RemoveAll( rb => rb.Body == null );

if ( removeDisabled ) {
int remShovels = m_shovels.RemoveAll( shovel => !shovel.Body.isActiveAndEnabled );
int remRBs = m_rigidbodies.RemoveAll( rb => !rb.Body.isActiveAndEnabled );
if ( remShovels + remRBs > 0 ) {
if ( warn )
Debug.LogWarning( $"Removed {remShovels} disabled shovels and {remRBs} disabled rigid bodies from terrain {gameObject.name}." +
" Disabled objects should not be added to the terrain on play and should instead be added manually when enabled during runtime." +
" To fix this warning, please remove any disabled objects from the terrain." );
else
Debug.Log( $"Removed {remShovels} disabled shovels and {remRBs} disabled rigid bodies from terrain {gameObject.name}." );

}
}
}
public override void ConvertToDynamicMassInShape( Shape failureVolume )
{
if ( Native != null ) {
Expand Down
Loading

0 comments on commit 1c3a68b

Please sign in to comment.