#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; namespace Nuclex.Graphics.SpecialEffects { /// Builds index lists for drawing vertex grids as triangle strips public static class TriangleStripIndexBuilder { /// /// Calculates the number of vertex indices required to draw an alternating /// triangle strip of the requested size /// /// /// Number of segments the strip should have on the X axis /// /// /// Number of segments the strip should have on the Y axis /// /// The number of indices required for the strip public static int CountAlternatingStripIndices(int segmentsX, int segmentsZ) { int indicesPerRow = (segmentsX + 1) * 2 - 1; return segmentsZ * indicesPerRow + 1; } /// /// Builds the index buffer for a grid of vertices drawn as a triangle strip /// /// Number of horizontal subdivisions in the plane /// Number of vertical subdivisions in the plane /// /// /// This method builds indices to draw a grid of vertices with alternating /// split diagonals for each line of quads. /// /// /// k-l-m-n-o /// |/|/|/|/| /// f-g-h-i-j /// |\|\|\|\| /// a-b-c-d-e /// |/|/|/|/| /// 5-6-7-8-9 /// |\|\|\|\| /// 0-1-2-3-4 /// /// /// Rows are drawn alternating diretion between left to right and /// right to left. Only a single, small degenerate triangle is required /// between two rows to move into the next row, resulting in (segmentsZ - 1) /// degenerate triangles for the whole grid. /// /// /// This method is ideal for graphics cards with a limited vertex cache /// because it only requires space for (segmentsX + 1) vertices in /// the vertex cache to reach optimum caching performance. /// /// public static short[] BuildAlternatingStrip(int segmentsX, int segmentsZ) { if(segmentsX < 1) { throw new ArgumentException("Too few segments in X direction", "segmentsX"); } if(segmentsZ < 1) { throw new ArgumentException("Too few segments in Z direction", "segmentsX"); } // Calculate the total number of indices we'll have int totalIndices = CountAlternatingStripIndices(segmentsX, segmentsZ); // Number of vertices in one row int verticesX = segmentsX + 1; // Set up the index array short[] indices = new short[totalIndices]; int indicesIndex = 1; // Current index in the vertex index array :) // This is how the indices will be generated: // // x 0 1 2 3 // // k l m n o // |/|/|/|/| // backwards f g h i j f g h i // |\|\|\|\| // forwards a b c d e b c d e backwards // |/|/|/|/| // 5 6 7 8 9 5 6 7 8 forwards // |\|\|\|\| // 0 1 2 3 4 // for(int row = 0; row < segmentsZ; ++row) { bool evenRow = ((row & 1) == 0); // Even row: Build sawtooths from left to right if(evenRow) { int rowStartIndex = row * verticesX + 1; int rowEndIndex = rowStartIndex + segmentsX; for(int index = rowStartIndex; index < rowEndIndex; ++index) { indices[indicesIndex++] = (short)(index + segmentsX); indices[indicesIndex++] = (short)(index); } indices[indicesIndex++] = (short)(rowEndIndex + segmentsX); } else { // Odd row: Build sawtooths from right to left int rowEndIndex = row * verticesX + verticesX; int rowStartIndex = rowEndIndex + segmentsX; for(int index = rowStartIndex; index > rowEndIndex; --index) { indices[indicesIndex++] = (short)(index); indices[indicesIndex++] = (short)(index - verticesX - 1); } indices[indicesIndex++] = (short)(rowEndIndex); } } return indices; } } } // namespace Nuclex.Graphics.SpecialEffects