//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2004 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// /* * Copyright (C) 1996, Christopher John Kline * Electronic mail: ckline@acm.org * * This software may be freely copied, modified, and redistributed * for academic purposes and by not-for-profit organizations, provided that * this copyright notice is preserved on all copies, and that the source * code is included or notice is given informing the end-user that the source * code is publicly available under the terms described here. * * Persons or organizations wishing to use this code or any modified version * of this code in a commercial and/or for-profit manner must contact the * author via electronic mail (preferred) or other method to arrange the terms * of usage. These terms may be as simple as giving the author visible credit * in the final product. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * If you use this software the author politely requests that you inform him via * electronic mail. * */ // Boid.h // // INTERFACE: Class for objects that move with A-Life boid-type behavior. // // (c) 1996 Christopher Kline // // $Id: Boid.h,v 1.4 2006/04/22 01:03:51 scara Exp $ #ifndef __BOID_H #define __BOID_H #include #include #include "BoidWorld.h" #include "SimObject.h" #include "Obstacle.h" class Boid : public SimObject { public: enum boidTypes { NORMAL = 0, PREDATOR, PREY }; Boid(BoidWorld *world, int boidNumber, BoidVector bPosition, BoidVector bVelocity); // Constructor. Creates a bird of type NORMAL with the given dimensions, // initial position, and velocity. // bDimensions.{x,y,z} = {length, width, height} virtual bool update(const double &elapsedSeconds); // Updates this object based on the amount of elapsed time since the last // update, and the previous acceleration and velocity. void updateslow(); double dampedroll; double roll; // [radians] Rotation around body-local z-axis (+roll = // counterclockwise). Default value is 0. double pitch; // [radians] Rotation around body-local x-axis (+pitch = nose tilting // upward). Default value is 0. double yaw; // [radians] Rotation around body-local y-axis (increasing // counterclockwise, 0 is along body-local +z). Default value is 0. protected: virtual double getGravAcceleration(void) const; // Returns the magnitude of gravitational acceleration in the (0, -1, 0) // direction [m/(sec^2)]. virtual double accumulate(BoidVector &accumulator, BoidVector valueToAdd); // Given an accumulator and a value to add to the accumulator, this // method truncates the magnitude of valueToAdd so that, when added to the // accumulator, the magnitude of the accumulator is at most 1.0. It then // adds the truncated value to the accumulator. The value returned is the // magnitude of the accumulator after the addition. virtual float getProbeLength(void); // Returns how far in front of boid to probe for obstacles. By default, // the probe length scales linearly from 10 times bodylength to 50 times // bodylength as the boid accelerates from 0 m/s to maxVelocity. virtual double desiredCruisingSpeed(void); // Returns the speed the boid would like to travel at when not under any // other influences (i.e., obstacles, flocking desires, etc). The default // value is 1/5 of maxVelocity. virtual void calculateVisibilityMatrix(void); // Each boid helps maintain a visibility matrix, which is an NxN matrix, // where N is the current number of boids (it is dynamically expanded each // time a new boid is created). Each cell [A,B] represents whether boid A can // see boid B. The contents of the matrix are described further in the // visMatrix macro in boid.c++ // The reason for this matrix is to drastically reduce the computational // complexity of determining which boids are visible to the others. virtual int visibleToSelf(Boid *b); // Returns 1 if this boid can see boid b, 0 otherwise. virtual void calculateRollPitchYaw(BoidVector appliedAcceleration, BoidVector currentVelocity, BoidVector currentPosition); // Calculate the roll, pitch, and yaw of this boid based on its // acceleration, velocity, and position. Though position isn't necessary // for most approximations of attitude, it may be useful in some // circumstances. virtual BoidVector levelFlight(BoidVector AccelSoFar); // Returns a BoidVector which indicates how the boid would like to accelerate // in order to fly level (i.e., with minimal pitch). virtual BoidVector wander(void); // Returns a BoidVector which indicates how the boid would like to accelerate // when not under any other influences. Related to desiredCruisingSpeed(). virtual BoidVector collisionAvoidance(void); // Returns a BoidVector which indicates how the boid would like to accelerate // in order to avoid collisions with non-boid obstacles. virtual BoidVector resolveCollision(BoidVector pointOnObject, BoidVector normalToObject); // Called by CollisionAvoidance, this method attempts to avoid a collision // with a specific obstacle, and returns an acceleration BoidVector indicating // how the boid should accelerate to achieve this end. virtual BoidVector maintainingCruisingDistance(void); // Returns a BoidVector which indicates how the boid would like to accelerate // in order to maintain a distance of cruiseDistance from the nearest // visible boid. virtual BoidVector velocityMatching(void); // Returns a BoidVector which indicates how the boid would like to accelerate // in order to fly at approximately the same speed and direction as the // nearby boids. virtual BoidVector flockCentering(void); // Returns a BoidVector which indicates how the boid would like to accelerate // in order to be near the center of the flock. virtual BoidVector navigator(void); // This method prioritizes and resolves the acceleration BoidVectors from // CollisionAvoidance(), FlockCentering(), MaintainingCruisingDistance(), // VelocityMatching(), Wander(), and LevelFlight(). It returns the actual // acceleration BoidVector that the boid will apply to its flight in the // current time step. virtual int getBoidType(void) const; // Returns the type of this boid. double time; // [sec] current time int boidNumber; // Unique integer identifying the number of this boid. The first boid // created is given boidNumber 1, and the values increase sequentially. bool flockSelectively; // Should this boid flock only with boids of the same boidType, or with // all boids? The default value is FALSE, meaning that this boid will // flock with all boids regardless of type. // Basically, should boids of a feather stick together? :) int boidType; // Identifies the type of boid for selective flocking private: BoidWorld *world; // All visible boids + obstacles BoidVector oldVelocity; // [m/sec] velocity at last update. BoidVector acceleration; // [m/(sec^2)] acceleration requested at last update. bool flightflag; // Has the boid been updated at least once? }; // ------------------------------------------------ inline methods ------------------------------------------------ inline double Boid::getGravAcceleration(void) const { return 9.806650; } inline int Boid::getBoidType(void) const { return boidType; } inline int Boid::visibleToSelf(Boid *b) { // find out if the boid b is within our field of view BoidVector BoidVectorToObject = b->position - position; // This isn't perfectly accurate, since we're not always facing in // the direction of our velocity, but it's close enough. return(AngleBetween(velocity, BoidVectorToObject) <= 1.0471967); // pi/3 radians is our FOV } inline float Boid::getProbeLength(void) { float maxScale = 5; // When we're at maxVelocity, scalefactor = maxScale. // When our velocity is 0, scalefactor = 1. // Linearly scale in between. float scaleFactor = float(((maxScale-1)/world->getMaxVelocity()) * Magnitude(velocity) + 1); return float(10.0f*scaleFactor); } inline double Boid::desiredCruisingSpeed(void) { return 0.2*world->getMaxVelocity(); } inline BoidVector Boid::levelFlight(BoidVector AccelSoFar) { // Determine the vertical acceleration. BoidVector verticalAcc(0, AccelSoFar.y, 0); // Try to negate it. return -verticalAcc; } #endif /* __BOID_H */