Начнем, как в задачнике по физике. Пусть тело массой 2 кг брошено с высоты 2 м со скоростью 35 м/с. На тело действует сила тяжести, с ускорением, равным 1 м/с'^2^' (ускорение пришлось сильно уменьшить, по сравнению с реальным 9,81 м/с'^2^', чтобы тело пролетело подольше). Посмотрим, как это будет выглядеть на экране.
Для определенности будем считать, что в задаче речь идет о мяче. Наш мяч — это частица, поэтому класс Ball
, отвечающий за его описание, включает в себя объект класса Particle
.
class Ball : public Application
{
Particle particle;
void render();
public:
Ball();
virtual const char* getTitle() { return "Ball"; }
virtual void update();
virtual void display();
};
Разберем подробнее методы этого класса. В конструкторе задаются масса, начальные координаты и скорость мяча, а также прочие его свойства. Кроме того, в нем перед началом расчетов обнуляется вектор сил, действующих на тело. Сила тяжести в данном примере описывается через действующее на мяч ускорение.
Ball::Ball()
{
// Задаем свойства частицы
particle.setMass(2.0); // 2.0 кг
particle.setVelocity(0.0, 0.0, 35.0); // 35 м/с
particle.setAcceleration(0.0, -1.0, 0.0);
particle.setDamping(0.99);
particle.setPosition(0.0, 2.0, 0.0);
// Обнуляем действующие силы
particle.clearAccumulator();
}
В методе update()
рассчитываются новые значения координат и скорости мяча, а также проверяется, не вышел ли он за границы сцены.
void Ball::update()
{
// Находим длительность последнего кадра, в секундах
float duration = (float)TimingData::get().lastFrameDuration * 0.001f;
if (duration <= 0.0f) return;
// Вычисляем состояние частицы спустя duration
particle.integrate(duration);
// Проверяем, не вышла ли частица за пределы сцены
if (particle.getPosition().y < 0.0f || particle.getPosition().z > 200.0f) {
return;
}
Application::update();
}
Шаг расчетов по времени duration
определяется на основе длительности последнего кадра. Позднее мы еще вернемся к этому вопросу.
Метод display()
непосредственно строит изображение. Через каждые 10 метров мы нарисуем линии, чтобы было видно, насколько далеко улетел мяч.
void Ball::display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(-25.0, 8.0, 5.0, 0.0, 5.0, 22.0, 0.0, 1.0, 0.0);
// Рисуем линии для контроля дальности выстрела
glColor3f(0.75f, 0.75f, 0.75f);
glBegin(GL_LINES);
for (unsigned i = 0; i < 200; i += 10) {
glVertex3f(-5.0f, 0.0f, i);
glVertex3f(5.0f, 0.0f, i);
}
glEnd();
render();
}
Метод render()
рисует положение частицы.
void Ball::render()
{
Vector3 position;
particle.getPosition(&position);
// Рисуем частицу
glColor3f(0, 0, 0);
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
glutSolidSphere(0.3f, 5, 4);
glPopMatrix();
// Рисуем тень частицы
glColor3f(0.75, 0.75, 0.75);
glPushMatrix();
glTranslatef(position.x, 0, position.z);
glScalef(1.0f, 0.1f, 1.0f);
glutSolidSphere(0.6f, 5, 4);
glPopMatrix();
}
Нам еще нужно не забыть функцию, создающую объект класса Ball
в функции main()
:
Application* getApplication()
{
return new Ball();
}
Файл main.cpp
также подвергся изменениям: в него пришлось добавить вызовы функций, контролирующих время расчетов.
#include ...
#include "engine/timing.h" // подключаем функции-таймеры
...
void update()
{
// Обновить значение счетчика времени
TimingData::get().update();
app->update();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
TimingData::init();
// #1: Инициализация и создание окна GLUT
app = getApplication();
createWindow(app->getTitle());
app->initGraphics();
// #2: Регистрация функций-обработчиков событий
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(update);
// #3: Запуск основного цикла GLUT
glutMainLoop();
// Очистка ресурсов
TimingData::deinit();
}
В результате получим:
След от приземлившегося мяча можно увидеть на восьмой от левого края линии. Значит мяч пролетел 70 метров.
Проверим полученный результат. Сначала найдем время полета t
из соотношения
высота_конечная = высота_начальная - g * t^2 / 2
(g
— ускорение свободного падения). Высота в конце полета равна нулю, а значит время полета составило t = 2
с.
Дальность полета равна:
Дальность полета = скорость * t
.
Отсюда находим, что дальность полета равна 70 м, как и получилось при моделировании.
Комментарии
comments powered by Disqus