Skip to content

Commit

Permalink
Merge pull request #126 from Algoryx/feature/merge-nearby
Browse files Browse the repository at this point in the history
Add Merge Nearby Vertices mesh processing option
  • Loading branch information
FilipAlg authored Aug 14, 2023
2 parents 2826e94 + 9151c96 commit be5c52a
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 24 deletions.
19 changes: 19 additions & 0 deletions AGXUnity/Collide/CollisionMeshGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,25 @@ private static CollisionMeshData CreateDataOptionallyReduce( Mesh mesh,
return null;
}

// Next, if merge nearby vertices is enabled, do that too:
var mergeNearbyEnabled = options != null && options.MergeNearbyEnabled;
orgNumVertices = merger.Vertices.Count;
if (mergeNearbyEnabled) {
merger.MergeNearby(options.MergeNearbyDistance);
}

if (merger.Vertices.Count == 0)
{
if (mergeNearbyEnabled && orgNumVertices > 0)
UnityEngine.Debug.LogWarning($"Merging nearby Vertices reduced a collision mesh from {orgNumVertices} vertices to zero. " +
"Ignoring collision mesh.", mesh);
else
UnityEngine.Debug.LogWarning($"Mesh \"{mesh.name}\" doesn't contain any vertices for the collision mesh. " +
"Ignoring collision mesh.", mesh);

return null;
}

var meshData = new CollisionMeshData();
meshData.Apply( merger.Vertices, merger.Indices );

Expand Down
45 changes: 44 additions & 1 deletion AGXUnity/Collide/CollisionMeshOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,41 @@ public MeshMode Mode
}
}

/// <summary>
/// Enable/disable merging of nearby vertices
/// Note that Apply has to be called before the change to take effect.
/// </summary>
[InspectorGroupBegin(Name = "Mesh Cleanup")]
public bool MergeNearbyEnabled
{
get { return m_mergeNearbyEnabled; }
set
{
if (m_mergeNearbyEnabled == value)
return;

m_mergeNearbyEnabled = value;
}
}

/// <summary>
/// Specify distance used for merging nearby vertices ranging from [0, 1] where 0 is
/// no reduction. Any vertex closer than this distance will be merged.
/// Note that Apply has to be called before the change to take effect.
/// </summary>
[FloatSliderInInspector(0.0001f, 1f)]
public float MergeNearbyDistance
{
get { return m_mergeNearbyDistance; }
set
{
if (Utils.Math.Approximately(m_mergeNearbyDistance, value))
return;

m_mergeNearbyDistance = Utils.Math.Clamp(value, 0, 1);
}
}

/// <summary>
/// Enable/disable triangle reduction of the mesh data.
/// Note that Apply has to be called before the change to take effect.
Expand Down Expand Up @@ -111,10 +146,12 @@ public int ElementResolutionPerAxis
/// <summary>
/// Reset all values to default.
/// </summary>
public void ResetToDesfault()
public void ResetToDefault()
{
m_mode = MeshMode.Trimesh;
m_reductionEnabled = false;
m_mergeNearbyEnabled = false;
m_mergeNearbyDistance = 1E-3f;
m_reductionRatio = 0.5f;
m_reductionAggressiveness = 7.0f;
m_elementResolutionPerAxis = 50;
Expand All @@ -124,9 +161,15 @@ public void ResetToDesfault()
[SerializeField]
private MeshMode m_mode = MeshMode.Trimesh;

[SerializeField]
private bool m_mergeNearbyEnabled = false;

[SerializeField]
private bool m_reductionEnabled = false;

[SerializeField]
private float m_mergeNearbyDistance = 1e-3f;

[SerializeField]
private float m_reductionRatio = 0.5f;

Expand Down
19 changes: 19 additions & 0 deletions AGXUnity/Utils/MeshMerger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ public MeshMerger( Transform transform )
m_toWorld = transform.localToWorldMatrix;
}

public bool MergeNearby(float mergeNearbyDistance)
{
if (m_vertices.Count == 0)
return false;

var reducedVertices = new agx.Vec3Vector();
var reducedIndices = new agx.UInt32Vector();
agxUtil.agxUtilSWIG.mergeDuplicateVertices(Vertices,
Indices,
reducedVertices,
reducedIndices,
mergeNearbyDistance);

m_vertices = reducedVertices;
m_indices = reducedIndices;

return true;
}

