Студопедия — Перемещение в пространстве
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Перемещение в пространстве






В данном разделе мы рассмотрим как можно смоделировать управление примитивным летательным аппаратом. Предположим, что сцена, вокруг которой должен летать наш самолет, представляет собой три стоящие недалеко друг от друга геометрические фигуры: куб, тетраэдр и додекаэдр. Мы хотим смоделировать изменения сцены, которые могли бы наблюдаться из окна летательного аппарата при управлении тремя характерными для всех летательных аппаратов углами: крена, атаки и курса (азимута), которые влияют на положение в пространстве самого летательного аппарата. Мы будем хранить эти значения в трех глобальных переменных: gdRoll — угол крена, gdPitch — угол атаки (или тангаж), и gdHeading — угол курса.

Функция Fly, преобразующая сцену OpenGL должна учитывать эти углы и изменять матрицу моделироваия так, чтобы векторы координат вершин примитивов сцены (которые будут умножены справа на матрицу моделирования) изменялись согласно положениям рулей-элеронов.

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

class Point3D

{

public:

double x, y, z;

 

Point3D() { x = y = z = 0.; }

Point3D (double xx, double yy, double zz) { x = xx; y = yy; z = zz; }

Point3D (double v[3]) { x = v[0]; y = v[1]; z = v[2]; }

Point3D operator+ (Point3D& p) { return Point3D (x+p.x, y+p.y, z+p.z); }

Point3D operator- (Point3D& p) { return Point3D (x-p.x, y-p.y, z-p.z); }

void operator+= (Point3D& p) { x += p.x; y += p.y; z += p.z; }

void operator-= (Point3D& p) { x -= p.x; y -= p.y; z -= p.z; }

Point3D operator* (double d) { return Point3D (x*d, y*d, z*d); }

Point3D operator* (Point3D& p)

{

return Point3D (y*p.z - z*p.y, z*p.x - x*p.z, x*p.y - y*p.x);

}

double operator! () { return sqrt (x*x + y*y + z*z); }

double Dist (Point3D& p) { return!Point3D (*this - p); }

 

Point3D ToUnit ()

{

double r =!*this;

return Point3D (x/r, y/r, z/r);

}

 

Point3D& Rotate (Point3D& p, double dr)

{

glMatrixMode (GL_MODELVIEW);

glLoadIdentity();

glRotated (dr, p.x, p.y, p.z);

 

double

mm[16],

t[3] = { x, y, z },

v[3];

glGetDoublev (GL_MODELVIEW_MATRIX, mm);

 

for (int i=0; i<3; i++)

{

v[i] = 0.;

for (int j=0; j<3; j++)

v[i] += mm[(i<<2) + j] * t[j];

}

x = v[0]; y = v[1]; z = v[2];

return *this;

}

};

 

const double PI = acos(-1.), ToRad = PI/180.; // Вспомогательные константы

//==== Направление вверх, положение центра сцены и позиция глаза наблюдателя

Point3D gU (0,1,0), gC, gE (0, 0, gDist);

double gSpeed = 0.1, gDist = 14; // Скорость и расстояние от глаза до центра сцены

Прежде всего напишем тела функций, которые задают списки команд для изображения сцены, то есть фигур ландшафта. Пусть первой фигурой будет зеленый куб. Просмотрите файл glut.h и найдите функции для изображения различных трехмерных фигур (например, glutSolideCube). Используйте их для создания объектов ландшафта.

void Cube()

{

static double green[3] = { 0.5, 0.75, 0.5 };

 

glNewList(1, GL_COMPILE);

glColor3dv(green);

//=== Здесь ваш код создания куба

//..........

glEndList();

}

Вторым элементом ландшафта (вторым списком команд) пусть будет тетраэдр. Его можно создать и вручную.

void Tetrahedron()

