Skip to content

Commit

Permalink
Obstacle avoidance behaviour is in (that should be all behaviors)
Browse files Browse the repository at this point in the history
  • Loading branch information
d0n3val committed Sep 1, 2016
1 parent 4febf42 commit cb59ef8
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Game/default.eduscene

Large diffs are not rendered by default.

72 changes: 64 additions & 8 deletions Source/ComponentSteering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ void ComponentSteering::OnSave(Config& config) const
config.AddUInt("Path", (path) ? path->GetGameObject()->GetUID() : 0);
config.AddFloat("Path Offset", path_offset);
config.AddFloat("Path Prediction", path_prediction);

config.AddFloat("Separation Radius", separation_radius);

config.AddFloat("Obstacle Distance", obstacle_avoid_distance);
config.AddFloat("Obstacle Detector", obstacle_detector_len);
}

// ---------------------------------------------------------
Expand All @@ -72,6 +77,9 @@ void ComponentSteering::OnLoad(Config * config)

path_offset = config->GetFloat("Path Offset", 0.1f);
path_prediction = config->GetFloat("Path Prediction", 0.0f);
separation_radius = config->GetFloat("Separation Radius", 10.0f);
obstacle_avoid_distance = config->GetFloat("Obstacle Distance", 3.0f);
obstacle_detector_len = config->GetFloat("Obstacle Detector", 3.0f);
}

// ---------------------------------------------------------
Expand Down Expand Up @@ -157,9 +165,11 @@ void ComponentSteering::OnUpdate(float dt)
mov_velocity += Separation();
break;
case ComponentSteering::collision_avoidance:
//mov_velocity += Arrive(Pursue(goal->GetGlobalPosition(), goal->GetVelocity()));
mov_velocity += CollisionAvoidance();
break;
case ComponentSteering::obstacle_avoidance:
mov_velocity += ObstacleAvoidance();
break;
case ComponentSteering::unknown:
break;
default:
Expand Down Expand Up @@ -253,8 +263,6 @@ void ComponentSteering::OnDebugDraw(bool selected) const
} break;
case separation:
{
DebugDraw(Circle(game_object->GetGlobalPosition(), float3::unitY, separation_radius));

vector<GameObject*> results;
App->level->FindNear(game_object->GetGlobalPosition(), separation_radius, results);

Expand All @@ -270,11 +278,30 @@ void ComponentSteering::OnDebugDraw(bool selected) const
DebugDrawArrow(direction.Normalized() * force, offset, Green, game_object->GetGlobalTransformation());
}
}
} break;
} // fallback
case collision_avoidance:
{
DebugDraw(Circle(game_object->GetGlobalPosition(), float3::unitY, separation_radius));

} break;
case obstacle_avoidance:
{
float3 a = game_object->GetGlobalTransformation().TransformPos(float3::unitZ * game_object->GetRadius());
float3 b = game_object->GetGlobalTransformation().TransformPos(float3::unitZ * (game_object->GetRadius() + obstacle_detector_len));

LineSegment detector(a, b);
DebugDraw(detector, Yellow);

float dist;
float3 normal;
const GameObject* go = App->level->CastRayOnBoundingBoxes(detector, dist, normal);

if (go != nullptr)
{
float3 hit_pos = detector.GetPoint(dist);
float3 ret = hit_pos + normal * obstacle_avoid_distance;
DebugDraw(LineSegment(hit_pos, ret), Yellow);
DebugDraw(Circle(ret, float3::unitY, 2.0f), Red);
}
} break;
}
}
Expand Down Expand Up @@ -495,7 +522,7 @@ float3 ComponentSteering::CollisionAvoidance() const
vector<GameObject*> results;
App->level->FindNear(game_object->GetGlobalPosition(), separation_radius, results);

float smallest_collision_time = -inf;
float smallest_collision_time = inf;
const GameObject* go_to_avoid = nullptr;
float3 smallest_relative_vel;
float3 smallest_relative_pos;
Expand Down Expand Up @@ -556,15 +583,38 @@ float3 ComponentSteering::CollisionAvoidance() const
return ret;
}

// ---------------------------------------------------------
float3 ComponentSteering::ObstacleAvoidance() const
{
float3 ret = float3::zero;

float3 a = game_object->GetGlobalTransformation().TransformPos(float3::unitZ * game_object->GetRadius());
float3 b = game_object->GetGlobalTransformation().TransformPos(float3::unitZ * (game_object->GetRadius() + obstacle_detector_len));

LineSegment detector(a, b);

float dist;
float3 normal;
const GameObject* go = App->level->CastRayOnBoundingBoxes(detector, dist, normal);

if (go != nullptr)
{
float3 hit_pos = detector.GetPoint(dist);
ret = hit_pos + normal * obstacle_avoid_distance;
}

return ret;
}

// ---------------------------------------------------------
void ComponentSteering::DrawEditor()
{
static_assert(Behaviour::unknown == 14, "code needs update");
static_assert(Behaviour::unknown == 15, "code needs update");

static const char* behaviours[] = {
"Seek", "Flee", "Arrive", "Align", "UnAlign", "Match Velocity",
"Pursue", "Evade", "Face", "Look Ahead", "Wander", "Follow Path",
"Separation", "Collision Avoidance", "Unknown" };
"Separation", "Collision Avoidance", "Obstacle Avoidance", "Unknown" };

