Projekt_Grafika/src/main_8_1.cpp

297 lines
9.5 KiB
C++

#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"
Core::Shader_Loader shaderLoader;
GLuint programColor;
GLuint programTexture;
GLuint programSkybox;
GLuint cubemapTexture;
GLuint skyboxVAO, skyboxVBO;
obj::Model planeModel;
obj::Model boxModel;
obj::Model shipModel;
obj::Model boosterModel;
obj::Model platformModel;
obj::Model craneModel;
obj::Model lampModel;
glm::mat4 boxModelMatrix;
GLuint boxTexture, groundTexture, shipTexture, stoneTexture, redTex;
Core::RenderContext planeContext, boxContext, shipContext, boosterContext, platformContext, craneContext, lampContext;
glm::vec3 cameraPos = glm::vec3(0, 10, 25);
glm::vec3 cameraDir;
glm::vec3 cameraSide;
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);
// Initalization of physical scene (PhysX)
Physics pxScene(9.8f /* gravity (m/s^2) */);
// fixed timestep for stable and deterministic simulation
const double physicsStepTime = 1.f / 60.f;
double physicsTimeToProcess = 0;
// physical objects
PxRigidStatic *planeBody = nullptr;
PxMaterial *planeMaterial = nullptr;
PxRigidDynamic *boxBody = nullptr;
PxMaterial *boxMaterial = nullptr;
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",
};
void initRenderables()
{
// load models
planeModel = obj::loadModelFromFile("models/plane.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");
// 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");
planeContext.initFromOBJ(planeModel);
boxContext.initFromOBJ(boxModel);
shipContext.initFromOBJ(shipModel);
boosterContext.initFromOBJ(boosterModel);
platformContext.initFromOBJ(platformModel);
craneContext.initFromOBJ(craneModel);
lampContext.initFromOBJ(lampModel);
}
void initPhysicsScene()
{
}
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 proper model matrices.
if (!actor->userData) continue;
glm::mat4 *modelMatrix = (glm::mat4*)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
*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.1f;
float moveSpeed = 0.5f;
switch (key)
{
case 'z': cameraAngle -= angleSpeed; break;
case 'x': cameraAngle += angleSpeed; break;
case 'w': cameraPos += cameraDir * moveSpeed; break;
case 's': cameraPos -= cameraDir * moveSpeed; break;
case 'd': cameraPos += cameraSide * moveSpeed; break;
case 'a': cameraPos -= cameraSide * moveSpeed; break;
case 'e': cameraPos += glm::cross(cameraDir, glm::vec3(1, 0, 0)) * moveSpeed; break;
case 'q': cameraPos -= glm::cross(cameraDir, glm::vec3(1, 0, 0)) * moveSpeed; break;
}
}
void mouse(int x, int y)
{
}
glm::mat4 createCameraMatrix()
{
cameraDir = glm::normalize(glm::vec3(cosf(cameraAngle - glm::radians(90.0f)), 0, sinf(cameraAngle - glm::radians(90.0f))));
glm::vec3 up = glm::vec3(0, 1, 0);
cameraSide = glm::cross(cameraDir, up);
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);
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 renderScene()
{
double time = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
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, 1000.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.1f, 0.3f, 1.0f);
glUseProgram(programTexture);
// Drawing skybox
Skybox::drawSkybox(programSkybox, cameraMatrix, perspectiveMatrix, cubemapTexture);
glUniform3f(glGetUniformLocation(programTexture, "lightPos"), 0, 0, 0);
// update transforms from physics simulation
updateTransforms();
// render models
drawObjectTexture(planeContext, glm::translate(glm::vec3(0, 0, 0)), groundTexture);
drawObjectTexture(shipContext, glm::translate(glm::vec3(0,3,0)), shipTexture); // boxModelMatrix was updated in updateTransforms()
drawObjectTexture(boosterContext, glm::translate(glm::vec3(0, 3, 0)), shipTexture);
drawObjectTexture(platformContext, glm::rotate(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)), stoneTexture);
drawObjectTexture(craneContext, glm::rotate(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)), redTex);
drawObjectColor(lampContext, glm::translate(glm::vec3(lightPos)) * glm::rotate(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)), glm::vec3(1, 1, 1));
glutSwapBuffers();
}
void init()
{
srand((unsigned int)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);
initRenderables();
initPhysicsScene();
}
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 idle()
{
glutPostRedisplay();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(200, 200);
glutInitWindowSize(600, 600);
glutCreateWindow("Projekt");
glewInit();
init();
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(mouse);
glutDisplayFunc(renderScene);
glutIdleFunc(idle);
glutMainLoop();
shutdown();
return 0;
}