public void CalculateMinLevelDist2( Real C )
#endif
{
//level 0 has no delta.
this.mMinLevelDistSqr[ 0 ] = 0;
int i, j;
for ( var level = 1; level < this.mOptions.maxGeoMipMapLevel; level++ )
{
this.mMinLevelDistSqr[ level ] = 0;
var step = 1 << level;
// The step of the next higher LOD
var higherstep = step >> 1;
#if AXIOM_SAFE_ONLY
ITypePointer<float> pDeltas = null;
#else
float* pDeltas = null;
#endif
BufferBase dataPtr;
if ( this.mOptions.lodMorph )
{
// Create a set of delta values (store at index - 1 since 0 has none)
this.mDeltaBuffers[ level - 1 ] = CreateDeltaBuffer();
// Lock, but don't discard (we want the pre-initialised zeros)
dataPtr = this.mDeltaBuffers[ level - 1 ].Lock( BufferLocking.Normal );
pDeltas = dataPtr.ToFloatPointer();
}
for ( j = 0; j < this.mOptions.tileSize - step; j += step )
{
for ( i = 0; i < this.mOptions.tileSize - step; i += step )
{
/* Form planes relating to the lower detail tris to be produced
For tri lists and even tri strip rows, they are this shape:
x---x
| / |
x---x
For odd tri strip rows, they are this shape:
x---x
| \ |
x---x
*/
var v1 = new Vector3( Vertex( i, j, 0 ), Vertex( i, j, 1 ), Vertex( i, j, 2 ) );
var v2 = new Vector3( Vertex( i + step, j, 0 ), Vertex( i + step, j, 1 ), Vertex( i + step, j, 2 ) );
var v3 = new Vector3( Vertex( i, j + step, 0 ), Vertex( i, j + step, 1 ), Vertex( i, j + step, 2 ) );
var v4 = new Vector3( Vertex( i + step, j + step, 0 ), Vertex( i + step, j + step, 1 ),
Vertex( i + step, j + step, 2 ) );
Plane t1, t2;
t1 = new Plane();
t2 = new Plane();
var backwardTri = false;
if ( !this.mOptions.useTriStrips || j%2 == 0 )
{
t1.Redefine( v1, v3, v2 );
t2.Redefine( v2, v3, v4 );
}
else
{
t1.Redefine( v1, v3, v4 );
t2.Redefine( v1, v4, v2 );
backwardTri = true;
}
// include the bottommost row of vertices if this is the last row
var zubound = ( j == ( this.mOptions.tileSize - step ) ? step : step - 1 );
for ( var z = 0; z <= zubound; z++ )
{
// include the rightmost col of vertices if this is the last col
var xubound = ( i == ( this.mOptions.tileSize - step ) ? step : step - 1 );
for ( var x = 0; x <= xubound; x++ )
{
var fulldetailx = i + x;
var fulldetailz = j + z;
if ( fulldetailx%step == 0 && fulldetailz%step == 0 )
{
// Skip, this one is a vertex at this level
continue;
}
var zpct = (Real)z/(Real)step;
var xpct = (Real)x/(Real)step;
//interpolated height
var actualPos = new Vector3( Vertex( fulldetailx, fulldetailz, 0 ), Vertex( fulldetailx, fulldetailz, 1 ),
Vertex( fulldetailx, fulldetailz, 2 ) );
Real interp_h;
// Determine which tri we're on
if ( ( xpct + zpct <= 1.0f && !backwardTri ) || ( xpct + ( 1 - zpct ) <= 1.0f && backwardTri ) )
{
// Solve for x/z
interp_h = ( -( t1.Normal.x*actualPos.x ) - t1.Normal.z*actualPos.z - t1.D )/t1.Normal.y;
}
else
{
// Second tri
interp_h = ( -( t2.Normal.x*actualPos.x ) - t2.Normal.z*actualPos.z - t2.D )/t2.Normal.y;
}
Real actual_h = Vertex( fulldetailx, fulldetailz, 1 );
//Check: not sure about fabs used here...
Real delta = Math.Abs( interp_h - actual_h );
var D2 = delta*delta*C*C;
if ( this.mMinLevelDistSqr[ level ] < D2 )
{
this.mMinLevelDistSqr[ level ] = D2;
}
// Should be save height difference?
// Don't morph along edges
if ( this.mOptions.lodMorph && fulldetailx != 0 && fulldetailx != ( this.mOptions.tileSize - 1 ) &&
fulldetailz != 0 &&
fulldetailz != ( this.mOptions.tileSize - 1 ) )
{
// Save height difference
pDeltas[ (int)( fulldetailx + ( fulldetailz*this.mOptions.tileSize ) ) ] = interp_h - actual_h;
}
}
}
}
}
// Unlock morph deltas if required
if ( this.mOptions.lodMorph )
{
this.mDeltaBuffers[ level - 1 ].Unlock();
}
}
// Post validate the whole set
for ( i = 1; i < this.mOptions.maxGeoMipMapLevel; i++ )
{
// Make sure no LOD transition within the tile
// This is especially a problem when using large tiles with flat areas
/* Hmm, this can look bad on some areas, disable for now
Vector3 delta(_vertex(0,0,0), mCenter.y, _vertex(0,0,2));
delta = delta - mCenter;
Real minDist = delta.squaredLength();
mMinLevelDistSqr[ i ] = std::max(mMinLevelDistSqr[ i ], minDist);
*/
//make sure the levels are increasing...
if ( this.mMinLevelDistSqr[ i ] < this.mMinLevelDistSqr[ i - 1 ] )
{
this.mMinLevelDistSqr[ i ] = this.mMinLevelDistSqr[ i - 1 ];
}
}
// Now reverse traverse the list setting the 'next level down'
Real lastDist = -1;
var lastIndex = 0;
for ( i = this.mOptions.maxGeoMipMapLevel - 1; i >= 0; --i )
{
if ( i == this.mOptions.maxGeoMipMapLevel - 1 )
{
// Last one is always 0
lastIndex = i;
lastDist = this.mMinLevelDistSqr[ i ];
this.mNextLevelDown[ i ] = 0;
}
else
{
this.mNextLevelDown[ i ] = lastIndex;
if ( this.mMinLevelDistSqr[ i ] != lastDist )
{
lastIndex = i;
lastDist = this.mMinLevelDistSqr[ i ];
}
}
}
}