pandemonium_engine/modules/steering_ai/behaviors/gsai_avoid_collisions.cpp

169 lines
6.2 KiB
C++

#include "gsai_avoid_collisions.h"
GSAISteeringAgent GSAIAvoidCollisions::get_ *_first_neighbor() {
return *_first_neighbor;
}
void GSAIAvoidCollisions::set_ *_first_neighbor(const GSAISteeringAgent &val) {
*_first_neighbor = val;
}
float GSAIAvoidCollisions::get__shortest_time() const {
return _shortest_time;
}
void GSAIAvoidCollisions::set__shortest_time(const float val) {
_shortest_time = val;
}
float GSAIAvoidCollisions::get__first_minimum_separation() const {
return _first_minimum_separation;
}
void GSAIAvoidCollisions::set__first_minimum_separation(const float val) {
_first_minimum_separation = val;
}
float GSAIAvoidCollisions::get__first_distance() const {
return _first_distance;
}
void GSAIAvoidCollisions::set__first_distance(const float val) {
_first_distance = val;
}
Vector3 GSAIAvoidCollisions::get__first_relative_position() {
return _first_relative_position;
}
void GSAIAvoidCollisions::set__first_relative_position(const Vector3 &val) {
_first_relative_position = val;
}
Vector3 GSAIAvoidCollisions::get__first_relative_velocity() {
return _first_relative_velocity;
}
void GSAIAvoidCollisions::set__first_relative_velocity(const Vector3 &val) {
_first_relative_velocity = val;
}
// Steers the agent to avoid obstacles in its path. Approximates obstacles as;
// spheres.;
// @category - Group behaviors;
GSAISteeringAgent *_first_neighbor;
float _shortest_time = 0.0;
float _first_minimum_separation = 0.0;
float _first_distance = 0.0;
Vector3 _first_relative_position = ;
Vector3 _first_relative_velocity = ;
void GSAIAvoidCollisions::_calculate_steering(const GSAITargetAcceleration &acceleration) {
_shortest_time = INF;
_first_neighbor = null;
_first_minimum_separation = 0;
_first_distance = 0;
int neighbor_count = proximity.find_neighbors(_callback);
if (neighbor_count == 0 || not _first_neighbor) {
acceleration.set_zero();
}
else {
if ((_first_minimum_separation <= 0 || _first_distance < agent.bounding_radius + _first_neighbor.bounding_radius)) {
acceleration.linear = _first_neighbor.position - agent.position;
}
else {
acceleration.linear = (_first_relative_position + (_first_relative_velocity * _shortest_time));
}
}
acceleration.linear = (acceleration.linear.normalized() * -agent.linear_acceleration_max);
acceleration.angular = 0;
}
// Callback for the proximity to call when finding neighbors. Keeps track of every `neighbor`;
// that was found but only keeps the one the owning agent will most likely collide with.;
// @tags - virtual;
bool GSAIAvoidCollisions::_report_neighbor(const GSAISteeringAgent &neighbor) {
Vector3 relative_position = neighbor.position - agent.position;
Vector3 relative_velocity = neighbor.linear_velocity - agent.linear_velocity;
float relative_speed_squared = relative_velocity.length_squared();
if (relative_speed_squared == 0) {
return false;
}
else {
float time_to_collision = -relative_position.dot(relative_velocity) / relative_speed_squared;
if (time_to_collision <= 0 || time_to_collision >= _shortest_time) {
return false;
}
else {
Variant = relative_position.length();
float minimum_separation = (distance - sqrt(relative_speed_squared) * time_to_collision);
if (minimum_separation > agent.bounding_radius + neighbor.bounding_radius) {
return false;
}
else {
_shortest_time = time_to_collision;
_first_neighbor = neighbor;
_first_minimum_separation = minimum_separation;
_first_distance = distance;
_first_relative_position = relative_position;
_first_relative_velocity = relative_velocity;
return true;
}
}
}
}
}
GSAIAvoidCollisions::GSAIAvoidCollisions() {
*_first_neighbor;
_shortest_time = 0.0;
_first_minimum_separation = 0.0;
_first_distance = 0.0;
_first_relative_position = ;
_first_relative_velocity = ;
}
GSAIAvoidCollisions::~GSAIAvoidCollisions() {
}
static void GSAIAvoidCollisions::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_*_first_neighbor"), &GSAIAvoidCollisions::get_ * _first_neighbor);
ClassDB::bind_method(D_METHOD("set_*_first_neighbor", "value"), &GSAIAvoidCollisions::set_ * _first_neighbor);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*_first_neighbor", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_*_first_neighbor", "get_*_first_neighbor");
ClassDB::bind_method(D_METHOD("get__shortest_time"), &GSAIAvoidCollisions::get__shortest_time);
ClassDB::bind_method(D_METHOD("set__shortest_time", "value"), &GSAIAvoidCollisions::set__shortest_time);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_shortest_time"), "set__shortest_time", "get__shortest_time");
ClassDB::bind_method(D_METHOD("get__first_minimum_separation"), &GSAIAvoidCollisions::get__first_minimum_separation);
ClassDB::bind_method(D_METHOD("set__first_minimum_separation", "value"), &GSAIAvoidCollisions::set__first_minimum_separation);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_first_minimum_separation"), "set__first_minimum_separation", "get__first_minimum_separation");
ClassDB::bind_method(D_METHOD("get__first_distance"), &GSAIAvoidCollisions::get__first_distance);
ClassDB::bind_method(D_METHOD("set__first_distance", "value"), &GSAIAvoidCollisions::set__first_distance);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_first_distance"), "set__first_distance", "get__first_distance");
ClassDB::bind_method(D_METHOD("get__first_relative_position"), &GSAIAvoidCollisions::get__first_relative_position);
ClassDB::bind_method(D_METHOD("set__first_relative_position", "value"), &GSAIAvoidCollisions::set__first_relative_position);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_first_relative_position"), "set__first_relative_position", "get__first_relative_position");
ClassDB::bind_method(D_METHOD("get__first_relative_velocity"), &GSAIAvoidCollisions::get__first_relative_velocity);
ClassDB::bind_method(D_METHOD("set__first_relative_velocity", "value"), &GSAIAvoidCollisions::set__first_relative_velocity);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_first_relative_velocity"), "set__first_relative_velocity", "get__first_relative_velocity");
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAIAvoidCollisions::_calculate_steering);
ClassDB::bind_method(D_METHOD("_report_neighbor", "neighbor"), &GSAIAvoidCollisions::_report_neighbor);
}