Add raycasting

This commit is contained in:
Dane Johnson 2021-04-21 18:27:30 -05:00
parent 84c4abbd94
commit fa20631e7b
5 changed files with 106 additions and 2 deletions

View File

@ -45,6 +45,7 @@ Rigidbody *Rigidbody::Instance() {
rigidbody->collisionShape = collisionShape; rigidbody->collisionShape = collisionShape;
rigidbody->btBody = new btRigidBody(rigidbody->mass, new RigidbodyMotionState(rigidbody), rigidbody->collisionShape); rigidbody->btBody = new btRigidBody(rigidbody->mass, new RigidbodyMotionState(rigidbody), rigidbody->collisionShape);
rigidbody->btBody->setAngularFactor(character ? 0.0f : 1.0f); rigidbody->btBody->setAngularFactor(character ? 0.0f : 1.0f);
rigidbody->btBody->setUserPointer(rigidbody);
World *world = World::GetWorld(); World *world = World::GetWorld();
world->AddRigidbody(rigidbody); world->AddRigidbody(rigidbody);
@ -119,8 +120,8 @@ void RigidbodyMotionState::getWorldTransform(btTransform &worldTrans) const {
void RigidbodyMotionState::setWorldTransform(const btTransform &worldTrans) { void RigidbodyMotionState::setWorldTransform(const btTransform &worldTrans) {
Transform transform = rigidbody->GetTransform(); Transform transform = rigidbody->GetTransform();
transform.position = Vector3(worldTrans.getOrigin().getX(), transform.position = Vector3(worldTrans.getOrigin().getX(),
worldTrans.getOrigin().getY(), worldTrans.getOrigin().getY(),
worldTrans.getOrigin().getZ()); worldTrans.getOrigin().getZ());
worldTrans.getRotation().getEulerZYX(transform.rotation.z, worldTrans.getRotation().getEulerZYX(transform.rotation.z,
transform.rotation.y, transform.rotation.y,

View File

@ -37,6 +37,26 @@ void World::Step(float delta) {
btWorld->stepSimulation(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::world { new World() };
World::World() { World::World() {

View File

@ -27,6 +27,13 @@
#include "Rigidbody.h" #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. 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 @param delta the time that has passed since the last physics update
*/ */
void Step(float delta); void Step(float delta);
RaycastResult Raycast(const Vector3 &from, const Vector3 &to);
private: private:
static World* world; static World* world;
// Some hocus pocus
btDiscreteDynamicsWorld *btWorld; btDiscreteDynamicsWorld *btWorld;
btDefaultCollisionConfiguration *collisionConfiguration; btDefaultCollisionConfiguration *collisionConfiguration;
btCollisionDispatcher *dispatcher; btCollisionDispatcher *dispatcher;
@ -55,6 +65,7 @@ private:
btSequentialImpulseConstraintSolver *solver; btSequentialImpulseConstraintSolver *solver;
World(); World();
~World(); ~World();
}; };
#endif /* WORLD_H */ #endif /* WORLD_H */

48
demo/shooter/main.lua Normal file
View File

@ -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

View File

@ -18,6 +18,17 @@
#include "Skybox.h" #include "Skybox.h"
#include "Rigidbody.h" #include "Rigidbody.h"
#include "CollisionShape.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 { class Vector3 {
@ -37,6 +48,19 @@ public:
} }
%ignore "Vector3"; %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 "types.h"
%include "constants.h" %include "constants.h"
%include "Node.h" %include "Node.h"