public bool Reduce( float reductionRatio, float reductionAggressiveness )
{
if ( m_vertices.Count == 0 )
Expand Down
43 changes: 20 additions & 23 deletions Editor/AGXUnityEditor/Tools/ShapeMeshTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,39 @@

namespace AGXUnityEditor.Tools
{
public static class CanceledAsyncCollisionMeshGeneretors
public static class CancelledAsyncCollisionMeshGenerators
{
public static void RegisterCanceled( AGXUnity.Collide.CollisionMeshGenerator generator )
public static void RegisterCancelled( AGXUnity.Collide.CollisionMeshGenerator generator )
{
if ( generator == null || s_canceledGenerators.Contains( generator ) )
if ( generator == null || s_cancelledGenerators.Contains( generator ) )
return;

if ( s_canceledGenerators.Count == 0 )
if ( s_cancelledGenerators.Count == 0 )
EditorApplication.update += OnUpdate;

Debug.Log( $"Registering canceled: {generator.GetHashCode()}" );
s_canceledGenerators.Add( generator );
Debug.Log( $"Registering cancelled: {generator.GetHashCode()}" );
s_cancelledGenerators.Add( generator );
}

private static void OnUpdate()
{
var generators = s_canceledGenerators.ToArray();
var generators = s_cancelledGenerators.ToArray();
if ( generators.Length == 0 ) {
Debug.Log( "Unregister update callback, all canceled tasks has been removed." );
Debug.Log( "Unregister update callback, all cancelled tasks has been removed." );
EditorApplication.update -= OnUpdate;
return;
}

foreach ( var generator in generators ) {
if ( generator.IsRunning )
continue;
Debug.Log( $"Canceled generator is done - removing {generator.GetHashCode()} from queue." );
Debug.Log( $"Cancelled generator is done - removing {generator.GetHashCode()} from queue." );
generator.Dispose();
s_canceledGenerators.Remove( generator );
s_cancelledGenerators.Remove( generator );
}
}

private static List<AGXUnity.Collide.CollisionMeshGenerator> s_canceledGenerators = new List<AGXUnity.Collide.CollisionMeshGenerator>();
private static List<AGXUnity.Collide.CollisionMeshGenerator> s_cancelledGenerators = new List<AGXUnity.Collide.CollisionMeshGenerator>();
}

[CustomTool( typeof( AGXUnity.Collide.Mesh ) )]
Expand Down Expand Up @@ -121,10 +121,6 @@ private void MeshOptionsGUI()
using ( new GUI.EnabledBlock( !EditorApplication.isPlayingOrWillChangePlaymode ) ) {
if ( InspectorGUI.Foldout( GetEditorData( Mesh ), GUI.MakeLabel( "Options" ) ) ) {
using ( InspectorGUI.IndentScope.Single ) {
if ( GetTargets<AGXUnity.Collide.Mesh>().Any( mesh => PrefabUtils.IsPrefabInstance( mesh ) ) )
InspectorGUI.WarningLabel( "WARNING!\n\nEditing mesh Options on a prefab <b>instance</b> may cause the Editor to hang\n" +
"due to extensive prefab Overrides.\n\nConsider making the changes in the <b>Prefab Stage</b> instead." );

InspectorEditor.DrawMembersGUI( Targets, t => ( t as AGXUnity.Collide.Mesh ).Options );
var applyResetResult = InspectorGUI.PositiveNegativeButtons( UnityEngine.GUI.enabled,
"Apply",
Expand All @@ -136,20 +132,21 @@ private void MeshOptionsGUI()
var collisionMeshGenerator = new AGXUnity.Collide.CollisionMeshGenerator();
var generatorStartTime = EditorApplication.timeSinceStartup;
collisionMeshGenerator.GenerateAsync( meshes );
var isCanceled = false;
while ( !isCanceled && collisionMeshGenerator.IsRunning ) {
var isCancelled = false;

while ( !isCancelled && collisionMeshGenerator.IsRunning ) {
var progressBarTitle = $"Generating collision meshes: {(int)( EditorApplication.timeSinceStartup - generatorStartTime )} s";
var progressBarInfo = string.Empty;
var progress = collisionMeshGenerator.Progress;
isCanceled = EditorUtility.DisplayCancelableProgressBar( progressBarTitle, progressBarInfo, progress );
if ( !isCanceled )
isCancelled = EditorUtility.DisplayCancelableProgressBar( progressBarTitle, progressBarInfo, progress );
if ( !isCancelled )
System.Threading.Thread.Sleep( 50 );
}

EditorUtility.ClearProgressBar();

if ( isCanceled )
CanceledAsyncCollisionMeshGeneretors.RegisterCanceled( collisionMeshGenerator );
if ( isCancelled )
CancelledAsyncCollisionMeshGenerators.RegisterCancelled( collisionMeshGenerator );
else {
var results = collisionMeshGenerator.CollectResults();
using ( new Utils.UndoCollapseBlock( "Apply collision mesh data" ) ) {
Expand All @@ -159,7 +156,7 @@ private void MeshOptionsGUI()
result.Mesh.PrecomputedCollisionMeshes = result.CollisionMeshes;
}
}

var hasPrefabAssetBeenChanged = results.Any( result =>
PrefabUtility.GetCorrespondingObjectFromOriginalSource( result.Mesh.gameObject ) == null &&
PrefabUtility.GetPrefabInstanceHandle( result.Mesh.gameObject ) == null );
Expand Down Expand Up @@ -189,7 +186,7 @@ private void MeshOptionsGUI()
mesh.DestroyCollisionMeshes();
if ( mesh.Options != null ) {
Undo.RecordObject( mesh, "Resetting mesh options to default" );
mesh.Options.ResetToDesfault();
mesh.Options.ResetToDefault();
}
}
}
Expand Down

0 comments on commit be5c52a

Please sign in to comment.