{

static double blue[3] = { 0.6667, 0.5, 1.0 };

 

double r = 1./sqrt(3); // To normalize normals

 

glNewList (2, GL_COMPILE);

glColor3dv (blue);

 

glBegin (GL_TRIANGLES); // Draw the four faces of the tetrahedron

 

glNormal3d (-r,-r,-r); // Left-Down-Rear

glVertex3d (1,-1,-1);

glVertex3d (-1,-1, 1);

glVertex3d (-1, 1,-1);

 

glNormal3d (-r, r, r); // Left-Up-Front

glVertex3d (1, 1, 1);

glVertex3d (-1, 1,-1);

glVertex3d (-1,-1, 1);

 

glNormal3d (r, r,-r); // Right-Up-Rear

glVertex3d (1, 1, 1);

glVertex3d (1,-1,-1);

glVertex3d (-1, 1,-1);

 

glNormal3d (r,-r, r); // Right-Down-Front

glVertex3d (1, 1, 1);

glVertex3d (-1,-1, 1);

glVertex3d (1,-1,-1);

 

glEnd();

glEndList();

}

Наконец, изобразим додекаэдр. Вручную его изобразить довольно сложно. Додекаэдр — это правильный многогранник из 12 пятиугольных граней и 20 вершин. Готовые коды можно найти во многих источниках, но проще использовать glut-функцию.

void Dodecahedron()

{

glNewList (3, GL_COMPILE); // Display list for Dodecahedron (12 pentagon faces, 20 vertices)

glColor3d (0.9, 0.6, 0.7); // DeepPurple

glutSolidDodecahedron ();

glEndList();

}

Создайте еще несколько деталей ландшафта, а затем соберите сцену из готовых деталей.

void DrawScene()

{

glPushMatrix();

glTranslated (-1.5, 0., 0.);

glCallList(1); // Первая фигура (куб) смещена влево (x = -1.5)

 

// Сместите как-то систему координат (2-ю фигуру относительно 1-й), чтобы тетраэдр был отделен от куба

// и нарисуйте тетраэдр (пирамиду)

glPopMatrix();

glPushMatrix();

glTranslated (1.5, 0., -5.);

glCallList (2);

// Еще раз сместите и поверните, с тем, чтобы додекаэдр стоял отдельно/ и нарисуйте Dodecahedron

//.......

//===== Продолжайтев том же духе, пока не будет готова вся сцена

}

Функция перерисовки может иметь вид:

void OnPaint()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Fly(); // Учет воздействия рулей управления и перерисовка

glutSwapBuffers();

}

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

void Fly ()

{

glMatrixMode (GL_MODELVIEW);

glLoadIdentity();

 

gluLookAt (gE.x, gE.y, gE.z, gC.x, gC.y, gC.z, gU.x, gU.y, gU.z);

DrawScene();

}

Инициализация сцены (Init) выполняет традиционные действия и кроме того, вызывает функции подготовки элементов ландшафта.

void Init()

{

glClearColor (0, 0, 0, 0);

glShadeModel (GL_SMOOTH);

 

glEnable (GL_DEPTH_TEST);

glEnable (GL_LIGHTING);

glEnable (GL_LIGHT0);

glEnable (GL_LIGHT1);

 

glEnable (GL_COLOR_MATERIAL);

glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);

 

float spec[] = { 1, 1, 1 };

glMaterialfv (GL_FRONT, GL_SPECULAR, spec);

glMaterialf (GL_FRONT, GL_SHININESS, 128);

 

float pos0[] = { -3, 3, 3, 0 };

glLightfv (GL_LIGHT0, GL_POSITION, pos0);

 

float amb[] = { 0.3f, 0.3f, 0.3f, 0 };

glLightfv (GL_LIGHT0, GL_AMBIENT, amb);

 

float pos1[] = { 3, 3, -3, 0 };

glLightfv (GL_LIGHT1, GL_POSITION, pos1);

 

glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

 

Cube();

Tetrahedron();

Dodecahedron();

 

glNewList (3, GL_COMPILE);

glColor3d (0.61424, 0.04136, 0.04136);

glutSolidTorus(0.275, 0.8, 16, 16);

glEndList();

 

glNewList (4, GL_COMPILE);

glColor3d(0,0,1);

glutSolidCone(0.4, 1.4, 16, 16);

glEndList();

 

glNewList (5, GL_COMPILE);

glColor3d(0,1,1);

glutSolidCone(0.3, 1.8, 16, 16);

glEndList();

glNewList (6, GL_COMPILE);

glColor3d (0.61424, 0.04136, 0.04136);

glutSolidSphere(0.5, 16, 16);

glEndList();

}

