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

Вход на сайт

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

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

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

Здравствуйте, Ильгиз. Математика - царица наук (Карл Гаусс). Изучение математики начинается с детского сада, когда нас учат считать и выполнять простые арифметические операции. Любой, даже самый простейший алгоритм будет связан с арифметическими...
Я хотел узнать математика это обязательно в программирование. Пять лет назад просто из любопытства я увлекся HTML потом изучил CSS и JvaScript потом изучил PHP и Java. Как то не задумывался и начал смотреть форумы и узнал что без математики не...
Все верно, но так же необходимо зайти в: Компоновщик -> Ввод -> Дополнительные зависимости Здесь необходимо нажать изменить и в Дополнительные зависимости прописать это: SDL2.lib SDL2main.lib SDL2test.lib Без этого не заработает. (MVS 2015)
Спасибо за реализацию, она действительно быстрая. Но не все линии отрисовывает в нужную сторону... Необходимо добавить проверку для случая X-линии if(y1 "<" y0) grad=-grad; и аналогично для Y-линии if(x1 "<" x0) grad=-grad; P.S. На...
Отличные уроки(учу GL по ним), только в renderScene нужно добавить очистку буфера цвета и буфера глубины. При изменении размеров треугольники размножаются)

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

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

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

Это легкий способ для создания интерактивных приложений. Всякий раз, когда мы нажимаем клавишу, мы знаем, что после событий клавиатуры обрабатывается наши функции обратного вызова, на дисплее функция будет вызываться снова и экран будет перерисовать.

Все, что требуется для нас зарегистрировать те же функции, как для дисплея, так и для пустой функции.

Если наше приложение будет работать с максимальным приоритетом, или мы хотим получить некоторые высокие результаты, используя его как бечмарк, тогда всё в порядке. Однако, когда наше приложение является лишь одной из программ, которые мы запускаем параллельно, то ресурсы компьютера могут стать дефицитными.

Виновником является , конечно, наше GLUT приложение, которое постоянно вызывает функции дисплея, даже если нет ничего нового для визуализации. Попробуйте проверить вкладку Диспетчер задач для процессов, и вы можете видеть, что даже если ничего не меняется от кадра к кадру, наше приложение GLUT ест ресурсы ЦП. GPU ресурсы также используются, конечно.

Когда нам нужно CPU или GPU для других вещей, то вы, вероятно, хотите сохранить эти ресурсы, сохраняя при этом поведение нашего приложения GLUT неизменным.

Для достижения этой цели мы должны избирательно позволить GLUT использовать функции дисплея. Вот для этого функция glutPostRedisplay и нужна нам.

glutPostRedisplay помечает активное окно, которое должно быть перерисовано, для вызова основного цикла. Обратите внимание, что только в текущем окне, не все окна. Наш последний урок содержит вложенные окна, и мы должны принять некоторые дополнительные меры, чтобы гарантировать, что все работает правильно.

Сначала мы собираемся изменить отображение функций для главного окна так, что цикл вызывает для визуализации все функции, определенные для дополнительного окна. Тогда мы можем просто вызвать glutPostRedisplay для главного окна и все будет оказана снова.

В функции main мы имели:

