我又来了,还是魔方的问题

alan19931103 2013-11-05 11:07:52
我们作业的要求是用opengl写一个3d旋转魔方

我先说一下我的思路:
绘制9个小立方体,然后移动组成一个魔方
立方体的数据用结构体存储
魔方旋转变形的时候先用一个指针数组选择出进行旋转的小立方体
旋转以后交换小立方体的数组引用,然后可以下一次变形


但是我现在就是不能进行连续的旋转,或者必须连续4次旋转同一组,然后才能对其他组变换,不然魔方就变得不是魔方了。。。。。

希望各位能告诉我这个思路可不可以
还有代码我放在楼下,如果能告诉我怎么修改就更好了
...全文
341 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
alan19931103 2013-11-12
  • 打赏
  • 举报
回复
过了那么就终于自己找到问题了。 是exchange的时候交换方块错了
赵4老师 2013-11-06
  • 打赏
  • 举报
回复
http://www.codeproject.com搜“Rubik Cube”或“Rubix Cube”
alan19931103 2013-11-05
  • 打赏
  • 举报
回复
#include "GL/glut.h"
#include "stdio.h"
#include "windows.h"

#define MAXORDER 200


	/*	*这是一个用极坐标指定的视图变换函数
		*例如但需要视野围绕原点的物体作轨道运动时可以调用该函数
		*distance定义轨道半径
		 azimuth定义视野在xy平面上旋转的角度
		 elevation定义视野在yz平面上旋转的角度
		 twist定义视镜体围绕视野的旋转角度
	*/
	void polarView(GLdouble distance,GLdouble twist,
				   GLdouble elevation,GLdouble azimuth)
	{
		glTranslated(0.0,0.0,-distance);
		glRotated(-twist,0.0,0.0,1.0);
		glRotated(-elevation,1.0,0.0,0.0);
		glRotated(azimuth,0.0,0.0,1.0);
	}

	//小立方体的结构,sx、sy、sz分别表示绕各轴的旋转角度
struct lc{
     int sx;
	 int sy;
	 int sz;
	 GLdouble x;
	 GLdouble y;
	 GLdouble z;
	 char orders[MAXORDER];
};



static GLfloat xy = 0.0,yz=90.0;//极坐标下视图变换的角度
static GLdouble viewSpeed = 2.0;//视角变换速度
static int spinspeed = 10;
int angle = 0;
int keyboard;//键盘按键
int spinning = 0;//判断魔方是否正在旋转,1表示正在旋转
struct lc cubes[3][3][3];// 创建魔方
struct lc *selected[9];//被选择进行旋转的魔方块
struct lc exc[3][3][3];


//选择变换的魔方块
void elect(){
	int t,i,j;
	switch (keyboard){
		case '1':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[0][i][j];
				}
			}break;
		case '2':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[1][i][j];
				}
			}break;
		case '3':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[2][i][j];
				}
			}break;
		case '4':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[j][0][i];
				}
			}break;
		case '5':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[j][1][i];
				}
			}break;
		case '6':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[j][2][i];
				}
			}break;
		case '7':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[i][j][0];
				}
			}break;
		case '8':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[i][j][1];
				}
			}break;
		case '9':
			t = 0;
			for(i=0;i<3;i++){
				for(j=0;j<3;j++){
					selected[t++] = &cubes[i][j][2];
				}
			}break;
	}
}

void makeorder(){
	int n,t;
	char flag;
	char temp[MAXORDER];

	if(keyboard>'0' && keyboard<='3'){
		flag = 'x';	
	}else if(keyboard>'3' && keyboard<='6'){
		flag = 'y';
	}else if(keyboard>'6' && keyboard<='9'){
		flag = 'z';
	}	

	for(n = 0;n<9;n++){
		for(t = 0;t<MAXORDER;t++){
			temp[t] = (*selected[n]).orders[t];
		}
		for(t = 0;t<MAXORDER-1;t++){
			(*selected[n]).orders[t] = temp[t+1];
		}
		(*selected[n]).orders[MAXORDER-1] = flag;
	}
}

//递归实现魔方变形
void go(){
	int t;
	if(keyboard>'0' && keyboard<='3'){
		for(t=0;t<9;t++){
			(*selected[t]).sx += spinspeed;
		}
	}else if(keyboard>'3' && keyboard<='6'){
		for(t=0;t<9;t++){
			(*selected[t]).sy += spinspeed;
		}
	}else if(keyboard>'6' && keyboard<='9'){
		for(t=0;t<9;t++){
			(*selected[t]).sz += spinspeed;
		}
	}
	angle += spinspeed;
	glutPostRedisplay();
	if(angle == 90){
		angle = 0;
		spinning = 0;
	}else {
		glutTimerFunc(50,go,1);
	}
}

