Projekt_Grafika/src/projekt.cpp

653 lines
21 KiB
C++
Raw Blame History

#include "glew.h"
#include "freeglut.h"
#include "glm.hpp"
#include "ext.hpp"
#include <iostream>
#include <cmath>
#include <vector>
#include "Shader_Loader.h"
#include "Render_Utils.h"
#include "Camera.h"
#include "Texture.h"
#include "Physics.h"
#include "Skybox.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
GLuint programColor;
GLuint programTexture;
GLuint programSkybox;
GLuint programSun;
GLuint cubemapTexture;
GLuint cubemapTexture2;
GLuint cubemapTexture3;
GLuint skyboxVAO, skyboxVBO;
Core::Shader_Loader shaderLoader;
obj::Model planeModel;
obj::Model boxModel;
obj::Model shipModel;
obj::Model boosterModel;
obj::Model platformModel;
obj::Model craneModel;
obj::Model lampModel;
glm::mat4 boxModelMatrix;
Core::RenderContext planeContext, boxContext, shipContext, boosterContext, platformContext, craneContext, lampContext;
GLuint boxTexture, groundTexture, shipTexture, stoneTexture, redTex, yellowTex;
glm::vec3 cameraPos = glm::vec3(-40, 5, 0);
glm::vec3 cameraDir;
glm::vec3 cameraSide;
glm::vec3 stationPos;
float cameraAngle = 0;
glm::mat4 cameraMatrix, perspectiveMatrix;
glm::vec3 lightDir = glm::normalize(glm::vec3(0.5, -1, -0.5));
glm::vec3 lightPos = glm::vec3(-15.75, 2, 0);
float appLoadingTime;
obj::Model shipModelOrbit;
obj::Model sphereModelOrbit;
obj::Model stationModelOrbit;
GLuint textureAsteroid;
GLuint textureShip;
GLuint textureSun;
GLuint textureEarthHighres;
GLuint textureMoon;
Core::RenderContext shipContextOrbit, sphereContextOrbit, stationContextOrbit;
float frustumScale = 1.f;
bool loading = false;
bool reload = false;
bool end = false;
float orbitSpeed = 0.003f;
// skybox
std::vector<std::string> faces
{
"textures/skybox/stars.jpeg",
"textures/skybox/stars.jpeg",
"textures/skybox/stars.jpeg",
"textures/skybox/stars.jpeg",
"textures/skybox/stars.jpeg",
"textures/skybox/stars.jpeg",
};
// skybox
std::vector<std::string> faces2
{
"textures/skybox/stars3.jpeg",
"textures/skybox/stars3.jpeg",
"textures/skybox/stars3.jpeg",
"textures/skybox/stars3.jpeg",
"textures/skybox/stars3.jpeg",
"textures/skybox/stars3.jpeg",
};
std::vector<std::string> faces3
{
"textures/skybox/stars4.jpeg",
"textures/skybox/stars4.jpeg",
"textures/skybox/stars4.jpeg",
"textures/skybox/stars4.jpeg",
"textures/skybox/stars4.jpeg",
"textures/skybox/stars4.jpeg",
};
// Initalization of physical scene (PhysX)
Physics pxScene(9.8 /* gravity (m/s^2) */);
// fixed timestep for stable and deterministic simulation
const double physicsStepTime = 1.f / 60.f;
double physicsTimeToProcess = 0;
double startupTime = 0;
// physical objects
PxRigidStatic* planeBody = nullptr;
PxMaterial* planeMaterial = nullptr;
std::vector<PxRigidDynamic*> boxBodies;
PxMaterial* boxMaterial = nullptr;
// renderable objects (description of a single renderable instance)
struct Renderable {
Core::RenderContext* context;
glm::mat4 modelMatrix;
GLuint textureId;
};
std::vector<Renderable*> renderables;
void initRenderables()
{
// load models
planeModel = obj::loadModelFromFile("models/plane2.obj");
boxModel = obj::loadModelFromFile("models/box.obj");
shipModel = obj::loadModelFromFile("models/ship.obj");
boosterModel = obj::loadModelFromFile("models/booster.obj");
platformModel = obj::loadModelFromFile("models/platform4.obj");
craneModel = obj::loadModelFromFile("models/crane.obj");
lampModel = obj::loadModelFromFile("models/lamp2.obj");
planeContext.initFromOBJ(planeModel);
boxContext.initFromOBJ(boxModel);
shipContext.initFromOBJ(shipModel);
boosterContext.initFromOBJ(boosterModel);
platformContext.initFromOBJ(platformModel);
craneContext.initFromOBJ(craneModel);
lampContext.initFromOBJ(lampModel);
// load textures
groundTexture = Core::LoadTexture("textures/sand.jpg");
boxTexture = Core::LoadTexture("textures/a.jpg");
shipTexture = Core::LoadTexture("textures/ship.png");
stoneTexture = Core::LoadTexture("textures/stone.png");
redTex = Core::LoadTexture("textures/redTex.png");
yellowTex = Core::LoadTexture("textures/yellowTex.jpg");
// This time we organize all the renderables in a list
// of basic properties (model, transform, texture),
// to unify their rendering and simplify their managament
// in connection to the physics simulation
// create ground
Renderable* ground = new Renderable();
ground->context = &planeContext;
ground->textureId = groundTexture;
renderables.emplace_back(ground);
Renderable* booster = new Renderable();
booster->context = &boosterContext;
booster->textureId = shipTexture;
renderables.emplace_back(booster);
Renderable* spaceship = new Renderable();
spaceship->context = &shipContext;
spaceship->textureId = shipTexture;
renderables.emplace_back(spaceship);
Renderable* platform = new Renderable();
platform->context = &platformContext;
platform->textureId = stoneTexture;
renderables.emplace_back(platform);
Renderable* crane = new Renderable();
crane->context = &craneContext;
crane->textureId = redTex;
renderables.emplace_back(crane);
Renderable* lamp = new Renderable();
lamp->context = &lampContext;
lamp->textureId = yellowTex;
renderables.emplace_back(lamp);
}
void initPhysicsScene()
{
planeBody = pxScene.physics->createRigidStatic(PxTransformFromPlaneEquation(PxPlane(0, 10, 0, 0)));
planeMaterial = pxScene.physics->createMaterial(0.5, 0.5, 0.6);
PxShape* planeShape = pxScene.physics->createShape(PxPlaneGeometry(), *planeMaterial);
planeBody->attachShape(*planeShape);
planeShape->release();
planeBody->userData = renderables[0];
pxScene.scene->addActor(*planeBody);
boxMaterial = pxScene.physics->createMaterial(0.5, 0.5, 0.6);
PxRigidDynamic* boosterBody = pxScene.physics->createRigidDynamic(PxTransform(0, -3, 0)); //desired position - 3
PxShape* boosterShape = pxScene.physics->createShape(PxBoxGeometry(1, 8, 1), *boxMaterial);
boosterShape->setLocalPose(PxTransform(0, 11, 0));
boosterBody->attachShape(*boosterShape);
boosterShape->release();
boosterBody->userData = renderables[1];
pxScene.scene->addActor(*boosterBody);
boxBodies.push_back(boosterBody);
PxRigidDynamic* spaceshipBody = pxScene.physics->createRigidDynamic(PxTransform(0, -3, 0)); // desiredPosition - 19
PxShape* spaceshipShape = pxScene.physics->createShape(PxBoxGeometry(1, 1, 1), *boxMaterial);
spaceshipShape->setLocalPose(PxTransform(0, 20, 0));
spaceshipBody->attachShape(*spaceshipShape);
spaceshipShape->release();
spaceshipBody->userData = renderables[2];
pxScene.scene->addActor(*spaceshipBody);
boxBodies.push_back(spaceshipBody);
}
void updateTransforms()
{
// Here we retrieve the current transforms of the objects from the physical simulation.
auto actorFlags = PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC;
PxU32 nbActors = pxScene.scene->getNbActors(actorFlags);
if (nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
pxScene.scene->getActors(actorFlags, (PxActor**)&actors[0], nbActors);
for (auto actor : actors)
{
// We use the userData of the objects to set up the model matrices
// of proper renderables.
if (!actor->userData) continue;
Renderable* renderable = (Renderable*)actor->userData;
// get world matrix of the object (actor)
PxMat44 transform = actor->getGlobalPose();
auto& c0 = transform.column0;
auto& c1 = transform.column1;
auto& c2 = transform.column2;
auto& c3 = transform.column3;
// set up the model matrix used for the rendering
renderable->modelMatrix = glm::mat4(
c0.x, c0.y, c0.z, c0.w,
c1.x, c1.y, c1.z, c1.w,
c2.x, c2.y, c2.z, c2.w,
c3.x, c3.y, c3.z, c3.w);
}
}
}
void keyboard(unsigned char key, int x, int y)
{
float angleSpeed = 0.5f;
float moveSpeed = 0.5f;
switch (key)
{
//case 'z': cameraAngle -= angleSpeed; break;
//case 'x': cameraAngle += angleSpeed; break;
//case 'd': cameraPos += glm::cross(cameraDir, glm::vec3(0, 1, 0)) * moveSpeed; break;
//case 'a': cameraPos -= glm::cross(cameraDir, glm::vec3(0, 1, 0)) * moveSpeed; break;
//case 'e': cameraPos += glm::vec3(0, 1, 0) * moveSpeed; break;
//case 'q': cameraPos -= glm::vec3(0, 1, 0) * moveSpeed; break;
case 'w':
if (orbitSpeed < 0.02f) {
orbitSpeed += 0.0001f;
}
break;
case 's':
if (orbitSpeed > 0.001f) {
orbitSpeed -= 0.0001f;
}
break;
case 'd':
if (orbitSpeed < 0.02f) {
orbitSpeed += 0.001f;
}
break;
case 'a':
if (orbitSpeed > 0.001f) {
orbitSpeed -= 0.001f;
}
break;
}
}
void mouse(int x, int y)
{
}
glm::mat4 createCameraMatrixLoading()
{
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.0f - appLoadingTime;
cameraDir = glm::normalize(glm::vec3(0, 0, 0) - cameraPos);
glm::vec3 up = glm::vec3(0, 1, 0);
return Core::createViewMatrix(cameraPos, cameraDir, up);
}
glm::mat4 createCameraMatrixOrbit()
{
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.0f - appLoadingTime;
// Obliczanie kierunku patrzenia kamery (w plaszczyznie x-z) przy uzyciu zmiennej cameraAngle kontrolowanej przez klawisze.
cameraPos = glm::rotate(cameraPos, orbitSpeed, glm::vec3(0, 1, 0));
//cameraDir = glm::vec3(cosf(cameraAngle), 0.0f, sinf(cameraAngle));
cameraDir = glm::normalize(glm::vec3(0, 0, 0) - cameraPos);
glm::vec3 up = glm::vec3(0, 1, 0);
return Core::createViewMatrix(cameraPos, cameraDir, up);
}
void drawObject(GLuint program, Core::RenderContext context, glm::mat4 modelMatrix, glm::vec3 color)
{
glUniform3f(glGetUniformLocation(program, "objectColor"), color.x, color.y, color.z);
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
glUniformMatrix4fv(glGetUniformLocation(program, "transformation"), 1, GL_FALSE, (float*)&transformation);
Core::DrawContext(context);
}
glm::mat4 createCameraMatrix()
{
cameraDir = glm::normalize(glm::vec3(cosf(cameraAngle), 0, sinf(cameraAngle)));
glm::vec3 up = glm::vec3(0, 1, 0);
cameraSide = glm::cross(cameraDir, up);
PxTransform position = boxBodies[1]->getGlobalPose();
cameraPos.y = position.p.y - 5 + 19;
return Core::createViewMatrix(cameraPos, cameraDir, up);
}
void drawObjectColor(Core::RenderContext* context, glm::mat4 modelMatrix, glm::vec3 color)
{
GLuint program = programColor;
glUseProgram(program);
glUniform3f(glGetUniformLocation(program, "objectColor"), color.x, color.y, color.z);
glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z);
glUniform3f(glGetUniformLocation(program, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation);
glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
Core::DrawContext(*context);
glUseProgram(0);
}
void drawObjectTexture(Core::RenderContext* context, glm::mat4 modelMatrix, GLuint textureId)
{
GLuint program = programTexture;
glUseProgram(program);
glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z);
glUniform3f(glGetUniformLocation(program, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
Core::SetActiveTexture(textureId, "textureSampler", program, 0);
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation);
glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
Core::DrawContext(*context);
glUseProgram(0);
}
void shutdown()
{
shaderLoader.DeleteProgram(programColor);
shaderLoader.DeleteProgram(programTexture);
planeContext.initFromOBJ(planeModel);
boxContext.initFromOBJ(boxModel);
shipContext.initFromOBJ(shipModel);
boosterContext.initFromOBJ(boosterModel);
platformContext.initFromOBJ(platformModel);
craneContext.initFromOBJ(craneModel);
lampContext.initFromOBJ(lampModel);
}
void renderScene()
{
//start
if (!loading) {
double time = glutGet(GLUT_ELAPSED_TIME) / 1000.0 - appLoadingTime;
static double prevTime = time;
double dtime = time - prevTime;
prevTime = time;
// Update physics
if (dtime < 1.f) {
physicsTimeToProcess += dtime;
while (physicsTimeToProcess > 0) {
// here we perform the physics simulation step
pxScene.step(physicsStepTime);
physicsTimeToProcess -= physicsStepTime;
}
}
// Update of camera and perspective matrices
cameraMatrix = createCameraMatrix();
perspectiveMatrix = Core::createPerspectiveMatrix(0.1f, 1500.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.1f, 0.3f, 1.0f);
Skybox::drawSkybox(programSkybox, cameraMatrix, perspectiveMatrix, cubemapTexture);
// update transforms from physics simulation
updateTransforms();
if (time > 2 && time < 7) {
boxBodies[0]->setLinearVelocity(PxVec3(0, time * 0.8, 0));
boxBodies[1]->setLinearVelocity(PxVec3(0, time * 0.8, 0));
}
if (time > 7 && time < 15) {
boxBodies[1]->setLinearVelocity(PxVec3(0, 15, 0));
}
if (time > 15) {
loading = true;
lightDir = glm::normalize(glm::vec3(1.0f, -1.0f, -1.0f));
lightPos = glm::vec3(0, 0, -800);
cameraAngle = glm::radians(0.0f);
cameraPos = glm::vec3(0, 0, 250);
appLoadingTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
}
// render models
for (Renderable* renderable : renderables) {
drawObjectTexture(renderable->context, renderable->modelMatrix, renderable->textureId);
}
glutSwapBuffers();
}
//loading screen
else if (!reload) {
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.0f - appLoadingTime;
if (time < 3) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.1f, 0.3f, 1.0f);
//cameraMatrix = createCameraMatrixLoading();
// perspectiveMatrix = Core::createPerspectiveMatrix(0.1f, 1000.f);
Skybox::drawSkybox(programSkybox, cameraMatrix, perspectiveMatrix, cubemapTexture2);
glutSwapBuffers();
}
else {
reload = true;
lightDir = glm::normalize(glm::vec3(1.0f, -1.0f, -1.0f));
lightPos = glm::vec3(0, 0, -800);
cameraAngle = glm::radians(0.0f);
cameraPos = glm::vec3(0.f, 0.f, -250.f);
stationPos = glm::vec3(0.f, -0.65f, 245.5f);
appLoadingTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
}
}
//orbit
else if (!end)
{
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.0f - appLoadingTime;
// opcjonalny ruch swiatla do testow
bool animateLight = false;
if (animateLight) {
float lightAngle = (glutGet(GLUT_ELAPSED_TIME) / 1000.0f) * 3.14 / 8;
lightDir = glm::normalize(glm::vec3(sin(lightAngle), -1.0f, cos(lightAngle)));
}
// Aktualizacja macierzy widoku i rzutowania.
cameraMatrix = createCameraMatrixOrbit();
perspectiveMatrix = Core::createPerspectiveMatrix(0.1f, 1500.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.3f, 0.3f, 1.0f);
// skybox
Skybox::drawSkybox(programSkybox, cameraMatrix, perspectiveMatrix, cubemapTexture);
//SHIP
glm::mat4 shipModelOrbitMatrix = glm::translate(cameraPos + cameraDir * 4.f + glm::vec3(0, -0.25f, 0)) * glm::rotate(glm::orientedAngle(glm::vec3(0, 0, 1), cameraDir, glm::vec3(0, 1, 0)), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.2)) * glm::translate(glm::vec3(2, 0, 0));
drawObjectTexture(&shipContextOrbit, shipModelOrbitMatrix, textureShip);
//SUN
//drawObjectTexture(&sphereModelOrbit, glm::translate(glm::vec3(0, 0, 0)) * glm::scale(glm::vec3(20.f)), textureSun);
//STATION
glm::mat4 stationmat = glm::rotate(time / 5.0f, glm::vec3(0, 1, 0)) * glm::translate(stationPos) * glm::scale(glm::vec3(0.4)) * glm::rotate(glm::radians(-90.0f), glm::vec3(0, 1, 0));
drawObjectTexture(&stationContextOrbit, stationmat, shipTexture);
//stationmat = perspectiveMatrix * stationmat;
glm::vec3 stationPos = glm::vec3(stationmat[3][0], stationmat[3][1], stationmat[3][2]);
float distance = sqrt((cameraPos.x - stationPos.x)*(cameraPos.x - stationPos.x) + (cameraPos.z - stationPos.z)* (cameraPos.z - stationPos.z));
std::cout << "distance: " << distance << std::endl;
//std::cout << "cameraPos.x: " << cameraPos.x << "cameraPos.z: " << cameraPos.z <<std::endl;
//std::cout << "stationPos.x: " << stationPos.x << "stationPos.z: " << stationPos.z << std::endl;
if (distance < 5) {
end = true;
lightDir = glm::normalize(glm::vec3(1.0f, -1.0f, -1.0f));
lightPos = glm::vec3(0, 0, -800);
cameraAngle = glm::radians(0.0f);
cameraPos = glm::vec3(0, 0, 250);
appLoadingTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
}
//EARTH nieruchoma - <20>atwiejsze dla naszej cutscenki
drawObjectTexture(&sphereContextOrbit, glm::scale(glm::vec3(45)), textureEarthHighres);
//MOON
drawObjectTexture(&sphereContextOrbit, glm::rotate(time / 50.0f, glm::vec3(0, 1, 0)) * glm::translate(glm::vec3(0, 0, 300)) * glm::scale(glm::vec3(20)), textureMoon);
// sun
glUseProgram(programSun);
glUniform3f(glGetUniformLocation(programSun, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
glUniform3f(glGetUniformLocation(programSun, "cameraPos"), cameraPos.x, cameraPos.y, cameraPos.z);
drawObject(programSun, sphereContextOrbit, glm::translate(lightPos) * glm::scale(glm::vec3(10.f)), glm::vec3(1.0f, 0.8f, 0.2f));
glUseProgram(0);
glutSwapBuffers();
}
//end
else
{
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.0f - appLoadingTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.1f, 0.3f, 1.0f);
cameraMatrix = createCameraMatrixLoading();
perspectiveMatrix = Core::createPerspectiveMatrix(0.1f, 1500.f);
Skybox::drawSkybox(programSkybox, cameraMatrix, perspectiveMatrix, cubemapTexture3);
glutSwapBuffers();
}
}
void init()
{
srand(time(0));
glEnable(GL_DEPTH_TEST);
programColor = shaderLoader.CreateProgram("shaders/shader_color.vert", "shaders/shader_color.frag");
programTexture = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
programSkybox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag");
cubemapTexture = Skybox::loadCubemap(faces);
cubemapTexture2 = Skybox::loadCubemap(faces2);
cubemapTexture3 = Skybox::loadCubemap(faces3);
glEnable(GL_DEPTH_TEST);
programSun = shaderLoader.CreateProgram("shaders/shader_4_2.vert", "shaders/shader_4_2.frag");
shipModelOrbit = obj::loadModelFromFile("models/ship_orbita.obj");
shipContextOrbit.initFromOBJ(shipModelOrbit);
stationModelOrbit = obj::loadModelFromFile("models/spaceStation.obj");
stationContextOrbit.initFromOBJ(stationModelOrbit);
sphereModelOrbit = obj::loadModelFromFile("models/sphere.obj");
sphereContextOrbit.initFromOBJ(sphereModelOrbit);
textureShip = Core::LoadTexture("textures/ship.png");
textureEarthHighres = Core::LoadTexture("textures/4k_earth_daymap.png");
textureAsteroid = Core::LoadTexture("textures/asteroid.png");
textureSun = Core::LoadTexture("textures/2k_sun_texture.png");
textureMoon = Core::LoadTexture("textures/2k_moon.png");
programSkybox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag");
initRenderables();
initPhysicsScene();
appLoadingTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
}
void idle()
{
glutPostRedisplay();
}
void onReshape(int width, int height)
{
frustumScale = (float)width / height;
glViewport(0, 0, width, height);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(200, 200);
glutInitWindowSize(600, 600);
glutCreateWindow("Projekt GRK");
glewInit();
init();
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(mouse);
glutDisplayFunc(renderScene);
glutIdleFunc(idle);
glutReshapeFunc(onReshape);
glutMainLoop();
shutdown();
return 0;
}