From 9cfc6d581ad0f2f81343c8f91beba8e90d341616 Mon Sep 17 00:00:00 2001 From: Anselme Date: Mon, 19 Dec 2016 15:11:50 +0100 Subject: [PATCH] fixed plenty of bugs, added sponza, added jumping --- src/defaultkeysmap.h | 5 ++- src/engine.cpp | 23 +++++++--- src/engine.h | 5 +++ src/scene/lightnode.cpp | 2 + src/scene/playercharacternode.cpp | 46 +++++++++++++++++--- src/scene/playercharacternode.h | 4 +- src/test/main.cpp | 71 ++++++++++++++++++++++++++----- src/test/potator.cpp | 3 -- src/tools/loader.cpp | 11 ++++- src/tools/loader.h | 2 +- 10 files changed, 138 insertions(+), 34 deletions(-) diff --git a/src/defaultkeysmap.h b/src/defaultkeysmap.h index 97fc000..24f86b6 100644 --- a/src/defaultkeysmap.h +++ b/src/defaultkeysmap.h @@ -6,7 +6,7 @@ class DefaultKeysMap : public IKeysMap { public: - enum{MAIN_ACTION, SECONDARY_ACTION, TERTIARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, + enum{MAIN_ACTION, SECONDARY_ACTION, TERTIARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, JUMP, TOGGLE_NOCLIP, TOGGLE_PHYSICS_DEBUG, TOGGLE_CONSOLE, MOVE_CURSOR_LEFT, MOVE_CURSOR_RIGHT, PLOP_TEST, CLEAR_CONSOLE, EXIT_GAME,LAST_DEFAULT_ACTION}; @@ -19,6 +19,7 @@ public: keys.push_back( {MOVE_BACKWARD, sf::Keyboard::S, IKeysMap::HOLD} ); keys.push_back( {STRAFE_LEFT, sf::Keyboard::Q, IKeysMap::HOLD} ); keys.push_back( {STRAFE_RIGHT, sf::Keyboard::D, IKeysMap::HOLD} ); + keys.push_back( {JUMP, sf::Keyboard::Space, IKeysMap::PRESSED} ); keys.push_back( {TOGGLE_NOCLIP, sf::Keyboard::G, IKeysMap::PRESSED} ); keys.push_back( {TOGGLE_PHYSICS_DEBUG, sf::Keyboard::P, IKeysMap::PRESSED} ); keys.push_back( {TOGGLE_CONSOLE, sf::Keyboard::F3, IKeysMap::PRESSED} ); @@ -31,7 +32,7 @@ public: static std::vector getDefaultContext() { - return {MAIN_ACTION, SECONDARY_ACTION, TERTIARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_PHYSICS_DEBUG, TOGGLE_CONSOLE, EXIT_GAME}; + return {MAIN_ACTION, SECONDARY_ACTION, TERTIARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, JUMP, TOGGLE_NOCLIP, TOGGLE_PHYSICS_DEBUG, TOGGLE_CONSOLE, EXIT_GAME}; } static std::vector getShellContext() diff --git a/src/engine.cpp b/src/engine.cpp index c694c4a..0abae30 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -19,7 +19,9 @@ Engine::Engine() : m_physicsDebugNode(nullptr), m_togglePhysicsDebugAction(NO_ACTION), m_toggleShellAction(NO_ACTION), - m_exitGameAction(NO_ACTION) + m_exitGameAction(NO_ACTION), + m_showMouseAction(NO_ACTION), + m_mouseVisible(true) { m_clock = new sf::Clock(); m_clock->restart(); @@ -47,7 +49,7 @@ void Engine::createWindow(std::string title, { m_window = new sf::Window(sf::VideoMode(w, h), title, - isWindowed ? sf::Style::Close : sf::Style::Fullscreen, + isWindowed ? sf::Style::Close : sf::Style::None, sf::ContextSettings(24, 8, 0, 3, 3, sf::ContextSettings::Attribute::Core)); m_window->setFramerateLimit(60); m_input = new Input(m_window); @@ -158,6 +160,12 @@ void Engine::disablePhysicsDebug() } } +void Engine::toggleMouseVisibility() +{ + m_mouseVisible = !m_mouseVisible; + m_window->setMouseCursorVisible(m_mouseVisible); +} + void Engine::setTogglePhysicsDebugAction(int action) { m_togglePhysicsDebugAction = action; @@ -173,6 +181,11 @@ void Engine::setExitGameAction(int action) m_exitGameAction = action; } +void Engine::setShowMouseAction(int action) +{ + m_showMouseAction = action; +} + void Engine::outputShell(std::string str) const { m_sparrowshell->out(str); @@ -190,13 +203,11 @@ void Engine::checkSpecialInputs() disablePhysicsDebug(); } else if(action == m_toggleShellAction) - { m_sparrowshell->toggleShell(); - } else if(action == m_exitGameAction) - { m_running = false; - } + else if(action == m_showMouseAction) + toggleMouseVisibility(); } } diff --git a/src/engine.h b/src/engine.h index 772e55b..f3344a3 100644 --- a/src/engine.h +++ b/src/engine.h @@ -32,10 +32,13 @@ public: void enablePhysicsDebug(); void disablePhysicsDebug(); + void toggleMouseVisibility(); + // special inputs void setTogglePhysicsDebugAction(int action); void setToggleShellAction(int action); void setExitGameAction(int action); + void setShowMouseAction(int action); void start(); void stop(); @@ -73,6 +76,8 @@ private: int m_togglePhysicsDebugAction; int m_toggleShellAction; int m_exitGameAction; + int m_showMouseAction; + bool m_mouseVisible; void checkSpecialInputs(); }; diff --git a/src/scene/lightnode.cpp b/src/scene/lightnode.cpp index eef653c..18081c9 100644 --- a/src/scene/lightnode.cpp +++ b/src/scene/lightnode.cpp @@ -15,6 +15,8 @@ void LightNode::update() { DirectionnalLight *l = (DirectionnalLight*)m_light; l->setDir(glm::mat3(combinedTransform) * l->getDir()); + if(l->isShadowCaster()) + l->updateShadowMap(m_scene); } break; diff --git a/src/scene/playercharacternode.cpp b/src/scene/playercharacternode.cpp index 8ad8303..fc225f9 100644 --- a/src/scene/playercharacternode.cpp +++ b/src/scene/playercharacternode.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -51,10 +52,12 @@ void FirstPersonCamera::setUpVector(const glm::vec3 &up) computeView(); } -const float WALK_SPEED = 12.f; +const float WALK_SPEED = 8.f; const float PLAYER_RADIUS = 0.30f; const float PLAYER_HEIGHT = 1.75f; const float EYES_OFFSET = 0.775f; +const float JUMP_VELOCITY = 5.f; +const float EPSILON = 1.f; PlayerCharacterNode::PlayerCharacterNode(bool noClip) : m_noclipMode(noClip), @@ -75,18 +78,19 @@ PlayerCharacterNode::PlayerCharacterNode(bool noClip) : m_rigidBody->setAngularFactor(0.0); } -void PlayerCharacterNode::setInputs(int forward, int backward, int strafeLeft, int strafeRight, int toggleNoClip) +void PlayerCharacterNode::setInputs(int forward, int backward, int strafeLeft, int strafeRight, int jump, int toggleNoClip) { m_inputActions[FORWARD] = forward; m_inputActions[BACKWARD] = backward; m_inputActions[STRAFE_LEFT] = strafeLeft; m_inputActions[STRAFE_RIGHT] = strafeRight; + m_inputActions[JUMP] = jump; m_inputActions[TOGGLE_NOCLIP] = toggleNoClip; } void PlayerCharacterNode::setPosition(float x, float y, float z) { - btTransform transform; + btTransform transform = btTransform::getIdentity(); btVector3 pos(x, y, z); transform.setOrigin(pos); m_rigidBody->setWorldTransform(transform); @@ -100,6 +104,7 @@ void PlayerCharacterNode::update() // get events int walk = 0; int strafe = 0; + bool jump = false; for(int action : input->getActions()) { if(action == m_inputActions[FORWARD]) @@ -110,6 +115,8 @@ void PlayerCharacterNode::update() --strafe; else if(action == m_inputActions[STRAFE_RIGHT]) ++strafe; + else if(action == m_inputActions[JUMP]) + jump = true; else if(action == m_inputActions[TOGGLE_NOCLIP]) toggleNoClip(); } @@ -124,6 +131,8 @@ void PlayerCharacterNode::update() // update body movement const glm::vec3 &glmDir = m_fpsCamera.getDirection(); + const btVector3 &velocity = m_rigidBody->getLinearVelocity(); + btVector3 targetVelocity(0.f, velocity.getY(), 0.f); if(walk != 0 || strafe != 0) { glm::vec3 moveDir = glm::normalize(glmDir*walk + glm::cross(glmDir, glm::vec3(0, 1, 0))*strafe); @@ -134,19 +143,42 @@ void PlayerCharacterNode::update() } else { - //TODO: if on ground + space pressed -> jump glm::vec2 hPos = glm::normalize(glm::vec2(moveDir.x, moveDir.z))*WALK_SPEED; - const btVector3 &velocity = m_rigidBody->getLinearVelocity(); - m_rigidBody->setLinearVelocity((velocity + btVector3(hPos.x, velocity.getY(), hPos.y)) / 2.f); // smooth movements + targetVelocity.setX(hPos.x); + targetVelocity.setZ(hPos.y); } } + // apply movements if(m_noclipMode) { - btTransform transform; + btTransform transform = btTransform::getIdentity(); transform.setOrigin(m_noclip_pos); m_rigidBody->setWorldTransform(transform); m_rigidBody->setLinearVelocity(btVector3(0, 0, 0)); } + else + { + float controlRatio = 0.2f; // 1 = total control, 0 = no control, can be seen as a slipperiness factor + btVector3 newVelocity = velocity*(1.f-controlRatio) + targetVelocity*controlRatio; + if(jump) + {/* + btVector3 start(pos); + start.setY(start.y() - PLAYER_HEIGHT/2.f); + btVector3 end(pos); + end.setY(end.y() - EPSILON); + btCollisionWorld::ClosestRayResultCallback RayCallback(start, end); + getEngine().getPhysics()->rayTest(start, end, RayCallback); + if(RayCallback.hasHit()) // if ground is nearby + { + //btVector3 normal = RayCallback.m_hitNormalWorld; + + }*/ + + // raycasting not working yet + newVelocity.setY(JUMP_VELOCITY); + } + m_rigidBody->setLinearVelocity(newVelocity); + } } void PlayerCharacterNode::toggleNoClip() diff --git a/src/scene/playercharacternode.h b/src/scene/playercharacternode.h index 0c13e17..b430621 100644 --- a/src/scene/playercharacternode.h +++ b/src/scene/playercharacternode.h @@ -41,12 +41,12 @@ class PlayerCharacterNode : public CameraNode std::vector m_inputActions; - enum PlayerAction {FORWARD, BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP}; + enum PlayerAction {FORWARD, BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, JUMP, TOGGLE_NOCLIP}; public: PlayerCharacterNode(bool noClip = true); - void setInputs(int forward, int backward, int strafe_left, int strafe_right, int toggleNoClip = NO_ACTION); + void setInputs(int forward, int backward, int strafe_left, int strafe_right, int jump = NO_ACTION, int toggleNoClip = NO_ACTION); void setPosition(float x, float y, float z); diff --git a/src/test/main.cpp b/src/test/main.cpp index 9a15b19..80b5453 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -81,9 +81,9 @@ void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world) mat->specular = glm::vec3(0.1f); mat->emission = glm::vec3(0.5f, 0.1f, 0.1f); - for(int x=-6; x<6; ++x) - for(int y=-3; y<3; ++y) - for(int z=-6; z<6; ++z) + for(int x=-3; x<3; ++x) + for(int y=-2; y<2; ++y) + for(int z=-3; z<3; ++z) { Chunk *chunk = new Chunk(&gen); // ! WARNING ! : chunk pointer is lost and never deleted glm::vec3 pos(x, y, z); @@ -102,29 +102,59 @@ void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world) } } +void generateSponza(SceneTree *scene, btDiscreteDynamicsWorld *world) +{ + GraphicalContainerNode* sponzaContainer = new GraphicalContainerNode(); + scene->getRootObject()->addChild(sponzaContainer); + Loader::setTexDirectory("../data/sponza/"); + std::vector meshes = Loader::loadMesh("sponza.obj"); + Loader::setTexDirectory("../data/"); + for(Mesh* m : meshes) + { + if(m->getName().find("fabric") != std::string::npos) + delete m; // moyen crade de se débarasser temporairement des rideaux + else + { + m->initGL(); + MeshNode *node = new MeshNode(m); + node->setTransform(glm::scale(glm::mat4(), glm::vec3(0.01f))); + sponzaContainer->addChild(node); + world->addRigidBody(node->buildStaticCollider()); + } + } +} + int main(int argc, char** argv){ - enum Mode { SIMPLEST_TEST, TERRAIN_TEST, FULLSCREEN_DEMO }; + enum Mode { SIMPLEST_TEST, TERRAIN_TEST, SPONZA_TEST, FULLSCREEN_DEMO }; Mode mode = SIMPLEST_TEST; if(argc > 1) { std::string modeStr(argv[1]); if(modeStr == "terrain") mode = TERRAIN_TEST; + else if(modeStr == "sponza") + mode = SPONZA_TEST; else if(modeStr == "demo") mode = FULLSCREEN_DEMO; else if(modeStr == "simple") mode = SIMPLEST_TEST; else - std::cout << "AVAILABLE MODES : simple(default) / terrain / demo" << std::endl; + std::cout << "AVAILABLE MODES : simple(default) / terrain / sponza / demo" << std::endl; } Engine engine; + Loader::setObjDirectory("../data/"); + Loader::setMtlDirectory("../data/"); + Loader::setTexDirectory("../data/"); // this creates the opengl context // the opengl context must exist before any opengl class is used (texture, pipeline, etc..) - if(mode == FULLSCREEN_DEMO) - engine.createWindow("Sparrow Engine Testing Environment", 1920, 1080, false); + if(mode == FULLSCREEN_DEMO && mode == SPONZA_TEST) + { + engine.createWindow("Sparrow Engine Testing Environment", 1920, 1080, true); + engine.toggleMouseVisibility(); + } else engine.createWindow("Sparrow Engine Testing Environment"); @@ -161,10 +191,9 @@ int main(int argc, char** argv){ */ // first person player controller PlayerCharacterNode *player = new PlayerCharacterNode(false); - player->setInputs(DefaultKeysMap::MOVE_FORWARD, DefaultKeysMap::MOVE_BACKWARD, DefaultKeysMap::STRAFE_LEFT, DefaultKeysMap::STRAFE_RIGHT, DefaultKeysMap::TOGGLE_NOCLIP); + player->setInputs(DefaultKeysMap::MOVE_FORWARD, DefaultKeysMap::MOVE_BACKWARD, DefaultKeysMap::STRAFE_LEFT, DefaultKeysMap::STRAFE_RIGHT, DefaultKeysMap::JUMP, DefaultKeysMap::TOGGLE_NOCLIP); scene->getRootObject()->addChild(player); scene->setMainCamera(player); - player->setPosition(0.f, 15.f, 0.f); engine.getPhysics()->addRigidBody(player->getRigidbody()); // throw cubes and spheres with mouse clicks @@ -172,14 +201,34 @@ int main(int argc, char** argv){ scene->getRootObject()->addChild(potator); // lighting - LightNode *sunLight = new LightNode(new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(1.f))); LightNode *ambientLight = new LightNode(new AmbientLight()); + + DirectionnalLight* sun = new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(0.9f)); + LightNode *sunLight = new LightNode(sun); + + LightNode *fillLight = new LightNode(new DirectionnalLight(glm::vec3(8, -4, 1), glm::vec3(0.1f))); + scene->getRootObject()->addChild(ambientLight); scene->getRootObject()->addChild(sunLight); + scene->getRootObject()->addChild(fillLight); // terrain if(mode != SIMPLEST_TEST) - generateTerrain(scene, engine.getPhysics()); + { + sun->initShadowMap(4096); + if(mode == SPONZA_TEST) + { + generateSponza(scene, engine.getPhysics()); + player->setPosition(0.f, 2.f, 0.f); + sun->setShadowView(glm::vec3(30, 30, 50)); + } + else + { + generateTerrain(scene, engine.getPhysics()); + player->setPosition(0.f, 15.f, 0.f); + sun->setShadowView(glm::vec3(130, 130, 70)); + } + } // shell output tests engine.outputShell("Hello World!"); diff --git a/src/test/potator.cpp b/src/test/potator.cpp index 6cdf55d..8843840 100644 --- a/src/test/potator.cpp +++ b/src/test/potator.cpp @@ -66,9 +66,6 @@ Potator::Potator(PlayerCharacterNode * player, m_cubeMesh->addTriangle(id+7, id+5, id+6); } - Loader::setObjDirectory("../data/"); - Loader::setMtlDirectory("../data/"); - Loader::setTexDirectory("../data/"); Image* wood = Loader::loadImage("woodbox.jpg", false); PhongMaterial *mat = new PhongMaterial(); mat->setTexture(PhongMaterial::DIFFUSE_SLOT, new Texture(wood), "wood_texture"); diff --git a/src/tools/loader.cpp b/src/tools/loader.cpp index 39b7cc2..6b886d0 100644 --- a/src/tools/loader.cpp +++ b/src/tools/loader.cpp @@ -31,12 +31,14 @@ std::string* Loader::loadTextFile(const std::string &filename) return str; } -Image* Loader::loadImage(const std::string &filename, bool hasAlpha) +Image* Loader::loadImage(const std::string &filename, bool hasAlpha, bool reversed) { sf::Image sfImg; bool ok = sfImg.loadFromFile(tex_directory+filename); if(!ok) return NULL; + if(reversed) + sfImg.flipVertically(); Image* img = new Image(); img->depth = hasAlpha ? 32 : 24; img->width = sfImg.getSize().x; @@ -98,7 +100,7 @@ Font* Loader::loadFont(const std::string &description_file, const std::string &t font->addCharInfo(id,char_info); } - Image* fucking_image_of_doom = loadImage(texture_file); + Image* fucking_image_of_doom = loadImage(texture_file, true, false); if(fucking_image_of_doom == NULL) printf("can't load \"%s\".\n", texture_file.c_str()); Texture* texture = new Texture(fucking_image_of_doom, false); // mipmaps are doing a very bad job at interpolating alpha component @@ -229,6 +231,7 @@ std::vector Loader::loadMesh(const std::string &filename){ RESOURCE_ADD(currentMat,Material,material_name); } currentMesh->setMaterial(currentMat); + currentMesh->setName(material_name); } break; default: @@ -250,6 +253,10 @@ std::vector Loader::loadMesh(const std::string &filename){ else { Mesh* m = meshes[i]; + if(m->normals.empty()) + m->computeNormals(); + if(m->getFlags() & (1 << Mesh::MATERIAL_PHONG_NORMAL_MAP)) + m->computeTangents(); m->mergeVertices(); } } diff --git a/src/tools/loader.h b/src/tools/loader.h index 04b0523..1abad52 100644 --- a/src/tools/loader.h +++ b/src/tools/loader.h @@ -17,7 +17,7 @@ class Loader public: static std::string* loadTextFile(const std::string &filename); - static Image* loadImage(const std::string &filename, bool hasAlpha = true); + static Image* loadImage(const std::string &filename, bool hasAlpha = true, bool reversed = true); static std::vector loadMesh(const std::string &filename); static Font* loadFont(const std::string &texture, const std::string &description); static bool loadMTL(const std::string &filename);