VTK face keeps rendering backwards - c++

I am trying to render the faces of a cube using VTK 9.2.
The cube's vertices are ordered like so:
// 7-------6
// /| /|
// 4-+-----5 |
// | | | | y
// | 3-----+-2 | z
// |/ |/ |/
// 0-------1 +--x
(Yes I know this is somewhat atypical ordering, but we're just rendering faces in VTK, so it shouldn't matter as long as we're consistent with the usage)
While one of the faces works perfectly, the other consistently renders backwards regardless of how I define it.
I am using the VTK_PIXEL ordering for each face.
Here is the code that does the rendering:
vtkGenericOpenGLRenderWindow* renderWindow = vtkGenericOpenGLRenderWindow::New();
vtkNew<vtkUnstructuredGrid> ugrid;
// Create and insert vertices
std::vector<std::vector<double>> vertices(8);
double halfWidth = 20.0;
vertices[0] = { - halfWidth, - halfWidth, - halfWidth }; // 0
vertices[1] = { + halfWidth, - halfWidth, - halfWidth }; // 1
vertices[2] = { + halfWidth, - halfWidth, + halfWidth }; // 2
vertices[3] = { - halfWidth, - halfWidth, + halfWidth }; // 3
vertices[4] = { - halfWidth, + halfWidth, - halfWidth }; // 4
vertices[5] = { + halfWidth, + halfWidth, - halfWidth }; // 5
vertices[6] = { + halfWidth, + halfWidth, + halfWidth }; // 6
vertices[7] = { - halfWidth, + halfWidth, + halfWidth }; // 7
vtkNew<vtkPoints> points;
for (auto i = 0; i < 8; ++i)
{
points->InsertNextPoint(vertices.at(i).at(0), vertices.at(i).at(1), vertices.at(i).at(2));
}
// Create faces
std::vector<std::array<vtkIdType, 4>> faces;
faces.push_back({ 3, 2, 7, 6 }); // +Z, works perfectly!
// -Z:
faces.push_back({ 1, 0, 5, 4 }); // backwards
//faces.push_back({ 0, 1, 4, 5 }); // backwards
//faces.push_back({ 0, 4, 1, 5 }); // backwards
//faces.push_back({ 5, 1, 4, 0 }); // backwards
//faces.push_back({ 4, 5, 0, 1 }); // backwards
//faces.push_back({ 1, 5, 0, 4 }); // backwards
//faces.push_back({ 4, 0, 5, 1 }); // backwards
//faces.push_back({ 5, 4, 1, 0 }); // also backwards
// Insert faces
for(int i = 0; i < faces.size(); i++)
{
ugrid->InsertNextCell(VTK_PIXEL, 4, faces.at(i).data());
}
ugrid->SetPoints(points);
// Create new data mapper for this snapshot
vtkNew<vtkDataSetMapper> mapper;
mapper->SetInputData(ugrid);
// Create new actor for this data snapshot
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
addActorToScene(0, 0.0, actor);
renderWindow->Render();
The +Z face works fantastic and looks correct. However, the other face is always backwards no matter what node order I try.
This is what I see in my window:
As seen there, the +Z face (3, 2, 7, 6) works great. It appears white on the outside and black on the inside.
But the -Z face does not work - it appears white on the inside of the cube, and black on the outside.

It was a lighting issue, mi aculpa. I was doing the following outside of this code:
vtkNew<vtkLight> light;
renderWindow->AddLight(light);
Once I removed that and the default lighting took over, both the inside and outside of each face appear white, so which side appears white does not indicate the direction of the face.

Related

How do I bring a polygon to the foreground in OpenGL?

The code below creates 2 square polygons, red and green.
I'm trying to place a red square on top of the green, but I can't.
The depth buffer is declared, cleaned when necessary, an orthogonal system is configured correctly.
If I specify a value outside the range (2;-2), the polygon disappears as it should.
#include <...>
constexpr auto FPS_RATE = 120;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;
void init();
void idleFunction();
void displayFunction();
double getTime();
double getTime()
{
using Duration = std::chrono::duration<double>;
return std::chrono::duration_cast<Duration>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count();
}
const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;
void init()
{
glutDisplayFunc(displayFunction);
glutIdleFunc(idleFunction);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, 2, -2);
glClearColor(0.0, 0.0, 0.0, 0.0);
}
void idleFunction()
{
const double current_time = getTime();
if ((current_time - last_render) > frame_delay)
{
last_render = current_time;
glutPostRedisplay();
}
}
void displayFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
//move the red square to the foreground
glTranslatef(-32.5, -32.5, 2);
glColor3f(1, 0, 0);
glBegin(GL_POLYGON);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glPopMatrix();
glPushMatrix();
//move the green square to the background
glTranslatef(32.5, 32.5, -2);
glColor3f(0, 1, 0);
glBegin(GL_POLYGON);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
glutCreateWindow("Window");
init();
glutMainLoop();
return 0;
}
You've to enable the Depth Test:
glEnable( GL_DEPTH_TEST );
The default depth test function (glDepthFunc) is < (GL_LESS).
If the distance to the far plane is 2.0 and the geometry is drawn with z coordinate of 2.0, then the geometry is clipped by the far plane, because the depth of the geometry is not less than the initialization depth of the depth buffer.
Change the depth function to <= (GL_LEQUAL):
glDepthFunc( GL_LEQUAL );
In a Right-handed system the viewspace z-axis points out of the viewport.
So if the z coordinate is "less than", then the object is "behind" an other object.
The projection matrix transforms from view space to normalized device space. In compare to the view space, the normalized device space is a left handed system, where the z-axis points in the viewport. The normalized device z-coordinate in range [-1, 1] (from the front to the back), is mapped to the depth value (in general in range [0, 1]), which is used for the depth test.
To deal with that glOrtho inverts the z-axis, if the near parameter is set less then the far parameter (this is how the function is suggested to be used).
This cause that the depth (z) order doesn't change, when the geometry is transformed form view space to normalized device space.
Note, glOrtho(-w, w, -h, h, -z, z) is the same as glScaled(1.0/w, 1.0/h, -1.0/z)
Since the z-axis is not inverted by the orthographic projection in your example, because near > far,
glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, 2, -2);
the z coordinate has to be greater, to be "behind".
If the green rectangle should be behind the red one, then you've to change the orthographic projection (near < far). e.g.:
glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -2, 2);
If you don't want to change the projection, then you've to swap the z-coordinates of the geometry:
glPushMatrix();
//move the red square to the foreground
glTranslatef(-32.5, -32.5, -2.0); // foreground because near > far
// ...
glPopMatrix();
glPushMatrix();
//move the green square to the background
glTranslatef(32.5, 32.5, 2.0); // background because near > far
// ...
glPopMatrix();

