11.2 Библиотека GLUT - создание примитивов, трансформация, перенос и масштабирование объектов в OpenGL.

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

Перед визуализацией примитива будут выполняться функции переноса, поворота и масштабирования – данные функции будут ориентироваться на состояние ранее объявленных переменных. Данные переменные, в свою очередь, обновляются при перетаскивании ползунков, нажатии на checkBox или изменении элементов comboBox.

Объявление начальных переменных и инициализация OpenGL выглядит следующим образом:

/*http://esate.ru, Anvi*/

// вспомогательные переменные - в них будут храниться обработанные значения, 
// полученные при перетаскивании ползунков пользователем 
double a = 0, b = 0, c = -5, d = 0, zoom = 1; // выбранные оси 
int os_x = 1, os_y = 0, os_z = 0;

// режим сеточной визуализации 
bool Wire = false ;

private void Form1_Load( object sender, EventArgs e)
{

  // инициализация библиотеки glut 
  Glut.glutInit();
  // инициализация режима экрана 
  Glut.glutInitDisplayMode( Glut.GLUT_RGB | Glut.GLUT_DOUBLE);

  // установка цвета очистки экрана (RGBA) 
  Gl.glClearColor(255, 255, 255, 1);

  // установка порта вывода 
  Gl.glViewport(0, 0, AnT.Width, AnT.Height);

  // активация проекционной матрицы 
  Gl.glMatrixMode( Gl.GL_PROJECTION);
  // очистка матрицы 
  Gl.glLoadIdentity();

  // установка перспективы 
  Glu.gluPerspective(45, (float)AnT.Width / (float)AnT.Height, 0.1, 200);

  Gl.glMatrixMode( Gl.GL_MODELVIEW);
  Gl.glLoadIdentity();

  // начальная настройка параметров openGL (тест глубины, освещение и первый источник света) 
  Gl.glEnable( Gl.GL_DEPTH_TEST);
  Gl.glEnable( Gl.GL_LIGHTING);
  Gl.glEnable( Gl.GL_LIGHT0);

  // установка первых элементов в списках combobox 
  comboBox1.SelectedIndex = 0;
  comboBox2.SelectedIndex = 0;

  // активация таймера, вызывающего функцию для визуализации 
  RenderTimer.Start();

}


Вы должны добавить обработку событий изменения элементов trackBar, событие отклика таймера и обработку изменения значений элементов checkbox и comboBox.

/*http://esate.ru, Anvi*/

// обрабатываем отклик таймера 
private void RenderTimer_Tick( object sender, EventArgs e)
{
  // вызываем функцию отрисовки сцены 
  Draw();
}

// событие изменения значения 
private void trackBar1_Scroll( object sender, EventArgs e)
{ 
  // переводим значение, установившееся в элементе trackBar в необходимый нам формат 
  a = (double)trackBar1.Value / 1000.0;
  // подписываем это значение в label элементе под данным ползунком 
  label4.Text = a.ToString();
}

// событие изменения значения 
private void trackBar2_Scroll( object sender, EventArgs e)
{ 
  // переводим значение, установившееся в элементе trackBar в необходимый нам формат 
  b = (double)trackBar2.Value / 1000.0;
  // подписываем это значение в label элементе под данным ползунком 
  label5.Text = b.ToString();
}

// событие изменения значения 
private void trackBar3_Scroll( object sender, EventArgs e)
{ 
  // переводим значение, установившееся в элементе trackBar в необходимый нам формат 
  c = (double)trackBar3.Value / 1000.0;
  // подписываем это значение в label элементе под данным ползунком 
  label6.Text = c.ToString();
}

// событие изменения значения 
private void trackBar4_Scroll( object sender, EventArgs e)
{ 
  // переводим значение, установившееся в элементе trackBar в необходимый нам формат 
  d = (double)trackBar4.Value;
  // подписываем это значение в label элементе под данным ползунком 
  label6.Text = d.ToString();
}

