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

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

Построение модели солнечной системы






Для того, чтобы создать примитивную, но управляемую модель солнечной системы нужно уметь правильно пользоваться стеком матриц моделирования. Команда glPushMatrix запоминает состояние текущей (верхней в стеке) матрицы моделирования. Это действие следует трактовать как запоминание текущего состояния координатного пространства. Если вслед за этим следует команда glTranslated (или glRotated), то она изменяет состояние пространства, умножая текущую матрицу моделирования на матрицу преобразования сдвига (или вращения) и вновь записывая результат в текущую (верхнюю в стеке) матрицу моделирования. Чтобы вспомнить предыдущее состояние пространства (то есть матрицу моделирования), надо дать команду glPopMatrix. Она сдвигает весь стек матриц вверх. При этом содержимое верхней матрицы уничтожается и заменяется тем, что было в матрице, лежащей под ней. Это следует понимать как возврат к предыдущему состоянию пространства.

Для изображения Солнца и планет можно использовать функцию glutWireSphere (double radius). Она состоит из последовательности команд, собирающих примитив из точек, то есть команд типа glVertex, и изображает каркас сферы заданного радиуса с центром в нуле координатного пространства. Положение нуля зависит от текущего состояния пространства. В нашей модели Солнце (с радиусом равным единице) должно всегда располагаться в центре сцены OpenGL. Оно может лишь вращаться вокруг своей оси. Земля должна вращаться как вокруг своей оси, так и вокруг Солнца. Луна должна вращаться вокруг своей оси, вокруг Земли и (вместе с нею) вокруг Солнца. Задачу лучше решать по частям. Сначала добиться изображения вращающегося Солнца, Затем добавить вращающуюся вокруг него Землю. После этого следует добавить вращение Земли вокруг своей оси. Луну следует создать в последнюю очередь.

Используем локальную систему координат (привязанную к объекту). Для определения порядка следования команд, изображающих Землю и Солнце, надо представить наблюдателя в начале этой системы координат, связанной с Землей. Пусть сначала и Земля и Солнце расположены в начале координат. Первая команда glRotate вращает локальную систему (Землю) относительно Солнца (годовое вращение Земли). Вторая команда glTranslate сдвигает Землю. Это означает задание радиуса планетарной орбиты. Земля помещается на орбиту в том месте, которое соответствует времени года. Третья команда glRotate вращает локальную систему координат вокруг локальной оси. Это означает поворот планеты вокруг своей оси — суточное вращение Земли.

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

glClear (GL_COLOR_BUFFER_BIT);

glColor3f (1, 1, 1);

glPushMatrix(); // Запоминаем единичное значение в стеке

glutWireSphere(1); // Рисуем Солнце

glRotated (gYear, 0, 1, 0); // Вращаем систему координат

glTranslated (2, 0, 0); // Смещаем Землю (вправо)

glRotated (gDay, 0, 0, 1); // Вращаем Землю в смещенной системе

 

glutWireSphere(0.3); // Рисуем Землю

glPopMatrix(); // Восстанавливаем единичное значение из стека

glutSwapBuffers();

Добейтесь раздельного управления всеми величинами (независимого выполнения всех преобразований). Дальнейшее усложнение сцены (изображение вращающегося Солнца и введение Луны) потребует от вас более интенсивной работы со стеком матриц моделирования. Вращение спутника Земли должно быть независимым от других движений.

int gSun, gYear, gDay, gMoon; // Углы вращения

 

void OnPaint()

{

glClear (GL_COLOR_BUFFER_BIT);

glColor3f (1, 1, 1);

 

glPushMatrix(); // Запоминаем единичное значение в стеке

glRotated (gSun, 1, 1, 1); // Вращаем систему координат

glutWireSphere(1); // Draw the Sun

 

// Операция со стеком

//....

glRotated (gYear, 0, 1, 0); // Вращаем систему координат

glTranslated (2, 0, 0); // Смещаем вправо (Землю)

 

// Операция со стеком

//....

glRotated (gDay, 0, 0, 1); // Вращаем в смещенной системе

 

glutWireSphere(0.3); // Draw the Earth

 

// Операция со стеком

//....

glRotated (gMoon, 1, 0, 0); // Вращаем систему координат

glTranslated (0, 0.45, 0); // Смещаем вверх (луну)

 

glutWireSphere(0.08); // Draw the moon

glPopMatrix(); // Восстанавливаем единичное значение из стека

glutSwapBuffers();

}

 

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

{

switch (ch)

{

case 27: exit(0); break;

case 'Y': /* Годовое вращение */ break;

case 'D': /* Дневное вращение */ break;

case 'M': /* Месячное вращение (для луны) */ break;

case 'S': /* Вращение Солнца */ break;

case 'Y': /* Годовое вращение */ break;

}

glutPostRedisplay();

}

 

void Init()

{

glClearColor (0, 0, 0, 0); // Вселенная черна как ночь

glShadeModel (GL_FLAT);

}

void OnIdle()

{

// Все типы вращений

OnPaint();

}

