glRotatef в чистом C

0

У меня проблема с написанием альтернативной функции для glRotatef в чистом 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. без вращающейся передней стороны куба

  2. когда я вращаюсь, он сжимается

После многих звонков функции rotate он сжимается до одной точки.

Что я делаю не так?

  • 1
    Почему бы не использовать GLM? glm.g-truc.net/0.9.6/index.html
  • 0
    GLM отлично, но это C ++. Несмотря на теги, в вопросе написано «чистый С». Возможно, вопрос можно уточнить - является ли C ++ приемлемым или нет?
Показать ещё 1 комментарий
Теги:
opengl
3d
glrotate

2 ответа

0
Лучший ответ

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

float *resultVertexList = current; //temporary help

не копирует список вершин. Вы копируете только указатель на список, поэтому после этого у вас есть два указателя, указывающих на один и тот же список. Из-за этого в следующем цикле используются уже повернутые координаты x/y для вычисления новых координат y/z, что, очевидно, неверно.

Я также задаюсь вопросом о вашем состоянии завершения:

current[i] != 0

Это не так, но это мешает вам иметь любую вершину с нулевой координатой. Вместо этого я бы предложил дополнительный параметр для прямого подсчета количества вершин.

Я бы также вращал per-vertex и не координировал, это просто более естественно и понятнее:

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. Спасибо за вашу поддержку!
0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню