protected void CreateTriangleStripBuffer(ushort batchSize, IndexData destData)
{
/* For even / odd tri strip rows, triangles are this shape:
6---7---8
| \ | \ |
3---4---5
| / | / |
0---1---2
Note how vertex rows count upwards. In order to match up the anti-clockwise
winding and this upward transitioning list, we need to start from the
right hand side. So we get (2,5,1,4,0,3) etc on even lines (right-left)
and (3,6,4,7,5,8) etc on odd lines (left-right). At the turn, we emit the end index
twice, this forms a degenerate triangle, which lets us turn without any artefacts.
So the full list in this simple case is (2,5,1,4,0,3,3,6,4,7,5,8)
Skirts are part of the same strip, so after finishing on 8, where sX is
the skirt vertex corresponding to main vertex X, we go
anticlockwise around the edge, (s8,7,s7,6,s6) to do the top skirt,
then (3,s3,0,s0),(1,s1,2,s2),(5,s5,8,s8) to finish the left, bottom, and
right skirts respectively.
*/
// to issue a complete row, it takes issuing the upper and lower row
// and one extra index, which is the degenerate triangle and also turning
// around the winding
VertexDataRecord vdr = this.VertextDataRecord;
int mainIndexPerRow = batchSize * 2 + 1;
int numRows = batchSize - 1;
int mainIndexCount = mainIndexPerRow * numRows;
// skirts share edges, so they take 1 less row per side than batchSize,
// but with 2 extra at the end (repeated) to finish the strip
// * 2 for the vertical line, * 4 for the sides, +2 to finish
int skirtIndexCount = (batchSize - 1) * 2 * 4 + 2;
destData.indexStart = 0;
destData.indexCount = mainIndexCount + skirtIndexCount;
destData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, destData.indexCount, BufferUsage.Static,false);
#warning IndexBuffer.Bind(DefaultHardwareIndexBuffer);
unsafe
{
ushort* pI = (ushort*)(destData.indexBuffer.Lock(BufferLocking.Discard));
ushort* basepI = pI;
// Ratio of the main terrain resolution in relation to this vertex data resolution
int resolutionRatio = (mTerrain.Size - 1) / (vdr.Resolution - 1);
// At what frequency do we sample the vertex data we're using?
// mSize is the coverage in terms of the original terrain data (not split to fit in 16-bit)
int vertexIncrement = ( mSize -1 )/ (batchSize -1);
// however, the vertex data we're referencing may not be at the full resolution anyway
vertexIncrement /= resolutionRatio;
int rowSize = vdr.Size * vertexIncrement;
// Start on the right
ushort currentVertex = (ushort)((batchSize - 1) * vertexIncrement);
// but, our quad area might not start at 0 in this vertex data
// offsets are at main terrain resolution, remember
ushort columnStart = (ushort)((mOffsetX - mNodeWithVertexData.mOffsetX) / resolutionRatio);
ushort rowStart = (ushort)((mOffsetY - mNodeWithVertexData.mOffsetY) / resolutionRatio);
currentVertex +=(ushort)((rowStart * vdr.Size) + columnStart);
bool rightToLeft = true;
for (ushort r = 0; r < (ushort)numRows; ++r)
{
for (ushort c = 0; c < batchSize; ++c)
{
*pI++ = currentVertex;
*pI++ = (ushort)(currentVertex + rowSize);
// don't increment / decrement at a border, keep this vertex for next
// row as we 'snake' across the tile
if (c + 1 < batchSize)
{
currentVertex = rightToLeft ?
(ushort)(currentVertex - vertexIncrement) : (ushort)(currentVertex + vertexIncrement);
}
}
rightToLeft = !rightToLeft;
currentVertex += (ushort)rowSize;
// issue one extra index to turn winding around
*pI++ = currentVertex;
}
// Skirts
for (ushort s = 0; s < 4; ++s)
{
// edgeIncrement is the index offset from one original edge vertex to the next
// in this row or column. Columns skip based on a row size here
// skirtIncrement is the index offset from one skirt vertex to the next,
// because skirts are packed in rows/cols then there is no row multiplier for
// processing columns
int edgeIncrement = 0, skirtIncrement = 0;
switch (s)
{
case 0: //top
edgeIncrement = -(int)vertexIncrement;
skirtIncrement = -(int)vertexIncrement;
break;
case 1:// left
edgeIncrement = -(int)rowSize;
skirtIncrement = -(int)vertexIncrement;
break;
case 2://bottom
edgeIncrement = (int)vertexIncrement;
skirtIncrement = (int)vertexIncrement;
break;
case 3://right
edgeIncrement = (int)rowSize;
skirtIncrement = (int)vertexIncrement;
break;
}
// Skirts are stored in contiguous rows / columns (rows 0/2, cols 1/3)
ushort skirtIndex = CalcSkirtVertexIndex(currentVertex, (s % 2) != 0);
for (ushort c = 0; c < (ushort)(batchSize - 1); ++c)
{
*pI++ = currentVertex;
*pI++ = skirtIndex;
currentVertex += (ushort)edgeIncrement;
skirtIndex += (ushort)skirtIncrement;
}
if (s == 3)
{
// we issue an extra 2 indices to finish the skirt off
*pI++ = currentVertex;
*pI++ = skirtIndex;
currentVertex += (ushort)edgeIncrement;
skirtIndex += (ushort)skirtIncrement;
}
}//end for
ushort val = (ushort)(pI - basepI);
//Debug.Assert(val == (ushort)destData.indexCount, "wrong indices");
}//end unsafe
}
/// <summary>