Related
I want to make my shapes to keep rotating by time while I can move them (Left-Right , Down-Up , Front-Back) using keyboard I added a function called timer() that should change the angles of the cube and pyramid by time.
The problem is the code keeps breaking at glutPostOverlayRedisplay(); function and it says :
Exception thrown at 0x10004813 (glut32.dll) in Opengl.exe: 0xC0000005:
Access violation reading location 0x00000020.
how can I fix this problem and why its happening ?
this is the code :
#include <GL/glut.h>
int object = 0;
float xLeftRight[]{ 0, 0 };
float yDownUp[]{ 0, 0 };
float zFrontBack[]{ 0, 0 };
float PyramidAngle = 0.0;
float CupeAngle = 0.0;
int t_refresh = 20;//ms
float degree = 0;
float xscale = 1, yscale = 1, zscale = 1;
void Keyboard(int buttons, int x, int y)
{
switch (buttons)
{
case GLUT_KEY_F1: object = 0; break;
case GLUT_KEY_F2: object = 1; break;
case GLUT_KEY_LEFT: xLeftRight[object] -= 0.1; break;
case GLUT_KEY_RIGHT: xLeftRight[object] += 0.1; break;
case GLUT_KEY_DOWN: yDownUp[object] -= 0.1; break;
case GLUT_KEY_UP: yDownUp[object] += 0.1; break;
case GLUT_KEY_PAGE_UP: zFrontBack[object] -= 0.1; break;
case GLUT_KEY_PAGE_DOWN: zFrontBack[object] += 0.1; break;
}
glutPostRedisplay();
}
void Settings()
{
glClearColor(1, 1, 1, 0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void DrawingFunction()//painting
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); //reset
glTranslatef(1.5f, 0.0f, -6.0f); // rotate left and back by time
glRotatef(PyramidAngle, 1.0f, 1.0f, 0.0f);
glColor3f(1.0, 0.0, 0.0);
glScalef(xscale, yscale, zscale);
glTranslatef(xLeftRight[0], yDownUp[0], zFrontBack[0]); //move the pyramid (if object = 0)
glBegin(GL_TRIANGLES);
// front
glColor3f(1.0f, 0.0f, 0.0f); //red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); //green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); //blue
glVertex3f(1.0f, -1.0f, 1.0f);
// right
glColor3f(1.0f, 0.0f, 0.0f); //red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); //blue
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); //green
glVertex3f(1.0f, -1.0f, -1.0f);
// back
glColor3f(1.0f, 0.0f, 0.0f); //red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); //green
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); //blue
glVertex3f(-1.0f, -1.0f, -1.0f);
// left
glColor3f(1.0f, 0.0f, 0.0f); //red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); //blue
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f); //green
glVertex3f(-1.0f, -1.0f, 1.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glLoadIdentity();//(Reset model-view matrix)
glTranslatef(-2.0f, 0.0f, -7.0f); // rotate the cube right and back by time
glRotatef(CupeAngle, 1.0f, 0.0f, 0.0f);
glTranslatef(xLeftRight[1], yDownUp[1], zFrontBack[1]); //move the cube (if object = 1)
glBegin(GL_QUADS); //cube
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 0.5f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();
glutSwapBuffers();
PyramidAngle += 1.0f; //changing the angle
CupeAngle -= 0.2f; //changing the angle
glPopMatrix();
}
void timer(int value)
{
glutPostOverlayRedisplay();
glutTimerFunc(t_refresh, timer, 0);
}
void ViewSetting(int x, int y)
{
int aspect = x / y;
glViewport(0, 0, x, y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, aspect, 0.1, 20);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowPosition(50, 50);
glutInitWindowSize(800, 600);
glutCreateWindow("3d shapes");
glutDisplayFunc(DrawingFunction);
glutReshapeFunc(ViewSetting);
glutSpecialFunc(Keyboard);
Settings();
glutTimerFunc(0, timer, 0);
glutMainLoop();
return 0;
}
glutPostOverlayRedisplay marks the overlay of the current window as needing to be redisplayed (See Overlay Management).
You have to use glutPostRedisplay:
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(t_refresh, timer, 0);
}
This code is to draw one pyramid and one cube. I am trying to colour them using GL_SMOOTH type by glShadeModel. But the result is that only the pyramid can be smooth while another one cube was only colored like a GL_FLAT one.
It seems that there are some problems with the normal vectors but I was poor at this aspect.
Here are my codes below:
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(1.5f, 0.0f, -7.0f);
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd(); // End of drawing color-cube
// Render a pyramid consists of 4 triangles
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(-1.5f, 0.0f, -6.0f); // Move left and into the screen
glBegin(GL_TRIANGLES); // Begin drawing the pyramid with 4 triangles
// Front
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
// Back
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Done drawing the pyramid
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
Can someone tell me how could this happen?
When you draw the pyramid, then you've one color associated to each vertex coordinate of the triangle primitives. e.g:
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
This causes that the colors of the vertices (corner) are interpolated on the triangle.
When you draw the cube then you've set one color fro each quad. Each corner of the quad is associated to the same color:
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
This causes that the entire quad primitiv is uniform colored. If you want a color gradient, then you've to associate different colors to the vertices (corners).
I'm trying to draw a "transparent" cube (with only edges) and place a pyramid inside this cube, the problem is that the edges of the cube are drawing over pyramid when I rotate it.
Here is an example
I understand why this is happening (because I draw pyramid first and then a cube), but I want that these edges to not be drawn over the pyramid when this is not needed.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QOpenGLWindow>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QTimer>
#ifdef _DEBUG
# include <QDebug>
#endif
class MainWindow: public QOpenGLWindow
{
Q_OBJECT
public:
MainWindow();
private:
QOpenGLContext *m_context;
QTimer m_timer;
GLfloat m_angle;
private slots:
void rotate();
protected:
void initializeGL() override;
void paintGL() override;
void paintEvent(QPaintEvent *event) override;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow():
QOpenGLWindow(),
m_angle(0.0f)
{
QSurfaceFormat sf;
sf.setProfile(QSurfaceFormat::CompatibilityProfile);
sf.setVersion(2, 1);
setFormat(sf);
setSurfaceType(QWindow::OpenGLSurface);
create();
m_context = new QOpenGLContext();
m_context->setFormat(sf);
m_context->create();
m_context->makeCurrent(this);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(rotate()));
m_timer.start(33);
}
void MainWindow::rotate()
{
m_angle += 0.5f;
if (m_angle >= 360.0f) {
m_angle = 0.0f;
}
update();
}
void MainWindow::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
void MainWindow::paintGL()
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.3f, 0.3f, 0.3f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
// The cube (only edges)
glScalef(1.5f, 1.5f, 1.5f);
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glEnd();
glFlush();
}
void MainWindow::paintEvent(QPaintEvent*)
{
paintGL();
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(480, 480);
w.show();
return a.exec();
}
... after that I got vice-versa behavior, take a look at this screenshot It seems like the front edges behave like back edges.
The triangles of your pyramid are set clockwise, but default, counterclockwise polygons are taken to be front-facing. Set glFrontFace(GL_CW) or change the order of glVertex3f.
Could someone explain me why triangle is rendering over quad please ?
When Depth Testing is active, the fragments will be displayed depending on their depth. The depth value from the fragment is compared to the depth value from the matching sample currently in the framebuffer. The conditional test is specified by the function glDepthFunc. The initial value of glDepthFunc is GL_LESS.
In your example the depth of the triangle's fragments is LESS than that of the quad's fragments, so the triangle is over the quad.
Setting minimal depth buffer didn't changed anything for me (likely because platform setting was already 24, but checking those defaults is not without merit). The problem is that displayed order of cube's edges still look wrong: the edge that supposed to be closer is painted over by pyramid.
Because you don't do anything about visibility of edges it causes illusion that cube must be rotating in direction opposite and perpendicular to rotation of pyramid.
The problem is that it's pyramid which is actually wrong. Let me prove that:
glBegin(GL_QUADS);//(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
Resulting image is:
Cube rotates in supposed direction, it isn't inside out. That means that pyramid is. One reason of that is that we actually see back faces, not front ones.
If I convert your code to emulate transparent pyramid, , but save default culling settings:
void MainWindow::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/*...*/
glFrontFace(GL_CCW);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 0.3f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(0.0f, 1.0f, 0.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor4f(0.0f, 0.0f, 1.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(1.0f, 1.0f, 0.0f, 0.3f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor4f(0.0f, 1.0f, 1.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glFrontFace(GL_CW);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 0.6f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(0.0f, 1.0f, 0.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor4f(0.0f, 0.0f, 1.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(1.0f, 1.0f, 0.0f, 0.6f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor4f(0.0f, 1.0f, 1.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
I get image
I still see how pyramid rotates, all of its edges and that line of cube that is "behind" is clipped (because blending does nothing to depth test).
But now if you look at the "bold" faces of pyramid - I intentionally made faces that are invisible without blending bold by giving them larger alpha value - you'll see that they rotate properly, in same direction as cube does. That means that your mesh, the pyramid, is actually inverted, "inside out". With non-convex figures that would be more obvious, with convex ones that creates illusion of opposite rotation.
All you should do is change order of vertices or switch to GL_CW for pyramid (GL_CCW is default).
I surmise that this is expected look of the pyramid, if the face colors are taken in account. If it isn't, that means that you assumed that vertices with greater Z-coordinate is further away from projection plane. With Identity projection matrix and GL_LESS depth test function it's opposite. Be advised, if you switch direction of only one axis, that literally inverts all rules that related to direction of rotation, counterclockwise becomes clockwise.
NB: Trick I used for transparency illusion doesn't work that well with non-convex figures. Why? To use color blending you have to draw faces in order of their depth test doing this manually. My dirty trick does draw all faces twice, but culling removes those which face camera during first pass, and removes those which face away during second pass. For non-convex that doesn't match the order - there are faces that face camera but are further away than some "hidden" ones, wrong order. More work is required. Usage of flexible pipeline really changes how OpenGL can handle this.
I've finally done it:
#include "mainwindow.h"
MainWindow::MainWindow():
QOpenGLWindow(),
m_angle(0.0f)
{
QSurfaceFormat sf;
sf.setProfile(QSurfaceFormat::CompatibilityProfile);
sf.setDepthBufferSize(24);
sf.setVersion(2, 1);
setSurfaceType(QWindow::OpenGLSurface);
setFormat(sf);
create();
m_context = new QOpenGLContext(this);
m_context->setFormat(sf);
m_context->create();
m_context->makeCurrent(this);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(rotate()));
m_timer.start(33);
}
void MainWindow::rotate()
{
m_angle += 0.5f;
if (m_angle >= 360.0f) {
m_angle = 0.0f;
}
update();
}
void MainWindow::initializeGL()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(-1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
}
void MainWindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// The Pyramid
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.33f, 0.33f, 0.33f);
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_TRIANGLES);
// Front
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
// Bottom
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
// The Cube (edges)
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.5f, 0.5f, 0.5f);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
// Front
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Back
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
// Left
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
// Right
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glEnd();
glFlush();
}
void MainWindow::paintEvent(QPaintEvent*)
{
paintGL();
}
Probably this solution is far from ideal, but it does exactly what I need (any tips would be appreciated).
demo image
I'd like to thank #Swift - Friday Pie and #Asaq for such detailed answers which helped me a bit more to understand how opengl works.
If anyone is interested - I'm on Linux (Fedora 28), graphic card is Intel HD Graphics 530 (Skylake GT2).
I need help. I have found several solutions to draw cube in OpenGl, but I have a problem.
My code is:
wglMakeCurrent(pDC->m_hDC, m_hrc);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(1.5f, 0.0f, -7.0f); // Move right and into the screen
glBegin(GL_QUADS); // Begin drawing the color cube with 6 quads
// Top face (y = 1.0f)
// Define vertices in counter-clockwise (CCW) order with normal pointing out
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd(); // End of drawing color-cube
glFlush();
SwapBuffers(pDC->m_hDC);
wglMakeCurrent(NULL, NULL);
Bellow is the image I want to get and the image I get.
expected image and the image I get
How to solve this problem?
You'll have to enable depth testing. Otherwise triangles are drawn in the order the are given in code which leads to overdraws even if a triangle is behind another one. To enable depth-testing call
glEnable(GL_DEPTH_TEST);
before issuing the first draw-call.
The following code draws a labyrinth or maze in OpenGL, the result is a 2D labyrinth, what I need to do now is to draw cubes instead these quads, how can I do it?
function drawmaze() {
int x,y,dl;
glNewList(dl=glGenLists(1),GL_COMPILE);
glPushAttrib(GL_TEXTURE_BIT | GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_QUADS);
// glPushMatrix();
float i = 0;
for(y=0;y < mazedata.size();y++) {
for(x=0;x < mazedata[y].size();x++) {
bool dibujar = false;
if(wall(x,y)) {
glColor3ub(46,151,208);
drawable = true;
}
else
if (entry(x,y)) {
glColor3f(0.0f,0.184f,0.792f);
drawable = true;
}
else
if (mazexit(x,y)) {
glColor3f(0.811f,0.188f,0.176f);
drawable = true;
}
else
if (thing(x,y)) {
glColor3ub( 151, 204, 0 );
drawable = true;
}
else
if (visited(x,y)) {
glColor3ub( 66, 66, 66 );
drawable = true;
}
if (drawable) {
//glPushMatrix();
/*
This is a try
glTranslatef(1.0,0., 0.0f );
glutSolidCube(0.5);*/
//glPopMatrix();
glVertex3f(x+0.0f ,y+0.0f ,0.0f );
glVertex3f(x+0.0f ,y+1.0f ,0.0f );
glVertex3f(x+1.0f ,y+1.0f ,0.0f );
glVertex3f(x+1.0f ,y+0.0f ,0.0f );
// topside:
glVertex3f(x+0.0f ,y+0.0f ,1.0f );
glVertex3f(x+1.0f ,y+0.0f ,1.0f );
glVertex3f(x+1.0f ,y+1.0f ,1.0f );
glVertex3f(x+0.0f ,y+1.0f ,1.0f );
}
}
i++;
}
glEnd();
// glPopMatrix();
glPopAttrib();
glEndList();
return(dl);
}
glBegin(GL_QUADS);
// front
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// back
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
// right
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
// left
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// top
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
// bottom
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glEnd();
There is no native opengl method that will draw a cube.
So you will have to draw 6 quads to draw a cube.