Добавлен: 09.01.2024
Просмотров: 247
Скачиваний: 15
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
// 1. Угол обзора в направлении OY
// 2. Соотношение X к Y (нужно для пропорций)
// 3. Последние две переменные отвечают за расстояние от зрителя до плоскостей
}
Нужно задать углы просмотра. Для удобства они будут равны 30 градусам:
// .f после числа делает его числом с плавающей запятой.
float mercury_angle = 30.0f; // стартовые углы
float satrun_ring_angle = 30.0f;
float venus_angle = 30.0f;
float earth_angle = 30.0f;
float moon_angle = 30.0f;
float earth_ring_angle = 30.0f;
float mars_angle = 30.0f;
float mars_ring_angle = 30.0f;
float mars_ring_angle2 = 30.0f;
float fobos_angle = 30.0f;
float fobos_angle2 = 30.0f;
float deimos_angle = 30.0f;
float deimos_angle2 = 30.0f;
float jupiter_angle = 30.0f;
float jupiter_angle1 = 30.0f;
float io_ring_angle = 30.0f;
float europa_ring_angle = 30.0f;
float ganimed_ring_angle = 30.0f;
float callisto_ring_angle = 30.0f;
float io_angle = 30.0f;
float europa_angle = 30.0f;
float europa_angle2 = 30.0f;
float satrun_angle = 30.0f;
float uranus_angle = 30.0f;
float uranus_ring_angle = 30.0f;
float neptune_angle = 30.0f;
float neptune_ring_angle = 30.0f;
float triton_angle = 30.0f;
Чтобы нарисовать 3д сцену нам нужна следующая функция(сама работа 2д):
void sceneDraw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очищает указанные буферы, а именно
// Очистка буфера цвета и Очистка буфера глубины. То что содержит данные о цвете пикселя может называться буфером цвета, а то что содержит данные
//о расстоянии пикселя до наблюдателя называется буфером глубины
glMatrixMode(GL_MODELVIEW); // Применяет последующие матричные операции к стеку матриц представления модели.
glLoadIdentity(); // заменяет текущую матрицу матрицей идентификаторов.
glTranslatef(0.0f, 0.0, -50.0f); // модифицируем текущую матрицу ( которая в данный момент единичная).
glScalef(0.4f, 0.4f, 0.4f); // меняет масштаб, приближает/отдаляет
// Строим орбиты планет
circleDraw(4.62); // Функция
circleDraw(9);
circleDraw(12.5);
circleDraw(18.8);
circleDraw(30);
circleDraw(39.5);
circleDraw(52);
circleDraw(63);
planetsDraw(); // Строим планеты
glutSwapBuffers(); //После отрисовки мы переставляем (заменяем) буфера
/*
Swap Buffers - обмен буферов. Используется при анимации.
Мы используем окно с двойной буферизацией, один буфер отображаемый, а другой - спрятанный.
В таком режиме инструкции OpenGL по рисованию изображений всегда применяются к спрятанному буферу.
Вызов функции glutSwapBuffers обменивает буфера, отображая окно целиком после того, как оно уже сформировано.
Эта технология не позволяет человеческому глазу видеть, как линия за линией формируется кадр.
*/
}
Теперь мы будем рисовать планеты, спутники и орбиты спутников при помощи этой функции:
void planetsDraw() {
Рассмотрим сначала построение планеты на примере Солнца:
//Sun
Sun Su;
glPushMatrix(); //для сохранения и восстановления текущих координат
/*
Сдвигает текущий стек матриц на единицу вниз, дублируя текущую матрицу.
То есть после вызова glPushMatrix матрица наверху стека идентична матрице под ним.
*/
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //устанавливает опции для отрисовки многоугольника.
/*
Второй параметр указывает, как будет рисоваться многоугольник.
GL_FILL(рисуем заполненный многоугольник).
Первый параметр указывает: к лицевой, тыльной или же к обеим сторонам применяется опция, заданная вторым параметром.
*/
glColor3f(0.9, 0.9, 0.0);
/*
Следующие строки кода используют команду glColor3f(r, g, b).
Три ее параметра указывают насыщенность цвета красной, синей и зеленой составляющей.
Каждый из них может принимать значение от 0.0f до 1.0f.
*/
glutSolidSphere(Su.getR(), 50, 50);
// Строит сферу с радиусом 2.5,
/*
slices Количество делений вокруг оси Z. (широта)
stacks Количество делений вдоль оси z. (долгота (см. глобус))
*/
glEnd(); // мы закончили рисовать приметив
glPopMatrix(); // извлекает текущий стек матриц, заменяя текущую матрицу той, что находится под ней в стеке.
Далее мы делаем аналогично, но с некоторыми добавлениями.
//Земля
Earth Ea;
glPushMatrix();
glRotatef(earth_angle, 0.0f, 0.0f, 1.0f);//отвечает за вращение планеты вокруг оси. Первый параметр-стартовый угол, затем координаты x, y, z вокруг которых происходит вращательное движение
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3f(0.137255, 0.137255, 0.556863);
glTranslatef(Ea.getS(), 0.0, 0.0f);//задаются координаты x,y,z
glutSolidSphere(Ea.getR(), 50, 50);
glPopMatrix();
Так мы добавили здесь вращение и смещение планеты относительно Солнца.
//Луна
Moon Mo;
glPushMatrix();
glRotatef(moon_angle, 0.0f, 0.0f, 2.0f);
glTranslatef(Mo.getSSun(), 0.0, 0.0f); // отдаляем от Солнца
glRotatef(moon_angle, 0.0f, 0.0f, 2.0f);
glTranslatef(Mo.getS(), 0.0, 0.0f); // расстояние от Земли
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3f(0.8f, 0.8f, 0.8f);
glutSolidSphere(Mo.getR(), 50, 50);
glPopMatrix();
Здесь мы должны еще отдалить наш спутник и от самой планеты, то есть в данном случае от Земли.
//Орбита Луны
glPushMatrix();
glRotatef(earth_ring_angle, 0.0f, 0.0f, 1.0f);
glTranslatef(12.4f, 0.0, 0.0f);
circleDraw(2); // зависимость от радиуса
glPopMatrix();
Здесь мы будем еще обращаться к функции circleDraw(float radius) для построения.
И так далее продолжаем действия с другими планетами, спутниками и орбитами этих спутников.
}
Теперь рассмотрим функцию построения окружности.
void circleDraw(float radius) { // Функция построения окружности с радиусом (радиус - вещественное число)
int cir_x = 0;
int cir_y = 0;
int min_angle = 0;
int max_angle = 360;
float theta;
int i;
float cir_x_itr;
float cir_y_itr;
float x;
float y;
glColor3f(1.0, 1.0, 1.0); // белый цвет
glPushMatrix();
glBegin(GL_LINE_LOOP);//здесь отрезок задается последней и первой вершиной, образуя замкнутую линию
for (i = min_angle; i <= max_angle; i++) { // цикл от 0 до 360 градусов
theta = 0.0174532925 * float(i); // 1 градус это 0.0174532925 радиан. Мы задаём i-ый итерационный угол, theta - угол в рад (мы перевели угол в градусах в угол в радианах ради косинуса и синуса)
cir_x_itr = radius * cosf(theta); // координаты для рисования i-ой итерационной точки по х и у
cir_y_itr = radius * sinf(theta);
x = cir_x + cir_x_itr; // x текущее положение x (то есть прошлое + прибавка нынешнего x)
y = cir_y + cir_y_itr;
glVertex3f(x, y, -30.0f); // Указывает вершины по координатам. Z = -30.0 для соблюдения масштаба
}
glEnd();
glPopMatrix();
}
Данная функция отвечает за движение:
void mercury_update(int value) {
mercury_angle += 2.0f; // 2 градуса в секунду - скорость планеты
if (mercury_angle > 360) {
mercury_angle -= 360;
}
Mercury Me;
glutPostRedisplay(); // помечает активное окно, которое должно быть перерисовано, для вызова основного цикла
glutTimerFunc(Me.getV(), mercury_update, 0);
/*
Эта функция устанавливает таймер.
Первый параметр millis задает время в миллисекундах, по истечении которых вызывается функция,
(вторая космическая скорость)
которая указана как второй параметр.
Третий параметр value указывает индентификатор таймера,
т.е. таймеров может быть одновременно запущено несколько.
*/
}
Посмотрим, как выстроить движение для Земли и ее спутника Луны:
void earth_update(int value) {
earth_angle += 2.0f;
if (earth_angle > 360) {
earth_angle -= 360;
}
Earth Ea;
glutPostRedisplay();
glutTimerFunc(Ea.getV(), earth_update, 0);
}
void moon_update(int value) {
moon_angle += 2.0f; // Скорость, с которой движется объект по орбите
if (moon_angle > 360) {
moon_angle -= 360;
}
Moon Mo;
glutPostRedisplay();
glutTimerFunc(Mo.getV(), moon_update, 0);
}
Движение самой орбиты:
void earth_update_ring(int value) {
earth_ring_angle += 2.0f;
if (earth_ring_angle > 360) {
earth_ring_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(15, earth_update_ring, 0);
}
int main(int argc, char** argv) {
// argc - количество параметров, передаваемых в функцию main
// argv[] - массив указателей на строки
// argc + argv нужны, чтоб заработал glutInit, когда он через командную строку обращается к своей библиотеке glut
//объявляем все наши классы, чтобы использовать их в таймерах
Mercury Me;
Venus Ve;
Earth Ea;
Moon Mo;
Mars Ma;
Fobos Fo;
Deimos De;
Saturn Sa;
Jupiter Ju;
Io Io;
Europa Eu;
Uranus Ur;
Neptune Ne;
Triton Tr;
/*
glutInit(int **argcp, char **argv);
argc - это указатель на еще не измененную переменную argc главной функции программы (main).
argv - это еще не измененная переменная argv главной функции.
glutInit позаботится об инициализации переменных состояния GLUT
и откроет сессию с системой управления окнами.
*/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
/* Выбор режима окна:
Одиночный буфер и RGBA палитра */
glutInitWindowSize(1080, 720);
/* Установка размеров окна */
initGL(); // Очистка цвета
glutCreateWindow("2D Solar System"); // Создание окна
initRendering(); // Рендер с тестом глубины
glutDisplayFunc(sceneDraw); // Отрисовка сцены
glutReshapeFunc(handleResize);
Функция, которая выполняет периодичность выполнения, выполняемая функция, идентификатор таймера
glutTimerFunc(Me.getV(), mercury_update, 0);
glutTimerFunc(Ve.getV(), venus_update, 0);
glutTimerFunc(Ea.getV(), earth_update, 0);
glutTimerFunc(Ea.getV(), earth_update_ring, 0);
glutTimerFunc(Mo.getV(), moon_update, 0);
glutTimerFunc(Ma.getV(), mars_update, 0);
glutTimerFunc(Ma.getV(), mars_update_ring, 0);
glutTimerFunc(Ma.getV(), mars_update_ring2, 0);
glutTimerFunc(Fo.getV(), fobos_update, 0);
glutTimerFunc(De.getV(), deimos_update, 0);
glutTimerFunc(De.getV(), deimos_update2, 0);
glutTimerFunc(Ju.getV(), jupiter_update, 0);
glutTimerFunc(Io.getV(), io_update_ring, 0);
glutTimerFunc(Io.getV(), io_update, 0);
glutTimerFunc(Eu.getV(), europa_update_ring, 0);
glutTimerFunc(Eu.getV(), europa_update, 0);
glutTimerFunc(Eu.getV(), europa_update2, 0);
glutTimerFunc(Sa.getV(), saturn_update, 0);
glutTimerFunc(Sa.getV(), saturn_update_ring, 0);
glutTimerFunc(Ur.getV(), uranus_update, 0);
glutTimerFunc(Ne.getV(), neptune_update, 0);
glutTimerFunc(Ne.getV(), neptune_ring_update, 0);
glutTimerFunc(Tr.getV(), triton_update, 0);
glutMainLoop();//внутри функции бесконечного цикла будет происходить контроль за всеми событиями и вызовами функций
return 0;
}
Заключение
Таким образом, в ходе выполнения курсовой работы была смоделирована солнечная система, в которой Солнце и планеты со своими спутниками располагаются на своих астрономических местах и движутся в правильном соотношении.
Из поставленных задач и целей было выполнено:
-
Построена астрономическая модель солнечной системы; -
Был изучен соответствующий материал и литература; -
Были изучены основные подходы объектно-ориентированного программирования на С++.
В ходе работы, был как негативный опыт, так и позитивный.
Негативный опыт работы заключается в:
-
Увеличение объема программы из-за описания каждой планеты; -
Необходимость вручную устанавливать вручную библиотеку OpenGL.
Позитивный опыт работы заключается в:
-
Уменьшении объема программы при помощи функций, применяемых многократно; -
Упрощение для понимания и корректировки данных для планет при помощи создания классов; -
Отсутствие потребности в больших объемах памяти.
Из практических навыков, которые были получены в процессе выполнения курсовой работы, можно отнести:
-
Навык работы с классами и объектами; -
Навык работы с графической библиотекой OpenGL; -
Навык в построении фигур и их анимации.
Список литературы
1) Бьёрн Страуструп. Программирование: принципы и практика использования C++, исправленное изд.: Перевод с англ. — М.: “Вильямс”, 2011.
2) Герберт Шилдт. Полный справочник по C++, 4-е изд.: Перевод с англ. — М.: “Вильямс”, 2011.
3) Стивен Прата. Язык программирования С++. Лекции и упражнения, 6-е изд.: Перевод с англ. - М.: “Вильямс”, 2017.
4) Скотт Мейерс. Эффективный и современный C++: 42 рекомендации по использованию C++11 и C++14: Пер. с англ. — М.: “Вильямс”, 2016.
5) Гради Буч, Роберт А. Максимчук, Майкл У. Энгл, Бобби Дж. Янг, Джим Коналлен, Келли А. Хьюстон. Объектно-ориентированный анализ и проектирование с примерами приложений. — 3-е изд.: Перевод с англ. — М.: — “Вильямс», 2010.
6) Ю.М.Баяковский, А.В.Игнатенко, А.И.Фролов: Графическая библиотека OpenGL, МГУ , учебно-методическое пособие, 2003.
7) Васильев С. А. “OpenGL : компьютерная графика: учебное пособие”, 2012
8) “Основы OpenGL” книга Игоря Тарасова, учебное пособие
9) Компьютерная графика. Учебник и практикум, 2016. Боресков Алексей Викторович, Шикин Евгений Викторович
10) Никулин, Е. А. .