How to draw square on the button at the center using OpenGL?

How to draw a square on the button at the center (like stop button)?
In this code that I try it be like a rectangle and full of the button:
void ButtonDraw(Button *b)
{
if(b)
{
/*
* We will indicate that the mouse cursor is over the button by changing its
* colour.
*/
if (b->highlighted)
glColor3f(0.7f,0.7f,0.8f);
else
glColor3f(0.6f,0.6f,0.6f);
/*
* draw background for the button.
*/
glBegin(GL_QUADS);
glVertex2i( b->x , b->y );
glVertex2i( b->x , b->y+b->h );
glVertex2i( b->x+b->w, b->y+b->h );
glVertex2i( b->x+b->w, b->y );
glEnd();
/*draw red square on the button*/
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2i(b->x, b->y);
glVertex2i(b->x+b->w, b->y);
glVertex2i(b->x+b->w, b->y + b->h);
glVertex2i(b->x, b->y + b->h);
glEnd();
/*
* Draw an outline around the button with width 3
*/
glLineWidth(3);
}
}
The obvious way is to not draw a red rectangle the same size as the button, but instead draw a square. Here is the most basic way to do this:
/*draw red square on the button*/
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
const int SQUARE_SIDE = 6; // Or however long you want a side
// Calculate the centre of the button rectangle
const int xMid = b->x + b->w / 2;
const int yMid = b->y + b->h / 2;
// Trace a square around the centre
glVertex2i(b->xMid - SQUARE_SIDE / 2, b->yMid - SQUARE_SIDE / 2);
glVertex2i(b->xMid - SQUARE_SIDE / 2, b->yMid + SQUARE_SIDE / 2);
glVertex2i(b->xMid + SQUARE_SIDE / 2, b->yMid + SQUARE_SIDE / 2);
glVertex2i(b->xMid + SQUARE_SIDE / 2, b->yMid - SQUARE_SIDE / 2);
glEnd();
The above code calculates the middle of the button then draws a square around it. For production code you'd of course check that you didn't overlap the edges of the button, and use floats to deal with rounding issues, etc.

