I am trying to draw some particles using GLFW and OpenGL. However, the output of the scene is weird.
I have 8 positions that they are a coordinates of a cubic in space:
-0.5 -0.5 -0.5 \\ position of particle 1
-0.5 -0.5 0.5 \\ position of particle 2
-0.5 0.5 -0.5 \\ position of particle 3
-0.5 0.5 0.5 \\ position of particle 4
0.5 -0.5 -0.5 \\ position of particle 5
0.5 -0.5 0.5 \\ position of particle 6
0.5 0.5 -0.5 \\ position of particle 7
0.5 0.5 0.5 \\ position of particle 8
and here is my OpenGL code for drawing them:
\\ First initialising:
void initializationGL()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
}
\\ Code for resizing the window:
void resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
\\ Code for drawing:
void PaintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
for (int i=0; i<env.Particles.size(); i++){
glTranslatef(Particles[i].X(0), Particles.X(1), Particles[i].X(2)); \\ X is an attribute of Particle that store poistion of that particle in space (X(0)=x, X(1)=y, X(2)=z)
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glLineWidth(2.0);
GLUquadric *quad;
quad = gluNewQuadric();
gluSphere(quad, 1, 100, 20);
}
glPopMatrix();
}
Here is the code for windowing and update the scene:
int main(int argc, char **argv)
{
GLFWwindow* window;
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(800, 800, "PBsimulation", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
initializationGL();
resizeGL(width, height);
PaintGL();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
However, the output of the code is:
Which is weird. They should be 8 vertex of a cube.
I think I need to adjust OpenGL code to adjust the view port so that all particle become visible and show vertexes of a cube. Any idea how can I do it?
I think I need to adjust OpenGL code to adjust the view port
No, the viewport rectangle is fine. You do not need to adjust the viewport, but you might need to adjust the viewing volume. The viewing volume is the area of the scene projected onto the viewport and defined by the projection matrix. However, that is also not the problem in this case.
glTranslate does not just set a translation, but specifies a translation matrix and multiplies the current matrix by the translation matrix. This permanently changes a global state.
Each of your spheres has its own translation, but the translations of the spheres should not be concatenated. Therefore, the current matrix must be saved and restored in the loop that draws the spheres:
void PaintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
for (int i=0; i<env.Particles.size(); i++){
glPushMatrix();
glTranslatef(Particles[i].X(0), Particles.X(1), Particles[i].X(2)); \\ X is an attribute of Particle that store poistion of that particle in space (X(0)=x, X(1)=y, X(2)=z)
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glLineWidth(2.0);
GLUquadric *quad;
quad = gluNewQuadric();
gluSphere(quad, 1, 100, 20);
glPopMatrix();
}
}
Related
I am trying to look at a cone lying on its side from above. For this I wrote the following code:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(250, 250, 0);
glRotatef(90, 1, 0, 0);
glutSolidCone(20, 20, 20, 20);
glTranslatef(-250, -250, 0);
glRotatef(-90, 1, 0, 0);
glFlush();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
float x, y;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("Cone");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMotionFunc(drag);
glutMouseFunc(click);
glutSpecialFunc(catchKey);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
I translate to the middle of the screen and then rotate 90 degrees around the x-axis, which in my idea should produce the cone on its side. The result however is a not a cone but a line which is not tilted 90 but 45 degrees. What should I change in order for the cone to show up as I want it to?
Where is the projection matrix?
If you don't set a projection matrix, then the coordiantes have to be set in normalize device space. In NDC all the coordinates are in range [-1.0, 1.0]:
e.g.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0);
glRotatef(90, 1, 0, 0);
glutSolidCone(1.0, 1.0, 20, 20);
glTranslatef(-0.5, -0.5, 0);
glRotatef(-90, 1, 0, 0);
Alternatively you can setup an orthographic projection, which projects the world coordinates 1:1 to the window coordinates. The projection matrix can be set by glOrtho:
e.g.
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 500.0, 500.0, 0.0, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(250, 250, 0);
glRotatef(90, 1, 0, 0);
glutSolidCone(20, 20, 20, 20);
glTranslatef(-250, -250, 0);
glRotatef(-90, 1, 0, 0);
glFlush();
glutSwapBuffers();
}
The projection matrix describes the mapping from 3D points of the view on a scene, to 2D points on the viewport. At Orthographic Projection, the view space coordinates are linearly mapped to the clip space coordinates. The clip space coordinates are equal to the normalized device coordinates.
The normalized device coordinates are linearly mapped to the viewport rectangle.
The viewport rectangle can be defined by glViewport. Initially it is defined by the size of the window.
Note, that drawing by glBegin/glEnd sequences and the fixed function matrix stack is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL.
Read about Vertex Specification and Shader for a state of the art way of rendering.
I've created a program in OpenGL that draws some shapes. I want the user to be able to zoom in on the shapes if they want to. This is the code that draws the shapes:
/*Initialise the required OpenGL functions*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, screenWidth, screenHeight, 0.0, -1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_CULL_FACE);
glClear(GL_DEPTH_BUFFER_BIT);
/*Draw a square*/
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex2f(screenWidth * 0.75, screenHeight * 0.08333);
glVertex2f(screenWidth * 0.75, screenHeight * 0.16666);
glVertex2f(screenWidth * 0.86666, screenHeight * 0.16666);
glVertex2f(screenWidth * 0.86666, screenHeight * 0.08333);
glEnd();
glColor3f(0, 0, 0);
/*Let the user zoom*/
if (GetAsyncKeyState(VK_UP))
{
/*"zoom" is a global variable*/
zoom += 0.005;
}
glScaled(1 + zoom, 1 + zoom, 1);
/*Everything that is drawn from this point on (A sphere and a cube) should be scaled*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.3, 0, 0);
glutSolidSphere(3, 20, 20);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.55, 0.36, 0);
glutSolidCube(0.05);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glutSwapBuffers();
The code draws the shapes properly, but the shapes can't be scaled. I've used similar code in some other functions, so I believe that it may be because I am using 3D shapes or it may have something to do with me calling "glMatrixMode" multiple times. Either way, how should I change my code so that the cube and sphere are scaled based on user input, but the first square is not affected?
glScaled() changes the current matrix. So as soon as you call glLoadIdentity() you are undoing your scaling. You are doing lots of unnecessary calls to glMatrixMode() and glLoadIdentity() that should be eliminated. So try something more like this:
// You probably don't really need to do these, but if you do, do it once up top.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix(); // Save the current matrix
glScaled(1 + zoom, 1 + zoom, 1); // Scale it
/*Everything that is drawn from this point on (A sphere and a cube) should be scaled*/
glTranslatef(-0.3, 0, 0);
glutSolidSphere(3, 20, 20);
glTranslatef(0.55, 0.36, 0);
glutSolidCube(0.05);
glPopMatrix(); // Undo the glScaled() call above
glutSwapBuffers();
I have a backgroundless image of a gun. I am trying to build a first person shooter game with the help of this 2D image of a gun. I have loaded the texture in my program but I am unable to make the background of the gun transparent. Moreover, why should I even have to do that when my image is already backgroundless. I used clippingmagic.com to remove the background of my image. The code is:
#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include<SOIL/SOIL.h>
//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
const float A = 1366.0; //width of the computer screen
const float B = 768.0; //height of the computer screen
//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
int x, int y) { //The current mouse coordinates
switch (key) {
case 27: //Escape key
exit(0); //Exit the program
}
}
//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
}
//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0); //The far z clipping coordinate
}
//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0.0,0.0,-10.0);
//DRAW WALL OF ROOM
glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 1.0);
glVertex3f(-100.0, -100.0, -100.0);
glVertex3f(-100.0, 100.0, -100.0);
glVertex3f( 100.0, 100.0, -100.0);
glVertex3f( 100.0, -100.0, -100.0);
glEnd();
//DRAW GUN
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLuint gun_tex_id = SOIL_load_OGL_texture
(
"GUN.png",
SOIL_LOAD_RGB, //I even tried SOIL_LOAD_AUTO and SOIL_LOAD_RGBA but it didn't help
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_MULTIPLY_ALPHA
);
glBindTexture(GL_TEXTURE_2D, gun_tex_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTranslatef(2.0,0.0,0.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-4.1,-4.15, 0.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 3.0,-4.15, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 3.0, 1.2, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-4.1, 1.2, 0.0);
glEnd();
glDisable(GL_BLEND);
glutSwapBuffers(); //Send the 3D scene to the screen
}
void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); /* gray background */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( -A/2, A/2, -B/2, B/2, -200, 200);
/* In World coordinates:position the "clipping rectangle" at -A/2, its right edge at +A/2, its bottom edge at -B/2 and its top edge at +B/2 */
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(A, B); //Set the window size
//Create the window
glutCreateWindow("My shooting game");
initRendering(); //Initialize rendering
//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
myinit();
glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}
You can do it using glBlendFunc function.
Try adding the following code snippet before you bind texture to the object.
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Read this for more information.
My origin is not at top left corner, when I resize my window. And the 2d coordinates are not in pixel coordinates:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rnd::initDraw();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, mainPanelx, mainPanely, 0.0, -1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
//glPushMatrix(); ----Not sure if I need this
glLoadIdentity();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0);
glVertex2f(0.0, 0.0);
glVertex2f(10.0, 0.0);
glVertex2f(10.0, 10.0);
glVertex2f(0.0, 10.0);
glEnd();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glutSwapBuffers();
Resize function:
void resize(int width, int height)
{
if (height == 0) height = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/* note we divide our width by our height to get the aspect ratio */
gluPerspective(45.0, width / height, 1.0, 400.0);
glMatrixMode(GL_MODELVIEW);
mainPanelx = width;
mainPanely = height;
std::cout<<mainPanelx<<", "<<mainPanely<<"\n";
}
How do i get the origin constant at the top left corner of my window and how do i get the 2d coordinates in pixel coordinates?
You forgot to call glViewport in your resize function.
This means OpenGL will still render to the old sized viewport.
I am facing a problem with converting 3D coordinate to screen coordinate. I have to convert the center of sphere to the screen coordinate. My code is here:
// OpenGL problem
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
void passive(int,int);
void reshape(int,int);
void init(void);
void display(void);
void camera(void);
int cursorX,cursorY,width,height;
double centerX,centerY,centerZ;
//GLfloat modelviewMatrix[16],projectionMatrix[16];
GLdouble modelviewMatrix[16],projectionMatrix[16];
GLint viewport[4];
int main (int argc,char **argv) {
glutInit (&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(1364,689);
glutInitWindowPosition(0,0);
glutCreateWindow("Sample");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutPassiveMotionFunc(passive);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void display() {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render 3D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.0,100.0); // create 3D perspective projection matrix
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
camera();
glTranslatef(-6,-2,0);
glColor3f(1,0,0);
glutSolidSphere(5,50,50);
glPopMatrix();
glGetDoublev(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
// get 3D coordinates based on window coordinates
gluProject(-6, -2, 0, modelviewMatrix, projectionMatrix, viewport, ¢erX, ¢erY, ¢erZ);
// Render 2D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width,height, 0); // create 2D orthographic projection matrix
glMatrixMode(GL_MODELVIEW);
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f( centerX,centerY ); // coordinate of center of the sphere in orthographic projection
glVertex2f( cursorX,cursorY );
glEnd();
glutSwapBuffers();
}
void camera(void) {
glRotatef(0.0,1.0,0.0,0.0);
glRotatef(0.0,0.0,1.0,0.0);
glTranslated(0,0,-20);
}
void init(void) {
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) {
width=w; height=h;
}
void passive(int x1,int y1) {
cursorX=x1; cursorY=y1;
}
In my code the centerX and centerY coordinates are going out of the screen. I have to draw a line between the center of the sphere and the mouse pointer. Any modification to the code to get it working properly?
Usually the function I use to switch between 3D / 2D coordinate. See if it works for you.
void toggle2DMode(bool flag, GLint Width, GLint Height) const
{
if(flag)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, Width, Height, 0.0, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
}
else
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
}
my function for checking resolution of a quad
void WINDOW_TEXT::calcResolution( GLshort & x , GLshort & y )
{
GLdouble tx, ty, ttx, tty, z; // target 2d coords (z is 'unused')
GLdouble model_view[16];
glGetDoublev(GL_MODELVIEW_MATRIX, model_view);
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
// get window coords based on 3D coordinates
gluProject( up_right.x, up_right.y, up_right.z,
model_view, projection, viewport,
&tx, &ty, &z);
gluProject( down_left.x, down_left.y, down_left.z,
model_view, projection, viewport,
&ttx, &tty, &z);
x = (GLshort)(tx-ttx);
y = (GLshort)(tty-ty);
};
"z" is ignored and you get pure resolution stored in x, and y