Vehicle & destructible bullet hitboxes
This commit is contained in:
parent
8c52678e79
commit
45cf603c83
@ -21,6 +21,10 @@ static collision::Material GetMaterialByName(const std::string& name)
|
|||||||
return collision::PM_GLASS;
|
return collision::PM_GLASS;
|
||||||
else if (name == "flesh")
|
else if (name == "flesh")
|
||||||
return collision::PM_FLESH;
|
return collision::PM_FLESH;
|
||||||
|
else if (name == "car") // TODO: make new material for cars
|
||||||
|
return collision::PM_METAL;
|
||||||
|
else if (name == "carwindow")
|
||||||
|
return collision::PM_NONE;
|
||||||
else
|
else
|
||||||
return collision::PM_STONE;
|
return collision::PM_STONE;
|
||||||
}
|
}
|
||||||
@ -35,7 +39,7 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
|
|||||||
std::unique_ptr<btConvexHullShape> temp_hull;
|
std::unique_ptr<btConvexHullShape> temp_hull;
|
||||||
std::unique_ptr<btCompoundShape> compound;
|
std::unique_ptr<btCompoundShape> compound;
|
||||||
|
|
||||||
bool current_collision = true;
|
collision::Material col_material = collision::PM_NONE;
|
||||||
|
|
||||||
LoadCMDFile(filename, [&](const std::string& command, std::istringstream& iss) {
|
LoadCMDFile(filename, [&](const std::string& command, std::istringstream& iss) {
|
||||||
if (command == "v")
|
if (command == "v")
|
||||||
@ -91,7 +95,7 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
|
|||||||
mb.AddTriangle(t);
|
mb.AddTriangle(t);
|
||||||
)
|
)
|
||||||
|
|
||||||
if (current_collision && model->cmesh_)
|
if (model->cmesh_)
|
||||||
{
|
{
|
||||||
glm::vec3 p[3];
|
glm::vec3 p[3];
|
||||||
for (size_t i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i)
|
||||||
@ -225,19 +229,18 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
|
|||||||
{
|
{
|
||||||
std::string pm_name;
|
std::string pm_name;
|
||||||
iss >> pm_name;
|
iss >> pm_name;
|
||||||
if (pm_name == "none")
|
|
||||||
|
if (model->cmesh_)
|
||||||
{
|
{
|
||||||
current_collision = false;
|
model->cmesh_->BeginMaterial(GetMaterialByName(pm_name));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_collision = true;
|
|
||||||
if (model->cmesh_)
|
|
||||||
{
|
|
||||||
model->cmesh_->BeginMaterial(GetMaterialByName(pm_name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (command == "cpm")
|
||||||
|
{
|
||||||
|
std::string pm_name;
|
||||||
|
iss >> pm_name;
|
||||||
|
col_material = GetMaterialByName(pm_name);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Unknown command in model file: " + command);
|
throw std::runtime_error("Unknown command in model file: " + command);
|
||||||
@ -268,6 +271,13 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
|
|||||||
model->cshape_ = std::move(compound);
|
model->cshape_ = std::move(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model->cshape_)
|
||||||
|
{
|
||||||
|
collision::SetShapeMaterial(*model->cshape_, col_material);
|
||||||
|
if (col_material != collision::PM_NONE)
|
||||||
|
model->cshape_is_bullet_target_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public:
|
|||||||
const glm::vec3& GetColOffset() const { return col_offset_; }
|
const glm::vec3& GetColOffset() const { return col_offset_; }
|
||||||
const collision::TriangleMesh* GetColMesh() const { return cmesh_.get(); }
|
const collision::TriangleMesh* GetColMesh() const { return cmesh_.get(); }
|
||||||
btCollisionShape* GetColShape() const { return cshape_.get(); }
|
btCollisionShape* GetColShape() const { return cshape_.get(); }
|
||||||
|
bool IsColShapeBulletTarget() const { return cshape_is_bullet_target_; }
|
||||||
|
|
||||||
const std::shared_ptr<const Skeleton>& GetSkeleton() const { return skeleton_; }
|
const std::shared_ptr<const Skeleton>& GetSkeleton() const { return skeleton_; }
|
||||||
CLIENT_ONLY(const std::shared_ptr<const Mesh>& GetMesh() const { return mesh_; })
|
CLIENT_ONLY(const std::shared_ptr<const Mesh>& GetMesh() const { return mesh_; })
|
||||||
@ -60,6 +61,7 @@ private:
|
|||||||
// std::vector<ModelCollisionShape> cshapes_;
|
// std::vector<ModelCollisionShape> cshapes_;
|
||||||
std::vector<std::unique_ptr<btCollisionShape>> subshapes_;
|
std::vector<std::unique_ptr<btCollisionShape>> subshapes_;
|
||||||
std::unique_ptr<btCollisionShape> cshape_;
|
std::unique_ptr<btCollisionShape> cshape_;
|
||||||
|
bool cshape_is_bullet_target_ = false;
|
||||||
|
|
||||||
std::shared_ptr<const Skeleton> skeleton_;
|
std::shared_ptr<const Skeleton> skeleton_;
|
||||||
CLIENT_ONLY(std::shared_ptr<const Mesh> mesh_;);
|
CLIENT_ONLY(std::shared_ptr<const Mesh> mesh_;);
|
||||||
|
|||||||
@ -9,6 +9,7 @@ namespace collision
|
|||||||
|
|
||||||
enum Material : uint8_t
|
enum Material : uint8_t
|
||||||
{
|
{
|
||||||
|
PM_NONE,
|
||||||
PM_STONE,
|
PM_STONE,
|
||||||
PM_DIRT,
|
PM_DIRT,
|
||||||
PM_GRASS,
|
PM_GRASS,
|
||||||
|
|||||||
@ -11,6 +11,9 @@ void collision::TriangleMesh::BeginMaterial(Material material)
|
|||||||
|
|
||||||
void collision::TriangleMesh::AddTriangle(const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2)
|
void collision::TriangleMesh::AddTriangle(const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2)
|
||||||
{
|
{
|
||||||
|
if (current_material_ == PM_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
btVector3 bt_v0(v0.x, v0.y, v0.z);
|
btVector3 bt_v0(v0.x, v0.y, v0.z);
|
||||||
btVector3 bt_v1(v1.x, v1.y, v1.z);
|
btVector3 bt_v1(v1.x, v1.y, v1.z);
|
||||||
btVector3 bt_v2(v2.x, v2.y, v2.z);
|
btVector3 bt_v2(v2.x, v2.y, v2.z);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public:
|
|||||||
btBvhTriangleMeshShape* GetShape() const { return bt_shape_.get(); }
|
btBvhTriangleMeshShape* GetShape() const { return bt_shape_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Material current_material_ = PM_STONE;
|
Material current_material_ = PM_NONE;
|
||||||
btTriangleMesh bt_mesh_;
|
btTriangleMesh bt_mesh_;
|
||||||
std::unique_ptr<btBvhTriangleMeshShape> bt_shape_;
|
std::unique_ptr<btBvhTriangleMeshShape> bt_shape_;
|
||||||
std::vector<Material> tri_materials_;
|
std::vector<Material> tri_materials_;
|
||||||
|
|||||||
@ -76,11 +76,19 @@ game::MapObjectCollision::MapObjectCollision(collision::DynamicsWorld& world,
|
|||||||
model_->GetParamFloat("destr_th", destr_th_);
|
model_->GetParamFloat("destr_th", destr_th_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
col_group_ = collision::OG_DEFAULT;
|
||||||
|
col_mask_ = collision::OG_ALL;
|
||||||
|
|
||||||
// prefer simple cshape which allow destruction
|
// prefer simple cshape which allow destruction
|
||||||
if (cshape)
|
if (cshape)
|
||||||
{
|
{
|
||||||
body_ = std::make_unique<btRigidBody>(
|
body_ = std::make_unique<btRigidBody>(
|
||||||
btRigidBody::btRigidBodyConstructionInfo(mass, nullptr, cshape, local_inertia));
|
btRigidBody::btRigidBodyConstructionInfo(mass, nullptr, cshape, local_inertia));
|
||||||
|
|
||||||
|
if (!model_->IsColShapeBulletTarget())
|
||||||
|
{
|
||||||
|
col_mask_ &= ~collision::OG_PROJECTILE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cmesh)
|
else if (cmesh)
|
||||||
{
|
{
|
||||||
@ -96,7 +104,7 @@ game::MapObjectCollision::MapObjectCollision(collision::DynamicsWorld& world,
|
|||||||
collision::SetObjectInfo(body_.get(), collision::OT_MAP_OBJECT, oflags, this);
|
collision::SetObjectInfo(body_.get(), collision::OT_MAP_OBJECT, oflags, this);
|
||||||
|
|
||||||
// world_.GetBtWorld().addRigidBody(body_.get(), btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter);
|
// world_.GetBtWorld().addRigidBody(body_.get(), btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter);
|
||||||
world_.GetBtWorld().addRigidBody(body_.get());
|
world_.GetBtWorld().addRigidBody(body_.get(), col_group_, col_mask_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::MapObjectCollision::Break()
|
void game::MapObjectCollision::Break()
|
||||||
@ -122,7 +130,7 @@ void game::MapObjectCollision::Break()
|
|||||||
|
|
||||||
collision::SetObjectInfo(body_.get(), collision::OT_UNDEFINED, 0, this);
|
collision::SetObjectInfo(body_.get(), collision::OT_UNDEFINED, 0, this);
|
||||||
|
|
||||||
world_.GetBtWorld().addRigidBody(body_.get());
|
world_.GetBtWorld().addRigidBody(body_.get(), col_group_, col_mask_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::MapObjectCollision::GetModelTransform(Transform& trans) const
|
void game::MapObjectCollision::GetModelTransform(Transform& trans) const
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public:
|
|||||||
net::ObjNum GetNum() const { return num_; }
|
net::ObjNum GetNum() const { return num_; }
|
||||||
float GetDestroyThreshold() const { return destr_th_; }
|
float GetDestroyThreshold() const { return destr_th_; }
|
||||||
|
|
||||||
|
int col_group_ = 0, col_mask_ = 0;
|
||||||
|
|
||||||
virtual ~MapObjectCollision() override;
|
virtual ~MapObjectCollision() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -38,6 +38,11 @@ void game::Vehicle::Update()
|
|||||||
{
|
{
|
||||||
Super::Update();
|
Super::Update();
|
||||||
|
|
||||||
|
if (physics_)
|
||||||
|
{
|
||||||
|
physics_->Update();
|
||||||
|
}
|
||||||
|
|
||||||
root_.UpdateMatrix();
|
root_.UpdateMatrix();
|
||||||
|
|
||||||
flags_ = 0;
|
flags_ = 0;
|
||||||
@ -99,7 +104,7 @@ void game::Vehicle::OnBulletHit(const game::BulletInfo& bullet, const btCollisio
|
|||||||
if (!physics_)
|
if (!physics_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto impulse = glm::normalize(bullet.end - bullet.start) * 10000.0f;
|
auto impulse = glm::normalize(bullet.end - bullet.start) * 100.0f;
|
||||||
physics_->GetBtBody().activate();
|
physics_->GetBtBody().activate();
|
||||||
physics_->GetBtBody().applyCentralImpulse(btVector3(impulse.x, impulse.y, impulse.z));
|
physics_->GetBtBody().applyCentralImpulse(btVector3(impulse.x, impulse.y, impulse.z));
|
||||||
}
|
}
|
||||||
@ -728,6 +733,25 @@ game::VehiclePhysics::VehiclePhysics(collision::DynamicsWorld& world, Transform&
|
|||||||
bt_world.addRigidBody(body_.get(), collision::OG_DEFAULT, ~collision::OG_PROJECTILE);
|
bt_world.addRigidBody(body_.get(), collision::OG_DEFAULT, ~collision::OG_PROJECTILE);
|
||||||
bt_world.addAction(vehicle_.get());
|
bt_world.addAction(vehicle_.get());
|
||||||
|
|
||||||
|
|
||||||
|
// make bullet hitbox
|
||||||
|
auto col_mesh = model.GetModel()->GetColMesh();
|
||||||
|
if (col_mesh)
|
||||||
|
{
|
||||||
|
bullet_hitbox_ = std::make_unique<btCollisionObject>();
|
||||||
|
bullet_hitbox_->setCollisionShape(col_mesh->GetShape());
|
||||||
|
collision::SetObjectInfo(bullet_hitbox_.get(), collision::OT_ENTITY, 0, &obj_cb);
|
||||||
|
|
||||||
|
bt_world.addCollisionObject(bullet_hitbox_.get(), collision::OG_DEFAULT, collision::OG_PROJECTILE);
|
||||||
|
|
||||||
|
UpdateBulletHitboxTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::VehiclePhysics::Update()
|
||||||
|
{
|
||||||
|
UpdateBulletHitboxTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
game::VehiclePhysics::~VehiclePhysics()
|
game::VehiclePhysics::~VehiclePhysics()
|
||||||
@ -735,4 +759,17 @@ game::VehiclePhysics::~VehiclePhysics()
|
|||||||
auto& bt_world = world_.GetBtWorld();
|
auto& bt_world = world_.GetBtWorld();
|
||||||
bt_world.removeRigidBody(body_.get());
|
bt_world.removeRigidBody(body_.get());
|
||||||
bt_world.removeAction(vehicle_.get());
|
bt_world.removeAction(vehicle_.get());
|
||||||
|
|
||||||
|
if (bullet_hitbox_)
|
||||||
|
{
|
||||||
|
bt_world.removeCollisionObject(bullet_hitbox_.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::VehiclePhysics::UpdateBulletHitboxTransform()
|
||||||
|
{
|
||||||
|
if (!bullet_hitbox_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bullet_hitbox_->setWorldTransform(body_->getWorldTransform());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,16 +41,22 @@ public:
|
|||||||
|
|
||||||
DELETE_COPY_MOVE(VehiclePhysics)
|
DELETE_COPY_MOVE(VehiclePhysics)
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
btRigidBody& GetBtBody() { return *body_; }
|
btRigidBody& GetBtBody() { return *body_; }
|
||||||
collision::RaycastVehicle& GetBtVehicle() { return *vehicle_; }
|
collision::RaycastVehicle& GetBtVehicle() { return *vehicle_; }
|
||||||
|
|
||||||
~VehiclePhysics();
|
~VehiclePhysics();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateBulletHitboxTransform();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
collision::DynamicsWorld& world_;
|
collision::DynamicsWorld& world_;
|
||||||
collision::MotionState motion_;
|
collision::MotionState motion_;
|
||||||
std::unique_ptr<btRigidBody> body_;
|
std::unique_ptr<btRigidBody> body_;
|
||||||
std::unique_ptr<collision::RaycastVehicle> vehicle_;
|
std::unique_ptr<collision::RaycastVehicle> vehicle_;
|
||||||
|
std::unique_ptr<btCollisionObject> bullet_hitbox_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Vehicle : public Entity
|
class Vehicle : public Entity
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user