Маятник : Простейшее интегрирование

Используем Метод Эйлера для интегрирования динамическиx уравнений.

Проект программы

Файл CMakeLists.txt:

cmake_minimum_required(VERSION 3.1)

project(simplest
    VERSION 0.1
    LANGUAGES CXX)

find_package(glfw3 REQUIRED)
find_package(OpenGL REQUIRED)
find_package(glm REQUIRED)

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} glfw OpenGL::GL glm)

Код программы

Файл main.cpp:

#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

static GLFWwindow *window   = nullptr;

static double length        = 1.0;
static double radius        = 0.05;
static double angle         = glm::radians(45.0);

static double angleVelosity = 0.0;

static double gravityAcceleration = 9.81;

static double lastTime      = 0.0;
static double currentTime   = 0.0;

void integrate(double delta)
{
    double angleAcceleration = -gravityAcceleration / length * glm::sin(angle);

    angle += angleVelosity * delta;
    angleVelosity += angleAcceleration * delta;
}

void draw()
{
    glLineWidth(1.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    glm::mat4x4 rot = glm::rotate(glm::mat4x4(1.0f)
                                , static_cast<float>(angle)
                                , glm::vec3(0.0f, 0.0f, 1.0f));
    glm::vec4 pos = rot * glm::vec4(0.0f, static_cast<float>(-length), 0.0f, 1.0f);
    glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3fv(glm::value_ptr(pos));
    glEnd();
    glColor3f(1.0f, 0.0f, 0.0f);
    int numSec = 36;
    glm::mat4x4 rotSec = glm::rotate(glm::mat4x4(1.0f)
                                    , glm::radians(360.0f / numSec)
                                    , glm::vec3(0.0f, 0.0f, 1.0f));
    glm::vec4 posLast(static_cast<float>(radius), 0.0f, 0.0f, 1.0f);
    glBegin(GL_TRIANGLES);
    for(int i = 0; i < numSec; ++i)
    {
        glm::vec4 posNext = rotSec * posLast;
        glVertex3fv(glm::value_ptr(pos));
        glVertex3fv(glm::value_ptr(pos + posLast));
        glVertex3fv(glm::value_ptr(pos + posNext));
        posLast = posNext;
    }
    glEnd();
}

void frame()
{
    currentTime = glfwGetTime();

    integrate(currentTime - lastTime);

    lastTime = currentTime;

    glClear(GL_COLOR_BUFFER_BIT);

    draw();

    glfwSwapBuffers(window);

    glfwPollEvents();
}

void draw();

void key(GLFWwindow* window, int key, int scancode, int action, int mods);

int main()
{
    if (!glfwInit())
    {
        return 1;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    window = glfwCreateWindow(600, 600, "Маятник: Графическое представление", nullptr, nullptr);
    if (!window)
    {
        return 2;
    }

    glfwMakeContextCurrent(window);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    lastTime = glfwGetTime();

    while (!glfwWindowShouldClose(window))
    {
        frame();
    }

    glfwTerminate();

    return 0;
}

Запуск программы

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