Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

dobryj den, popytalas otkryt prikreplionnyj fail ctoby posmotret kak rabotaet, no mne ego ne pokazyvaet vydajet osibku. Pochemu?
Очень интересно! ии сайт крутой жалко что умирает(
У Вас число превысит максимальное число int. Можно использовать в Вашем случае uint, но лучше все переписать на double.
Добавление к программе строки glutReshapeFunc(changeSize); приводит к тому, что треугольник перестаёт совсем отрисовываться.
Выдаёт ошибку glut32.dll не найден! При том, что он лежит в System32! Всё решил) Нужно отправить не в System32, а в System.

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Среда программирования: 
Microsoft C#

В данной программе будет представлен пример, как работать с объёмными фигурами в
OpenGL на языке C#, где в итоге мы изобразим простой дом в 3-ёх мерном виде.

При построении фигур с подключением OpenGL важно помнить, что система координат отличается от декартовой системы координат и базисные вектора имеют следующие направления (по умолчанию)

При этом задание координат для точек имеет привычный нам вид
(X, Y, Z)

1. Начало работы:
В данной программе мы используем плагин SharpGL, который помимо поддержки OpenGL включает в себя создание шаблона с основными функциями при создании нового проекта, такие как:

public SharpGLForm(){}
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e){}
private void openGLControl_OpenGLInitialized(object sender, EventArgs e){}
private void openGLControl_Resized(object sender, EventArgs e){}

Как подключить SharpGL, смотрите здесь: http://grafika.me/node/365

2. Преобразование картинки к трёхмерному виду:
Для этого используется функция openGLControl_Resized(). В ней происходят наши преобразования координат для создания объёмного изображения:

private void openGLControl_Resized(object sender, EventArgs e)
        {
            //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Зададим матрицу проекции
            gl.MatrixMode(OpenGL.GL_PROJECTION);
 
            //  Единичная матрица для последующих преобразований
            gl.LoadIdentity();
 
            //  Преобразование
            gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);
 
            //  Данная функция позволяет установить камеру и её положение
            gl.LookAt( -5, 3, -6,    // Позиция самой камеры (x, y, z)
                        0, 1, 0,     // Направление, куда мы смотрим
                        0, 2, 0);    // Верх камеры
 
            //  Зададим модель отображения
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }

3. Установка цвета фоновой заливки:
Для этого используется функция openGLControl_OpenGLInitialized(), в которой помимо фоновой заливки можно задать ряд других значения по умолчанию:

private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
        {
           //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Устанавливаем цвет заливки по умолчанию (в данном случае цвет голубой)
            gl.ClearColor(0.1f, 0.5f, 1.0f, 0);
        }

4. Нарисуем крышу дома
Для начала нарисуем треугольник и посмотрим на него.

private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
        {
            //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Очищаем буфер цвета и глубины
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
 
            gl.Begin(OpenGL.GL_TRIANGLES); // задаём какую фигуру будем рисовать
 
            gl.Color(1f, 0.2f, 0.0f); // здесь задаём цвет (для всех последующих элементов);
            // при повторном вызове Color() мы зададим цвет для последующих фигур;
            // иначе цвет будет одинаковым для всех фигур, до вызова следующей функции Color()
            gl.Vertex(0.0f, 2.5f, 0.0f); // здесь задаём координаты точек
            gl.Vertex(2.0f, 1.5f, -2.0f);
            gl.Vertex(2.0f, 1.5f, 2.0f);
 
            gl.End();
        }  

Получим следующую картинку (параметры для gl.LookAt(5, 4, 0, 0, 1, 0, 0, 1, 0)):


*Далее координаты фигур и изменение градуса поворота будут указываться в функции openGLControl_OpenGLDraw(), изменения gl.LookAt() производятся в функции openGLControl_Resized()*