void exchange(){
	 int i,j,k;
     
    for(i = 0;i < 3;i++){
        for(j = 0;j < 3;j++){
            for(k = 0;k < 3;k++){
                exc[i][j][k] = cubes[i][j][k];
				cubes[i][j][k].sx = 0;
				cubes[i][j][k].sy = 0;
				cubes[i][j][k].sz = 0;
            }
        }
    }
 
    for(j = 0;j < 3;j++){
        for(k = 0;k < 3;k++){
            if(keyboard>'0' && keyboard<='3'){
                i = keyboard - '1';
                cubes[i][j][k] = exc[i][2-k][j];
            }
            if(keyboard>'3' && keyboard<='6'){
                i = keyboard - '4';
                cubes[j][i][k] = exc[k][i][2-j];
            }
            if(keyboard>'6' && keyboard<='9'){
                i = keyboard - '7';
                cubes[k][j][i] = exc[2-j][k][i];
            }
        }
    }
}

void cubeTransform(){
	spinning = 1;
	elect();
	go();

	makeorder();
	exchange();
}

//监听键盘事件,并实现用asdw控制视角
void keyEvent1(unsigned char key,int x,int y){
	if(spinning != 0){}
	else{
		keyboard =(int) key;
		switch (key){
			case 's':
				yz -= viewSpeed;
				glutPostRedisplay();
				break;
			case 'w':
				yz += viewSpeed;
				glutPostRedisplay();
				break;
			case 'd':
				xy -= viewSpeed;
				glutPostRedisplay();
				break;
			case 'a':
				xy += viewSpeed;
				glutPostRedisplay();
				break;
			default:
				cubeTransform();
				break;
		}
	}
}


//监听键盘事件,并实现用 上下左右 控制视角
void keyEvent2(int key,int x,int y){
	if(spinning != 0){}
	else{
		keyboard =(int) key;
		switch (key){
			case GLUT_KEY_DOWN:
			yz -= viewSpeed;
			break;
		case GLUT_KEY_UP:
			yz += viewSpeed;
			break;
		case GLUT_KEY_RIGHT:
			xy -= viewSpeed;
			break;
		case GLUT_KEY_LEFT:
			xy += viewSpeed;
			break;
		default:
			break;
		}
	}glutPostRedisplay();
}



//绘制一个小立方体
void cube(){
	glutWireCube(1.0);
}



/*初始化各个立方体*/
void initCubes(){
	GLfloat x,y,z;
	int i,j,k,t;
	for(i=0,x=-1.0;i<3;i++,x+=1.0){
       for(j=0,y=-1.0;j<3;j++,y+=1.0){
           for(k=0,z=-1.0;k<3;k++,z+=1.0){
               cubes[i][j][k].x=x;cubes[i][j][k].sx=0;
               cubes[i][j][k].y=y;cubes[i][j][k].sy=0;
               cubes[i][j][k].z=z;cubes[i][j][k].sz=0; 
				for(t=0;t>MAXORDER;t++){
					cubes[i][j][k].orders[t] = 0; 
				}
			}
        }
    }
}

void drawCube(){
	int i,j,k,t;
		for(i=0;i<3;i++){
		for(j=0;j<3;j++){
			for(k=0;k<3;k++){
				glPushMatrix();      
				glRotatef(cubes[i][j][k].sx, 1.0, 0.0, 0.0);	
				glRotatef(cubes[i][j][k].sz, 0.0, 0.0, 1.0); 	
				glRotatef(cubes[i][j][k].sy, 0.0, 1.0, 0.0);   	
				for(t=MAXORDER-1;t>-1;t--){
					switch(cubes[i][j][k].orders[t]){
						case 'x':
							glRotatef(90.0, 1.0, 0.0, 0.0);
							break;
						case 'y':
							glRotatef(90.0, 0.0, 1.0, 0.0);
							break;
						case 'z':
							glRotatef(90.0, 0.0, 0.0, 1.0);
							break;
							
					}
				}
				glTranslatef(cubes[i][j][k].x,cubes[i][j][k].y,cubes[i][j][k].z); 
				cube();            
				glPopMatrix();
			}
		}
	}            
}

/*绘制场景*/
void display(void){
	glClearColor(0.0,0.0,0.0,0.0);
	glColor3f(0.0,0.0,1.0);
	glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
	polarView(9.0,0.0,yz,xy);
	drawCube();
	glPopMatrix();
	glutSwapBuffers();
}

/*当窗口被改变时的处理方法*/
void reshape(int width,int height){
//设置适口大小和位置,保证魔方不变形
	GLint side = width>height? height:width;
	GLint pos = (width-side)/2;

	glViewport(pos,0,(GLsizei)side,(GLsizei)side);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(50.0,1.0,1.0,15.0);
	
}

void init(){
	initCubes();
}
/*主函数
	初始化 
	设定显示模式双缓冲RGB
	初始化窗口大小位置
	注册事件函数
	显示窗口
*/
main(int argc,char **argv){
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB| GLUT_DEPTH);

	glutInitWindowSize(800,600);
	glutInitWindowPosition(50,50);

	glutCreateWindow("3D魔方");
	init();

	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyEvent1);
	glutSpecialFunc(keyEvent2);

	glutMainLoop();
}

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