This commit is contained in:
Lendemor 2016-12-12 23:20:28 +01:00
commit c105feeee9
25 changed files with 697 additions and 223 deletions

View File

@ -9,7 +9,7 @@ set(EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/src)
# choose source file
file(GLOB LIB_SRC_LIST src/*.cpp src/tools/*.cpp src/scene/*.cpp src/sparrowshell/*.cpp)
file(GLOB LIB_HEAD_LIST src/*.h src/tools/*.h src/scene/*.h src/sparrowshell/*.h)
set(EXEC_SRC_LIST src/test/main.cpp)
file(GLOB EXEC_SRC_LIST src/test/*.cpp)
#set compilation option
set(IS_LIBRARY True)

View File

@ -10,11 +10,14 @@
#include "resourcemanager.h"
#include "scene/scenetree.h"
#include "sparrowshell/sparrowshell.h"
#include "scene/physicsdebugnode.h"
Engine::Engine() :
m_window(NULL),
m_input(NULL),
m_world(NULL)
m_window(nullptr),
m_input(nullptr),
m_world(nullptr),
m_physicsDebugNode(nullptr),
m_togglePhysicsDebugAction(NO_ACTION)
{
m_clock = new sf::Clock();
m_clock->restart();
@ -67,12 +70,22 @@ void Engine::update()
m_timeStamp = (unsigned int) m_clock->getElapsedTime().asMilliseconds();
// update Events
m_input->updateEvents();
checkSpecialInputs();
// update Physics
if(m_world != nullptr)
{
m_world->stepSimulation(1000.f*(float)getDeltaTime());
if(m_physicsDebugNode != nullptr)
{
m_physicsDebugNode->clearBuffers();
m_world->debugDrawWorld();
}
}
// update Scene
m_scene->update();
// update Physics
if(m_world != NULL)
m_world->stepSimulation(1000.f*(float)getDeltaTime());
// update Display
if(m_input->isResized())
m_renderer->resizeGL(m_window->getSize().x, m_window->getSize().y);
@ -94,18 +107,24 @@ void Engine::stop()
m_running = false;
}
unsigned int Engine::getTime()
unsigned int Engine::getTime() const
{
return m_timeStamp;
}
unsigned int Engine::getDeltaTime()
unsigned int Engine::getDeltaTime() const
{
return m_timeStamp - m_lastTimeStamp;
}
void Engine::setScene(SceneTree *scene)
{
if(m_physicsDebugNode != nullptr)
{
m_scene->removeFromIndex(m_physicsDebugNode);
scene->addToIndex(m_physicsDebugNode);
}
scene->getRootObject()->removeChild(m_sparrowshell);
m_scene = scene;
m_renderer->setScene(m_scene);
m_renderer->resizeGL(m_window->getSize().x, m_window->getSize().y);
@ -114,7 +133,56 @@ void Engine::setScene(SceneTree *scene)
scene->updateShaders();
}
void Engine::outputShell(std::string str)
void Engine::enablePhysicsDebug()
{
if(m_world != nullptr && m_physicsDebugNode == nullptr)
{
m_physicsDebugNode = new PhysicsDebugNode();
m_scene->addToIndex(m_physicsDebugNode);
m_world->setDebugDrawer(m_physicsDebugNode);
m_world->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
m_scene->updateShaders();
}
}
void Engine::disablePhysicsDebug()
{
if(m_world != nullptr && m_physicsDebugNode != nullptr)
{
m_world->setDebugDrawer(nullptr);
m_scene->removeFromIndex(m_physicsDebugNode);
delete m_physicsDebugNode;
m_physicsDebugNode = nullptr;
}
}
void Engine::setTogglePhysicsDebugAction(int action)
{
m_togglePhysicsDebugAction = action;
}
void Engine::outputShell(std::string str) const
{
m_sparrowshell->out(str);
}
void Engine::checkSpecialInputs()
{
for(int action : m_input->getActions())
{
if(action == m_togglePhysicsDebugAction)
{
if(m_physicsDebugNode == nullptr)
enablePhysicsDebug();
else
disablePhysicsDebug();
}
}
}
SceneTree* Engine::createScene()
{
return new SceneTree(*this);
}

View File

@ -7,6 +7,7 @@ class Input;
class SparrowRenderer;
class SceneTree;
class SparrowShell;
class PhysicsDebugNode;
namespace sf
{
@ -28,18 +29,24 @@ public:
void setScene(SceneTree *scene);
void initPhysics();
void enablePhysicsDebug();
void disablePhysicsDebug();
void setTogglePhysicsDebugAction(int action);
void start();
void stop();
Input* getInput() {return m_input;}
sf::Window* getWindow(){return m_window;}
SparrowRenderer* getRenderer() {return m_renderer;}
btDiscreteDynamicsWorld* getPhysics() {return m_world;}
Input* getInput() const {return m_input;}
sf::Window* getWindow() const {return m_window;}
SparrowRenderer* getRenderer() const {return m_renderer;}
btDiscreteDynamicsWorld* getPhysics() const {return m_world;}
void outputShell(std::string str);
void outputShell(std::string str) const;
unsigned int getTime();
unsigned int getDeltaTime();
unsigned int getTime() const;
unsigned int getDeltaTime() const;
SceneTree* createScene();
private:
sf::Clock* m_clock;
@ -53,9 +60,13 @@ private:
SceneTree* m_scene;
SparrowShell* m_sparrowshell;
btDiscreteDynamicsWorld* m_world;
PhysicsDebugNode *m_physicsDebugNode;
int m_togglePhysicsDebugAction;
SparrowRenderer* m_renderer;
void update();
void checkSpecialInputs();
};
#endif

View File

@ -1,4 +1,11 @@
#include "containernode.h"
#include <iostream>
ContainerNode::~ContainerNode()
{
for(SceneNode *child : m_children)
delete child;
}
// Container Node
void ContainerNode::update()
@ -21,14 +28,17 @@ void ContainerNode::removeChild(SceneNode* node)
{
if(node != nullptr)
{
for(auto it = m_children.begin(); it != m_children.end(); ++it)
for(auto it = m_children.begin(); it != m_children.end();)
{
if(*it == node)
{
m_children.erase(it);
it = m_children.erase(it);
node->m_parent = nullptr;
node->setSceneTree(nullptr);
// break;
}
else
++it;
}
}
}

View File

@ -10,6 +10,8 @@
class ContainerNode : public SceneNode
{
public:
virtual ~ContainerNode();
virtual void update();
/**
* @brief addChild adds node in the ContainerNode's children list

View File

@ -0,0 +1,52 @@
#include "gibgeneratornode.h"
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include "scenetree.h"
#include "graphicalnode.h"
void GibGeneratorNode::createGib(GraphicalNode* graphicalPart,
btCollisionShape *physicsShape,
float mass,
const glm::vec3 &pos,
const glm::vec3 &velocity,
unsigned int lifeSpan)
{
if(m_scene != nullptr)
{
graphicalPart->moveTo(pos);
// Create the rigid body object
btMotionState *motionState = graphicalPart->getMotionState();
btVector3 localInertia;
physicsShape->calculateLocalInertia(mass, localInertia);
btRigidBody *body = new btRigidBody(mass, motionState, physicsShape, localInertia);
body->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
getEngine().getPhysics()->addRigidBody(body);
m_gibs.push_back(new Gib(body, graphicalPart, getEngine().getTime()+lifeSpan));
addChild(graphicalPart);
m_scene->updateShaders(); // TODO : optimisations needed
}
}
void GibGeneratorNode::update()
{
// TODO : optimisation possible : use some kind of heap stack structure instead of vector
for(auto it = m_gibs.begin(); it != m_gibs.end();)
{
Gib *g = *it;
if(g->expiration < getEngine().getTime())
{
removeChild(g->graphics);
delete g->graphics;
it = m_gibs.erase(it);
getEngine().getPhysics()->removeCollisionObject(g->body);
delete g;
}
else
++it;
}
for(SceneNode* child : m_children)
child->update();
}

View File

@ -0,0 +1,45 @@
#ifndef GIBGENERATORNODE_H
#define GIBGENERATORNODE_H
#include "containernode.h"
#include <glm/vec3.hpp>
#include <BulletDynamics/Dynamics/btRigidBody.h>
class btCollisionShape;
class btRigidBody;
class GraphicalNode;
class GibGeneratorNode : public ContainerNode
{
struct Gib
{
btRigidBody* body;
GraphicalNode* graphics;
unsigned int expiration;
Gib(btRigidBody* b, GraphicalNode* g, unsigned int e) :
body(b),
graphics(g),
expiration(e)
{}
~Gib()
{
delete body;
}
};
std::vector<Gib*> m_gibs;
public:
void createGib(GraphicalNode* graphicalPart,
btCollisionShape *physicsShape,
float mass,
const glm::vec3 &pos = glm::vec3(0),
const glm::vec3 &velocity = glm::vec3(0),
unsigned int lifeSpan = 5000);
virtual void update();
};
#endif // GIBGENERATORNODE_H

View File

@ -1,4 +1,12 @@
#include "graphicalcontainernode.h"
#include "scenetree.h"
GraphicalContainerNode::~GraphicalContainerNode()
{
setVisible(false); // renderer de-indexing
for(GraphicalNode* child : m_children)
delete child;
}
void GraphicalContainerNode::update()
{
@ -15,7 +23,7 @@ void GraphicalContainerNode::update()
void GraphicalContainerNode::setSceneTree(SceneTree* tree)
{
SceneNode::setSceneTree(tree);
for(auto child : m_children)
for(GraphicalNode* child : m_children)
child->setSceneTree(tree);
}
@ -27,6 +35,8 @@ void GraphicalContainerNode::addChild(GraphicalNode *node)
node->setSceneTree(m_scene);
m_children.push_back(node);
node->m_parent = this;
node->setParentTransform(m_transform);
node->setParentVisible(isVisible());
}
}
@ -44,3 +54,9 @@ void GraphicalContainerNode::removeChild(GraphicalNode *node)
}
}
}
void GraphicalContainerNode::updateVisibility(bool visible)
{
for(GraphicalNode* child : m_children)
child->setParentVisible(visible);
}

View File

@ -12,10 +12,14 @@ protected:
glm::mat4 m_combinedTransform;
public:
virtual ~GraphicalContainerNode();
virtual void update();
virtual void setSceneTree(SceneTree* tree);
virtual void updateVisibility(bool visible);
void addChild(GraphicalNode* node);
void removeChild(GraphicalNode* node);
};

View File

@ -4,22 +4,14 @@
#include <iostream>
void GraphicalNode::setSceneTree(SceneTree *tree){
SceneNode::setSceneTree(tree);
if(tree && m_visible)
tree->addToIndex(this);
}
void GraphicalNode::toggleVisibility(){
if(!m_scene){
std::cout << "Warning: trying to toggle a node before m_scene was initialized"<< std::endl;
return;
}
m_visible = !m_visible;
if(m_visible){
m_scene->addToIndex(this);
}else{
m_scene->removeFromIndex(this);
if(isVisible())
{
if(m_scene != nullptr)
m_scene->removeFromIndex(this);
if(tree != nullptr)
tree->addToIndex(this);
}
m_scene = tree;
}
// tools
@ -67,3 +59,52 @@ void GraphicalNode::setParentTransform(const glm::mat4 &transform)
m_parentTransform = transform;
m_transformChanged = true;
}
void GraphicalNode::toggleVisibility()
{
setVisible(!m_visible);
}
void GraphicalNode::setVisible(bool visible)
{
if(m_parentVisible)
{
if(m_visible && !visible)
updateVisibility(false);
if(visible && !m_visible)
updateVisibility(true);
}
m_visible = visible;
}
void GraphicalNode::setParentVisible(bool visible)
{
if(m_visible)
{
if(m_parentVisible && !visible)
updateVisibility(false);
if(visible && !m_parentVisible)
updateVisibility(true);
}
m_parentVisible = visible;
}
void GraphicalNode::updateVisibility(bool visible)
{
if(visible)
m_scene->addToIndex(this);
else
m_scene->removeFromIndex(this);
}
void GraphicalNode::SparrowMotionState::getWorldTransform(btTransform& worldTrans ) const
{
worldTrans.setFromOpenGLMatrix(glm::value_ptr(m_node->getTransform()));
}
void GraphicalNode::SparrowMotionState::setWorldTransform(const btTransform& worldTrans)
{
glm::mat4 t;
worldTrans.getOpenGLMatrix(glm::value_ptr(t));
m_node->setTransform(t);
}

View File

@ -4,36 +4,60 @@
#include "scenenode.h"
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include "LinearMath/btMotionState.h"
class SceneTree;
class GraphicalNode : public SceneNode
{
public:
class SparrowMotionState : public btMotionState
{
GraphicalNode* m_node;
public:
SparrowMotionState(GraphicalNode* node) : m_node(node) {}
virtual void getWorldTransform(btTransform& worldTrans ) const;
//Bullet only calls the update of worldtransform for active objects
virtual void setWorldTransform(const btTransform& worldTrans);
};
protected:
// m_parentTransform is the base transform for this element
glm::mat4 m_parentTransform;
// m_transform is the relative transformation matrix of this node
glm::mat4 m_transform;
bool m_parentVisible;
bool m_visible;
bool m_transformChanged;
SparrowMotionState m_motionState;
virtual void updateVisibility(bool visible);
public:
// GraphicalNode();
// GraphicalNode(bool);
GraphicalNode(bool visible = true) : m_visible(visible), m_transformChanged(true) {}
GraphicalNode(bool visible = true) : m_parentVisible(true), m_visible(visible), m_transformChanged(true), m_motionState(this) {}
virtual ~GraphicalNode() { setVisible(false); }
// bool isVisible(){return m_visible;}
// void toggleVisibility();
bool isVisible(){return m_visible;}
void toggleVisibility();
virtual void setSceneTree(SceneTree* tree);
// transform methods
void setTransform(const glm::mat4 &transform);
const glm::mat4& getTransform() { return m_transform; }
void setParentTransform(const glm::mat4 &transform);
const glm::mat4& getTransform() { return m_transform; }
// visibility methods
bool isVisible(){return m_parentVisible && m_visible;}
void toggleVisibility();
void setVisible(bool visible);
void setParentVisible(bool visible);
// transformation tools :
void moveTo(const glm::vec3 &position);
@ -41,6 +65,9 @@ public:
void lookAt(const glm::vec3 &target, const glm::vec3 &upVector = glm::vec3(0, 1, 0));
void rotate(float angle, const glm::vec3 &vector);
void scale(const glm::vec3 &scaleFactor);
// this is used to synchronize a bullet rigidbody's transform with a GraphicalNode transform
SparrowMotionState* getMotionState() { return &m_motionState; }
};
#endif // GRAPHICALNODE_H

View File

@ -12,21 +12,8 @@ void MeshNode::setDepth(float depth){
void MeshNode::update()
{
// temp animation system
m_movement = m_acceleration * m_movement;
m_geometry.modelMatrix = m_movement * m_geometry.modelMatrix;
if(m_transformChanged)
{
m_geometry.modelMatrix = m_parentTransform * m_transform;
if(m_rigidBody != nullptr)
{
btTransform transform;
transform.setFromOpenGLMatrix(glm::value_ptr(m_geometry.modelMatrix));
m_rigidBody->setWorldTransform(transform);
m_rigidBody->setLinearVelocity(btVector3(0,0,0));
}
}
}
btRigidBody* MeshNode::buildStaticCollider()
@ -45,11 +32,16 @@ btRigidBody* MeshNode::buildStaticCollider()
bulletMesh->m_indexType = PHY_INTEGER;
// building bullet rigidbody
btTriangleIndexVertexArray* collisionShape = new btTriangleIndexVertexArray();
collisionShape->addIndexedMesh(*bulletMesh, PHY_INTEGER);
btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(collisionShape, false);
btTriangleIndexVertexArray* indexArray = new btTriangleIndexVertexArray();
indexArray->addIndexedMesh(*bulletMesh, PHY_INTEGER);
btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(indexArray, true);
shape->setLocalScaling(btVector3(m_transform[0].x, m_transform[1].y, m_transform[2].z));
btMotionState *motionState = new btDefaultMotionState();
m_rigidBody = new btRigidBody(0, motionState, shape);
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(m_transform[3].x, m_transform[3].y, m_transform[3].z));
// IMPORTANT ! collisions on static meshes does not work if the transform is modified after the rigidbody construction
m_rigidBody = new btRigidBody(0., nullptr, shape);
m_rigidBody->setWorldTransform(transform);
return m_rigidBody;
}

View File

@ -15,16 +15,15 @@ class btRigidBody;
class MeshNode : public GraphicalNode
{
protected:
GeometryNode m_geometry;
// physics
btRigidBody *m_rigidBody;
public:
// temp
glm::mat4 m_movement;
glm::mat4 m_acceleration;
// WARNING ! this class doesn't handle the destruction of the rendered mesh and the eventually generated rigidbody
// this behaviour allows the use of the same meshes in multiple nodes
MeshNode(Mesh* mesh, bool visible = true) : GraphicalNode(visible), m_geometry(mesh, glm::mat4()), m_rigidBody(nullptr) {}
virtual void update();
@ -33,6 +32,7 @@ public:
virtual GeometryNode* getGeometryNode() { return &m_geometry; }
// this creates a new rigidbody, you must handle its destruction manually
btRigidBody* buildStaticCollider();
};

View File

@ -0,0 +1,42 @@
#include "physicsdebugnode.h"
#include "mesh.h"
#include "phongmaterial.h"
PhysicsDebugNode::PhysicsDebugNode() :
MeshNode(new Mesh())
{
PhongMaterial* mat = new PhongMaterial();
mat->emission = glm::vec3(1, 0, 0);
mat->diffuse = glm::vec3(0);
mat->specular = glm::vec3(0);
m_geometry.mesh->setMaterial(mat);
m_geometry.mesh->setPrimitiveType(GL_LINES);
m_geometry.mesh->setWireframe(true);
glm::vec3 pos1(0, 1, 0);
glm::vec3 pos2(0, 0, 0);
glm::vec3 color(1, 0, 0);
m_geometry.mesh->addVertex(pos1, color);
m_geometry.mesh->addVertex(pos2, color);
m_geometry.mesh->updateFlags();
}
void PhysicsDebugNode::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
{
glm::vec3 glColor(color.x(), color.y(), color.z());
m_geometry.mesh->addVertex(glm::vec3(from.x(), from.y(), from.z()), glColor);
m_geometry.mesh->addVertex(glm::vec3(to.x(), to.y(), to.z()), glColor);
}
void PhysicsDebugNode::flushLines()
{
// a little heavy, but it's a debug mode so it shouldn't be a problem
m_geometry.mesh->initGL();
}
void PhysicsDebugNode::clearBuffers()
{
m_geometry.mesh->positions3D.clear();
m_geometry.mesh->normals.clear();
}

View File

@ -0,0 +1,32 @@
#ifndef PHYSICSDEBUGNODE_H
#define PHYSICSDEBUGNODE_H
#include "meshnode.h"
#include <LinearMath/btIDebugDraw.h>
class PhysicsDebugNode : public MeshNode, public btIDebugDraw
{
Mesh* m_debugMesh;
int m_debugMode;
public:
PhysicsDebugNode();
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color);
virtual void flushLines();
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) {} // not supported yet
virtual void reportErrorWarning(const char* warningString) {} // not supported yet
virtual void draw3dText(const btVector3& location, const char* textString) {} // not supported yet
// currently useless
virtual void setDebugMode(int debugMode) { m_debugMode = debugMode; }
virtual int getDebugMode() const { return m_debugMode; }
void clearBuffers();
};
#endif // PHYSICSDEBUGNODE_H

View File

@ -5,6 +5,8 @@
#include <glm/ext.hpp>
#include "scenetree.h"
#define DEFAULT_ROTATION_SPEED 0.01f
void FirstPersonCamera::computeView()
@ -54,13 +56,12 @@ const float PLAYER_RADIUS = 0.30f;
const float PLAYER_HEIGHT = 1.75f;
const float EYES_OFFSET = 0.775f;
PlayerCharacterNode::PlayerCharacterNode(Input *input) :
m_input(input),
m_noclipMode(true),
PlayerCharacterNode::PlayerCharacterNode(bool noClip) :
m_noclipMode(noClip),
m_inputActions({NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION})
{
btDefaultMotionState *motionState = new btDefaultMotionState();
m_motionState = new btDefaultMotionState();
// Create the shape
btCollisionShape *shape = new btCapsuleShape(PLAYER_RADIUS, PLAYER_HEIGHT);
@ -70,7 +71,7 @@ PlayerCharacterNode::PlayerCharacterNode(Input *input) :
shape->calculateLocalInertia(1.0, localInertia);
// Create the rigid body object
m_rigidBody = new btRigidBody(1.0, motionState, shape, localInertia);
m_rigidBody = new btRigidBody(1.0, m_motionState, shape, localInertia);
// capsule always pointing up
m_rigidBody->setSleepingThresholds(0.0, 0.0);
@ -98,10 +99,11 @@ void PlayerCharacterNode::setPosition(float x, float y, float z)
void PlayerCharacterNode::update()
{
Input *input = getEngine().getInput();
// get events
int walk = 0;
int strafe = 0;
for(int action : m_input->getActions())
for(int action : input->getActions())
{
if(action == m_inputActions[FORWARD])
++walk;
@ -116,7 +118,7 @@ void PlayerCharacterNode::update()
}
// update camera rotation
sf::Vector2i diff = m_input->getDeltaPosition();
sf::Vector2i diff = input->getDeltaPosition();
m_fpsCamera.rotate(diff.x, diff.y);
// update camera position

View File

@ -6,6 +6,7 @@
#include <LinearMath/btVector3.h>
class btRigidBody;
class btDefaultMotionState;
class FirstPersonCamera : public BasicCamera
{
@ -26,15 +27,14 @@ public:
void lookAt(const glm::vec3 &targetPos);
void setUpVector(const glm::vec3 &up);
const glm::vec3& getEyePosition() { return m_eye; }
const glm::vec3& getDirection() { return m_direction; }
};
class PlayerCharacterNode : public CameraNode
{
Input *m_input;
btRigidBody* m_rigidBody;
btDefaultMotionState *m_motionState;
FirstPersonCamera m_fpsCamera;
bool m_noclipMode;
@ -45,12 +45,15 @@ class PlayerCharacterNode : public CameraNode
enum PlayerAction {FORWARD, BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP};
public:
PlayerCharacterNode(Input *input);
PlayerCharacterNode(bool noClip = true);
void setInputs(int forward, int backward, int strafe_left, int strafe_right, int toggleNoClip = NO_ACTION);
void setPosition(float x, float y, float z);
glm::vec3 getEyePosition() { return m_fpsCamera.getEyePosition(); }
glm::vec3 getDirection() { return m_fpsCamera.getDirection(); }
virtual void update();
void toggleNoClip();

8
src/scene/scenenode.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "scenenode.h"
#include "scenetree.h"
const Engine& SceneNode::getEngine()
{
return m_scene->getEngine();
}

View File

@ -4,9 +4,12 @@
class SceneTree;
class Light;
class GeometryNode;
class Engine;
class SceneNode
{
protected:
const Engine& getEngine();
public:
SceneNode() : m_parent(nullptr), m_scene(nullptr) {}
@ -16,7 +19,7 @@ public:
virtual void update() = 0;
virtual Light* getLight() {return nullptr;}
virtual GeometryNode* getGeometryNode() {return nullptr;}
virtual void setSceneTree(SceneTree* tree){m_scene = tree;}
virtual void setSceneTree(SceneTree* tree) {m_scene = tree;}
// virtual void toggleNode(){m_enabled = !m_enabled;}
};

View File

@ -9,8 +9,9 @@
#include "scene/scenenode.h"
#include "scene/cameranode.h"
SceneTree::SceneTree() :
SceneTree::SceneTree(const Engine &engine) :
Scene(),
m_engine(engine),
m_skybox(NULL)
{
DeferredPipeline *pipeline = new DeferredPipeline();
@ -48,25 +49,29 @@ void SceneTree::addToIndex(SceneNode* node){
Light *light = node->getLight();
GeometryNode *geometrynode = node->getGeometryNode();
//TODO : Check for doublon in m_lights et m_geometries => not necessary if correctly removed ?
if (light) m_lights.push_back(light);
if (geometrynode) m_geometries.push_back(geometrynode);
}
void SceneTree::removeObject(ContainerNode* parent,SceneNode *node){
parent->removeChild(node);
removeFromIndex(node);
if (light != nullptr) m_lights.push_back(light);
if (geometrynode != nullptr) m_geometries.push_back(geometrynode);
}
void SceneTree::removeFromIndex(SceneNode *node){
auto it_l = std::find(m_lights.begin(),m_lights.end(),node->getLight());
if (it_l != m_lights.end()){
std::iter_swap(it_l,m_lights.end()-1);
m_lights.pop_back();
Light *light = node->getLight();
GeometryNode *geometrynode = node->getGeometryNode();
if(light != nullptr)
{
auto it_l = std::find(m_lights.begin(),m_lights.end(),node->getLight());
if (it_l != m_lights.end()){
std::iter_swap(it_l,m_lights.end()-1);
m_lights.pop_back();
}
}
auto it_g = std::find(m_geometries.begin(),m_geometries.end(),node->getGeometryNode());
if (it_g != m_geometries.end()){
std::iter_swap(it_g,m_geometries.end()-1);
m_geometries.pop_back();
if(geometrynode != nullptr)
{
auto it_g = std::find(m_geometries.begin(),m_geometries.end(),node->getGeometryNode());
if (it_g != m_geometries.end()){
std::iter_swap(it_g,m_geometries.end()-1);
m_geometries.pop_back();
}
}
}

View File

@ -4,11 +4,10 @@
#include <vector>
#include <string>
#include "scene.h"
#include "light.h"
#include "resourcemanager.h"
#include "containernode.h"
#include "engine.h"
class Light;
class CameraNode;
/**
@ -19,7 +18,6 @@ class CameraNode;
class SceneTree : public Scene
{
public:
SceneTree();
~SceneTree();
virtual SceneIterator<Light*>* getLights();
@ -34,10 +32,17 @@ public:
ContainerNode* getRootObject(){return &m_root;}
void addToIndex(SceneNode* node);
void removeObject(ContainerNode* parent,SceneNode *node);
void removeFromIndex(SceneNode *node);
void updateShaders();
const Engine& getEngine() { return m_engine; }
private:
// A SceneTree can only be constructed by the engine by using Engine::createScene()
friend SceneTree* Engine::createScene();
SceneTree(const Engine &engine);
const Engine &m_engine;
ContainerNode m_root;
std::vector<Light*> m_lights;
std::vector<GeometryNode*> m_geometries;

View File

@ -9,6 +9,8 @@
#include "phongmaterial.h"
#include "tools/utils.h"
#include "tools/font.h"
#include "resourcemanager.h"
#include "tools/loader.h"
const unsigned int SparrowShell::BUFFER_MAX_LENGTH = 50;
const unsigned int SparrowShell::BUFFER_DISPLAYED_NUMBER = 10;
@ -25,6 +27,8 @@ SparrowShell::SparrowShell(sf::Window* window, Input* input):
m_dimension = glm::ivec2(size.x,size.y/2);
m_buffer->setFontSize(16.f);
Font* fonte_des_neiges = Loader::loadFont("../data/consolas.fnt","../data/consolas.png");
RESOURCE_ADD(fonte_des_neiges,Font,"shellfont");
//Create mesh for background
Mesh* mesh = new Mesh();

View File

@ -27,57 +27,27 @@
#include <glm/ext.hpp>
#include "potator.h"
class myKeysMap : public IKeysMap{
public:
enum{MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_CONSOLE = 15};
enum{MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_PHYSICS_DEBUG, TOGGLE_CONSOLE = 15};
myKeysMap(){
Binding b;
b.action = TOGGLE_CONSOLE;
b.key = sf::Keyboard::F3;
b.type = IKeysMap::PRESSED;
keys.push_back(b);
b.action = MAIN_ACTION;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::KeyCount + sf::Mouse::Left;
keys.push_back(b);
b.action = SECONDARY_ACTION;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::KeyCount + sf::Mouse::Right;
keys.push_back(b);
b.action = MOVE_FORWARD;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::Z;
keys.push_back(b);
b.action = MOVE_BACKWARD;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::S;
keys.push_back(b);
b.action = STRAFE_LEFT;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::Q;
keys.push_back(b);
b.action = STRAFE_RIGHT;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::D;
keys.push_back(b);
b.action = TOGGLE_NOCLIP;
b.type = IKeysMap::PRESSED;
b.key = sf::Keyboard::G;
keys.push_back(b);
keys.push_back( {MAIN_ACTION, sf::Keyboard::KeyCount + sf::Mouse::Left, IKeysMap::PRESSED} );
keys.push_back( {SECONDARY_ACTION, sf::Keyboard::KeyCount + sf::Mouse::Right, IKeysMap::PRESSED} );
keys.push_back( {MOVE_FORWARD, sf::Keyboard::Z, IKeysMap::HOLD} );
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( {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} );
}
static std::vector<int> getMap()
{
return {MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_CONSOLE};
return {MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_PHYSICS_DEBUG, TOGGLE_CONSOLE};
}
};
@ -154,92 +124,50 @@ int main(){
// this creates the opengl context
// the opengl context must exist before any opengl class is used (texture, pipeline, etc..)
engine.createWindow("test");
engine.createWindow("Sparrow Engine Testing Environment");
// setting up SparrowEngine
engine.initPhysics();
SceneTree scene;
SceneTree *scene = engine.createScene();
engine.setScene(scene);
// settin gup SparrowInput
Input* input = engine.getInput();
input->setKeysMap(myKeysMap());
input->addContext(Context("default", myKeysMap::getMap()));
input->setCurrentContext("default");
input->updateKeyBindings();
engine.setTogglePhysicsDebugAction(myKeysMap::TOGGLE_PHYSICS_DEBUG);
/*
TrackBallCameraNode *cam = new TrackBallCameraNode(engine.getInput());
cam->setInputs(myKeysMap::SECONDARY_ACTION, myKeysMap::MAIN_ACTION);
scene.getRootObject()->addChild(cam);
scene.setMainCamera(cam);
// 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();
player->setInputs(myKeysMap::MOVE_FORWARD, myKeysMap::MOVE_BACKWARD, myKeysMap::STRAFE_LEFT, myKeysMap::STRAFE_RIGHT, myKeysMap::TOGGLE_NOCLIP);
scene->getRootObject()->addChild(player);
scene->setMainCamera(player);
player->setPosition(0.f, 10.f, 0.f);
engine.getPhysics()->addRigidBody(player->getRigidbody());
PlayerCharacterNode *cam = new PlayerCharacterNode(engine.getInput());
cam->setInputs(myKeysMap::MOVE_FORWARD, myKeysMap::MOVE_BACKWARD, myKeysMap::STRAFE_LEFT, myKeysMap::STRAFE_RIGHT, myKeysMap::TOGGLE_NOCLIP);
scene.getRootObject()->addChild(cam);
scene.setMainCamera(cam);
cam->setPosition(0.f, 4.f, 0.f);
engine.getPhysics()->addRigidBody(cam->getRigidbody());
// throw cubes and spheres with mouse clicks
Potator *potator = new Potator(player, myKeysMap::MAIN_ACTION, myKeysMap::SECONDARY_ACTION);
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());
scene.getRootObject()->addChild(ambientLight);
scene.getRootObject()->addChild(sunLight);
scene->getRootObject()->addChild(ambientLight);
scene->getRootObject()->addChild(sunLight);
/* Exemple creation mesh 2D
*
Mesh* mesh = new Mesh();
mesh->addRectangle2D(180, 400,10,64);
PhongMaterial *mat = new PhongMaterial();
mat->diffuse = glm::vec3(1, 0.5, 0);
mesh->setMaterial(mat);
mesh->setDepth(1);
mesh->initGL();
scene.getRootObject()->addChild(new MeshNode(mesh));
*/
/* Exemple ajout d'un objet a la scene
*
SparrowShell *shell = new SparrowShell(engine.getWindow(),engine.getInput());
scene.getRootObject()->addChild(shell);
*/
// the pipeline needs to updates his shaders because the scene changed
// this should be handled somewhere else in the future
//DeferredPipeline* pipeline = (DeferredPipeline*)scene.getPipeline();
//pipeline->refreshScene(&scene);
Font* fonte_des_neiges = Loader::loadFont("../data/consolas.fnt","../data/consolas.png");
RESOURCE_ADD(fonte_des_neiges,Font,"shellfont");
TextNode* tnode/* = new MeshNode(fonte_des_neiges->getTextMesh("Hello World!"));
scene.getRootObject()->addChild(mnode)*/;
// mnode = new MeshNode(fonte_des_neiges->getTextMesh("Portez ce vieux whisky au juge blond qui fume.", glm::vec3(0.5, 0.7, 0.2)));
// mnode->setTransform(glm::rotate(glm::translate(glm::mat4(), glm::vec3(70, 30, 0)), 0.4f, glm::vec3(0, 0, 1)));
// utils::setPosition2D(mnode,glm::vec2(0, 400));
// utils::rotate2D(mnode, glm::vec2(10,10),0.5);
// scene.getRootObject()->addChild(mnode);
tnode = fonte_des_neiges->getTextNode("Such Text", glm::vec3(0.7, 0.4, 0.2), 32.f);
utils::setPosition2D((MeshNode*)tnode,glm::vec2(200, 170));
utils::rotate2D((MeshNode*)tnode, glm::vec2(0),-0.5);
tnode->m_movement = glm::translate(glm::rotate(glm::translate(glm::mat4(), glm::vec3(240, 180, 0)), 0.03f, glm::vec3(0, 0, 1)), glm::vec3(-240, -180, 0));
// mnode->setTransform(glm::rotate(glm::translate(glm::mat4(), glm::vec3(200, 170, 0)), -0.5f, glm::vec3(0, 0, 1)));
scene.getRootObject()->addChild((SceneNode*)tnode);
//tnode = fonte_des_neiges->getTextNode("Such Text", glm::vec3(0.7, 0.4, 0.2));
//tnode->setTransform(glm::rotate(glm::translate(glm::mat4(), glm::vec3(200, 170, 0)), -0.5f, glm::vec3(0, 0, 1)));
//scene.getRootObject()->addChild(tnode);
// mnode = new MeshNode(fonte_des_neiges->getTextMesh("Very font", glm::vec3(0.7, 0.2, 0.8)));
// mnode->setTransform(glm::rotate(glm::translate(glm::mat4(), glm::vec3(180, 400, 0)), 0.1f, glm::vec3(0, 0, 1)));
// scene.getRootObject()->addChild(mnode);
// mnode = new MeshNode(fonte_des_neiges->getTextMesh("Much animation", glm::vec3(0.3, 0.3, 0.8)));
// mnode->setTransform(glm::translate(glm::mat4(), glm::vec3(400, 250, 0)));
// mnode->m_movement = glm::translate(glm::rotate(glm::translate(glm::mat4(), glm::vec3(580, 280, 0)), 0.03f, glm::vec3(0, 0, 1)), glm::vec3(-580, -280, 0));
// scene.getRootObject()->addChild(mnode);
generateTerrain(&scene, engine.getPhysics());
engine.setScene(&scene);
// terrain
generateTerrain(scene, engine.getPhysics());
// shell output tests
engine.outputShell("Hello World!");
engine.outputShell("Starting test :");
@ -247,15 +175,12 @@ int main(){
engine.outputShell(std::to_string(i));
}
Input* input = engine.getInput();
input->setKeysMap(myKeysMap());
input->addContext(Context("default", myKeysMap::getMap()));
input->setCurrentContext("default");
input->updateKeyBindings();
// preparing shaders and launching the engine
scene->updateShaders();
engine.start();
/* GraphNode n1 = GraphNode();
// pathfinding tests
/* GraphNode n1 = GraphNode();
n1.setValue(1);
GraphNode n2 = GraphNode();
n2.setValue(2);
@ -279,6 +204,7 @@ int main(){
std::cout << gn->getValue() << std::endl;
}
// loaders tests
Loader::setObjDirectory("../data/");
Loader::setMtlDirectory("../data/");
Loader::setTexDirectory("../data/");

137
src/test/potator.cpp Normal file
View File

@ -0,0 +1,137 @@
#include "potator.h"
#include "scene/playercharacternode.h"
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include "scene/scenetree.h"
#include "parametricmesh.h"
#include "phongmaterial.h"
#include "scene/meshnode.h"
#define PHYSICS_OFFSET 0.05f
Potator::Potator(PlayerCharacterNode * player,
int cube_action,
int sphere_action) :
m_player(player),
m_throwCubeAction(cube_action),
m_throwSphereAction(sphere_action)
{
glm::vec3 cubeDim(1);
float sphereRadius = 0.5f;
glm::vec3 s = cubeDim*0.5f;
float density = 1.f;
// creating cube
m_cubeMesh = new Mesh();
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, 1*s.z),glm::vec3(0, 0, 1),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, 1*s.z),glm::vec3(0, 0, 1),glm::vec2(0, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, 1*s.z),glm::vec3(0, 0, 1),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, 1*s.z),glm::vec3(0, 0, 1),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, -1*s.z),glm::vec3(0, 0, -1),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, -1*s.z),glm::vec3(0, 0, -1),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, -1*s.z),glm::vec3(0, 0, -1),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, -1*s.z),glm::vec3(0, 0, -1),glm::vec2(0, 1));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, -1*s.z),glm::vec3(0, 1, 0),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, 1*s.z),glm::vec3(0, 1, 0),glm::vec2(0, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, -1*s.z),glm::vec3(0, 1, 0),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, 1*s.z),glm::vec3(0, 1, 0),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, -1*s.z),glm::vec3(0, -1, 0),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, 1*s.z),glm::vec3(0, -1, 0),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, -1*s.z),glm::vec3(0, -1, 0),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, 1*s.z),glm::vec3(0, -1, 0),glm::vec2(0, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, 1*s.z),glm::vec3( 1, 0, 0),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, 1*s.z),glm::vec3( 1, 0, 0),glm::vec2(0, 1));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, -1*s.y, -1*s.z),glm::vec3( 1, 0, 0),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3( 1*s.x, 1*s.y, -1*s.z),glm::vec3( 1, 0, 0),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, 1*s.z),glm::vec3(-1, 0, 0),glm::vec2(1, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, 1*s.z),glm::vec3(-1, 0, 0),glm::vec2(1, 1));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, -1*s.y, -1*s.z),glm::vec3(-1, 0, 0),glm::vec2(0, 0));
m_cubeMesh->addVertex(glm::vec3(-1*s.x, 1*s.y, -1*s.z),glm::vec3(-1, 0, 0),glm::vec2(0, 1));
for(int id=0; id<24; id+=8)
{
m_cubeMesh->addTriangle(id+0, id+1, id+2);
m_cubeMesh->addTriangle(id+2, id+1, id+3);
m_cubeMesh->addTriangle(id+6, id+5, id+4);
m_cubeMesh->addTriangle(id+7, id+5, id+6);
}
PhongMaterial *mat = new PhongMaterial();
mat->diffuse = glm::vec3(0.6f, 0.2f, 0.3f);
mat->specular = glm::vec3(0.3f);
mat->shininess = 5.f;
mat->emission = glm::vec3(0.0f);
m_cubeMesh->setMaterial(mat);
m_cubeMesh->initGL();
btVector3 halfExtents(s.x+PHYSICS_OFFSET, s.y+PHYSICS_OFFSET, s.z+PHYSICS_OFFSET);
m_cubeShape = new btBoxShape(halfExtents);
m_cubeMass = cubeDim.x*cubeDim.y*cubeDim.z*density;
// creating sphere
mat = new PhongMaterial();
mat->diffuse = glm::vec3(0.1f, 0.6f, 0.3f);
mat->specular = glm::vec3(0.7f);
mat->shininess = 35.f;
mat->emission = glm::vec3(0.0f);
SphereGenerator sphereGen;
m_sphereMesh = sphereGen.generateGeodesicMesh(mat, 2, sphereRadius);
m_sphereMesh->computeNormals();
m_sphereMesh->mergeVertices();
m_sphereMesh->initGL();
m_sphereShape = new btSphereShape(sphereRadius+PHYSICS_OFFSET);
float sphereVolume = 4.18879020479f*(sphereRadius*sphereRadius*sphereRadius); // (4*pi)/3 = 4.18879020479
m_sphereMass = sphereVolume*density;
}
void Potator::throwCube()
{
glm::vec3 pos(0, 10, 0);
glm::vec3 dir(0, 1, 0);
if(m_player != nullptr)
{
dir = m_player->getDirection();
pos = m_player->getEyePosition() + dir*2.f;
}
float throwForce = 20.f;
createGib(new MeshNode(m_cubeMesh), m_cubeShape, m_cubeMass, pos, dir*throwForce, 10000);
}
void Potator::throwSphere()
{
glm::vec3 pos(0, 10, 0);
glm::vec3 dir(0, 1, 0);
if(m_player != nullptr)
{
pos = m_player->getEyePosition();
dir = m_player->getDirection();
}
float throwForce = 20.f;
createGib(new MeshNode(m_sphereMesh), m_sphereShape, m_sphereMass, pos, dir*throwForce, 10000);
}
void Potator::update()
{
GibGeneratorNode::update();
Input *input = getEngine().getInput();
for(int action : input->getActions())
{
if(action == m_throwCubeAction)
throwCube();
else if(action == m_throwSphereAction)
throwSphere();
}
}

39
src/test/potator.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef POTATOR_H
#define POTATOR_H
#include "scene/gibgeneratornode.h"
#include "input.h"
class PlayerCharacterNode;
class Mesh;
class Potator : public GibGeneratorNode
{
PlayerCharacterNode *m_player;
int m_throwCubeAction;
int m_throwSphereAction;
Mesh* m_cubeMesh;
btCollisionShape* m_cubeShape;
float m_cubeMass;
Mesh* m_sphereMesh;
btCollisionShape* m_sphereShape;
float m_sphereMass;
void throwCube();
void throwSphere();
public:
Potator(PlayerCharacterNode * player = nullptr,
int cube_action = NO_ACTION,
int sphere_action = NO_ACTION);
void setPlayer(PlayerCharacterNode *player) { m_player = player; }
void setCubeThrowingAction(int action) { m_throwCubeAction = action; }
void setSphereThrowingAction(int action) { m_throwSphereAction = action; }
virtual void update();
};
#endif // POTATOR_H