Теперь дорисуем остальные стороны нашей "крыши" и посмотрим с другого ракурса. Получился следующий код:

            gl.Begin(OpenGL.GL_TRIANGLES);
 
            gl.Color(1f, 0.2f, 0.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(2.0f, 1.5f, -2.0f);
            gl.Vertex(2.0f, 1.5f, 2.0f);
 
            gl.Color(1f, 0.3f, 0.0f);
            gl.Vertex(-2.0f, 1.5f, -2.0f);
            gl.Vertex(-2.0f, 1.5f, 2.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
 
            gl.Color(1f, 0.4f, 0.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(2.0f, 1.5f, -2.0f);
            gl.Vertex(-2.0f, 1.5f, -2.0f);
 
            gl.Color(1f, 0.1f, 0.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(-2.0f, 1.5f, 2.0f);
            gl.Vertex(2.0f, 1.5f, 2.0f);
 
            gl.End();

gl.LookAt(5, 8, 0, 0, 1, 0, 0, 1, 0);
Получаем следующее изображение нашей крыши:

5. Рисуем стены и землю используя полигоны
Добавим следующий элемент кода после треугольника, который нарисует стену:

            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.8f, 0f);
            gl.Vertex(2f, 0f, -2f);
            gl.Vertex(2f, 0f, 2f);
            gl.Vertex(2f, 1.5f, 2f);
            gl.Vertex(2f, 1.5f, -2f);
            gl.End();

gl.LookAt(5, 6, 0, 0, 1, 0, 0, 1, 0);
Получаем следующее изображение:

gl.LookAt(5, 6, 4, 0, 1, 0, 0, 1, 0);

Как мы видим, на данный момент у нас всего одна стена, поэтому дорисуем остальные стены и добавим двери на самую светлую сторону. Полигоны всех четырёх стен имеют следующие координаты и цвета:
            // передняя часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 1f, 0f);
            gl.Vertex(2f, 1.5f, -2f);
            gl.Vertex(2f, 0f, -2f);
            gl.Vertex(-2f, 0f, -2f);
            gl.Vertex(-2f, 1.5f, -2f);
 
            gl.End();
 
            // правая часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.8f, 0f);
            gl.Vertex(2f, 0f, -2f);
            gl.Vertex(2f, 0f, 2f);
            gl.Vertex(2f, 1.5f, 2f);
            gl.Vertex(2f, 1.5f, -2f);
            gl.End();
 
            // задняя часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.7f, 0f);
            gl.Vertex(2f, 0f, 2f);
            gl.Vertex(-2f, 0f, 2f);
            gl.Vertex(-2f, 1.5f, 2f);
            gl.Vertex(2f, 1.5f, 2f);
            gl.End();
 
            // левая часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.9f, 0f);
            gl.Vertex(-2f, 0f, -2f);
            gl.Vertex(-2f, 0f, 2f);
            gl.Vertex(-2f, 1.5f, 2f);
            gl.Vertex(-2f, 1.5f, -2f);
            gl.End();
 
            // дверь (передняя стена)
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.5f, 0f);
            gl.Vertex(0.3f, 0f, -2.01f);
            gl.Vertex(-0.3f, 0f, -2.01f);
            gl.Vertex(-0.3f, 1.2f, -2.01f);
            gl.Vertex(0.3f, 1.2f, -2.01f);
            gl.End();

gl.LookAt(5, 6, 4, 0, 1, 0, 0, 1, 0);

gl.LookAt(5, 6, -7, 0, 1, 0, 0, 1, 0);

Нарисуем землю с помощью полигона:
            // рисуем землю            
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(0f, 1f, 0f);
            gl.Vertex(-10f, 0f, -10f);
            gl.Vertex(10f, 0f, -10f);
            gl.Vertex(10f, 0f, 10f);
            gl.Vertex(-10f, 0f, 10f);
            gl.End();

gl.LookAt(5, 6, -7, 0, 1, 0, 0, 1, 0);

6. Вращение вокруг заданной оси
Перед функцией public SharpGLForm() инициализируем переменную rotation (угол поворота).

        float rotation = 0.0f;
        public SharpGLForm()
        {
            InitializeComponent();
        }

Затем добавим (в openGLControl_OpenGLDraw()) функцию поворота и укажем ось, вокруг которой нам нужно вращать картинку. После написания кода, укажем насколько градусов разворачивать изображение за 1 кадр.
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
 
            //  Загружаем единичную матрицу
            gl.LoadIdentity();
 
            //  Указываем оси вращения (x, y, z)
            gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
            //---- Код -----
            rotation += 1.5f;

Запускаем и получаем следующее изображение:


 

В итоге мы получили код, который целиком выглядит следующим образом:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpGL;
 
namespace OpenGL_lesson_CSharp
{
    public partial class SharpGLForm : Form
    {
        float rotation = 0.0f; // переменная, которая будет задавать угол поворота
 
        public SharpGLForm()
        {
            InitializeComponent();
        }
 
        // Функция, которая используется для рисования нашего объекта
        private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
        {
           //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Очищаем буфер цвета и глубины
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
 
            //  Загружаем единичную матрицу
            gl.LoadIdentity();
 
            //  Указываем оси вращения (x, y, z)
            gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
 
            // рисуем крышу
            gl.Begin(OpenGL.GL_TRIANGLES);
 
            gl.Color(1f, 0.2f, 0.0f); // здесь задаём цвет для каждой плоскости
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(2.0f, 1.5f, -2.0f);
            gl.Vertex(2.0f, 1.5f, 2.0f);
 
            gl.Color(1f, 0.3f, 0.0f);
            gl.Vertex(-2.0f, 1.5f, -2.0f);
            gl.Vertex(-2.0f, 1.5f, 2.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
 
            gl.Color(1f, 0.4f, 0.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(2.0f, 1.5f, -2.0f);
            gl.Vertex(-2.0f, 1.5f, -2.0f);
 
            gl.Color(1f, 0.1f, 0.0f);
            gl.Vertex(0.0f, 2.5f, 0.0f);
            gl.Vertex(-2.0f, 1.5f, 2.0f);
            gl.Vertex(2.0f, 1.5f, 2.0f);
 
            gl.End();
 
            // передняя часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 1f, 0f);
            gl.Vertex(2f, 1.5f, -2f);
            gl.Vertex(2f, 0f, -2f);
            gl.Vertex(-2f, 0f, -2f);
            gl.Vertex(-2f, 1.5f, -2f);
 
            gl.End();
 
            // правая часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.8f, 0f);
            gl.Vertex(2f, 0f, -2f);
            gl.Vertex(2f, 0f, 2f);
            gl.Vertex(2f, 1.5f, 2f);
            gl.Vertex(2f, 1.5f, -2f);
            gl.End();
 
            // задняя часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.7f, 0f);
            gl.Vertex(2f, 0f, 2f);
            gl.Vertex(-2f, 0f, 2f);
            gl.Vertex(-2f, 1.5f, 2f);
            gl.Vertex(2f, 1.5f, 2f);
            gl.End();
 
            // левая часть дома
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.9f, 0f);
            gl.Vertex(-2f, 0f, -2f);
            gl.Vertex(-2f, 0f, 2f);
            gl.Vertex(-2f, 1.5f, 2f);
            gl.Vertex(-2f, 1.5f, -2f);
            gl.End();
 
            // дверь (передняя стена)
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(1f, 0.5f, 0f);
            gl.Vertex(0.3f, 0f, -2.01f);
            gl.Vertex(-0.3f, 0f, -2.01f);
            gl.Vertex(-0.3f, 1.2f, -2.01f);
            gl.Vertex(0.3f, 1.2f, -2.01f);
            gl.End();
 
            // рисуем землю            
            gl.Begin(OpenGL.GL_POLYGON);
            gl.Color(0f, 1f, 0f);
            gl.Vertex(-10f, 0f, -10f);
            gl.Vertex(10f, 0f, -10f);
            gl.Vertex(10f, 0f, 10f);
            gl.Vertex(-10f, 0f, 10f);
            gl.End();
 
            rotation += 1.5f; // угол разворота за 1 кадр
        }
 
        // Эту функцию используем для задания некоторых значений по умолчанию
        private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
        {
           //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Фоновый цвет по умолчанию (в данном случае цвет голубой)
            gl.ClearColor(0.1f, 0.5f, 1.0f, 0);
        }
 
        // Данная функция используется для преобразования изображения 
        // в объёмный вид с перспективой
        private void openGLControl_Resized(object sender, EventArgs e)
        {
            //  Возьмём OpenGL объект
            OpenGL gl = openGLControl.OpenGL;
 
            //  Зададим матрицу проекции
            gl.MatrixMode(OpenGL.GL_PROJECTION);
 
            //  Единичная матрица для последующих преобразований
            gl.LoadIdentity();
 
            //  Преобразование
            gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);
 
            //  Данная функция позволяет установить камеру и её положение
            gl.LookAt( -5, 3, -6,    // Позиция самой камеры (x, y, z)
                        0, 1, 0,     // Направление, куда мы смотрим
                        0, 2, 0);    // Верх камеры
 
            //  Зададим модель отображения
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }
    }
}

Прикрепленный файлРазмер
Duma_OpenGL_lesson_CSharp.rar1.11 Мб