Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions AGXUnity/Model/DeformableTerrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
8 changes: 2 additions & 6 deletions AGXUnity/Model/DeformableTerrainConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public Vector3 GetOffsetPosition()
var resolution = TerrainUtils.TerrainDataResolution(Terrain.terrainData);
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!" );
Expand All @@ -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;
}
}
Expand Down
39 changes: 31 additions & 8 deletions AGXUnity/Model/DeformableTerrainPager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ private void InitializeNative()
foreach ( var rb in m_rigidbodies )
Native.add( rb.Body.GetInitialized<RigidBody>().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()
Expand Down Expand Up @@ -433,7 +432,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;
Expand All @@ -445,12 +444,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, Terrain, unityIndex );
OnModification?.Invoke( terrain, index, tile, unityIndex );
m_updatedTerrains.Add( tile );
};

Expand Down Expand Up @@ -834,17 +833,41 @@ 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 = Native.getTemplateTerrain().exchangeTerrainMaterial( oldMat.Native, newMat.Native );
Native.applyChangesToTemplateTerrain();
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;

Native.getTemplateTerrain().setAssociatedMaterial( terrMat.Native, shapeMat.Native );
Native.applyChangesToTemplateTerrain();
}

public override void AddTerrainMaterial( DeformableTerrainMaterial terrMat, Shape shape = null )
{
throw new NotImplementedException( "Terrain pager does not yet support Inhomogeneous terrain" );
if ( Native == null )
return;

var template = Native.getTemplateTerrain();
var idx = template.getMaterialController().getTerrainMaterialIndex( terrMat.Native );
if ( idx == uint.MaxValue ) {
template.addTerrainMaterial( terrMat.Native );
idx = template.getMaterialController().getTerrainMaterialIndex( terrMat.Native );
}
if ( shape != null )
m_terrainDataSource.addTerrainMaterialSourceGeometry( shape.NativeGeometry, idx );

Native.applyChangesToTemplateTerrain();
}

protected override bool IsNativeNull() { return Native == null; }
Expand Down
142 changes: 65 additions & 77 deletions AGXUnity/Rendering/TerrainPatchRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,12 @@

namespace AGXUnity.Rendering
{
/// <summary>
/// Wrapper class for storing/resetting initial state of TerrainData.
/// This is by no means a complete store/restore, only the parts used by <see cref="TerrainPatchRenderer"/>.
/// </summary>
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<agxTerrain.TerrainMaterial, int> m_materialMapping;
public int m_layerCount;
public int m_defaultLayerIndex;
}

[RequireComponent( typeof( DeformableTerrainBase ) )]
Expand All @@ -37,11 +21,9 @@ public void Reset( TerrainData td )
public class TerrainPatchRenderer : ScriptComponent
{
private DeformableTerrainBase terrain;
private float[,,] alphamap;
private Dictionary<agxTerrain.TerrainMaterial, int> m_materialMapping;
private InitialTerrainData m_initialData;
private int m_layerCount;
private int m_defaultLayerIndex;

private Dictionary<Terrain, TileData> m_perTileData;
private List<Terrain> m_shouldUpdate;

[SerializeField]
private TerrainLayer m_defaultLayer;
Expand All @@ -56,7 +38,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;
Expand All @@ -77,7 +59,7 @@ public SerializableDictionary<DeformableTerrainMaterial, TerrainLayer> 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;
Expand Down Expand Up @@ -109,37 +91,18 @@ public Dictionary<DeformableTerrainMaterial, TerrainLayer> MaterialRenderMap

public TerrainMaterialPatch[] RenderedPatches => gameObject.GetComponentsInChildren<TerrainMaterialPatch>();

protected override bool Initialize()
private void InitializeTile( Terrain tile )
{
terrain = gameObject.GetInitializedComponent<DeformableTerrainBase>();
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<Terrain>();
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<agxTerrain.TerrainMaterial, int>();
tileData.m_materialMapping = new Dictionary<agxTerrain.TerrainMaterial, int>();
foreach ( var (mat, tl) in MaterialRenderMap ) {
var terrMat = mat.GetInitialized<DeformableTerrainMaterial>().Native;
if ( terrMat != null ) {
Expand All @@ -150,34 +113,50 @@ protected override bool Initialize()

if ( !layers.Contains( tl ) )
layers.Add( tl );
m_materialMapping.Add( mat.GetInitialized<DeformableTerrainMaterial>().Native, layers.IndexOf( tl ) );
tileData.m_materialMapping.Add( mat.GetInitialized<DeformableTerrainMaterial>().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<DeformableTerrainBase>();
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<Terrain>();
var td = uTerr.terrainData;

protected override void OnApplicationQuit()
{
m_initialData?.Reset( GetComponent<Terrain>().terrainData );
}
m_perTileData = new Dictionary<Terrain, TileData>();
m_shouldUpdate = new List<Terrain>();

protected override void OnDestroy()
{
m_initialData?.Reset( GetComponent<Terrain>().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()
Expand All @@ -201,23 +180,32 @@ protected override void OnEnable()

private void PostStep()
{
var td = GetComponent<Terrain>().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;

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);
Expand All @@ -231,8 +219,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;
}
}
}
Expand Down
Binary file modified Plugins/x86_64/agxDotNet.dll
Binary file not shown.
Loading