2015-10-09 2 views
0

Я пытаюсь запрограммировать простую анимацию с использованием GLUT и OpenGL в C++. Для этой цели я создал три функции: catSpline(), fillArray() и fixedAngle(). catSpline() возвращает значение GLfloat, fillArray() - это функция пустот, которая состоит из серии циклов, которая заполняет ряд массивов значениями GLfloat, создаваемыми с использованием catSpline, и fixedAngle() вернет массив из 16 элементов. Вот код для этих трех методов:Проблемы с вызовом функции, которая возвращает массив

GLfloat * fixedAngle(GLfloat initialX, GLfloat initialY, GLfloat initialZ, GLfloat rotX, GLfloat rotY, GLfloat rotZ) 

{ 
     ArrayXXf z(4,4); //initializing the 4x4 rotation matrixes 
     ArrayXXf y(4,4); 
     ArrayXXf x(4,4); 

     x<<1, 0, 0, 0, 
      0, cos(rotX), -sin(rotX), 0, 
      0, sin(rotX), cos(rotX), 0, 
      0, 0, 0, 1; 

     y<<cos(rotY), 0, sin(rotY), 0, 
      0, 1, 0, 0, 
      -sin(rotY), 0, cos(rotY), 0, 
      0, 0, 0, 1; 

     z<< cos(rotZ), -sin(rotZ), 0, 0, 
      sin(rotZ), cos(rotZ), 0, 0, 
      0, 0, 1, 0, 
      0, 0, 0, 1; 



     ArrayXXf fin(4,4); 

     fin = x * y * z; 

     fin(0,3) = initialX; 
     fin(1,3) = initialY; 
     fin(2,3) = initialZ; 
     //now we've moved the translational information into the final matrix 
    // std::cout << fin; 

    fin(3,3) = 1; 

    GLfloat * arr; 
    arr = (GLfloat *) malloc(16*sizeof(GLfloat)); 

      arr[0] = fin(0,0); 
     arr[1] = fin(0,1); 
     arr[2] = fin(0,2); 
     arr[3] = fin(0,3); 
     arr[4] = fin(1,0); 
     arr[5] = fin(1,1); 
      arr[6] = fin(1,2); 
     arr[7] = fin(1,3); 
          arr[8] = fin(2,0); 
          arr[9] = fin(2,1); 
          arr[10] = fin(2,2); 
          arr[11] = fin(2,3); 
          arr[12] = fin(3,0); 
          arr[13] = fin(3,1); 
          arr[14] = fin(3,2); 
          arr[15] = fin(3,3); 


     return arr; 

} 

GLfloat catSpline(GLfloat x1, GLfloat x2, GLfloat x3, GLfloat x4, GLfloat t) 
{ 
    ArrayXXf M(4,4); //4x4 M matrix 
    ArrayXXf P(4,1); //matrix to hold keyframe x values 

    P(0,0) = x1; 
    P(1,0) = x2; 
    P(2,0) = x3; 
    P(3,0) = x4; 
    //keyframe x values 

    M(0,0) = -0.5; 
    M(0,1) = 2-(-0.5); 
    M(0,2) = -0.5-2; 
    M(0,3) = 0.5; 

    M(1,0) = 2*0.5; 
    M(1,1) = 0.5-3; 
    M(1,2) = 3-(2*0.5); 
    M(1,3) = -0.5; 

    M(2,0) = -0.5; 
    M(2,1) = 0; 
    M(2,2) = 0.5; 
    M(2,3) = 0; 

    M(3,0) = 0; 
    M(3,1) = 1; 
    M(3,2)=0; 
    M(3,3)=0; 

     ArrayXXf T(1,4); 



     T(0,0) = t*t*t; //you can't cube a float, but you can get the same result by doing this 
     T(0,1) = t*t; 
     T(0,2) = t; 
     T(0,3)=1; 
     //now the T matrix is filled 
     ArrayXXf TM(1,4); 

     TM(0,0) = (T(0,0) * M(0,0)) + (T(0,1) * M(1,0)) + (T(0,2) * M(2,0)) + (T(0,3) * M(0,3)); 
     TM(0,1) = (T(0,0) * M(0,1)) + (T(0,1) * M(1,1)) + (T(0,2) * M(2,1)) + (T(0,3) * M(3,1)); 
     TM(0,2) = (T(0,0) * M(0,2)) + (T(0,1) * M(1,2)) + (T(0,2) * M(2,2)) + (T(0,3) * M(3,2)); 
     TM(0,3) = (T(0,0) * M(0,3)) + (T(0,1) * M(1,3)) + (T(0,2) * M(2,3)) + (T(0,3) * M(3,3)); 
     //first multiply T amd M 




     GLfloat TMP; 

     TMP = (TM(0,0) * P(0,0)) + (TM(0,1) *P(1,0)) + (TM(0,2) * P(2,0)) + (TM(0,3) * P(3,0)); 



     return TMP; 
} 