Управление углами летательного аппарата возложим на цифровые клавиши правой части клавиатуры (keypad) так как обозначено в функции main:

void main()

{

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

glutInitWindowSize(500, 500);

glutCreateWindow ("KeyPad: 2-8, 4-6, 7-9, 5-0, 1-3, Space, Up-Down");

 

Init();

 

glutSpecialFunc (OnSpecialKey);

glutKeyboardFunc(OnKey);

 

glutReshapeFunc(OnSize);

glutDisplayFunc(OnPaint);

glutMainLoop();

}

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

void OnKey (unsigned char ch, int x, int y)

{

switch (ch)

{

case '7': Roll(-1); break;

case '9': Roll(1); break;

case '8': Pitch(-1); break;

case '2': Pitch(1); break;

case '4': Head(-1); break;

case '6': Head(1); break;

case '5': // Движение вперед

{

Point3D pt ((gE-gC) * gSpeed);

gE -= pt;

gC -= pt;

Fly();

break;

}

case '3': // Движение назад

{

// Реализуйте по аналогии с движением вперед

Fly();

break;

}

case ' ':

cout <<"\nE = (" <<gE.x<<", "<<gE.y<<", "<<gE.z<<')'

<<"\nC = (" <<gC.x<<", "<<gC.y<<", "<<gC.z<<')'

<<"\nU = (" <<gU.x<<", "<<gU.y<<", "<<gU.z<<")\n";

break;

case 27: exit(0); break;

}

glutPostRedisplay();

}

Приведем возможный способ реализации функции, реагирующей на изменение тангажа.

void Pitch (int angle)

{

Point3D v = gC - gE,

n = v * gU;

gC = gE + v.Rotate(n, angle);

gU.Rotate (n, angle);

Fly();

}

Обработку WM_SIZE можно взять такой

void OnSize (int w, int h)

{

glViewport (0, 0, w, h);

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

gluPerspective(35, double(w)/h,.1, 1000);

}

Чтобы не затеряться в бескрайних небесных просторах, введите следующий код в реакцию на нажатие клавиши 0 (на Key Pad). Нажатие на эту клавишу должно возвращать сцену в первоначальное состояние.

case '0': // Возврат в исходное состояние

gC = Point3D (0, 0, 0);

gU = Point3D (0, 1, 0);

gE = Point3D (0, 0, gDist);

Fly();

break;

Создайте недостающие обработчики сообщений и добейтесь осмысленного (то есть управляемого вами) перемещения в пространстве.







Дата добавления: 2015-10-19; просмотров: 492. Нарушение авторских прав; Мы поможем в написании вашей работы!



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

ТЕОРЕТИЧЕСКАЯ МЕХАНИКА Статика является частью теоретической механики, изучающей условия, при ко­торых тело находится под действием заданной системы сил...

Теория усилителей. Схема Основная масса современных аналоговых и аналого-цифровых электронных устройств выполняется на специализированных микросхемах...

Логические цифровые микросхемы Более сложные элементы цифровой схемотехники (триггеры, мультиплексоры, декодеры и т.д.) не имеют...

Краткая психологическая характеристика возрастных периодов.Первый критический период развития ребенка — период новорожденности Психоаналитики говорят, что это первая травма, которую переживает ребенок, и она настолько сильна, что вся последую­щая жизнь проходит под знаком этой травмы...

РЕВМАТИЧЕСКИЕ БОЛЕЗНИ Ревматические болезни(или диффузные болезни соединительно ткани(ДБСТ))— это группа заболеваний, характеризующихся первичным системным поражением соединительной ткани в связи с нарушением иммунного гомеостаза...

Решение Постоянные издержки (FC) не зависят от изменения объёма производства, существуют постоянно...

Патристика и схоластика как этап в средневековой философии Основной задачей теологии является толкование Священного писания, доказательство существования Бога и формулировка догматов Церкви...

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

Вопрос 1. Коллективные средства защиты: вентиляция, освещение, защита от шума и вибрации Коллективные средства защиты: вентиляция, освещение, защита от шума и вибрации К коллективным средствам защиты относятся: вентиляция, отопление, освещение, защита от шума и вибрации...

Studopedia.info - Студопедия - 2014-2024 год . (0.012 сек.) русская версия | украинская версия