OpenGL Перемещение полигонов по экрану - PullRequest
0 голосов
/ 31 октября 2018

У меня есть 2 многоугольника с обеих сторон экрана, которые вращаются по кругу. Я пытаюсь сделать так, чтобы оба этих многоугольника двигались вдоль оси x, когда они вращаются, и в итоге они будут пересекаться в середине, но я не уверен, как это сделать.

glm::mat4 model_view = glm::scale(glm::mat4(1.0), glm::vec3(0.2, 0.2, 0.8));
model_view = glm::translate(model_view, glm::vec3(-3.0, 0.0, 0.0));
model_view = glm::rotate(model_view, 5*rotate_value, glm::vec3(0.0f, 0.0, 1.0f));

glUniformMatrix4fv(location, 1, GL_FALSE, &model_view[0][0]);

glDrawArrays(GL_POLYGON, 0, NumVertices);

//Object 2
glm::mat4 model_view2 = glm::scale(glm::mat4(1.0), glm::vec3(0.2, 0.2, 0.8));
model_view2 = glm::translate(model_view2, glm::vec3(2.0, 0.0, 0.0));
model_view2 = glm::rotate(model_view2, 5 * rotate_value, glm::vec3(0.0, 0.0, -1.0f));

glUniformMatrix4fv(location, 1, GL_FALSE, &model_view2[0][0]);

//Starting the pipeline
glDrawArrays(GL_POLYGON, 0, NumVertices);

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Я пытаюсь сделать так, чтобы оба этих многоугольника двигались вдоль оси х, когда они вращаются, и в итоге они будут пересекаться в середине, но я не уверен, как это сделать.

Для этого вам необходимо рассчитать вращение и перемещение в зависимости от времени. Угол поворота и вектор перемещения являются функцией времени.

Для этого необходимо знать период времени, прошедший с начала анимации, в каждый момент времени, когда отображается сцена.
Одна из возможностей для расчета пройденного времени - использовать std::chrono::high_resolution_clock. Сохраните текущий момент времени в начале анимации. Рассчитайте разницу двух временных точек в каждом кадре, чтобы получить прошедший период времени.

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

#include <chrono>

std::chrono::high_resolution_clock::time_point start_time =
    std::chrono::high_resolution_clock::now();

std::chrono::high_resolution_clock::time_point current_time =
    std::chrono::high_resolution_clock::now();
auto delta_time = current_time - start_time;
double time_s = 
    (double)std::chrono::duration_cast<std::chrono::milliseconds>(delta_time).count() / 1000.0;

Чтобы вычислить угол в зависимости от времени, вы должны определить число оборотов в секунду. Разделите период времени на количество секунд и умножьте результат на 360 для градусов соответственно 2*PI для радиан:

float rot_per_s = 10.0f; // 10 full rotations per second
float angle_deg = (float)(360.0 * time_s / rot_per_s);

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

double    motiontime_s = 5.0f;  // from start to end and back in 5 seconds
glm::vec3 start_pt1    = .....; // start point of the movement
glm::vec3 end_pt1      = .....; // end point of the movement

double times;
double pos_rel   = modf(time_s / motiontime_s, &times);
float  w         = pos_rel < 0.5 ? (float)pos_rel * 2.0f : (float)(1.0 - pos_rel) * 2.0f;
glm::vec3 trans1 = start_pt1 * (w-1.0f) + end_pt1*w;

С помощью угла и вектора переноса можно рассчитать матрицы моделей для объектов и нарисовать сцену:

float rot_per_s = 1.0f/5.0f; // 1 full rotations in 5 second
float angle_deg = (float)(360.0 * time_s * rot_per_s);

double    motiontime_s = 5.0f; // from start to end and back in 5 seconds
glm::vec3 start_pt1    = .....;
glm::vec3 end_pt1      = .....;

double times;
double pos_rel   = modf(time_s / motiontime_s, &times);
float  w         = pos_rel < 0.5 ? (float)pos_rel * 2.0f : (float)(1.0 - pos_rel) * 2.0f;
glm::vec3 trans1 = start_pt1 * (w-1.0f) + end_pt1*w;

glm::vec3 start_pt2 = glm::vec3(  1.0f, 0.0f, 0.0f );
glm::vec3 end_pt2   = glm::vec3(  0.0f, 0.0f, 0.0f );
glm::vec3 trans2    = start_pt2 * (w-1.0f) + end_pt2*w;

glm::mat4 model1( 1.0f );
model1 = glm::translate( model1, trans1 );
model1 = glm::rotate( model1, glm::radians(angle_deg), glm::vec3(0.0f, 0.0f, 1.0f) );
model1 = glm::scale( model1, glm::vec3(....) );

glm::mat4 model2( 1.0f );
model2 = glm::translate( model2, trans2 );
model2 = glm::rotate( model2, glm::radians(-angle_deg), glm::vec3(0.0f, 0.0f, 1.0f) );
model2 = glm::scale( model2, glm::vec3(....) );

// Object 1
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(model1));
glDrawArrays(GL_POLYGON, 0, NumVertices);

// Object 2
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(model2));
glDrawArrays(GL_POLYGON, 0, NumVertices);

Результат может выглядеть так:

0 голосов
/ 31 октября 2018

Скажем, у вас есть объект, центр которого C{cx, cy}. Вы хотите нарисовать этот объект повернутым и переведенным в другую точку. Итак, у вас есть два преобразования: вращение и перевод.

Дело в том, что эти преобразования НЕ коммутативны. Заказ имеет значение.

Вращение (2D, для простоты) вокруг точки зависит от того, где находится объект относительно точки. Земля вращается вокруг Солнца, но также и вокруг себя. Результат для каждого поворота различен.

Если вы хотите, чтобы ваш многоугольник вращался вокруг своего центра (опять же, для простоты понимания), вам нужно:

  1. Переведите многоугольник в центр вращения, это C{cx,cy}.
  2. Затем поверните его.
  3. Затем переведите в точку, в которой это было до шага 1, или в новую точку, которую вы хотите (вдоль оси X в вашем случае).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...