首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

openGL的3D旋转魔方遇到的有关问题

2013-10-31 
openGL的3D旋转魔方遇到的问题本帖最后由 alan19931103 于 2013-10-25 13:10:54 编辑我的代码在魔方旋转的

openGL的3D旋转魔方遇到的问题
本帖最后由 alan19931103 于 2013-10-25 13:10:54 编辑 我的代码在魔方旋转的时候好像有问题,编译没有错,但是运行就不行,麻烦各位大大帮我看看。
我把所有代码都放在下面(现在还没有贴图)。

mofang.c

#include "GL/glut.h"
#include "stdio.h"
#include "transform.c"


/*绘制场景*/
void display(void){
//清除背景
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glPushMatrix();
//设置视野
polarView(9.0,0.0,yz,xy);
//绘制立方体
//glutWireCube(3.0);
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(){
//初始化颜色
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(0.0,0.0,1.0);
initCubes();
}

main(int argc,char **argv){
//初始化 设定显示模式双缓冲RGB
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);
//glutMouseFunc(mouseEvent);
//glutMotionFunc(motionEvent);
//显示窗口
glutMainLoop();
}


drawCube.c
#include "GL/glut.h"

#define MAXORDER 200//存储魔方旋转顺序的最大记录次数

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


//小立方体的结构,sx、sy、sz分别表示绕各轴的旋转角度
//order数组用于记录各块的旋转次序
//x,y,z记录位置
struct lc{
     int sx;
 int sy;
 int sz;
 GLdouble x;
 GLdouble y;
 GLdouble z;
 int order[MAXORDER];

};

//记录魔方旋转
void record(struct lc *tem,int s){
int temp[MAXORDER],t;

for(t = 0;t < MAXORDER;t++){
//将旋转次序最近一次旋转记录到数组的最后位置
if(t == MAXORDER-1){
temp[t] = s;
}else{
temp[t] =  (*tem).order[t+1];
}
}

for(t = 0;t < MAXORDER;t++){
(*tem).order[t] = temp[t];
}
}

struct lc cubes[3][3][3];
struct lc *temp[3][3];
struct lc exc[3][3][3];

/*初始化各个立方体*/
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].order[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++){
for(t = MAXORDER-1;t >= 0;t--){
glPushMatrix();
switch (cubes[i][j][k].order[t]){
case 'x':
   glRotatef(cubes[i][j][k].sx, 1.0, 0.0, 0.0);//绕x轴
break;
case 'z':
glRotatef(cubes[i][j][k].sz, 0.0, 0.0, 1.0); //绕z轴
break;
case 'y':
glRotatef(cubes[i][j][k].sy, 0.0, 1.0, 0.0);   //绕y轴 
break;
default :
break;
}
glTranslatef(cubes[i][j][k].x,cubes[i][j][k].y,cubes[i][j][k].z); //移动  
cube(); 
glPopMatrix();
}
}
}
}            
}


transform.c
#include "GL/glut.h"
#include "drawCube.c"
#include "stdio.h"

