3,881
社区成员
发帖
与我相关
我的任务
分享#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();
}