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

Вход на сайт

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

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

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

Спасибо за реализацию, она действительно быстрая. Но не все линии отрисовывает в нужную сторону... Необходимо добавить проверку для случая X-линии if(y1 "<" y0) grad=-grad; и аналогично для Y-линии if(x1 "<" x0) grad=-grad; P.S. На...
Отличные уроки(учу GL по ним), только в renderScene нужно добавить очистку буфера цвета и буфера глубины. При изменении размеров треугольники размножаются)
как исправить это , сделал все по инструкции
Timer1 - выдает ошибку. Использовал IdleTimer1, работает! unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, OpenGLContext, GL, GLU; type { TForm1 } TForm1 =...
в коде присутствуют ошибки! // Считываем координаты procedure TForm1.getCoords(Sender: TObject); var j1:longint; begin n:= StrToInt(Edit2.Text); //число точек s1:=Edit1.Text; s2:=''; i := 1; j:=1; k:=0...

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

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

В предыдущем уроке мы видели, как создать простое меню и обрабатывать события, генерируемые при выборе пользователя щелчком клавишей мыши. Теперь мы увидим, как добавить каскад подменю. Подменю создается той же функцией, как и меню. Поэтому мы используем функцию glutCreateMenu( см. в предыдущем уроке), для создания подменю, а также меню. Затем мы должны добавить подменю в качестве входа в меню. Это делается в GLUT использованием glutAddSubMenu.

void glutAddSubMenu(char *entryName, int menuIndex);

Параметры:

- entryName - название подменю пункта в меню.
- menuIndex - Индекс подменю, который мы получаем в качестве возвращаемого значения при вызове glutCreateMenu для подменю.

Эта функция добавляет запись в конец меню. При выборе новой записи откроется подменю. Следующий фрагмент кода иллюстрирует использование описанной выше функции:

void createPopupMenus() {
 
	shrinkMenu = glutCreateMenu(processShrinkMenu);
	glutAddMenuEntry("Shrink",SHRINK);
	glutAddMenuEntry("NORMAL",NORMAL);
 
	fillMenu = glutCreateMenu(processFillMenu);
	glutAddMenuEntry("Fill",FILL);
	glutAddMenuEntry("Line",LINE);
 
	colorMenu = glutCreateMenu(processColorMenu);
	glutAddMenuEntry("Red",RED);
	glutAddMenuEntry("Blue",BLUE);
	glutAddMenuEntry("Green",GREEN);
	glutAddMenuEntry("Orange",ORANGE);
 
	mainMenu = glutCreateMenu(processMainMenu);
	glutAddSubMenu("Polygon Mode", fillMenu);
	glutAddSubMenu("Color", colorMenu);
 
	// прикрепить меню к правой кнопке мыши
	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

Использование кода свыше будет таково, что когда пользователь нажимает правой клавишей мыши - появляется меню с двумя опциями: "Polygon Mode" и "Color". Нажатие на "Color", появится подменю с тремя пунктами: "Red", "Blue", "Green" и "Orange".

Изменение меню

В некоторых случаях изменение пункта меню может быть нежелательно. GLUT позволяет изменять и удалять пункты меню. Чтобы альтернативного использования пункта меню:

void glutChangeToMenuEntry(int entry, char *name, int value);

Параметры:

- entry - индекс записи, это должно быть между 1 и общее количество записей.
- *name - имя новой записи.
- value - значение, которое будет вернуться к функции обратного вызова при выборе записи.

Для переключения использования подменю:

void glutChangeToSubMenu(int entry, char *name, int menu);

Параметры:

- entry - индекс записи, это должно быть между 1 и общее количество записей.
- *name - имя новой записи.
- menu - индекс меню, которое необходимо использовать.

Следующая функция удаляет элементы меню.

void glutRemoveMenuItem(int entry);

Параметры:

- entry - индекс записи, это должно быть между 1 и общее количество записей.

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

void processMenuEvents(int option) {
 
	red = 0.0;
	green = 0.0;
	blue = 0.0;
 
	switch (option) {
		case RED :
			red = 1.0; break;
		case GREEN :
			green = 1.0; break;
		case BLUE :
			blue = 1.0; break;
		case WHITE :
			red = 1.0;
			green = 1.0;
			blue = 1.0; break;
	}
}
 
void processKeys(unsigned char c, int x, int y) {
 
	int num = glutGet(GLUT_MENU_NUM_ITEMS);
	switch (c) {
		case 'a':
			glutChangeToMenuEntry(1,"Blue",BLUE);
			glutChangeToMenuEntry(3,"Red",RED);
			break;
		case 'b':
			glutChangeToMenuEntry(3,"Blue",BLUE);
			glutChangeToMenuEntry(1,"Red",RED);
			break;
		case 'c':
			if (num > 3)
				glutRemoveMenuItem(num);
			break;
		case 'd': if (num == 3)
				glutAddMenuEntry("White",WHITE);
			break;
	}
	glutSetMenu(menu);
}
 
void createGLUTMenus() {
 
	menu = glutCreateMenu(processMenuEvents);
	glutAddMenuEntry("Red",RED);
	glutAddMenuEntry("Green",GREEN);
	glutAddMenuEntry("Blue",BLUE);
	glutAddMenuEntry("White",WHITE);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

Заметим, что мы изменили меню в функции обратного вызова клавиатуры, в отличие от функции обратного вызова меню. Это потому, что мы не должны делать любые изменения в меню во время его использования. Меню при использовании до обратного вызова не закончится, так что мы не могли изменить структуру меню внутри собственного обратного вызова меню.

Как упоминалось ранее, когда меню используется, оно не может быть изменено. В целях предотвращения ошибки мы должны убедиться, что меню не используется, прежде чем перейти к следующему пункту меню. GLUT позволяет зарегистрировать обратный вызов функции, которая будет вызываться не когда меню всплывает, а когда оно скрывается. Функция должна быть зарегистрирована в обратном вызове glutMenuStatusFunc.

void glutMenuStatusFunc(void (*func)(int status, int x, int y);

Параметры:

*func – имя вызываемой функции.

Эта функция может быть вызвана в main(). Как видно, glutMenuStatusFunc должнf принять три параметра. К ним относятся:

- status - одна из GLUT_MENU_IN_USE или GLUT_MENU_NOT_IN_USE
- х - координата меню слева относительно клиентской области окна.
- y - координата меню cверху относительно клиентской области окна.

В качестве примера представлена ​​функция, где устанавливается флаг, когда меню находится в использовании.

void processMenuStatus(int status, int x, int y) {
 
	if (status == GLUT_MENU_IN_USE)
		flag = 1;
	else
		flag = 0;
}

Теперь мы можем использовать этот флаг при обработке события от клавиатуры, как в следующем примере:

void processKeys(unsigned char c, int x, int y) {
 
	if (!flag) {
		int num = glutGet(GLUT_MENU_NUM_ITEMS);
		switch (c) {
			case 'a':
				glutChangeToMenuEntry(1,"Blue",BLUE);
				glutChangeToMenuEntry(3,"Red",RED);
				break;
			case 'b':
				glutChangeToMenuEntry(3,"Blue",BLUE);
				glutChangeToMenuEntry(1,"Red",RED);
				break;
			case 'c':
				if (num > 3)
					glutRemoveMenuItem(num);
				break;
			case 'd': if (num == 3)
					glutAddMenuEntry("White",WHITE);
				break;
		}
	}
}

Готовый код мы с Вами рассмотрим в уроке № 10, скриншоты с меню приложены из урока 10.