void OnSize (int w, int h)

{

glViewport (0, 0, w, h);

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

 

// gluPerspective(60., float(w)/ h, 1.0, 20.); // Или так

glFrustum (-1.0, 1.0, -1.0, 1.0, 2., 20.0); // Или так

//========= Размещаем наблюдателя (свой глаз)

gluLookAt (0, 0, 5, 0, 0, 0, 0, 1, 0);

 

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

Если вам трудно, то тщательно анализируйте более простую модель, которая работает.

Смешивание цветов (Blending)

Вы уже знаете, что цвет в OpenGL может быть задан четырьмя компонентами (red, green, blue, alpha). До сих пор мы не использовали четвертую компоненту. Она управляет режимом смешивания цветов (blending). С ее помощью можно управлять прозрачностью объектов сцены OpenGL. По умолчанию этот режим выключен (равносильно команде glDisable (GL_BLEND)). Если его включить, то значение alpha используется при вычислении цвета пиксела. При этом учитывается цвет вновь поступившего пиксела и цвет пиксела, который уже присутствует в буфере кадра (framebuffer). Смешивание работает в момент, когда сцена уже прошла фазу растеризации (преобразована в множество фрагментов), но перед тем, как получить и записать в буфер кадра окончательный цвет пиксела.

Если режим смешивания выключен, то каждый новый фрагмент замещает тот, который уже существует в буфере кадра. В этом случае говорят, что новый фрагмент непрозрачен. Если режим включен, то значение alpha определяет степень использования цвета нового фрагмента в процессе комбинирования его с цветом существующего. Это влияет на степень непрозрачности (opacity) нового слоя изображения. Часто оперируют величиной transparency, которая дополняет opacity до единицы и называется прозрачностью. Так, если мы изоражаем объект, расположенный за зеленым стеклом, непрозрачность (opacity) которого 10% (а прозрачность 90%), то при вычислении комбинированного цвета пиксела естественно взять 10% (зеленого) цвета стекла и 90% цвета объекта. Эта логика обобщается и на случай нескольких последовательно соединенных пропускающих свет поверхностей.

Рассмотрим простейший пример смешивания цветов. Изобразим два плоских квадрата частично наложенных друг на друга. Пусть один будет желтым, а другой цвета cyan. По нажатию левой кнопки мыши будем изменять порядок поступления команд рисования квадратов. Это позволит увидеть как смешивается желтый источник с циановой мишенью и наоборот. Степень непрозрачности (opacity) обоих квадратов выберем одинаковой по 0.75. Метод смешивания зададим с помощью двух констант:

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

В этом варианте обратите внимание на то, что цвета квадратов смешиваются не только друг с другом, но и с цветом фона. Попробуйте хотя бы частично избавиться от этого. Другие варианты сочетания констант, задающих метод смешивания, вы исследуете самостоятельно. Количество вариантов огромно, если учесть то, что можно исследовать эффект смешивания при разных значениях непрозрачности источника и мишени. Бездумный перебор вариантов вас разочарует, так как далеко не все комбинации имеют смысл. В качестве отправной точки для анализа сообщим, что самый простой вариант (отсутствие смешивания) дает такое сочетание коэффициентов: glBlendFunc (GL_ONE, GL_ZERO);.

bool bYellow = true; // Флаг: источник желтый

 

void Yellow() // Желтый квадрат

{

glBegin (GL_QUADS);

glColor4d(1, 1, 0, 0.75);

glVertex2d(0.1, 0.7);

glVertex2d(0.1, 0.1);

glVertex2d(0.7, 0.1);

glVertex2d(0.7, 0.7);

glEnd();

}

 

void Cyan() // Циановый квадрат

{

glBegin (GL_QUADS);

glColor4d(0, 1, 1, 0.75);

glVertex2d(0.3, 0.9);

glVertex2d(0.3, 0.3);

glVertex2d(0.9, 0.3);

glVertex2d(0.9, 0.9);

glEnd();

}

 

void Init()

{

glEnable (GL_BLEND); // Включаем режим смешивания цветов

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glShadeModel (GL_FLAT);

glClearColor (0, 0, 0, 0);

}

 

void OnPaint()

{

glClear(GL_COLOR_BUFFER_BIT);

 

if (bYellow)

{

Cyan(); Yellow();

}

else

{

Yellow(); Cyan();

}

glutSwapBuffers();

}

 

void OnSize (int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

 

if (w <= h)

gluOrtho2D (0, 1, 0, double(h)/w);

else

gluOrtho2D (0, double(w)/h, 0, 1);

}

 

void OnMouse(int button, int state, int x, int y)

{

if (state == GLUT_DOWN)

bYellow =!bYellow; // Меняем местами источник и мишень

}

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

double gx, gy, gz = 7.; // Для перемещения наблюдателя в пространстве

 

void Init()

{

glEnable(GL_DEPTH_TEST);

glEnable(GL_CULL_FACE); // Для уменьшения работы (не рисуем обратно-ориентированные грани)

 

glEnable (GL_LIGHTING);

glEnable (GL_LIGHT0);

glEnable(GL_AUTO_NORMAL);

glEnable(GL_NORMALIZE);

 

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

 

glMaterialfv(GL_FRONT, GL_SPECULAR, spec);

glMateriali(GL_FRONT, GL_SHININESS, 20);

 

glEnable (GL_BLEND);

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

}

 

void OnPaint()

{

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 

glPushMatrix ();

 

gluLookAt (gx, gy, gz, 0, 0, 0, 0, 1, 0);

 

glFrontFace(GL_CCW);

 

float dif[] = { 0.75f, 0.75f, 0, 1 };

glMaterialfv(GL_FRONT, GL_DIFFUSE, dif); // Gold

glTranslated (0, 0, -0.5);

glutSolidTorus (0.275, 0.85);

 

float blue[] = {0, 0.75f, 0.75f, 0.85f };

glMaterialfv(GL_FRONT, GL_DIFFUSE, blue); // Blue

glTranslated (-0.7, 0, 1);

glutSolidCylinder (0.3, 2);

 

glFrontFace(GL_CW);

float green[] = {0, 1, 0, 0.85f };

glMaterialfv(GL_FRONT, GL_DIFFUSE, green); // Green

 

glTranslated (1.4, 0, 0);

glutSolidTeapot(0.6);

 

glPopMatrix ();

glutSwapBuffers();

}

 

void OnSize (int w, int h)

{

if (!h)

return;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(30, (double) w/ h, 1, 30);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void OnSpecialKey (int key, int x, int y)

{

switch (key)

{

case GLUT_KEY_LEFT: gx +=.5; break;

case GLUT_KEY_RIGHT: gx -=.5; break;

case GLUT_KEY_DOWN: gy -=.5; break;

case GLUT_KEY_UP: gy +=.5; break;

}

glutPostRedisplay();

}

 

void OnMouse(int button, int state, int x, int y)

{

if (state == GLUT_DOWN)

{

gz = - gz;

}

}

Для того, чтобы понять эффект, производимый командой glEnable(GL_CULL_FACE) надо провести эксперимент. Нажимая клавишу стрелка-вниз убедитесь в том, что обратная сторона цилиндра не генерируется. Затем закомментируйте команду и вновь просмотрите обратную сторону цилиндра. Тороид и чайник — это вещи в себе. Для чайника (при включенном режиме GL_CULL_FACE) необходимо изменить ориентацию граней, из которых он состоит. Смотри команду glFrontFace(GL_CW). Аббревиатура CW скрывает описатель clock-wise, а команда означает, что фронтальными считаются поверхности, заданные обходом вершин по часовой стрелке. Для других объектов мы восстанавливаем обычное направление обхода вершин граней командой glFrontFace(GL_CCW). CCW соответствует counter clock-wise, а команда означает, что фронтальными считаются поверхности, заданные обходом вершин против часовой стрелки. Чайник требует также включить режим автоматического масштабирования нормалей. При этом, как вы помните, все векторы нормалей изменяются так, чтобы их длина была равна 1. Это делает команда glEnable(GL_NORMALIZE). Она нужна для правильной работы формулы учета освещенности, но сильно тормозит процесс генерации сцены. В этом легко убедиться методом сравнения. Пример также позволяет показать как тонко можно регулировать цветовую гамму сцены, изменяя многочисленные параметры в формуле учета освещенности. Вставьте, например, в функцию Init (перед вызовом glEnable (GL_BLEND)) следующие строки и сравните результат с тем, что было.

//=== При освещении общим светом все материалы максимально отражают синюю компоненту цвета

float amb[] = { 0, 0, 1, 1 };

glMaterialfv(GL_FRONT, GL_AMBIENT, amb);







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



Шрифт зодчего Шрифт зодчего состоит из прописных (заглавных), строчных букв и цифр...

Картограммы и картодиаграммы Картограммы и картодиаграммы применяются для изображения географической характеристики изучаемых явлений...

Практические расчеты на срез и смятие При изучении темы обратите внимание на основные расчетные предпосылки и условности расчета...

Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Подкожное введение сывороток по методу Безредки. С целью предупреждения развития анафилактического шока и других аллергических реак­ций при введении иммунных сывороток используют метод Безредки для определения реакции больного на введение сыворотки...

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

ПРОФЕССИОНАЛЬНОЕ САМОВОСПИТАНИЕ И САМООБРАЗОВАНИЕ ПЕДАГОГА Воспитывать сегодня подрастающее поколение на со­временном уровне требований общества нельзя без по­стоянного обновления и обогащения своего профессио­нального педагогического потенциала...

Кран машиниста усл. № 394 – назначение и устройство Кран машиниста условный номер 394 предназначен для управления тормозами поезда...

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

Измерение следующих дефектов: ползун, выщербина, неравномерный прокат, равномерный прокат, кольцевая выработка, откол обода колеса, тонкий гребень, протёртость средней части оси Величину проката определяют с помощью вертикального движка 2 сухаря 3 шаблона 1 по кругу катания...

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