我特别需要手动将存储的 openGL 矩阵应用于顶点。我承认在矩阵数学方面有一个弱点,但我已经阅读了我能找到的所有文档,并且我有理由确定我这样做是正确的,但我得到了一个意想不到的结果。我错过了什么?
(请注意,这可能是一个数学问题,但我怀疑我实际上误解了如何应用翻译矩阵,所以我想我会在这里尝试)
在下面的代码片段中,#1 工作正常,#2 失败......
float x=1;
float y=1;
float z=1;
float w=1;
float x2=0;
float y2=0;
float z2=0;
float w2=1;
// 1 THIS WORKS:
glLoadIdentity();
// Convert from NSArray to C float
float modelMatrix[16];
for(int x=0;x<16;x++){modelMatrix[x]=[[cs.modelView objectAtIndex:x] floatValue];}
// Load the matrix the openGL way
glLoadMatrixf(modelMatrix);
// Custom function takes two coordinates and draws a box
[self drawBoxFromX:x FromY:y FromZ:z ToX:x2 ToY:y2 ToZ:z2];
//2 THIS DOES NOT WORK: Apply the matrix by hand
glLoadIdentity();
float new_x = (x*modelMatrix[0])+(y*modelMatrix[4])+(z*modelMatrix[8])+(w*modelMatrix[12]);
float new_y = (x*modelMatrix[1])+(y*modelMatrix[5])+(z*modelMatrix[9])+(w*modelMatrix[13]);
float new_z = (x*modelMatrix[2])+(y*modelMatrix[6])+(z*modelMatrix[10])+(w*modelMatrix[14]);
float new_x2 = (x2*modelMatrix[0])+(y2*modelMatrix[4])+(z2*modelMatrix[8])+(w2*modelMatrix[12]);
float new_y2 = (x2*modelMatrix[1])+(y2*modelMatrix[5])+(z2*modelMatrix[9])+(w2*modelMatrix[13]);
float new_z2 = (x2*modelMatrix[2])+(y2*modelMatrix[6])+(z2*modelMatrix[10])+(w2*modelMatrix[14]);
// Should draw a box identical to above, but gives strange result)
[self drawBoxFromX:new_x FromY:new_y FromZ:new_z ToX:new_x2 ToY:new_y2 ToZ:new_z2];
更新:
根据下面的有用评论,我意识到我只旋转了两个顶点,而不是立方体的全部 8 个。以下代码按预期工作,在这里发布给遇到类似问题的任何人,他们围绕 3d/opengl 的东西。(注意:如果不明显,这不是生产代码。有许多更有效且更少手动的方法乘以矩阵和描述立方体(见注释)。这段代码的目的只是为了明确地说明一种行为。)
struct Cube myCube;
myCube.a1.x=-1;
myCube.a1.y=-1;
myCube.a1.z=-1;
myCube.b1.x=-1;
myCube.b1.y=-1;
myCube.b1.z=1;
myCube.c1.x=1;
myCube.c1.y=-1;
myCube.c1.z=1;
myCube.d1.x=1;
myCube.d1.y=-1;
myCube.d1.z=-1;
myCube.a2.x=-1;
myCube.a2.y=1;
myCube.a2.z=-1;
myCube.b2.x=-1;
myCube.b2.y=1;
myCube.b2.z=1;
myCube.c2.x=1;
myCube.c2.y=1;
myCube.c2.z=1;
myCube.d2.x=1;
myCube.d2.y=1;
myCube.d2.z=-1;
//1 Load modelview and draw a box (this works fine)
glLoadIdentity();
float modelMatrix[16];
for(int x=0;x<16;x++){modelMatrix[x]=[[cs.modelView objectAtIndex:x] floatValue];}
glLoadMatrixf(modelMatrix);
[self drawCube:myCube];
//2 Load the matrix by hand (identical to above)
glLoadIdentity();
float w=1;
float new_Ax = (myCube.a1.x*modelMatrix[0])+(myCube.a1.y*modelMatrix[4])+(myCube.a1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Ay = (myCube.a1.x*modelMatrix[1])+(myCube.a1.y*modelMatrix[5])+(myCube.a1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Az = (myCube.a1.x*modelMatrix[2])+(myCube.a1.y*modelMatrix[6])+(myCube.a1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Bx = (myCube.b1.x*modelMatrix[0])+(myCube.b1.y*modelMatrix[4])+(myCube.b1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_By = (myCube.b1.x*modelMatrix[1])+(myCube.b1.y*modelMatrix[5])+(myCube.b1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Bz = (myCube.b1.x*modelMatrix[2])+(myCube.b1.y*modelMatrix[6])+(myCube.b1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Cx = (myCube.c1.x*modelMatrix[0])+(myCube.c1.y*modelMatrix[4])+(myCube.c1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Cy = (myCube.c1.x*modelMatrix[1])+(myCube.c1.y*modelMatrix[5])+(myCube.c1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Cz = (myCube.c1.x*modelMatrix[2])+(myCube.c1.y*modelMatrix[6])+(myCube.c1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Dx = (myCube.d1.x*modelMatrix[0])+(myCube.d1.y*modelMatrix[4])+(myCube.d1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Dy = (myCube.d1.x*modelMatrix[1])+(myCube.d1.y*modelMatrix[5])+(myCube.d1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Dz = (myCube.d1.x*modelMatrix[2])+(myCube.d1.y*modelMatrix[6])+(myCube.d1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_A2x = (myCube.a2.x*modelMatrix[0])+(myCube.a2.y*modelMatrix[4])+(myCube.a2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_A2y = (myCube.a2.x*modelMatrix[1])+(myCube.a2.y*modelMatrix[5])+(myCube.a2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_A2z = (myCube.a2.x*modelMatrix[2])+(myCube.a2.y*modelMatrix[6])+(myCube.a2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_B2x = (myCube.b2.x*modelMatrix[0])+(myCube.b2.y*modelMatrix[4])+(myCube.b2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_B2y = (myCube.b2.x*modelMatrix[1])+(myCube.b2.y*modelMatrix[5])+(myCube.b2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_B2z = (myCube.b2.x*modelMatrix[2])+(myCube.b2.y*modelMatrix[6])+(myCube.b2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_C2x = (myCube.c2.x*modelMatrix[0])+(myCube.c2.y*modelMatrix[4])+(myCube.c2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_C2y = (myCube.c2.x*modelMatrix[1])+(myCube.c2.y*modelMatrix[5])+(myCube.c2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_C2z = (myCube.c2.x*modelMatrix[2])+(myCube.c2.y*modelMatrix[6])+(myCube.c2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_D2x = (myCube.d2.x*modelMatrix[0])+(myCube.d2.y*modelMatrix[4])+(myCube.d2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_D2y = (myCube.d2.x*modelMatrix[1])+(myCube.d2.y*modelMatrix[5])+(myCube.d2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_D2z = (myCube.d2.x*modelMatrix[2])+(myCube.d2.y*modelMatrix[6])+(myCube.d2.z*modelMatrix[10])+(w*modelMatrix[14]);
myCube.a1.x=new_Ax;
myCube.a1.y=new_Ay;
myCube.a1.z=new_Az;
myCube.b1.x=new_Bx;
myCube.b1.y=new_By;
myCube.b1.z=new_Bz;
myCube.c1.x=new_Cx;
myCube.c1.y=new_Cy;
myCube.c1.z=new_Cz;
myCube.d1.x=new_Dx;
myCube.d1.y=new_Dy;
myCube.d1.z=new_Dz;
myCube.a2.x=new_A2x;
myCube.a2.y=new_A2y;
myCube.a2.z=new_A2z;
myCube.b2.x=new_B2x;
myCube.b2.y=new_B2y;
myCube.b2.z=new_B2z;
myCube.c2.x=new_C2x;
myCube.c2.y=new_C2y;
myCube.c2.z=new_C2z;
myCube.d2.x=new_D2x;
myCube.d2.y=new_D2y;
myCube.d2.z=new_D2z;
[self drawCube:myCube];