libGLI - New Object HowTo
by Benjamin Schieder
v0.1, 03. Jan 2003This HowTo mainly shows how to create a new 3D-Object using and for use with libGLI
Copyright (c) 2003 Benjamin Schieder
1. Introduction
- 1.1 Author
- 1.2 Getting
2. Problem
- 2.1 Requirements
- 2.2 Problem-Description
3. Solution
- 3.1 Start
- 3.2 Adding the class
- 3.3 Adding the Draw() code
- 3.4 Effects
- 3.5 Multiple Objects
1. Introduction
1.1 Author
The Author of this document is also the current Maintainer of libGLI which, at the time of writing, can be found at http://www.crash-override.net.You contact him via E-Mail via 'libgli at scavenger dot homeip dot net'
1.2 Getting
This document is maintained together with the libGLI library at its website http://www.crash-override.net.1.3 License
Copyright (c) 2003 Benjamin Schieder2. Problem
2.1 Requirements
To create a new object to use it with libGLI you need the following:- libGLI - http://www.crash-override.net./libgli/main.php
- An implementation of OpenGL - Mesalib, NVidia's GLX driver or whatever suits your needs (ask your distributor)
- A C++-Compiler and standard header files (*.h)
- Knowledge about OpenGL-Programming
- The will to do it
2.2 Problem-Description
So, now you've successfully downloaded, compiled and installed libGLI, you understand how the demo-programs work and adapted them a little so that you now have a basic understanding of how libGLI works. Now you want to create your own object for your own program, say, a game.This HowTo will tell you how to create a simple 3D-Object with libGLI.
3. Solution
3.1 Start
We start out with a simple program opening our OpenGL-Window with a width of 800600 using the GLUT library.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <GL/glut.h>
#include "gli.h"
int WindW, WindH;
CGLI_Interface iface;
void Reshape(int width, int height){
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width <= height){
glOrtho(-100.0, 100.0, -100.0*(GLfloat)height/(GLfloat)width, 100.0*(GLfloat)height/(GLfloat)width, -100.0, 100.0);
} else {
glOrtho(-100.0*(GLfloat)width/(GLfloat)height, 100.0*(GLfloat)width/(GLfloat)height, -100.0, 100.0, -100.0, 100.0);
}
glMatrixMode(GL_MODELVIEW);
WindW = width;
WindH = height;
}
void Draw(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
iface.Draw();
glFlush();
glutSwapBuffers();
}
void mouse(int button, int state, int x, int y){
switch (button){
case GLUT_LEFT_BUTTON: button = GLI_MOUSE_BUTTON_LEFT; break;
case GLUT_MIDDLE_BUTTON: button = GLI_MOUSE_BUTTON_MIDDLE; break;
case GLUT_RIGHT_BUTTON: button = GLI_MOUSE_BUTTON_RIGHT; break;
}
switch (state){
case GLUT_DOWN: state = GLI_MOUSE_BUTTON_DOWN; break;
case GLUT_UP: state = GLI_MOUSE_BUTTON_UP; break;
}
iface.SendMouseParameters(GLI_MOUSE_CLICK, button, state, x, WindH-y);
}
void mouse2(int x, int y){
iface.SendMouseParameters(GLI_MOUSE_MOTION_BUTTON, GLI_MOUSE_BUTTON_NONE, GLI_MOUSE_BUTTON_NONE, x, WindH-y);
}
void mouse3(int x, int y){
iface.SendMouseParameters(GLI_MOUSE_MOTION, GLI_MOUSE_BUTTON_NONE, GLI_MOUSE_BUTTON_NONE, x, WindH-y);
}
static void Key(unsigned char key, int x, int y){
switch (key){
case 27: exit(0);
break;
}
}
void timf(int value){
glutPostRedisplay();
glutTimerFunc(30, timf, 0);
}
void CallBack(GLuint id){
exit(0);
}
int main(int argc, char *argv[]){
WindW = 800;
WindH = 600;
glutInit(&argc, argv);
glutInitWindowSize(WindW, WindH);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
(void)glutCreateWindow("Image Demo");
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
glutMouseFunc(mouse);
glutMotionFunc(mouse2);
glutPassiveMotionFunc(mouse3);
glutKeyboardFunc(Key);
glutTimerFunc(10, timf, 0);
glClearColor(0, 0, 0, 0);
glColor3f(1, 1, 1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glutMainLoop();
return 0;
}
|
3.2 Adding the class
For the sake of simplicuty we just add the new class to the existing code instead of a separate file.DO NOT DO THAT IN PRODUCTION CODE!!!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <GL/glut.h>
#include "gli.h"
int WindW, WindH;
CGLI_Interface iface;
class CGLI_Pyramid : public CGLI_Object {
public:
CGLI_Pyramid();
virtual ~CGLI_Pyramid();
virtual void Draw(); // Draw method
virtual void UpdateObject();
virtual void DoAnimationTick();
protected:
virtual void ProcessInternalCallBack(GLuint obj_id);
};
CGLI_Pyramid::CGLI_Pyramid(){
}
CGLI_Pyramid::~CGLI_Pyramid(){
}
void CGLI_Pyramid::Draw(){
}
void CGLI_Pyramid::UpdateObject(){
}
void CGLI_Pyramid::DoAnimationTick(){
}
void CGLI_Pyramid::ProcessInternalCallBack(GLuint obj_id){
}
CGLI_Pyramid pyramid;
|
3.3 Adding the Draw() code
Now, what good does this do when the object does not draw anything to the screen? Here we add the Draw() code:
CGLI_Pyramid::CGLI_Pyramid(){
}
CGLI_Pyramid::~CGLI_Pyramid(){
}
void CGLI_Pyramid::Draw(){
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
}
|
int main(int argc, char *argv[]){
WindW = 800;
WindH = 600;
glutInit(&argc, argv);
glutInitWindowSize(WindW, WindH);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
(void)glutCreateWindow("Image Demo");
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
glutMouseFunc(mouse);
glutMotionFunc(mouse2);
glutPassiveMotionFunc(mouse3);
glutKeyboardFunc(Key);
glutTimerFunc(10, timf, 0);
glClearColor(0, 0, 0, 0);
glColor3f(1, 1, 1);
pyramid.SetScalingFactor(25);
pyramid.SetRotation(45, 45, 0);
iface.AddObject(&pyramid);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glutMainLoop();
return 0;
}
|
3.4 Effects
Now, an object that just sits there is pretty boring. Now we let the pyramid do something when clicked on with the mouse. To achive this, we insert two new variables and some code into the constructor, the Draw(), and the ProcessInternalCallBack():
class CGLI_Pyramid : public CGLI_Object {
public:
CGLI_Pyramid();
virtual ~CGLI_Pyramid();
virtual void Draw(); // Draw method
virtual void UpdateObject();
virtual void DoAnimationTick();
protected:
virtual void ProcessInternalCallBack(GLuint obj_id);
GLint m_rot_add;
GLint m_click_event_type;
};
CGLI_Pyramid::CGLI_Pyramid(){
m_rot_add = 0;
m_click_event_type = 0;
}
|
m_click_event_type will indicate which rotation will be done:
0: Z-Axis
1: Y-Axis
2: X-Axis
CGLI_Pyramid::~CGLI_Pyramid(){
}
void CGLI_Pyramid::Draw(){
if (m_rot_add > 0){
switch (m_click_event_type) {
case 0: glRotatef(m_rot_add, 0, 0, 1); break;
case 1: glRotatef(m_rot_add, 0, 1, 0); break;
case 2: glRotatef(m_rot_add, 1, 0, 0); break;
}
}
|
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
if (m_rot_add > 0){
switch (m_click_event_type) {
case 0: glRotatef(-m_rot_add, 0, 0, 1); break;
case 1: glRotatef(-m_rot_add, 0, 1, 0); break;
case 2: glRotatef(-m_rot_add, 1, 0, 0); break;
}
m_rot_add--;
}
|
m_rot_add will also be decreasd by 1.
}
void CGLI_Pyramid::UpdateObject(){
}
void CGLI_Pyramid::DoAnimationTick(){
}
void CGLI_Pyramid::ProcessInternalCallBack(GLuint obj_id){
if (m_rot_add != 0){
return;
}
if (m_event_type == GLI_CLICKED){
m_rot_add = 360;
m_click_event_type++;
if (m_click_event_type == 3){
m_click_event_type = 0;
}
}
}
|
If so, we set m_rot_add to 360 (Degrees) and increase m_click_event_type by 1 and wrap it to 0 if it is equal to 3.
3.5 Multiple Objects
As a last thing we add a second pyramid just for fun :)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <GL/glut.h>
#include "gli.h"
int WindW, WindH;
CGLI_Interface iface;
class CGLI_Pyramid : public CGLI_Object {
public:
CGLI_Pyramid();
virtual ~CGLI_Pyramid();
virtual void Draw(); // Draw method
virtual void UpdateObject();
virtual void DoAnimationTick();
protected:
virtual void ProcessInternalCallBack(GLuint obj_id);
GLint m_rot_add;
GLint m_click_event_type;
};
CGLI_Pyramid::CGLI_Pyramid(){
m_rot_add = 0;
m_click_event_type = 0;
}
CGLI_Pyramid::~CGLI_Pyramid(){
}
void CGLI_Pyramid::Draw(){
if (m_rot_add > 0){
switch (m_click_event_type) {
case 0: glRotatef(m_rot_add, 0, 0, 1); break;
case 1: glRotatef(m_rot_add, 0, 1, 0); break;
case 2: glRotatef(m_rot_add, 1, 0, 0); break;
}
}
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
if (m_rot_add > 0){
switch (m_click_event_type) {
case 0: glRotatef(-m_rot_add, 0, 0, 1); break;
case 1: glRotatef(-m_rot_add, 0, 1, 0); break;
case 2: glRotatef(-m_rot_add, 1, 0, 0); break;
}
m_rot_add--;
}
}
void CGLI_Pyramid::UpdateObject(){
}
void CGLI_Pyramid::DoAnimationTick(){
}
void CGLI_Pyramid::ProcessInternalCallBack(GLuint obj_id){
if (m_rot_add != 0){
return;
}
if (m_event_type == GLI_CLICKED){
m_rot_add = 360;
m_click_event_type++;
if (m_click_event_type == 3){
m_click_event_type = 0;
}
}
}
CGLI_Pyramid pyramid;
CGLI_Pyramid pyramid2;
void Reshape(int width, int height){
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width <= height){
glOrtho(-100.0, 100.0, -100.0*(GLfloat)height/(GLfloat)width, 100.0*(GLfloat)height/(GLfloat)width, -100.0, 100.0);
} else {
glOrtho(-100.0*(GLfloat)width/(GLfloat)height, 100.0*(GLfloat)width/(GLfloat)height, -100.0, 100.0, -100.0, 100.0);
}
glMatrixMode(GL_MODELVIEW);
WindW = width;
WindH = height;
}
void Draw(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
iface.Draw();
glFlush();
glutSwapBuffers();
}
void mouse(int button, int state, int x, int y){
switch (button){
case GLUT_LEFT_BUTTON: button = GLI_MOUSE_BUTTON_LEFT; break;
case GLUT_MIDDLE_BUTTON: button = GLI_MOUSE_BUTTON_MIDDLE; break;
case GLUT_RIGHT_BUTTON: button = GLI_MOUSE_BUTTON_RIGHT; break;
}
switch (state){
case GLUT_DOWN: state = GLI_MOUSE_BUTTON_DOWN; break;
case GLUT_UP: state = GLI_MOUSE_BUTTON_UP; break;
}
iface.SendMouseParameters(GLI_MOUSE_CLICK, button, state, x, WindH-y);
}
void mouse2(int x, int y){
iface.SendMouseParameters(GLI_MOUSE_MOTION_BUTTON, GLI_MOUSE_BUTTON_NONE, GLI_MOUSE_BUTTON_NONE, x, WindH-y);
}
void mouse3(int x, int y){
iface.SendMouseParameters(GLI_MOUSE_MOTION, GLI_MOUSE_BUTTON_NONE, GLI_MOUSE_BUTTON_NONE, x, WindH-y);
}
static void Key(unsigned char key, int x, int y){
switch (key){
case 27: exit(0);
break;
}
}
void timf(int value){
glutPostRedisplay();
glutTimerFunc(30, timf, 0);
}
void CallBack(GLuint id){
exit(0);
}
int main(int argc, char *argv[]){
WindW = 800;
WindH = 600;
glutInit(&argc, argv);
glutInitWindowSize(WindW, WindH);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
(void)glutCreateWindow("Image Demo");
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
glutMouseFunc(mouse);
glutMotionFunc(mouse2);
glutPassiveMotionFunc(mouse3);
glutKeyboardFunc(Key);
glutTimerFunc(10, timf, 0);
glClearColor(0, 0, 0, 0);
glColor3f(1, 1, 1);
pyramid.SetScalingFactor(25);
pyramid.SetPosition(-45, 0, 0);
pyramid.SetRotation(45, 45, 0);
iface.AddObject(&pyramid);
pyramid2.SetScalingFactor(25);
pyramid2.SetPosition(45, 0, 0);
pyramid2.SetRotation(45, 45, 0);
iface.AddObject(&pyramid2);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glutMainLoop();
return 0;
}
|