Cамоучитель по Visual Studio.Net

       

Формирование массива вершин и индексов



Формирование массива вершин и индексов

Самой сложной задачей является правильное вычисление координат всех вершин треугольников и формирование массива индексов Tria, с помощью которого команда glDrawElements обходит массив Vert при задании треугольников. Функция Sphere реализует алгоритм последовательного обхода сначала всех сферических треугольников вокруг полюсов сферы, а затем обхода сферических четырехугольников, образованных пересечением параллелей и меридианов. В процессе обхода формируется массив вершин vert. После этого обходы повторяются для того, чтобы заполнить массив индексов Tria. Северный и южный полюса обрабатываются индивидуально. Для осуществления обхода предварительно создаются константы:

  • da — шаг изменения сферического угла а (широта),
  • db — шаг изменения сферического угла b (долгота),
  • af и bf — конечные значения углов.

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

  • После обработки северного и южного полюсов мы движемся вдоль первой широты (a=da) от востока к западу по невидимой части полусферы и возвращаемся назад по видимой ее части. Затем происходит переход на следующую широту (а += da) и цикл повторяется.


  • Координаты вершин (х, z) представляют собой проекции точек на экваториальную плоскость, а координата у постоянна для каждой широты.
  • При обработке одной секции кольца для двух треугольников формируется по три индекса:

void Sphere(VERT *v, TRIA* t)

{

//====== Формирование массива вершин

//====== Северный полюс

v[0].v = CPointSD (0, gRad, 0);

v[0].n = CPoint3D (0, 1, 0);

v[0].с = gClr2;

//====== Индекс последней вершины (на южном полюсе)

UINT last = gnVert - 1; //====== Южный полюс

v[last].v = CPointSD (0, -gRad, 0);

v[last].n = CPointSD (0, -1, 0) ;

v[last].c = gnVert & 1 ? gClr2 : gClrl;

//====== Подготовка констант

double da = PI / (gnRings +2.),

db = 2. * PI / gnSects,

af = PI - da/2.;

bf = 2. * PI - db/2.;

//=== Индекс вершины, следующей за северным полюсом

UINT n = 1;

//=== Цикл по широтам

for (double a = da; a < af; a += da)

{

//=== Координата у постоянна для всего кольца

double у = gRad * cos(a),

//====== Вспомогательная точка

xz = gRad * sin(a);

//====== Цикл по секциям (долгота)

for (double b = 0.; b < bf; n++, b += db)

}

// Координаты проекции в экваториальной плоскости

double х = xz * sin(b), z = xz * cos(b);

//====== Вершина, нормаль и цвет

v[n].v = CPointSD (x, у, z);

v[n].n = CPointSD (x / gRad, у / gRad, z / gRad);

v[n].c = n & 1 ? gClrl : gClr2; } }

//====== Формирование массива индексов

//====== Треугольники вблизи полюсов

for (n = 0; n < gnSects; n++)

{

//====== Индекс общей вершины (северный полюс)

t[n] .11 = 0;

//====== Индекс текущей вершины

t[n] .12 = n + 1;

//====== Замыкание

t[n].13 = n == gnSects - 1 ? 1 : n + 2;

//====== Индекс общей вершины (южный полюс)

t [gnTria-gnSects+n] .11 = gnVert - 1;

t tgnTria-gnSects+n] . 12 = gnVert - 2 - n;

t [gnTria-gnSects+n] .13 = gnVert - 2

t ( (1 + n) % gnSects) ;

}

//====== Треугольники разбиения колец

//====== Вершина, следующая за полюсом

int k = 1;

//====== gnSects - номер следующего треугольника

S' n = gnSects;

for (UINT i = 0; i < gnRings; i++, k += gnSects) {

for (UINT j = 0; j < gnSects; j++, n += 2) {

//======= Индекс общей вершины

t[n] .11 = k + j;

//======= Индекс текущей вершины

t[n].12 = k + gnSects + j;

//======= Замыкание

t[n].13 = k + gnSects + ((j + 1) % gnSects)

//======= To же для второго треугольника

t[n + 1].11 = t[n].11;

t[n + 1].12 = t[n].13;

t[n + 1].13 = k + ((j + 1) % gnSects);

Для завершения работы осталось дополнить программу стандартным набором процедур, алгоритм функционирования которых вы уже изучили:

void_stdcall OnSize(GLsizei w, GLsizei h) { glViewport(0, 0, w, h);

}

void main ()

{

auxInitDisplayMode(AUX_RGB | AUX_DOUBLE) ;

auxInitPositiondO, 10, 512, 512);

auxInitwindow("Vertex Array");

Init() ;

auxReshapeFunc (OnSize) ;

auxIdleFunc (OnDraw) ;

auxMainLoop (OnDraw) ;

}

Запустите проект на выполнение и уберите возможные неполадки. Исследуйте функционирование программы, вводя различные значения глобальных параметров (регулировок). Попробуйте задать нечетное число секций. Объясните результат. В качестве упражнения введите возможность интерактивного управления степенью дискретизации сферы и исследуйте эффективность работы конвейера при ее увеличении.



Содержание раздела