2015-01-04 3 views
0

У меня проблема с написанием альтернативной функции для glRotatef в чистом C. Мне нужно реализовать функцию, аргументы которой: список точек, угол и поворот вектора. Функция должна возвращать список точек после вращения. Моя функция выглядит следующим образом:glRotatef in pure C

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 функции она стягивается в одну точку.

Что я делаю неправильно?

+1

Почему бы не использовать glm? http://glm.g-truc.net/0.9.6/index.html – Ryp

+0

glm отлично, но это C++. Несмотря на теги, вопрос говорит «чистый C». Возможно, вопрос может быть выяснен - ​​приемлемо ли C++ или нет? – Justin

+0

чистый C, мне нужно написать эту функцию в сборке x86 сейчас – devPash

ответ

0

Эта строка кода:

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

Спасибо! Я вижу свою ошибку.В моем проекте я не могу передать vertexCount, к сожалению, поэтому я сделал немного странную вещь: current [i]! = 0. Спасибо за вашу поддержку! – devPash

0

То, как вы реализуете матрица-вектор-mulitplication очень сырой и - что более важно - просто неправильно.

Проблема в том, что вы перезаписываете данные, которые вам по-прежнему нужны. Таким образом, в самом начале взаимодействия вы фактически пишете current[0] (и ваш указатель resultVertexList вообще не помогает. Он указывает на вашу единственную икопию данных, непосредственно переписывая ее на месте. В следующих двух итерациях новое значение для current[0] будет использоваться вместо исходного.

Я предлагаю вам просто реализовать прямолинейную функцию mat3 * vec3, которую можно легко вызывать в цикле и которая заботится о том, чтобы не перезаписывать данные, которые она по-прежнему