diff --git a/src/kekengine/cpp/common/defaults.cpp b/src/kekengine/cpp/common/defaults.cpp index 9f92cfe..58b2ff6 100644 --- a/src/kekengine/cpp/common/defaults.cpp +++ b/src/kekengine/cpp/common/defaults.cpp @@ -42,10 +42,10 @@ static void defaultInput(GLFWwindow *window, void *data) { direction += glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f))); } - bool jump = false; + //bool jump = false; if(Input::getKeyState(keyUp) == GLFW_PRESS) { direction += glm::vec3(0,1,0); - jump = kekData.player->onGround; + //jump = kekData.player->onGround; } if(Input::getKeyState(keyDown) == GLFW_PRESS) { @@ -58,13 +58,15 @@ static void defaultInput(GLFWwindow *window, void *data) { kekData.activeCamera->translate(direction * KEK_NOCLIP_SPEED * kekData.lastFrameTime); }else { //kekData.player->physics->body->applyCentralImpulse(Physics::fromGLM(glm::normalize(direction) * (kekData.lastFrameTime * 20))); - btVector3 vel = kekData.player->physics->body->getLinearVelocity(); - glm::vec3 newVel = glm::normalize(direction) * 6.0f; + /*btVector3 vel = kekData.player->physics->body->getLinearVelocity(); + glm::vec3 newVel = glm::normalize(direction) * KEK_PLAYER_WALK_VELOCITY; newVel.y = vel.y(); - if(jump) newVel.y = 2.7f; - kekData.player->physics->body->setLinearVelocity(Physics::fromGLM(newVel)); + if(jump) newVel.y = KEK_PLAYER_JUMP_VELOCITY; + kekData.player->physics->body->setLinearVelocity(Physics::fromGLM(newVel));*/ + kekData.player->controller->move(direction * (kekData.lastFrameTime * 10)); } } + kekData.player->controller->update(); } static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) { @@ -176,21 +178,33 @@ void init() { float radii[2] = {KEK_PLAYER_RADIUS, KEK_PLAYER_RADIUS}; btCollisionShape *shape = new btMultiSphereShape(positions, radii, 2); btRigidBody *body = new btRigidBody(KEK_PLAYER_MASS, nullptr, shape); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); body->setFriction(3); body->setActivationState(DISABLE_DEACTIVATION); kekData.physics->world->addRigidBody(body); - btCollisionShape *jumpShape = new btSphereShape(KEK_PLAYER_RADIUS / 2); + /*btCollisionShape *jumpShape = new btSphereShape(KEK_PLAYER_RADIUS / 2); btGhostObject *jumpCollider = new btGhostObject(); jumpCollider->setCollisionShape(jumpShape); jumpCollider->setCollisionFlags(jumpCollider->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); jumpCollider->setActivationState(DISABLE_DEACTIVATION); - kekData.physics->world->addCollisionObject(jumpCollider); + kekData.physics->world->addCollisionObject(jumpCollider);*/ + + btTransform from; + from.setIdentity(); + from.setOrigin(btVector3(0,0,0)); + + btTransform to; + to.setIdentity(); + to.setOrigin(btVector3(1,1,1)); + + btCollisionWorld::ClosestConvexResultCallback cb = btCollisionWorld::ClosestConvexResultCallback(from.getOrigin(), to.getOrigin()); + kekData.physics->world->convexSweepTest((btConvexShape *) shape, from, to, cb); kekData.player->physics = new PlayerPhysicsObjectData(); kekData.player->physics->body = body; - kekData.player->physics->jumpCollider = jumpCollider; - kekData.player->moveTo(glm::vec3(0,10,0)); + //kekData.player->physics->jumpCollider = jumpCollider; + kekData.player->moveTo(glm::vec3(5,10,0)); } void destroy() { diff --git a/src/kekengine/cpp/common/engine.cpp b/src/kekengine/cpp/common/engine.cpp index d1f39d9..ef86f4e 100644 --- a/src/kekengine/cpp/common/engine.cpp +++ b/src/kekengine/cpp/common/engine.cpp @@ -122,7 +122,7 @@ int init() { glCullFace(GL_BACK); glClearColor(0.1f, 0.3f, 0.1f, 0.0f); - glfwSwapInterval(0); + //glfwSwapInterval(0); stbi_set_flip_vertically_on_load(true); diff --git a/src/kekengine/cpp/physics/physics.cpp b/src/kekengine/cpp/physics/physics.cpp index 6973b58..45e4ea6 100644 --- a/src/kekengine/cpp/physics/physics.cpp +++ b/src/kekengine/cpp/physics/physics.cpp @@ -38,11 +38,11 @@ void step(float deltaT) { } } - kekData.player->physics->jumpCollider->getWorldTransform().setOrigin(Physics::fromGLM(kekData.player->getFootPosition() + glm::vec3(0, KEK_PLAYER_RADIUS / 2, 0))); + //kekData.player->physics->jumpCollider->getWorldTransform().setOrigin(Physics::fromGLM(kekData.player->getFootPosition() + glm::vec3(0, KEK_PLAYER_RADIUS / 2, 0))); kekData.physics->world->stepSimulation(deltaT, 100); - kekData.player->onGround = kekData.player->physics->jumpCollider->getNumOverlappingObjects() > 1; // TODO: improve + //kekData.player->onGround = kekData.player->physics->jumpCollider->getNumOverlappingObjects() > 1; // TODO: improve if(!kekData.player->noclip) { kekData.activeCamera->moveTo(kekData.player->getEyePosition()); diff --git a/src/kekengine/cpp/player/defaultplayercontroller.cpp b/src/kekengine/cpp/player/defaultplayercontroller.cpp new file mode 100644 index 0000000..301169f --- /dev/null +++ b/src/kekengine/cpp/player/defaultplayercontroller.cpp @@ -0,0 +1,78 @@ +#include "defaultplayercontroller.h" + +#include "internal.h" +#include "internal/physics.h" + +#include +#include + +namespace kek { + +static bool castPlayer(glm::vec3 pos, glm::vec3 delta, const btCollisionObject **outBody, float *outFrac, glm::vec3 *outPoint, glm::vec3 *outNormal){ + btTransform from; + from.setIdentity(); + from.setOrigin(Physics::fromGLM(pos)); + + btTransform to; + to.setIdentity(); + to.setOrigin(Physics::fromGLM(pos + delta)); + + ClosestNotSelfConvexResultCallback cb = ClosestNotSelfConvexResultCallback(from.getOrigin(), to.getOrigin(), kekData.player->physics->body); + cb.m_collisionFilterGroup = -1; + cb.m_collisionFilterMask = -1; + kekData.physics->world->convexSweepTest((btConvexShape *) kekData.player->physics->body->getCollisionShape(), from, to, cb); + if(!cb.m_hitCollisionObject) return false; + + *outBody = cb.m_hitCollisionObject; + *outFrac = cb.m_closestHitFraction; + *outPoint = Physics::toGLM(cb.m_hitPointWorld); + *outNormal = Physics::toGLM(cb.m_hitNormalWorld); + return true; +} + +DefaultPlayerController::DefaultPlayerController() { + +} + +DefaultPlayerController::~DefaultPlayerController() { + +} + +glm::vec3 DefaultPlayerController::move(glm::vec3 movement) { + glm::vec3 pos = kekData.player->getPosition(); + + int count = 0; + while (count < 3) { + const btCollisionObject *object; + float frac; + glm::vec3 point; + glm::vec3 normal; + bool collision = castPlayer(pos, movement, &object, &frac, &point, &normal); + if(!collision) { + pos += movement; + break; + } + + normal = glm::normalize(normal); + + float angle = glm::angle(normal, glm::normalize(movement)) / M_PI; + + if(angle > 0.9) break; + + pos += movement * frac; + pos += normal * 0.001f; + + glm::vec3 remainingProjected = glm::normalize(glm::cross(normal, glm::cross(movement, normal))) * glm::length(movement) * (1 - frac); + movement = remainingProjected; + count++; + } + + kekData.player->moveTo(pos); + return pos; +} + +void DefaultPlayerController::update() { + move(glm::vec3(0, -10, 0) * kekData.lastFrameTime); +} + +} diff --git a/src/kekengine/cpp/object/player.cpp b/src/kekengine/cpp/player/player.cpp similarity index 88% rename from src/kekengine/cpp/object/player.cpp rename to src/kekengine/cpp/player/player.cpp index f9224dc..14064c1 100644 --- a/src/kekengine/cpp/object/player.cpp +++ b/src/kekengine/cpp/player/player.cpp @@ -1,5 +1,6 @@ #include "player.h" +#include "defaultplayercontroller.h" #include "internal/physics.h" namespace kek { @@ -7,6 +8,7 @@ namespace kek { Player::Player(): RotateableObject() { this->noclip = false; this->onGround = false; + this->controller = new DefaultPlayerController(); } void Player::rotateTo(glm::quat rotation) { diff --git a/src/kekengine/cpp/player/playercontroller.cpp b/src/kekengine/cpp/player/playercontroller.cpp new file mode 100644 index 0000000..2a644c5 --- /dev/null +++ b/src/kekengine/cpp/player/playercontroller.cpp @@ -0,0 +1,9 @@ +#include "playercontroller.h" + +namespace kek { + +PlayerController::~PlayerController() { + +} + +} diff --git a/src/kekengine/include/constants.h b/src/kekengine/include/constants.h index e2d36fb..3b3ba05 100644 --- a/src/kekengine/include/constants.h +++ b/src/kekengine/include/constants.h @@ -47,3 +47,5 @@ #define KEK_PLAYER_RADIUS 0.5f #define KEK_PLAYER_EYE_OFFSET (KEK_PLAYER_HEIGHT / 2 - KEK_PLAYER_RADIUS) #define KEK_PLAYER_MASS 50 +#define KEK_PLAYER_WALK_VELOCITY 6.0f +#define KEK_PLAYER_JUMP_VELOCITY 2.4f diff --git a/src/kekengine/include/defaultplayercontroller.h b/src/kekengine/include/defaultplayercontroller.h new file mode 100644 index 0000000..24b1a86 --- /dev/null +++ b/src/kekengine/include/defaultplayercontroller.h @@ -0,0 +1,18 @@ +#pragma once + +#include "playercontroller.h" + +namespace kek { + +class DefaultPlayerController: public PlayerController { + +public: + DefaultPlayerController(); + virtual ~DefaultPlayerController(); + + virtual glm::vec3 move(glm::vec3 movement); + virtual void update(); + +}; + +} diff --git a/src/kekengine/include/internal/physics.h b/src/kekengine/include/internal/physics.h index 077c190..8cd72a7 100644 --- a/src/kekengine/include/internal/physics.h +++ b/src/kekengine/include/internal/physics.h @@ -17,6 +17,36 @@ struct PlayerPhysicsObjectData: public PhysicsObjectData { btGhostObject *jumpCollider; }; +struct ClosestNotSelfConvexResultCallback : public btCollisionWorld::ConvexResultCallback { + ClosestNotSelfConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld, btCollisionObject *self) : + m_self(self), + m_convexFromWorld(convexFromWorld), + m_convexToWorld(convexToWorld), + m_hitCollisionObject(0){} + + btCollisionObject *m_self; + btVector3 m_convexFromWorld; //used to calculate hitPointWorld from hitFraction + btVector3 m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + const btCollisionObject* m_hitCollisionObject; + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace) { + if(convexResult.m_hitCollisionObject == m_self) return 1.0f; + m_closestHitFraction = convexResult.m_hitFraction; + m_hitCollisionObject = convexResult.m_hitCollisionObject; + if (normalInWorldSpace) { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + }else{ + ///need to transform normal into worldspace + m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal; + } + m_hitPointWorld = convexResult.m_hitPointLocal; + return convexResult.m_hitFraction; + } +}; + namespace Physics { glm::vec3 toGLM(btVector3 vec); diff --git a/src/kekengine/include/kekengine.h b/src/kekengine/include/kekengine.h index e8c750c..c876f77 100644 --- a/src/kekengine/include/kekengine.h +++ b/src/kekengine/include/kekengine.h @@ -3,6 +3,7 @@ #include "camera.h" #include "color.h" #include "constants.h" +#include "defaultplayercontroller.h" #include "engine.h" #include "errordialog.h" #include "fonts.h" @@ -13,6 +14,8 @@ #include "object.h" #include "objparser.h" #include "physics.h" +#include "player.h" +#include "playercontroller.h" #include "resource.h" #include "scene.h" #include "shader.h" diff --git a/src/kekengine/include/player.h b/src/kekengine/include/player.h index 24a79ef..9a3fc37 100644 --- a/src/kekengine/include/player.h +++ b/src/kekengine/include/player.h @@ -1,6 +1,7 @@ #pragma once #include "gameobject.h" +#include "playercontroller.h" namespace kek { @@ -8,6 +9,7 @@ class Player: public RotateableObject { public: PlayerPhysicsObjectData *physics; + PlayerController *controller; bool noclip; bool onGround; diff --git a/src/kekengine/include/playercontroller.h b/src/kekengine/include/playercontroller.h new file mode 100644 index 0000000..b6a819a --- /dev/null +++ b/src/kekengine/include/playercontroller.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace kek { + +class PlayerController { + +public: + virtual ~PlayerController() = 0; + + virtual glm::vec3 move(glm::vec3 movement) = 0; + virtual void update() = 0; + +}; + +} diff --git a/src/kekgame/cpp/kekgame.cpp b/src/kekgame/cpp/kekgame.cpp index 2952c4c..3c17f20 100644 --- a/src/kekgame/cpp/kekgame.cpp +++ b/src/kekgame/cpp/kekgame.cpp @@ -62,32 +62,42 @@ int main(int argc, char **argv) { scene->addObject(floor); } - Mesh *mesh = ObjParser::loadMesh("object/sphere/Sphere.obj"); + GameObject *wall = new GameObject(); + { + std::shared_ptr tex = Texture::load("image/white.png"); + wall->addMesh(genCubeMesh(1, 10, 50, tex, tex, tex)); + btCollisionShape *shape = new btBoxShape(btVector3(0.5,5,25)); + wall->addPhysics(shape, 0, btCollisionObject::CF_STATIC_OBJECT); + wall->moveTo(glm::vec3(0,5,0)); + scene->addObject(wall); + } + + /*Mesh *mesh = ObjParser::loadMesh("object/sphere/Sphere.obj"); GameObject *test = new GameObject(); btCollisionShape *shape = new btSphereShape(1); test->addPhysics(shape, 10); test->addMesh(mesh); test->moveTo(glm::vec3(0,5,0)); - scene->addObject(test); + scene->addObject(test);*/ - Mesh *mesh2 = ObjParser::loadMesh("object/cube_colored/Cube.obj"); + /*Mesh *mesh2 = ObjParser::loadMesh("object/cube_colored/Cube.obj"); GameObject *test3 = new GameObject(); btCollisionShape *shape2 = new btBoxShape(btVector3(1,1,1)); test3->addPhysics(shape2, 0, btCollisionObject::CF_STATIC_OBJECT); test3->addMesh(mesh2); test3->moveTo(glm::vec3(2, 1, 2)); - scene->addObject(test3); + scene->addObject(test3);*/ - for(int i = 0; i < 10; i++) { + /*for(int i = 0; i < 10; i++) { GameObject *test2 = new GameObject(); btCollisionShape *shape = new btBoxShape(btVector3(1,1,1)); test2->addPhysics(shape, 10); test2->addMesh(ObjParser::loadMesh("object/cube_colored/Cube.obj")); test2->moveTo(glm::vec3(1.0f, 5.0f, 3 * i)); scene->addObject(test2); - } + }*/ - PointLight *light = new PointLight(glm::vec3(1), 1, 0, 1); + PointLight *light = new PointLight(glm::vec3(1), 1, 0, 0.1); light->moveTo(glm::vec3(0,1,0)); scene->lights->add(light);