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).
Related
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();
I am getting the following errors:
QWidget::repaint: Recursive repaint detected.
QPainter::begin: A paint device can only be painted by one painter at a` time.
QPainter::beginNativePainting: Painter not active.
QPainter::setRenderHint: Painter must be active to set rendering hints.
QPainter::translate: Painter not active.
void Graficador::paintEvent(QPaintEvent *event){
QPainter painter;
painter.begin(this);
painter.beginNativePainting();
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(250, 250);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.2,0.4,0.3,1);
glClear(GL_COLOR_BUFFER_BIT);
std::vector<unsigned short> nodosaux;
glPushMatrix();
for (unsigned i=1;i<=automata->Dimension();i++)
{
nodosaux=(automata->operator [](i))->Nodos();
if((automata->operator [](i))->Estado()==0)
glColor3f(0.3,0.3,0.3);
else if((automata->operator [](i))->Estado()==1.0)
glColor3f(1.0,1.0,1.0);
else if((automata->operator [](i))->Estado()==2.0)
glColor3f(0.7,0.7,0.7);
glBegin(GL_POLYGON);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
}
glPopMatrix();
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINES);
glVertex2f(-500.0,0.0);
glVertex2f(500.0,0.0);
glVertex2f(0.0,-500.0);
glVertex2f(0.0,500.0);
glEnd();
glPopMatrix();
painter.endNativePainting();
painter.end();
}
(Sorry for the use of operator, I know that its not the proper use but I need to solve this problem first).
This is the paintEvent() of a QGLWidget. I had no problem until I started using a pointer of my class "automata". This class only have some vectors with the coordinates (x,y) of the vertices, so I have no idea why I have this problem.
The complete program has a big class System that has inside: a user interface, an automata and some other classes that are used for other tasks. The user interface has this QGLWidget inside, and the automata that I'm trying to use here is a pointer that points to the automata in the system class.
I'm passing that pointer like this:
void Cargar_automata(Automata_Celular* ac)
{
automata = new Automata_Celular();
automata =ac;
}
I have some other widgets but they are only buttons to manage files and timers.
When using an OpenGL widget in Qt all painting should be done in a member called paintGL(). You are using the paintEvent which is what is causing the error messages you are seeing.
So your code should look something like this:
void Graficador::paintGL(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.2,0.4,0.3,1);
glClear(GL_COLOR_BUFFER_BIT);
std::vector<unsigned short> nodosaux;
glPushMatrix();
for (unsigned i=1;i<=automata->Dimension();i++)
{
nodosaux=(automata->operator [](i))->Nodos();
if((automata->operator [](i))->Estado()==0)
glColor3f(0.3,0.3,0.3);
else if((automata->operator [](i))->Estado()==1.0)
glColor3f(1.0,1.0,1.0);
else if((automata->operator [](i))->Estado()==2.0)
glColor3f(0.7,0.7,0.7);
glBegin(GL_POLYGON);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
}
glPopMatrix();
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINES);
glVertex2f(-500.0,0.0);
glVertex2f(500.0,0.0);
glVertex2f(0.0,-500.0);
glVertex2f(0.0,500.0);
glEnd();
glPopMatrix();
}
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.
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'm creating a 2D game and when the player dies I want the texture I to switch to another (to show an explosion) I also want the game to pause for a second or two so the user can see that the texture has changed.
My textures are loading correctly because I can apply it to a shape and i can see it if I say switched it with the players original texture.
I think that it must be that it is only rendering in one frame and then disappearing or something like that. Here is the code.
void Player::die(){
if(Player::lives > 0){
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, explosionTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTranslatef(200, 200, 0.0);
glRotatef(heading, 0,0,1);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 1.0); glVertex2f(-40,40);
glTexCoord2f(0.0, 0.0); glVertex2f(-40,-40);
glTexCoord2f(1.0, 0.0); glVertex2f(40,-40);
glTexCoord2f(1.0, 1.0); glVertex2f(40,40);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
Sleep ( 1000 );
*xscroll = 0;
*yscroll = 0;
Player::lives--;
Player::XPos = 0;
Player::YPos = 0;
Player::heading = 0;
Player::speed = 0;
}
}
How can I get it to switch texture, display that and then sleep for a time?
You need to swap your buffers before you Sleep() if you want to see anything.
More generally, replace the Sleep() with a ExplodeStart, which you set to CurrentTimeInMilliseconds(). Then each time through your render loop check if CurrentTimeInMilliseconds()-ExplodeStart > 1000. If it is, switch to your regular player texture again.