问题
I have a code to find the cell mouse clicked in chess board then a 2D Triangle shape go to the cell position, Now I want to change 2D Triangle to 3D cube but I don't know how to do that.
This my code
#include <string>
#include <stdlib.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <iostream>
using namespace std;
void init()
{
glClearColor (1.0, 0.0, 1.0, 0.0);
glShadeModel (GL_FLAT);
}
const int scl = 80 ;
const int STEP_SIZE = 80;
const int WIN_WIDTH = 800;
const int WIN_HEIGHT = 800;
int LeftRight = 0 ;
int UpDown = 0;
void moveRight()
{
LeftRight+=STEP_SIZE;
}
void moveLeft()
{
LeftRight-=STEP_SIZE;
}
void moveUp()
{
UpDown+=STEP_SIZE;
}
void moveDown()
{
UpDown-=STEP_SIZE;
}
void DrawBoard()
{
int x , y , color = 0;
glClear (GL_COLOR_BUFFER_BIT);
for(x=1; x<=8; x++)
{
if(color==0)
glColor3f (1.0, 0.0, 0.0), color++;
else
glColor3f (1.0, 1.0, 1.0),color=0;
for(y=1; y<=8; y++)
{
if(color==0)
glColor3f (0.0, 0.0, 0.0),color++;
else
glColor3f (1.0, 1.0, 1.0),color=0;
glBegin(GL_QUADS);
glVertex2f(scl+scl*x, scl+scl*y);
glVertex2f(scl*x, scl+scl*y);
glVertex2f(scl*x, scl*y);
glVertex2f(scl+scl*x, scl*y);
glEnd();
}
}
// This is the Triangle that will change to cube
glBegin(GL_QUADS);
glColor3f (1.0, 0.5, 0.0);
glVertex2f(90+LeftRight,100+UpDown);
glVertex2f(90+LeftRight,100+UpDown);
glVertex2f(120+LeftRight,140+UpDown);
glVertex2f(150+LeftRight,100+UpDown);
glEnd();
//--------------------------------------
glFlush ();
}
int mouse_x = -1 ;
int mouse_y = -1 ;
int object_x = -1 ;
int object_y = -1 ;
void moveObjectToFrom()
{
if (mouse_x > 8 || mouse_x < 1 || mouse_y > 8 || mouse_y < 1 )
return ;
if(object_x > mouse_x )
{
object_x-- ;
moveUp();
}
if(object_x < mouse_x )
{
object_x++;
moveDown();
}
if(object_y > mouse_y )
{
object_y-- ;
moveLeft();
}
if(object_y < mouse_y)
{
object_y++ ;
moveRight();
}
}
void mouseClicks( int button , int key, int x, int y )
{
// this variables related to chessboard
mouse_x = y / scl ;
mouse_y = 9 - (WIN_HEIGHT - x)/scl ;
object_x = 9 - (100 + UpDown)/ scl ;
object_y = 9 - (WIN_HEIGHT - (LeftRight+90))/scl ;
if (button !=0 || mouse_x > 8 || mouse_x < 1 || mouse_y > 8 || mouse_y < 1 )
return ;
glutPostRedisplay();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (0.0, (GLdouble) w, 0.0, (GLdouble) h);
}
void update(int value)
{
moveObjectToFrom();
glutTimerFunc(50, update, 0);
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
// glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glEnable(GL_DEPTH_TEST);
glutInitWindowSize (WIN_WIDTH, WIN_HEIGHT);
glutInitWindowPosition (100,100);
glutCreateWindow (argv[0]);
glutTimerFunc(25, update, 0);
glutMouseFunc(mouseClicks);
init ();
glutDisplayFunc(DrawBoard);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
回答1:
Your main problem is that your GL_PROJECTION
is set to gluOrtho2D
so when you render axis align cube it will always produce just square. To remedy this you should use gluProjection
instead. But that will give you view centered around 0.0,0.0
instead of your current screen center coordinate (0.5*w,0.5*h)
so you need also translate the GL_MODELVIEW
by it.
Here example how to do this:
- 2D shape in C++ by using the OpenGl library
Now to render a cube you can do this:
void render_cube()
{
const GLfloat a=20.0; // cube half size
const GLfloat pos[]= // glVertex cube centered at (0,0,0) of size 2*a
{
// x y z
-a,+a,-a,
+a,+a,-a,
+a,-a,-a,
-a,-a,-a,
-a,-a,+a,
+a,-a,+a,
+a,+a,+a,
-a,+a,+a,
-a,-a,-a,
+a,-a,-a,
+a,-a,+a,
-a,-a,+a,
+a,-a,-a,
+a,+a,-a,
+a,+a,+a,
+a,-a,+a,
+a,+a,-a,
-a,+a,-a,
-a,+a,+a,
+a,+a,+a,
-a,+a,-a,
-a,-a,-a,
-a,-a,+a,
-a,+a,+a,
};
const GLfloat col[]=
{
// r g b
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
};
const GLfloat nor[]= // glNormal
{
// nx ny nz
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
};
int i,i3;
glBegin(GL_QUADS);
for (i=0,i3=0;i<24;i++,i3+=3)
{
glColor3fv (col+i3);
glNormal3fv(nor+i3);
glVertex3fv(pos+i3);
}
glEnd();
}
which is supposed to render like this:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
render_cube();
just set the a
constant to what ever you need and translate modelview to its placement position ...
here preview:
Each side has its own color for debug purposes ... Look here for 3D view example:
- Faces missing when drawing icosahedron in OpenGL following code in redBook
[Edit1] I tweaked your code a bit
there were some inconsistencies in polygon winding. Try to swap your functions with these (they worked for me) and leave the rest of your code as is:
//---------------------------------------------------------------------------
void render_cube(GLfloat a) // cube half size
{
GLfloat pos[]= // glVertex
{
// x y z
-a,+a,-a,
+a,+a,-a,
+a,-a,-a,
-a,-a,-a,
-a,-a,+a,
+a,-a,+a,
+a,+a,+a,
-a,+a,+a,
-a,-a,-a,
+a,-a,-a,
+a,-a,+a,
-a,-a,+a,
+a,-a,-a,
+a,+a,-a,
+a,+a,+a,
+a,-a,+a,
+a,+a,-a,
-a,+a,-a,
-a,+a,+a,
+a,+a,+a,
-a,+a,-a,
-a,-a,-a,
-a,-a,+a,
-a,+a,+a,
};
const GLfloat col[]= // glColor
{
// r g b
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,0.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
1.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,0.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,1.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
};
const GLfloat nor[]= // glNormal
{
// nx ny nz
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0, 0.0,+1.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
0.0,-1.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
+1.0, 0.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
0.0,+1.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
};
int i,i3;
glBegin(GL_QUADS);
for (i=0,i3=0;i<24;i++,i3+=3)
{
glColor3fv (col+i3);
glNormal3fv(nor+i3);
glVertex3fv(pos+i3);
}
glEnd();
}
//---------------------------------------------------------------------------
void init()
{
glClearColor(1.0, 0.0, 1.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
}
//---------------------------------------------------------------------------
const int scl = 80 ;
int LeftRight = 0 ;
int UpDown = 0;
void DrawBoard()
{
int x , y , color = 0;
glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // do not forget also to clear depth buffer
for(x=1;x<=8;x++)
{
if (color) glColor3f (0.0, 0.0, 0.0); // I like this a bit better then your approach
else glColor3f (1.0, 1.0, 1.0); color^=1;
for(y=1; y<=8; y++)
{
if (color) glColor3f (0.0, 0.0, 0.0);
else glColor3f (1.0, 1.0, 1.0); color^=1;
glBegin(GL_QUADS);
glNormal3f(0.0,0.0,+1.0);
glVertex3f(scl+scl*x, scl+scl*y,0.0);
glVertex3f(scl*x, scl+scl*y,0.0);
glVertex3f(scl*x, scl*y,0.0);
glVertex3f(scl+scl*x, scl*y,0.0);
glEnd();
}
}
// your triangle just above cube (and reversed order to match the rest of rendering)
glBegin(GL_QUADS);
glColor3f (1.0, 0.5, 0.0);
glNormal3f(0.0,0.0,+1.0);
glVertex3f(150+LeftRight,100+UpDown,scl+1.0);
glVertex3f(120+LeftRight,140+UpDown,scl+1.0);
glVertex3f( 90+LeftRight,100+UpDown,scl+1.0);
glVertex3f( 90+LeftRight,100+UpDown,scl+1.0);
glEnd();
// cube
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); // remember modelview
glTranslatef(1.5*scl+LeftRight,1.5*scl+UpDown,+0.5*scl); // set cube position
render_cube(0.5*scl);
glPopMatrix(); // restore modelview
glFlush();
}
//---------------------------------------------------------------------------
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,float(w)/float(h),10.0,10000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-w/2,-h/2,-1000.0);
}
//---------------------------------------------------------------------------
Using 800x800 window the result should look like this:
btw. these includes are obsolete:
#include <string>
#include <stdlib.h>
#include <iostream>
using namespace std;
as you are not using anything from them in your code.
来源:https://stackoverflow.com/questions/43618023/change-2d-object-to-3d-object-opengl