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

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

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






Для того, чтобы создать примитивную, но управляемую модель солнечной системы нужно уметь правильно пользоваться стеком матриц моделирования. Команда 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; просмотров: 525. Нарушение авторских прав; Мы поможем в написании вашей работы!



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

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

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

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

Этапы трансляции и их характеристика Трансляция (от лат. translatio — перевод) — процесс синтеза белка из аминокислот на матрице информационной (матричной) РНК (иРНК...

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

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

Задержки и неисправности пистолета Макарова 1.Что может произойти при стрельбе из пистолета, если загрязнятся пазы на рамке...

Вопрос. Отличие деятельности человека от поведения животных главные отличия деятельности человека от активности животных сводятся к следующему: 1...

Расчет концентрации титрованных растворов с помощью поправочного коэффициента При выполнении серийных анализов ГОСТ или ведомственная инструкция обычно предусматривают применение раствора заданной концентрации или заданного титра...

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