В предыдущей главе я рассказывал о том, как можно упростить определение нескольких треугольников методом индексов . В этой главе, мы создадим небольшую поверхность из треугольников. Небольшой она будет для наглядности, но на деле она будет поддерживать динамическое расширение, что позволит сделать ее намного больше.

Для начала зададим размеры поверхности:

1
2
  private int WIDTH = 4 ;
  private int HEIGHT = 3 ;

Третью координату – высоту, мы зададим, как массив высот:

1
  private int [ , ] heightData ;

Также нам необходим метод для определения карты высот:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  private void LoadHeightData ( )
  {
      heightData = new int [ WIDTH , HEIGHT ] ;
      heightData [ 0 , 0 ] = 0 ;
      heightData [ 1 , 0 ] = 0 ;
      heightData [ 2 , 0 ] = 0 ;
      heightData [ 3 , 0 ] = 0 ;
      heightData [ 0 , 1 ] = 1 ;
      heightData [ 1 , 1 ] = 0 ;
      heightData [ 2 , 1 ] = 2 ;
      heightData [ 3 , 1 ] = 2 ;
      heightData [ 0 , 2 ] = 2 ;
      heightData [ 1 , 2 ] = 2 ;
      heightData [ 2 , 2 ] = 4 ;
      heightData [ 3 , 2 ] = 2 ;
  }

Этот метод должен выполняться единожды при запуске программы. Для создания подобной карты поверхности, нам необходимо задать 12 вершин (WIDTH*HEIGHT). Изменим метод VertexDeclaration так, чтобы осуществить это:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  private void VertexDeclaration ( )
  {
      vb = new VertexBuffer ( typeof ( CustomVertex . PositionColored ) , WIDTH* HEIGHT , device , Usage . Dynamic | Usage . WriteOnly , CustomVertex . PositionColored . Format , Pool . Default ) ;
      vertices = new CustomVertex . PositionColored [ WIDTH* HEIGHT ] ;
     for ( int x = 0 ; x < WIDTH ; x ++ )
{
         for ( int y = 0 ; y < HEIGHT ; y ++ )
         {
             vertices [ x + y* WIDTH ] . Position = new Vector3 ( x , y , 0 ) ;
             vertices [ x + y* WIDTH ] . Color = Color . White . ToArgb ( ) ;
         }
     }
     vb . SetData ( vertices , 0 , LockFlags . None ) ;
}

На данный момент мы не используем карту высот: определяем 12 точек и делаем их белыми. Дальнейшие действия менее очевидны: нам нужно создать треугольники на базе 12 вершин с помощью метода индексов.

Изменим метод IndicesDeclaration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void IndicesDeclaration ( )
{
ib = new IndexBuffer ( typeof ( int ) , ( WIDTH - 1 ) * ( HEIGHT - 1 ) * 6 , device , Usage . WriteOnly , Pool . Default ) ;
indices = new int [ ( WIDTH - 1 ) * ( HEIGHT - 1 ) * 6 ] ;
for ( int x = 0 ; x < WIDTH - 1 ; x ++ ) {
for ( int y = 0 ; y < HEIGHT - 1 ; y ++ ) {
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 ] = ( x + 1 ) + ( y + 1 ) * WIDTH ;
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 + 1 ] = ( x + 1 ) + y* WIDTH ;
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 + 2 ] = x + y* WIDTH ;
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 + 3 ] = ( x + 1 ) + ( y + 1 ) * WIDTH ;
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 + 4 ] = x + y* WIDTH ;
indices [ ( x + y* ( WIDTH - 1 ) ) * 6 + 5 ] = x + ( y + 1 ) * WIDTH ;
}
}
ib . SetData ( indices , 0 , LockFlags . None ) ;
}

Единственное, что осталось – немного изменить код OnPaint метода:

1
2
3
4
5
6
7
device . BeginScene ( ) ;
device . VertexFormat = CustomVertex . PositionColored . Format ;
device . SetStreamSource ( 0 , vb , 0 ) ;
device . Indices = ib ;
device . DrawIndexedPrimitives ( PrimitiveType . TriangleList , 0 , 0 , WIDTH* HEIGHT , 0 , indices . Length / 3 ) ;
device . EndScene ( ) ;

Установите камеру в (0,0,15) и запустите программу. Вы должны увидеть вашу поверхность. Однако пока она не имеет высоты. Добавьте ее с помощью этой строки:

1
vertices [ x + y* WIDTH ] . Position = new Vector3 ( x , y , heightData [ x , y ] ) ;