#include "glew.h" #include "freeglut.h" #include "glm.hpp" #include "ext.hpp" #include #include #include #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 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 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 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 boxBodies; PxMaterial* boxMaterial = nullptr; // renderable objects (description of a single renderable instance) struct Renderable { Core::RenderContext* context; glm::mat4 modelMatrix; GLuint textureId; }; std::vector 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 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 <