int main(int argc, char **argv) {
 
	// инициализация GLUT и создание окна
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(800,800);
	mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial");
 
	// регистрация обратных вызовов для главного окна
	glutDisplayFunc(renderScene);
	glutReshapeFunc(changeSize);
        glutIdleFunc(renderSceneAll);
        ...

Мы собираемся изменить отображение функции для основного окна renderSceneAll. Мы удалении регистрации обратных вызовов для простой функции.

int main(int argc, char **argv) {
 
	//  инициализация GLUT и создание окна
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(800,800);
	mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial");
 
	// регистрация обратных вызовов для главного окна
	glutDisplayFunc(renderSceneAll);
	glutReshapeFunc(changeSize);
 
	// Удаление пустой функции для высвобождения ресурсов CPU и GPU
	//glutIdleFunc(renderSceneAll);
        ...

Теперь давайте посмотрим, где мы должны сделать наши вызовы glutPostRedisplay. Мы только хотим, чтобы наши функции дисплея вызывались, когда будут изменения в изображении. Так как все сцены является статическим, единственный раз, когда появляются изменения, это когда мы перемещаем камеру.

Камера перемещается с помощью мыши и клавиатуры, поэтому мы должны добавить вызов glutPostRedisplay, когда эти события будут обработаны.

Давайте начнем с мышью. Камера перемещается при перемещении мыши. Таким образом, мы собираемся изменить нашу функцию перемещения мыши:

void mouseMove(int x, int y) {
	// когда левая кнопка нажата
	if (xOrigin >= 0) {
		// обновить deltaAngle
		deltaAngle = (x - xOrigin) * 0.001f;
		// обновить положение камеры
		lx = sin(angle + deltaAngle);
		lz = -cos(angle + deltaAngle);
	}
}

меняем на:

void mouseMove(int x, int y) {
 
	// когда левая кнопка нажата
	if (xOrigin >= 0) {
		// обновить deltaAngle
		deltaAngle = (x - xOrigin) * 0.001f;
		//  обновить положение камеры
		lx = sin(angle + deltaAngle);
		lz = -cos(angle + deltaAngle);
                //установка основного окна в качестве активного
                //и помечает его для перерисовки
		glutSetWindow(mainWindow);
		glutPostRedisplay();
	}
}

Теперь для клавиатуры. Функция, которая обрабатывает события нажатия клавиш - pressKey. Таким образом, мы собираемся изменить pressKey:

void pressKey(int key, int xx, int yy) {
	switch (key) {
		case GLUT_KEY_UP : deltaMove = 0.5f; break;
		case GLUT_KEY_DOWN : deltaMove = -0.5f; break;
	}
}

меняем на:

void pressKey(int key, int xx, int yy) {
	switch (key) {
		case GLUT_KEY_UP : deltaMove = 0.5f; break;
		case GLUT_KEY_DOWN : deltaMove = -0.5f; break;
	}
        //установка основного окна в качестве активного
        //и помечает его для перерисовки
	glutSetWindow(mainWindow);
	glutPostRedisplay();
 
}

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

К счастью, есть способ обойти это. Когда нажимаем клавишу мы присваиваем переменной ненулевое значение. Переменные мы проверили - и теперь положение камеры необходимо обновить. Эта проверка состоялась в renderSceneAll функции, поэтому мы знаем, что этот тест будет проходить всякий раз, когда пользователь сначала нажимает клавишу.

Вот renderSceneAll функции из предыдущего примера:

// Глобальная функция рендеринга
void renderSceneAll() {
 
	// проверки наличия клавиатурных движений
	if (deltaMove) {
		computePos(deltaMove);
	}
 
	renderScene();
	renderScenesw1();
	renderScenesw2();
	renderScenesw3();
}

Переменная deltaMode будет иметь ненулевое значение, когда клавиша нажата изначально. Поэтому мы можем назвать glutPostRedisplay внутри, если заявление, как показано ниже.

// Глобальная функция рендеринга
void renderSceneAll() {
 
	// проверки наличия клавиатурных движений
	if (deltaMove) {
		computePos(deltaMove);
 
                //установка основного окна в качестве активного
                //и помечает его для перерисовки
		glutSetWindow(mainWindow);
		glutPostRedisplay();
	}
 
	renderScene();
	renderScenesw1();
	renderScenesw2();
	renderScenesw3();
}

Наша функцию рендерит сцену, пока deltaMove не равен нулю. Это происходит только когда пользователь отпускает клавишу, как описано в функции releaseKey:

void releaseKey(int key, int x, int y) {
	switch (key) {
		case GLUT_KEY_UP :
		case GLUT_KEY_DOWN : deltaMove = 0;break;
	}
}

Продолжение в следующем уроке