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

Вход на сайт

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

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

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

Здравствуйте. Спасибо за проект. У меня вопрос, по какой причине определение принадлежности точки многоугольнику работает некорректно, если координаты из больших чисел состоят, например: int[] vertex = new int[] {...
Сейчас проверила нашла причину не запускания // Создание контекста воспроизведения OpenGL и привязка его к панели на форме OpenGLControl1:=TOpenGLControl.Create(Self); with OpenGLControl1 do begin Name:='OpenGLControl1'; //вот тут...
Ну..кажется что то пошло не так http://pp.usera...
Пример, к которому вы оставили комментарий строит именно то самое изображение на языке с#, которое вам необходимо. Отличается только цветовая палитра.

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

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