Добрый вечер, Хабр!

Сегодня я Вам продемонстрирую API правда устаревший(версии 1.0), для отрисовки растительного листика. В программе используется библиотека OpenGL и язык С++. Думаю что не стану перегружать Вас кодом который создает окно и контекст, будет лишь так сказать самая "вкуснятина" в виде разбора кода. Немного предыстории. Больше 10 лет назад я написал программу плеер для Windows и в нем помимо списка музыки и кнопок управления, были еще 3D объекты которые вращались - ну как бы под музыку ничего особенного. Я тогда только изучал это все и вот беда - код не сохранился. Осталась лишь одна программа и сейчас буквально за час, я попытался реверс-инжинирингом восстановить один из 3D объектов. Я конечно не помню как я его делал столько времени прошло, но я помню идею которой руководствовался - это зеркальное отображение и масштабирование части изображения чтобы получить симметричный объект. Перейдем к коду:

void MyWidget::HalfList()//пол-листика точнее пол ответвления
{
	glColor3f(0.0, 0.5, 0.0);//задаем цвет
	glBegin(GL_QUADS);//рисуем квадратами
	for (float i = -0.8; i < 0.8; i += 0.1)//в цикле пробегаем и рисуем праллелограммы
	{
		glVertex3f(0, i, 0);
		glVertex3f(0.1, i + 0.1, 0);
		glVertex3f(0.1, i + 0.2, 0);
		glVertex3f(0, i + 0.1, 0);
	}
	glEnd();
	glBegin(GL_TRIANGLES);//рисуем треугольниками
	glVertex3f(0, 0.8, 0);//рисуем кончик листика
	glVertex3f(0.1, 0.9, 0);
	glVertex3f(0, 1.0, 0);
	glEnd();
	glColor3f(0, 1.0, 0);//задаем цвет для скелета
	glLineWidth((GLfloat)1);//задаем толщину линий
	glBegin(GL_LINES);//рисуем линиями
	glVertex3f(0, -0.8, -0.01);//вертикальная линия
	glVertex3f(0, 1, -0.01);
	glVertex3f(0, -0.8, 0.01);
	glVertex3f(0, 1, 0.01);
	glEnd();
	glBegin(GL_LINES);//рисуем линиями
	for (float i = -0.8; i < 0.9; i += 0.1)
	{
		glVertex3f(0, i, -0.01);//рисуем скелет листика
		glVertex3f(0.11, i + 0.1, -0.01);
		glVertex3f(0, i, 0.01);
		glVertex3f(0.11, i + 0.1, 0.01);
	}
	glEnd();
}

void MyWidget::FullList()
{
	HalfList();//рисуем пол-ответвления
	glPushMatrix();
	glRotatef(180, 0, 1, 0);//поворачиваем сцену на 180 градусов вокруг оси игрек
	HalfList();//дорисовываем вторую половину пол-ответвления
	glPopMatrix();
}
void MyWidget::Show()//рисуем целый лист
{
	glPushMatrix();
	glScalef(0.7, 0.7, 1);//масштабируем весь объект
	glColor3f(0.0, 0.5, 0.0);
	glBegin(GL_TRIANGLES);//рисуем треугольниками
	glVertex3f(0,-0.8,0);//рисуем хвостик листика
	glVertex3f(-0.01,-1,0);
	glVertex3f(0.01, -1, 0);
	glEnd();
	FullList();//вертикальная часть листа
	glPushMatrix();
	glTranslatef(-0.2, -0.45, 0);
	glRotatef(30, 0, 0, 1);
	glScalef(0.6, 0.6, 1);
	FullList();//часть листа повернутая на 30 градусов
	glPopMatrix();
	glPushMatrix();
	glTranslatef(0.2,-0.45, 0);
	glRotatef(-30, 0, 0, 1);
	glScalef(0.6, 0.6, 1);
	FullList();//часть листа повернутая на -30 градусов
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-0.3, -0.7, 0);
	glRotatef(60, 0, 0, 1);
	glScalef(0.4, 0.4, 1);
	FullList();//часть листа повернутая на 60 градусов
	glPopMatrix();
	glPushMatrix();
	glTranslatef(0.3, -0.7, 0);
	glRotatef(-60, 0, 0, 1);//часть листа повернутая на -60 градусов
	glScalef(0.4, 0.4, 1);
	FullList();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-0.15, -0.9, 0);
	glRotatef(100, 0, 0, 1);
	glScalef(0.2, 0.2, 1);
	FullList();//часть листа повернутая на 100 градусов
	glPopMatrix();
	glPushMatrix();
	glTranslatef(0.15, -0.9, 0);
	glRotatef(-100, 0, 0, 1);//часть листа повернутая на -100 градусов
	glScalef(0.2, 0.2, 1);
	FullList();
	glPopMatrix();
	glPopMatrix();
}
void MyWidget::paintGL() // рисование
{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		Show();
}

Собственно что такое пол-ответвления:

Я конечно не ботаник не знаю как эту часть назвать.

Вот скелет его и c кончиком и хвостиком:

Собственно дальше с помощью поворота масштабирования и параллельного переноса получается так

Здесь градусы вместо процентов.

Итоговый объект:

Ну и всё!

Не унывайте.

Комментарии (13)


  1. nin-jin
    05.02.2023 17:39
    +1

    Я конечно не ботаник не знаю как эту часть назвать.

    Это называется лента. И ленты проще рисовать не кучейQUADS, а одним TRIANGLE_STRIP.


  1. Paranoich
    05.02.2023 18:05

    А яндекс узнал изображенное на рисунке и даже сказал, что «нажмите, чтобы выбрать товар на этом изображении».
    Финальное изображение ведь случайно получилось именно такое, верно? И уголы именно такие (вместо ожидаемых 120 — 100). Случайно ведь?
    Полагаю, что пользователи оценили.


    1. AllKnowerHou Автор
      05.02.2023 19:24
      -2

      Что-то заминусовали без обратной связи непонятно


      1. BadHandycap
        05.02.2023 20:05
        +3

        Вы серьезно не понимаете за что минусы? Статья очень маленькая. OpenGL старый. Результат дерьмовый.


        1. AllKnowerHou Автор
          05.02.2023 20:06
          -3

          Статья очень маленькая

          Краткость сестра таланта


          1. BadHandycap
            05.02.2023 20:12
            +1

            Явно не на этом ресурсе.


            1. AllKnowerHou Автор
              05.02.2023 20:29
              -2

              Чисто поржать


              1. randomsimplenumber
                05.02.2023 23:58
                +2

                А в каком месте можно начинать смеяться? ;)
                Код, состоящий из волшебных констант более чем полностью - это не смешно.


                1. AllKnowerHou Автор
                  06.02.2023 18:09

                  я мастер волшебства, а как без них тогда объясни


      1. Moskus
        06.02.2023 00:15

        Идите почитайте что студенты на эту тему напрограммировали в Университете Калгари http://algorithmicbotany.org/

        Изобретать велосипед вообще с нуля в современной ситуации - несколько глупо. "Сделать что-то своё", при этом, может быть намного интереснее, если знаешь, что уже сделано.


        1. AllKnowerHou Автор
          06.02.2023 18:15

          можно вообще купить лицензию на speedtree и сидеть радоваться


  1. CrashLogger
    06.02.2023 23:16

    Лучше на шейдерах сделай такое. Кому нужен OpenGl 1.0 в 2023 году ?


    1. AllKnowerHou Автор
      07.02.2023 00:13

      да там надо скомпилить библиотеки опенжл, я как то не особо разбираюсь в гите khronos group не пойму где там ветка - там много всяких штук