fixed uninitialized m_scene in scene node causing segfaults, added player node and fps camera

This commit is contained in:
Anselme 2016-12-09 01:16:34 +01:00
parent 47e1273a0f
commit 93f7facea9
13 changed files with 353 additions and 35 deletions

View File

@ -47,7 +47,7 @@ void Engine::createWindow(std::string title,
m_window->setFramerateLimit(60);
m_input = new Input(m_window);
m_renderer->initGL(w, h);
m_sparrowshell = new SparrowShell(m_window,m_input);
m_sparrowshell = new SparrowShell(m_window, m_input);
}
void Engine::initPhysics()
@ -57,7 +57,7 @@ void Engine::initPhysics()
btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
btSequentialImpulseConstraintSolver *solver = new btSequentialImpulseConstraintSolver();
m_world = new btDiscreteDynamicsWorld(dispatcher, broadPhase, solver, collisionConfiguration);
m_world->setGravity(btVector3(0, -10, 0));
m_world->setGravity(btVector3(0, -9.81f, 0));
}
void Engine::update()

View File

@ -2,28 +2,15 @@
#define CAMERANODE_H
#include "scenenode.h"
#include "trackballcamera.h"
#include "input.h"
#include "camera.h"
/**
* @brief The CameraNode class is a scene node that can be used by the renderer
*/
class CameraNode : public TrackBallCamera, public SceneNode
class CameraNode : public SceneNode
{
Input *m_input;
int m_action_move;
int m_action_rotate;
public:
CameraNode(Input *input);
void setInputs(int action_move, int action_rotate)
{
m_action_move = action_move;
m_action_rotate = action_rotate;
}
virtual void update();
virtual Camera *getCamera() = 0;
};
#endif // CAMERANODE_H

View File

