/*
Niniejszy program jest wolnym oprogramowaniem; możesz go
rozprowadzać dalej i / lub modyfikować na warunkach Powszechnej
Licencji Publicznej GNU, wydanej przez Fundację Wolnego
Oprogramowania - według wersji 2 tej Licencji lub(według twojego
wyboru) którejś z późniejszych wersji.
Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on
użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej
gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH
ZASTOSOWAŃ.W celu uzyskania bliższych informacji sięgnij do
Powszechnej Licencji Publicznej GNU.
Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz
Powszechnej Licencji Publicznej GNU(GNU General Public License);
jeśli nie - napisz do Free Software Foundation, Inc., 59 Temple
Place, Fifth Floor, Boston, MA 02110 - 1301 USA
*/
#define GLM_FORCE_RADIANS
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <lodepng.h>
#include "constants.h"
#include "allmodels.h"
#include "mycube.h"
using namespace glm;
float aspect=1.0f; //Aktualny stosunek szerokości do wysokości okna
float speed_x=0; //Szybkość kątowa obrotu obiektu w radianach na sekundę wokół osi x
float speed_y=0; //Szybkość kątowa obrotu obiektu w radianach na sekundę wokół osi y
GLuint tex; //Uchwyt – deklaracja globalna
//Procedura obsługi błędów
void error_callback(int error, const char* description) {
fputs(description, stderr);
}
//Procedura obługi zmiany rozmiaru bufora ramki
void windowResize(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height); //Obraz ma być generowany w oknie o tej rozdzielczości
aspect=(float)width/(float)height; //Stosunek szerokości do wysokości okna
}
//Procedura obsługi klawiatury
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){
if (action == GLFW_PRESS) {
if (key == GLFW_KEY_LEFT) speed_y=PI/2;
if (key == GLFW_KEY_RIGHT) speed_y=-PI/2;
if (key == GLFW_KEY_UP) speed_x=PI/2;
if (key == GLFW_KEY_DOWN) speed_x=-PI/2;
}
if (action == GLFW_RELEASE) {
if (key == GLFW_KEY_LEFT) speed_y=0;
if (key == GLFW_KEY_RIGHT) speed_y=0;
if (key == GLFW_KEY_UP) speed_x=0;
if (key == GLFW_KEY_DOWN) speed_x=0;
}
}
//Procedura inicjująca
void initOpenGLProgram(GLFWwindow* window) {
//************Tutaj umieszczaj kod, który należy wykonać raz, na początku programu************
glfwSetFramebufferSizeCallback(window, windowResize); //Zarejestruj procedurę obsługi zmiany rozdzielczości bufora ramki
glfwSetKeyCallback(window, key_callback); //Zarejestruj procedurę obsługi klawiatury
glClearColor(0,0,0,1); //Ustaw kolor czyszczenia ekranu
glEnable(GL_LIGHTING); //Włącz tryb cieniowania
glEnable(GL_LIGHT0); //Włącz zerowe źródło światła
glEnable(GL_DEPTH_TEST); //Włącz używanie budora głębokości
//glEnable(GL_COLOR_MATERIAL); //Włącz śledzenie kolorów przez materiał
glEnable(GL_TEXTURE_2D);
glEnable(GL_NORMALIZE);
//Wczytanie i import obrazka – w initOpenGLProgram
//Wczytanie do pamięci komputera
std::vector<unsigned char> image; //Alokuj wektor do wczytania obrazka
unsigned width, height; //Zmienne do których wczytamy wymiary obrazka
//Wczytaj obrazek
unsigned error = lodepng::decode(image, width, height, "bricks.png");
//Import do pamięci karty graficznej
glGenTextures(1,&tex); //Zainicjuj jeden uchwyt
glBindTexture(GL_TEXTURE_2D, tex); //Uaktywnij uchwyt
//Wczytaj obrazek do pamięci KG skojarzonej z uchwytem
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*) image.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
//Procedura rysująca zawartość sceny
void drawScene(GLFWwindow* window,float angle_x,float angle_y) {
//************Tutaj umieszczaj kod rysujący obraz******************l
float ambientemmisio[]={0,0,0,1};
float ambientemmisio2[]={0,0,0,1};
float difussion[]={0.7,0.5,0.5,1};
float specular[] = {0,0,0,1};
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //Wyczyść bufor kolorów (czyli przygotuj "płótno" do rysowania)
//***Przygotowanie do rysowania****
mat4 P=perspective(50.0f*PI/180.0f,aspect,1.0f,50.0f); //Wylicz macierz rzutowania P
mat4 V=lookAt( //Wylicz macierz widoku
vec3(0.0f,0.0f,-5.0f),
vec3(0.0f,0.0f,0.0f),
vec3(0.0f,1.0f,0.0f));
glMatrixMode(GL_PROJECTION); //Włącz tryb modyfikacji macierzy rzutowania
glLoadMatrixf(value_ptr(P)); //Załaduj macierz rzutowania
glMatrixMode(GL_MODELVIEW); //Włącz tryb modyfikacji macierzy model-widok
//Rysowanie kostki
mat4 M=mat4(1.0f);
M=rotate(M,angle_x,vec3(1.0f,0.0f,0.0f));
M=rotate(M,angle_y,vec3(0.0f,1.0f,0.0f));
glLoadMatrixf(value_ptr(V));
float lightPos[]={0,0,-6,1};
float lightPos2[]= {0,0,1,0};
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightPos2);
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,10);
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,128);
float test[]={0.1,0.1,0.1,0.1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,test),
glLoadMatrixf(value_ptr(V*M));
//glColor3d(0,1,0);
//Models::cube.drawSolid();
glBindTexture(GL_TEXTURE_2D,tex);
Models::detailedCube.drawSolid();
// glEnableClientState( GL_VERTEX_ARRAY );
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glEnableClientState( GL_NORMAL_ARRAY );
//glEnableClientState( GL_COLOR_ARRAY );
//glVertexPointer( 3, GL_FLOAT, 0, myCubeVertices);
//glTexCoordPointer( 2, GL_FLOAT, 0, myCubeTexColors);
//glNormalPointer( GL_FLOAT, 0, myCubeVertices);
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambientemmisio);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,ambientemmisio);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,difussion);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50 );
//glColorPointer( 3, GL_FLOAT, 0, myCubeColors);
//glDrawArrays(GL_QUADS,0, myCubeVertexCount);
//glDisableClientState( GL_VERTEX_ARRAY );
//glDisableClientState( GL_COLOR_ARRAY );
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState( GL_NORMAL_ARRAY );
glfwSwapBuffers(window); //Przerzuć tylny bufor na przedni
}
int main(void)
{
GLFWwindow* window; //Wskaźnik na obiekt reprezentujący okno
glfwSetErrorCallback(error_callback);//Zarejestruj procedurę obsługi błędów
if (!glfwInit()) { //Zainicjuj bibliotekę GLFW
fprintf(stderr, "Nie można zainicjować GLFW.\n");
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(500, 500, "OpenGL", NULL, NULL); //Utwórz okno 500x500 o tytule "OpenGL" i kontekst OpenGL.
if (!window) //Jeżeli okna nie udało się utworzyć, to zamknij program
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window); //Od tego momentu kontekst okna staje się aktywny i polecenia OpenGL będą dotyczyć właśnie jego.
glfwSwapInterval(1); //Czekaj na 1 powrót plamki przed pokazaniem ukrytego bufora
GLenum err;
if ((err=glewInit()) != GLEW_OK) { //Zainicjuj bibliotekę GLEW
fprintf(stderr, "Nie można zainicjować GLEW: %s\n", glewGetErrorString(err));
exit(EXIT_FAILURE);
}
initOpenGLProgram(window); //Operacje inicjujące
float angle_x=0.0f; //Aktualny kąt obrotu obiektu wokół osi x
float angle_y=0.0f; //Aktualny kąt obrotu obiektu wokół osi y
glfwSetTime(0); //Wyzeruj timer
//Główna pętla
while (!glfwWindowShouldClose(window)) //Tak długo jak okno nie powinno zostać zamknięte
{
angle_x+=speed_x*glfwGetTime(); //Oblicz przyrost kąta obrotu i zwiększ aktualny kąt
angle_y+=speed_y*glfwGetTime(); //Oblicz przyrost kąta obrotu i zwiększ aktualny kąt
glfwSetTime(0); //Wyzeruj timer
drawScene(window,angle_x,angle_y); //Wykonaj procedurę rysującą
glfwPollEvents(); //Wykonaj procedury callback w zalezności od zdarzeń jakie zaszły.
}
//Usunięcie tekstury z pamięci karty graficznej – po głownej pętli
glDeleteTextures(1,&tex);
glfwDestroyWindow(window); //Usuń kontekst OpenGL i okno
glfwTerminate(); //Zwolnij zasoby zajęte przez GLFW
exit(EXIT_SUCCESS);
}