OpenGL - Line disappear when move camera

I write a program to draw one line.
The line sometimes disappear when I move camera to positive z-axis (especially when z-axis greater than 10000).
There are some test result.
When z set 20541, the line can be seen.
When z set 20542, the line CAN'T be seen.
When z set 30320, the line can be seen.
When z set 30321, the line CAN'T be seen.
and so forth ...
The code is attached. What's wrong?
P.S.
The code is written by OpenGL 1.0, but I can still get the same test result when written by OpenGL 3.0 + glm library.
#include <glut.h>
/*
System Info
-------------
OS: Win7 professional 64-bit SP1
CPU: Intel i3-4170 # 3.70GHz
GPU: HD Graphics 4400
*/
void display(void) {
// 20541 ok, 20542 not visible
// 30320 ok, 30321 not visible
const GLfloat z = 20541;
const GLfloat far = 1000, near = 0.1;
GLfloat vertices[4 * 3] = {
-far, -far, z - far,
far, far, z - far,
};
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, z, 0, 0, z - 1, 0, 1, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.1, 0.1, -0.1, 0.1, near, far);
glColor3f(0, 1, 1); // blue
glBegin(GL_LINES);
glVertex3f(vertices[0], vertices[1], vertices[2]);
glVertex3f(vertices[3], vertices[4], vertices[5]);
glEnd();
glFlush();
}
int main() {
glutCreateWindow("");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
This issue seems to be a numerical instability of the floating point arithmetic. Since you are projecting points that are exactly on the far-plane, they get clipped when the floating-point result is a little bit larger than the expected result.
Let's assume a C++ implementation of what the gpu basically does:
glm::vec4 test_fp(float z)
{
//Construct matrices
auto ortho = glm::frustum(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1000.0f);
auto lookat = glm::lookAt(glm::vec3(0, 0, z), glm::vec3(0, 0, z - 1.0f), glm::vec3(0, 1, 0));
//We are only interested in the z-value
glm::vec4 tvec(0, 0, z - 1000.0f, 1);
//Calculate ndc vector
auto result = ortho * lookat * tvec;
//Homogenize
result /= result.w;
return result;
}
When now calling this function with the values you provided we get the following results:
auto a = test_fp(20541.0); //< [0, 0, 1.00000000, 1]
auto b = test_fp(20542.0); //< [0, 0, 1.00000191, 1]
auto c = test_fp(30320.0); //< [0, 0, 1.00000000, 1]
auto d = test_fp(30321.0); //< [0, 0, 1.00000191, 1]
As you can see, the results of b and d diverge from the mathematical correct result and are slightly above 1.0. Since values above 1.0 are behind the far-plane, they are clipped away and are not visible, which is exactly the behavior you have.

trouble displaying graphics in opengl program

I am making changes in the code from this article, to acomplish the same result without need the methods specific for Windows and be able to run the programa in other platforms. I can compile and run the program without errors (with the Main and Render functions listed below), but the result is a blank screen. Someone can find some reason in the code for this issue happen?
Main:
int main(int argc, char **argv)
{
// temp var's
int width = 800;
int height = 600;
int bits = 32;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(width,height);
glutInit(&argc, argv);
glutCreateWindow("Terrain");
glutDisplayFunc(Render);
glutReshapeFunc(AlteraTamanhoJanela);
glutKeyboardFunc(GerenciaTeclado);
glutMouseFunc(GerenciaMouse);
Initialize();
glutMainLoop();
}
Render:
void Render()
{
radians = float(PI*(angle-90.0f)/180.0f);
// calculate the camera's position
cameraX = lookX + sin(radians)*mouseY; // multiplying by mouseY makes the
cameraZ = lookZ + cos(radians)*mouseY; // camera get closer/farther away with mouseY
cameraY = lookY + mouseY / 2.0f;
// calculate the camera look-at coordinates as the center of the terrain map
lookX = (MAP_X*MAP_SCALE)/2.0f;
lookY = 150.0f;
lookZ = -(MAP_Z*MAP_SCALE)/2.0f;
// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// set the camera position
gluLookAt(cameraX, cameraY, cameraZ, lookX, lookY, lookZ, 0.0, 1.0, 0.0);
// set the current texture to the land texture
glBindTexture(GL_TEXTURE_2D, land);
// we are going to loop through all of our terrain's data points,
// but we only want to draw one triangle strip for each set along the x-axis.
for (int z = 0; z < MAP_Z-1; z++)
{
//printf("%s %d\n","Loop FOR para Z = ",z);
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < MAP_X-1; x++)
{
//printf("%s %d\n","Loop FOR para X = ",x);
// for each vertex, we calculate the grayscale shade color,
// we set the texture coordinate, and we draw the vertex.
/*
the vertices are drawn in this order:
0 ---> 1
/
/
|/
2 ---> 3
*/
// draw vertex 0
//printf("%s\n","Primeiro");
glColor3f(terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(terrain[x][z][0], terrain[x][z][1], terrain[x][z][2]);
// draw vertex 1
//printf("%s\n","Segundo");
glTexCoord2f(1.0f, 0.0f);
glColor3f(terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f);
glVertex3f(terrain[x+1][z][0], terrain[x+1][z][1], terrain[x+1][z][2]);
// draw vertex 2
//printf("%s\n","Terceiro");
glTexCoord2f(0.0f, 1.0f);
glColor3f(terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f);
glVertex3f(terrain[x][z+1][0], terrain[x][z+1][1], terrain[x][z+1][2]);
// draw vertex 3
//printf("%s\n","Quarto");
glColor3f(terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(terrain[x+1][z+1][0], terrain[x+1][z+1][1], terrain[x+1][z+1][2]);
}
glEnd();
}
// enable blending
glEnable(GL_BLEND);
// enable read-only depth buffer
glDepthMask(GL_FALSE);
// set the blend function to what we use for transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
// set back to normal depth buffer mode (writable)
glDepthMask(GL_TRUE);
// disable blending
glDisable(GL_BLEND);
glFlush();
//SwapBuffers(g_HDC); // bring backbuffer to foreground
}
Update: As requested, here is the other functions from my code.
void InitializeTerrain()
{
// loop through all of the heightfield points, calculating
// the coordinates for each point
for (int z = 0; z < MAP_Z; z++)
{
for (int x = 0; x < MAP_X; x++)
{
terrain[x][z][0] = float(x)*MAP_SCALE;
terrain[x][z][1] = (float)imageData[(z*MAP_Z+x)*3];
terrain[x][z][2] = -float(z)*MAP_SCALE;
}
}
}
void CleanUp()
{
free(imageData);
free(landTexture);
}
// Initialize
// desc: initializes OpenGL
void Initialize()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // clear to black
glShadeModel(GL_SMOOTH); // use smooth shading
glEnable(GL_DEPTH_TEST); // hidden surface removal
glEnable(GL_CULL_FACE); // do not calculate inside of poly's
glFrontFace(GL_CCW); // counter clock-wise polygons are out
glEnable(GL_TEXTURE_2D); // enable 2D texturing
imageData = LoadBitmapFile("terrain2.bmp", &bitmapInfoHeader);
// initialize the terrain data and load the textures
InitializeTerrain();
LoadTextures();
}
// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
int width, height;
height = h; // retrieve width and height
width = w;
if (height==0) // don't want a divide by zero
{
height=1;
}
glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix
// calculate aspect ratio of window
gluPerspective(54.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity(); // reset modelview matrix
}
// Função callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
int oldMouseX, oldMouseY;
// save old mouse coordinates
oldMouseX = mouseX;
oldMouseY = mouseY;
// get mouse coordinates from Windows
mouseX = x;
mouseY = y;
// these lines limit the camera's range
if (mouseY < 200)
mouseY = 200;
if (mouseY > 450)
mouseY = 450;
if ((mouseX - oldMouseX) > 0) // mouse moved to the right
angle += 3.0f;
else if ((mouseX - oldMouseX) < 0) // mouse moved to the left
angle -= 3.0f;
glutPostRedisplay();
}
/* Key press processing */
void GerenciaTeclado(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
}
And, finally, the content from file vkgllib.h, included by source code file above:
#include <iostream>
#include <fstream>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define WINDOW_WIDTH 640 // Window Width Default
#define WINDOW_HEIGHT 480 // Window Height Default
// definition of PI
#define PI 3.14159265
// Used to defien the title of the window
#define WINDOW_TITLE "OpenGL Terrain Generation"
// A simple structure to define a point whose coordinates are integers
/*typedef struct { GLint x, y; } GLintPoint;
// This structure is used to store the vertices of a polyline
typedef struct { int num; GLintPoint pt[100]; } GLintPointArray;
// Data for an Icosahedron
#define ICO_X 0.525731112119133606
#define ICO_Z 0.850650808352039932*/
/*static GLfloat vdataICO[12][3] =
{
{ -ICO_X, 0.0, ICO_Z }, { ICO_X, 0.0, ICO_Z }, { -ICO_X, 0.0, -ICO_Z }, { ICO_X, 0.0, -ICO_Z },
{ 0.0, ICO_Z, ICO_X }, { 0.0, ICO_Z, -ICO_X }, { 0.0, -ICO_Z, ICO_X }, { 0.0, -ICO_Z, -ICO_X },
{ ICO_Z, ICO_X, 0.0 }, { -ICO_Z, ICO_X, 0.0 }, { ICO_Z, -ICO_X, 0.0 }, { -ICO_Z, -ICO_X, 0.0 }
};
static GLuint tindicesICO[20][3] =
{
{ 1, 4, 0 }, { 4, 9, 0 }, { 4, 5, 9 }, { 8, 5, 4 }, { 1, 8, 4 },
{ 1, 10, 8 }, { 10, 3, 8 }, { 8, 3, 5 }, { 3, 2, 5 }, { 3, 7, 2 },
{ 3, 10, 7 }, { 10, 6, 7 }, { 6, 11, 7 }, { 6, 0, 11 }, {6, 1, 0 },
{ 10, 1, 6 }, { 11, 0, 9 }, { 2, 11, 9 }, { 5, 2, 9 }, { 11, 2, 7 }
};*/
// Data for Tetrahedron
static GLfloat P1T[3] = { -2, 3, 0 };
static GLfloat P2T[3] = { -3, 0, 0 };
static GLfloat P3T[3] = { -1, 0, 3 };
static GLfloat P4T[3] = { -4, 0, 0 };
// Calculating the Normalized Cross Product of Two Vectors
void normalize( float v[3] )
{
GLfloat d = sqrt( float(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) );
if( d==0.0 )
{
cerr<<"zero length vector"<<endl;
return;
}
v[0] /= d;
v[1] /= d;
v[2] /= d;
}
void normcrossprod( float v1[3], float v2[3], float out[3] )
{
out[0] = v1[1]*v2[2] - v1[2]*v2[1];
out[1] = v1[2]*v2[0] - v1[0]*v2[2];
out[2] = v1[0]*v2[1] - v1[1]*v2[0];
normalize( out );
}
////// Defines
#define BITMAP_ID 0x4D42 // the universal bitmap ID
#define MAP_X 32 // size of map along x-axis
#define MAP_Z 32 // size of map along z-axis
#define MAP_SCALE 20.0f // the scale of the terrain map
////// Texture Information
BITMAPINFOHEADER bitmapInfoHeader; // temp bitmap info header
BITMAPINFOHEADER landInfo; // land texture info header
BITMAPINFOHEADER waterInfo; // water texture info header
//AUX_RGBImageRec
unsigned char* imageData; // the map image data
unsigned char* landTexture; // land texture data
unsigned int land; // the land texture object
////// Terrain Data
float terrain[MAP_X][MAP_Z][3]; // heightfield terrain data (0-255); 256x256
// LoadBitmapFile
// desc: Returns a pointer to the bitmap image of the bitmap specified
// by filename. Also returns the bitmap header information.
// No support for 8-bit bitmaps.
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
bool LoadTextures()
{
// load the land texture data
landTexture = LoadBitmapFile("green.bmp", &landInfo);
if (!landTexture)
return false;
// generate the land texture as a mipmap
glGenTextures(1, &land);
glBindTexture(GL_TEXTURE_2D, land);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, landInfo.biHeight, landInfo.biWidth, GL_RGB, GL_UNSIGNED_BYTE, landTexture);
return true;
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
^^^^^^^^^^^
You've asked for double-buffering.
And yet your Render() function seems to assume you're using single-buffering:
void Render()
{
...
glFlush();
}
Either switch to GLUT_SINGLE or use glutSwapBuffers() instead of glFlush().

