I have a code with which I generate a pawn in OpenGL. However, I want to make its parts draggable. My question is more of a general one, but here's the code for my pawn so that you get an idea of what I'm doing:
int main()
{
/* open gl initialization */
while(running())
{
glClear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glColor3ub(0, 0, 0);
/* the basis of the pawn */
glPushMatrix();
glScalef(1.6, 1.6, 0.8);
glTranslatef(0.0, 0.0, -2.7 - offset);
drawSmoothUnityEllipsoidPatch(0, 2*M_PI, 0, M_PI /2 );
glPopMatrix();
/* upped ellipsoid */
glPushMatrix();
glScalef(0.8, 0.8, 0.15);
glTranslatef(0.0 - offset, 0.0, 6.0);
drawSmoothUnitySphere();
glPopMatrix();
/* lower ellipsoid */
glPushMatrix();
glScalef(1.2, 1.2, 0.15);
glTranslatef(0.0 - offset, 0.0, -10.0);
drawSmoothUnitySphere();
glPopMatrix();
/* the cone */
glPushMatrix();
glScalef(1.0, 1.0, 3.5);
glTranslatef(0.0 + offset, 0.0, -0.5);
drawSmoothUnityCone();
glPopMatrix();
/* the sphere on top of the pawn */
glPushMatrix();
glScalef(0.7, 0.7, 0.7);
glTranslatef(0.0, 0.0, 2.3 + offset);
drawSmoothUnitySphere();
glPopMatrix();
glfwTerminate();
return 0;
}
where offset is irrelevant. The functions drawSmoothUnity(shape) just draw a unity shape in the centre of the coordinate system. I want to te able to drag and drop any of these shapes in the visible area (800x600, my window-size).
You can use gluUnproject to map your cursor position from screen space into world space. By tracking the delta of the 3D world coordinates when the mouse button was first clicked to the current position (after dragging) this gives you the x,y&z values you should use to translate your object.
Also, it should be 'glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);'
This is kind of off the top of my head and is psuedocodish. This doesn't take into account any selection or any of that. So, clicking down and moving the mouse would move the object even if the object wasn't under the mouse cursor when you clicked. You'll obviously need to add mouse handlers.
glm::dvec3 original_position;//position of object when we start moving
glm::dvec3 world_anchor;//world space coordinates of where we left clicked
glm::ivec2 screen_anchor;//screen space coordinates of where we left clicked
Object object;
OnLButtonDown(int x, int y)//x,y = where we clicked
{
original_position = object.GetPosition();
screen_anchor = ivec2(x,y);//screen coords where we clicked
gluUnproject(x,y,0,modelview_matrix,projection_matrix,viewport,&world_anchor.x,
&world_anchor.y,&world_anchor.z);
}
OnMouseMove(int x, int y) //x,y = current mouse cursor position
{
if(left_button_down)
MoveObject(screen_anchor.x-x,screen_anchor.y-y);
}
}
MoveObject(int dx, int dy)//dx,dy = distance from current mouse position to screen_anchor
{
glm::dvec3 world_position;//current mouse position in world coordinates
gluUnProject(dx,dy,0,modelview_matrix,projection_matrix,viewport,&world_position.x,
&world_position.y,&world_position.z);
glm::dev3 world_delta = world_anchor-world_position;
object.SetPosition(original_position+world_delta);
}
Related
I am using C++, OpenGL and glut. I am trying to make 5 houses that are rotated properly like this:
However, whenever I try to implement the glRotatef function, I seem to not be able to either get the proper coordinates or something is off somewhere in my code. Furthermore, I set the background color to white but it's still all black, how come? For now I have the houses set to white to counter this for now. Here is my code:
#include <GL/glut.h>
typedef int vert2D[2];
void initialize()
{
glClearColor(1.0, 1.0, 1.0, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(10.0, 215.0, 0.0, 250.0);
glMatrixMode(GL_MODELVIEW);
}
void drawHouse(vert2D* sq, vert2D* tri)
{
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
glVertex2iv(sq[0]);
glVertex2iv(sq[1]);
glVertex2iv(sq[2]);
glVertex2iv(sq[3]);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2iv(tri[0]);
glVertex2iv(tri[1]);
glVertex2iv(tri[2]);
glEnd();
}
void render()
{
vert2D sqPts[4] = { {115, 150}, {115, 125}, {100,125}, {100,150} };
vert2D triPts[3] = { {120, 150}, {95,150}, {108,160} };
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glMatrixMode(GL_MODELVIEW);
drawHouse(sqPts, triPts);
glPushMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef(-10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glTranslatef(1.0, 0.0, 0.0);
glRotatef(-10.0, 0.0, 0.0, -1.0);
drawHouse(sqPts, triPts);
glPopMatrix();
glPushMatrix();
glTranslatef(-1.0, 0.0, 0.0);
glRotatef(10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glTranslatef(-1.0, 0.0, 0.0);
glRotatef(10.0, 0.0, 0.0, 1.0);
drawHouse(sqPts, triPts);
glPopMatrix();
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(640, 480);
glutCreateWindow("TestMeOut");
initialize();
glutDisplayFunc(render);
glutMainLoop();
}
Let's answer the simpler question of why your background is still black, first:
You simply never glClear(GL_COLOR_BUFFER_BIT) the color buffer. You tell OpenGL "hey, the next time I call glClear with (at least) the GL_COLOR_BUFFER_BIT, I want the color buffer to be cleared to white." but you never actually clear the buffer.
Now, onto how we can draw the houses with their correct locations and orientations:
You should first start by defining your house's vertices in a sensible local coordinate system/frame that is suitable for transforming them in further steps. Currently, with how you define your house's vertices, it is hard to do any transformations on those (mainly because linear transformations like rotation are always relative to the coordinate system's origin).
So, let's change that. Let's define the origin (0, 0) for your house to be the center of the bottom/base line of the house. And let's also define that your house's quad has a side length of 10 "units":
vert2D sqPts[4] = {
{-5, 0}, // <- bottom left
{ 5, 0}, // <- bottom right
{ 5,10}, // <- top right
{-5,10} // <- top left
};
Now, for the roof of the house, we assume the same coordinate system (with (0, 0) being the center of the house's base/bottom line), so we start at Y=10:
vert2D triPts[3] = {
{-6, 10}, // <- left
{ 6, 10}, // <- right
{ 0, 12} // <- top
};
Next, we need to define where (0, 0) should be in our "world", so to speak. One definition could be: (0, 0) should be the center of the bottom of the viewport/screen and the viewport should have a length of 100 "units". Right now, we don't care about a correct aspect ratio when the viewport's width does not equal the viewport's height. This can be added later.
Starting from the clip space coordinate system, we can transform this clip space into our own "world space" by using these transformations:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(0.0, -1.0, 0.0); // <- move the origin down to the bottom of the viewport
glScalef(1.0 / 50.0, 1.0 / 50.0, 1.0); // <- "scale down" the clip space to cover more space in the viewport
Now, the above part is essentially what gluOrtho2D() does as well, but highlighting the actual coordinate system transformation steps is useful here.
Now that we defined our house's local coordinate system and our "world" coordinate system, we can rotate and translate the world coordinate system such that the houses appear at their correct locations and orientations in our world.
In order to draw 5 houses, we just use a for-loop:
glMatrixMode(GL_MODELVIEW);
for (int i = -2; i <= 2; i++) { // <- 5 steps
glPushMatrix();
glRotatef(i * 20.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 50.0, 0.0);
drawHouse(sqPts, triPts);
glPopMatrix();
}
So, starting from our world coordinate system, we transform it by rotating the appropriate amount around its origin (0, 0) for the house with index i to have the correct rotation, and then translate the coordinate system by 50 units along its (now rotated) Y axis.
These two transformations will now result in a house to be drawn at the desired location. So, repeat that 5 times in total with differing rotation angles, and you're done.
I am a beginner in OpenGl and I am struggling a bit with setting up the glOrtho camera to match the window size so that I can draw a line using the window's coordinates. For example, if I want to draw a line from coordinates 0,10 (x,y) to 600,10. I managed to draw the line (which will be a "Separator" from the viewport and a toolbar with buttons) in my current set up but it was by "try end error" approach and the coordinates that I needed to put don't make any sense to me. When I tried to draw a line using the above-mentioned coordinates, the line simply did not show up. What I need to change in the glOrtho set up in order to work with these (1000x600) screen size and draw my vertices and not these:
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
Note, my current window size is 1000x600 (width/height)
This is the line (on the top that crosses the whole screen):
This is my OGWindow class that handles all of the drawing:
void OGWindow::MyReSizeGLScene(int fwidth, int fheight)
{
// Store window size in class variables so it can be accessed in myDrawGLScene() if necessary
wWidth = fwidth;
wHeight = fheight;
// Calculate aspect ration of the OpenGL window
aspect_ratio = (float) fwidth / fheight;
// Set camera so it can see a square area of space running from 0 to 10
// in both X and Y directions, plus a bit of space around it.
Ymin = -1;
Ymax = 12;
Xmin = -1;
// Choose Xmax so that the aspect ration of the projection
// = the aspect ratio of the viewport
Xmax = (aspect_ratio * (Ymax -Ymin)) + Xmin;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
glOrtho(Xmin, Xmax, Ymin, Ymax, -1.0, 1.0);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
}
void OGWindow::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
OGWindow::myDrawModel();
drawToolbar();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
void OGWindow::myDrawModel(GLvoid)
{
switch ( squareColour ) {
case RED:
glColor3f(1.0, 0.0, 0.0);
break;
case BLUE:
glColor3f(0.0, 0.0, 1.0);
break;
}
glBegin( GL_QUADS );
glVertex3f( squareX, squareY, 0.0 ); // Coordinates of bottom-left corner of square
glVertex3f( squareX + squareWidth, squareY, 0.0 );
glVertex3f( squareX + squareWidth, squareY + squareHeight, 0.0 );
glVertex3f( squareX, squareY + squareHeight, 0.0 );
glEnd();
}
// Convert from screen coords returned by mouse
// to world coordinates.
// Return result in worldX, worldY
void OGWindow::screen2World(int screenX, int screenY, double & worldX, double & worldY)
{
// Dimensions of rectangle viewed by camera projection
double projWidth = Xmax -Xmin;
double projHeight = Ymax - Ymin;
// Screen coords with origin at bottom left
int screenLeft = screenX;
int screenUp = wHeight - screenY;
worldX = Xmin + screenLeft * projWidth / wWidth ;
worldY = Ymin + screenUp * projHeight / wHeight ;
}
//Method to draw the toolbar separator line
void OGWindow::drawToolbar(GLvoid) {
//draw toolbar line separator
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
glEnd();
//draw create button
glPushMatrix();
glTranslatef(2.0, 10.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
}
This is my main class where I am ivoking the methods from OGWindow:
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Demo");
glEnable(GL_DEPTH_TEST); // enable the depth buffer test
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMotion);
glutPassiveMotionFunc(mousePassiveMotion);
glutIdleFunc(Idle);
theWindow.initGL();
glutMainLoop();
}
Check out the documentation of glOrtho function. As you see, there are 6 parameters: left, right, bottom, top, near, far. You made mistake by setting window width to top instead of bottom parameter. Here's proper use of function:
glOrtho (0, 1000, 600, 0, -1.0, 1.0)
So, first your ortho settings. If you want your camera to match the screen dimensions, glOrtho has to use the same dimensions.
// This will anchor the camera to the center of the screen
// Camera will be centered on (0,0)
glOrtho( -screenWidth/2.f, screenWidth/2.f, -screenHeight/2.f, screenHeight/2.f, -1, 1 );
// This will anchor the camera to the lower left corner of the screen
// Camera will be centered on (screenWidth/2, screenHeight/2)
glOrtho( 0, screenWidth, 0, screenHeight, -1, 1 );
Try both and see the difference. Although if you are making some sort of editor, where your camera doesn't move, you may be looking for the second ortho setup.
Second, you only ever use (apparently) the GL_PROJECTION matrix mode. You must use this mode to set the camera projection and GL_MODELVIEW to apply transforms to the camera or the objects.
So when you call resize and don't change the matrix mode back to GL_MODELVIEW, you'll be applying translations to the projection matrix.
If you did forget to initialize the modelview matrix it may contain garbage values and yield unexpected results.
I am currently trying to create a 2D side scroller and i currently have my "world" drawing (a large white box for the time being), but i cannot figure out any relationship between the edge of the world map and the edge of the viewport to ensure that the viewport is always fully covered by the map.
My basic world drawing code is:
void drawTiles(void)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 500; j++)
{
glPushMatrix();
glTranslatef(j, -i, 0);
glBegin (GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix();
}
}
}
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(camX, camY, -20); //translate back a bit to view the map correctly (our camera)
drawTiles(); //draw our tiles
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
camY -= 0.25;
break;
case 's':
camY += 0.25;
break;
case 'a':
camX += 0.25;
break;
case 'd':
camX -= 0.25;
break;
}
}
How would i go about ensuring that when I use WASD and on viewport resize, that i do not translate beyond the bounds of the map (currently 500x50 tiles)?
If you have a planar scene (2D only), it should be sufficient to use an orthographic projection transformation. The projection transformation determines the camera's parameters. In the current state (with the perspective projection) you have a usual pin hole camera with a vertical opening angle of 60°.
An orthographic projection is defined by its edges. Let's say you want your camera to "see" two units to the left, 3 units to the right, 1 unit up and 4 units down. This would be possible, although it might not be reasonable in your case.
The current perspective camera "sees" about 11.5 units up and down. The according width can be calculated from the window dimensions (we do not want to stretch the image). So instead of gluPerspective, use the following:
float halfHeight = 11.5f;
float halfWidth = halfHeight * (GLfloat)w / (GLfloat)h; //based on window aspect ratio
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);
If you want to change the visible area, you just need to adjust the halfHeight. The -1 and 1 are the znear and zfar plane. Everything that is between these planes is visible. Everything else will be cut off. But since you have only 2D content, this should not be relevant.
In your call to glTranslatef(camX, camY, -20);, set the z-coordinate to 0. This is not needed any more, because we have an orthographic view.
Now if you want to check if the map is still visible, do the following. I'll just show the exmple of checking the left/right boundary. The vertical case is similar:
//The camera can see from camX-halfWidth to camX+halfWidth
//You might want to make halfWidth and halfHeight class variables
float leftMapBoundary = 0;
float rightMapBoundary = 500;
//the camera must be
// * at least halfWidth right of the left boundary and
// * at least halfWidth left of the right one:
if(camX < leftMapBoundary + halfWidth)
camX = leftMapBoundary + halfWidth;
if(camX > rightMapBoundary - halfWidth)
camX = rightMapBoundary - halfWidth;
Add the code after the switch in your keyboard function or whenever you move the camera.
I need to make this wheel to make a rotation animation around its center in openGL continuously without clicking the mouse,because the wheel makes its rotation if the left button of the mouse is clicked!!, this is the wheel:
This is the code I used to draw the wheel and to make the rotation:
#include <freeglut.h>
#include <glaux.h>
void whiteStud()
{
glColor3f(1.0, 1.0, 1.0);
glutSolidSphere(0.01, 16, 16);
}
void blackWheel()
{
glColor3f(0.129412, 0.129412, 0.129412);
glutSolidSphere(0.1, 16, 16);
}
void wheelWithStuds()
{
/**********************************/
int iTimeElapsed = glutGet(GLUT_ELAPSED_TIME);
float fScale= 0.5f;
long i;
/**********************************/
/* clear all pixels */
glClear(GL_COLOR_BUFFER_BIT);
/**********************************/
glPushMatrix();
glTranslatef(0.25, 0.25, 0.0);
glRotatef(iTimeElapsed * fScale,0.0,0.0,1.0);
blackWheel(); // draw the wheel without studs.
/**********************************/
// five studs, step 72 degree (72*5=360 degree).
for (i=0; i<5; i++) {
glPushMatrix();
glRotatef(72*i,0.0,0.0,1.0); // rotate coordinate 72 degree.
glTranslatef(0.04, 0.0, 0.0);// translate on the rotated coordinate.
whiteStud(); // draw the stud.
glPopMatrix();
}
glTranslatef(0.0, 0.0, 0.0);// translate in order to draw a stud at the center of the wheel.
whiteStud();// draw the stud at the center of the wheel.
/**********************************/
/* don't wait! start processing buffered OpenGL routines */
glFlush();
glPopMatrix();
/**********************************/
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(10, 10);
glutCreateWindow("(-Rotating Car Wheel-)");
/* select clearing (background) color */
glClearColor(1.0, 1.0,1.0, 1.0);
/* initialize viewing values */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutDisplayFunc(wheelWithStuds);
glutMainLoop();
return 0;
}
I want this wheel to rotate by itself without clicking the left button of the mouse, how can I perform this?
Here is a new draw_wheel() with the desired motion. Notably, you forgot glutPostRedisplay() at the end of the draw method; this function tells glut to redraw the window. Also you were not resetting your first call to glTranslatef(), so every time you clicked the window the object got further away from its original position.
void draw_wheel()
{
int iTimeElapsed = glutGet(GLUT_ELAPSED_TIME);
float fRevolveScale1 = 0.2f;
float fRevolveScale2 = 0.4f;
long i;
// clear all pixels
glClear(GL_COLOR_BUFFER_BIT);
// push temp state
glPushMatrix();
// translate to center
glTranslatef(0.5f, 0.5f, 0.0);
// rotate around pivot
glRotatef(iTimeElapsed * fRevolveScale1,0.0,0.0,1.0);
// translate to planet location
glTranslatef(0.25f, 0.25f, 0.0);
glRotatef(iTimeElapsed * fRevolveScale2,0.0,0.0,1.0);
glColor3f(0.129412f, 0.129412f, 0.129412f);
glutSolidSphere(0.1f, 16, 16);
// five bolts, step 72 degree (72*5=360 degree)
glColor3f(1.0, 1.0, 1.0);
for(i=0; i<5; ++i)
{
glPushMatrix();
glRotatef(72.0f*i,0.0,0.0,1.0); // rotate coordinate 72 degree
glTranslatef(0.04f, 0.0, 0.0);// translate on the rotated coordinate
glutSolidSphere(0.01f, 16, 16);
glPopMatrix();
}
glTranslatef(0.0f, 0.0f, 0.0f);// translate on the rotated coordinate
glutSolidSphere(0.01, 16, 16);
// pop temp state
glPopMatrix();
glFlush();
glutPostRedisplay();
}
I've been experimenting with programs from my text book that involved clipping 2-D polygons using glOrtho and then creating glutWireSpheres in gluPerspective. My goal is to clip half the sphere with a plane, however, I am having trouble clipping 3-D objects. I created a toggle button to show the sphere clipped and unclipped, however, the button instead shows the sphere moving in a ellipse motion I believe.
Here is my drawscene for creating the sphere
double eqn0[4] = {1, 0, 0.0, -60}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
And here is my toggle
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
Can someone help me get in the right direction for clipping 3-D objects? Because this will work on 2-D polygons, yet when I try to apply it to spheres, the toggle button doesn't even act like a toggle.
EDIT: Full code:
#include <cmath>
#include <iostream>
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
#define PI 3.14159265
using namespace std;
// Globals.
static int id1, id2; // Window identifiers.
static int isClip0 = 0; // Is clipping plane 0 enabled?
static int isClip1 = 0; // Is clipping plane 1 enabled?
static int isClip3 = 0; // Is clipping plane 0 enabled?
static int isClip4 = 0; // Is clipping plane 1 enabled?
// Drawing routine for first window.
void drawScene1(void)
{
// Choose window.
glutSetWindow(id1);
glClear(GL_COLOR_BUFFER_BIT);
// A red square.
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(40.0, 10.0, 0.0);
glVertex3f(40.0, 40.0, 0.0);
glVertex3f(10.0, 40.0, 0.0);
glEnd();
glFlush();
}
// Drawing routine for second window.
void drawScene2(void)
{
double eqn0[4] = {1, 0, 0.0, -1000}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
}
// Initialization routine for first window.
void setup1(void)
{
// Black background.
glClearColor(0.0, 0.0, 0.0, 0.0);
}
// Initialization routine for second window.
void setup2(void)
{
// Green background.
glClearColor(1.0, 1.0, 1.0, 0.0);
}
// Reshape routine for first window.
void resize1(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Non-square aspect ratio squashes the square.
glOrtho(0.0, 50.0, 0.0, 100.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Reshape routine for second window.
void resize2(int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)w/(float)h, 1.0, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine shared by both windows.
void keyInput(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
default:
break;
}
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
// First top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(100, 100);
// Create the first window and return id.
id1 = glutCreateWindow("windows.cpp - window 1");
// Initialization, display, and other routines of the first window.
setup1();
glutDisplayFunc(drawScene1);
glutReshapeFunc(resize1);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
// Second top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(400, 100);
// Create the second window and return id.
id2 = glutCreateWindow("windows.cpp - window 2");
// Initialization, display, and other routines of the second window.
setup2();
glutDisplayFunc(drawScene2);
glutReshapeFunc(resize2);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
glutMainLoop();
return 0;
}
Sphere is dealt with in drawScene2
So, after adding a glLoadIdentity() right before the gluLookAt(), the movements will go away (as I already had suggested...). And when one sets a useful clip plane equation, the clipping works as expected, too. As you define a sphere with radius 1 around the object space center, setting
GLdouble eqn0[4] = {1, 0, 0.0, 0.5};
will result in the sphere being clipped at x=-0.5, so 3/4 of it is still visible, as one would expect.