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

Вход на сайт

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

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

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

torrvic, возможно, Вам нужно добавить -lGLU
Извините за тупой вопрос. У меня при сборке Вашего примера выходит ошибка: "undefined reference to gluLookAt". Не могу найти в какой библиотеке находится эта функция. У меня задано: -lGL -lglut ... Искал в /usr/lib таким образом: nm lib*so* | grep...
Здравствуйте. Спасибо за проект. У меня вопрос, по какой причине определение принадлежности точки многоугольнику работает некорректно, если координаты из больших чисел состоят, например: int[] vertex = new int[] {...
Сейчас проверила нашла причину не запускания // Создание контекста воспроизведения OpenGL и привязка его к панели на форме OpenGLControl1:=TOpenGLControl.Create(Self); with OpenGLControl1 do begin Name:='OpenGLControl1'; //вот тут...
Ну..кажется что то пошло не так http://pp.usera...

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

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