// событие изменения значения 
private void trackBar5_Scroll( object sender, EventArgs e)
{ 
  // переводим значение, установившееся в элементе trackBar в необходимый нам формат 
  zoom = (double)trackBar5.Value / 1000.0;
  // подписываем это значение в label элементе под данным ползунком 
  label6.Text = zoom.ToString();
}

// изменения значения чекбокса 
private void checkBox1_CheckedChanged( object sender, EventArgs e)
{ 
  // если отмечен 
  if (checkBox1.Checked)
  { 
    // устанавливаем сеточный режим визуализации 
    Wire = true;
  }
  else
  { 
    // иначе - полигональная визуализация 
    Wire = false;
  }
}

// изменение в элементах comboBox 
private void comboBox1_SelectedIndexChanged( object sender, EventArgs e)
{ 
  // в зависимости от выбранного режима 
  switch (comboBox1.SelectedIndex)
  { 
    // устанавливаем необходимую ось (будет использована в функции glRotate**) 
    case 0:
    { 
      os_x = 1;
      os_y = 0;
      os_z = 0;
      break;
    }
    case 1:
    { 
      os_x = 0;
      os_y = 1;
      os_z = 0;
      break;
    }
    case 2:
    { 
      os_x = 0;
      os_y = 0;
      os_z = 1;
      break;
    }
  }
}



Ну и собственно функция отрисовки сцены. Обратите внимание на то, что перед использованием трансформации обязательно необходимо поместить состояние текущей матрицы в стек матриц, чтобы дальнейшие преобразования затронули только визуализируемые объекты.

/*http://esate.ru, Anvi*/

// функция отрисовки 
private void Draw()
{

  // очистка буфера цвета и буфера глубины 
  Gl.glClear( Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);

  Gl.glClearColor(255, 255, 255, 1);
  // очищение текущей матрицы 
  Gl.glLoadIdentity();

  // помещаем состояние матрицы в стек матриц, дальнейшие трансформации затронут только визуализацию объекта 
  Gl.glPushMatrix();
  // производим перемещение в зависимости от значений, полученных при перемещении ползунков 
  Gl.glTranslated(a, b, c);
  // поворот по установленной оси 
  Gl.glRotated(d, os_x, os_y, os_z);
  // и масштабирование объекта 
  Gl.glScaled(zoom, zoom, zoom);

  // в зависимости от установленного типа объекта 
  switch (comboBox2.SelectedIndex)
  { 
    // рисуем нужный объект, используя функции библиотеки GLUT 
    case 0:
    { 
      if(Wire) // если установлен сеточный режим визуализации 
        Glut.glutWireSphere(2, 16, 16); // сеточная сфера 
      else
        Glut.glutSolidSphere(2, 16, 16); // полигональная сфера 
      break ;
    }
    case 1:
    { 
      if(Wire) // если установлен сеточный режим визуализации 
        Glut.glutWireCylinder(1, 2, 32, 32); // цилиндр 
      else
        Glut.glutSolidCylinder(1, 2, 32, 32);
      break;
    }
    case 2:
    { 
      if(Wire) // если установлен сеточный режим визуализации 
        Glut.glutWireCube(2); // куб 
      else
        Glut.glutSolidCube(2);
      break;
    }
    case 3:
    { 
      if (Wire) // если установлен сеточный режим визуализации 
        Glut.glutWireCone(2, 3, 32, 32); // конус 
      else
        Glut.glutSolidCone(2, 3, 32, 32);
      break;
    }
    case 4:
    { 
      if (Wire) // если установлен сеточный режим визуализации 
        Glut.glutWireTorus(0.2, 2.2, 32, 32); // тор 
      else
        Glut.glutSolidTorus(0.2, 2.2, 32, 32);
      break;
    }
  }

  // возвращаем состояние матрицы 
  Gl.glPopMatrix();

  // завершаем рисование 
  Gl.glFlush();

  // обновляем элемент AnT 
  AnT.Invalidate();

}


Примеры работы программы:
Уроки OpenGL + C#: Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT Рисунок 1. Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT.
Уроки OpenGL + C#: Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT Рисунок 2. Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT.

Нет доступа к просмотру комментариев.

^