Ola amigos!
Hoje estarei aqui ensinando a vocês um pouco de OpenGL (com sorte, o bastante para vocês conseguirem fazer o trabalho de PPC a tempo), assim como um pouco sobre a função popen, a fget e qualquer outra que tenhamos utilizado para fazer o nosso =P
Comecemos então:
OpenGL Basics
Primeiro, vou dar-lhes alguns conceitos sobre OpenGL… quer dizer, poucos conceitos(já que vocês devem estar bem apressados para terminar logo este tutorial e fazerem o maldito trabalho xP), então, OpenGL é uma biblioteca que utiliza chamadas gráficas (Open Graphics Library), para utiliza-la, nós a acessamos através de uma biblioteca chamada glut, que facilita o trabalho, diminuindo as rotinas cruas do OpenGL.
Entendendo as rotinas
As rotinas são sempre chamadas na função main do seu programa, se você conseguir entender inglês, certamente irá perceber que os nomes não são coisa de outro mundo, pois bem, seguem elas:
int main(int argc, char **argv){
glutInit(&argc,argv); //Esta é a função do início das rotinas
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB); //Esta aqui inicia os buffers que agirão sobre a sua janela, nesse caso, um double buffer, um depth buffer e um rgb buffer
glutInitWindowPosition(5,5); //Aqui temos funcao que define a posição inicial da janela, no caso, no pixel (5,5), ou seja, localizado bem proximo ao canto superior esquerdo da tela
glutInitWindowSize(1150,300); //Essa função define o tamanho inicial da janela que você quer mostrar, no caso, 1150×300 pixels
glutCreateWindow(“Process Viewer”); //Essa funcao cria a janela propriamente dita, com o titulo que voce passa por parametro, no caso, Process Viewer
glutDisplayFunc(Desenha); // Essa função define qual a função que irá desenhar na janela criada, no caso, estamos passando a função Desenha como parametro (Explicaremos a criação dessa e de outras funções mais adiante)
glutKeyboardFunc(Teclado); //Essa função define qual a função que irá gerenciar os eventos de teclado, no caso, Teclado
glutTimerFunc(200,Anima,1); //Essa funcao define qual a função que irá ser usada para gerar os eventos de animação, ela recebe também um tempo, que definirá de quanto em quanto tempo a função será chamada, no caso ela tem 200 milisegundos e a função definida é a Anima
CriaMenu(); //Essa função é definida pelo usuário para gerenciar os menus pop-up, explicaremos seu funcionamento mais adiante
Inicializa(); //Essa função é definida pelo usuário para Inicializar o ambiente gráfico, explicaremos seu funcionamento mais adiante
glutMainLoop(); //Essa função é responsável pela constante atualização dos eventos no ambiente do programa
return 0;
}
Funcoes de gerenciamento
Explicaremos agora as funções de gerenciamento de eventos anteriormente citadas, começando pela:
void Desenha(void){
glClear(GL_COLOR_BUFFER_BIT); //Essa função limpa a tela com a cor armazenada no buffer
glColor3f(0,0,0); //Essa função seta uma cor no buffer a partir de 3 floats, cada float indica a porcentagem de uma certa cor (Red,Green,Blue) que vão de 0 a 1
if(start){ //A razão deste if será explicada mais à frente, não se preocupe com ele por hora
FILE *uname; //Aqui nós estamos criando um arquivo que iremos utilizar para armazenar o resultado de um comando do console
char os[200]; //Aqui criamos um char para armazenar uma linha de uname
uname = popen(exibir,”r”); //Aqui nós utilizamos a função popen para passar o conteudo do comando contido na string exibir, executada pelo console do linux, no arquivo que criamos previamente, o uname
int lines = 900; //Aqui iremos definir lines, que será utilizado para imprimir as linhas de uname na janela, você verá a razão a seguir
while(fgets(os,200,uname)!=NULL){ //Aqui, com o while e o fgets, nós percorremos uname linha a linha, armazenando cada linha por vez em os, até o final do arquivo, no caso, fgets joga o conteudo de uma linha de uname para os, copiando no máximo 200 caracteres, a função retorna NULL quando o arquivo acaba
glPushMatrix(); //Aqui nós criamos (damos um push(pilha =P)) uma matriz de movimento para um futuro objeto que criaremos, ela é criada para se fazer rotações, translações, etc
glTranslatef(-3500,lines,0); //Essa função é responsável por definir a localização do que será exibido na tela, ou seja, ela define o centro da tela especifico para um objeto a ser criado, no caso, utilizamos -3500 unidades para a localização no eixo x e utilizamos lines, que criamos anteriormente, com valor 900, para ser responsável pela localização no eixo y do que será construído, e, como estamos num ambiente 2D, deixamos o valor 0 para a localização no eixo z
glScalef(0.5,0.5,0.5); //Aqui nós redimensionamos o que será construído para 50% do seu tamanho real em todos os eixos (fizemos isso porque se mostrou o melhor tamanho para tratar o que queríamos, mas para cada caso só fazendo testes para definir o melhor tamanho, assim como a melhor translação(função anteriormente citada))
glRotatef(0,0,0,1); //Esta é a função de rotação, nós não rotacionamos nosso texto, portando todos os valores são 0
glLineWidth(1); //Essa função define a espessura da linha que você irá utilizar, no caso, colocamos 1 (o padrão)
DesenhaTextoStroke(GLUT_STROKE_MONO_ROMAN, os); //Wow, parece coisa de outro mundo, mas não é, essa é uma função que criamos para escrever um texto na tela e será explicada posteriormente, não se preocupa com isso agora
glPopMatrix(); //Agora nós damos um pop(pilha =P) na matriz que nós criamos
lines-=100; //Aha, agora você irá saber o porque do lines, veja bem, não há uma função para imprimir um newline no OpenGL, então o que fizemos foi calcular mais ou menos um espaçamento ótimo entre as linhas e utilizamos o lines para decrementar toda vez que uma linha for escrita, assim, tem-se a ilusão que estamos utilizando algo parecido com um newline na janela
}
pclose(uname); //Aqui você fecha o arquivo uname, que foi utilizado anteriormente
}
glutSwapBuffers(); //Aqui você chama uma função da glut para trocar os buffers
}
Agora vamos para uma função bem simples que deve tê-los deixados pensativos e que utilizamos previamente:
void DesenhaTextoStroke(void *font, char *string){ //Como o glut só exibe um char por vez na tela, temos que criar uma função para ele desenhar uma linha inteira
while(*string){ //Aqui nós lemos a string de char em char, até o final
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *string++); //Aqui nós imprimimos cada char por vez, mas como eu sei onde imprimir o proximo char? bem, o glut já calcula a distancia certa para tal feito =P
}
}
Agora vamos para a próxima função, a mais simples dessa vez, para dar um descanso:
void Teclado(unsigned char key, int x, int y){ //A função de gerenciamento de teclado deve receber como parametros um unsigned char e 2 ints, o char indica qual tecla foi apertada e os ints indicam a posição do mouse no momento do ocorrido
if(key==27) exit(0); //Aqui é simples, se o usuário pressionar ESC(27) o programa é encerrado
}
Agora vamos para a proxima, a função de gerenciamento de animação:
void Anima(int value){ //A função de animação recebe um int como parametro
glutPostRedisplay(); //Essa função é responsável pelo redesenho da tela
glutTimerFunc(time,Anima,1); //Essa função é semelhante a que está contida na main, define a função de animação e a quanto tempo era irá ser chamada novamente em milisegundos, no caso, a variável time é a responsável por isso, nós definimos time no inicio do programa, antes de declarar qualquer função, como a seguir
}
int time=1000; //Declaração da variável de escopo global time, que irá ser utilizada para definir a taxa de atualização do programa
Falando no time, lembra do start lá na função desenha, nós também o declaramos no escopo global:
bool start=false; //Ela é usada para dar início ou parar o programa quando assim desejado, é comandada através do menu pop-up, assim como a time e a:
char * exibir = “ps -auf”; //Essa string também é utilizada na função Desenha, quando chamamos o popen (se não se lembra, sobe aí e da uma olhadinha!), ela irá definir a filtragem que o usuário deseja
Vamos agora para a criação dos menus:
Criar menus em OpenGL é tão fácil quanto esperar um sorvete derreter no deserto do saara em pleno meio dia =P
Basicamente, cria-se uma função que recebe um int e dentro dela, vários switchs, onde cada um equivale a uma opção do menu, fazer submenus também é extremamente simples, vamos para os exemplos:
void MenuFiltro(int op){ //Aqui nós criamos uma função para um menu, no caso, a função se chama MenuFiltro, ela recebe um int, que é passada a ela quando se clica numa opção no menu pop-up
switch(op){ //Aqui nós temos o switch com os vários casos que nós definimos, dá para entender apenas dando uma lida no que eles fazem =P
case 0:
exibir=”ps -auf | grep ppcq1″;
break;
case 1:
exibir=”ps -auf | grep ppcq2″;
break;
case 2:
exibir=”ps -auf | grep ppcq3″;
break;
case 3:
exibir=”ps -auf | grep ppcq4″;
break;
case 4:
exibir=”ps -auf”;
break;
default:
break;
}
}
Os outros menus são feitos da mesma maneira, com um switch para cada opção, vamos agora para a construção do menu pop-up propriamente dito:
void CriaMenu(){ //Veja que essa é a função que chamamos lá na main
int menu, submenu1,submenu2,submenu3,submenu4; //ints utilizados para receber o resultado das funções de criação de menus
submenu1=glutCreateMenu(MenuFiltro); //Aqui nós criamos um submenu, a partir da função MenuFiltro
glutAddMenuEntry(“ppcq1″,0); //Aqui nós criamos uma entrada no submenu em aberto (submenu1 no caso) e adicionamos um nome e um valor a entrada, ppcq1 e 0 neste caso, analogamente, o mesmo é feito para as outras opções
glutAddMenuEntry(“ppcq2″,1);
glutAddMenuEntry(“ppcq3″,2);
glutAddMenuEntry(“ppcq4″,3);
glutAddMenuEntry(“All proc”,5);
submenu2=glutCreateMenu(MenuTempo); //A partir daqui, nós fechamos o submenu1 e abrimos o submenu2 para a edição, a partir da função MenuTempo, fazendo os mesmos passos para adicionar entradas, até chegarmos ao menu principal
menu = glutCreateMenu(MenuPrincipal); //Aqui nós fechamos qualquer outro menu que estava em aberto anteriormente e começamos a editar o menu principal
glutAddSubMenu(“Filtro”,submenu1); //Aqui nós adicionamos um submenu ao menu principal, nomeando o submenu de Filtro e passando o seu valor, no caso, submenu1
glutAddSubMenu(“Tempo”,submenu2); //Analogamente, fazemos o mesmo com os outros submenus
glutAddSubMenu(“Load”,submenu3);
glutAddMenuEntry(“Start”,0); //Também podemos adicionar entradas normais ao menu, do mesmo jeito que nos menus anteriores
glutAddMenuEntry(“Stop”,1);
glutAddMenuEntry(“Exit”,2);
glutAttachMenu(GLUT_RIGHT_BUTTON); //Essa função associa o menu em aberto (no caso, o menu principal) ao clique com o botao direito do mouse
}
E finalmente chegamos nela, a ultima função (oooooooohhhhhhh =O):
void Inicializa(void){
glMatrixMode(GL_PROJECTION); //Define o modo da matriz para projeção
glLoadIdentity(); //Carrega a matriz identidade
gluOrtho2D(-3500,3500,-1000,1000); //Define a câmera de visualização, no caso, uma camera ortografica 2D, com limites de -3500 a 3500 no eixo x e de -1000 a 1000 no eixo y
glMatrixMode(GL_MODELVIEW); //Define o modo da matriz para visualização
glClearColor(1,1,1,1); //Define a cor a ser utilizada para limpar a janela,utilizando 4 floats, no caso, a cor escolhida foi o branco
}
E esse foi o nosso tutorial rápido do OpenGL!!
AH, falta uma coisa, sim, claro, como eu poderia esquecer dele, afinal, o programa não iria fazer nada se você não pudesse compilá-lo =P
segue o Makefile para compilar seu arquivo:
INCPATH = -I/usr/X11R6/include
LIBS = -lglut -lGLU -lGL -lm -lpthread
LIBPATH = -L/usr/lib -L/usr/X11R6/lib/
%:%.c
gcc $(INCPATH) $(LIBPATH) $^ $(LIBS) -o $@
%:%.cpp
g++ $(INCPATH) $(LIBPATH) $^ $(LIBS) -o $@
Agora é só colocar o Makefile na mesma pasta do seu arquivo e digitar Make nomedoarquivo(não precisa colocar o .cpp/.c(por exemplo, se eu tenho teste.cpp, eu compilo como: Make teste)), não esqueça de ter certeza de ter o glut instalado no seu linux, se não tiver, tente dar:
sudo apt-get install freeglut3-dev
E enfim, chegamos ao fim desse rápido tutorial de OpenGL orientado a questão 5 da nossa lista de PPC
Espero que tenham conseguido entender algo e possam concluir o trabalho a tempo!
Até a próxima galera!
September 10,2008
Categories: Tutorials . Tags: gl, glut, open, opengl, ppc, ppcq5, tutorial . Author: Tiago Gestalt . Comments: 3 Comments