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

Вход на сайт

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

Построения
на плоскости (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

Данный урок основан на уроке № 4.

В этом уроке мы будем перемещаться по небольшому искуственному миру снеговиков и для перемещения камеры будем использовать клавиши со стрелками. Клавиши "влево" и "вправо" будут вращать камеру вокруг оси "y", т.е. в плоскости "xz", тогда как клавиши "вверх" и "вниз" будет двигать камеру вперед и назад в пределах текущего направления. Код для этого примера в представлен с комментариями.
Во-первых, нам нужны глобальные переменные для хранения параметров камеры. Переменные будут хранить как положение камеры, так и вектор, который дает нам цель направления. Мы также будем хранить угол поворота. Там нет необходимости хранить у компоненту, поскольку он является постоянным. Следовательно,нам нужно:

- Угол поворота вокруг оси "у". Эта переменная позволит поворачивать камеру.
- float x, z: переменные, хранящие положение камеры в плоскости "xz".
- float lx, lz: координаты вектора, определяющие направление перемещения камеры.

Определим такие переменные:

// угол поворота камеры
float angle=0.0;
// координаты вектора направления движения камеры
float lx=0.0f,lz=-1.0f;
// XZ позиция камеры
float x=0.0f,z=5.0f;

Воспользуемся готовым кодом, описывающим сцену со снеговиком.

void drawSnowMan() {
 
	glColor3f(1.0f, 1.0f, 1.0f);
 
// тело снеговика
	glTranslatef(0.0f ,0.75f, 0.0f);
	glutSolidSphere(0.75f,20,20);
 
// голова снеговика
	glTranslatef(0.0f, 1.0f, 0.0f);
	glutSolidSphere(0.25f,20,20);
// глаза снеговика
	glPushMatrix();
	glColor3f(0.0f,0.0f,0.0f);
	glTranslatef(0.05f, 0.10f, 0.18f);
	glutSolidSphere(0.05f,10,10);
	glTranslatef(-0.1f, 0.0f, 0.0f);
	glutSolidSphere(0.05f,10,10);
	glPopMatrix();
// нос снеговика
	glColor3f(1.0f, 0.5f , 0.5f);
	glRotatef(0.0f,1.0f, 0.0f, 0.0f);
	glutSolidCone(0.08f,0.5f,10,2);
}

Теперь модифицируем функцию визуализации

Первое изменение в функции gluLookAt. Параметры gluLookAt функции теперь стали переменными вместо фиксированных значений. Функция gluLookAt обеспечивает простой и интуитивно понятный способ определения положения и ориентации камеры. В основном это три группы параметров, каждый из которых состоит из 3 значений с плавающей точкой. Первые три значения указывают положение камеры. Второй набор значений определяет точку зрения камеры. На самом деле это может быть любая точка в нашей линии обзора. Последняя группа параметров указывает на вектор, это, как правило, установленные значения ( 0.0, 1.0 , 0.0), это означает, что камеры не наклонена. Если вы хотите наклонить камеру - просто поиграйте с этими параметрами и посмотрите результат. Например, чтобы видеть все вверх тормашками, нужно ввести следующие значения попробовать (0.0 , -1.0, 0.0). Итак, первый набор параметров х, у, и z - начальное положение камеры. Второй набор параметров, это направление вектора обзора, рассчитывается сложением вектора, который определяет нашу линию обзора с положением камеры. Точка = прямая видимость + координаты положения камеры. Код функции рендеринга:

void renderScene(void) {
	// Очистка буфера цвета и глубины.
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// обнулить трансформацию
	glLoadIdentity();
	// установить камеру
	gluLookAt(   x, 1.0f,     z,
		  x+lx, 1.0f,  z+lz,
		  0.0f, 1.0f,  0.0f );
        // нарисуем "землю"
	glColor3f(0.9f, 0.9f, 0.9f);
	glBegin(GL_QUADS); // полигон с коондинатами
		glVertex3f(-100.0f, 0.0f, -100.0f);
		glVertex3f(-100.0f, 0.0f,  100.0f);
		glVertex3f( 100.0f, 0.0f,  100.0f);
		glVertex3f( 100.0f, 0.0f, -100.0f);
	glEnd();
        // Нарисуем 64 снеговика
	for(int i = -4; i < 4; i++)
		for(int j=-4; j < 4; j++) {
			glPushMatrix();
			glTranslatef(i*5.0, 0, j * 5.0);
			drawSnowMan();
			glPopMatrix();
		}
	glutSwapBuffers();
}

Теперь нужно создать функцию перемещения камеры, обрабатывающую нажатия клавиш перемещения. Мы используем клавиши "влево" и "вправо", чтобы повернуть камеру, или изменить вектор, который определяет линию обзора. Клавиши "вверх" и "вниз" используются для перемещения вдоль нынешней линии обзора. Когда пользователь нажимает левую или правую клавиши, переменная угла наклона изменяется соответствующим образом. На основании значения угла она вычисляет соответствующие значения для новых компонентов lx и lz линии вектора обзора. Обратите внимание, что мы только движется в плоскости "xz" , поэтому нам не нужно , чтобы менялась ly координата линии вектора обзора. Новые значения lx и lz обображаются на единичном круге на плоскости "xz". Поэтому, учитывая переменную угла ang , новые значения для lx и lz, расчитываются по формуле:

lx = sin(ang);
lz = -cos(ang);

Мы производили бы эти действия, если бы мы хотели конвертировать полярные координаты в декартовы координаты. lz является отрицательным, потому что начальное значение равно -1. Заметьте, что камера не двигается при обновлении lx и lz, положение камеры остается, только меняется точка обзора. Мы также хотим перемещать камеру вдоль линии обзора. Для этого мы собираемся добавить или вычесть часть линии вектора обзора нашей текущей позиции, когда стрелки "вверх" и "вниз" будут нажаты соответсвенно. Например, для перемещения камеры вперед новые значения для переменных x и z будут:

x = x + lx * fraction;
z = z + lz * fraction;

fraction - возможная реализация скорости. Мы знаем, что (lx, lz) является единичным вектором (как упоминалось ранее, его точка в единичном круге), поэтому если fraction остается постоянным, то скорость останется постоянной. При увеличении значения fraction мы перемещаемся быстрее.

Функция обработки нажатия клавиш перемещения

void processSpecialKeys(int key, int xx, int yy) {
	float fraction = 0.1f;
	switch (key) {
		case GLUT_KEY_LEFT :
			angle -= 0.01f;
			lx = sin(angle);
			lz = -cos(angle);
			break;
		case GLUT_KEY_RIGHT :
			angle += 0.01f;
			lx = sin(angle);
			lz = -cos(angle);
			break;
		case GLUT_KEY_UP :
			x += lx * fraction;
			z += lz * fraction;
			break;
		case GLUT_KEY_DOWN :
			x -= lx * fraction;
			z -= lz * fraction;
			break;
	}
}

Далее следует код main()

int main(int argc, char **argv) {
	// Инициализация и создание окна
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(400,400);
	glutCreateWindow("Урок 5");
 
	// Регистрация
	glutDisplayFunc(renderScene);
	glutReshapeFunc(changeSize);
	glutIdleFunc(renderScene);
	glutKeyboardFunc(processNormalKeys);
	glutSpecialFunc(processSpecialKeys);
 
	// Инициализация OpenGL функции теста
	glEnable(GL_DEPTH_TEST);
 
	// Основной цикл GLUT
	glutMainLoop();
 
	return 1;
}

Продолжение в уроке № 6