int behaviour_type = behaviour;
if (ImGui::Combo("Behaviour", &behaviour_type, behaviours, (int) Behaviour::unknown))
Expand Down Expand Up @@ -673,6 +723,12 @@ void ComponentSteering::DrawEditor()
{
ImGui::DragFloat("Radius", &separation_radius, 0.1f, 0.1f);
} break;

case obstacle_avoidance:
{
ImGui::DragFloat("Detector Len", &obstacle_detector_len, 0.01f, 1.0f, 50.0f);
ImGui::DragFloat("Distance", &obstacle_avoid_distance, 0.01f, 1.0f, 10.0f);
}
}

// Curve editor! ---
Expand Down
5 changes: 5 additions & 0 deletions Source/ComponentSteering.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ComponentSteering : public Component
follow_path,
separation,
collision_avoidance,
obstacle_avoidance,
unknown
};

Expand Down Expand Up @@ -64,6 +65,7 @@ class ComponentSteering : public Component
float3 FollowPath() const;
float3 Separation() const;
float3 CollisionAvoidance() const;
float3 ObstacleAvoidance() const;

private:
uint goal_uid = 0;
Expand Down Expand Up @@ -102,6 +104,9 @@ class ComponentSteering : public Component

float separation_radius = 10.0f;

float obstacle_detector_len = 5.0f;
float obstacle_avoid_distance = 5.0f;

private:

Behaviour behaviour = Behaviour::seek;
Expand Down
8 changes: 8 additions & 0 deletions Source/GameObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,3 +737,11 @@ float3 GameObject::GetVelocity() const
{
return velocity;
}

// ---------------------------------------------------------
float GameObject::GetRadius() const
{
if(global_bbox.IsFinite())
return global_bbox.HalfDiagonal().Length();
return 0.0f;
}
1 change: 1 addition & 0 deletions Source/GameObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class GameObject
bool HasComponent(Component::Types type) const;

float3 GetVelocity() const;
float GetRadius() const;

private:
AABB local_bbox;
Expand Down
39 changes: 39 additions & 0 deletions Source/ModuleLevelManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,36 @@ GameObject* ModuleLevelManager::CastRay(const LineSegment& segment, float& dist)
return candidate;
}

void ModuleLevelManager::RecursiveTestRayBBox(const LineSegment & segment, float & dist, float3 & normal, GameObject ** best_candidate) const
{
map<float, GameObject*> objects;
quadtree.CollectIntersections(objects, segment);

for (map<float, GameObject*>::const_iterator it = objects.begin(); it != objects.end(); ++it)
{
// Look for meshes
GameObject* go = it->second;
if (go->HasComponent(Component::Types::Geometry) == true)
{
float closer = inf;
*best_candidate = (GameObject*) go;
dist = it->first;

// let's find out the plane that hit the segment and fill in the normal
for (int i = 0; i < 6; ++i)
{
Plane p(go->global_bbox.FacePlane(i));
float d;
if (p.Intersects(segment, &d))
{
if (d < closer)
normal = p.normal;
}
}
}
}
}

void ModuleLevelManager::RecursiveTestRay(const LineSegment& segment, float& dist, GameObject** best_candidate) const
{
map<float, GameObject*> objects;
Expand Down Expand Up @@ -413,6 +443,15 @@ GameObject* ModuleLevelManager::CastRay(const Ray & ray, float& dist) const
return candidate;
}

GameObject * ModuleLevelManager::CastRayOnBoundingBoxes(const LineSegment & segment, float & dist, float3 & normal) const
{
dist = inf;
normal = float3::zero;
GameObject* candidate = nullptr;
RecursiveTestRayBBox(segment, dist, normal, &candidate);
return candidate;
}

void ModuleLevelManager::RecursiveTestRay(const Ray& ray, float& dist, GameObject** best_candidate) const
{
map<float, GameObject*> objects;
Expand Down
2 changes: 2 additions & 0 deletions Source/ModuleLevelManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ class ModuleLevelManager : public Module
GameObject* Validate(const GameObject* pointer) const;
GameObject* CastRay(const LineSegment& segment, float& dist) const;
GameObject* CastRay(const Ray& ray, float& dist) const;
GameObject* CastRayOnBoundingBoxes(const LineSegment& segment, float& dist, float3& normal) const;
void FindNear(const float3& position, float radius, std::vector<GameObject*>& results) const;

private:
void RecursiveTestRayBBox(const LineSegment& segment, float& dist, float3& normal, GameObject** best_candidate) const;
void RecursiveTestRay(const LineSegment& segment, float& dist, GameObject** best_candidate) const;
void RecursiveTestRay(const Ray& ray, float& dist, GameObject** best_candidate) const;
void RecursiveDrawGameObjects(const GameObject* go) const;
Expand Down

0 comments on commit cb59ef8

Please sign in to comment.