OpenGL: How to make light stationary when moving the camera around? - c

I'm trying to render a simple (10x3x10 in size) room using OpenGL and GLUT, written in C.
I'd like to create a simple statinary spotlight, while i can move around in the room.
(The ultimate goal is to make a spotlight coming from a lamp at the ceiling)
The problem is the light changes when i move the camera around.
I'm calling the following function from main():
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture(); // loading some textures using SOIL
loadModels(); // loading some OBJ models
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glClearColor(0, 0, 0, 1);
}
The function i pass to glutDisplayFunc():
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
initLight();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
// ...
// drawing the ground, ceiling and the walls
// no matrix transformations here, just simple glVertex () calls
// ...
glPushMatrix();
// drawing a table
glTranslatef(5, 0.842843, 5);
glBindTexture(GL_TEXTURE_2D, texture[1]);
draw_model(&modelTable);
// drawing some chairs
glTranslatef(0, -0.312053, chair1Position);
glBindTexture(GL_TEXTURE_2D, texture[2]);
draw_model(&modelChair1);
glTranslatef(0, 0, chair2Position);
draw_model(&modelChair2);
glPopMatrix();
glutSwapBuffers();
}
And the initLight() function:
void initLight() {
// i would like the light to originate from an upper corner
// directed to the opposing lower corner (across the room basically)
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat ambientLight[] = { 0.3, 0.3, 0.3, 1 };
GLfloat diffuseLight[] = { 1, 1, 1, 1 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 64);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
I was told this problem could be solved by the proper positioning of the glPushMatrix() and glPopMatrix() calls.
Wherever i put them, the light either keeps changing when i'm moving the camera or i got no light at all. I just cannot figure it out.
What would be a proper solution here?
Thanks in advance.
EDIT:
I've moved the initLight() call to after the gluLookAt() call as #derhass suggested below.
The light is still changing when i'm moving around.
There are two screenshots below.
On the first one the light is not even visible. When i turn slightly to the right, it appears.
EDIT2:
The full (stripped down) source code:
#include <GL/glut.h>
#include <SOIL/SOIL.h>
#include <math.h>
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat diffuseLight[] = { 0, 1, 0, 1 };
GLfloat ambientLight[] = { 0.2, 0.2, 0.2, 1 };
float x = 1.0f, z = 5.0f;
float vX = 1.0f, vZ = 0.0f;
float angle = 1.5f;
int windowWidth = 1024;
int windowHeight = 768;
char* textureFiles[13] = { "floortexture.png", "tabletexture.png",
"chairtexture.png", "orange.png", "helptexture.png",
"fridgetexture.png", "oven.png", "yellow.png", "dishwasher.png",
"metallic.png", "cabinet.png", "wood.png", "cabinet2.png" };
GLuint texture[13];
void loadTexture() {
for (int i = 0; i < 13; i++) {
texture[i] = SOIL_load_OGL_texture(textureFiles[i], SOIL_LOAD_RGBA,
SOIL_CREATE_NEW_ID, 0);
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture();
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0, 0, 0, 1);
}
void processSpecialKeys(int key, int xx, int yy) {
float moveFraction = 0.2f;
float angleFraction = 0.1f;
switch (key) {
case GLUT_KEY_LEFT:
angle -= angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_RIGHT:
angle += angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_UP:
x += vX * moveFraction;
z += vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
case GLUT_KEY_DOWN:
x -= vX * moveFraction;
z -= vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
}
}
void initLight() {
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 128);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
void renderWalls() {
// floor
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 8);
glVertex3f(0.0f, 0.0f, 10.0f);
glTexCoord2f(8, 8);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(8, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// walls
glBindTexture(GL_TEXTURE_2D, texture[3]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// first wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// second wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glEnd();
// third wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// fourth wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// ceiling
glBindTexture(GL_TEXTURE_2D, texture[7]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 3.0f, 10.0f);
glEnd();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
initLight();
renderWalls();
glutSwapBuffers();
}
void changeWindowSize(int width, int height) {
if (height == 0) {
height = 1;
}
float ratio = 1.0 * width / height;
windowWidth = width;
windowHeight = height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(0, 0);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Kitchen");
init();
glutDisplayFunc(display);
glutReshapeFunc(changeWindowSize);
glutIdleFunc(display);
glutSpecialFunc(processSpecialKeys);
glutMainLoop();
return 0;
}

Your light is stationary - but to the camera.
Fixed-function OpenGL does all the lighting calculations in eye space. At the moment you specify the GL_POSITION of a light, it is transformed according to the current modelView matrix at the time of the call, to get the eye space position. Since modelView is set to identity, it will always set the light to the given eye-space location - no matter where you later place the camera.
To fix this, just move initLight() after the gluLookAt.
However. You should not be doing this at all. You are using deprecated OpenGL features which you shouldn't use since a decade now. In modern GL, that functionality is completely removed. So if you are learning OpenGL in 2016, do yourself a favour and forget about that old cruft, and just learn shaders directly.

Related

Not able to to move two objects in opposite directions simultaneously in openGl

I am trying to make a project where we can move one tank in one direction ,other in the opposite direction by using translatef function I am able to move tank 1 ,when I try moving tank2 both the tanks start moving in the same direction along with the background .
Here is the image:-
Here when i click "Move Russian tank".It is moving .When i click Ukrainian tank i want it to move in opposite direction. I am not able to move Ukranian tank in opposite direction .Can u help with this ?.
Here is my code snipet:-
float th = 0.0;
float trX = 0.0, trY = 0.0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
if (rFlag == 1) //Rotate Around origin
{
trX += 0.5;
trY += 0.0;
}
background();
tank2();
glTranslatef(trX, trY, 0.0);
if (rFlag == 2) {
trX = 0.0;
}
tank1();
glutPostRedisplay();
glutSwapBuffers();
}
void rotateMenu(int option)
{
if (option == 1)
rFlag = 1;
if (option == 2)
rFlag = 2;
if (option == 3)
rFlag = 3;
}
void tank1()
{
glColor3f(0.0f, 0.1f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-479, -429);
glVertex2f(-479, -359);
glVertex2f(-399, -359);
glVertex2f(-399, -429);
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-459, -389);
glVertex2f(-459, -379);
glVertex2f(-419, -379);
glVertex2f(-419, -389);
glEnd();
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-459, -399);
glVertex2f(-459, -389);
glVertex2f(-419, -389);
glVertex2f(-419, -399);
glEnd();
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-459, -409);
glVertex2f(-459, -399);
glVertex2f(-419, -399);
glVertex2f(-419, -409);
glEnd();
glColor3f(0.0f, 0.1f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-459, -359);
glVertex2f(-459, -329);
glVertex2f(-419, -329);
glVertex2f(-419, -359);
glEnd();
glBegin(GL_QUADS);
glVertex2f(-439, -329);
glVertex2f(-419, -289);
glVertex2f(-414, -289);
glVertex2f(-434, -329);
glEnd();
}
void tank2()
{
glColor3f(0.0f, 0.1f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(391, -309);
glVertex2f(391, -239);
glVertex2f(471, -239);
glVertex2f(471, -309);
glEnd();
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(411, -279);
glVertex2f(411, -264);
glVertex2f(451, -264);
glVertex2f(451, -279);
glEnd();
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(411, -279);
glVertex2f(411, -294);
glVertex2f(451, -294);
glVertex2f(451, -279);
glEnd();
glColor3f(0.0f, 0.1f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(411, -239);
glVertex2f(411, -209);
glVertex2f(451, -209);
glVertex2f(451, -239);
glEnd();
glBegin(GL_QUADS);
glVertex2f(431, -209);
glVertex2f(451, -169);
glVertex2f(456, -169);
glVertex2f(436, -209);
glEnd();
}
int background()
{
glColor3f(0.0f, 1.0f, 0.0f);//Green
glBegin(GL_QUADS);
glVertex2f(-600, -800);
glVertex2f(-600, -100);
glVertex2f(800, -100);
glVertex2f(800, -800);
glEnd();
}
You need to have separate positions for both tanks and a separate mechanism for updating their position. Let us apply a smattering of OO:
struct Tank {
float x = 0, y = 0;
float dx = 0, dy = 0;
std::function<void()> drawFunc;
void update() {
x += dx;
y += dy;
}
void startMoving(float dx_, float dy_) {
dx = dx_;
dy = dy_;
}
void stopMoving() {
dx = dy = 0;
}
void draw() {
glLoadIdentity();
glTranslatef(dx, dy, 0);
drawFunc();
}
};
That means we can now declare the following somewhere global:
Tank tank1{0, 0, 0, 0, &draw_tank1};
Tank tank2{0, 0, 0, 0, &draw_tank2};
Your display function is now simply:
tank1.update(); tank1.draw();
tank2.update(); tank2.draw();
And you need to call startMoving or stopMoving on the correct tank in response to inputs, of course.
As a first improvement you should make the x and y positions match the positions of the tanks on screen and rewrite the draw_tank functions to draw around (0,0).

Freetype with opengl shows no text

I’m trying to add freetype text to my running program. The code below was adapted from EdoardoLuciani. No text is shown, though.
I checked if the the tff file is loaded correctly and that valid textures ids are generated. They are o.k.
The remaining of the program is running without problem, but no text is drawn.
Could you help me to find what's wrong, please?
Environment:
DELL XPS
GPU 1050
OpenGL 4.6
Win32
Language C
// Main program
...
initText()
...
// Drawing loop
...
{
drawText(10, 300, "Hello World!");
}
void initText()
{
// Extract glyphs textures
//
glUseProgram(textShader);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, "arial.ttf", 0, &face);
FT_Set_Pixel_Sizes(face, 0, 48);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int c = 0; c < 128; c++)
{
FT_Load_Char(face, c, FT_LOAD_RENDER);
//
// Extract glyph
//
GLuint texture;
glCreateTextures(GL_TEXTURE_2D,1, &texture);
glTextureStorage2D(texture, 1, GL_R8, face->glyph->bitmap.width, face->glyph->bitmap.rows);
glTextureSubImage2D(texture, 0, 0, 0, face->glyph->bitmap.width, face->glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
//
// Save glyph to lookup table
//
Character ch;
ch.texture = texture;
ch.bearing[0] = face->glyph->bitmap.width;
ch.bearing[1] = face->glyph->bitmap.rows;
ch.size[0] = face->glyph->bitmap_left;
ch.size[1] = face->glyph->bitmap_top;
ch.advance = face->glyph->advance.x;
characters[c] = ch;
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
//
// Create VAO
//
glCreateVertexArrays(1, &textVAO);
glBindVertexArray(textVAO);
//
// Create the unique VBO
//
glCreateBuffers(1, &VBO);
glNamedBufferStorage(VBO, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayVertexBuffer(textVAO, 0, VBO, 0, sizeof(GLfloat) * 4);
glVertexArrayAttribFormat(textVAO, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(textVAO, 0, 0);
glEnableVertexArrayAttrib(textVAO, 0);
//
// Send color to fragment shader
//
glUniform3f(6, 0.88f, 0.59f, 0.07f);
}
void drawText(float x, float y, float scale, char *text)
{
glEnable(GL_CULL_FACE);
glUseProgram(textShader);
glBindVertexArray(textVAO);
//
// Draw each character
//
char *c = text;
while(*c != 0)
{
Character ch = characters[(int)*c];
if(ch.bearing[0] != 0 && ch.bearing[1] != 0)
{
GLfloat xpos = x + ch.bearing[0] * scale;
GLfloat ypos = y - (ch.size[1] - ch.bearing[1]) * scale;
//
GLfloat w = ch.size[0] * scale;
GLfloat h = ch.size[1] * scale;
//
// Update VBO for each character
//
GLfloat vertices[6*4] =
{
xpos, ypos + h, 0.0f, 0.0f ,
xpos, ypos, 0.0f, 1.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos, ypos + h, 0.0f, 0.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos + w, ypos + h, 1.0f, 0.0f
};
glNamedBufferSubData(VBO, 0, sizeof(GLfloat)*6*4, vertices);
glBindTexture(GL_TEXTURE_2D, ch.texture);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
x += (ch.advance >> 6) * scale;
c++;
}
glDisable(GL_CULL_FACE);
}
The vertex shader:
#version 460 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
layout (location = 1) uniform mat4 projection;
out vec2 TexCoords;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}
The fragment shader:
#version 460 core
in vec2 TexCoords;
out vec4 color;
layout (binding = 0) uniform sampler2D text;
layout (location = 6) uniform vec3 textColor;
void main()
{
color = vec4(textColor, 1.0) * texture(text, TexCoords).r;
}

Texture Mapping disappeared when added 3D models

I am trying to make a background using SOIL_load_OGL_texture but when I added my 3D models the texture disappeared. The code for 3D models were separated from the texture code but when I combine it, the background becomes black and my 3D models is facing back. Is the problem here because of the coordination?
I expect the output would be the 3D models facing front and it is in front of the texture.
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "SOIL2.h"
GLuint myTexture;
const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
static int head = 0, rear = -90, lear = -90, body = 0, lleg = -90, rleg = -90, ball = 0, stage = 0;
GLfloat ballRadius = 0.1f;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0.5, 0.85, 0.9); // head
glPushMatrix();
glTranslated(0, 0.25, 0.15);
glRotated((GLfloat)head, 0, 1, 0);
glutSolidSphere(0.2, 40, 50);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(0.11, 0.3, 0.18);
glRotated((GLfloat)rear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(-0.11, 0.3, 0.18);
glRotated((GLfloat)lear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glColor3d(0.0, 0.0, 0.0); //eyes
glPushMatrix();
glTranslated(0.07, 0.3, 0.33);
glRotated(-5, 0, 0, 1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //eyes
glTranslated(-0.07, 0.3, 0.33);
glRotated(-5, 0, 0, -1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //mouth
glTranslated(0.0, 0.25, 0.35);
glRotated(0, 0, 0, 0);
glScalef(1, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glColor3d(1.0, 1.0, 1.0);
glPushMatrix(); // teeth
glTranslated(-0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glPushMatrix(); // teeth
glTranslated(0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glColor3d(0.5, 0.85, 0.88); // body
glTranslatef(0, 0, 0.1);
glPushMatrix();
glRotated((GLfloat)body, 1, 0, 0);
glutSolidSphere(0.3, 40, 50);
glPopMatrix();
glPushMatrix();
glTranslatef(0, 0.7, 0.0);
glRotatef((GLfloat)stage, 0.0, 1.0, 0.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutWireCube(1.0);
glPopMatrix();
//glFlush();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
/*glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); */
glNormal3f(0.0, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, -2.5f, -2.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, -2.5f, -2.5f);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
}
void reshape(int width, int height)
{
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutCreateWindow("SOIL test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
myTexture = SOIL_load_OGL_texture("background.png", 0, 1, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_INVERT_Y);
if (!myTexture)
{
printf("soil failed to load texture\n");
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glutMainLoop();
return EXIT_SUCCESS;
}
If you want that the background image is draw in the back, then you've to draw the background first, but disable the Depth Test (The depth buffer has to be cleared before).
This causes that the other geometry covers the background.
When the background is drawn no projection matrix is set, the projection matrix is the identity matrix. So the z-coordinate of the background has to be in [-1, 1], else it wold be clipped by the near or far plane.
If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.
This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor3d.
Set a "white" color before you render the texture:
glColor3d(1.0, 1.0, 1.0);
Note, OpenGL is a state engine. If a color was set, the color is kept until it is changed again, even beyond frames. So this might not be an issue in the first frame, but it would be in the further frames.
The fixed function light model is applied on the background, too. This will cause a bad look with fixed function gouraud light model. I recommend to disable lighting before you draw the background.
glDisable(GL_LIGHTING);
and to enable lighting before you draw the geometry
glEnable(GL_LIGHTING);
The function display may look like this:
void display(void)
{
// clear color buffer and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// prepare for drawing the back ground
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glColor3d(1.0, 1.0, 1.0);
// projection and model view for the background
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw the background
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
// prepare for drawing the geometry
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
// projection and model view for the geoemtry
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw geometry
glColor3d(0.5, 0.85, 0.9); // head
// ...
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}

Rotating around the origin in 3d space using GLUT

I am stuck trying to get this code to work in Visual Studio 2012 using glut. It renders a 10/10 3D grid but it will not respond to my input from the keyboard. I am trying to get the camera to rotate around the origin when i hit the left arrow key.
// This example shows how to create a camera for 3D graphics.
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int g_winWidth = 1024;
int g_winHeight = 512;
bool keyStatus[256];
float angle = 0.0f; //angle for rotating camera
float beginning_angle = 0.0f;
float cx = 10.0, cy = 10.0, cz = -10.0;
void initialGL()
{
glEnable(GL_DEPTH_TEST);
glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
}
//initialize the keyboard keys
void initialization()
{
for(int i =0; i<256; i++)
keyStatus[i] = false;
}
//function to draw the colored x,y, and z axis
void drawCS()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef(10.0f, 10.0f, 10.0f);
glLineWidth(2.5f);
glBegin(GL_LINES);
//axis x
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.3f, 0.0f, 0.0f);
//text x
glVertex3f(0.4f, 0.05f, 0.0f);
glVertex3f(0.5f, -0.05f, 0.0f);
glVertex3f(0.4f, -0.05f, 0.0f);
glVertex3f(0.5f, 0.05f, 0.0f);
//axis y
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.3f, 0.0f);
//text y
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(0.0f, 0.4f, 0.0f);
glVertex3f(-0.05f, 0.55f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(0.05f, 0.55f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
//axis z
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.3f);
//text z
glVertex3f(-0.025f, 0.025f, 0.4f);
glVertex3f(0.025f, 0.025f, 0.4f);
glVertex3f(0.025f, 0.025f, 0.4f);
glVertex3f(-0.025f, -0.025f, 0.4f);
glVertex3f(-0.025f, -0.025f, 0.4f);
glVertex3f(0.025f, -0.025f, 0.4f);
glEnd();
glLineWidth(1.0f);
glPopMatrix();
}
//function to draw the grid
void drawGrid()
{
int size = 10; // determining the grid size and the numbers of cells
if(size%2 != 0) ++size;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//glScalef(30.0f, 30.0f, 30.0f);
glBegin(GL_LINES);
for (int i =0; i<size+1; i++) {
if((float)i == size/2.0f) {
glColor3f(0.0f, 0.0f, 0.0f);
} else {
glColor3f(0.8f, 0.8f, 0.8f);
}
glVertex3f(-size/2.0f, 0.0f, -size/2.0f+i);
glVertex3f(size/2.0f, 0.0f, -size/2.0f+i);
glVertex3f(-size/2.0f+i, 0.0f, -size/2.0f);
glVertex3f(-size/2.0f+i, 0.0f, size/2.0f);
}
glEnd();
glPopMatrix();
}
//function to display everything that is happening in window
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawGrid();// call to function to draw the grid
drawCS();//call to function to draw the x,y,z axis
glutSwapBuffers();
}
void reshape(int w, int h)
{
g_winWidth = w;
g_winHeight = h;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//this function sets the initial position of the camera in 3D space
/*
Need to find a way to rotate around the origin from left to right
*/
gluLookAt( cx, cy, cz, //camera position
0.0f, 0.0f, 0.0f, //what camera looks at
0.0f, 1.0f, 0.0f); //
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, g_winWidth/g_winHeight, 0.1, 100);//specifies the view for the scene
glViewport(0, 0, w, h);
//angle += 0.1f;
}
//keyboard function for the exit key
void keyboard(unsigned char key, int x, int y)
{
keyStatus[key] = true;
switch (key) {
case 27:
exit(0);
break;
default:
break;
}
}
//sets the keyboard callback to the current window
void keyboardUp(unsigned char key, int x, int y)
{
keyStatus[key] = false;
}
//function for arrow keys output
void processSpecialKeys(int key, int xx, int yy) {
switch(key) {
case GLUT_KEY_LEFT :
//What the left arrow key does
angle -= 0.01f;
cx = sin(angle);
cz = -cos(angle);
break;
case GLUT_KEY_RIGHT :
//What the right arrow key does
break;
case GLUT_KEY_UP :
//What the up arrow key does
break;
case GLUT_KEY_DOWN :
//What the down arrow key does
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(g_winWidth, g_winHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Camera");
initialGL();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(processSpecialKeys);
glEnable(GL_DEPTH_TEST);
initialization();
glutMainLoop();
return 1;//changed from EXIT_SUCCESS
}

Using Multiple Textures in OpenGL only One Displayed

I've modified my original code (previous post) to use two textures. Here they are:
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "support.h"
using namespace std;
GLuint *images;
GLubyte *image;
GLuint texture1=0;
GLuint texture2=0;
GLuint LoadTexture(int width, int height, char *fName);
int n=200;
int m=200;
void showPictureW();
void showPictureR();
float rX=0;
float rY=0;
float rZ=0;
float tX=0;
float tY=0;
float tZ=-3.5;
float nr = -5.0;
float fr = -4.0;
float tpx = 1.0;
float tpy = 1.0;
float btx = -1.0;
float bty = -1.0;
float dZ =-2.0;
void showPictureW()
{
/* clear all pixels */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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);
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0);
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);
glEnd();
}
void showPictureR()
{
//clear all pixels
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,1,1);
//face 1
glBegin( GL_POLYGON );
glTexCoord2d(1.0,1.0); glVertex3d(-1.2,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(0.0,1.0,-2.0);
glTexCoord2d(0.0,0.0); glVertex3d(0.0,2.0,-2.0);
glEnd();
//face 2
glBegin( GL_POLYGON );
glTexCoord2d(0.0,0.0); glVertex3d(0.0,2.0,-2.0);
glTexCoord2d(0.0,1.0); glVertex3d(0.0,1.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(1.2,1.0,-2.0);
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() ;
}
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,0,0);
glEnable( GL_TEXTURE_2D );
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,0,1,0);
glRotated(rZ,1,0,0);
showPictureR();
glPopMatrix();
glutSwapBuffers();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
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);
texture1 = LoadTexture( 200, 200, "wall.ppm" );
texture2 = LoadTexture( 200, 200, "roof.ppm" );
glutMainLoop();
return EXIT_SUCCESS;
}
GLuint LoadTexture(int width, int height, 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);
nm = n*m;
images = new GLuint[3*sizeof(GLuint)*nm];
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++)
{
tot++;
}
image = new BYTE[width*height*3*sizeof(BYTE)];
int nmOne = width*height;
for(int i=0;i<nmOne*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;
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, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, image );
return texture;
}
My problem is that it won't load both textures at once. I've tried using one at a time and they're okay. But with the above code only the second texture ("roof.ppm") appears. I found the code below in another post which seems quite similar to my problem but I'm not sure how to use it.
void DrawFrame()
{
...
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(0, this.Width, 0, this.Height);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// "camera" transform(s)
foreach object
{
glPushMatrix();
// per-object matrix transform(s)
// draw object
glPopMatrix();
}
}
You do call
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
in both of your showPictureW and showPictureR functions, so it should not surprise you that only the effects last of these calls can be seen in the end.

Resources