OpenGL在屏幕上移动多边形

时间:2018-10-31 19:19:58

标签: c++ opengl

我在屏幕的任一侧都有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 :(得分:1)

  

我要做的是让这两个多边形在旋转时都沿x轴移动,因此最终它们将在中间重叠,但是我不确定如何做到这一点。

为此,您必须根据时间计算旋转和平移。旋转角度和平移矢量是时间的函数。

为此,您必须知道自动画开始以来在渲染场景的每个时间点过去的时间。
计算通过时间的一种可能性是使用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);

结果可能看起来像这样:

答案 1 :(得分:0)

假设您有一个对象为C{cx, cy}。您想要绘制旋转并平移到另一点的对象。因此,您有两种转换:旋转和平移。

重点是那些转换不是可交换的。订单很重要。

围绕点旋转(为简便起见,为2D)取决于对象相对于该点的位置。地球围绕太阳旋转,但也围绕自身旋转。每次旋转的结果都不同。

如果您想让多边形围绕其中心旋转(同样,为了简单理解),那么您需要:

  1. 将多边形平移到旋转中心,即C{cx,cy}
  2. 然后旋转它。
  3. 然后平移到步骤1之前的位置,或平移到所需的新点(在您的情况下沿X轴)。
相关问题