I'm working on porting my open source particle engine test from SDL to SDL + OpenGL. I've managed to get it compiling, and running, but the screen stays black no matter what I do.
main.cpp:
#include "glengine.h"
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//Create a glengine instance
ultragl::glengine *gle = new ultragl::glengine();
if(gle->init())
gle->run();
else
std::cout << "glengine initializiation failed!" << std::endl;
//If we can't initialize, or the lesson has quit we delete the instance
delete gle;
return 0;
};
glengine.h:
//we need to include window first because GLee needs to be included before GL.h
#include "window.h"
#include <math.h> // Math Library Header File
#include <vector>
#include <stdio.h>
using namespace std;
namespace ultragl
{
class glengine
{
protected:
window m_Window; ///< The window for this lesson
unsigned int m_Keys[SDLK_LAST]; ///< Stores keys that are pressed
float piover180;
virtual void draw();
virtual void resize(int x, int y);
virtual bool processEvents();
void controls();
private:
/*
* We need a structure to store our vertices in, otherwise we
* just had a huge bunch of floats in the end
*/
struct Vertex
{
float x, y, z;
Vertex(){}
Vertex(float x, float y, float z)
{
this->x = x;
this->y = y;
this->z = z;
}
};
struct particle
{
public :
double angle;
double speed;
Vertex v;
int r;
int g;
int b;
int a;
particle(double angle, double speed, Vertex v, int r, int g, int b, int a)
{
this->angle = angle;
this->speed = speed;
this->v = v;
this->r = r;
this->g = g;
this->b = b;
this->a = a;
}
particle()
{
}
};
particle p[500];
float particlesize;
public:
glengine();
~glengine();
virtual void run();
virtual bool init();
void glengine::test2(int num);
void glengine::update();
};
};
window.h:
#include <string>
#include <iostream>
#include "GLee/GLee.h"
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <GL/glu.h>
using namespace std;
namespace ultragl
{
class window
{
private:
int w_height;
int w_width;
int w_bpp;
bool w_fullscreen;
string w_title;
public:
window();
~window();
bool createWindow(int width, int height, int bpp, bool fullscreen, const string& title);
void setSize(int width, int height);
int getHeight();
int getWidth();
};
};
glengine.cpp (the main one to look at):
#include "glengine.h"
namespace ultragl{
glengine::glengine()
{
piover180 = 0.0174532925f;
}
glengine::~glengine()
{
}
void glengine::resize(int x, int y)
{
std::cout << "Resizing Window to " << x << "x" << y << std::endl;
if (y <= 0)
{
y = 1;
}
glViewport(0,0,x,y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)x/(GLfloat)y,1.0f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
bool glengine::processEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))//get all events
{
switch (event.type)
{
// Quit event
case SDL_QUIT:
{
// Return false because we are quitting.
return false;
}
case SDL_KEYDOWN:
{
SDLKey sym = event.key.keysym.sym;
if(sym == SDLK_ESCAPE) //Quit if escape was pressed
{
return false;
}
m_Keys[sym] = 1;
break;
}
case SDL_KEYUP:
{
SDLKey sym = event.key.keysym.sym;
m_Keys[sym] = 0;
break;
}
case SDL_VIDEORESIZE:
{
//the window has been resized so we need to set up our viewport and projection according to the new size
resize(event.resize.w, event.resize.h);
break;
}
// Default case
default:
{
break;
}
}
}
return true;
}
bool glengine::init()
{
srand( time( NULL ) );
for(int i = 0; i < 500; i++)
p[i] = particle(0, 0, Vertex(0.0f, 0.0f, 0.0f), 0, 0, 0, 0);
if (!m_Window.createWindow(640, 480, 32, false, "Paricle Test GL"))
{
return false;
}
particlesize = 0.01;
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glEnable(GL_BLEND);
glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
return true;
}
void glengine::test2(int num)
{
glPushMatrix();
glTranslatef(p[num].v.x, p[num].v.y, p[num].v.z);
glBegin(GL_QUADS);
glColor4i(p[num].r, p[num].g, p[num].b, p[num].a); // Green for x axis
glVertex3f(-particlesize, -particlesize, particlesize);
glVertex3f( particlesize, -particlesize, particlesize);
glVertex3f( particlesize, particlesize, particlesize);
glVertex3f(-particlesize, particlesize, particlesize);
glEnd();
glPopMatrix();
}
void glengine::draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
gluLookAt(0, 5, 20, 0, 0, 0, 0, 0, 0);
for(int i = 0; i < 500; i++)
test2(i);
}
void glengine::update()
{
for(int i = 0; i < 500; i++)
{
if(p[i].a <= 0)
p[i] = particle(5 + rand() % 360, (rand() % 10) * 0.1, Vertex(0.0f, 0.0f, 0.0f), 0, 255, 255, 255);
else
p[i].a -= 1;
p[i].v.x += (sin(p[i].angle * (3.14159265/180)) * p[i].speed);
p[i].v.y -= (cos(p[i].angle * (3.14159265/180)) * p[i].speed);
}
}
void glengine::run()
{
while(processEvents())
{
update();
draw();
SDL_GL_SwapBuffers();
}
}
};
And finally window.cpp:
#include "window.h"
namespace ultragl
{
window::window(): w_width(0), w_height(0), w_bpp(0), w_fullscreen(false)
{
}
window::~window()
{
SDL_Quit();
}
bool window::createWindow(int width, int height, int bpp, bool fullscreen, const string& title)
{
if( SDL_Init( SDL_INIT_VIDEO ) != 0 )
return false;
w_height = height;
w_width = width;
w_title = title;
w_fullscreen = fullscreen;
w_bpp = bpp;
//Set lowest possiable values.
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Set title.
SDL_WM_SetCaption(title.c_str(), title.c_str());
// Flags tell SDL about the type of window we are creating.
int flags = SDL_OPENGL;
if(fullscreen == true)
flags |= SDL_FULLSCREEN;
// Create window
SDL_Surface * screen = SDL_SetVideoMode( width, height, bpp, flags );
if(screen == 0)
return false;
//SDL doesn't trigger off a ResizeEvent at startup, but as we need this for OpenGL, we do this ourself
SDL_Event resizeEvent;
resizeEvent.type = SDL_VIDEORESIZE;
resizeEvent.resize.w = width;
resizeEvent.resize.h = height;
SDL_PushEvent(&resizeEvent);
return true;
}
void window::setSize(int width, int height)
{
w_height = height;
w_width = width;
}
int window::getHeight()
{
return w_height;
}
int window::getWidth()
{
return w_width;
}
};
Anyway, I really need to finish this, but I've already tried everything I could think of. I tested the glengine file many different ways to where it looked like this at one point:
#include "glengine.h"
#include "SOIL/SOIL.h"
#include "SOIL/stb_image_aug.h"
#include "SOIL/image_helper.h"
#include "SOIL/image_DXT.h"
namespace ultragl{
glengine::glengine()
{
piover180 = 0.0174532925f;
}
glengine::~glengine()
{
}
void glengine::resize(int x, int y)
{
std::cout << "Resizing Window to " << x << "x" << y << std::endl;
if (y <= 0)
{
y = 1;
}
glViewport(0,0,x,y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)x/(GLfloat)y,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
bool glengine::processEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))//get all events
{
switch (event.type)
{
// Quit event
case SDL_QUIT:
{
// Return false because we are quitting.
return false;
}
case SDL_KEYDOWN:
{
SDLKey sym = event.key.keysym.sym;
if(sym == SDLK_ESCAPE) //Quit if escape was pressed
{
return false;
}
m_Keys[sym] = 1;
break;
}
case SDL_KEYUP:
{
SDLKey sym = event.key.keysym.sym;
m_Keys[sym] = 0;
break;
}
case SDL_VIDEORESIZE:
{
//the window has been resized so we need to set up our viewport and projection according to the new size
resize(event.resize.w, event.resize.h);
break;
}
// Default case
default:
{
break;
}
}
}
return true;
}
bool glengine::init()
{
srand( time( NULL ) );
for(int i = 0; i < 500; i++)
p[i] = particle(0, 0, Vertex(0.0f, 0.0f, 0.0f), 0, 0, 0, 0);
if (!m_Window.createWindow(640, 480, 32, false, "Paricle Test GL"))
{
return false;
}
particlesize = 10.01;
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glEnable(GL_BLEND);
glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
return true;
}
void glengine::test2(int num)
{
//glPushMatrix();
//glTranslatef(p[num].v.x, p[num].v.y, p[num].v.z);
glColor4i(255, 255, 255, 255);
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f(-particlesize, -particlesize, particlesize);
glVertex3f( particlesize, -particlesize, particlesize);
glVertex3f( particlesize, particlesize, particlesize);
glVertex3f(-particlesize, particlesize, particlesize);
glEnd();
// Back Face
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-particlesize, -particlesize, -particlesize);
glVertex3f(-particlesize, particlesize, -particlesize);
glVertex3f( particlesize, particlesize, -particlesize);
glVertex3f( particlesize, -particlesize, -particlesize);
glEnd();
// Top Face
glBegin(GL_QUADS);
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-particlesize, particlesize, -particlesize);
glVertex3f(-particlesize, particlesize, particlesize);
glVertex3f( particlesize, particlesize, particlesize);
glVertex3f( particlesize, particlesize, -particlesize);
glEnd();
// Bottom Face
glBegin(GL_QUADS);
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-particlesize, -particlesize, -particlesize);
glVertex3f( particlesize, -particlesize, -particlesize);
glVertex3f( particlesize, -particlesize, particlesize);
glVertex3f(-particlesize, -particlesize, particlesize);
glEnd();
// Right face
glBegin(GL_QUADS);
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( particlesize, -particlesize, -particlesize);
glVertex3f( particlesize, particlesize, -particlesize);
glVertex3f( particlesize, particlesize, particlesize);
glVertex3f( particlesize, -particlesize, particlesize);
glEnd();
// Left Face
glBegin(GL_QUADS);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-particlesize, -particlesize, -particlesize);
glVertex3f(-particlesize, -particlesize, particlesize);
glVertex3f(-particlesize, particlesize, particlesize);
glVertex3f(-particlesize, particlesize, -particlesize);
glEnd();
//glPopMatrix();
}
void glengine::draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
gluLookAt(0, 5, 20, 0, 0, 0, 0, 1, 0);
for(int i = 0; i < 500; i++)
test2(i);
}
void glengine::update()
{
for(int i = 0; i < 500; i++)
{
if(p[i].a <= 0)
p[i] = particle(5 + rand() % 360, (rand() % 10) * 0.1, Vertex(0.0f, 0.0f, -5.0f), 0, 255, 255, 255);
else
p[i].a -= 1;
p[i].v.x += (sin(p[i].angle * (3.14159265/180)) * p[i].speed);
p[i].v.y -= (cos(p[i].angle * (3.14159265/180)) * p[i].speed);
}
}
void glengine::run()
{
while(processEvents())
{
update();
draw();
SDL_GL_SwapBuffers();
}
}
};
It still didn't work. I'm really at my wits end on this one.
I haven't checked your code, but one thing I always do when debugging this kind of problems is to set the clear color to something colorful like (1, 0, 1) or so.
This will help you see if the problem is that your drawn object is completely black or if it's not drawn at all.
EDIT:
As someone mentioned in the comment: It also shows if you have a correct GL context if the clear operation clears to the right color or if it stays black.
Okay, I managed to fix it using a lot of your suggestions, and some other source code I had laying around. Turns out the problem was from 3 different lines.
particlesize = 0.01; should have been bigger: particlesize = 1.01;
glColor4i(255, 255, 255, 255) was turning the cube the same color as the clear color because I was using it wrong. I couldn't figure out how to use it right, so I'm using glColor4f(0.0f,1.0f,1.0f,0.5f) instead, and that works.
Last of all gluLookAt(0, 5, 20, 0, 0, 0, 0, 0, 0) needed to be gluLookAt(0, 5, 20, 0, 0, 0, 0, 1, 0)
Thank you all for your help, and your time.
You're not checking the return values of the SDL-GL-SetAttribute() calls.
And is 5/5/5/5 20-bpp color supported by your video card?
Check OpenGL for error states. Use glslDevil, glIntercept or gDebugger. Check the glGetError function. Can you test whether SDL actually acquired a device context?
Does the Window reflect changes in the glClearColor call? Don't use 0.5 as an alpha value in glClearColor.
Try these suggestions and report back with a minimal example as Simucal suggested.
Related
I want to move the object(6-point star with 2 triangles) with mouse clicking.
I wrote the following code, but there is no response.
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
float x_min = (-x + 500) / 500;
float x_max = (x - 500) / 500;
float y_min = (-y + 500) / 500;
float y_max = (y - 500) / 500;
gluOrtho2D(x_min, x_max, y_min, y_max);
}
glutPostRedisplay();
break;
In the case GLUT_LEFT_BUTTON, I put minimum/maxmimum x and y position but nothing works when I clicked left mouse button.
Here is the full codes:
#include <stdlib.h>
#include <GL/glut.h>
float v1[3] = { -35.0f, 22.5f, 0.0f };
float v2[3] = { -35.0f, -22.5f, 0.0f };
float v3[3] = { 0.0f, 42.5f, 0.0f };
float v4[3] = { 0.0f, -42.5f, 0.0f };
float v5[3] = { 35.0f, 22.5f, 0.0f };
float v6[3] = { 35.0f, -22.5f, 0.0f };
static GLfloat spin = 0.0;
float x = 400.0f, y = 442.5f;
float x_position;
float y_position;
float color1[3] = { 1.0f, 1.0f, 1.0f };
float color2[3] = { 1.0f, 1.0f, 1.0f };
int mode = 1;
int rotate = 1;
void init(void);
void triangle_1(void);
void triangle_2(void);
void display(void);
void spinDisplay_1(void);
void spinDisplay_2(void);
void reshape(int, int);
void changeColor(int);
void mouse(int, int, int, int);
////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(300, 300);
glutCreateWindow("6-Point Star");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
////////////////////////////////////////////////////////////////////
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void triangle_1(void) { //// triangle_1 and triangle_2 make 6-point star ////
glColor3fv(color1);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v5);
glEnd();
}
void triangle_2(void) {
glColor3fv(color2);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v6);
glEnd();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(x, y, 0.0f);
glRotatef(spin, 0.0, 0.0, 1.0);
triangle_1();
triangle_2();
glPopMatrix();
glutSwapBuffers();
}
void spinDisplay_1(void) {
spin = spin + 2.0;
if (spin > 360.0) {
spin = spin - 360.0;
}
glutPostRedisplay();
}
void spinDisplay_2(void) {
spin = spin - 2.0;
if (spin < 360.0) {
spin = spin + 360.0;
}
glutPostRedisplay();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void changeColor(int n) {
if (n == 1) {
color1[0] = 0.0f, color1[1] = 0.0f, color1[2] = 1.0f;
color2[0] = 0.0f, color2[1] = 1.0f, color2[2] = 0.0f;
}
else if (n == 2) {
color1[0] = 1.0f, color1[1] = 1.0f, color1[2] = 1.0f;
color2[0] = 1.0f, color2[1] = 1.0f, color2[2] = 1.0f;
}
}
void mouse(int button, int state, int x, int y) { /////// mouse event ////////
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
float x_min = (-x + 500) / 500;
float x_max = (x - 500) / 500;
float y_min = (-y + 500) / 500;
float y_max = (y - 500) / 500;
gluOrtho2D(x_min, x_max, y_min, y_max);
}
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN) {
if (mode == 1) {
changeColor(mode);
mode = 2;
}
else if (mode == 2) {
changeColor(mode);
mode = 1;
}
}
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
if (rotate == 1) {
glutIdleFunc(spinDisplay_1);
rotate = 2;
}
else if (rotate == 2) {
glutIdleFunc(spinDisplay_2);
rotate = 1;
}
break;
default:
break;
}
}
I want to move the object (6-point star with 2 triangles) with mouse clicking
If you want to left click and that position now being the center of the star, then you're overcomplicating things. You already have the star's position as global variables x and y. Thus in mouse() you just set those to the mouse position.
However remember to subtract the height of the window by y, since 0x0 is top left on the screen but bottom left in OpenGL.
if (state == GLUT_DOWN) {
::x = x;
::y = glutGet(GLUT_WINDOW_HEIGHT) - y;
}
Since mouse()'s x and y parameters shadows your global variables x and y, you have to prefix with ::. You could also rename mouse()'s parameters to say mx and my:
void mouse(int button, int state, int mx, int my) {
[...]
if (state == GLUT_DOWN) {
x = mx;
y = glutGet(GLUT_WINDOW_HEIGHT) - my;
}
Here's a GIF of clicking random places on the window:
My problem is textures wont work. I put source below.
main.cpp
#include <cstdio>
#include <cstring>
#include <cmath>
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glext.h>
PFNGLACTIVETEXTUREPROC glActiveTexture;
#include "config.h"
#include "camera.cpp"
#include "keyboardControl.cpp"
void *__gxx_personality_v0;
#define win_style WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void EnableOpenGL();
void DisableOpenGL();
void renderframe();
void renderframe2();
void SetDCPixelFormat(HDC hDC);
void Reset();
void InitGL();
void SetRenderMode(int mode);
void InitKeys();
void CameraMove(void*);
void CameraRot(void*);
void sMode(void* data);
void LoadTextures();
HWND hWnd;
HDC hDC;
HGLRC hRC;
config CFG;
bool getFPS = 0;
int lx, ly;
int sx, sy;
bool m = false;
static int keys1[] = { 6, 'W', 'S', 'D', 'A', VK_SPACE, VK_LSHIFT, (int)&CameraMove };
static int keys2[] = { 1, 'Q', (int)&CameraRot };
static int keys3[] = { 3, '1', '2', '3', (int)&sMode };
GLuint texture;
float pixels[] = {
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f
};
camera cam;
keyboardControl keys;
void LoadTextures() {
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
void sMode(void* data) {
for(int i = 0; i < 3; i++)
{
if( ((int*)data)[i] & 1 )
{
SetRenderMode(i);
return;
}
}
}
void CameraMove(void* data) {
int *bPtr = (int*)data;
double add[3] = { 0, 0, 0 };
for(int x = 0; x < 3; x++)
{
if(bPtr[x*2]) add[x] += 0.1f;
if(bPtr[x*2 + 1]) add[x] -= 0.1f;
}
cam.move(add[0], add[1], add[2]);
}
void CameraRot(void* data) {
if( *((int*)data) & 1 )
{
SetCursorPos(lx, ly);
m = !m;
}
}
void renderframe2() {
static float rot = 0.0f;
glLoadIdentity();
gluLookAt(cam.position[0], cam.position[1], cam.position[2], cam.lookAtPos[0], cam.lookAtPos[1], cam.lookAtPos[2], 0.0f, 0.0f, 1.0f);
glClearColor( 0.4f, 0.4f, 0.6f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(rot/10.0f, 1, 1, 0);
glBegin(GL_LINES);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 0.0f, 2.0f, 0.0f);
glVertex3f( 0.0f, -2.0f, 0.0f);
glVertex3f( 2.0f, 0.0f, 0.0f);
glVertex3f( -2.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 2.0f);
glVertex3f( 0.0f, 0.0f, -2.0f);
glEnd();
glActiveTexture(GL_TEXTURE0);
glBindTexture( GL_TEXTURE_2D, texture );
glBegin(GL_QUADS);
glColor3f(0.0f,0.0f,1.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2d(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2d(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2d(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2d(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2d(0.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2d(1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd();
glFlush();
SwapBuffers( hDC );
rot += 1.0f;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) {
CFG.resolution[0] = 800;
CFG.resolution[1] = 600;
WNDCLASS wc;
MSG msg;
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = "Window1";
RegisterClass( &wc );
int x = 50, y = 50;
RECT wr = { x, y, x + CFG.resolution[0], y + CFG.resolution[1] };
hWnd = CreateWindow(
"Window1", "...",
win_style,
wr.left, wr.top, wr.right-wr.left, wr.bottom-wr.top,
NULL, NULL, hInstance, NULL );
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
double PCFreq = double(li.QuadPart);
double fc = PCFreq/64;
cam.setup(0, -10, 0, 0, 0);
EnableOpenGL();
InitKeys();
glActiveTexture = (PFNGLACTIVETEXTUREPROC) wglGetProcAddress ("glActiveTexture");
if(glActiveTexture == NULL)
{
printf("Critical Error 1\n");
return 1;
}
bool bEND = false;
__int64 CounterStart = 0;
__int64 CounterCur = 0;
__int64 CounterMark = 0;
while(!bEND)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
bEND = true;
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
QueryPerformanceCounter((LARGE_INTEGER*)&CounterStart);
renderframe2();
keys.a();
QueryPerformanceCounter((LARGE_INTEGER*)&CounterCur);
CounterMark = CounterStart + fc;
while(CounterCur < CounterMark)
{
QueryPerformanceCounter((LARGE_INTEGER*)&CounterCur);
Sleep(1);
}
if(getFPS)
{
getFPS = 0;
printf("%0.2lf fps\n", (double)(1/((double)(CounterCur-CounterStart)/PCFreq)));
}
}
}
DisableOpenGL();
DestroyWindow(hWnd);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message)
{
case WM_MOVE:
{
int xPos = ((__int16*)&lParam)[0];
int yPos = ((__int16*)&lParam)[1];
RECT wr = { xPos, yPos, xPos + CFG.resolution[0], yPos + CFG.resolution[1] };
RECT wr2;
memcpy(&wr2, &wr, sizeof(RECT));
AdjustWindowRect(&wr2, win_style, false);
lx = (CFG.resolution[0] >> 1) + wr2.left;
ly = (CFG.resolution[1] >> 1) + wr2.top;
sx = (CFG.resolution[0] >> 1) - wr2.right + wr.right;
sy = (CFG.resolution[1] >> 1) - wr.top + wr2.top;
} break;
case WM_MOUSEMOVE:
{
if(!m) break;
int xPos = ((__int16*)&lParam)[0];
int yPos = ((__int16*)&lParam)[1];
if(xPos == sx && yPos == sy)
{
break;
}
if(xPos != sx || yPos != sy)
{
int ia = (xPos - sx);
int ib = (sy - yPos);
double a = (ia)?(double)ia / 100:0;
double b = (ib)?(double)ib / 100:0;
cam.moveC(a, b);
}
SetCursorPos(lx, ly);
} break;
case WM_CREATE:
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_DESTROY:
return 0;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
{
PostQuitMessage(0);
return 0;
}
return 0;
}
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
}
void Reset() {
RECT rc;
GetClientRect(hWnd, &rc);
int h = rc.bottom-rc.top;
int w = rc.right-rc.left;
if(!h) h=1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (float)w/(float)h, 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
};
void EnableOpenGL() {
hDC = GetDC(hWnd);
SetDCPixelFormat( hDC );
hRC = wglCreateContext( hDC );
wglMakeCurrent( hDC, hRC );
Reset();
InitGL();
LoadTextures();
SetRenderMode(2);
}
void DisableOpenGL() {
glDeleteTextures(1, &texture);
wglMakeCurrent( NULL, NULL );
wglDeleteContext( hRC );
ReleaseDC(hWnd, hDC);
}
void SetDCPixelFormat( HDC hDC ) {
INT nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER | PFD_TYPE_RGBA,
8,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
void InitGL() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void InitKeys() {
keys.Add(keys1);
keys.Add(keys2);
keys.Add(keys3);
}
void SetRenderMode(int mode) {
switch (mode)
{
case 0: glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
case 1:
{
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}; break;
case 2:
{
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}; break;
};
};
camera.cpp
#pragma once
#include <cstring>
#include <cmath>
#include <cstdio>
class camera
{
public:
double position[3];
double lookAtPos[3];
private:
int r;
double speed;
double vRad, hRad;
public:
camera();
//~camera();
void setup(double x, double y, double z, double v, double h);
void moveC(double v, double h);
void move(double a, double b, double c);
void debug();
void reset();
};
camera::camera() {
memset(position, 0, sizeof(double)*3);
memset(lookAtPos, 0, sizeof(double)*3);
r = 10;
speed = 0.5f;
vRad = 0;
hRad = 0;
}
void camera::setup(double x, double y, double z, double v, double h) {
position[0] = x;
position[1] = y;
position[2] = z;
vRad = v;
hRad = h;
moveC(0, 0);
}
void camera::move(double a, double b, double c) {
double sv = sin(vRad), cv = cos(vRad);
double sh = sin(hRad), ch = cos(hRad);
if(a)
{
position[0] += ch * sv * a;
position[1] += ch * cv * a;
position[2] += sh * a;
}
if(b)
{
double svb = sin(vRad + 1.57), cvb = cos(vRad + 1.57);
position[0] += svb * b;
position[1] += cvb * b;
}
if(c)
{
position[2] += c;
}
reset();
}
void camera::moveC(double v, double h) {
if(v)
{
vRad += v;
if(vRad > 6.28) vRad -= 6.28;
if(vRad < 0) vRad += 6.28;
}
if(h)
{
hRad += h;
if(hRad > 1.57) hRad = 1.57;
if(hRad < -1.57) hRad = -1.57;
}
reset();
}
void camera::reset() {
double sv = sin(vRad), cv = cos(vRad), sh = sin(hRad), ch = cos(hRad);
lookAtPos[0] = ch * sv * r + position[0];
lookAtPos[1] = ch * cv * r + position[1];
lookAtPos[2] = sh * r + position[2];
}
keyboardControl.cpp
#pragma once
#include <cstdlib>
#include <windows.h>
class keyboardControl {
private:
int count;
int **DATA;
public:
keyboardControl();
~keyboardControl();
void Add(int*);
void a();
};
keyboardControl::keyboardControl() {
DATA = (int**) malloc(256 * 4);
count = 0;
}
keyboardControl::~keyboardControl() {
free(DATA);
}
void keyboardControl::a() {
for(int i = 0; i < count; i++)
{
int t[DATA[i][0]];
bool work = false;
for(int x = 0; x < DATA[i][0]; x++)
{
t[x] = GetAsyncKeyState(DATA[i][x + 1]);
if(t[x]) work = true;
}
if(work)
{
((void (*)(void*))DATA[i][DATA[i][0]+1])(t);
}
}
}
void keyboardControl::Add(int* data) {
DATA[count++] = data;
}
I'm using MinGW and compile.bat
#echo off
erase run.exe
set dir1="%cd%"
cd ../../../MinGW/bin
gcc %dir1%/main.cpp -lwsock32 -lopengl32 -lGdi32 -lglu32 -o %dir1%/run.exe
cd %dir1%
set dir1=
echo =-=
run
#echo on
Enable texturing via glEnable(GL_TEXTURE_2D) before attempting to render textured geometry:
glEnable(GL_TEXTURE_2D); // important!
glActiveTexture(GL_TEXTURE0);
glBindTexture( GL_TEXTURE_2D, texture );
glBegin(GL_QUADS);
glColor3f(0.0f,0.0f,1.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f,-1.0f);
...
glBindTexture() alone is necessary but not sufficient.
When I try to compile Clam-NetworkEditor-1.4.0 I get these errors:
In file included from src/widgets/generated/moc_QFirstPerson.cxx:10:0:
src/widgets/generated/../QFirstPerson.hxx:348:15: error: function definition does not declare parameters
src/widgets/generated/../QFirstPerson.hxx: In member function ‘virtual void QFirstPerson::paintScene()’:
src/widgets/generated/../QFirstPerson.hxx:202:21: error: ‘((QFirstPerson*)this)->QFirstPerson::sphere’ cannot be used as a function
src/widgets/generated/../QFirstPerson.hxx: In member function ‘void QFirstPerson::drawLight(float*, float*, const char*, const QColor&)’:
src/widgets/generated/../QFirstPerson.hxx:231:20: error: ‘((QFirstPerson*)this)->QFirstPerson::sphere’ cannot be used as a function
scons: * [src/widgets/generated/generated/moc_QFirstPerson.os] Error 1
scons: building terminated because of errors.
Here is the code from QFirstPerson.hxx
#ifndef QFirstPerson_hxx
#define QFirstPerson_hxx
#include <QtOpenGL/QGLWidget>
#undef GetClassName
#include <QtGui/QKeyEvent>
#include <iostream>
#include <cmath>
#include <GL/glu.h>
static float * vColor(const QColor & color)
{
static float vcolor[4];
vcolor[0]=color.redF();
vcolor[1]=color.greenF();
vcolor[2]=color.blueF();
vcolor[3]=color.alphaF();
return vcolor;
}
class Light
{
unsigned _index;
QColor _ambient;
QColor _specular;
QColor _diffuse;
float _position[4];
float _direction[4];
int _cutoff;
float _exponent;
bool _enabled;
public:
Light(unsigned index,
float * position, float * direction,
int cutoff,
float exponent,
const QColor & diffuse=Qt::white,
const QColor & specular=Qt::white,
const QColor & ambient=Qt::black)
: _index(index)
, _ambient(ambient)
, _specular(specular)
, _diffuse(diffuse)
, _cutoff(cutoff)
, _exponent(exponent)
, _enabled(true)
{
for (unsigned i=0; i<4; i++) _position[i]=position[i];
for (unsigned i=0; i<4; i++) _direction[i]=direction[i];
}
void place()
{
glLightfv(GL_LIGHT0+_index, GL_AMBIENT, vColor(_ambient));
glLightfv(GL_LIGHT0+_index, GL_DIFFUSE, vColor(_diffuse));
glLightfv(GL_LIGHT0+_index, GL_SPECULAR, vColor(_specular));
glLightfv(GL_LIGHT0+_index, GL_SPOT_DIRECTION, _direction);
glLightfv(GL_LIGHT0+_index, GL_POSITION, _position);
glLighti (GL_LIGHT0+_index, GL_SPOT_CUTOFF, _cutoff);
glLightf (GL_LIGHT0+_index, GL_SPOT_EXPONENT, _exponent);
glLightf (GL_LIGHT0+_index, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf (GL_LIGHT0+_index, GL_LINEAR_ATTENUATION, 0.2f);
glLightf (GL_LIGHT0+_index, GL_QUADRATIC_ATTENUATION, 0.0f);
(*(_enabled? &glEnable:&glDisable) )(GL_LIGHT0+_index);
}
};
class QFirstPerson : public QGLWidget
{
double _viewX;
double _viewY;
double _viewRotation;
double _viewElevation;
double _sourceX;
double _sourceY;
double _sphere;
GLUquadric * sphere;
Q_OBJECT
public:
QFirstPerson(QWidget * parent=0)
: QGLWidget(parent)
, _viewX(0)
, _viewY(-1)
, _viewRotation(0)
, _viewElevation(0)
, _sourceX(0)
, _sourceY(0)
, _sphere(0)
{
}
void initializeGL()
{
std::cout << "init" << std::endl;
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
bool blend = true;
if (blend) glEnable(GL_BLEND);
bool ligth = true;
if (ligth) glEnable(GL_LIGHTING);
}
void resizeGL(int width, int height)
{
std::cout << "resize" << std::endl;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0f, (GLfloat)width / (GLfloat)height, 0.01f, 1250.0f);
glMatrixMode(GL_MODELVIEW);
}
void paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glRotatef( -_viewElevation, 1.0f, 0.0f, 0.0f);
glRotatef(180-_viewRotation, 0.0f, 1.0f, 0.0f);
glTranslatef(-_viewX, 0, -_viewY); // y is at z
placeLights();
paintScene();
glPopMatrix();
glDepthFunc(GL_NONE);
paintDecoration();
}
virtual void placeLights()
{
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vColor("#505060"));
static GLfloat position0[] = { 0.0f, 1.5f, 0.0f, 1.0f };
static GLfloat direction0[] = { 0.0f, -0.5f, 0.0f, 1.0f };
Light light0(0, position0, direction0, 90, 2, "#555", "#555", "#555");
light0.place();
static GLfloat position1[] = { -5.0f, 1.0f, 5.0f, 1.0f };
static GLfloat direction1[] = { .5f, -.5f, -.5f, 1.0f };
Light light1(1, position1, direction1, 90, 2, "#700", "#770", "#700");
light1.place();
static GLfloat position2[] = { 5.0f, 1.0f, -5.0f, 1.0f };
static GLfloat direction2[] = { -1.0f/5, -1.0f/5, 1.0f, 1.0f };
Light light2(2, position2, direction2, 90, 2, "#077", "#007", "#077");
light2.place();
drawLight(position0, direction0, "Light0", "#777");
drawLight(position1, direction1, "Light1", "#a00");
drawLight(position2, direction2, "Light2", "#0aa");
}
void roomWall(float bottom, float top)
{
glBegin(GL_QUAD_STRIP);
for (unsigned i=0; i<20; i++)
{
glVertex3f(10.f-i,top,10.f);
glVertex3f(10.f-i,bottom,10.f);
}
for (unsigned i=0; i<20; i++)
{
glVertex3f(-10.f,top,10.f-i);
glVertex3f(-10.f,bottom,10.f-i);
}
for (unsigned i=0; i<20; i++)
{
glVertex3f(-10.f+i,top,-10.f);
glVertex3f(-10.f+i,bottom,-10.f);
}
for (unsigned i=0; i<20; i++)
{
glVertex3f(10.f,top,-10.f+i);
glVertex3f(10.f,bottom,-10.f+i);
}
glVertex3f(10.f,top,10.f);
glVertex3f(10.f,bottom,10.f);
glEnd();
}
virtual void paintScene()
{
glMaterialfv(GL_FRONT, GL_DIFFUSE, vColor("white"));
glMaterialfv(GL_FRONT, GL_AMBIENT, vColor("white"));
glMaterialfv(GL_FRONT, GL_SPECULAR, vColor("#333"));
glMaterialf(GL_FRONT, GL_SHININESS, 0);
glColor4fv(vColor(Qt::white));
roomWall(-1.75, -1);
roomWall(-1, 0);
roomWall(0, 1);
roomWall(1, 1.75);
qglColor(Qt::yellow);
drawPlane(-1.75);
glColor4fv(vColor("#aaa"));
drawPlane(+1.75);
qglColor(QColor("#ffa"));
renderText(0., 1, 10.-1, "North (+Y)");
renderText(0., 1, -10.+1, "South (-Y)");
renderText(10.-1, 1, 0., "East (+X)");
renderText(-10.+1, 1, 0., "West (-X)");
glPushMatrix();
glColor4fv(vColor("#b22"));
glTranslatef(_sourceX,0,_sourceY);
renderText(0., 1, 0., "Source");
glBegin(GL_LINES);
glVertex3f(0.,1.,0.);
glVertex3f(0.,0.,0.);
glEnd();
gluSphere(sphere(), 0.5f, 40, 20);
glPopMatrix();
}
void drawPlane(float height)
{
for (unsigned j=0; j<20; j++)
{
glBegin(GL_QUAD_STRIP);
for (unsigned i=0; i<=20; i++)
{
glVertex3f(10.f-j,height,10.f-i);
glVertex3f(10.f-(j+1),height,10.f-i);
}
glEnd();
}
}
void drawLight(float * position, float * direction, const char * label, const QColor & color)
{
glPushMatrix();
glColor4fv(vColor(color));
glTranslatef(position[0],position[1],position[2]);
renderText(0., 2, 0., label);
glMaterialfv(GL_FRONT, GL_EMISSION, vColor(color));
glBegin(GL_LINES);
glVertex3f(0.,0.,0.);
glVertex3fv(direction);
glVertex3f(0.,2.,0.);
glVertex3f(0.,0.,0.);
glEnd();
gluSphere(sphere(), 0.2f, 40, 20);
glMaterialfv(GL_FRONT, GL_EMISSION, vColor("black"));
glPopMatrix();
}
virtual void paintDecoration()
{
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
QString emiterString = tr("Emitter: %1, %2")
.arg(QString::number(_sourceX,'d',2))
.arg(QString::number(_sourceY,'d',2))
;
QString receiverString = tr("Receiver: %1, %2 angle %3")
.arg(QString::number(_viewX,'d',2))
.arg(QString::number(_viewY,'d',2))
.arg(QString::number(_viewRotation,'d',0))
;
glColor4fv(vColor("black"));
renderText(10,20, receiverString);
renderText(10,40, emiterString);
glBegin(GL_LINES);
glVertex3f(0,.06,-.1);
glVertex3f(0,.02,-.1);
glVertex3f(0,-.06,-.1);
glVertex3f(0,-.02,-.1);
glVertex3f(.06,0,-.1);
glVertex3f(.02,0,-.1);
glVertex3f(-.06,0,-.1);
glVertex3f(-.02,0,-.1);
glEnd();
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void keyPressEvent( QKeyEvent * event)
{
std::cout << "key" << std::endl;
float cosOrientation = std::cos(_viewRotation*M_PI/180.f);
float sinOrientation = std::sin(_viewRotation*M_PI/180.f);
bool strafe = event->modifiers() & Qt::AltModifier;
bool run = event->modifiers() & Qt::ShiftModifier;
float step = run ? .4f : .1f;
switch (event->key())
{
case Qt::Key_Left:
if (strafe)
{
_viewX += cosOrientation * step;
_viewY -= sinOrientation * step;
emitPositionChange();
}
else
{
_viewRotation+=10;
emit orientationChanged(_viewRotation);
}
break;
case Qt::Key_Right:
if (strafe)
{
_viewX -= cosOrientation * step;
_viewY += sinOrientation * step;
emitPositionChange();
emit posChanged(QPointF(_viewX, _viewY));
}
else
{
_viewRotation-=10;
emit orientationChanged(_viewRotation);
}
break;
case Qt::Key_PageUp:
_viewElevation+=10;
break;
case Qt::Key_PageDown:
_viewElevation-=10;
break;
case Qt::Key_Up:
_viewX += sinOrientation * step;
_viewY += cosOrientation * step;
emitPositionChange();
break;
case Qt::Key_Down:
_viewX -= sinOrientation * step;
_viewY -= cosOrientation * step;
emitPositionChange();
break;
case Qt::Key_A:
_sourceX+=step;
break;
case Qt::Key_D:
_sourceX-=step;
break;
case Qt::Key_W:
_sourceY+=step;
break;
case Qt::Key_S:
_sourceY-=step;
break;
case Qt::Key_Escape:
close();
break;
default:
event->ignore();
return;
return;
}
while (_viewRotation>=360.f) _viewRotation-=360.f;
while (_viewRotation<0.f) _viewRotation+=360.f;
event->accept();
updateGL();
}
signals:
double posChanged(QPointF point);
double xPosChanged(double x);
double yPosChanged(double y);
double orientationChanged(double degrees);
private:
GLUquadric * sphere
{
if (!_sphere) _sphere = gluNewQuadric();
return _sphere;
}
void emitPositionChange()
{
emit posChanged(QPointF(_viewX, _viewY));
emit xPosChanged(_viewX);
emit yPosChanged(_viewY);
}
};
#endif// QFirstPerson_hxx
You have this declaration
class QFirstPerson : public QGLWidget
{
double _viewX;
double _viewY;
double _viewRotation;
double _viewElevation;
double _sourceX;
double _sourceY;
double _sphere;
GLUquadric * sphere; // <--
But later this code
gluSphere(sphere(), 0.5f, 40, 20);
Which assumes that sphere is callable. The compiler disagrees.
I would like to get color from the pixel in my game and save this color in variable. How to do it in opengl?
glReadPixels():
#include <GL/glut.h>
#include <iostream>
using namespace std;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10, 10, -10, 10, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glScalef(5,5,5);
glBegin(GL_TRIANGLES);
glColor3ub(255,0,0);
glVertex2f(-1,-1);
glColor3ub(0,255,0);
glVertex2f(1,-1);
glColor3ub(0,0,255);
glVertex2f(1,1);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void motion(int x, int y)
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
unsigned char pixel[4];
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
cout << "R: " << (int)pixel[0] << endl;
cout << "G: " << (int)pixel[1] << endl;
cout << "B: " << (int)pixel[2] << endl;
cout << endl;
}
int main(int argc, char **argv)
{
glutInitWindowSize(640,480);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("glReadPixels()");
glutDisplayFunc(display);
glutPassiveMotionFunc(motion);
glutMainLoop();
return 0;
}
struct{ GLubyte red, green, blue; } pixel;
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
#include <math.h>
#include <gl/glut.h>
struct Point {
GLint x;
GLint y;
};
struct Color {
GLfloat r;
GLfloat g;
GLfloat b;
};
void init() {
glClearColor(1.0, 1.0, 1.0, 0.0);
glColor3f(0.0, 0.0, 0.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 640, 0, 480);
}
//this function is used for getting color of pixel
Color getPixelColor(GLint x, GLint y) {
Color color;
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, &color);
return color;
}
void setPixelColor(GLint x, GLint y, Color color) {
glColor3f(color.r, color.g, color.b);
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
glFlush();
}
void floodFill(GLint x, GLint y, Color oldColor, Color newColor) {
Color color;
color = getPixelColor(x, y);
if(color.r == oldColor.r && color.g == oldColor.g && color.b == oldColor.b)
{
setPixelColor(x, y, newColor);
floodFill(x+1, y, oldColor, newColor);
floodFill(x, y+1, oldColor, newColor);
floodFill(x-1, y, oldColor, newColor);
floodFill(x, y-1, oldColor, newColor);
}
return;
}
void onMouseClick(int button, int state, int x, int y)
{
Color newColor = {1.0f, 0.0f, 0.0f};
Color oldColor = {1.0f, 1.0f, 1.0f};
floodFill(320, 240, oldColor, newColor);
}
void draw_circle(Point pC, GLfloat radius) {
GLfloat step = 1/radius;
GLfloat x, y;
for(GLfloat theta = 0; theta <= 360; theta += step) {
x = pC.x + (radius * cos(theta));
y = pC.y + (radius * sin(theta));
glVertex2i(x, y);
}
}
void display(void) {
Point pt = {320, 240};
GLfloat radius = 50;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
draw_circle(pt, radius);
glEnd();
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(200, 200);
glutCreateWindow("Open GL");
init();
glutDisplayFunc(display);
glutMouseFunc(onMouseClick);
glutMainLoop();
return 0;
}
This is basic question about lighting and texturing in OpenGL. I tried to apply a texture in pure OpenGL app, unfortunately, the color is different from the texture. Here is the texture:
and here is what i got after applying the texture:
I used Videotutorialrocks BMP Loader. This coloring problem does not exist if i use their BMP file (i.e. the color is the same as the texture file).
Here's the code:
#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include "imageloader.h"
using std::stringstream;
using std::cout;
using std::endl;
using std::ends;
using namespace std;
float lpos[4] = {1.0,0.0,0.0,0.0};
void *font = GLUT_BITMAP_8_BY_13;
float color[4] = {0.0, 1.0, 0.0, 1.0};
GLuint _textureId; //The id of the texture
float a = 0;
float eye_x = 5.0;
float eye_y = 5.0;
float eye_z = 5.0;
//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId); //Make room for our texture
glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D, //Always GL_TEXTURE_2D
0, //0 for now
GL_RGB, //Format OpenGL uses for image
image->width, image->height, //Width and height
0, //The border of the image
GL_RGB, //GL_RGB, because pixels are stored in RGB format
GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
//as unsigned numbers
image->pixels); //The actual pixel data
return textureId; //Returns the id of the texture
}
// write 2d text using GLUT
// The projection matrix must be set to orthogonal before call this function.
void drawString(const char *str, int x, int y, float color[4], void *font)
{
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT); // lighting and color mask
glDisable(GL_LIGHTING); // need to disable lighting for proper text color
glColor4fv(color); // set text color
glRasterPos2i(x, y); // place text position
// loop all characters in the string
while(*str)
{
glutBitmapCharacter(font, *str);
++str;
}
glEnable(GL_LIGHTING);
glPopAttrib();
}
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short. (you cant make a window of zero width).
if(h == 0)
h = 1;
float ratio = 1.0* w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45,ratio,1,100);
glMatrixMode(GL_MODELVIEW);
}
void initRendering(){
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
Image* image = loadBMP("vtr_6.bmp");
_textureId = loadTexture(image);
delete image;
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Add ambient light
//GLfloat ambientColor[] = {0.4f, 0.2f, 0.2f, 1.0f}; //Color(0.2, 0.2, 0.2)
GLfloat ambientColor[] = {1.0f, 1.0f, 1.0f, 1.0f}; //Color(0.2, 0.2, 0.2)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
//Add positioned light
//GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color (0.5, 0.5, 0.5)
GLfloat lightColor0[] = {1.0f, 1.0f, 1.0f, 1.0f}; //Color (0.5, 0.5, 0.5)
GLfloat lightPos0[] = {4.0f, 0.0f, 8.0f, 1.0f}; //Positioned at (4, 0, 8)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
//Add directed light
//GLfloat lightColor1[] = {0.7f, 0.2f, 0.1f, 1.0f}; //Color (0.5, 0.2, 0.2)
GLfloat lightColor1[] = {1.0f, 1.0f, 1.0f, 1.0f};
//Coming from the direction (-1, 0.5, 0.5)
GLfloat lightPos1[] = {1.0f, 0.5f, 0.5f, 0.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);
//Bottom
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gluLookAt(eye_x,eye_y,eye_z,
0.0,0.0,0.0,
0.0f,1.0f,0.0f);
stringstream ss;
ss << std::fixed << std::setprecision(2);
ss << "Eye Position : x,y,z = (" << eye_x << ", " << eye_y << ", " << eye_z << ")" << ends;
drawString(ss.str().c_str(), -6, 1, color, font);
ss.str("");
glRotatef(a,0,1,0);
glutSolidTeapot(2);
glDisable(GL_TEXTURE_2D);
a+=0.1;
glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
switch ( key )
{
case 27:
exit(0);
break;
case '1':
eye_x += 0.1;
break;
case '2':
eye_x -= 0.1;
break;
case '3' :
eye_y += 0.1;
break;
case '4' :
eye_y -= 0.1;
break;
case '5':
eye_z += 0.1;;
break;
case '6':
eye_z -= 0.1;
break;
case '0':
eye_x = 5.0;
eye_y = 5.0;
eye_z = 5.0;
break;
}
}
#define printOpenGLError() printOglError(__FILE__, __LINE__)
int printOglError(char *file, int line)
{
GLenum glErr;
int retCode = 0;
glErr = glGetError();
while (glErr != GL_NO_ERROR)
{
printf("glError in file %s # line %d: %s\n", file, line, gluErrorString(glErr));
retCode = 1;
glErr = glGetError();
}
return retCode;
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,600);
glutCreateWindow("OpenGL Teapot w/ lighting");
initRendering();
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);
glutIdleFunc(renderScene);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0,0.0,0.0,0.0);
glutMainLoop();
return 0;
}
Here is the code for Image Loader:
#include <assert.h>
#include <fstream>
#include "imageloader.h"
using namespace std;
Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {
}
Image::~Image() {
delete[] pixels;
}
namespace {
//Converts a four-character array to an integer, using little-endian form
int toInt(const char* bytes) {
return (int)(((unsigned char)bytes[3] << 24) |
((unsigned char)bytes[2] << 16) |
((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}
//Converts a two-character array to a short, using little-endian form
short toShort(const char* bytes) {
return (short)(((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}
//Reads the next four bytes as an integer, using little-endian form
int readInt(ifstream &input) {
char buffer[4];
input.read(buffer, 4);
return toInt(buffer);
}
//Reads the next two bytes as a short, using little-endian form
short readShort(ifstream &input) {
char buffer[2];
input.read(buffer, 2);
return toShort(buffer);
}
//Just like auto_ptr, but for arrays
template<class T>
class auto_array {
private:
T* array;
mutable bool isReleased;
public:
explicit auto_array(T* array_ = NULL) :
array(array_), isReleased(false) {
}
auto_array(const auto_array<T> &aarray) {
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}
~auto_array() {
if (!isReleased && array != NULL) {
delete[] array;
}
}
T* get() const {
return array;
}
T &operator*() const {
return *array;
}
void operator=(const auto_array<T> &aarray) {
if (!isReleased && array != NULL) {
delete[] array;
}
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}
T* operator->() const {
return array;
}
T* release() {
isReleased = true;
return array;
}
void reset(T* array_ = NULL) {
if (!isReleased && array != NULL) {
delete[] array;
}
array = array_;
}
T* operator+(int i) {
return array + i;
}
T &operator[](int i) {
return array[i];
}
};
}
Image* loadBMP(const char* filename) {
ifstream input;
input.open(filename, ifstream::binary);
assert(!input.fail() || !"Could not find file");
char buffer[2];
input.read(buffer, 2);
assert(buffer[0] == 'B' && buffer[1] == 'M' || !"Not a bitmap file");
input.ignore(8);
int dataOffset = readInt(input);
//Read the header
int headerSize = readInt(input);
int width;
int height;
switch(headerSize) {
case 40:
//V3
width = readInt(input);
height = readInt(input);
input.ignore(2);
assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
assert(readShort(input) == 0 || !"Image is compressed");
break;
case 12:
//OS/2 V1
width = readShort(input);
height = readShort(input);
input.ignore(2);
assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
break;
case 64:
//OS/2 V2
assert(!"Can't load OS/2 V2 bitmaps");
break;
case 108:
//Windows V4
assert(!"Can't load Windows V4 bitmaps");
break;
case 124:
//Windows V5
assert(!"Can't load Windows V5 bitmaps");
break;
default:
assert(!"Unknown bitmap format");
}
//Read the data
int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
int size = bytesPerRow * height;
auto_array<char> pixels(new char[size]);
input.seekg(dataOffset, ios_base::beg);
input.read(pixels.get(), size);
//Get the data into the right format
auto_array<char> pixels2(new char[width * height * 3]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
for(int c = 0; c < 3; c++) {
pixels2[3 * (width * y + x) + c] =
pixels[bytesPerRow * y + 3 * x + (2 - c)];
}
}
}
input.close();
return new Image(pixels2.release(), width, height);
}
And this is the header file:
#ifndef IMAGE_LOADER_H_INCLUDED
#define IMAGE_LOADER_H_INCLUDED
//Represents an image
class Image {
public:
Image(char* ps, int w, int h);
~Image();
/* An array of the form (R1, G1, B1, R2, G2, B2, ...) indicating the
* color of each pixel in image. Color components range from 0 to 255.
* The array starts the bottom-left pixel, then moves right to the end
* of the row, then moves up to the next column, and so on. This is the
* format in which OpenGL likes images.
*/
char* pixels;
int width;
int height;
};
//Reads a bitmap image from file.
Image* loadBMP(const char* filename);
#endif
I have tried to replace the file format for glTexImage2D with GL_BGR_EXT, but no result. Is there any way to correct the texture?
Perhaps your image has an alpha channel, which requires GL_RGBA, not GL_RGB.
Try opening your texture with some sort of image editing software (gimp, photoshop, etc), and save it as a BMP with 24 color bits (I think: 8 for each r/b/g), and just make sure all of the BMP settings are correct. It definitely looks like it's a problem with the format of your texture. There are multiple BMP formats.
See what happens when you disable lighting.
Also this page suggests you should use:
glFrontFace(GL_CW);
glutSolidTeapot(size);
glFrontFace(GL_CCW);
http://pyopengl.sourceforge.net/documentation/manual/glutSolidTeapot.3GLUT.html
In the loadTexture function, in glTexImage2D change the second(format) GL_RGB to GL_BGR.
If you try loading PNG image file, add the alpha, too.