I am trying to draw something like this image of the target output using OpenGL. I am using freeglut. I could draw three polygons, but I don't know how to give the three polygons right positioning. Below I attached the target output and my correct output.
The target output
My output
#include <GL/glut.h>
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
}
void drawSquare(void)
{
glBegin(GL_POLYGON);
glVertex2f(0.0f, -1.0f);
glVertex2f(2.0f, 0.0f);
glVertex2f(0.0f, 1.0f);
glVertex2f(-2.0f, 0.0f);
glEnd();
}
void myDraw1(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
drawSquare();
glTranslatef(2.0, 3.0, 0.0);
glRotatef(30, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 0.0);
drawSquare();
glLoadIdentity();
glTranslatef(-2.0, -3.0, 0.0);
glRotatef(-30, 0.0, 0.0, 1.0);
glColor3f(0.0, 0.0, 1.0);
drawSquare();
glFlush();
}
void myDraw2(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
drawSquare();
glPushMatrix();
glTranslatef(2.0, 3.0, 0.0);
glRotatef(30, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 0.0);
drawSquare();
glPopMatrix();
glTranslatef(-2.0, -3.0, 0.0);
glRotatef(-30, 0.0, 0.0, 1.0);
glColor3f(0.0, 0.0, 1.0);
drawSquare();
glFlush();
}
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(0, 0);
glutInitWindowSize(600, 600);
glutCreateWindow("Rotate");
init();
glutDisplayFunc(myDraw1);
glutMainLoop();
}
The angle between the polygons is 120°. The center of the polygons is (0, 0). You have to rotate around the point (-2, 0). Translate the polygon in that way that that (-2, 0) is moved to (0, 0) and rotate the polygon:
glRotatef(120.0, 0.0, 0.0, 1.0);
glTranslatef(2.0, 0.0, 0.0);
Note, operations like glTranslatef and glRotatef, specify a matrix and multiply the current matrix by the new specified matrix. Use glPushMatrix/glPopMatrix to save and restore the matrix (push on and pop from matrix stack).
e.g:
void myDraw1(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
glPushMatrix();
glRotatef(90.0, 0.0, 0.0, 1.0);
glTranslatef(2.0, 0.0, 0.0);
drawSquare();
glPopMatrix();
glColor3f(0.0, 1.0, 0.0);
glPushMatrix();
glRotatef(210.0, 0.0, 0.0, 1.0);
glTranslatef(2.0, 0.0, 0.0);
drawSquare();
glPopMatrix();
glColor3f(0.0, 0.0, 1.0);
glPushMatrix();
glRotatef(330.0, 0.0, 0.0, 1.0);
glTranslatef(2.0, 0.0, 0.0);
drawSquare();
glPopMatrix();
glFlush();
}
Related
I'm facing a problem in my opengl code
I'm trying to build a house, and rotate it 360°, for simplicity let's assume the house has the front wall with window and dor, and a back wall.
I'm using DEPTH_BUFFER not to see the back wall when viewing the front wall, and the other way around, but when I rotate the house the door and window start to shake and get distorced.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity();
gluLookAt(0.0, 0.0, 40.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angle, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(8.0, 3.0, 0.0);
glVertex3f(8.0, -10.0, 0.0);
glVertex3f(1.0, -10.0, 0.0);
glVertex3f(1.0, 3.0, 0.0);
glEnd();
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(-9.0, -4.0, 0.0);
glVertex3f(-9.0, 3.0, 0.0);
glVertex3f(-2.0, 3.0, 0.0);
glVertex3f(-2.0, -4.0, 0.0);
glEnd();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, -10.0, -20.0);
glVertex3f(-10.0, -10.0, -20.0);
glVertex3f(-10.0, 10.0, -20.0);
glVertex3f(10.0, 10.0, -20.0);
glEnd();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, -10.0, 0.0);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(-10.0, 10.0, 0.0);
glVertex3f(-10.0, -10.0, 0.0);
glEnd();
glDisable(GL_DEPTH_TEST);
glutSwapBuffers();
The issue is called Z-fighting. This is caused, because depth of the "door", "window" and "wall" are equal. The vertiex coordinates are transformed by the model view matrix and projection matrix and interpolated for each fragment which is covered by the polygon. This results in inaccuracies of the final z coordinate (depth).
Enable the polygon fill offset (glPolygonOffset) by before drawing the walls, to solve the issue:
glEnable(GL_DEPTH_TEST);
glDisable( GL_POLYGON_OFFSET_FILL );
// draw door and window
// ...
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 1, 1 );
// draw walls
// ...
Polygon fill offset manipulates the depth of a fragment by a minimum amount. This causes that the depth of the "walls" is different to the depth of the "window" and "door", even after the transformation by the model view and projection matrix.
Since an offset is added to the depth of the "wall", the "wall" is always behind the window and the door, independent of the point of view.
I'm making a square arm with push-pop matrix and pop-up menu entries. I want to make the objects rotate individually, so I create the code below but the one finger moves along with the others. Why is it moving together?
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
draw_lines();
glPushMatrix();
glColor3f(1.0, 1.0, 1.0);
glTranslatef(-1.0, 0.0, 0.0);
glRotatef((GLfloat)shoulder, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.5);
glutWireCube(1.0); //First square(Shoulder)
glPopMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)elbow, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.5);
glutWireCube(1.0); //Second Square(Elbow)
glPopMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)finger_1, 0.0, 0.0, 1.0);
glTranslatef(0.25, 0.0, 0.7);
glPushMatrix();
glScalef(0.5, 0.2, 0.2);
glutWireCube(1.0); //First Finger
glPopMatrix();
glTranslatef(-0.3, 0.0, 0.0);
glRotatef((GLfloat)finger_2, 0.0, 0.0, 1.0);
glTranslatef(0.25, 0.0, -0.4);
glPushMatrix();
glScalef(0.5, 0.2, 0.2);
glutWireCube(1.0); //Second Finger
glPopMatrix();
glTranslatef(-0.3, 0.0, 0.0);
glRotatef((GLfloat)finger_3, 0.0, 0.0, 1.0);
glTranslatef(0.25, 0.0, -0.5);
glPushMatrix();
glScalef(0.5, 0.2, 0.2);
glutWireCube(1.0); //Third Finger
glPopMatrix();
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
Object rotation is made by separate functions.
I am trying to learn how to use a spot light in OpenGL. I wish to shine a spot (torch) light from a point marked (lighpos), and shown as grey dot, onto the side of a GLUT teapot centered at (possph) in 3D space. I have attached an example where I have tried to do this but I cannot get the light to focus on the teapot. I am expecting a almost touch light focus based on the parameters I have tried to use.
Could someone point out what I have missed / mistake I have made.
Thanks
Stuart
#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
GLfloat lighpos[] = { -300., 200., 250., 1.0 }; // Location of light
GLfloat possph[] = { -50., 350., 150. }; // Position of teapot
GLfloat ligdir[] = { 250., 150., -100. }; // Direction from light to teapot
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_POSITION, lighpos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, ligdir);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 10.0);
GLfloat ambientLight0[] = { 0.25, 0.25, 0.25, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight0);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight0);
GLfloat diffuseLight0[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight0);
GLfloat specularLight0[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight0);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 128.0f);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void drawAxis() {
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0); glVertex3f(-500., 0.0, 0.0); glVertex3f(500., 0.0, 0.0);
glColor3f(0.0, 1.0, 0.0); glVertex3f(0.0, -500., 0.0); glVertex3f(0.0, 500., 0.0);
glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0, 0.0, -500.); glVertex3f(0.0, 0.0, 500.);
glEnd();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
drawAxis();
glPushMatrix();
glPointSize(10);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POINTS);
glVertex3d(lighpos[0], lighpos[1], lighpos[2]);
glEnd();
glPopMatrix();
glColor3f(1., 0., 0.);
glPushMatrix();
glTranslated(possph[0], possph[1], possph[2]);
glutSolidTeapot(100.);
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 4, 3000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1500.0, 1500.0, 1500.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(0.0, 0.0);
glutInitWindowSize(800, 800);
glutCreateWindow("spotlight");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Fixed function pipeline illumination, which is what you are using in your code, performs lighting calculations only at the vertices. If your spotlight illuminates only a few or a single vertex you'll not get a pleasing spotlight effect. One possible solution would be to highly refine your models' meshes. The better, much more efficient and elegant solution is to drop using the fixed function pipeline and implement a illumination fragment shader, so that lighting is calculated for each pixel.
Is this possible? (I know, it is, but I can't do it.)
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
if (isWire)
glPolygonMode(GL_FRONT, GL_LINE);
else
glPolygonMode(GL_FRONT, GL_FILL);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(10,10,0);
glVertex3f(20,10,0);
glVertex3f(30,80,0);
glVertex3f(40,70,0);
glVertex3f(50,80,0);
glVertex3f(60,10,0);
glVertex3f(70,10,0);
glEnd();
glBegin(GL_TRIANGLE_STRIP);
glEnd();
glFlush();
}
There is my attempt, although my next idea would be to bridge the legs of the A. But I would like to do it in one single strip.
With help from my friend geometry :)
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
if (isWire)
glPolygonMode(GL_FRONT, GL_LINE);
else
glPolygonMode(GL_FRONT, GL_FILL);
// Draw a triangle strip.
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(20.0, 10.0, 0.0);
glVertex3f(12.0, 30.0, 0.0);
glVertex3f(22.0, 30.0, 0.0);
glVertex3f(17.0, 80.0, 0.0);
glVertex3f(26.0, 70.0, 0.0);
glVertex3f(35.0, 80.0, 0.0);
glVertex3f(31.0, 40.0, 0.0);
glVertex3f(42.0, 35.0, 0.0);
glVertex3f(23.0, 40.0, 0.0);
glVertex3f(25.0, 35.0, 0.0);
glVertex3f(21.9, 30.0,0.0);
glVertex3f(42.0, 35.0, 0.0);
glVertex3f(32.0, 30.0, 0.0);
glVertex3f(46.0, 10.0, 0.0);
glVertex3f(36.5, 10.0, 0.0);
glEnd();
glFlush();
}
I made a program written in OpenGL and when ever I run It the program fills up all the ram and then closes at approximately 3300/4000 Mb of ram. Here is my program:
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <windows.h>
#include <gl/gl.h>
#include <gl/glut.h>
#include <gl/GLU.h>
#include <gl/glaux.h>
using namespace std;
GLuint texture;
AUX_RGBImageRec* LoadImage (char* file) {
return auxDIBImageLoad (file);
}
int LoadTexture (char* file) {
AUX_RGBImageRec* Textureimage;
Textureimage = LoadImage (file);
glGenTextures (1, &texture);
glBindTexture (GL_TEXTURE_2D, texture);
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB,
Textureimage->sizeX,
Textureimage->sizeY,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
Textureimage->data
);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
delete Textureimage;
return 0;
}
void exitkey (unsigned char key, int x, int y) {
switch (key) {
case 27:
exit (0);
}
}
void Render3d () {
glEnable (GL_DEPTH_TEST);
glEnable (GL_NORMALIZE);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_LIGHT1);
glEnable (GL_TEXTURE_2D);
}
void incaseofresize (int w, int h) {
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (90.0, (double)w / (double)h, 0.7, 300.0);
}
double theangle = 30.0;
void draw () {
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -6.0);
glPushMatrix ();
glRotatef (theangle, 0.0, 1.0, 0.0);
GLfloat ambientlightcolor [] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light0color [] = { 0.5, 0.5, 0.0, 1.0 };
GLfloat light1color [] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat light0position [] = { 2.0, 0.0, 3.0, 1.0 };
GLfloat light1position [] = { -2.0, 0.0, 3.0, 1.0 };
glLightModelfv (GL_LIGHT_MODEL_AMBIENT, ambientlightcolor);
glLightfv (GL_LIGHT0, GL_DIFFUSE, light0color);
glLightfv (GL_LIGHT0, GL_POSITION, light0position);
glLightfv (GL_LIGHT1, GL_DIFFUSE, light1color);
glLightfv (GL_LIGHT1, GL_POSITION, light1position);
LoadTexture ("me.bmp");
glBegin (GL_QUADS);
//Drawing shape
glColor3f (1.0, 1.0, 1.0);
//Left side
glNormal3f (0.0, 0.0, 1.0);
glTexCoord2f (0.0, 0.0);
glVertex3f (-1.5, -1.0, -1.5);
glTexCoord2f (1.0, 0.0);
glVertex3f (0.0, -1.0, 1.5);
glTexCoord2f (1.0, 1.0);
glVertex3f (0.0, 1.0, 1.5);
glTexCoord2f (0.0, 1.0);
glVertex3f (-1.5, 1.0, -1.5);
glEnd ();
LoadTexture ("mom.bmp");
glBegin(GL_QUADS);
//Right side
glNormal3f (0.0, 1.0, 1.0);
glTexCoord2f (0.0, 0.0);
glVertex3f (0.0, -1.0, 1.5);
glTexCoord2f (1.0, 0.0);
glVertex3f (1.5, -1.0, -1.5);
glTexCoord2f (1.0, 1.0);
glVertex3f (1.5, 1.0, -1.5);
glTexCoord2f (0.0, 1.0);
glVertex3f (0.0, 1.0, 1.5);
glEnd ();
glBegin (GL_QUADS);
//Back right side
glNormal3f (0.0, 1.0, 0.0);
glVertex3f (1.5, -1.0, -1.5);
glVertex3f (0.0, -1.0, -4.5);
glVertex3f (0.0, 1.0, -4.5);
glVertex3f (1.5, 1.0, -1.5);
glEnd ();
glBegin (GL_QUADS);
glNormal3f (0.0, 1.0, 0.0);
glVertex3f (0.0, -1.0, -4.5);
glVertex3f (-1.5, -1.0, -1.5);
glVertex3f (-1.5, 1.0, -1.5);
glVertex3f (0.0, 1.0, -4.5);
glEnd ();
glutSwapBuffers ();
}
void rotate (int value) {
theangle += 1.5;
if (theangle > 360) {
theangle -=360;
}
glutPostRedisplay ();
glutTimerFunc (50, rotate, 0);
}
int main (int argcpp, char** argv) {
glutInit (&argcpp, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (720, 480);
glutCreateWindow ("OpenGL");
Render3d ();
glutDisplayFunc (draw);
glutKeyboardFunc (exitkey);
glutReshapeFunc (incaseofresize);
glutTimerFunc (50, rotate, 0);
glutMainLoop ();
return 0;
}
I think its the LoadTexture function reloading the image over and over again each loop and I cant find a way to delete the image data after each loop.
Every time your program iterates through the display function it will load images into a new texture object, not freeing the previously created ones.
The canonical way is to load textures only once. OpenGL organizes textures in so called texture objects, identified by a so called name ID. LoadTexture does return this ID. You use such a texture by calling glBindTexture(GL_TEXTURE_2D, theTextureID);