public bool Prepare( ImportData importData )
{
FreeTemporaryResources();
FreeCPUResources();
CopyGlobalOptions();
//validate
if (
!( Bitwise.IsPow2( importData.TerrainSize - 1 ) && Bitwise.IsPow2( importData.MinBatchSize - 1 ) &&
Bitwise.IsPow2( importData.MaxBatchSize - 1 ) ) )
{
throw new AxiomException( "terrainSize, minBatchSize and maxBatchSize must all be n^2 + 1. Terrain.Prepare" );
}
if ( importData.MinBatchSize > importData.MaxBatchSize )
{
throw new AxiomException( "MinBatchSize must be less then or equal to MaxBatchSize. Terrain.Prepare" );
}
if ( importData.MaxBatchSize > TERRAIN_MAX_BATCH_SIZE )
{
throw new AxiomException( "MaxBatchSize must be not larger then {0} . Terrain.Prepare", TERRAIN_MAX_BATCH_SIZE );
}
Alignment = importData.TerrainAlign;
this.mSize = importData.TerrainSize;
this.mWorldSize = importData.WorldSize;
this.mLayerDecl = importData.LayerDeclaration;
CheckDeclaration();
this.mLayers = importData.LayerList;
CheckLayers( false );
DeriveUVMultipliers();
this.mMaxBatchSize = importData.MaxBatchSize;
this.mMinBatchSize = importData.MinBatchSize;
this.mPos = importData.Pos;
UpdateBaseScale();
DetermineLodLevels();
int numVertices = this.mSize*this.mSize;
this.mHeightData = new float[numVertices];
if ( importData.InputFloat != null )
{
if ( Utility.RealEqual( importData.InputBias, 0.0f ) && Utility.RealEqual( importData.InputScale, 1.0f ) )
{
//straigt copy
this.mHeightData = new float[numVertices];
Array.Copy( importData.InputFloat, this.mHeightData, this.mHeightData.Length );
}
else
{
// scale & bias, lets do it unsafe, should be faster :)
var src = importData.InputFloat;
for ( var i = 0; i < numVertices; ++i )
{
this.mHeightData[ i ] = ( src[ i ]*importData.InputScale ) + importData.InputBias;
}
}
}
else if ( importData.InputImage != null )
{
var img = importData.InputImage;
if ( img.Width != this.mSize || img.Height != this.mSize )
{
img.Resize( this.mSize, this.mSize );
}
// convert image data to floats
// Do this on a row-by-row basis, because we describe the terrain in
// a bottom-up fashion (ie ascending world coords), while Image is top-down
var pSrcBaseF = BufferBase.Wrap( img.Data );
var pHeightDataF = BufferBase.Wrap( this.mHeightData, mHeightData.Length * sizeof(float) );
for ( var i = 0; i < this.mSize; ++i )
{
var srcy = this.mSize - i - 1;
using ( var pSrc = pSrcBaseF + srcy*img.RowSpan )
{
using ( var pDest = pHeightDataF + i*this.mSize*sizeof ( float ) )
{
PixelConverter.BulkPixelConversion( pSrc, img.Format, pDest, PixelFormat.FLOAT32_R, this.mSize );
}
}
}
pSrcBaseF.Dispose();
pHeightDataF.Dispose();
if ( !Utility.RealEqual( importData.InputBias, 0.0f ) || !Utility.RealEqual( importData.InputScale, 1.0f ) )
{
for ( int i = 0; i < numVertices; ++i )
{
this.mHeightData[ i ] = ( this.mHeightData[ i ]*importData.InputScale ) + importData.InputBias;
}
}
}
else
{
// start with flat terrain
this.mHeightData = new float[this.mSize*this.mSize];
}
var deltaData = new float[numVertices];
this.mHeightDataPtr = BufferBase.Wrap( this.mHeightData,mHeightData.Length * sizeof(float) );
this.mDeltaDataPtr = BufferBase.Wrap( deltaData, deltaData.Length * sizeof(float) );
var numLevel = (ushort)(int)( NumLodLevels - 1 );
QuadTree = new TerrainQuadTreeNode( this, null, 0, 0, this.mSize, (ushort)( NumLodLevels - 1 ), 0, 0 );
QuadTree.Prepare();
//calculate entire terrain
var rect = new Rectangle();
rect.Top = 0;
rect.Bottom = this.mSize;
rect.Left = 0;
rect.Right = this.mSize;
CalculateHeightDeltas( rect );
FinalizeHeightDeltas( rect, true );
DistributeVertexData();
// Imported data is treated as modified because it's not saved
IsModified = true;
IsHeightDataModified = true;
return true;
}