diff --git a/core/Rigidbody.cpp b/core/Rigidbody.cpp index cf04bbd..2b8624a 100644 --- a/core/Rigidbody.cpp +++ b/core/Rigidbody.cpp @@ -45,6 +45,7 @@ Rigidbody *Rigidbody::Instance() { rigidbody->collisionShape = collisionShape; rigidbody->btBody = new btRigidBody(rigidbody->mass, new RigidbodyMotionState(rigidbody), rigidbody->collisionShape); rigidbody->btBody->setAngularFactor(character ? 0.0f : 1.0f); + rigidbody->btBody->setUserPointer(rigidbody); World *world = World::GetWorld(); world->AddRigidbody(rigidbody); @@ -119,8 +120,8 @@ void RigidbodyMotionState::getWorldTransform(btTransform &worldTrans) const { void RigidbodyMotionState::setWorldTransform(const btTransform &worldTrans) { Transform transform = rigidbody->GetTransform(); transform.position = Vector3(worldTrans.getOrigin().getX(), - worldTrans.getOrigin().getY(), - worldTrans.getOrigin().getZ()); + worldTrans.getOrigin().getY(), + worldTrans.getOrigin().getZ()); worldTrans.getRotation().getEulerZYX(transform.rotation.z, transform.rotation.y, diff --git a/core/World.cpp b/core/World.cpp index cac4579..661416f 100644 --- a/core/World.cpp +++ b/core/World.cpp @@ -37,6 +37,26 @@ void World::Step(float delta) { btWorld->stepSimulation(delta); } +RaycastResult World::Raycast(const Vector3 &from, const Vector3 &to) { + RaycastResult rcr; + btVector3 btFrom = btVector3(from.x, from.y, from.z); + btVector3 btTo = btVector3(to.x, to.y, to.z); + btCollisionWorld::ClosestRayResultCallback rayCallback(btFrom, btTo); + rayCallback.m_collisionFilterGroup = -1; // Everything + btWorld->rayTest(btFrom, btTo, rayCallback); + rcr.hit = rayCallback.hasHit(); + if (rcr.hit) { + rcr.position = Vector3(rayCallback.m_hitPointWorld.getX(), + rayCallback.m_hitPointWorld.getY(), + rayCallback.m_hitPointWorld.getZ()); + rcr.normal = Vector3(rayCallback.m_hitNormalWorld.getX(), + rayCallback.m_hitNormalWorld.getY(), + rayCallback.m_hitNormalWorld.getZ()); + rcr.object = (Rigidbody*) rayCallback.m_collisionObject->getUserPointer(); + } + return rcr; +} + World* World::world { new World() }; World::World() { diff --git a/core/World.h b/core/World.h index 8c709a5..cb95d5d 100644 --- a/core/World.h +++ b/core/World.h @@ -27,6 +27,13 @@ #include "Rigidbody.h" +struct RaycastResult { + bool hit; + Vector3 position; + Vector3 normal; + Rigidbody *object; +}; + /** World is the object that performs the rigidbody physics simulation. Presently there is only one world. */ @@ -46,8 +53,11 @@ public: @param delta the time that has passed since the last physics update */ void Step(float delta); + + RaycastResult Raycast(const Vector3 &from, const Vector3 &to); private: static World* world; + // Some hocus pocus btDiscreteDynamicsWorld *btWorld; btDefaultCollisionConfiguration *collisionConfiguration; btCollisionDispatcher *dispatcher; @@ -55,6 +65,7 @@ private: btSequentialImpulseConstraintSolver *solver; World(); ~World(); + }; #endif /* WORLD_H */ diff --git a/demo/shooter/main.lua b/demo/shooter/main.lua new file mode 100644 index 0000000..6fce558 --- /dev/null +++ b/demo/shooter/main.lua @@ -0,0 +1,48 @@ +package.path = package.path .. ";../scripts/?.lua" +local freecam = require("freecam") +local Vector3 = couch.Vector3 + +function init() + freecam.init_camera() + + local light = couch.DirectionalLight() + light:SetDirection(Vector3(1.0, -2.0, -1.0)) + light:SetColor(Vector3(1.0, 1.0, 1.0)) + light:SetAmbient(0.2) + light:SetDiffuse(1.0) + light:SetSpecular(0.1) + couch.Node.GetRoot():AddChild(light:Instance()) + + local box_mesh = couch.TexturedMesh("../resources/cube.obj", "../resources/paintedwood.jpg") + local box = couch.Rigidbody() + box:SetCollisionShape(couch.BoxCollisionShape(1, 1, 1)) + box:AddChild(box_mesh) + couch.Node.GetRoot():AddChild(box:Instance()) + + local ground = couch.Rigidbody() + ground:SetCollisionShape(couch.BoxCollisionShape(100, 0.1, 100)) + ground:Translate(Vector3(0.0, -1.0, 0.0)) + ground:SetMass(0.0) + couch.Node.GetRoot():AddChild(ground:Instance()) +end + +function update(delta) + freecam.update_camera(delta) +end + +function onkey(key, code, action, mod) + freecam.onkey(key, code, action, mod) + local camera_transform = freecam.camera:GetTransform() + if action == couch.ACTION_PRESS and key == couch.KEY_R then + local res = couch.World.GetWorld():Raycast(camera_transform.position, + camera_transform.position + camera_transform:Forward() * 100.0) + if (res.hit) then + res.object:ApplyImpulse(res.normal * -100.0) + end + end +end + +function onmousemotion(_, _, relx, rely) + freecam.onmousemotion(relx, rely) +end + diff --git a/scripting/couch.i b/scripting/couch.i index 884142a..bf29990 100644 --- a/scripting/couch.i +++ b/scripting/couch.i @@ -18,6 +18,17 @@ #include "Skybox.h" #include "Rigidbody.h" #include "CollisionShape.h" +struct RaycastResult { + bool hit; + Vector3 position; + Vector3 normal; + Rigidbody *object; +}; +class World { +public: + static World* GetWorld(); + RaycastResult Raycast(const Vector3 &from, const Vector3 &to); +}; %} class Vector3 { @@ -37,6 +48,19 @@ public: } %ignore "Vector3"; +struct RaycastResult { + bool hit; + Vector3 position; + Vector3 normal; + Rigidbody *object; +}; +class World { +public: + static World* GetWorld(); + RaycastResult Raycast(const Vector3 &from, const Vector3 &to); +}; + + %include "types.h" %include "constants.h" %include "Node.h"