How to proper position skybox camera using openGL

I created a skybox for my project and it looks the way I wanted it to; however, there are a few issues I cannot figure out how to fix and I have read some tutorials on this subject, but I was not able to find something that would help me.
The first problem is that I don't know how to get the box to always move with my camera. In the image below you can see that I am able to zoom out and see the whole box, instead of only zooming in/out of the solar system and always having the stars on the background.
The other issue I have is that when I zoom in too close my background disappears.The picture below illustrates what I mean
I know if I can get the camera working properly I can get this fixed, but it goes back to my first problem. I don't know how to access the camera info.
I believe I would have to modify glTranslatef() and glScalef() in my code from a fixed number to a number that changes with the camera position.
Here is my code:
void Skybox::displaySkybox()
{
Images::RGBImage test[6]; //6 pictures for 6 sides
test[0]=Images::readImageFile(fileName); //Top
//test[1]=Images::readImageFile(fileName);//Back
//test[2]=Images::readImageFile(fileName);//Bottom
//test[3]=Images::readImageFile(fileName);//Right
//test[4]=Images::readImageFile(fileName); //Left
//test[5]=Images::readImageFile(fileName); //Front
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
test[0].glTexImage2D(GL_TEXTURE_2D,0,GL_RGB);
// Save Current Matrix
glPushMatrix();
// Second Move the render space to the correct position (Translate)
glTranslatef(0,0,0);
// First apply scale matrix
glScalef(10000,10000,10000);
static const GLint faces[6][4] =
{
{5, 1, 2, 6}, // back
{5, 4, 0, 1}, // bottom
{0, 4, 7, 3}, // front
{4, 5, 6, 7}, // right ( 'left' in crinity's labeling )
{1, 0, 3, 2}, // left ( 'right' in crinity's labeling )
{2, 3, 7, 6} // top*/
};
GLfloat v[8][3];
GLint i;
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1; // min x
v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1; // max x
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1; // min y
v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1; // max y
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -1; // min z
v[1][2] = v[2][2] = v[5][2] = v[6][2] = 1; // max z
for (i = 0; i < 7; i++)
{
//
glBegin(GL_QUADS);
glTexCoord2f(0,1); glVertex3fv(&v[faces[i][0]][0]);
glTexCoord2f(1,1); glVertex3fv(&v[faces[i][1]][0]);
glTexCoord2f(1,0); glVertex3fv(&v[faces[i][2]][0]);
glTexCoord2f(0,0); glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
// Load Saved Matrix
glPopMatrix();
}
How can I get access to these variables? Does openGL alreay have a function that takes care of that?
I believe I would have to modify glTranslatef() and glScalef() in my code from a fixed number to a number that changes with the camera position.
You're close, but there's a simpler solution:
Draw the skybox first, before translating the camera, so that you don't have to translate the box. Don't forget to clear your depth buffer for each new frame (you'll see why in a second).
Disable writes to the depth buffer (call glDepthMask(GL_FALSE)). This will cause every other object you render to draw over it, making it always appear "behind" everything else.
Assuming your transform matrices were reset at the start of the frame, apply only the rotation of the camera. This way the camera will always be "centered" inside the box.
Draw the skybox. Since writes to the depth buffer are off, it doesn't matter how small it is as long as it's larger than your camera's near clip plane.
Re-enable writes to the depth buffer (call glDepthMask(GL_TRUE))
Render your scene normally.
I haven't worked with skyboxes before, but it would make sense that the camera should always be at the center of the box. So start by translating the box to center around the camera coordinates, something like glTranslate(camera.x, camera.y, camera.z);
Then I'd think the box should stay infinitely distant, so maybe set the vertices to INT_MAX or something ridonculously big.
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -INT_MAX; // min x
v[4][0] = v[5][0] = v[6][0] = v[7][0] = INT_MAX; // max x ...etc
Then probably get rid of the call to glScalef(). Try that out