I'm rendering fire in opengl using freeglut, I created a particlesystem with emmiter and forcefield and they are working well.
I'm going to put the fire in an old train in a university project, I used textured spheres to simulate it.
The code is going to be long , I'm very sorry but all is relevant, here it is :
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SOIL/SOIL.h>
#include <glm/glm.hpp>
#include <deque> using namespace std;
typedef glm::vec3 Vector3;
struct Force { private :
float strength;
Vector3 orentation; public :
Force(const Vector3 &v,const float &s)
:strength(s),orentation(v)
{
}
Force(const Force &f)
:strength(f.strength),orentation(f.orentation)
{
}
float getStrength() const
{
return strength;
}
Vector3 getOrentation() const
{
return orentation;
} };
class Particle { public :
Vector3 velocity,position;
const float mass;
float *deltatime;
float lifebegin;
Particle(const Vector3 &pos,const float &m,float *dt,const float &life)
:velocity(Vector3()),position(pos),mass(m),deltatime(dt),lifebegin(life)
{
}
void applyforce(const Force &f)
{
Vector3 force=f.getOrentation()*f.getStrength();
Vector3 accleration=force/mass;
velocity+=accleration*(*deltatime);
proceedintime();
}
void proceedintime()
{
position+=velocity*(*deltatime);
}
virtual void draw()const=0;
virtual bool collide(Particle *p)const=0;
virtual ~Particle()
{
} }; class TexturedParticle : public Particle { protected :
unsigned int textureid; public:
TexturedParticle(const Vector3 &pos,const float &m,float *dt,const float &life,const unsigned int &tex)
:Particle(pos,m,dt,life),textureid(tex)
{
}
virtual ~TexturedParticle()
{
}
}; class Emmiter; class ForceField;
class ParticleSystem {
friend class Emmiter;
friend class ForceField; private :
deque<Particle*> particles;
float elapsedtime;
float *deltatime;
float LifeOfParticles;
unsigned short particlesperframe; public :
ParticleSystem(const float &life,float *dt)
:elapsedtime(0),deltatime(dt),LifeOfParticles(life)
{
}
void deleteparticles()
{
float div=fmod(elapsedtime,LifeOfParticles);
if(div==0)
{
deque<Particle*>::const_iterator begin=particles.begin();
deque<Particle*>::const_iterator end=particles.end();
for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
delete (*it);
particles.clear();
}
}
void drawparticl1es()
{
deque<Particle*>::const_iterator begin=particles.begin();
deque<Particle*>::const_iterator end=particles.end();
for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
{
(*it)->proceedintime();
(*it)->draw();
}
elapsedtime+=(*deltatime);
} };
class Emmiter { public :
unsigned short ParticlesPerSecond;
Vector3 position;
ParticleSystem *ps;
unsigned char count;
float *deltatime;
Particle *(*emitfunc)(const Emmiter &em);
Emmiter(const unsigned short &parpersec,const Vector3 &pos,ParticleSystem *p,const unsigned char &c)
:ParticlesPerSecond(parpersec),position(pos),ps(p),count(c)
{
}
unsigned short particlesperframe()const
{
return ParticlesPerSecond*(*deltatime);
}
void emitparticles()const
{
unsigned short numpars=particlesperframe();
Particle *p=0;
for(unsigned char i=0;i<count;i++)
{
for(unsigned short j=0;j<numpars;j++)
{
p=emitfunc(*this);
p->lifebegin=ps->elapsedtime;
ps[i].particles.push_back(p);
}
}
} }; class ForceField { private :
Vector3 center;
float radius,MaxAcceleration;
unsigned char count;
ParticleSystem *pars; public:
ForceField(const Vector3 &cen,const float &r,const float &mf,ParticleSystem *ps,const unsigned char &c);
void applyforceonparticle(Particle *p)const;
void applyforceonsystems()const; };
ForceField::ForceField(const Vector3 &cen,const float &r,const float
&mf,ParticleSystem *ps,const unsigned char &c)
:center(cen),radius(r),MaxAcceleration(mf),count(c),pars(ps) {
}
void ForceField::applyforceonsystems() const {
for(unsigned char i=0;i<count;i++)
{
ParticleSystem p=pars[i];
for(deque<Particle*>::const_iterator it=p.particles.begin();it!=p.particles.end();it++)
{
applyforceonparticle(*it);
}
} }
void ForceField::applyforceonparticle(Particle *p) const {
Vector3 orentation=center-p->position;
float strength=1-orentation.length()/radius;
if(strength<=0)
return;
p->applyforce(Force(orentation,strength*MaxAcceleration*p->mass)); }
class BallParticle:public TexturedParticle { public :
float radius;
BallParticle(const Vector3 &pos,const float &r,const float &m,float *dt,const float &life,const unsigned int &tex)
:TexturedParticle(pos,m,dt,life,tex),radius(r)
{
}
void draw() const
{
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,textureid);
glTranslatef(position.x, position.y, position.z);
glutSolidSphere(radius,10,10);
glPopMatrix();
}
bool collide(Particle *p) const
{
BallParticle *b=dynamic_cast<BallParticle*>(p);
return (b)&&((b->position-position).length()<=b->radius+radius);
} }; using namespace std;
float deltatime; float oldtime; float newtime; GLuint texture;
ParticleSystem pars(1,&deltatime); Emmiter
emmiter(100,Vector3(0,0,0),&pars,1); ForceField
f(Vector3(0,0.5f,0),0.5f,0.1f,&pars,1);
float myrand(const float &min,const float &max) {
return min+(max-min)*(float(rand())/float(RAND_MAX)); }
Particle *emitfunction(const Emmiter &em) {
float x=em.position.x,y=em.position.y;
BallParticle *b=new BallParticle(Vector3(myrand(x-1,x+1),myrand(y-1,y+1),em.position.z),1,2,&deltatime,0.0f,texture);
b->velocity=Vector3(0,1,0);
return b; }
GLuint GetTextId(const char *texture_name) {
return(SOIL_load_OGL_texture(
texture_name,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
));
}
/* GLUT callback Handlers */ void resize(int width, int height) {
glViewport(0, 0, width, height);
/*glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(4/3.0f),2,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.LookAt();*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(float)width/(float)height,0.1f,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( 0, 0, 10, 0, 0, 0, 0, 1, 0 ); }
void display() {
glClear(GL_COLOR_BUFFER_BIT);
newtime=glutGet(GLUT_ELAPSED_TIME)/1000;
deltatime=newtime-oldtime;
oldtime=newtime;
pars.drawparticl1es();
glutSwapBuffers(); } void idle() {
emmiter.emitparticles();
f.applyforceonsystems();
pars.deleteparticles();
glutPostRedisplay(); }
void init() {
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 0.0f };
const GLfloat light_diffuse[] = { 1, 0.5f, 0.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
const GLfloat mat_emissive[]={1,0.5f,0,1};
glClearColor(0, 0, 0, 0);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glMaterialfv(GL_FRONT,GL_EMISSION,mat_emissive);
//glShadeModel(GL_SMOOTH);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE); }
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(300,200);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Fire");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutIdleFunc(idle);
init();
oldtime=glutGet(GLUT_ELAPSED_TIME)/1000;
emmiter.emitfunc=&emitfunction;
emmiter.deltatime=&deltatime;
texture=GetTextId("/home/abd/graphics/fire2.jpg");
glutMainLoop();
return EXIT_SUCCESS;
}
and here is the texture I'm using :
The fire looks somewhat good but I'm still having an empty hole in the middle, also the particles don't move smoothly.
I tried these things :
1-change the strength and radius of the forcefield: didn't work.
2-increasing the number of particles per second : didn't work, still see the hole.
3-I made my particles bigger: well it made the fire look better and the hole almost disappeared(almost, it somewhat goes and come) but I get strange curves around the fire and it's still not moving smoothly.
4-I have double buffering and I made a call to glutPostRedisplay in the idle function , they still don't move smoothly, I tried removing the hint for PERSPECTIVE NICEST and SMOOTH_SHADING_MODEL, I'm using glutSolidSphere which uses new opengl capabilities and I have Nvidia GT9400 with updated driver to the last version, and still they don't move smoothly.
So what to do to solve these two problems ?
PS
because this is for a university project, I don't want code, "where is the mistake" is enough, I can solve it after I know it.
An algorithm is ok but not code.
EDIT
here's a screenshot of the output :
As you can see, there is a small hole in the middle and curves around the fire.
at a first glance it looks like you have to play a bit with the glBlendFunc
https://www.opengl.org/sdk/docs/man2/xhtml/glBlendFunc.xml
here's a nice viewer of what those parameters do
http://www.andersriggelsen.dk/glblendfunc.php
I'm trying to display an image in openGL using SDL and SOIL but it isn't working.
Globals.h
#include <SDL.h>
#include <SDL_OpenGL.h>
#include <SOIL.h>
#include "player.h"
main.cpp
#include "Globals.h"
int main(int argc, char** argv){
//Begin SDL initialization
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface* Screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE|SDL_OPENGL);
SDL_Event Event;
//End SDL initialization
//Begin OpenGL initialization
glClearColor(1, 1, 1, 1);//Set colour for empty screen
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);//Enable transparency
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//End OpenGL initialization
Player Player(0, 0, 32, 64, 1, 0, 0, 0.5);
bool gameRunning = true;
while(gameRunning){
while(SDL_PollEvent(&Event)){
if(Event.type == SDL_QUIT)
gameRunning = false;
//If user closed the window in any way stop gameRunning
Player.Events(Event);
}
Player.Update();
glClear(GL_COLOR_BUFFER_BIT);//Clear screen
glPushMatrix();
Player.DisplayWithImage("Brick.png", 32, 64);
glPopMatrix();
SDL_GL_SwapBuffers();//Update screen with new shit
}
SDL_Quit();//Quit SDL
return 0;//End program
}
player.h
#pragma once
class Player{
public:
GLfloat X, Y, W, H, R, G, B, A;
bool movingUp, movingRight, movingDown, movingLeft;
GLuint image;
Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h,
GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void Events(SDL_Event &Event);
void Update();
void Display();
void DisplayWithImage(const char* filename, GLsizei w, GLsizei h);
};
player.cpp
#include "Globals.h"
Player::Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h, GLfloat r, GLfloat g, GLfloat b, GLfloat a){
X = x;
Y = y;
W = w;
H = h;
R = r;
G = g;
B = b;
A = a;
movingUp = false;
movingRight = false;
movingDown = false;
movingLeft = false;
}
void Player::Events(SDL_Event &Event){
if(Event.type == SDL_KEYDOWN){
if(Event.key.keysym.sym == SDLK_w)
movingUp = true;
if(Event.key.keysym.sym == SDLK_d)
movingRight = true;
if(Event.key.keysym.sym == SDLK_s)
movingDown = true;
if(Event.key.keysym.sym == SDLK_a)
movingLeft = true;
}
if(Event.type == SDL_KEYUP){
if(Event.key.keysym.sym == SDLK_w)
movingUp = false;
if(Event.key.keysym.sym == SDLK_d)
movingRight = false;
if(Event.key.keysym.sym == SDLK_s)
movingDown = false;
if(Event.key.keysym.sym == SDLK_a)
movingLeft = false;
}
}
void Player::Update(){
if(movingUp)
Y ++;
if(movingRight)
X ++;
if(movingDown)
Y --;
if(movingLeft)
X --;
}
void Player::Display(){
glBegin(GL_QUADS);
glColor4f(R, G, B, A);
//bottom right
glVertex2f(X+(W/2), Y-(H/2));
//top right
glVertex2f(X+(W/2), Y+(H/2));
//top left
glVertex2f(X-(W/2), Y+(H/2));
//bottom left
glVertex2f(X-(W/2), Y-(H/2));
glEnd();
}
void Player::DisplayWithImage(const char* filename, GLsizei w, GLsizei h){
image = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glBindTexture(GL_TEXTURE_2D, image);
glBegin(GL_QUADS);
//bottom right
glTexCoord2f(0, 0); glVertex2f(X+(W/2), Y-(H/2));
//top right
glTexCoord2f(0, H); glVertex2f(X+(W/2), Y+(H/2));
//top left
glTexCoord2f(W, H); glVertex2f(X-(W/2), Y+(H/2));
//bottom left
glTexCoord2f(W, 0); glVertex2f(X-(W/2), Y-(H/2));
glEnd();
}
You have three problems in your code:
GL_TEXTURE_2D uses normalized texture coordinates (0.0 - 1.0). Unless H and W are 1.0 or less you do not want to use them for your texture coordinates. If you just want to stretch this texture across your quad one time, use 1.0 in-place of W and H.
Most Serious Issue: You are creating a new texture on each frame, you should load the texture one time and then pass the loaded texture handle to DisplayWithImage (...) instead of having that function load a texture each time you call it.
glOrtho (...) creates an orthographic projection matrix, any GL operation that uses the projection matrix in isolation (e.g. not Projection * ModelView) is going to fail to work properly if you use an identity projection matrix and an orthographic projection matrix for your modelview matrix. By the same token, things like vertex lighting will not work properly with a projection matrix serving as your modelview matrix...
You can correct bullet point 3 by re-writing part of your code this way:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display
~~~~~~~ This should come AFTER you set the matrix mode to projection!
I am making a basic OpenGl program which is my weekend project.
Description: If I drag the mouse on the window screen then after I release the button(left) a line should appear that shows the path of dragging the mouse and a circle should traverse that line from start to end.
My Code Works Very Well but the problem is that the line drawn is not continuous[rather its dashed] and it may be because of the mapping of OS screen to OpenGL screen.
SO is there any way to make a continous line path or correct me If I am doing something wrongHere is my code:
#include <iostream>
#include <glut.h>
#include <string.h>
#define WIDTH 600
#define HEIGHT 600
using namespace std;
double arr[5000][4];
int z=0;
int flag=0;
float radius=0.03;
int ptr=0;
int faltu_bit=1;
float color[3][3]={{1.0,1.0,1.0},{1.0,1.0,0.0},{0.0,1.0,0.0}};
void drawText(char *str,float x,float y,int id)
{
int i;
int len=strlen(str);
//glLoadIdentity();
glColor3f(color[id][0],color[id][1],color[id][2]);
glRasterPos2f(x,y);
for(i=0;i<len;i++)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,str[i]);
}
void init()
{
glClearColor( 0.0, 0.0, 0.0, 1.0);
glMatrixMode( GL_PROJECTION);
gluOrtho2D(0.0,WIDTH,0.0,HEIGHT);
memset(arr,0,5000);
glPointSize(20.0);
}
void resetAll()
{
memset(arr,0,5000);
z=0;
}
///OPENGL MAPPING///
float getOpenGLX(int x)
{
double ox = x/ (double)WIDTH*(WIDTH);
return ox;
}
float getOpenGLY(int y)
{
double oy = (1 - y/ (double) HEIGHT)*HEIGHT;
return oy;
}
void drawPoints()
{
glBegin( GL_POINTS );
glColor3f( 0.0,1.0,0.0 );
for ( int i = 0; i < z; i++ )
{
glVertex2f( arr[i][0],arr[i][1]);
}
glEnd();
}
void drawBall(float x,float y)
{
glBegin( GL_POINTS);
glColor3f( 1.0,1.0,0.0 );
glVertex2f(x,y);
glEnd();
}
void drawLines()
{
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0);
for(int i=0;i<z;i++)
{
glVertex2f(arr[i][0],arr[i][1]);
}
glEnd();
}
void addValue(int x,int y)
{
arr[z][0]=getOpenGLX(x);
arr[z++][1]=getOpenGLY(y);
}
void trackBall()
{
drawPoints();
}
void myDisplay()
{
glClear( GL_COLOR_BUFFER_BIT);
if(!flag)
{
drawLines();
if(!faltu_bit)
drawBall(arr[ptr][0],arr[ptr][1]);
}
if(faltu_bit)
{
drawText("Project by: Adil Ansar [10 CSS-32]",50.0,500.0,0);
drawText("Welcome",250.0,300.0,1);
drawText("Drag the Mouse Any Where in the Window to see the Path",10.0,200.0,2);
}
glutSwapBuffers();
glutPostRedisplay();
glFlush();
}
void myMouseStat(int button,int state,int x, int y)
{
if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
{
if(!flag)
{
if(faltu_bit)
{
faltu_bit=0;
}
resetAll();
flag=1;
}
}
else if(button==GLUT_LEFT_BUTTON && state==GLUT_UP)
{
if(flag)
{
ptr=0;
flag=0;
}
}
}
void myPressedMove(int x,int y)
{
if(flag)
{
addValue(x,y);
}
}
void myTimer(int t)
{
if(ptr!=z)
{
ptr++;
}
else
{
ptr=0;
}
glutTimerFunc(100,myTimer,0);
}
int main( int argc, char ** argv)
{
glutInit( &argc, argv);
glutInitDisplayMode( GLUT_DOUBLE| GLUT_RGB);
glutInitWindowPosition( 100, 100);
glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow( "Testing");
init();
glutDisplayFunc(myDisplay);
glutMouseFunc(myMouseStat);
glutMotionFunc(myPressedMove);
glutTimerFunc(100,myTimer,0);
glutMainLoop();
return 0;
}
This Is What I get:
In this code
void drawLines()
{
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0);
for(int i=0;i<z;i++)
{
glVertex2f(arr[i][0],arr[i][1]);
}
glEnd();
}
GL_LINES is a drawing mode where two consecutive vertices make a line segment. Then the next two and so so. What you're drawing is a line strip; replacing GL_LINES with GL_LINE_STRIP will give you your expected result.
On a side note: You should abandon using immediate mode (glBegin, glVertex, glEnd). It's slow, it's cumbersome to work with and in the long term can become a major PITA. Use at least vertex arrays; they've been the recommended way of supplying geometry data for well over 15 years. Plus it makes your code much simpler. Your code above can be replaced with this:
/* vertex data comes from an array */
glEnableClientState(GL_VERTEX_ARRAY);
/* we want to use a common color for all vertices */
glDisableClientState(GL_COLOR_ARRAY);
glColor3f(1.0, 0.0, 0.0);
/* where to get the data from */
glVertexPointer(2, GL_DOUBLE, sizeof(double)*4, arr);
/* draw the whole thing */
glDrawArrays(GL_LINE_STRIP, 0, z);
/* cleanup */
glDisableClientState(GL_VERTEX_ARRAY);
As you can see it's shorter, more concise, easier to read and it avoids doing z+3 function calls, each of which taking some time to execute.
Important that OpenGL can digest that multidimensional array arr is due to the fact, that statically allocated storage of multidimensional arrays is always contiguous. It would not work if you'd allocate an array of pointers to arrays (the naive way to allocate multidimensional arrays dynamically).
my next question(or problem) in line is that when i load a model with glm, im able to see through parts of the model for example: if there were two mountains one in front of the other, i could see through the nearer mountain.
i would show a picture but it wouldnt be understandable since the texture doesnt work.
heres that problem here:
OLDER STUFF:vvvvvvvvvvvvvvvvvvvvvvv
all im wondering is: what is the best Matrix mode for using glm?
i have been used to GL_PROJECTION but its giving me too many problems when loading my model
and with GL_MODELVIEW im not able to move the camera back
i am also wondering: if i use GL_MODELVIEW, then how can i move the "camera" in the scene? is there a way to maybe setup one since ima have to eventually?
EDIT: alright heres some code to give you guys some kind of vision:
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <assert.h>
#include <vector>
#include <glm/glm.h>
#include <glm/glmint.h>
#include "Item.hpp"
#include "Player.hpp"
///GOLD WAVE
using namespace std;
///GLOBAL VARIABLES
vector<sf::Sprite> SpriteList;
vector<GLMmodel*> ModelList;
vector<GLuint> _texture;
vector<Item*> DefItemList;
Player *pPlayer=new Player();
sf::RenderWindow GameWind(sf::VideoMode(800,600,32),"Carperon Game Window",sf::Style::Titlebar);
sf::View GameView(sf::FloatRect(0,0,25,18.75));//65x45 and 8x 0,0,65,45
///PROTOTYPE FUNCTIONS
void SFMLcreate();
void SFMLdraw();
void GLMcreate();
void GLdraw();
GLuint LoadTexture();
void GLiniti();
void ITEMdefault();
///////////////////////////////////STOP PROTOTYPES//////////////////////////////
//////////////////////////////////FUNCTIONS//////////////////////////////////
int main()
{
GLiniti();
SFMLcreate();
GLMcreate();
ITEMdefault();
sf::Event EventMain;
vector<sf::Sprite> ShowingBag;
sf::Image isbItem[45],iseItem[6];
sf::Sprite sbItem[45],seItem[6];
int BagSlotX[45] {0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30};
int BagSlotY[45] {0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30};
int EquipSlotY[6] {0,15,30,0,15,30};
bool BagUpdate = true;
int click = 0;
///MAIN PLAYER
pPlayer->PlayerCreate("Molma");
pPlayer->EquipFill(DefItemList[0]);
pPlayer->AddItem(DefItemList[1]);
pPlayer->AddItem(DefItemList[2]);
pPlayer->AddItem(DefItemList[3]);
pPlayer->AddItem(DefItemList[4]);
while(GameWind.IsOpened())
{
while(GameWind.GetEvent(EventMain))
{
//If its closed
if(EventMain.Type==sf::Event::Closed)
{
//Close the whole thing!
//GameWind.Close();
GameWind.Close();
}
}
float MouseX = (GameWind.GetInput().GetMouseX()/32.f);
float MouseY = (GameWind.GetInput().GetMouseY()/32.f);
if(GameWind.GetInput().IsKeyDown(sf::Key::Escape))
{
GameWind.Close();
//GameWind.Close();
}
/////////////////////////////BEGIN INPUT/////////////////////////////////////////////////
if(GameWind.GetInput().IsKeyDown(sf::Key::Return))
{
pPlayer->RandHealth();
BagUpdate = true;
}
if(GameWind.GetInput().IsKeyDown(sf::Key::Z))
{
pPlayer->GetHit();
}
if(GameWind.GetInput().IsMouseButtonDown(sf::Mouse::Right)&&click<=0)
{
for(int a=0;a<pPlayer->Bag.size();++a)
{
if(MouseX>((17.f+(BagSlotX[a]))/16.f)&&MouseX<(((32.f+(BagSlotX[a]))/16.f))&&MouseY>((60.f+(BagSlotY[a]))/16.f)&&MouseY<(((75.f+(BagSlotY[a]))/16.f)))
{
pPlayer->ItemUse(pPlayer->Bag[a],a);
BagUpdate = true;
click=20;
//cout << "Item used!" << endl;
}
}
for(int b=0;b<6;++b)
{
if(MouseX>2.f/16.f&&MouseX<17.f/16.f&&MouseY>((60.f+(EquipSlotY[b]))/16.f)&&MouseY<((75.f+(EquipSlotY[b]))/16.f)&&pPlayer->EqSpot[b]->get_Type()!="Blank Spot")
{
pPlayer->Unequip(pPlayer->EqSpot[b],DefItemList[0],b);
BagUpdate = true;
click=20;
}
}
}
///////////////////////////////END INPUT/////////////////////////////////////////////////
//////////////////////////////AUTO FUNCTIONS//////////////////////////////////////////////
pPlayer->Guarding();
pPlayer->HitTiming();
if(BagUpdate)
{
for(int a=0;a<pPlayer->Bag.size();++a)
{
isbItem[a].LoadFromFile("Graphics/Items.png");
sbItem[a].SetImage(isbItem[a]);
sbItem[a].SetPosition(((17.f+(BagSlotX[a]))/16.f),((60.f+(BagSlotY[a]))/16.f));
}
for(int b=0;b<6;++b)
{
iseItem[b].LoadFromFile("Graphics/Items.png");
seItem[b].SetImage(iseItem[b]);
seItem[b].SetPosition(2.f/16.f,((60.f+(EquipSlotY[b]))/16.f));
}
BagUpdate=false;
}
if(click>0)
{
click-=1;
}
SpriteList[22].SetPosition(MouseX,MouseY);
GameWind.SetView(GameView);
GLdraw();
SFMLdraw();
for(int a=((pPlayer->get_BagShow())*9);a<((pPlayer->get_BagShow()*9)+9);++a)//18-27=A
{
if(a<pPlayer->Bag.size())
{
sbItem[a].Resize(15.f/16.f,15.f/16.f);
sbItem[a].SetSubRect(sf::IntRect((pPlayer->Bag[a]->get_Index()*15),0,((pPlayer->Bag[a]->get_Index()*15)+15),15));
GameWind.Draw(sbItem[a]);
//cout << "Items Drawn! Position: " << BagSlotX[a] << "," << BagSlotY[a] << "Item: " << a << endl;
//image pos resize subrect
}
}
for(int b=((pPlayer->get_EquipShow())*3);b<((pPlayer->get_EquipShow()*3)+3);++b)
{
seItem[b].Resize(15.f/16.f,15.f/16.f);
seItem[b].SetSubRect(sf::IntRect((pPlayer->EqSpot[b]->get_Index()*15),0,((pPlayer->EqSpot[b]->get_Index()*15)+15),15));
GameWind.Draw(seItem[b]);
}
GameWind.Draw(SpriteList[16]);
GameWind.Draw(SpriteList[20]);
GameWind.Draw(SpriteList[21]);
GameWind.Draw(SpriteList[22]);
GameWind.Display();
GameWind.SetFramerateLimit(60);
}
return EXIT_SUCCESS;
}
void SFMLcreate()
{
sf::Image iStatBack,iStatWindow,ipHealth,ipEnergy,ipStr,ipDex,ipInt,ipEnd,ipCrit,ipSwd,ipAxe,ipBow,ipStar,ipWand,ipStaff,ipBag,ipEquip,ipSkills,ipNumHP,ipNumEP,ipGuard,ipRank,ipRankXP,iCursor;
sf::Sprite StatBack,StatWindow,pHealth,pEnergy,pStr,pDex,pInt,pEnd,pCrit,pSwd,pAxe,pBow,pStar,pWand,pStaff,pBag,pEquip,pSkills,pNumHP,pNumEP,pGuard,pRank,pRankXP,Cursor;
sf::Font MainFont;
//LoadFromFile
iStatBack.LoadFromFile("Graphics/Player Stats/Stats Back.png");
iStatWindow.LoadFromFile("Graphics/Player Stats/StatWindow2.png");
ipHealth.LoadFromFile("Graphics/Player Stats/Health.png");
ipEnergy.LoadFromFile("Graphics/Player Stats/Energy.png");
ipStr.LoadFromFile("Graphics/Player Stats/Strength.png");
ipDex.LoadFromFile("Graphics/Player Stats/Dexterity.png");
ipInt.LoadFromFile("Graphics/Player Stats/Intellegence.png");
ipEnd.LoadFromFile("Graphics/Player Stats/Endurance.png");
ipCrit.LoadFromFile("Graphics/Player Stats/Critical.png");
ipSwd.LoadFromFile("Graphics/Player Stats/Sword Mast.png");
ipAxe.LoadFromFile("Graphics/Player Stats/Axe Mast.png");
ipBow.LoadFromFile("Graphics/Player Stats/Bow Mast.png");
ipStar.LoadFromFile("Graphics/Player Stats/Star Mast.png");
ipWand.LoadFromFile("Graphics/Player Stats/Wand Mast.png");
ipStaff.LoadFromFile("Graphics/Player Stats/Staff Mast.png");
ipBag.LoadFromFile("Graphics/Player Stats/Bag.png");
ipEquip.LoadFromFile("Graphics/Player Stats/Bag.png");
ipSkills.LoadFromFile("Graphics/Player Stats/Skill.png");
ipNumHP.LoadFromFile("Graphics/Player Stats/Number HE.png");
ipNumEP.LoadFromFile("Graphics/Player Stats/Number HE.png");
ipGuard.LoadFromFile("Graphics/Player Stats/Guard.png");
ipRank.LoadFromFile("Graphics/Player Stats/Rank.png");
ipRankXP.LoadFromFile("Graphics/Player Stats/RankXP.png");
iCursor.LoadFromFile("Graphics/Cursor.png");
//SetSmooth()
ipStr.SetSmooth(false);
ipDex.SetSmooth(false);
ipInt.SetSmooth(false);
ipEnd.SetSmooth(false);
ipCrit.SetSmooth(false);
ipSwd.SetSmooth(false);
ipAxe.SetSmooth(false);
ipBow.SetSmooth(false);
ipStar.SetSmooth(false);
ipWand.SetSmooth(false);
ipStaff.SetSmooth(false);
ipSkills.SetSmooth(false);
ipHealth.SetSmooth(false);
ipEnergy.SetSmooth(false);
ipGuard.SetSmooth(false);
ipNumHP.SetSmooth(false);
ipNumEP.SetSmooth(false);
ipRankXP.SetSmooth(false);
ipRank.SetSmooth(false);
//SetImage!!
StatBack.SetImage(iStatBack);
StatWindow.SetImage(iStatWindow);
pHealth.SetImage(ipHealth);
pEnergy.SetImage(ipEnergy);
pStr.SetImage(ipStr);
pDex.SetImage(ipDex);
pInt.SetImage(ipInt);
pEnd.SetImage(ipEnd);
pCrit.SetImage(ipCrit);
pSwd.SetImage(ipSwd);
pAxe.SetImage(ipAxe);
pBow.SetImage(ipBow);
pStar.SetImage(ipStar);
pWand.SetImage(ipWand);
pStaff.SetImage(ipStaff);
pBag.SetImage(ipBag);
pEquip.SetImage(ipEquip);
pSkills.SetImage(ipSkills);
pNumHP.SetImage(ipNumHP);
pNumEP.SetImage(ipNumEP);
pGuard.SetImage(ipGuard);
pRank.SetImage(ipRank);
pRankXP.SetImage(ipRankXP);
Cursor.SetImage(iCursor);
//SetPosition(x,y)!!
StatBack.SetPosition(0,0);
StatWindow.SetPosition(-5.f/16.f,-5.f/16.f);
pHealth.SetPosition(5.f/16.f,23.25f/16.f);
pEnergy.SetPosition(5.f/16.f,31.5f/16.f);
pStr.SetPosition(59.f/16.f,23.f/16.f);
pDex.SetPosition(59.f/16.f,35.f/16.f);
pInt.SetPosition(59.f/16.f,47.f/16.f);
pEnd.SetPosition(3.f/16.f,37.f/16.f);
pCrit.SetPosition(32.f/16.f,37.f/16.f);
pSwd.SetPosition(63.f/16.f,21.f/16.f);
pAxe.SetPosition(63.f/16.f,29.f/16.f);
pBow.SetPosition(63.f/16.f,33.f/16.f);
pStar.SetPosition(63.f/16.f,41.f/16.f);
pWand.SetPosition(63.f/16.f,45.f/16.f);
pStaff.SetPosition(63.f/16.f,53.f/16.f);
pBag.SetPosition(2.f/16.f,60.f/16.f);
pEquip.SetPosition(2.f/16.f,60.f/16.f);
pSkills.SetPosition(71.f/16.f,61.f/16.f);
pNumHP.SetPosition(4.f/16.f,22.f/16.f);
pNumEP.SetPosition(4.f/16.f,30.f/16.f);
pGuard.SetPosition(4.f/16.f,22.5f/16.f);
pRank.SetPosition(41.5f/16.f,25.f/16.f);
pRankXP.SetPosition(39.5f/16.f,23.f/16.f);
//VECTOR STORE
SpriteList.push_back(StatWindow);
SpriteList.push_back(pHealth);
SpriteList.push_back(pEnergy);
SpriteList.push_back(pStr);
SpriteList.push_back(pDex);
SpriteList.push_back(pInt);
SpriteList.push_back(pEnd);
SpriteList.push_back(pCrit);
SpriteList.push_back(pSwd);
SpriteList.push_back(pAxe);
SpriteList.push_back(pBow);
SpriteList.push_back(pStar);
SpriteList.push_back(pWand);
SpriteList.push_back(pStaff);
SpriteList.push_back(pBag);
SpriteList.push_back(pEquip);
SpriteList.push_back(pSkills);
SpriteList.push_back(pNumHP);
SpriteList.push_back(pNumEP);
SpriteList.push_back(pGuard);
SpriteList.push_back(pRank);
SpriteList.push_back(pRankXP);
SpriteList.push_back(Cursor);
}
void SFMLdraw()
{
//////////////////////////////STAT RESIZE/SUBRECT///////////////////////////////////////
SpriteList[1].SetSubRect(sf::IntRect(0,0,120,12)); //30,3
SpriteList[2].SetSubRect(sf::IntRect(0,0,120,12)); //30,3
SpriteList[3].SetSubRect(sf::IntRect(pPlayer->get_Str()*28,0,(pPlayer->get_Str()*28)+28,7)); //28,7
SpriteList[4].SetSubRect(sf::IntRect(pPlayer->get_Dex()*28,0,(pPlayer->get_Dex()*28)+28,7)); //28,7
SpriteList[5].SetSubRect(sf::IntRect(pPlayer->get_Int()*28,0,(pPlayer->get_Int()*28)+28,7)); //28,7
SpriteList[6].SetSubRect(sf::IntRect(pPlayer->get_End()*28,0,(pPlayer->get_End()*28)+28,7)); //28,7
SpriteList[7].SetSubRect(sf::IntRect(pPlayer->get_Crit()*28,0,(pPlayer->get_Crit()*28)+28,7)); //28,7
SpriteList[8].SetSubRect(sf::IntRect(pPlayer->get_Sword()*18,0,(pPlayer->get_Sword()*18)+18,3)); //18,3
SpriteList[9].SetSubRect(sf::IntRect(pPlayer->get_Axe()*18,0,(pPlayer->get_Axe()*18)+18,3)); //18,3
SpriteList[10].SetSubRect(sf::IntRect(pPlayer->get_Bow()*18,0,(pPlayer->get_Bow()*18)+18,3)); //18,3
SpriteList[11].SetSubRect(sf::IntRect(pPlayer->get_Star()*18,0,(pPlayer->get_Star()*18)+18,3)); //18,3
SpriteList[12].SetSubRect(sf::IntRect(pPlayer->get_Wand()*18,0,(pPlayer->get_Wand()*18)+18,3)); //18,3
SpriteList[13].SetSubRect(sf::IntRect(pPlayer->get_Staff()*18,0,(pPlayer->get_Staff()*18)+18,3)); //18,3
SpriteList[14].SetSubRect(sf::IntRect((pPlayer->get_BagShow()*60)+120,0,(pPlayer->get_BagShow()*60)+180,48));
SpriteList[15].SetSubRect(sf::IntRect(pPlayer->get_EquipShow()*60,0,(pPlayer->get_EquipShow()*60)+60,48));
SpriteList[16].SetSubRect(sf::IntRect(pPlayer->get_SkillShow()*30,0,(pPlayer->get_SkillShow()*30)+30,64));
SpriteList[17].SetSubRect(sf::IntRect(pPlayer->get_Health()*7,0,(pPlayer->get_Health()*7)+7,5));
SpriteList[18].SetSubRect(sf::IntRect(pPlayer->get_Energy()*7,0,(pPlayer->get_Energy()*7)+7,5));
SpriteList[19].SetSubRect(sf::IntRect(0,0,128,20));
SpriteList[20].SetSubRect(sf::IntRect(pPlayer->get_Rank()*14,0,(pPlayer->get_Rank()*14)+14,6));//10
SpriteList[21].SetSubRect(sf::IntRect(pPlayer->get_tRankXPN()*18,0,(pPlayer->get_tRankXPN()*18)+18,10));//16
/////////////////////RESIZE PART
SpriteList[0].Resize(410.f/16.f,310.f/16.f);
SpriteList[1].Resize(pPlayer->get_tHealth()/64.f,12.f/64.f);
SpriteList[2].Resize(pPlayer->get_tEnergy()/64.f,12.f/64.f);
SpriteList[3].Resize(28.f/16.f,7.f/16.f);
SpriteList[4].Resize(28.f/16.f,7.f/16.f);
SpriteList[5].Resize(28.f/16.f,7.f/16.f);
SpriteList[6].Resize(28.f/16.f,7.f/16.f);
SpriteList[7].Resize(28.f/16.f,7.f/16.f);
SpriteList[8].Resize(18.f/16.f,3.f/16.f);
SpriteList[9].Resize(18.f/16.f,3.f/16.f);
SpriteList[10].Resize(18.f/16.f,3.f/16.f);
SpriteList[11].Resize(18.f/16.f,3.f/16.f);
SpriteList[12].Resize(18.f/16.f,3.f/16.f);
SpriteList[13].Resize(18.f/16.f,3.f/16.f);
SpriteList[14].Resize(60.f/16.f,48.f/16.f);
SpriteList[15].Resize(60.f/16.f,48.f/16.f);
SpriteList[16].Resize(30.f/16.f,64.f/16.f);
SpriteList[17].Resize(7.f/16.f,5.f/16.f);
SpriteList[18].Resize(7.f/16.f,5.f/16.f);
SpriteList[19].Resize(pPlayer->get_tGuard()/64.f,20.f/64.f);
SpriteList[20].Resize(14.f/16.f,6.f/16.f);
SpriteList[21].Resize(18.f/16.f,10.f/16.f);
SpriteList[22].Resize(15.f/16.f,15.f/16.f);
///////////////////////////////////END RESIZE/SUBRECT!!!////////////////////////////////
////////////////////////////////////DONT TOUCH/////////////////////////////////////////
///////////////////////////////NOW YOU CAN TOUCH//////////////////////////////////////////
//////////////////////////////DRAW STARTS///////////////////////////////////////////////
GameWind.Draw(SpriteList[0]);
GameWind.Draw(SpriteList[19]);
GameWind.Draw(SpriteList[1]);
GameWind.Draw(SpriteList[17]);
GameWind.Draw(SpriteList[2]);
GameWind.Draw(SpriteList[18]);
GameWind.Draw(SpriteList[3]);
GameWind.Draw(SpriteList[4]);
GameWind.Draw(SpriteList[5]);
GameWind.Draw(SpriteList[6]);
GameWind.Draw(SpriteList[7]);
GameWind.Draw(SpriteList[8]);
GameWind.Draw(SpriteList[9]);
GameWind.Draw(SpriteList[10]);
GameWind.Draw(SpriteList[11]);
GameWind.Draw(SpriteList[12]);
GameWind.Draw(SpriteList[13]);
GameWind.Draw(SpriteList[14]);
GameWind.Draw(SpriteList[15]);
}
void GLMcreate()
{
GLMmodel* World = glmReadOBJ("3Dobject/WorldMap3Dv1.obj");
glmUnitize(World);
glmScale(World,1);
}
void GLdraw()
{
GameWind.SetActive();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
////////AMBIENT LIGHT
GLfloat AmbientColor[] = {0.05f,0.05f,0.2f,1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,AmbientColor);
////////POSITIONED LIGHT
GLfloat LightColor0[] = {0.5f,0.5f,0.5f,1.0f};
GLfloat LightPos0[] = {4.0f,4.0f,0.0f,1.0f};
glLightfv(GL_LIGHT0,GL_DIFFUSE,LightColor0);
glLightfv(GL_LIGHT0,GL_POSITION,LightPos0);
////////DIRECTED LIGHT
GLfloat LightColor1[] = {0.9f,0.9f,0.6f,1.0f};
/////Coming from direction (x,y,z)
GLfloat LightPos1[] = {-1.0f,0.5f,0.5f,0.0f};
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightColor1);
glLightfv(GL_LIGHT1,GL_POSITION,LightPos1);
///DRAWING MODELS
}
void GLiniti()
{
GameWind.PreserveOpenGLStates(true);
GameWind.ShowMouseCursor(false);
glClearDepth(1.f);
glClearColor(0.2f,0.2f,0.8f,1.f);
/////z buffer
glEnable(GL_POLYGON_STIPPLE);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_FRONT);
glFrontFace(GL_CW);
glShadeModel(GL_SMOOTH);
glDepthMask(GL_TRUE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.f,(double)800 / (double)600,200.f,0.f);
glTranslatef(0.f, 0.f, -10.0f);
}
GLuint LoadTexture(sf::Image image)
{
GLuint Texture;
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,image.GetWidth(),image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE,image.GetPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
return Texture;
}
void ITEMdefault()
{
Blank *BlankSpot=new Blank();
BlankSpot->ItemCreate(0,0,0,0,0,0,0);
///TEST ITEMS
Weapon *sword=new Weapon();
sword->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),1,0,sf::Randomizer::Random(1,4));
Armor *sword2=new Armor();
sword2->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),2,0,sf::Randomizer::Random(1,4));
Necklace *sword3=new Necklace();
sword3->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),3,0,sf::Randomizer::Random(1,4));
Consume *hppotion=new Consume();
hppotion->ItemCreate(0,0,0,6,83,0,6);
DefItemList.push_back(BlankSpot);
DefItemList.push_back(sword);
DefItemList.push_back(sword2);
DefItemList.push_back(sword3);
DefItemList.push_back(hppotion);
}
There is not one certain matrix mode you switch OpenGL too. I explained it already in this post OpenGL: What is MatrixMode? , which I'll simple copy here:
OpenGL uses several matrices to transform geometry and associated data. Those matrices are:
Modelview – places object geometry in the global, unprojected space
Proection – projects global coordinates into clip space; you may think of it as kind of a lens
Texture – adjusts texture coordinates before; mostly used to implement texture projection (i.e. projecting a texture as if it was a slide in a projector)
Color – adjusts the vertex colors. Seldomly touched at all
All these matrices are used all the time. Since they follow all the same rules OpenGL has only one set of matrix manipulation functions: glPushMatrix, glPopMatrix, glLoadIdentity, glLoadMatrix, glMultMatrix, glTranslate, glRotate, glScale, glOrtho, glFrustum.
glMatrixMode selects on which matrix those operations act upon. Say you wanted to write some C++ namespacing wrapper, it could look like this:
namespace OpenGL {
// A single template class for easy OpenGL matrix mode association
template<GLenum mat> class Matrix
{
public:
void LoadIdentity() const
{ glMatrixMode(mat); glLoadIdentity(); }
void Translate(GLfloat x, GLfloat y, GLfloat z) const
{ glMatrixMode(mat); glTranslatef(x,y,z); }
void Translate(GLdouble x, GLdouble y, GLdouble z) const
{ glMatrixMode(mat); glTranslated(x,y,z); }
void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) const
{ glMatrixMode(mat); glRotatef(angle, x, y, z); }
void Rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) const
{ glMatrixMode(mat); glRotated(angle, x, y, z); }
// And all the other matrix manipulation functions
// using overloading to select proper OpenGL variant depending on
// function parameters, and all the other C++ whiz.
// ...
};
//
const Matrix<GL_MODELVIEW> Modelview;
const Matrix<GL_PROJECTION> Projection;
const Matrix<GL_TEXTURE> Texture;
const Matrix<GL_COLOR> Color;
}
Later on in a C++ program you could write then
void draw_something()
{
OpenGL::Projection::LoadIdentity();
OpenGL::Projection::Frustum(...);
OpenGL::Modelview::LoadIdentity();
OpenGL::Modelview::Translate(...);
// drawing commands
}
Unfortunately C++ can't template namespaces, or apply using (or with) on instances (other languages have this), otherwise I'd had written something like (invalid C++)
void draw_something_else()
{
using namespace OpenGL;
with(Projection) { // glMatrixMode(GL_PROJECTION);
LoadIdentity(); // glLoadIdentity();
Frustum(...); // glFrustum(...);
}
with(Modelview) { // glMatrixMode(GL_MODELVIEW);
LoadIdentity(); // glLoadIdentity();
Translate(...); // glTranslatef(...);
}
}
I think this last snipped of (pseudo-)code makes it clear: glMatrixMode is kind of a with statement of OpenGL.
All the matrices are used during rendering!
You move the camera by using glTranslate().