void fillArrays() 
{ 


    /* zRot = catSpline(2, 4, 5, 6); 
     yRot = catSpline(1, 4, 6, 7); 
     xRot = catSpline(6, 3, 2, 6); 

     xArr = catSpline(9, 4, 3, 10); 
     yArr = catSpline(1, 2, 4, 8); 
     zArr = catSpline(8, 3, 1, 3);*/ 

    for(int j=0; j>=100; j++) 
    { 
     xArr[j] = catSpline(2, 4, 5, 6, t); 
     t+=0.1; 
    } 
    for(int i=0; i>=100; i++) 
    { 
     yArr[i] = catSpline(2, 4, 5, 6, ty); 
     ty+=0.1; 
    } 
    for(int k=0; k>=100; k++) 
    { 
     xArr[k] = catSpline(2, 4, 5, 6, tz); 
     tz += 0.1; 
    } 

    for(int a=0; a>=100; a++) 
    { 
     xRot[a] = catSpline(2, 4, 5, 6, rx); 
     rx += 0.1; 
    } 

    for(int b=0; b>=100; b++) 
    { 
     yRot[b] = catSpline(2, 4, 5, 6, ry); 
     rz += 0.1; 
    } 

    for(int c=0; c>=100; c++) 
    { 
     zRot[c] = catSpline(2, 4, 5, 6, rz); 
     rz += 0.1; 
    } 


} 

Путь я использую эти три функции в цикле называется Рендер, настроить OpenGL для отображения анимации модели чайника, вызовите fillArrays(), а затем пытаться сохраните результат одного вызова fixedAngle (используя несколько записей из массивов, заполненных непосредственно перед этим) в новом массиве с именем foo. Это, по-видимому, является причиной ошибок, причем foo содержит только адрес указателя, а не указывает на фактический массив, поэтому я могу его использовать. Это код, я использую, чтобы вызвать эти функции:

fillArrays(); 

    GLfloat * foo; 
    foo = (GLfloat *) malloc(16*sizeof(GLfloat)); 

    foo = fixedAngle(xArr[tp], yArr[tp], zArr[tp], xRot[tp], yRot[tp], zRot[tp]); 

    glLoadMatrixf(foo); 

После использования нескольких операторов печати, чтобы распечатать результаты своих функций, я знаю, что эта проблема должна быть, как настроить указатели где-то , Может ли кто-нибудь помочь мне правильно вернуть массив?

Обратите внимание: если какой-либо синтаксис матрицы кажется не знакомым, это потому, что я использую библиотеку C++, называемую Eigen, для выполнения некоторой математической матрицы. Еще раз, после тщательного изложения результатов функций, я знаю, что функции, которые используют синтаксис Eigen, производят правильные значения.

+2

Вы не указали достаточно информации, чтобы даже попытаться воспроизвести проблему, о которой вы сообщаете. Случайные фрагменты кода очень сложны для анализа. –

+3

Мне кажется, что мне кажется странным, что вы выделяете память для 'foo', а затем ** сразу ** назначили другую выделенную память' foo'. Это наверняка будет утечкой памяти в один прекрасный день. Скорее всего, это не причина вашей ошибки. –

+0

Знаете ли вы, как я могу это исправить? –

ответ

1

Вы можете заменить ...

GLfloat * arr; 
arr = (GLfloat *) malloc(16*sizeof(GLfloat)); 

... с ...

std::vector<GLfloat> arr(16); 

... или даже непосредственно инициализирует его вместо копирования элементов после ...

std::vector<GLfloat> arr { fin(0,0), fin(0,1), fin(0,2), fin(0,3), 
          fin(1,0), fin(1,1), fin(1,2), fin(1,3), 
          fin(2,0), fin(2,1), fin(2,2), fin(2,3), 
          fin(3,0), fin(3,1), fin(3,2), fin(3,3) }; 

... который - FWIW - тоже можно сделать подобный ...

std::vector<GLfloat> arr; 
for (int a = 0; a <= 3; ++a) 
    for (int b = 0; b <= 3; ++b) 
     arr.push_back(fin(a,b)); 

С любым из вышеперечисленных, вам необходимо изменить тип возвращаемого соответственно ...

std::vector<GLfloat> fixedAngle(
    GLfloat initialX, GLfloat initialY, GLfloat initialZ, 
    GLfloat rotX, GLfloat rotY, GLfloat rotZ) 
{ 
    ... 

... то вы можете позвонить fixedAngle и использовать foo как это:

fillArrays(); 
std::vector<GLfloat> foo = fixedAngle(xArr[tp], yArr[tp], zArr[tp], 
            xRot[tp], yRot[tp], zRot[tp]); 
glLoadMatrixf(foo.data()); // or `&foo[0]` if you prefer... 
+0

Я просто хочу знать, как мне изменить тип возврата. (Я все еще новичок в C++). –

+1

@ Maria-Andersado: если вы «просто» хотите изменить тип возврата, вы в тупике: ваша функция уже использует «GLfloat *» для обращения к памяти «malloc» и имеет правильный тип возврата для возврата к вызывающему коду. Таким образом, изменение «только» типа возврата будет препятствовать компиляции вашей программы (если вы не сделаете бесполезное изменение как 'void *'). (Мой ответ пытается показать вам способ избежать указателей, чтобы вы могли продуктивно писать надежный код, несмотря на то, что были новичком на C++, и избегать явного распределения памяти на уровне приложения считается наилучшей практикой даже для экспертов C++ ....) –

+0

Нет, просто вы сказали, что использование ваших рекомендуемых решений потребует от меня изменить тип возврата. Я все еще изучаю синтаксис C++ и хотел узнать, как я могу изменить тип возвращаемого значения, чтобы он соответствовал чему-то вроде std :: vector

Смежные вопросы