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:
After many callings of rotate
function it shrinks to one point.
What am I doing wrong?
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;
}
}