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

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

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

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

У меня проблема вот с этим: gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);. Вылезает ошибка: CS1061 "object" не содержит определения "GL_COLOR_BUFFER_BIT", и не удалось найти доступный метод расширения "GL_COLOR_BUFFER_BIT",...
Большое спасибо. Единственный код который прошел без каких либо ошибок. Ура!!!
Скажите пожалуйста, подскажите алгоритм по которому по заданным точкам можно определить тип многогранника, скажем это куб или прямоугольный параллелепипед. Нашел теорию по этим фигурам: https://www.mat... https://www.mat... Акцентировать внимание...
Всем у кого не работает. файл wizard.script Ещё одно упоминание Glut32 в строке "if (!VerifyLibFile(dir_nomacro_lib, _T("glut32"), _T("GLUT's"))) return false;" меняем на "if (!VerifyLibFile(dir_nomacro_lib, _T("freeglut"), _T("GLUT's"))) return...
Не получается, емаё

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

Рейтинг@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 Мб