glRotatef in pure C

446 Views Asked by At

I have a problem with writing an alternative function for glRotatef in pure C. I need to implement function which arguments are: list of points, angle and rotate vector. Function must return list of points after rotation. My function looks like this:

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;
}

I'm calling it like here: rotate(current, M_PI/10, 0, 1, 0);

After that, I take current list of points and simply draw them with openGL. For testing I tried to rotate list of points representing cube. It rotates, but with every one call of rotate function it shrinks. I have no idea why. See some screenshots:

  1. without any rotating, front side of cube

  2. when I rotate it shrinks

After many callings of rotate function it shrinks to one point.

What am I doing wrong?

2

There are 2 best solutions below

1
On BEST ANSWER

This line of code:

float *resultVertexList = current; //temporary help

does not copy your vertex list. You are only copying the pointer to the list, so after this you have two pointers pointing to the same list. Because of that, the following loop uses already rotated x/y coordinates for calculating the new y/z coordinates, which is obviously wrong.

I'm also wondering about your termination condition:

current[i] != 0

It's not wrong, but it prevents you from having any vertex with a zero coordinate. Instead, I'd suggest an additional parameter for passing the vertex count explicitly.

I would also rotate per-vertex and not per-coordinate, it's simply more natural and easier to understand:

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;
    }
}
0
On

The way you implement the matrix-vector-mulitplication is very crude and - more importantly - just wrong.

The problem is that you overwrite the data you still need. So in the very fisrt interation, you effectively write to current[0] (and your resultVertexList pointer is no help at all. It is pointing at your one and only icopy of the data, directly overwriting it in-place. In the next two iterations, the new value for current[0] will be used, instead of the original one.

I suggest that you simply implement a straight-forward mat3 * vec3 function which can easily be called in a loop, and which takes care about not overwriting the data it still needs.