anyone can teach me how to draw 2 objects, for example a cube and a sphere, in origin (0, 0, 0) and when i move the cube, the sphere just remains in the origin. same with moving the sphere, the cube remains..
using keyboardfunc.
if (!LightSwitch)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPushMatrix();
glTranslatef(CubeX, CubeY, CubeZ);
glColor3f(1.0, 0.0, 0.0);
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Green);
glutSolidCube(2.0);
glPopAttrib();
glPopMatrix();
glEnd();
}
if (!LightSwitch1)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
glPushMatrix();
glTranslatef(AxisX, AxisY, AxisZ);
glColor3f(1.0, 0.0, 0.0);
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Blue);
glutSolidSphere(2.0, 10.0, 5.0);
glPopAttrib();
glPopMatrix();
}
glEnd();
I'm no expert, but I believe that by having separate glPushMatrix() / glPopMatrix() blocks for the sphere and the cube, you are giving each object its own local coordinate system. This is why they transform independent of each other.
If you want to move them together, you need to specify glTranslate() outside your glPushMatrix() / glPopMatrix() first:
glTranslatef(translation....); // Translates the whole scene
glPushMatrix();
glTranslatef(the sphere); // Sphere & cube locations changeable via keyb.
glTranslatef(the cube);
glPopMatrix();
If you want to, say, rotate the cube with respect to the sphere (ie., make the center of the sphere the origin of the cube's coordinate system), make a new glPushMatrix()/glPopMatrix() block nested within the first block:
glPushMatrix();
glTranslatef(the sphere);
glPushMatrix();
glRotatef(the cube); // Rotate about specific axis of the sphere
glPopMatrix();
glPopMatrix();
I believe your code is correct for drawing the sphere at location Axis and the cube at location Cube. You say you are using a keyboard func and it is moving them both together when you want to move just one. I believe you are updating both sets of variables in your keyboard function. Try printing out CubeXYZ and AxisXYZ and make sure you're getting the right thing.
Related
I am currently working on a project with OpenGL. I wanted to stick an image onto the sign below to make it more realistic. Is there a way to do this with OpenGL? Maybe loading the image in and paint it onto the shape?
Here is the code to create the block of sign:
//Set the size and position
glPushMatrix();
glTranslatef(-550.0, 500.0, fltSignOffset);
glScalef(700.0, 150.0, 20.0);
//Create the shape
glPushMatrix();
glColor3f(0.0, 0.55, 0.27); //Use SpringGreen4 for sign
glutSolidCube(1);
//Create the wireframe of the shape
glColor3f(0.0, 0.0, 0.0);
glutWireCube(1);
glPopMatrix();
glPopMatrix();
I am currently working on the printing loop of my software that reads 3D obj file.
I have stored my obj file read in the variable tie. This variable contain an OpenGL list. My objective is to be able to move around the read object by using keyboard. The keyboard reading is implemented correctly (i can see in through the logs).
Issue
When i compile the following code loop, the gluLookAt exucute properly and I am able to move around my object by changing the value of the parameters.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
light();
gluPerspective (60.0, 250/(float)250, 0.1, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,eyeX+directionX,eyeY+directionY,eyeZ+directionZ,upX,upY,upZ);
glPushMatrix();
glRotated(45,0,0,1);
glTranslated(0,0,50);
glBindTexture(GL_TEXTURE_2D,texture1);
//glCallList(xwing); //ICI
glEnd();
glPopMatrix();
glColor3d(1,1,1);
glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture2);
GLUquadric* params = gluNewQuadric();
gluQuadricDrawStyle(params,GLU_FILL);
gluQuadricTexture(params,GL_TRUE);
gluSphere(params,100,20,20);
gluDeleteQuadric(params);
glEnable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture1);
glCallList(tie); //ICI
glPointSize(5.0);
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(-1.0f,0.0f,0.0f);
glEnd();
SwapBuffers(hDC);
//} //else
Sleep(1);
But when i comment these 4 lines:
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(-1.0f,0.0f,0.0f);
glEnd();
My object doesn't move anymore. As if gluLookAt didn't succeed to execute.
Do you have any idea why is this happening. Did I forget something in my code?
glBegin and glEnd delimit the vertices that define a primitive or a group of like primitives. You have to ensure, the each glBegin is followed by a glEnd.
This means, if your Display Lists contains a glBegin then it should contain a glEnd, too. I strongly recommend to do it this way. The other possibility would be to do it manually after glCallList:
glCallList(tie);
glEnd();
glPushMatrix and glPopMatrix are used to push matrices on and pop matrices from the matrix stack. If you want to add a model matrix to the view matrix, then you have to do the following steps.
Push the view matrix glPushMatrix. This pushs a copy of the view matrix on the stack.
Add the model matrix to the current view matrix (glRotated, glTranslated, ... )
Draw the model. (glCallList, gluSphere, ... )
Restore the original view matrix (glPopMatrix).
Adapt your code somehow like this:
// set up view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,eyeX+directionX,eyeY+directionY,eyeZ+directionZ,upX,upY,upZ);
// save view matrix
glPushMatrix();
// add model matrix
glRotated(45,0,0,1);
glTranslated(0,0,50);
// do the drawing
glColor3d(1,1,1);
glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture2);
GLUquadric* params = gluNewQuadric();
gluQuadricDrawStyle(params,GLU_FILL);
gluQuadricTexture(params,GL_TRUE);
gluSphere(params,100,20,20);
gluDeleteQuadric(params);
glEnable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture1);
glCallList(tie);
glEnd(); // <-- maybe this could be done in "tie"
// restore the view matrix
glPopMatrix();
So I draw an 'I' and use gluLookAt(0.f,0.f,3.f,0.f,0.f,0.f,0.f,1.f,0.f), and the I is moderate size. Then I add a drawScene() function which draw the background with gradient color, and then the 'I' becomes super big. I guess it is because I change matrix mode to GL_PROJECTION and GL_MODELVIEW in drawScene(), and those change the perspective maybe? I guess glPushMatrix() and glPopMatrix() are needed to reserve matrix status, but I have hard time finding where to put them. So how can I make the 'I' look normal size? Here are my drawI() and drawScene():
void drawI(int format)
{
glBegin(format);
glColor3f(0, 0, 1);
glVertex2f(point[3][0], point[3][1]);
glVertex2f(point[2][0], point[2][1]);
glVertex2f(point[1][0], point[1][1]);
glVertex2f(point[12][0], point[12][1]);
glVertex2f(point[10][0], point[10][1]);
glEnd();
glBegin(format);
glVertex2f(point[10][0], point[10][1]);
glVertex2f(point[11][0], point[11][1]);
glVertex2f(point[12][0], point[12][1]);
glEnd();
glBegin(format);
glVertex2f(point[9][0], point[9][1]);
glVertex2f(point[10][0], point[10][1]);
glVertex2f(point[3][0], point[3][1]);
glVertex2f(point[4][0], point[4][1]);
glVertex2f(point[6][0], point[6][1]);
glColor3f(1, 0.5, 0);
glVertex2f(point[7][0], point[7][1]);
glVertex2f(point[8][0], point[8][1]);
glEnd();
glBegin(format);
glColor3f(0, 0, 1);
glVertex2f(point[5][0], point[5][1]);
glVertex2f(point[6][0], point[6][1]);
glVertex2f(point[4][0], point[4][1]);
glEnd();
}
void drawScene()
{
glBegin(GL_QUADS);
//red color
glColor3f(1.0,0.0,0.0);
glVertex2f(-1.0,-1.0);
glVertex2f(1.0,-1.0);
//blue color
glColor3f(0.0,0.0,1.0);
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd();
}
Thanks a lot!
So I take glMatrixMode() and glLoadIdentity() out of drawScene() and drawI() and put them in display(). I changed drawScene() and drawI() above, and here is my display()
void display()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.f,1.f,0.001f,30.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawScene();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.f,0.f,3.f,0.f,0.f,0.f,0.f,1.f,0.f);
drawI(GL_TRIANGLE_FAN);
glutSwapBuffers();
}
The normal way to do this (in a 3D mode) is in your code, before you call drawI or drawScene would be:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, aspect, near, far); // fov is camera angle in degrees, aspect is width/height of your viewing area, near and far are your near and far clipping planes.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,3.0,0.0,0.0,0.0,0.0,1.0,0.0)
In your 2D rendering, you probably don't need the call to gluPerspective, but these calls should be done in your code before you call drawI or drawScene. Do this and delete the glMatrixMode() and glLoadIdentity() calls from drawI and drawScene.
Edit:
If your "I" is still too big, there are a number of things you could do, but you should probably be operating in 3D (giving a Z coordinate also).
You could scale the object:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,3.0,0.0,0.0,0.0,0.0,1.0,0.0)
glScalef(0.5, 0.5, 0.5);
You could move the camera further back (you'll need to include the gluPerspective() call as well):
gluLookAt(0.0,0.0,50.0,0.0,0.0,0.0,0.0,1.0,0.0);
Perhaps the easiest way to control the rendered image size in a 3D mode is to both move the camera (eye) back a way and then control the image size by changing the camera aperture angle (fov in the gluPerspective() call). A wider fov will shrink the rendered image; a smaller fov will enlarge it.
I don't know what the values for your coordinates are in drawI since they're variables, but a camera position of 3.0, an fov of 70.0 and an aspect of 1 should give you left, right, top and bottom clipping planes of about +/- 2.1 at Z = 0.
If you kept everything else the same and moved the camera to 50.0, the clipping planes would be at about +/- 35.0, so your "I" would occupy a much smaller portion of the viewing area.
If you then left the camera position at 50.0, but changed the fov to 40.0, the clipping planes would be at about +/- 18.2. Your "I" would fill a larger area than it did at cameraZ = 50.0, fov = 70.0, but a smaller area than cameraZ = 3.0, fov = 70.0.
You can play with camera position and fov to get the image size you want, or you could just scale the image. I like to keep camera position constant and change the fov. If I provide a function that changes the fov based on user input (maybe a mouse scroll), it's a good way to provide a zoom in/out effect.
BTW, in your original code, if you called:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,3.0,0.0,0.0,0.0,0.0,1.0,0.0)
Then later in DrawI or drawScene call:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
You've trashed the matrix loaded by your earlier call to gluLookAt().
i want to draw a rotating cube in the middle of the screen, and i want it to be lit by a light above it (i want it to look as if the cube was being lit from a fixed screen position). my problem is that i don't know how to prevent the light from rotating with the cube.
here's the code:
(SUMMARY: initGL, paintGL, and resizeGl are the functions that you always have to implement. in paintGL i use makeCube(). in makeCube() i use glBegin(GL_QUADS) to make a cube,and i use calcNormals() to calculate the normals of the cube )
-------------initGL--------------------------
angle=0.0;
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 1.5f,1.5f, 1.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
glEnable (GL_LIGHT0);
--------------paintGL------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -13.0);
glRotatef(angle,0.0f,1.0f,0.0f);
makeCube();
angle+=0.3;
--------------void makeCube()-------------------
float P[8][3]={ {-1,-1, 1},{1,-1, 1},{1,1, 1},{-1,1, 1},
{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1}};
float * planes[6][4] ={ {P[0],P[1],P[2],P[3]},
{P[1],P[5],P[6],P[2]},
{P[4],P[7],P[6],P[5]},
{P[0],P[3],P[7],P[4]},
{P[3],P[2],P[6],P[7]},
{P[0],P[4],P[5],P[1]}};
int i;
for(i=0;i<6;i++){
float *normal;
normal = calcNormal(planes[i][0],planes[i][1],planes[i][2]);
glBegin(GL_QUADS);
glNormal3f(normal[0], normal[1], normal[2]);
glVertex3f(planes[i][0][0],planes[i][0][1],planes[i][0][2]);
glVertex3f(planes[i][1][0],planes[i][1][1],planes[i][1][2]);
glVertex3f(planes[i][2][0],planes[i][2][1],planes[i][2][2]);
glVertex3f(planes[i][3][0],planes[i][3][1],planes[i][3][2]);
glEnd();
}
----------------float* calcNormal()----------------------
float vec1[3] = {P2[0]-P1[0],P2[1]-P1[1],P2[2]-P1[2]};
float vec2[3] = {P3[0]-P2[0],P3[1]-P2[1],P3[2]-P2[2]};
float cross[3] = {vec1[1]*vec2[2]-vec2[1]*vec1[2],
vec1[2]*vec2[0]-vec2[2]*vec1[0],
vec1[0]*vec2[1]-vec2[0]*vec1[1]};
float modCross = sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2]);
cross[0]/=modCross;
cross[1]/=modCross;
cross[2]/=modCross;
return cross;
-------------resizeGL--------------------------
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat x = GLfloat(width) / height;
glFrustum(-x, +x, -1.0, +1.0, 4.0, 15.0);
glMatrixMode(GL_MODELVIEW);
It seems that you're transforming the position of the light in your paintGL section.
Looking over old code, I found an app in my code directory that loads and rotates .OBJ meshes, while allowing the light to be moved.
I think that the solution is to set the position of the light each frame. (Can't remember it's been over 18 months since I touched the project)
void idleFunc()
{
light(); /// *** I think you need to replicate this functionality ****
glPushMatrix();
myGluLookAt(0.0, -.50, -6.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
transformFunc();
displayFunc();
glPopMatrix();
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (useDrawList)
glCallList(DLid);
else
drawObj(loadedObj);
drawLight0(); // *** just displays an unlit sphere at the position of the light **
glutSwapBuffers();
frameCount++;
}
/* set the poition of each of the lights */
void light()
{
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
}
i solved this problem drawing the cube with VERTEX ARRAYS rather than DIRECT MODE, it seems that rotations or lights affect the object in a different way with each method, which is quite weird
I have put all the necessary files[temp link removed] if you need to have a look.
mavStar.exe is my program.
The function currently I‘m trying to debug is :
void drawOG()
{
int curr,right,back,bottom;
//Does NOT draw the right most,back most,bottom most layer at the moment
//Does NOT draw face between state 1 & 2
for(int z=0;z+1 < occupancyGrid->Nz; z++){
glPushMatrix();
for(int y=0;y+1 < occupancyGrid->Ny; y++){
glPushMatrix();
for(int x=0;x+1 < occupancyGrid->Nx; x++){
curr = occupancyGrid->M[x][y][z];
right = occupancyGrid->M[x+1][y][z];
back = occupancyGrid->M[x][y][z+1];
bottom = occupancyGrid->M[x][y+1][z];
drawCube(RIGHT_FACE,colorBetween(curr,right));
drawCube(BACK_FACE,colorBetween(curr,back));
drawCube(BOTTOM_FACE,colorBetween(curr,bottom));
glTranslatef (HALF_VOXEL_SIZE*2, 0.0, 0.0);
}
glPopMatrix();
glTranslatef (0.0, -HALF_VOXEL_SIZE*2, 0.0);
}
glPopMatrix();
glTranslatef (0.0, 0.0, -HALF_VOXEL_SIZE*2);
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//mouse tracking
glRotatef(fYDiff, 1,0,0);
glRotatef(fXDiff, 0,1,0);
glRotatef(fZDiff, 0,0,1);
glScalef(fScale, fScale, fScale);
//draw model
glMatrixMode(GL_MODELVIEW);
drawOG();
printOpenGLError(); // Check for OpenGL errors
glutSwapBuffers();
}
There is a much easier way to draw the faces you want by using:
glPushMatrix();
glBegin(GL_QUADS);
//Draw the 16 vertices with their normals.
glEnd();
glPopMatrix();
For example if you want the front:
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(1.0f,1.0f,1.0f);
glNormal3f(0.0,0.0,1.0);
glVertex3f( position[0], position[1], position[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f( position1[0], position1[1], position1[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f(position2[0], position2[1], position2[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f(position3[0], position3[1], position3[2]);
glEnd();
glPopMatrix();
Draw the faces on a piece of paper to figure out what values you need for position,position1,position2,position3,etc. Named them so for general purpose, it should be fairly easy to determine their coordinates.
If you want to give it a touch of flexibility you can create a Cube class and render only the faces for witch you have set a flag to be on. By using a class you gain lots of control on how you want your render-able object to be displayed (color,position,scale, etc).