这是问题的照片:
这是显示这些立方体的完整程序(需要SDL和OpenGL)
//==============================================================================#include <cmath>#include <SDL/SDL.h>#include <SDL/SDL_opengl.h>namespace game_lib{ struct vec3 { vec3() : x(0),y(0),z(0) { } vec3(float x,float y,float z) : x(x),y(y),z(z) { } vec3 normalize(); inline float lenSqr() { return x*x + y*y + z*z; } float len(); inline vec3 operator+(vec3 v) { v.x += x; v.y += y; v.z += z; return v; } inline vec3 operator-(vec3 v) { v.x = x - v.x; v.y = y - v.y; v.z = z - v.z; return v; } inline vec3 operator*(float f) { return vec3(f*x,f*y,f*z); } inline vec3 operator/(float f) { return vec3(x/f,y/f,z/f); } bool operator==(vec3 v); float x,y,z; enum faces { FRONT,BACK,left,RIGHT,top,BottOM }; }; inline vec3 operator*(float f,vec3 v) { return v*f; } struct quaternion { quaternion() : w(1),x(0),z(0) { } quaternion(float w,float x,float z) : w(w),x(x),z(z) { } quaternion(float angle,vec3 axis); quaternion normalize(); inline float lenSqr() { return w*w + x*x + y*y + z*z; } float len(); quaternion operator*(quaternion); float w,x,z; }; voID DrawGLCuboID(vec3 centre,vec3 dimensions,quaternion rotation,const vec3 colours[6]);}const int EPSILON = 0.001;inline bool feq(float f1,float f2){ const float diff = f1 - f2; return (diff > -EPSILON) && (diff < EPSILON);}//{=================== vec3 methods =================game_lib::vec3 game_lib::vec3::normalize(){ const float lengthSqr = lenSqr(); if (lengthSqr > 1-EPSILON*EPSILON and lengthSqr < 1+EPSILON*EPSILON) // Optimisation to not re-normalize a normalized vector return *this; const float length = std::sqrt(lengthSqr); return game_lib::vec3(x/length,y/length,z/length);}float game_lib::vec3::len() { return std::sqrt(lenSqr()); }bool game_lib::vec3::operator==(vec3 v) { return feq(v.x,x) and feq(v.y,y) and feq(v.z,z); }//}==================================================//{================ quaternion methods ==============game_lib::quaternion::quaternion(float angle,vec3 axis){ const vec3 axisN = axis.normalize(); const float sin_a_2 = std::sin(angle*M_PI/360); w = std::cos(angle*M_PI/360); x = axisN.x*sin_a_2; y = axisN.y*sin_a_2; z = axisN.z*sin_a_2;}game_lib::quaternion game_lib::quaternion::normalize(){ const float lengthSqr = lenSqr(); if (lengthSqr > 1-EPSILON*EPSILON and lengthSqr < 1+EPSILON*EPSILON) // Optimisation to not re-normalize a normalized quaternion return *this; const float length = std::sqrt(lengthSqr); return game_lib::quaternion(w/length,x/length,z/length);}float game_lib::quaternion::len() { return std::sqrt(lenSqr()); }game_lib::quaternion game_lib::quaternion::operator*(game_lib::quaternion q){ return game_lib::quaternion(w*q.w - x*q.x - y*q.y - z*q.z,w*q.x + x*q.w + y*q.z - z*q.y,w*q.y - x*q.z + y*q.w + z*q.x,w*q.z + x*q.y - y*q.x + z*q.w);}//}==================================================voID game_lib::DrawGLCuboID(vec3 cen,vec3 dim,quaternion rot,const vec3 col[6]){ glPushmatrix(); glTranslatef(cen.x,cen.y,cen.z); vec3 dim_2 = 1/2*dim; const quaternion r_norm = rot.normalize(); // Quaternion to matrix const float x_x = r_norm.x*r_norm.x,y_y = r_norm.y*r_norm.y,z_z = r_norm.z*r_norm.z; const float w_x = r_norm.w*r_norm.x,w_y = r_norm.w*r_norm.y,w_z = r_norm.w*r_norm.z; const float x_y = r_norm.x*r_norm.y,x_z = r_norm.x*r_norm.z,y_z = r_norm.y*r_norm.z; GLfloat matrix[16]; // Column 1 // Column 2 // Column 3 // Column 4 matrix[0] = 1-2*(y_y+z_z); matrix[4] = 2*(x_y-w_z); matrix[8] = 2*(x_z+w_y); matrix[12] = 0; matrix[1] = 2*(x_y+w_z); matrix[5] = 1-2*(x_x+z_z); matrix[9] = 2*(y_z+w_x); matrix[13] = 0; matrix[2] = 2*(x_z-w_y); matrix[6] = 2*(y_z-w_x); matrix[10] = 1-2*(x_x+y_y); matrix[14] = 0; matrix[3] = 0; matrix[7] = 0; matrix[11] = 0; matrix[15] = 1; /* From http://www.cprogramming.com/tutorial/3d/quaternions.HTML 1-2y2-2z2 2xy-2wz 2xz+2wy 0 2xy+2wz 1-2x2-2z2 2yz+2wx 0 2xz-2wy 2yz-2wx 1-2x2-2y2 0 0 0 0 1 */ glMultMatrixf(matrix); glBegin(GL_QUADS); int i = vec3::FRONT; glcolor3f(col[i].x,col[i].y,col[i].z); glVertex3f(-1,1,1); glVertex3f(1,-1,1); glVertex3f(-1,1); i = vec3::BACK; glcolor3f(col[i].x,-1); glVertex3f(1,-1); glVertex3f(-1,-1); i = vec3::left; glcolor3f(col[i].x,-1); i = vec3::RIGHT; glcolor3f(col[i].x,col[i].z); glVertex3f(1,-1); i = vec3::BottOM; glcolor3f(col[i].x,-1); i = vec3::top; glcolor3f(col[i].x,-1); glcolor3f(1,1); // Following three quads are axes to help determine rotational correctness... // x-axis glVertex3f(-2,0.05,0.05); glVertex3f(2,-0.05,-0.05); glVertex3f(-2,-0.05); // y-axis glVertex3f(0.05,-2,0.05); glVertex3f(0.05,2,0.05); glVertex3f(-0.05,-0.05); glVertex3f(-0.05,-0.05); // z-axis glVertex3f(0.05,-2); glVertex3f(0.05,2); glVertex3f(-0.05,-2); glEnd(); glPopMatrix();}using namespace game_lib;struct SDL_Surface;union SDL_Event;class CApp { private: bool m_running,m_init; SDL_Surface* m_screen; float depth; public: CApp(); ~CApp(); bool init(); int execute(); voID cleanup(); private: //voID processEvent(SDL_Event* Event); // Usually I have this,but it's big and irrelevant ( voID render();};//==============================================================================CApp::CApp(): m_running(true),m_init(false),m_screen(NulL),depth(-6) { }CApp::~CApp(){ if (m_init) cleanup();}//------------------------------------------------------------------------------bool CApp::init(){ if(SDL_Init(SDL_INIT_EVERYTHING) < 0) return false; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8); SDL_GL_SetAttribute(SDL_GL_Alpha_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16); SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32); SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,8); SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,8); SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,8); SDL_GL_SetAttribute(SDL_GL_ACCUM_Alpha_SIZE,8); SDL_GL_SetAttribute(SDL_GL_MulTISAMPLEBUFFERS,1); SDL_GL_SetAttribute(SDL_GL_MulTISAMPLESAMPLES,2); const SDL_VIDeoInfo* inf = SDL_GetVIDeoInfo(); if((m_screen = SDL_SetVIDeoMode(inf->current_w,inf->current_h,SDL_OPENGL | SDL_FulLSCREEN)) == NulL) return false; glClearcolor(0,0); glClearDepth(1); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glVIEwport(0,inf->current_w,inf->current_h); glMatrixMode(GL_PROJECTION); // Camera space glLoadIDentity(); gluPerspective(45.0f,1024.0f/600.0f,0.1f,100.0f); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); // Model space glLoadIDentity(); m_init = true; return true;}int CApp::execute(){ if(init() == false) return -1; SDL_Event event; while(m_running) { //while(SDL_PollEvent(&event)) // process events removed to save space render(); SDL_Delay(10); } cleanup(); return 0;}voID CApp::cleanup(){ if (m_screen) { SDL_FreeSurface(m_screen); m_screen = NulL; } SDL_Quit(); m_init = false;}voID CApp::render(){ glClear(GL_color_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIDentity(); glTranslatef(0.0f,0.0f,depth); //glrotatef(63,0); // How I used to do rotation //glrotatef(47,0); const vec3 c1colours[] = {vec3(1,0),vec3(0,vec3(1,0.2,1),0.5,1)}; const vec3 c2colours[] = {vec3(1,vec3(0.5,0)}; // New rotation method,but doesn't work... const quaternion c1Rotation = quaternion(63,0)) * quaternion(47,0)); DrawGLCuboID(vec3(-2,-2),vec3(2,2),c1Rotation,c1colours); DrawGLCuboID(vec3(2.5,0.3,-1.2),quaternion(72,1)),c2colours); SDL_GL_SwapBuffers();}int main(int argc,char* argv[]){ CApp theApp; return theApp.execute();}解决方法 如前所述,你可能最好使用已经为你做数学的库.
这里的问题是你在矩阵[6]和矩阵[9]上交换了w_x的符号.
相关的行应该如此阅读:
matrix[1] = 2*(x_y+w_z); matrix[5] = 1-2*(x_x+z_z); matrix[9] = 2*(y_z-w_x); matrix[13] = 0;matrix[2] = 2*(x_z-w_y); matrix[6] = 2*(y_z+w_x); matrix[10] = 1-2*(x_x+y_y); matrix[14] = 0;总结
以上是内存溢出为你收集整理的c – 使用四元数的OpenGL立方体旋转全部内容,希望文章能够帮你解决c – 使用四元数的OpenGL立方体旋转所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)