#include #include #include #include #include #include #include #include #include #include #include #include "defaultkeysmap.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "scene/gui/buttonnode.h" #include "scene/gui/buttonshape.h" #include "scene/gui/backgroundnode.h" #include "potator.h" #include "SparrowSerializer/serializationmanager.h" #include "SparrowSerializer/serializable.h" #include #include "resourcemanager.h" #include "scene/gui/callback.h" class TestGen : public TerrainGenerator { float map[64*64]; public: TestGen() { for(int i=0; i<64*64; ++i) map[i] = (rand()%64)/64.f; } float getHeight(float x, float z, float zoom) { x /= zoom; z /= zoom; int i1 = int(floor(x)+64)%64; int j1 = int(floor(z)+64)%64; int i2 = (i1+1)%64; int j2 = (j1+1)%64; float v1 = map[i1*64+j1]; float v2 = map[i2*64+j1]; float v3 = map[i1*64+j2]; float v4 = map[i2*64+j2]; float ph = x - floor(x); float pv = z - floor(z); ph = 0.5f-cos(3.1416*ph)/2; pv = 0.5f-cos(3.1416*pv)/2; float v5 = v1*(1-ph) + v2*ph; float v6 = v3*(1-ph) + v4*ph; return (v5*(1-pv) + v6*pv)*zoom; } virtual float func(float x, float y, float z) { float height = getHeight(x+6.7, z+15.7, 2.5f); height += getHeight(x+5.76, z+2.14, 5.4f); height += getHeight(x, z, 10.f); return y+8.f - height; } }; void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world) { GraphicalContainerNode* terrainContainer = new GraphicalContainerNode(); scene->getRootObject()->addChild(terrainContainer); TestGen gen; PBRMaterial *mat = new PBRMaterial(); mat->albedo = glm::vec3(0.1f, 0.4f, 0.2f); mat->metallic = 0.2f; mat->roughness = 0.95f; 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); chunk->generate(pos); if(chunk->mesh->positions3D.empty()) delete chunk; else { chunk->mesh->setMaterial(mat); chunk->mesh->initGL(); MeshNode *node = new MeshNode(chunk->mesh); node->setTransform(glm::translate(glm::scale(glm::mat4(), glm::vec3(2.f)), pos*8.f)); terrainContainer->addChild(node); world->addRigidBody(node->buildStaticCollider()); } } } 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()); } } } struct Config : public Serializable { P_STRING(mode) // fullscreen / windowed / borderless P_STRING(scene) // terrain / sponza / none P_BOOL(vsync) P_INT(width) P_INT(height) SERIALIZABLE(Config, CAST(mode), CAST(scene), CAST(vsync), CAST(width), CAST(height)) Config() { mode = "windowed"; scene = "sandbox"; vsync = false; width = 800; height = 600; } static Config* load() { std::fstream configFile; configFile.open("config.ini", std::ios_base::in); Config *conf; if(configFile.is_open()) { ObjectLoader loader; loader.loadAscii(configFile); configFile.close(); const std::vector& confVec = loader.getObjects(); if(confVec.size() != 0) conf = confVec[0]; else conf = new Config(); } else conf = new Config(); ObjectSaver saver; saver.addObject(conf); configFile.open("config.ini", std::ios_base::out); saver.saveAscii(configFile); configFile.close(); return conf; } }; class Demo { std::string m_demo_scene; Engine* m_engine; Config* m_config; PlayerCharacterNode* m_player; public: Demo(Engine* engine,Config* config):m_demo_scene("demo"),m_engine(engine),m_config(config){ m_engine->createScene(m_demo_scene); } void initScene(){ //player m_player = new PlayerCharacterNode(false); m_player->setInputs(DefaultKeysMap::MOVE_FORWARD, DefaultKeysMap::MOVE_BACKWARD, DefaultKeysMap::STRAFE_LEFT, DefaultKeysMap::STRAFE_RIGHT, DefaultKeysMap::JUMP, DefaultKeysMap::RUN, DefaultKeysMap::TOGGLE_NOCLIP); SceneTree* scene = RESOURCE_GET(SceneTree, m_demo_scene); scene->getRootObject()->addChild(m_player); scene->setMainCamera(m_player); //potator Potator *potator = new Potator(m_player, DefaultKeysMap::MAIN_ACTION, DefaultKeysMap::SECONDARY_ACTION, DefaultKeysMap::TERTIARY_ACTION); scene->getRootObject()->addChild(potator); //lighting Texture* skyboxTexture = RESOURCE_GET(Texture, "radiance"); Texture* ambientTexture = RESOURCE_GET(Texture, "irradiance"); LightNode *ambientLight = new LightNode(new AmbientLight(ambientTexture, skyboxTexture)); DeferredPipeline* pipeline = dynamic_cast(scene->getPipeline()); pipeline->setSkybox(RESOURCE_GET(Texture, "skybox")); DirectionnalLight* sun = new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(4.f)); LightNode *sunLight = new LightNode(sun); scene->getRootObject()->addChild(ambientLight); if(m_config->scene == "sponza") { sun->initShadowMap(4096); generateSponza(scene, m_engine->getPhysics()); scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-3.5, 2, 1.8), 15, glm::vec3(0.35f)))); scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-5, 6, 2), 15, glm::vec3(0.35f)))); m_player->setPosition(0.f, 2.f, 0.f); sun->setShadowView(glm::vec3(30, 30, 50)); } else if(m_config->scene == "terrain") { sun->initShadowMap(4096); generateTerrain(scene, m_engine->getPhysics()); m_player->setPosition(0.f, 15.f, 0.f); sun->setShadowView(glm::vec3(130, 130, 70)); } else if(m_config->scene == "sandbox") { sun->initShadowMap(4096); GraphicalContainerNode* sandboxContainer = new GraphicalContainerNode(); scene->getRootObject()->addChild(sandboxContainer); std::vector meshes = Loader::loadMesh("sandbox.obj"); for(Mesh* m : meshes) { m->initGL(); MeshNode *node = new MeshNode(m); sandboxContainer->addChild(node); m_engine->getPhysics()->addRigidBody(node->buildStaticCollider()); } m_player->setPosition(0.f, 1.4f, 0.f); sun->setShadowView(glm::vec3(80)); } scene->getRootObject()->addChild(sunLight); } std::string getScene(){return m_demo_scene;} PlayerCharacterNode* getPlayer(){return m_player;} }; class ButtonDemoCallBack : public CallBack { Engine* m_engine; Demo* m_demo; public: ButtonDemoCallBack(Engine* engine, Demo* demo):m_engine(engine),m_demo(demo){} void exec(){ m_demo->initScene(); m_engine->setScene(m_demo->getScene()); m_engine->getInput()->setCurrentContext("default"); m_engine->getInput()->setMouseGrabbed(true); m_engine->getPhysics()->addRigidBody(m_demo->getPlayer()->getRigidbody()); m_engine->toggleMouseVisibility(); } }; class Menu { int m_left_click_action; ButtonNode* m_button_demo; std::string m_menu_scene; public: Menu(Engine* engine,Config* config):m_menu_scene("menu"){ engine->createScene(m_menu_scene); SceneTree* scene = RESOURCE_GET(SceneTree,m_menu_scene); m_button_demo = new ButtonNode(new RectangleButtonShape(glm::vec2(300,100))); m_button_demo->getLabel()->setText("Start DEMO"); m_button_demo->getLabel()->setColor(glm::vec3(1.,1.,1.)); m_button_demo->getBackGround()->setColor(glm::vec3(0.88,0.05,0.05)); scene->getRootObject()->addChild(m_button_demo); sf::Vector2u size = engine->getWindow()->getSize(); glm::vec2 pos = glm::vec2(size.x,size.y)/glm::vec2(2,2) - m_button_demo->getDimension()/glm::vec2(2,2); m_button_demo->setPosition(pos); m_button_demo->setVisible(true); } void setLeftClickAction(int action){ m_left_click_action = action; m_button_demo->setAction(m_left_click_action); } void setButtonCallBack(ButtonDemoCallBack* button_callback){ m_button_demo->setCallBack(button_callback); } std::string getScene(){return m_menu_scene;} }; INIT_SERIALIZABLE(Config) int main(){ Config* config = Config::load(); 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..) engine.createWindow("Sparrow Engine Demo", config->width, config->height, config->mode); engine.getWindow()->setVerticalSyncEnabled(config->vsync); // opengl context is created, we can initialize the global textures used by the rendering pipeline Image* img = Loader::loadImage("ibl_brdf_lut.png", 24, true); AmbientLight::setBrdfLut(new Texture(img)); delete img; Image * imgs[6]; imgs[0] = Loader::loadImage("skybox/posx.jpg", 24, false); // right imgs[1] = Loader::loadImage("skybox/negx.jpg", 24, false); // left imgs[2] = Loader::loadImage("skybox/posy.jpg", 24, false); // top imgs[3] = Loader::loadImage("skybox/negy.jpg", 24, false); // bottom imgs[4] = Loader::loadImage("skybox/posz.jpg", 24, false); // front imgs[5] = Loader::loadImage("skybox/negz.jpg", 24, false); // back RESOURCE_ADD(new Texture(imgs), Texture, "skybox"); for(int i=0; i<6; ++i) delete imgs[i]; imgs[0] = Loader::loadImage("skybox/irradiance/output_iem_posx.tga", 24, false); // right imgs[1] = Loader::loadImage("skybox/irradiance/output_iem_negx.tga", 24, false); // left imgs[2] = Loader::loadImage("skybox/irradiance/output_iem_posy.tga", 24, false); // top imgs[3] = Loader::loadImage("skybox/irradiance/output_iem_negy.tga", 24, false); // bottom imgs[4] = Loader::loadImage("skybox/irradiance/output_iem_posz.tga", 24, false); // front imgs[5] = Loader::loadImage("skybox/irradiance/output_iem_negz.tga", 24, false); // back RESOURCE_ADD(new Texture(imgs, false), Texture, "irradiance"); for(int i=0; i<6; ++i) delete imgs[i]; imgs[0] = Loader::loadImage("skybox/radiance/output_pmrem_posx_0_256x256.tga", 24, false); // right imgs[1] = Loader::loadImage("skybox/radiance/output_pmrem_negx_0_256x256.tga", 24, false); // left imgs[2] = Loader::loadImage("skybox/radiance/output_pmrem_posy_0_256x256.tga", 24, false); // top imgs[3] = Loader::loadImage("skybox/radiance/output_pmrem_negy_0_256x256.tga", 24, false); // bottom imgs[4] = Loader::loadImage("skybox/radiance/output_pmrem_posz_0_256x256.tga", 24, false); // front imgs[5] = Loader::loadImage("skybox/radiance/output_pmrem_negz_0_256x256.tga", 24, false); // back RESOURCE_ADD(new Texture(imgs), Texture, "radiance"); for(int i=0; i<6; ++i) delete imgs[i]; // engine.toggleMouseVisibility(); // setting up SparrowEngine engine.initPhysics(); // SceneTree *scene = engine.createScene(); // engine.setScene(scene); // settin gup SparrowInput Input* input = engine.getInput(); input->setKeysMap(DefaultKeysMap()); input->addContext(Context("default", DefaultKeysMap::getDefaultContext())); input->setCurrentContext("default"); input->updateKeyBindings(); engine.setTogglePhysicsDebugAction(DefaultKeysMap::TOGGLE_PHYSICS_DEBUG); engine.setToggleShellAction(DefaultKeysMap::TOGGLE_CONSOLE); engine.setExitGameAction(DefaultKeysMap::EXIT_GAME); engine.setShowMouseAction(DefaultKeysMap::TOGGLE_MOUSE_CURSOR); //c'est un goup SparrowShell SparrowShell* shell = engine.getShell(); shell->setInputs(DefaultKeysMap::MOVE_CURSOR_LEFT,DefaultKeysMap::MOVE_CURSOR_RIGHT,DefaultKeysMap::HISTORY_UP,DefaultKeysMap::HISTORY_DOWN); input->addContext(Context("shell",DefaultKeysMap::getShellContext())); input->updateKeyBindings(); //setup menu Menu* menu = new Menu(&engine,config); Demo* demo = new Demo(&engine,config); menu->setLeftClickAction(DefaultKeysMap::LEFT_CLICK); input->addContext(Context("menu",DefaultKeysMap::getMenuContext())); input->setCurrentContext("menu"); input->updateKeyBindings(); menu->setButtonCallBack(new ButtonDemoCallBack(&engine,demo)); engine.setScene(menu->getScene()); engine.getInput()->setMouseGrabbed(false); /* // trackball camera TrackBallCameraNode *trackBallCam = new TrackBallCameraNode(engine.getInput()); trackBallCam->setInputs(myKeysMap::SECONDARY_HOLD, myKeysMap::MAIN_HOLD); scene.getRootObject()->addChild(trackBallCam); scene.setMainCamera(trackBallCam); // first person player controller PlayerCharacterNode *player = new PlayerCharacterNode(false); 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); engine.getPhysics()->addRigidBody(player->getRigidbody()); // throw cubes and spheres with mouse clicks Potator *potator = new Potator(player, DefaultKeysMap::MAIN_ACTION, DefaultKeysMap::SECONDARY_ACTION, DefaultKeysMap::TERTIARY_ACTION); scene->getRootObject()->addChild(potator); // lighting LightNode *ambientLight = new LightNode(new AmbientLight(glm::vec3(0.05f))); DirectionnalLight* sun = new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(0.9f)); LightNode *sunLight = new LightNode(sun); scene->getRootObject()->addChild(ambientLight); scene->getRootObject()->addChild(sunLight); */ // scene /* if(config.scene == "sponza") { sun->initShadowMap(4096); generateSponza(scene, engine.getPhysics()); scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-3.5, 2, 1.8), 15, glm::vec3(0.35f)))); scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-5, 6, 2), 15, glm::vec3(0.35f)))); player->setPosition(0.f, 2.f, 0.f); sun->setShadowView(glm::vec3(30, 30, 50)); } else if(config->scene == "terrain") { sun->initShadowMap(4096); generateTerrain(scene, engine.getPhysics()); player->setPosition(0.f, 15.f, 0.f); sun->setShadowView(glm::vec3(130, 130, 70)); }*/ // shell output tests engine.getShell()->out("Hello World!"); engine.getShell()->out("Starting test :"); // engine.getScene()->updateShaders(); // BackGroundNode* bgrn = new BackGroundNode(glm::vec2(10),glm::vec3(1.,1.,1.),1,1); // engine.getScene()->getRootObject()->addChild(bgrn); // preparing shaders and launching the engine engine.start(); // pathfinding tests /* GraphNode n1 = GraphNode(); n1.setValue(1); GraphNode n2 = GraphNode(); n2.setValue(2); GraphNode n3 = GraphNode(); n3.setValue(3); GraphNode n4 = GraphNode(); n4.setValue(4); GraphNode n5 = GraphNode(); n5.setValue(5); n1.addNeighbours(&n2); n1.addNeighbours(&n3); n2.addNeighbours(&n4); n3.addNeighbours(&n4); n3.addNeighbours(&n2); n3.addNeighbours(&n5); std::vector path = PathFinder::a_star(&n1,&n4,true); std::cout << "Path Size: " << path.size() << std::endl; for(GraphNode* gn: path){ std::cout << gn->getValue() << std::endl; } // loaders tests Loader::setObjDirectory("data/"); Loader::setMtlDirectory("data/"); Loader::setTexDirectory("data/"); std::vector meshes = Loader::loadMesh("sword.obj"); */ }