如何使对象在 Opengl 中沿用户定义的线移动

Posted

技术标签:

【中文标题】如何使对象在 Opengl 中沿用户定义的线移动【英文标题】:How to make an object move along a user-defined line in Opengl 【发布时间】:2016-10-14 14:50:01 【问题描述】:

我的程序允许用户单击窗口上的任意位置,当按下 Enter 时,它会沿着这些点跟踪线。另外,当按下空格键时,它会在第一个点画一个三角形,我希望它沿着整条线移动到最后,然后回到起点,然后重复。

我在起点上进行了线跟踪和绘制三角形,我什至让平移运动开始工作。我唯一的问题是,无论这条线如何,它都会一直在右下角移动。这一定是我的方向,但我不知道出了什么问题。

首先这是我绘制三角形的方法。用户定义的点在名为 controlPoints 的 glm::vec3 变量中定义。所以我在第一个点创建三角形(然后它被传递到 VBO,绑定到 VAO,等等 [triangleVertices 也是一个 glm::vec3 变量]):

        // Lower-left vertex
        triangleVertices.push_back(glm::vec3(controlPoints[0].x - 30.0f, controlPoints[0].y + 30.0f, controlPoints[0].z));

        // Lower-right vertex
        triangleVertices.push_back(glm::vec3(controlPoints[0].x + 30.0f, controlPoints[0].y + 30.0f, controlPoints[0].z));

        // Upper-center vertex
        triangleVertices.push_back(glm::vec3(controlPoints[0].x, controlPoints[0].y, controlPoints[0].z));

        // Bind VAO for the triangle
        glBindVertexArray(VAOTriangle);

        // Bind and implement VBO for the triangle
        glBindBuffer(GL_ARRAY_BUFFER, VBOTriangle);
        glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof(glm::vec3), triangleVertices.data(), GL_STATIC_DRAW);

        // Connecting coordinates to shader
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
        glEnableVertexAttribArray(0);

        // Unbind VAO
        glBindVertexArray(0);

然后在我的游戏循环中,我是这样进行转换的(模型矩阵已经乘以着色器中的位置,对象已经绑定到该位置):

        glBindVertexArray(VAOTriangle);

        float inputX = 0.0;
        float inputY = 0.0;

        GLfloat deltaTime = 0.0f;
        GLfloat lastFrame = 0.0f;
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        GLfloat speed = 5.0f * deltaTime;
        glm::vec2 direction;

        for (int i = 0; i < controlPoints.size(); i++)
        
            inputX = controlPoints[i].x;
            inputY = controlPoints[i].y;
            direction.x = inputX * float((speed * deltaTime) / 1000.0f);
            direction.y = inputY * float((speed * deltaTime) / 1000.0f);

            model_matrix = glm::translate(model_matrix, glm::vec3(direction, 0.0f));    
            glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model_matrix));    
        

        glDrawArrays(GL_TRIANGLES, 0, triangleVertices.size());


        glBindVertexArray(0);

如果我将 glDrawArrays 放在 for 循环中,它会创建与点相同数量的三角形,这不是我想要的(只有 1 个三角形)。但是像这样,它看起来只需要最后一点的方向,因为它在整个循环结束后绘制。但它也没有这样做。就像我说的,它只是右下角(直到它从窗口中消失),无论线条结构如何。

编辑:

这是我关于如何沿线平移对象的新设置。不管我做什么,它仍然会朝着右下方向脱线。

        glBindVertexArray(VAOTriangle);

        // Getting time to define translation speed
        GLfloat deltaTime = 0.0f;
        GLfloat lastFrame = 0.0f;
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
        GLfloat speed = 3.0f * deltaTime;

        // Going through all points of the line
        translationX = controlPoints[translationIndex].x;
        translationY = controlPoints[translationIndex].y;

        if (translationIndex < controlPoints.size() - 1)
        
            translationIndex++;
            translationIndex %= controlPoints.size();
        

        // Update direction vector
        translationDirection.x = translationX * float((speed * deltaTime) / 1000.0f);
        translationDirection.y = translationY * float((speed * deltaTime) / 1000.0f);
        model_matrix = glm::translate(model_matrix, glm::vec3(translationDirection, 0.0f));
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model_matrix));    
        glDrawArrays(GL_TRIANGLES, 0, triangleVertices.size());     
        glBindVertexArray(0);

【问题讨论】:

【参考方案1】:

您正在一次遍历整个 controlPoints 数组,并且只有最后一次调用 glUniformMatrix4fv 很重要。

您应该尝试做的是删除此 for 循环并增加一些值(每个帧或特定步骤),这将替换您的“i”变量。

【讨论】:

所以你说我删除了循环,我做了: 所以你说我删除了循环,在游戏循环之外定义 int i = 0,我这样做: inputX = controlPoints[i].x; inputY = controlPoints[i].y;我 = 我 + 1;如果是这样,程序就会崩溃。 你会限制值吗?它应该在 0 到 controlPoints.size() - 1 的范围内。在递增后尝试使用 i = i % controlPonts.size()。 好的,现在发生了同样的事情(只是移动了左下角),除了三角形 gitters,它更糟。你确定我的其他代码没问题吗? 索引增量多久发生一次?它的运行速度是否与渲染单帧一样快?请记住,这种方式可以运行 200 FPS,因此这意味着您的计数器在几分之一秒内达到最大值。由于您已经在使用时间获取器,请尝试添加一些“冷却时间”,您将检查该 if 条件。

以上是关于如何使对象在 Opengl 中沿用户定义的线移动的主要内容,如果未能解决你的问题,请参考以下文章

在 3d 中沿贝塞尔路径移动对象:旋转问题

在 Unity 中沿其移动方向旋转对象

在 Unity 中沿光线投射实例化预定义数量的对象

在OpenGL中使对象跟随相机

在多维数组java中沿方向移动数字

OpenGL:移动相机时如何使光线静止?