486 lines
17 KiB
C++
486 lines
17 KiB
C++
#include <engine.h>
|
|
#include <SparrowInput/input.h>
|
|
#include <SparrowRenderer/scene.h>
|
|
#include <SparrowRenderer/mesh.h>
|
|
#include <SparrowRenderer/image.h>
|
|
#include <SparrowRenderer/deferredpipeline.h>
|
|
#include <SparrowRenderer/pbrmaterial.h>
|
|
#include <resourcemanager.h>
|
|
#include <SparrowRenderer/sparrowrenderer.h>
|
|
#include <SparrowRenderer/texture.h>
|
|
#include <SparrowRenderer/chunk.h>
|
|
#include "defaultkeysmap.h"
|
|
|
|
#include <scene/scenetree.h>
|
|
#include <scene/textnode.h>
|
|
#include <scene/trackballcameranode.h>
|
|
#include <scene/playercharacternode.h>
|
|
#include <scene/lightnode.h>
|
|
#include <scene/graphicalcontainernode.h>
|
|
#include <tools/graph.h>
|
|
#include <tools/pathfinder.h>
|
|
#include <tools/loader.h>
|
|
|
|
#include <tools/font.h>
|
|
#include <tools/utils.h>
|
|
|
|
#include <sparrowshell/sparrowshell.h>
|
|
#include <btBulletDynamicsCommon.h>
|
|
|
|
#include <glm/ext.hpp>
|
|
|
|
#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 <fstream>
|
|
|
|
#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<Mesh*> 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<Config*>& confVec = loader.getObjects<Config>();
|
|
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<DeferredPipeline*>(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<Mesh*> 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<GraphNode*> 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<Mesh*> meshes = Loader::loadMesh("sword.obj");
|
|
*/
|
|
|
|
|
|
}
|