/**用极坐标指定的视图变换函数
*例如但需要视野围绕原点的物体作轨道运动时可以调用该函数
*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);
}


static GLfloat xy = 0.0,yz=90.0;//极坐标下视图变换的角度
static GLdouble viewSpeed = 2.0;//视角变换速度
int spinRate=1;//定时函数时间
int clock_key;
int spinning = 0;//判断魔方是否正在旋转,1表示正在旋转
char spinTimes = 0;



void exchangCubes(){
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];
}
}
}

for(j = 0;j < 3;j++){
for(k = 0;k < 3;k++){
if(clock_key>'0' && clock_key<='3'){
i = clock_key - '0';
cubes[i][j][k] = exc[i][2-k][j];
record(&(cubes[i][j][k]),'x');
}
if(clock_key>'3' && clock_key<='6'){
i = clock_key - ' 3';
cubes[j][i][k] = exc[k][i][2-j];
record(&(cubes[i][j][k]),'y');
}
if(clock_key>'6' && clock_key<='9'){
i = clock_key - '6';
cubes[k][j][i] = exc[2-j][k][i];
record(&(cubes[i][j][k]),'z');
}
}
}

for(i = 0;i < 3;i++){
for(j = 0;j < 3;j++){
for(k = 0;k < 3;k++){
cubes[i][j][k].sx = 0;
cubes[i][j][k].sy = 0;
cubes[i][j][k].sz = 0;
}
}
}
}


//选择将要进行旋转的一组立方体
void selectSpin(char key){
  int i,j;  
  for(i=0;i<3;i++){
      for(j=0;j<3;j++){
          switch (key){
              case '1':
                  temp[i][j]=&cubes[0][i][j]; break;
              case '2':
                  temp[i][j]=&cubes[1][i][j]; break;
              case '3':
                  temp[i][j]=&cubes[2][i][j]; break;
              case '4':
                  temp[i][j]=&cubes[j][0][i]; break;
              case '5':
                  temp[i][j]=&cubes[j][1][i]; break;
              case '6':
                  temp[i][j]=&cubes[j][2][i]; break;
              case '7':
                  temp[i][j]=&cubes[i][j][0]; break;
              case '8':
                  temp[i][j]=&cubes[i][j][1]; break;
              case '9':
                  temp[i][j]=&cubes[i][j][2]; break;
          }            
      }
  }     
}

/*该函数实现魔方的旋转、变形*/
void cubeTransform(unsigned char key){
int i,j,k;
selectSpin(key);
for(j = 0;j < 3;j++){
for(k = 0;k < 3;k++){            
if(key>'0' && key<='3'){
(*temp[j][k]).sx+=10;
spinning = 1;
}
else if(key>'3' && key<='6'){
(*temp[j][k]).sy+=10;
spinning = 1;
}
else if(key>'6' && key<='9'){
(*temp[j][k]).sz+=10;
spinning = 1;
}
}
}

/*for(j = 0;j < 3;j++){
for(k = 0;k < 3;k++){ 
for(i = 0;i < 3;i++){
if(cubes[j][k][i].sx > 350)
cubes[j][k][i].sx -= 360;
if(cubes[j][k][i].sy > 350)
cubes[j][k][i].sy -= 360;
if(cubes[j][k][i].sz > 350)
cubes[j][k][i].sz -= 360;
}
}
}
*/
}

/*该函数实现定时功能,注册于glutTimerFunc()*/
void clock(int value){
if(spinTimes < 9){
cubeTransform((char) clock_key);
glutTimerFunc(spinRate,clock,1);
spinTimes++;
}else{
spinning = 0;
spinTimes = 0;
exchangCubes();
}
glutPostRedisplay();
}

//监听键盘事件,并实现用asdw控制视角
void keyEvent1(unsigned char key,int x,int y){


if(spinning != 0){}
else{
clock_key =(int) key;
switch (key){
case 's':
yz -= viewSpeed;
break;
case 'w':
yz += viewSpeed;
break;
case 'd':
xy -= viewSpeed;
break;
case 'a':
xy += viewSpeed;
break;
default:
glutTimerFunc(spinRate,clock,1);
break;
}
}glutPostRedisplay();
}


//监听键盘事件,并实现用 上下左右 控制视角
void keyEvent2(int key,int x,int y){
clock_key =(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();
}



我找了好多天都没发现问题在哪里。求大神笼罩
[解决办法]
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试是程序员必须掌握的技能之一。

[解决办法]
在函数exchangCubes中如下修改3行可解决问题:

for(j = 0;j < 3;j++){
for(k = 0;k < 3;k++){
if(clock_key>'0' && clock_key<='3'){
i = clock_key - '1';//改 i = clock_key - '0';
cubes[i][j][k] = exc[i][2-k][j];
record(&(cubes[i][j][k]),'x');
}
if(clock_key>'3' && clock_key<='6'){
        i = clock_key - '4';//改 i = clock_key - ' 3';这里3前面还多了一个空格
        cubes[j][i][k] = exc[k][i][2-j];
record(&(cubes[i][j][k]),'y');
}
if(clock_key>'6' && clock_key<='9'){
i = clock_key - '7';//改 i = clock_key - '6';
cubes[k][j][i] = exc[2-j][k][i];
record(&(cubes[i][j][k]),'z');
}
}
}


原来的语句计算出来的i为3时超出下标的合法范围0..2,导致在函数record访问非法内存。

热点排行