private void _setupGeometry()
{
int vertexCount = _caption.Length * 6;
if ( renderOperation.vertexData != null )
{
renderOperation.vertexData = null;
_updateColor = true;
}
if ( renderOperation.vertexData == null )
renderOperation.vertexData = new VertexData();
renderOperation.indexData = null;
renderOperation.vertexData.vertexStart = 0;
renderOperation.vertexData.vertexCount = vertexCount;
renderOperation.operationType = OperationType.TriangleList;
renderOperation.useIndices = false;
VertexDeclaration decl = renderOperation.vertexData.vertexDeclaration;
VertexBufferBinding bind = renderOperation.vertexData.vertexBufferBinding;
int offset = 0;
// create/bind positions/tex.ccord. buffer
if ( decl.FindElementBySemantic( VertexElementSemantic.Position ) == null )
decl.AddElement( POS_TEX_BINDING, offset, VertexElementType.Float3, VertexElementSemantic.Position );
offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
if ( decl.FindElementBySemantic( VertexElementSemantic.TexCoords ) == null )
decl.AddElement( POS_TEX_BINDING, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 );
HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl.Clone( POS_TEX_BINDING ), renderOperation.vertexData.vertexCount, BufferUsage.DynamicWriteOnly );
bind.SetBinding( POS_TEX_BINDING, vbuf );
// Colors - store these in a separate buffer because they change less often
if ( decl.FindElementBySemantic( VertexElementSemantic.Diffuse ) == null )
decl.AddElement( COLOR_BINDING, 0, VertexElementType.Color, VertexElementSemantic.Diffuse );
HardwareVertexBuffer cbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl.Clone( COLOR_BINDING ), renderOperation.vertexData.vertexCount, BufferUsage.DynamicWriteOnly );
bind.SetBinding( COLOR_BINDING, cbuf );
int charlen = _caption.Length;
float largestWidth = 0.0f;
float left = 0f * 2.0f - 1.0f;
float top = -( ( 0f * 2.0f ) - 1.0f );
// Derive space with from a capital A
if ( _spaceWidth == 0 )
_spaceWidth = (int)( _font.GetGlyphAspectRatio( 'A' ) * _characterHeight * 2.0f );
// for calculation of AABB
Vector3 min, max, currPos;
float maxSquaredRadius = 0.0f;
bool first = true;
min = max = currPos = Vector3.NegativeUnitY;
// Use iterator
bool newLine = true;
float len = 0.0f;
if ( _verticalAlignment == VerticalAlignment.Above )
{
// Raise the first line of the caption
top += _characterHeight;
for ( int i = 0; i != charlen; i++ )
{
if ( _caption[ i ] == '\n' )
top += _characterHeight * 2.0f;
}
}
//Real *pPCBuff = static_cast<Real*>(ptbuf.lock(HardwareBuffer::HBL_DISCARD));
IntPtr ipPos = vbuf.Lock( BufferLocking.Discard );
int cntPos = 0;
unsafe
{
float* pPCBuff = (float*)ipPos.ToPointer();
for ( int i = 0; i != charlen; i++ )
{
if ( newLine )
{
len = 0.0f;
for ( int j = i; j != charlen && _caption[ j ] != '\n'; j++ )
{
if ( _caption[ j ] == ' ' )
len += _spaceWidth;
else
len += _font.GetGlyphAspectRatio( _caption[ j ] ) * _characterHeight * 2.0f;
}
newLine = false;
}
if ( _caption[ i ] == '\n' )
{
left = 0f * 2.0f - 1.0f;
top -= _characterHeight * 2.0f;
newLine = true;
continue;
}
if ( _caption[ i ] == ' ' )
{
// Just leave a gap, no tris
left += _spaceWidth;
// Also reduce tri count
renderOperation.vertexData.vertexCount -= 6;
continue;
}
float horiz_height = _font.GetGlyphAspectRatio( _caption[ i ] );
Real u1, u2, v1, v2;
_font.GetGlyphTexCoords( _caption[ i ], out u1, out v1, out u2, out v2 );
// each vert is (x, y, z, u, v)
//-------------------------------------------------------------------------------------
// First tri
//
// Upper left
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u1;
pPCBuff[ cntPos++ ] = v1;
// Deal with bounds
if ( _horizontalAlignment == HorizontalAlignment.Left )
currPos = new Vector3( left, top, -1.0f );
else
currPos = new Vector3( left - ( len / 2.0f ), top, -1.0f );
if ( first )
{
min = max = currPos;
maxSquaredRadius = currPos.LengthSquared;
first = false;
}
else
{
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
}
top -= _characterHeight * 2.0f;
// Bottom left
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u1;
pPCBuff[ cntPos++ ] = v2;
// Deal with bounds
if ( _horizontalAlignment == HorizontalAlignment.Left )
currPos = new Vector3( left, top, -1.0f );
else
currPos = new Vector3( left - ( len / 2.0f ), top, -1.0f );
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
top += _characterHeight * 2.0f;
left += horiz_height * _characterHeight * 2.0f;
// Top right
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u2;
pPCBuff[ cntPos++ ] = v1;
//-------------------------------------------------------------------------------------
// Deal with bounds
if ( _horizontalAlignment == HorizontalAlignment.Left )
currPos = new Vector3( left, top, -1.0f );
else
currPos = new Vector3( left - ( len / 2.0f ), top, -1.0f );
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
//-------------------------------------------------------------------------------------
// Second tri
//
// Top right (again)
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u2;
pPCBuff[ cntPos++ ] = v1;
currPos = new Vector3( left, top, -1.0f );
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
top -= _characterHeight * 2.0f;
left -= horiz_height * _characterHeight * 2.0f;
// Bottom left (again)
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u1;
pPCBuff[ cntPos++ ] = v2;
currPos = new Vector3( left, top, -1.0f );
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
left += horiz_height * _characterHeight * 2.0f;
// Bottom right
if ( _horizontalAlignment == HorizontalAlignment.Left )
pPCBuff[ cntPos++ ] = left;
else
pPCBuff[ cntPos++ ] = left - ( len / 2.0f );
pPCBuff[ cntPos++ ] = top;
pPCBuff[ cntPos++ ] = -1.0f;
pPCBuff[ cntPos++ ] = u2;
pPCBuff[ cntPos++ ] = v2;
//-------------------------------------------------------------------------------------
currPos = new Vector3( left, top, -1.0f );
min.Floor( currPos );
max.Ceil( currPos );
maxSquaredRadius = Utility.Max( maxSquaredRadius, currPos.LengthSquared );
// Go back up with top
top += _characterHeight * 2.0f;
float currentWidth = ( left + 1.0f ) / 2.0f - 0.0f;
if ( currentWidth > largestWidth )
largestWidth = currentWidth;
}
}
// Unlock vertex buffer
vbuf.Unlock();
// update AABB/Sphere radius
this.box = new AxisAlignedBox( min, max );
this._radius = Utility.Sqrt( maxSquaredRadius );
if ( _updateColor )
this._updateColors();
_needUpdate = false;
}