public void NeighbourModified( NeighbourIndex index, Rectangle edgerect, Rectangle shadowrect )
{
// We can safely assume that we would not have been contacted if it wasn't
// important
var neighbour = GetNeighbour( index );
if ( neighbour == null )
{
return; // bogus request
}
var updateGeom = false;
byte updateDerived = 0;
if ( !edgerect.IsNull )
{
// update edges; match heights first, then recalculate normals
// reduce to just single line / corner
var heightMatchRect = new Rectangle();
GetEdgeRect( index, 1, ref heightMatchRect );
heightMatchRect = heightMatchRect.Intersect( edgerect );
for ( var y = heightMatchRect.Top; y < heightMatchRect.Bottom; ++y )
{
for ( var x = heightMatchRect.Left; x < heightMatchRect.Right; ++x )
{
long nx = 0, ny = 0;
GetNeighbourPoint( index, x, y, ref nx, ref ny );
var neighbourHeight = neighbour.GetHeightAtPoint( nx, ny );
if ( !Utility.RealEqual( neighbourHeight, GetHeightAtPoint( x, y ), 1e-3f ) )
{
SetHeightAtPoint( x, y, neighbourHeight );
if ( !updateGeom )
{
updateGeom = true;
updateDerived |= DERIVED_DATA_ALL;
}
}
}
}
// if we didn't need to update heights, we still need to update normals
// because this was called only if neighbor changed
if ( !updateGeom )
{
// ideally we would deal with normal dirty rect separately (as we do with
// lightmaps) because a dirty geom rectangle will actually grow by one
// element in each direction for normals recalculation. However for
// the sake of one row/column it's really not worth it.
this.mDirtyDerivedDataRect.Merge( edgerect );
updateDerived |= DERIVED_DATA_NORMALS;
}
}
if ( !shadowrect.IsNull )
{
// update shadows
// here we need to widen the rect passed in based on the min/max height
// of the *neighbour*
var lightVec = TerrainGlobalOptions.LightMapDirection;
var widenedRect = new Rectangle();
WidenRectByVector( lightVec, shadowrect, neighbour.MinHeight, neighbour.MaxHeight, ref widenedRect );
// set the special-case lightmap dirty rectangle
this.mDirtyLightmapFromNeighboursRect.Merge( widenedRect );
updateDerived |= DERIVED_DATA_LIGHTMAP;
}
if ( updateGeom )
{
UpdateGeometry();
}
if ( updateDerived != 0 )
{
UpdateDerivedData( false, updateDerived );
}
}