| Index: experimental/flocking_geese/nacl_app/goose.cc
|
| diff --git a/experimental/flocking_geese/nacl_app/goose.cc b/experimental/flocking_geese/nacl_app/goose.cc
|
| deleted file mode 100644
|
| index 1250caa404e365882943307a694eea8ef59d9d5d..0000000000000000000000000000000000000000
|
| --- a/experimental/flocking_geese/nacl_app/goose.cc
|
| +++ /dev/null
|
| @@ -1,201 +0,0 @@
|
| -// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "nacl_app/goose.h"
|
| -
|
| -namespace {
|
| -// The maximum speed of a goose. Measured in meters/second.
|
| -const double kMaxSpeed = 2.0;
|
| -
|
| -// The maximum force that can be applied to turn a goose when computing the
|
| -// aligment. Measured in meters/second/second.
|
| -const double kMaxTurningForce = 0.05;
|
| -
|
| -// The neighbour radius of a goose. Only geese within this radius will affect
|
| -// the flocking computations of this goose. Measured in pixels.
|
| -const double kNeighbourRadius = 64.0;
|
| -
|
| -// The minimum distance that a goose can be from this goose. If another goose
|
| -// comes within this distance of this goose, the flocking algorithm tries to
|
| -// move the geese apart. Measured in pixels.
|
| -const double kPersonalSpace = 32.0;
|
| -
|
| -// The distance at which attractors have effect on a goose's direction.
|
| -const double kAttractorRadius = 320.0;
|
| -
|
| -// The goose will try to turn towards geese within this distance (computed
|
| -// during the cohesion phase). Measured in pixels.
|
| -const double kMaxTurningDistance = 100.0;
|
| -
|
| -// The weights used when computing the weighted sum the three flocking
|
| -// components.
|
| -const double kSeparationWeight = 2.0;
|
| -const double kAlignmentWeight = 1.0;
|
| -const double kCohesionWeight = 1.0;
|
| -
|
| -} // namespace
|
| -
|
| -namespace flocking_geese {
|
| -
|
| -Goose::Goose() : location_(0, 0) {
|
| - velocity_ = Vector2::RandomUnit();
|
| -}
|
| -
|
| -Goose::Goose(const Vector2& location) : location_(location) {
|
| - velocity_ = Vector2::RandomUnit();
|
| -}
|
| -
|
| -void Goose::SimulationTick(const std::vector<Goose>& geese,
|
| - const std::vector<Vector2>& attractors,
|
| - const pp::Rect& flockBox) {
|
| - Vector2 acceleration = Flock(geese, attractors);
|
| - velocity_.Add(acceleration);
|
| - // Limit the velocity to a maximum speed.
|
| - velocity_.Clamp(kMaxSpeed);
|
| - location_.Add(velocity_);
|
| - // Wrap the goose location to the flock box.
|
| - if (!flockBox.IsEmpty()) {
|
| - if (location_.x() < flockBox.x()) {
|
| - location_.set_x(flockBox.right() - 1);
|
| - }
|
| - if (location_.x() >= flockBox.right()) {
|
| - location_.set_x(flockBox.x());
|
| - }
|
| - if (location_.y() < flockBox.y()) {
|
| - location_.set_y(flockBox.bottom() - 1);
|
| - }
|
| - if (location_.y() >= flockBox.bottom()) {
|
| - location_.set_y(flockBox.y());
|
| - }
|
| - }
|
| -}
|
| -
|
| -Vector2 Goose::Flock(const std::vector<Goose>& geese,
|
| - const std::vector<Vector2>& attractors) {
|
| - // Loop over all the neighbouring geese in the flock, accumulating
|
| - // the separation mean, the alignment mean and the cohesion mean.
|
| - int32_t separationCount = 0;
|
| - Vector2 separation;
|
| - int32_t alignCount = 0;
|
| - Vector2 alignment;
|
| - int32_t cohesionCount = 0;
|
| - Vector2 cohesion;
|
| -
|
| - for (std::vector<Goose>::const_iterator goose_it = geese.begin();
|
| - goose_it < geese.end();
|
| - ++goose_it) {
|
| - const Goose& goose = *goose_it;
|
| - // Compute the distance from this goose to its neighbour.
|
| - Vector2 gooseDirection = Vector2::Difference(
|
| - location_, goose.location());
|
| - double distance = gooseDirection.Magnitude();
|
| - separationCount = AccumulateSeparation(
|
| - distance, gooseDirection, &separation, separationCount);
|
| - alignCount = AccumulateAlignment(
|
| - distance, goose, &alignment, alignCount);
|
| - cohesionCount = AccumulateCohesion(
|
| - distance, goose, &cohesion, cohesionCount);
|
| - }
|
| - // Compute the means and create a weighted sum. This becomes the goose's new
|
| - // acceleration.
|
| - if (separationCount > 0) {
|
| - separation.Scale(1.0 / static_cast<double>(separationCount));
|
| - }
|
| - if (alignCount > 0) {
|
| - alignment.Scale(1.0 / static_cast<double>(alignCount));
|
| - // Limit the effect that alignment has on the final acceleration. The
|
| - // alignment component can overpower the others if there is a big
|
| - // difference between this goose's velocity and its neighbours'.
|
| - alignment.Clamp(kMaxTurningForce);
|
| - }
|
| -
|
| - // Compute the effect of the attractors and blend this in with the flock
|
| - // cohesion component. An attractor has to be within kAttractorRadius to
|
| - // effect the heading of a goose.
|
| - for (size_t i = 0; i < attractors.size(); ++i) {
|
| - Vector2 attractorDirection = Vector2::Difference(
|
| - attractors[i], location_);
|
| - double distance = attractorDirection.Magnitude();
|
| - if (distance < kAttractorRadius) {
|
| - attractorDirection.Scale(1000); // Each attractor acts like 1000 geese.
|
| - cohesion.Add(attractorDirection);
|
| - cohesionCount++;
|
| - }
|
| - }
|
| -
|
| - // If there is a non-0 cohesion component, steer the goose so that it tries
|
| - // to follow the flock.
|
| - if (cohesionCount > 0) {
|
| - cohesion.Scale(1.0 / static_cast<double>(cohesionCount));
|
| - cohesion = TurnTowardsTarget(cohesion);
|
| - }
|
| - // Compute the weighted sum.
|
| - separation.Scale(kSeparationWeight);
|
| - alignment.Scale(kAlignmentWeight);
|
| - cohesion.Scale(kCohesionWeight);
|
| - Vector2 weightedSum = cohesion;
|
| - weightedSum.Add(alignment);
|
| - weightedSum.Add(separation);
|
| - return weightedSum;
|
| -}
|
| -
|
| -Vector2 Goose::TurnTowardsTarget(const Vector2& target) {
|
| - Vector2 desiredDirection = Vector2::Difference(target, location_);
|
| - double distance = desiredDirection.Magnitude();
|
| - Vector2 newDirection;
|
| - if (distance > 0.0) {
|
| - desiredDirection.Normalize();
|
| - // If the target is within the turning affinity distance, then make the
|
| - // desired direction based on distance to the target. Otherwise, base
|
| - // the desired direction on MAX_SPEED.
|
| - if (distance < kMaxTurningDistance) {
|
| - // Some pretty arbitrary dampening.
|
| - desiredDirection.Scale(kMaxSpeed * distance / 100.0);
|
| - } else {
|
| - desiredDirection.Scale(kMaxSpeed);
|
| - }
|
| - newDirection = Vector2::Difference(desiredDirection, velocity_);
|
| - newDirection.Clamp(kMaxTurningForce);
|
| - }
|
| - return newDirection;
|
| -}
|
| -
|
| -int32_t Goose::AccumulateSeparation(double distance,
|
| - const Vector2& gooseDirection,
|
| - Vector2* separation, /* inout */
|
| - int32_t separationCount) {
|
| - if (distance > 0.0 && distance < kPersonalSpace) {
|
| - Vector2 weightedDirection = gooseDirection;
|
| - weightedDirection.Normalize();
|
| - weightedDirection.Scale(1.0 / distance);
|
| - separation->Add(weightedDirection);
|
| - separationCount++;
|
| - }
|
| - return separationCount;
|
| -}
|
| -
|
| -int32_t Goose::AccumulateAlignment(double distance,
|
| - const Goose& goose,
|
| - Vector2* alignment, /* inout */
|
| - int32_t alignCount) {
|
| - if (distance > 0.0 && distance < kNeighbourRadius) {
|
| - alignment->Add(goose.velocity());
|
| - alignCount++;
|
| - }
|
| - return alignCount;
|
| -}
|
| -
|
| -int32_t Goose::AccumulateCohesion(double distance,
|
| - const Goose& goose,
|
| - Vector2* cohesion, /* inout */
|
| - int32_t cohesionCount) {
|
| - if (distance > 0.0 && distance < kNeighbourRadius) {
|
| - cohesion->Add(goose.location());
|
| - cohesionCount++;
|
| - }
|
| - return cohesionCount;
|
| -}
|
| -
|
| -} // namespace flocking_geese
|
| -
|
|
|