@ -16,7 +16,8 @@ void GraphicalContainerNode::addChild(GraphicalNode *node)
{
if(node != nullptr)
{
node->setSceneTree(m_scene);
if(m_scene != nullptr)
node->setSceneTree(m_scene);
m_children.push_back(node);
node->m_parent = this;
}

View File

@ -1,7 +1,39 @@
#include "meshnode.h"
#include "mesh.h"
#include "scenetree.h"
#include <glm/ext.hpp>
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
void MeshNode::setDepth(float depth){
m_geometry.mesh->setDepth(depth);
}
btRigidBody* MeshNode::buildStaticCollider()
{
bulletMesh = new btIndexedMesh();
Mesh *m = m_geometry.mesh;
// vertices
bulletMesh->m_numVertices = m->positions3D.size();
bulletMesh->m_vertexBase = (unsigned char*)(m->positions3D.data());
bulletMesh->m_vertexStride = sizeof(glm::vec3);
bulletMesh->m_vertexType = PHY_FLOAT;
// indices
bulletMesh->m_numTriangles = m->indices.size()/3;
bulletMesh->m_triangleIndexBase = (unsigned char*)(m->indices.data());
bulletMesh->m_triangleIndexStride = 3*sizeof(GLuint);
bulletMesh->m_indexType = PHY_INTEGER;
// building bullet rigidbody
btTriangleIndexVertexArray* collisionShape = new btTriangleIndexVertexArray();
collisionShape->addIndexedMesh(*bulletMesh, PHY_INTEGER);
btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(collisionShape, false);
// positionning
btTransform transform;
transform.getOpenGLMatrix(glm::value_ptr(m_geometry.modelMatrix));
btMotionState *motionState = new btDefaultMotionState(transform);
return new btRigidBody(0, motionState, shape);
}

View File

@ -5,6 +5,9 @@
#include "glm/mat4x4.hpp"
#include "scene.h"
class btRigidBody;
class btIndexedMesh;
/**
* @brief The MeshNode class holds a mesh
*/
@ -13,12 +16,14 @@ class MeshNode : public GraphicalNode
{
GeometryNode m_geometry;
btIndexedMesh *bulletMesh;
public:
// temp
glm::mat4 m_movement;
glm::mat4 m_acceleration;
MeshNode(Mesh* mesh) : m_geometry(mesh, glm::mat4()) {}
MeshNode(Mesh* mesh) : m_geometry(mesh, glm::mat4()), bulletMesh(nullptr) {}
virtual void update()
{
@ -31,6 +36,8 @@ public:
void setDepth(float depth);
virtual GeometryNode* getGeometryNode() { return &m_geometry; }
btRigidBody* buildStaticCollider();
};
#endif // MESHNODE_H

View File

@ -0,0 +1,156 @@
#include "playercharacternode.h"
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <glm/ext.hpp>
#define DEFAULT_ROTATION_SPEED 0.01f
void FirstPersonCamera::computeView()
{
m_view = glm::lookAt(m_eye, m_eye + m_direction, m_upVector);
}
FirstPersonCamera::FirstPersonCamera(float myFov, float myNear, float myFar) :
BasicCamera(myFov, myNear, myFar), m_direction(0, 0, 1), m_upVector(0, 1, 0)
{
computeView();
}
void FirstPersonCamera::move(const glm::vec3 &translation)
{
m_eye += translation;
computeView();
}
void FirstPersonCamera::rotate(float dx, float dy)
{
m_direction = glm::rotate(m_direction, -dx*DEFAULT_ROTATION_SPEED, m_upVector);
m_direction = glm::rotate(m_direction, -dy*DEFAULT_ROTATION_SPEED, glm::cross(m_direction, m_upVector));
m_direction = glm::normalize(m_direction);
computeView();
}
void FirstPersonCamera::moveTo(const glm::vec3 &targetPos)
{
m_eye = targetPos;
computeView();
}
void FirstPersonCamera::lookAt(const glm::vec3 &targetPos)
{
m_view = glm::lookAt(m_eye, targetPos, m_upVector);
}
void FirstPersonCamera::setUpVector(const glm::vec3 &up)
{
m_upVector = up;
computeView();
}
const float WALK_SPEED = 0.5f;
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),
m_inputActions({NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION})
{
btDefaultMotionState *motionState = new btDefaultMotionState();
// Create the shape
btCollisionShape *shape = new btCapsuleShape(PLAYER_RADIUS, PLAYER_HEIGHT);
// Add mass
btVector3 localInertia;
shape->calculateLocalInertia(1.0, localInertia);
// Create the rigid body object
m_rigidBody = new btRigidBody(1.0, motionState, shape, localInertia);
// capsule always pointing up
m_rigidBody->setSleepingThresholds(0.0, 0.0);
m_rigidBody->setAngularFactor(0.0);
}
void PlayerCharacterNode::setInputs(int forward, int backward, int strafeLeft, int strafeRight, int toggleNoClip)
{
m_inputActions[FORWARD] = forward;
m_inputActions[BACKWARD] = backward;
m_inputActions[STRAFE_LEFT] = strafeLeft;
m_inputActions[STRAFE_RIGHT] = strafeRight;
m_inputActions[TOGGLE_NOCLIP] = toggleNoClip;
}
void PlayerCharacterNode::setPosition(float x, float y, float z)
{
btTransform transform;
btVector3 pos(x, y, z);
transform.setOrigin(pos);
m_rigidBody->setWorldTransform(transform);
m_noclip_pos = pos;
m_rigidBody->setLinearVelocity(btVector3(0,0,0));
}
void PlayerCharacterNode::update()
{
// get events
int walk = 0;
int strafe = 0;
for(int action : m_input->getActions())
{
if(action == m_inputActions[FORWARD])
++walk;
else if(action == m_inputActions[BACKWARD])
--walk;
else if(action == m_inputActions[STRAFE_LEFT])
--strafe;
else if(action == m_inputActions[STRAFE_RIGHT])
++strafe;
else if(action == m_inputActions[TOGGLE_NOCLIP])
toggleNoClip();
}
// update camera rotation
sf::Vector2i diff = m_input->getDeltaPosition();
m_fpsCamera.rotate(diff.x, diff.y);
// update camera position
btVector3 pos = m_rigidBody->getCenterOfMassPosition();
m_fpsCamera.moveTo(glm::vec3(pos.x(), pos.y()+EYES_OFFSET, pos.z()));
// update body movement
const glm::vec3 &glmDir = m_fpsCamera.getDirection();
if(walk != 0 || strafe != 0)
{
glm::vec3 moveDir = glm::normalize(glmDir*walk + glm::cross(glmDir, glm::vec3(0, 1, 0))*strafe);
if (m_noclipMode)
{
btVector3 dir(moveDir.x, moveDir.y, moveDir.z);
m_noclip_pos += dir*WALK_SPEED*2.f;
}
else
{
//TODO: if on ground + space pressed -> jump
glm::vec2 hPos = glm::normalize(glm::vec2(moveDir.x, moveDir.y));
m_rigidBody->setLinearVelocity((m_rigidBody->getLinearVelocity() + btVector3(hPos.x, m_rigidBody->getLinearVelocity().getY(), hPos.y)) / 2.f); // smooth movements
}
}
if(m_noclipMode)
{
btTransform transform;
transform.setOrigin(m_noclip_pos);
m_rigidBody->setWorldTransform(transform);
m_rigidBody->setLinearVelocity(btVector3(0, 0, 0));
}
}
void PlayerCharacterNode::toggleNoClip()
{
m_noclipMode = !m_noclipMode;
m_noclip_pos = m_rigidBody->getCenterOfMassPosition();
}

View File

@ -0,0 +1,63 @@
#ifndef PLAYERCHARACTERNODE_H
#define PLAYERCHARACTERNODE_H
#include "cameranode.h"
#include "input.h"
#include <LinearMath/btVector3.h>
class btRigidBody;
class FirstPersonCamera : public BasicCamera
{
private:
// camera position
glm::vec3 m_eye;
glm::vec3 m_direction;
glm::vec3 m_upVector;
void computeView();
public:
FirstPersonCamera(float myFov = 70.f, float myNear = 0.1f, float myFar = 1000.f);
void move(const glm::vec3 &translation);
void rotate(float dx, float dy);
void moveTo(const glm::vec3 &targetPos);
void lookAt(const glm::vec3 &targetPos);
void setUpVector(const glm::vec3 &up);
const glm::vec3& getDirection() { return m_direction; }
};
class PlayerCharacterNode : public CameraNode
{
Input *m_input;
btRigidBody* m_rigidBody;
FirstPersonCamera m_fpsCamera;
bool m_noclipMode;
btVector3 m_noclip_pos;
std::vector<int> m_inputActions;
enum PlayerAction {FORWARD, BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP};
public:
PlayerCharacterNode(Input *input);
void setInputs(int forward, int backward, int strafe_left, int strafe_right, int toggleNoClip = NO_ACTION);
void setPosition(float x, float y, float z);
virtual void update();
void toggleNoClip();
btRigidBody* getRigidbody() { return m_rigidBody; }
virtual Camera *getCamera() { return &m_fpsCamera; }
};
#endif // PLAYERCHARACTERNODE_H

View File

@ -8,6 +8,8 @@ class GeometryNode;
class SceneNode
{
public:
SceneNode() : m_parent(nullptr), m_scene(nullptr) {}
SceneNode* m_parent;
SceneTree* m_scene;
// bool m_enabled;

View File

@ -7,6 +7,7 @@
#include <mesh.h>
#include <iostream>
#include "scene/scenenode.h"
#include "scene/cameranode.h"
SceneTree::SceneTree() :
Scene(),
@ -23,9 +24,9 @@ SceneTree::~SceneTree()
}
void SceneTree::setMainCamera(CameraNode *camera)
void SceneTree::setMainCamera(CameraNode *camNode)
{
((DeferredPipeline*)m_pipeline)->setCamera((Camera*)camera);
((DeferredPipeline*)m_pipeline)->setCamera(camNode->getCamera());
}
SceneIterator<Light*>* SceneTree::getLights()

View File

@ -30,7 +30,7 @@ public:
Texture* getSkybox() {return m_skybox;}
void setSkybox(Texture* skybox) {m_skybox = skybox;}
void setMainCamera(CameraNode *camera);
void setMainCamera(CameraNode *camNode);
ContainerNode* getRootObject(){return &m_root;}
void addToIndex(SceneNode* node);

View File

@ -1,12 +1,12 @@
#include "cameranode.h"
#include "trackballcameranode.h"
CameraNode::CameraNode(Input *input) :
TrackBallCameraNode::TrackBallCameraNode(Input *input) :
m_input(input),
m_action_move(NO_ACTION),
m_action_rotate(NO_ACTION)
{}
void CameraNode::update()
void TrackBallCameraNode::update()
{
sf::Vector2i diff = m_input->getDeltaPosition();
for(int action : m_input->getActions())

View File

@ -0,0 +1,31 @@
#ifndef TRACKBALLCAMERANODE_H
#define TRACKBALLCAMERANODE_H
#include "cameranode.h"
#include "trackballcamera.h"
#include "input.h"
/**
* @brief The CameraNode class is a scene node that can be used by the renderer
*/
class TrackBallCameraNode : public CameraNode, public TrackBallCamera
{
Input *m_input;
int m_action_move;
int m_action_rotate;
public:
TrackBallCameraNode(Input *input);
void setInputs(int action_move, int action_rotate)
{
m_action_move = action_move;
m_action_rotate = action_rotate;
}
virtual void update();
virtual Camera *getCamera() { return this; }
};
#endif // TRACKBALLCAMERANODE_H

View File

@ -11,7 +11,8 @@
#include <scene/scenetree.h>
#include <scene/textnode.h>
#include <scene/cameranode.h>
#include <scene/trackballcameranode.h>
#include <scene/playercharacternode.h>
#include <scene/lightnode.h>
#include <scene/graphicalcontainernode.h>
#include <tools/graph.h>
@ -22,12 +23,13 @@
#include <tools/utils.h>
#include <sparrowshell/sparrowshell.h>
#include <btBulletDynamicsCommon.h>
#include <glm/ext.hpp>
class myKeysMap : public IKeysMap{
public:
enum{ROTATE_CAMERA, MOVE_CAMERA, TOGGLE_CONSOLE = 15};
enum{MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_CONSOLE = 15};
myKeysMap(){
Binding b;
@ -37,20 +39,45 @@ public:
b.type = IKeysMap::PRESSED;
keys.push_back(b);
b.action = ROTATE_CAMERA;
b.action = MAIN_ACTION;
b.type = IKeysMap::HOLD;
b.key = sf::Keyboard::KeyCount + sf::Mouse::Left;
keys.push_back(b);
b.action = MOVE_CAMERA;
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);
}
static std::vector<int> getMap()
{
return {ROTATE_CAMERA, MOVE_CAMERA, TOGGLE_CONSOLE};
return {MAIN_ACTION, SECONDARY_ACTION, MOVE_FORWARD, MOVE_BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, TOGGLE_NOCLIP, TOGGLE_CONSOLE};
}
};
@ -94,7 +121,7 @@ public:
}
};
void generateTerrain(SceneTree *scene)
void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world)
{
GraphicalContainerNode* terrainContainer = new GraphicalContainerNode();
scene->getRootObject()->addChild(terrainContainer);
@ -117,6 +144,7 @@ void generateTerrain(SceneTree *scene)
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());
}
}
}
@ -127,12 +155,22 @@ 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.initPhysics();
SceneTree scene;
CameraNode *cam = new CameraNode(engine.getInput());
cam->setInputs(myKeysMap::MOVE_CAMERA, myKeysMap::ROTATE_CAMERA);
/*
TrackBallCameraNode *cam = new TrackBallCameraNode(engine.getInput());
cam->setInputs(myKeysMap::SECONDARY_ACTION, myKeysMap::MAIN_ACTION);
scene.getRootObject()->addChild(cam);
scene.setMainCamera(cam);
*/
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());
LightNode *sunLight = new LightNode(new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(1.f)));
LightNode *ambientLight = new LightNode(new AmbientLight());
@ -198,7 +236,7 @@ int main(){
// 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);
generateTerrain(&scene, engine.getPhysics());
engine.setScene(&scene);