【问题标题】:glRotatef in pure C纯 C 中的 glRotatef
【发布时间】:2015-01-04 17:07:59
【问题描述】:

我在用纯 C 语言编写 glRotatef 的替代函数时遇到问题。我需要实现参数为:点列表、角度和旋转向量的函数。函数必须在旋转后返回点列表。我的函数如下所示:

void rotate(float * current, float a, float x, float y, float z)
{
    float sina = sinf(a);
    float cosa = cosf(a);
    float rotateMatrix[9] = //creating rotate matrix
    {
        x*x*(1-cosa) + cosa,    x*y*(1-cosa) - z*sina,  x*z*(1-cosa) + y*sina,
        y*x*(1-cosa) + z*sina,  y*y*(1-cosa) + cosa,    y*z*(1-cosa) - x*sina,
        z*x*(1-cosa) - y*sina,  z*y*(1-cosa) + x*sina,  z*z*(1-cosa) + cosa
    };
    float *resultVertexList = current; //temporary help
    int i;
    for(i=0;current[i] != 0;i++) //multiplying CURRENT_MATRIX * ROTATE_MATRIX
    {
        int currentVertex = (i/3) * 3;
        int rotateColumn = i%3;
        resultVertexList[i] =
        current[currentVertex] * rotateMatrix[rotateColumn] +
        current[currentVertex+1] * rotateMatrix[rotateColumn+3] +
        current[currentVertex+2] * rotateMatrix[rotateColumn+6];
    }
    current = resultVertexList;
}

我在这里这样称呼它:rotate(current, M_PI/10, 0, 1, 0);

之后,我获取current 点列表,然后使用openGL 简单地绘制它们。为了测试,我尝试旋转代表立方体的点列表。它会旋转,但每次调用rotate 函数都会缩小。我不知道为什么。看一些截图:

  1. without any rotating, front side of cube

  2. when I rotate it shrinks

在多次调用rotate 函数后,它会缩小到一个点。

我做错了什么?

【问题讨论】:

  • 为什么不使用 glm ? glm.g-truc.net/0.9.6/index.html
  • glm 很棒,但它是 C++。尽管有标签,但问题是“纯 C”。也许这个问题可以澄清——C++ 是否可以接受?
  • 纯C,我现在得用x86汇编写这个函数

标签: c++ c opengl 3d glrotate


【解决方案1】:

这行代码:

float *resultVertexList = current; //temporary help

不复制您的顶点列表。您只是将指针复制到列表中,因此在此之后您有两个指向同一个列表的指针。因此,下面的循环使用已经旋转的 x/y 坐标来计算新的 y/z 坐标,这显然是错误的。

我也想知道你的终止条件:

current[i] != 0

这没有错,但它可以防止您拥有任何零坐标的顶点。相反,我建议使用一个额外的参数来显式传递顶点数。

我也会按顶点而不是按坐标旋转,这更自然且更容易理解:

void rotate(float * current, int vertexCount, float a, float x, float y, float z)
{
    float sina = sinf(a);
    float cosa = cosf(a);
    float rotateMatrix[9] =
    {
        x*x*(1 - cosa) + cosa, x*y*(1 - cosa) - z*sina, x*z*(1 - cosa) + y*sina,
        y*x*(1 - cosa) + z*sina, y*y*(1 - cosa) + cosa, y*z*(1 - cosa) - x*sina,
        z*x*(1 - cosa) - y*sina, z*y*(1 - cosa) + x*sina, z*z*(1 - cosa) + cosa
    };

    int i;
    for (i = 0; i < vertexCount; ++i)
    {
        float* vertex = current + i * 3;

        float x = rotateMatrix[0] * vertex[0] + rotateMatrix[1] * vertex[1] + rotateMatrix[2] * vertex[2];
        float y = rotateMatrix[3] * vertex[0] + rotateMatrix[4] * vertex[1] + rotateMatrix[5] * vertex[2];
        float z = rotateMatrix[6] * vertex[0] + rotateMatrix[7] * vertex[1] + rotateMatrix[8] * vertex[2];

        vertex[0] = x;
        vertex[1] = y;
        vertex[2] = z;
    }
}

【讨论】:

  • 谢谢!我看到了我的错误。不幸的是,在我的项目中,我无法通过 vertexCount,这就是为什么我做了一些奇怪的事情,例如:current[i] != 0。感谢您的支持!
【解决方案2】:

您实现矩阵向量乘法的方式非常粗糙,而且 - 更重要的是 - 完全是错误的。

问题是你覆盖了你仍然需要的数据。因此,在第一次交互中,您有效地写入current[0] (而您的resultVertexList 指针根本没有帮助。它指向您唯一的数据icopy,直接就地覆盖它。在下一个两次迭代,将使用 current[0] 的新值,而不是原来的值。

我建议你简单地实现一个简单的mat3 * vec3 函数,它可以很容易地在循环中调用,并且注意不覆盖它仍然需要的数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多