This code initially uses one texture. I duplicated some functions to use two textures. There doesn't seem to be any errors but when I run I only see the black command window for a bit then it closes. Is there any additional line that I should add?
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "support.h"
using namespace std;
/* GLUT callback Handlers */
MYPOINT*ptsW,*ptsR;
MYFACE *faceW,*faceR;
GLuint *images;
GLubyte *image;
GLuint texture;
void loadImage(int n, int m, char *fName);
GLuint LoadTexture(int width, int height);
int n=200,m=200;
void constructBox();
void constructTri();
void init();
void showPictureW();
void showPictureR();
float rX=0, rY=0, rZ=0;
float tX=0, tY=0, tZ=-3.5;
float nr = -5.0;
float fr = -4.0;
float tpx = 1.0, tpy = 1.0;
float btx = -1.0, bty = -1.0;
float dZ =-2.0;
void init(){
constructBox();
loadImage(n,m,"wall.ppm");
constructTri();
loadImage(n,m,"roof.ppm");
}
void showPictureW(){
/* clear all pixels */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
texture = LoadTexture(n,m);
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );
glColor3d(1,1,1);
//face 1
glBegin( GL_POLYGON );
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(-1,-1.0,-2.0); //1 -1
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0); //-1 -1
glEnd();
//face 2
glBegin( GL_POLYGON );
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0);
glTexCoord2d(0.0,1.0); glVertex3d(1.0,1.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0); //1 -1
glEnd();
}
void showPictureR(){
/* clear all pixels */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
texture = LoadTexture(n,m);
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );
glColor3d(1,1,1);
//face 1
glBegin( GL_POLYGON );
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(-1,-1.0,-2.0); //1 -1
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0); //-1 -1
glEnd();
//face 2
glBegin( GL_POLYGON );
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,0.0);
glTexCoord2d(0.0,1.0); glVertex3d(1.0,3.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,3.0,-2.0); //1 -1
glEnd();
}
static void
resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
init();
}
static void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,0,0);
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,0,1,0);
glRotated(rZ,1,0,0);
showPictureW();
glPopMatrix();
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,1,1,0);
glRotated(rZ,1,0,0);
showPictureR();
glPopMatrix();
glutSwapBuffers();
}
void constructBox()
{
int nPtsW = 8;
int nFaceW = 12;
ptsW = new MYPOINT[nPtsW];
faceW = new MYFACE[nFaceW];
getPoints(ptsW,"myVertWall.txt");
getFace(faceW,"myFaceWall.txt");
}
void constructTri()
{
int nPtsR = 6;
int nFaceR = 8;
ptsR = new MYPOINT[nPtsR];
faceR = new MYFACE[nFaceR];
getPoints(ptsR,"myVertRoof.txt");
getFace(faceR,"myFaceRoof.txt");
}
static void
key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
break;
case 'x':
rX= rX + 0.5;
break;
case 'X':
rX= rX - 0.5;
break;
case 'y':
rY= rY + 0.5;
break;
case 'Y':
rY= rY - 0.5;
break;
case 'z':
rZ= rZ + 0.5;
break;
case 'Z':
rZ= rZ - 0.5;
break;
case 'd':
dZ = dZ+100.0;// horizontal movement to the left
printf("Nilai dZ=%.2f\n",dZ);
break;
case 'D':
dZ = dZ-100.0;// horizontal movement to the right
printf("Nilai dZ=%.2f\n",dZ);
break;
}
glutPostRedisplay();
}
static void
idle(void)
{
glutPostRedisplay();
}
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
/* Program entry point */
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("FreeGLUT Shapes");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(1,1,1,1);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glutMainLoop();
return EXIT_SUCCESS;
}
GLuint LoadTexture(int width, int height)
{
image = new BYTE[width*height*3*sizeof(BYTE)];
int nm = width*height;
for(int i=0;i<nm*3;i++)//copy each value 3 times
{
image[i] = (GLubyte)images[i];
image[i] = (GLubyte)images[i];
image[i] = (GLubyte)images[i];
}
bool wrap = true;
glGenTextures( 1, &texture );
// select our current texture
glBindTexture( GL_TEXTURE_2D, texture );
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,wrap ? GL_REPEAT : GL_CLAMP );
// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, image );
// free buffer
//free( data );
return texture;
}
void loadImage(int n, int m, char *fName)
{
FILE *fd;
int k, nm;
int i;
char bc[71];
float s;
unsigned int red, green, blue;
char c;
fd = fopen(fName,"r");
fscanf(fd,"%[^\n]",bc); // reads data from stream
printf("Nilai %s \n\n",bc);
if(bc[0]!='P'|| bc[1]!='3')
{
printf("%s Not a PPM file\n",bc);
exit(0);
}
printf("%s is a PPM file\n",bc);
fscanf(fd,"%s",bc);
printf("line 1 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 2 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 3 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 4 %s \n",bc);
fscanf(fd,"%c",&c);
ungetc(c,fd);
fscanf(fd,"%d %d %d", &n,&m,&k);
// printf("%d rows %d columns max value = %d\n",n,m,k);
nm = n*m;
images = new GLuint[3*sizeof(GLuint)*nm];
//s = 255./k;
for (i=0;i<nm;i++)
{
fscanf(fd,"%u %u %u", &red, &green, &blue);
images[3*nm-3*i-3] = red;
images[3*nm-3*i-2] = green;
images[3*nm-3*i-1] = blue;
}
int totSize = 3*nm;
int tot=0;
for(i=0;i<nm;i++)
{
// fprintf(stderr,"(%d,%d,%d) ", images[3*nm-3*i-3], images[3*nm-3*i-2], images[3*nm-3*i-1]);
tot++;
}
// printf("%d \n",tot);
}
The coordinates are still all over. I'm just trying if the two textures come out okay.
Try this:
#include <GL/glut.h>
#include <vector>
float rX=0, rY=0, rZ=0;
float dZ =-2.0;
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
break;
case 'x':
rX= rX + 0.5;
break;
case 'X':
rX= rX - 0.5;
break;
case 'y':
rY= rY + 0.5;
break;
case 'Y':
rY= rY - 0.5;
break;
case 'z':
rZ= rZ + 0.5;
break;
case 'Z':
rZ= rZ - 0.5;
break;
case 'd':
dZ = dZ+100.0;// horizontal movement to the left
break;
case 'D':
dZ = dZ-100.0;// horizontal movement to the right
break;
}
}
void showPictureW()
{
//face 1
glBegin( GL_TRIANGLES );
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(-1,-1.0,-2.0); //1 -1
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0); //-1 -1
//face 2
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0);
glTexCoord2d(0.0,1.0); glVertex3d(1.0,1.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0); //1 -1
glEnd();
}
void showPictureR()
{
//face 1
glBegin( GL_TRIANGLES );
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(-1,-1.0,-2.0); //1 -1
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0); //-1 -1
//face 2
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,0.0);
glTexCoord2d(0.0,1.0); glVertex3d(1.0,3.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,3.0,-2.0); //1 -1
glEnd();
}
GLuint texture1 = 0;
GLuint texture2 = 0;
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
glEnable( GL_TEXTURE_2D );
glColor3ub(255,255,255);
glBindTexture( GL_TEXTURE_2D, texture1 );
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,0,1,0);
glRotated(rZ,1,0,0);
showPictureW();
glPopMatrix();
glBindTexture( GL_TEXTURE_2D, texture2 );
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,1,1,0);
glRotated(rZ,1,0,0);
showPictureR();
glPopMatrix();
glutSwapBuffers();
}
static void idle(void)
{
glutPostRedisplay();
}
GLuint LoadTexture(int width, int height, unsigned int component )
{
std::vector< unsigned char > image( width*height*3 );
for(int i=0;i< width*height*3; i += 3)
{
image[i+0] = 0;
image[i+1] = 0;
image[i+2] = 0;
image[i+component] = rand() % 255;
}
bool wrap = true;
GLuint texture = 0;
glGenTextures( 1, &texture );
// select our current texture
glBindTexture( GL_TEXTURE_2D, texture );
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,wrap ? GL_REPEAT : GL_CLAMP );
// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB, GL_UNSIGNED_BYTE, &image[0] );
return texture;
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("FreeGLUT Shapes");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(1,1,1,1);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
srand( 0 );
texture1 = LoadTexture( 256, 256, 0 );
texture2 = LoadTexture( 256, 256, 1 );
glutMainLoop();
return EXIT_SUCCESS;
}
Related
I draw patterns which have detailed pixels and they often face with Moire effect. I am not good at shading and I am not sure if this problem will be solved by shaders. I have not found any basic, understandable and complete example of shaders. Most of the tutorial websites start a program from the middle omitting the header file includes!
This is a MWE of my code. Is it possible to mitigate or remove the Moire effect from it?
#include <cmath>
#include <vector>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
const int w=640,h=480;
float cam_angle=0.0f;
void init()
{
GLfloat LightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat LightDiffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightPosition[] = { 5.0f, 5.0f, -10.0f, 1.0f };
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
glEnable(GL_LIGHT1);
}
void onDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (90, float(w)/float(h), 0.01, 10000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const double pi=3.1415926;
double cam_x=2.0*cos(pi/4.0)*cos(cam_angle);;
double cam_y=2.0*sin(pi/4.0)*cos(cam_angle);;
double cam_z=2.0*sin(cam_angle);
gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);
struct Point3D
{
double x, y, z;
unsigned char r, g, b, a=255;
};
for(double r=0.5;r<=1.0;r+=0.03)
{
std::vector<Point3D> points;
for(int i=0;i<1000;i++)
{
double theta=double(i)/1000.0*pi*2.0;
Point3D p;
p.x=r*sin(theta);
p.y=r*cos(theta);
p.z=r;
p.r=128;
p.g=200;
p.b=50;
points.push_back(p);
}
// draw
glPushMatrix();
glColor3ub(255,255,255);
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer(3, GL_DOUBLE, sizeof(Point3D), &points[0].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Point3D), &points[0].r );
// glPointSize( 3.0 );
glLineWidth(2.0);
glDrawArrays( GL_LINE_STRIP, 0, int(points.size()) );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glPopMatrix();
}
glFlush();
glutSwapBuffers();
}
void Timer(int /*value*/)
{
cam_angle+=0.01f;
glutPostRedisplay();
// 100 milliseconds
glutTimerFunc(100, Timer, 0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize (w, h);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowPosition (100, 100);
glutCreateWindow ("my window");
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
init();
glutDisplayFunc(onDisplay);
Timer(0);
glutMainLoop();
return 0;
}
If you use Multisampling, then the result will be significantly improved:
glutSetOption(GLUT_MULTISAMPLE, 8);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
without GLUT_MULTISAMPLE:
with GLUT_MULTISAMPLE:
See also the answer to GLUT + OpenGL multisampling anti aliasing (MSAA)
I try to do OpenGL picking so I followed this post (OpenGL Picking on Selection Mode ) which seems to have a working solution but I can't make mine work. I have a 3D textured polygon in my scene and I would like to know when I click on it.
Here is my code :
The mouse method which launches the picking when right click :
void mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button()==Qt::RightButton){
pickObjects(event->pos().x(),event->pos().y());
}
}
The pickObjects method:
#define BUFSIZE 512
void pickObjects(int x, int y)
{
GLint viewport[4];
GLint hits;
GLuint selectBuf[BUFSIZE];
glSelectBuffer (BUFSIZE, selectBuf);
glRenderMode (GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glGetIntegerv (GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport);
gluPerspective(fov, this->width() / this->height(), 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glInitNames();
makeCustomAnnot(GL_SELECT);
int hits=0;
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glMatrixMode(GL_MODELVIEW);
hits = glRenderMode (GL_RENDER);
if (hits != 0)
{
cout<<"FOUND " << hits << " hit(s)"<<endl; //ALWAYS GIVES 0 HITS
processHits(hits,selectBuf);
}
}
The processHits method :
void processHits(GLint inHits, GLuint buffer[])
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < inHits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
cout << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
cout<< *ptr ;
}
}
The drawing obejct method :
void makeCustomAnnot(GLenum mode){
glEnable(GL_TEXTURE_2D);
glColor3f(1,1,1);
GLuint j=0;
QImage img("img.jpg");
img=QGLWidget::convertToGLFormat(img);
GLuint texturesAnnot[1];
glBindTexture( GL_TEXTURE_2D, texturesAnnot[0] );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
if(mode == GL_SELECT){
glPushName (j);
}
glBegin(GL_QUADS);
glTexCoord2d(0,0);glVertex3d(x4,y4,z4);
glTexCoord2d(1,0);glVertex3d(x3,y3,z3);
glTexCoord2d(1,1);glVertex3d(x2,y2,z2);
glTexCoord2d(0,1);glVertex3d(x1,y1,z1);
glEnd();
if(mode == GL_SELECT)
glPopName ();
}
glDisable(GL_TEXTURE_2D);
}
The rendering method :
void render()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,this->width() , this->height());
gluPerspective(fov, this->width() / this->height(), 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xRot / 5.0f, 1.0f, 0.0f, 0.0f);
glRotatef(yRot / 5.0f, 0.0f, 1.0f, 0.0f);
glRotatef(zRot / 5.0f, 0.0f, 0.0f, 1.0f);
glPushMatrix();
makeCustomAnnot(GL_RENDER);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
So hits = glRenderMode (GL_RENDER); always returns 0 hits. What am I doing wrong?
So here is what I did to have it work perfectly.
The processHits method :
void processHits(GLint inHits, GLuint buffer[])
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < inHits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
cout << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
cout<< *ptr ;
}
}
The drawing object method with creates the objects I need to pick :
void makeCustomAnnot(GLenum mode){
glEnable(GL_TEXTURE_2D);
glColor3f(1,1,1);
GLuint j=0;
QImage img("img.jpg");
img=QGLWidget::convertToGLFormat(img);
GLuint texturesAnnot[1];
glBindTexture( GL_TEXTURE_2D, texturesAnnot[0] );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
if(mode == GL_SELECT)
glLoadName (j);
glBegin(GL_QUADS);
glTexCoord2d(0,0);glVertex3d(x4,y4,z4);
glTexCoord2d(1,0);glVertex3d(x3,y3,z3);
glTexCoord2d(1,1);glVertex3d(x2,y2,z2);
glTexCoord2d(0,1);glVertex3d(x1,y1,z1);
glEnd();
glDisable(GL_TEXTURE_2D);
}
The pickObjects method, identical to the rendering function but with instructions for picking :
#define BUFSIZE 512
unsigned int selectBuf[BUFSIZE];
void pickObjects(int x, int y)
{
GLint viewport[4];
GLint hits;
glSelectBuffer (BUFSIZE, selectBuf);
glRenderMode (GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glGetIntegerv (GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport);
gluPerspective(fov, this->width() / this->height(), 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xRot / 5.0f, 1.0f, 0.0f, 0.0f);
glRotatef(yRot / 5.0f, 0.0f, 1.0f, 0.0f);
glRotatef(zRot / 5.0f, 0.0f, 0.0f, 1.0f);
glRotatef((float)angleV, 1.0f, 0.0f, 0.0f);
glInitNames();
glPushName( 10000 );
glPushMatrix();
makeCustomAnnot(GL_SELECT);//draw scene in GL_SELECT mode to create the names
glPopMatrix();
hits = glRenderMode (GL_RENDER);//get the hits in GL_RENDER mode
if (hits != 0)
{
processHits(hits,selectBuf);
}
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
The rendering method :
void render()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,this->width() , this->height());
gluPerspective(fov, this->width() / this->height(), 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xRot / 5.0f, 1.0f, 0.0f, 0.0f);
glRotatef(yRot / 5.0f, 0.0f, 1.0f, 0.0f);
glRotatef(zRot / 5.0f, 0.0f, 0.0f, 1.0f);
glRenderMode (GL_RENDER);
glPushMatrix();
makeCustomAnnot(GL_RENDER);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
And finally hits = glRenderMode (GL_RENDER); in pickObjects method and then the processHits method return exactly the picked object.
I tried to load the six pictures as texture and draw a skybox, but the result is weird, each picture is mapped three times on its corresponding rectangle in grey. What is the problem?
#include <stdlib.h>
#include <stdio.h>
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <math.h>
#include <windows.h>
GLuint texture [6]; //the array for our texture
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glShadeModel (GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
}
GLuint LoadTexture( const char * filename, int width, int height) {
GLuint texture;
unsigned char * data;
FILE* file;
file = fopen( filename, "r" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &texture );
}
void skybox (void) {
float x = 0;
float y = 0;
float z = 0;
float width = 100;
float height = 100;
float length = 100;
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
// Bind the BACK texture of the sky map to the BACK side of the cube
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Center the skybox
x = x - width / 2;
y = y - height / 2;
z = z - length / 2;
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z + length);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glEnd();
//glBindTexture( GL_TEXTURE_CUBE_MAP, texture[0] ); //bind the texture
//glRotatef( angle, 1.0f, 1.0f, 1.0f );
//glutSolidSphere(2, 40, 40);
}
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.0, 0.0, 30.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLoadIdentity();
glPushMatrix();
gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
texture[1] = LoadTexture( "front.bmp", 256, 256 ); //load the texture
texture[2] = LoadTexture( "left.bmp", 256, 256 ); //load the texture
texture[3] = LoadTexture( "right.bmp", 256, 256 ); //load the texture
texture[4] = LoadTexture( "bottom.bmp", 256, 256 ); //load the texture
texture[5] = LoadTexture( "top.bmp", 256, 256 ); //load the texture
glPopMatrix();
glPopMatrix();
//glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
//glEnable(GL_TEXTURE_GEN_T);
skybox();
for (int i = 0; i < 6; i++) {
FreeTexture( texture[i] );
}
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0,-100.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("A basic OpenGL Window");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
So, you're trying to load DIB/BMP image files:
> texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
> ^^^^
>
Reading the contents of the file
> GLuint LoadTexture( const char * filename, int width, int height) {
> GLuint texture; unsigned char * data; FILE* file;
>
> file = fopen( filename, "r" );
> if ( file == NULL ) return 0;
> data = (unsigned char *)malloc( width * height * 3 );
> fread( data, width * height * 3, 1, file );
This is too short for a BMP, BTW.
> fclose( file );
So where's your DIB parser code?
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
You just pass the unparsed DIB/BMP file contents to OpenGL. What do you expect OpenGL to do with this? OpenGL has no idea about file format, less how process a DIB file. You need a DIB parser there.
Since you're loading RGB data make sure GL_UNPACK_ALIGNMENT is set to 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1).
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
I use the ImageMagick open library to easily load any image for use with OpenGL.
I am using Visual C++ and GLUT. Am I missing something such a normals? this is the exact code I am using. I tried to insert glNormal3f(0, 0, 1); before the vertex statements but this did not change anything. The glutSolidSphere renders just as I expect it to but not the quad.
#include "stdafx.h"
#include <stdlib.h>
#include <GL/glut.h>
float spin = 0.0f;
float zDir = 0;
GLfloat diffuseIntensity[] = {.75, .75, .75, 1};
GLfloat specularHue[] = {0, 0, .5f, 1};
GLfloat shininess[] = {5};
void moveCamera();
void checkKeys(int, int, int);
void setUpLighting();
void changeSize(int w, int h) {
if (h == 0)
h = 1;
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
moveCamera();
glTranslatef(0, 0, zDir-5);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, specularHue);
glPushMatrix();
glRotatef(90, 1, 0, 0);
glRotatef(spin, 0, 0, 1);
glutSolidSphere(.5f, 24, 24);
glPopMatrix();
spin += .01f;
if(spin > 360) spin -= 360;
glBegin(GL_QUADS);
glVertex3f(-10, 0, -10);
glVertex3f(-10, 0, 10);
glVertex3f(10, 0, 10);
glVertex3f(10, 0, -10);
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,600);
glutCreateWindow("Lighthouse3D - GLUT Tutorial");
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutSpecialFunc(checkKeys);
glEnable(GL_DEPTH_TEST);
setUpLighting();
glutMainLoop();
return 1;
}
void moveCamera(){
glTranslatef(0, 0, zDir);
}
void checkKeys(int key, int x, int y){
switch(key){
case GLUT_KEY_UP:
zDir += .1f;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
zDir += -.1f;
glutPostRedisplay();
break;
case GLUT_KEY_END:
exit(0);
}
}
void setUpLighting(){
GLfloat position0[] = {3, 1, 0, 1};
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseIntensity);
}
Give this a shot:
#include <GL/glut.h>
float zDir = 12;
void checkKeys(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_UP:
zDir += -.5f;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
zDir += .5f;
glutPostRedisplay();
break;
case GLUT_KEY_END:
exit(0);
}
}
float spin = 0;
void renderScene(void)
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(45,w/h,0.1,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -zDir);
// set up light
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat diffuseIntensity[] = {.75, .75, .75, 1};
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseIntensity);
// draw sphere at light position
glDisable( GL_LIGHTING );
glPushMatrix();
// spin light position around the y axis
glRotatef( -spin, 0, 1, 0 );
GLfloat position0[] = {3,3,3, 1};
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glTranslatef( position0[0], position0[1], position0[2] );
glColor3ub(255,255,255);
glutSolidSphere(0.1,8,8);
glPopMatrix();
glEnable( GL_LIGHTING );
// draw sphere
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
GLfloat specularHue[] = {0, 0, .5f, 1};
GLfloat shininess[] = {5};
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, specularHue);
spin += .01f;
if(spin > 360) spin -= 360;
glPushMatrix();
glRotatef(spin, 0, 1, 0);
glutSolidSphere(2, 24, 24);
glPopMatrix();
// draw quad
glColor3ub(255,0,0);
glPushMatrix();
glScalef( 3, 3, 3 );
glBegin(GL_QUADS);
glNormal3f( 0, 0, 1 );
glVertex2f( -1, -1 );
glVertex2f( 1, -1 );
glVertex2f( 1, 1 );
glVertex2f( -1, 1 );
glEnd();
glPopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,600);
glutCreateWindow("Lighthouse3D - GLUT Tutorial");
glutDisplayFunc(renderScene);
glutSpecialFunc(checkKeys);
glutMainLoop();
return 1;
}
The quad is rendered, but you don't see it because it is drawn very much like the surface of a table and your eyes are at the same level of the table. Because of this, the effect is like that of which nothing was drawn at all. That or you'll see a line.
Your rotation above, being wrapped in a PushMatrix/PopMatrix only works with the solid sphere.
I have an assignment to do, but i can't seem to trully comprehend it.
The assignment is as follows : Adding a texture to background (solar system), adding texture to 2 objects (drawn shapes) and adding an animation where the two objects have to bounce from eachother & from far walls (as in end of screen).
I have managed to do everything except the animation.
How can I do this kind of animation?
p.s. animation in there is the best i could come up with.
#include <gl/glut.h>
#include <gl/gl.h >
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
float x;
float y;
unsigned char *imageData;
int imageRows, imageCols;
extern void loadBMP(char *);
char cotton1[] = "cotton1.bmp";
char cotton2[] = "cotton2.bmp";
char fons[] = "solar.bmp";
GLuint texture[3];
float cube[1], Vcube[1];
/* GLUT callback Handlers */
void init()
{
cube[0]=0;
Vcube[0]=0.01;
cube[1]=0;
Vcube[1]=0.01;
glShadeModel(GL_SMOOTH);
glGenTextures( 3, &texture[0] );
loadBMP(cotton1);
glBindTexture( GL_TEXTURE_2D, texture[0] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
loadBMP(cotton2);
glBindTexture( GL_TEXTURE_2D, texture[1] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
loadBMP(fons);
glBindTexture( GL_TEXTURE_2D, texture[2] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
static void
resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
static void
idle(void)
{
glutPostRedisplay();
}
void animation()
{
cube[1]+=Vcube[1];
if (cube[1]<0.1)
{ Vcube[1]+=Vcube[1]; }
if (cube[1]>0.095)
{ Vcube[1]=-0.01; }
if (cube[1]<0)
{ Vcube[1]=+0.01; }
glTranslatef(cube[1],0,0);
Sleep(100);
glutPostRedisplay();
}
void animation2()
{
cube[0]+=Vcube[0];
if (cube[0]<(-0.1))
{ Vcube[0]-=0.01; }
if (cube[0]>0)
{ Vcube[0]-=0.01; }
if (cube[0]<0.1)
{ Vcube[0]+=0.01; }
glTranslatef(cube[0],0,0);
Sleep(100);
glutPostRedisplay();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//Background
glLoadIdentity();
glBindTexture( GL_TEXTURE_2D, texture[2]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_QUADS );
glTexCoord2f(1.0,1.0); glVertex2f(-1.0,1.0);
glTexCoord2f(0.0,1.0); glVertex2f(1.0,1.0);
glTexCoord2f(0.0,0.0); glVertex2f(1.0,-1.0);
glTexCoord2f(1.0,0.0); glVertex2f(-1.0,-1.0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
animation();
//TEXTURE 1
glBindTexture( GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f); glVertex2f( 0.5f, 0.0f); //center
glTexCoord2f(1.0f, 0.5f); glVertex2f( 0.8f+x, 0.0f); //right
glTexCoord2f(0.75f, 1.0f); glVertex2f( 0.55f+x, 0.3f+x); //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f( 0.35f-x, 0.3f+x); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex2f( 0.25f-x, 0.0f); //left
glTexCoord2f(0.25f, 0.0f); glVertex2f( 0.45f-x,-0.3f-x); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f( 0.7f+x, -0.2f-x); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex2f( 0.8f+x, 0.0f); //right
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
//TEXTURE 2
animation2();
glBindTexture( GL_TEXTURE_2D, texture[1]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f); glVertex2f( -0.5f, 0.0f); //center
glTexCoord2f(1.0f, 0.5f); glVertex2f( -0.2f+y, 0.0f); //right
glTexCoord2f(0.75f, 1.0f); glVertex2f( -0.4f+y, 0.2f+y); //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f( -0.7f-y, 0.1f+y); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex2f( -0.8f-y, 0.0f); //left
glTexCoord2f(0.25f, 0.0f); glVertex2f( -0.7f-y, -0.1f-y); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f( -0.3f+y, -0.2f-y); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex2f( -0.2f+y, 0.0f); //right
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
glFlush();
}
static void
key(unsigned char key, int a, int b)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
if ((x+0.01)<0.98)
x=x+0.01;
if ((y+0.01)<0.98)
y=y+0.01;
break;
case '-':
if ((x-0.1)>(-0.15))
x=x-0.01;
if ((y-0.1)>(-0.10))
y=y-0.01;
break;
case 'o':
if ((x+0.01)<0.98)
x=x+0.01;
break;
case 'p':
if ((x-0.1)>(-0.15))
x=x-0.01;
break;
case '[':
if ((y+0.01)<0.98)
y=y+0.01;
break;
case ']':
if ((y-0.1)>(-0.10))
y=y-0.01;
break;
}
glutPostRedisplay();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(640, 640);
glutInitWindowPosition(50, 50);
glutCreateWindow("Assignment number 3");
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(1.0, 1.0, 1.0, 1.0);
init();
glutMainLoop();
return EXIT_SUCCESS;
}
Problem 1: You mistake OpenGL for a scene graph. Take your animation1 function for example:
void animation2(
)
{
cube[0] += Vcube[0];
if( cube[0] < ( -0.1 ) ) {
Vcube[0] -= 0.01;
}
if( cube[0] > 0 ) {
Vcube[0] -= 0.01;
}
if( cube[0] < 0.1 ) {
Vcube[0] += 0.01;
}
glTranslatef( cube[0], 0, 0 );
Sleep( 100 );
glutPostRedisplay( );
}
That glTranslatef there at the end will just trash around on whatever matrix is currently active in the OpenGL context. That's not how to do it.
Next problem: You're calling the animation functions from the drawing code. At the point of drawing all the scene state should be determined. Also, calling that animation function will sleep in your display function. That's not how to do it.
Okay, what to do: First put all the animation progressor functions into the idle loop. Don't sleep, instead measure the time between animation iterations and advance the animation accordingly. Don't call glutPostRedisplay in the animation functions. At the end of the idle handler yes, but not in the animators. In the drawing code use the evaluated animation state to place objects accordingly. Use the matrix stack (glPushMatrix, glPopMatrix) to keep things nicely separated.
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* for gettimeofday */
#include <sys/time.h>
/* In general, littering your program with global variables should be avoided.
* I admit, that sometimes even I don't adhere to this rule, and especially
* using GLUT it takes to jump several very arcane hoops to avoid it.
* So in this case, yes, having global variables is in order.
*
* The principle idea of global variables is to put data into them, that is
* valid and the same for the whole of the program. More importantly they
* must not be used to pass around data.
*
* It's also a good idea to make those variables static, so that they are
* contained withing this compilation unit.
*/
static float x;
static float y;
/* This is not how globals should be used. They're used to pass data around between
* functions. DON'T DO THAT!
*
* Also this misses the extern keyword. Unless the compilation unit loading the
* bmp files declares those being extern, hence relying on another compilation unit
* to expose them like this, this code is likely to break.
unsigned char *imageData;
int imageRows, imageCols;
extern void loadBMP(char *);
* BTW: You don't need the extern keyword here.
* Instead have a nice little function that loads a BMP file and puts it into a
* newly allocated texture object.
*/
GLuint loadBmpToTexture(char const * const filename)
{
/* Implementation of this left as an exercise to the reader */
return 0;
}
static double ftime(void)
{
/* Now this is a bit complicated: There's no portable high resolution
* timer function. On Linux and Unices (hence also MacOS X) you have
* gettimeofday, on Windows there are the High Performance Counters.
* ... Totally annoying.
* Look here for a comparison:
* http://www.songho.ca/misc/timer/timer.html
*
* Since I'm on a Linux box this is using gettimeofday
*/
struct timeval t;
gettimeofday(&t, NULL);
return 1.0*t.tv_sec + 1e-6*t.tv_usec;
}
/* In this variable we store the time of the last iteration of the animation
* loop to determine the time to time difference for the next one. */
static double last_T;
/* Actually those should be of type char const * const
* This is one of the finer details of C. The arrays like you've declared them
* here are mutable, but of constant size.
* However you normally don't want string constant be like this. The preferred
* modus operandi is to have the string constants in read only memory and pointers
* to them. Like this:
*/
char const * const cotton1 = "cotton1.bmp";
char const * const cotton2 = "cotton2.bmp";
char const * const fons = "solar.bmp";
/* Okay, now consider what would happen if you had several objects, not just two or
* three? How would you keep track of all those indices? Really, that's bad style.
* If you've data belonging together, like state of an object, put it into a struct
* and then also use useful variable names.
*/
GLuint texture_background;
typedef struct s_Cube {
float x, V_x;
GLuint texture;
} Cube;
/* also we can statically initialize here */
Cube cube[2] = {
{-0.05, 0.01, 0},
{0.05, -0.02, 0}
};
/* GLUT callback Handlers */
static void init(void)
{
/* loadBmpToTexture is defined to return 0 in case of failure
* which is also the OpenGL default texture object, so this
* fails safely. */
texture_background = loadBmpToTexture(fons);
cube[0].texture = loadBmpToTexture(cotton1);
cube[1].texture = loadBmpToTexture(cotton2);
glClearColor( 0.0, 0.5, 0.7, 1.0 );
last_T = ftime();
}
static void animation(
float const speed
)
{
/* The objective is to let the cubes bounce into each other
* (collision) and with the walls. First the collision: */
if( cube[0].x > cube[1].x && cube[0].V_x > 0 && cube[1].V_x < 0 ) {
/* cubes bounced off each other. Exchange their velocities */
double const V_x = cube[0].V_x;
cube[0].V_x = cube[1].V_x;
cube[1].V_x = V_x;
double const x = cube[0].x;
cube[0].x = cube[1].x;
cube[1].x = x;
}
/* and the wall bounce */
if( cube[0].x < -0.1 && cube[0].V_x < 0 ) {
/* left cube bounced into left wall */
cube[0].V_x *= -1;
}
if( cube[1].x > 0.1 && cube[1].V_x > 0 ) {
/* right cube bounced into left wall */
cube[1].V_x *= -1;
}
cube[0].x += speed * cube[0].V_x;
cube[1].x += speed * cube[1].V_x;
}
/* Ideally we'd use a precise animation loop interleaved with event processing here.
* Unfortunately GLUT doesn't offer those, so we use this arcane kludge.
*
* It would get a bit more robust by putting the whole timing into the display function
* but better abandon GLUT and get a true event loop.
*/
static void idle(
void )
{
const double now_T = ftime();
const double delta_T = now_T - last_T;
last_T = now_T;
const double speed = delta_T * 60;
animation( speed );
glutPostRedisplay( );
}
static void display(void)
{
/* We try to be as stateless as possible. Yes, in the face of a statefull
* API, like OpenGL, this may sound a bit pedantic. */
const int width = glutGet(GLUT_WINDOW_WIDTH);
const int height = glutGet(GLUT_WINDOW_HEIGHT);
const float ar = ( float ) width / ( float ) height;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
/* It's really best practice to set everything related to drawing
* – and that includes the projection – in the drawing function */
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-ar, ar, -1, 1, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//Background
if(texture_background) {
glBindTexture( GL_TEXTURE_2D, texture_background );
glEnable( GL_TEXTURE_2D );
glBegin( GL_QUADS );
glTexCoord2f( 1.0, 1.0 );
glVertex2f( -1.0, 1.0 );
glTexCoord2f( 0.0, 1.0 );
glVertex2f( 1.0, 1.0 );
glTexCoord2f( 0.0, 0.0 );
glVertex2f( 1.0, -1.0 );
glTexCoord2f( 1.0, 0.0 );
glVertex2f( -1.0, -1.0 );
glEnd();
glDisable( GL_TEXTURE_2D );
}
//TEXTURE 1
glBindTexture( GL_TEXTURE_2D, cube[1].texture );
glEnable( GL_TEXTURE_2D );
/* Remember we're still in modelview matrix mode.
* This push creates a copy of the currently modelview matrix,
* for our disposal. With a following pop we restore to the
* state saved now. Pushes and Pops nest. */
glPushMatrix();
/* This applies our animation position to the modelview matrix.
* All geometry drawing to follow is subject to this additional
* transformation, until the matrix changes again. */
glTranslatef(cube[1].x, 0, 0);
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f( 0.5f, 0.5f );
glVertex2f( 0.5f, 0.0f ); //center
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( 0.8f + x, 0.0f ); //right
glTexCoord2f( 0.75f, 1.0f );
glVertex2f( 0.55f + x, 0.3f + x ); //top right
glTexCoord2f( 0.25f, 1.0f );
glVertex2f( 0.35f - x, 0.3f + x ); //Top left
glTexCoord2f( 0.0f, 0.5f );
glVertex2f( 0.25f - x, 0.0f ); //left
glTexCoord2f( 0.25f, 0.0f );
glVertex2f( 0.45f - x, -0.3f - x ); //bottom left
glTexCoord2f( 0.75f, 0.0f );
glVertex2f( 0.7f + x, -0.2f - x ); //bottom right
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( 0.8f + x, 0.0f ); //right
glEnd( );
glPopMatrix( );
glDisable( GL_TEXTURE_2D );
//TEXTURE 2
/* in the original code you didn't use the other texture,
* Probably because you lost track of variables and indices. */
glBindTexture( GL_TEXTURE_2D, cube[0].texture );
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glTranslatef(cube[0].x, 0, 0);
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f( 0.5f, 0.5f );
glVertex2f( -0.5f, 0.0f ); //center
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( -0.2f + y, 0.0f ); //right
glTexCoord2f( 0.75f, 1.0f );
glVertex2f( -0.4f + y, 0.2f + y ); //top right
glTexCoord2f( 0.25f, 1.0f );
glVertex2f( -0.7f - y, 0.1f + y ); //Top left
glTexCoord2f( 0.0f, 0.5f );
glVertex2f( -0.8f - y, 0.0f ); //left
glTexCoord2f( 0.25f, 0.0f );
glVertex2f( -0.7f - y, -0.1f - y ); //bottom left
glTexCoord2f( 0.75f, 0.0f );
glVertex2f( -0.3f + y, -0.2f - y ); //bottom right
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( -0.2f + y, 0.0f ); //right
glEnd();
glPopMatrix();
glDisable( GL_TEXTURE_2D );
glutSwapBuffers();
/* Your glFinish here was totally pointless.
* First it would belong _before_ glutSwapBuffers.
* Second glutSwapBuffers implies a glFinish, so it's totally redundant. */
}
static void key(
unsigned char key,
int a,
int b )
{
switch ( key ) {
case 27:
case 'q':
exit( 0 );
break;
case '+':
if( ( x + 0.01 ) < 0.98 )
x = x + 0.01;
if( ( y + 0.01 ) < 0.98 )
y = y + 0.01;
break;
case '-':
if( ( x - 0.1 ) > ( -0.15 ) )
x = x - 0.01;
if( ( y - 0.1 ) > ( -0.10 ) )
y = y - 0.01;
break;
case 'o':
if( ( x + 0.01 ) < 0.98 )
x = x + 0.01;
break;
case 'p':
if( ( x - 0.1 ) > ( -0.15 ) )
x = x - 0.01;
break;
case '[':
if( ( y + 0.01 ) < 0.98 )
y = y + 0.01;
break;
case ']':
if( ( y - 0.1 ) > ( -0.10 ) )
y = y - 0.01;
break;
}
glutPostRedisplay();
}
int main(
int argc,
char *argv[] )
{
glutInit( &argc, argv );
glutInitWindowSize( 640, 640 );
glutInitWindowPosition( 50, 50 );
/* glutInitDisplayMode must be called before calling glutCreateWindow
* GLUT, like OpenGL is stateful */
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
glutCreateWindow( "Assignment number 3" );
glutDisplayFunc( display );
glutKeyboardFunc( key );
glutIdleFunc( idle );
init();
glutMainLoop( );
return EXIT_SUCCESS;
}