📄 cboid.cpp
字号:
// test: if this is OUR flock, skip it if (i == flock_id) continue;#ifdef VISIBILITY_DEBUG myprintf(" Testing to see if %x can see anybody in flock %d\n",this,i);#endif // not our flock, so check it out enemy = CFlock::ListOfFlocks[i]->GetFirstMember(); while (enemy != NULL) { #ifdef VISIBILITY_DEBUG myprintf(" looking at %x\n",enemy);#endif // if this enemy is visible... if ((dist = CanISee(enemy)) != INFINITY) { // I can see it..increment counter m_num_enemies_seen++; // Test: Closest enemy? if (dist < m_dist_to_nearest_enemy) { // yes...save it off m_dist_to_nearest_enemy = dist; m_nearest_enemy = enemy; } } // get next enemy in flock enemy = enemy->GetNext(); } }#ifdef VISIBILITY_DEBUG myprintf("\n"); myprintf(" total enemies seen = %d\n",m_num_enemies_seen); myprintf(" nearest enemy is %x at %f\n",m_nearest_enemy,m_dist_to_nearest_enemy);#endif return (m_num_enemies_seen);}// SeeFriends.// Determines which flockmates a given flock boid can see.int CBoid::SeeFriends (CBoid *first_boid){ float dist; CBoid *flockmate = first_boid;#ifdef BOID_DEBUG myprintf("\nInside SeeFriends\n");#endif#ifdef VISIBILITY_DEBUG myprintf(" Building visibilty list for %x...\n",this);#endif // clear the existing visibility list of any holdover from last round ClearVisibleList(); // now figure out who we can see while (flockmate != NULL) { // Test: Within sight of this boid?#ifdef VISIBILITY_DEBUG myprintf(" looking at %x\n",flockmate);#endif if ((dist = CanISee(flockmate)) != INFINITY) { // add it to the list AddToVisibleList(flockmate); // Test: If this guy is closer than the current // closest, make him the current closest if (dist < m_dist_to_nearest_flockmate) { m_dist_to_nearest_flockmate = dist; m_nearest_flockmate = flockmate; } } // next flockmate flockmate = flockmate->GetNext(); }#ifdef VISIBILITY_DEBUG myprintf("\n"); myprintf(" total flockmates seen = %d\n",m_num_flockmates_seen); myprintf(" nearest flockmate is %x at %f\n", m_nearest_flockmate, m_dist_to_nearest_flockmate);#endif return (m_num_flockmates_seen);}// SteerToCenter.// Generates a vector to guide a flock boid towards// the "center of mass" of the flockmates he can see.vector CBoid::SteerToCenter (void){ vector center, change;#ifdef BOID_DEBUG myprintf("\nInside SteerToCenter\n");#endif // walk down the visibility list and sum up their position vectors for (int i = 0; i < m_num_flockmates_seen; i++) { if (VisibleFriendsList[i] != NULL) center += VisibleFriendsList[i]->m_pos; }#ifdef BOID_DEBUG myprintf(" perceived center before averaging = %f %f %f\n",center.x, center.y, center.z); myprintf(" num_flockmates_seen = %d\n",m_num_flockmates_seen);#endif // average the positions to get the perceived center of the flock center /= m_num_flockmates_seen;#ifdef BOID_DEBUG myprintf(" perceived center after averaging = %f %f %f\n",center.x, center.y, center.z);#endif // now that we have the perceived center, computer a vector towards it change = center - m_pos; // Scale the change vector so we don't turn on a dime.. change.SetMagnitudeOfVector (MinUrgency);#ifdef BOID_DEBUG myprintf(" final change vector from SteerToCenter = %f %f %f\n", change.x, change.y, change.z);#endif // return change vector return (change);}// WorldBound.// Implements a world boundary so that flocks don't fly// infinitely far away from the camera, instead remaining // in a nice viewable area. It does this by wrapping flock// boids around to the other side of the world, so (for example)// they move out the right and return on the left.// Returns: nothing.void CBoid::WorldBound (void){ float maxX = CBox::WorldPtr->GetBoxWidth()/2; float maxY = CBox::WorldPtr->GetBoxHeight()/2; float maxZ = CBox::WorldPtr->GetBoxLength()/2; float minX = -maxX; float minY = -maxY; float minZ = -maxZ;#ifdef BOID_DEBUG myprintf("\nInside Worldbound\n");#endif // test position of flock boid and // 'warp' if they've strayed out of bounds if (m_pos.x > maxX) { m_pos.x = minX; } else if (m_pos.x < minX) { m_pos.x = maxX; } else if (m_pos.y > maxY) { m_pos.y = minY; } else if (m_pos.y < minY) { m_pos.y = maxY; } else if (m_pos.z > maxZ) { m_pos.z = minZ; } else if (m_pos.z < minZ) { m_pos.z = maxZ; }}////////////////////////// miscellaneous methods////////////////////////// AccumulateChanges.// Adds vector values in changes into the accumumlator vector.// Returns: magnitude of accumulator vector after adding changes.float CBoid::AccumulateChanges (vector &accumulator, vector changes){#ifdef BOID_DEBUG myprintf("\nInside AccumulateChanges\n");#endif // apply the change accumulator += changes; //accumulator.x += changes.x; //accumulator.y += changes.y; //accumulator.z += changes.z; return (accumulator.length());}// AddToVisibleList.// Adds a boid to the list of visible boids.// This visibility list is regenerated for each boid each update cycle,// and acts much like a push-down queue; the latest boid added to the// list becomes the first one when the list is sequentially accessed.// Mostly I did this for speed reasons, as this allows for fast inserts// (and we don't delete from this list, we just rebuild it each update cycle).void CBoid::AddToVisibleList (CBoid *ptr){ // test: do we see enough buddies already? if (m_num_flockmates_seen < Max_Friends_Visible) { // nope--we can add to this one to the list VisibleFriendsList[m_num_flockmates_seen] = ptr; // increment counter m_num_flockmates_seen++; }#ifdef VISIBILITY_DEBUG int i; myprintf("visibility list for %x after adding %x:\n",this,ptr); for (i = 0; i < m_num_flockmates_seen; i++) { if (VisibleFriendsList[i] != NULL) { myprintf("VFL = %x\n",VisibleFriendsList[i]); } else { break; } }#endif}// ClearVisibleList.// Clears the visibility list.void CBoid::ClearVisibleList (void){ // walk down the list and clear each visible entry for (int i = 0; i < Max_Friends_Visible; i++) { VisibleFriendsList[i] = NULL; } // clear other visibility info m_num_flockmates_seen = 0; m_nearest_flockmate = NULL; m_dist_to_nearest_flockmate = INFINITY;}// Determine whether a given invoking boid can see the boid in question.// Returns the distance to the boid.float CBoid::CanISee (CBoid *ptr){#ifdef VISIBILITY_DEBUG myprintf("\n Inside CanISee.\n");#endif // Test: if we're looking at ourselves, never mind if (this == ptr) return (INFINITY); // figure out distance float dist = (m_pos.GetDist(m_pos, ptr->m_pos));#ifdef VISIBILITY_DEBUG myprintf(" dist between %x and %x = %f\n",this,ptr,dist);#endif // if we're using truth data, don't bother to check sighting if (UseTruth) return (dist); // not using truth, so check sighting if (m_perception_range > dist) return (dist); // fell through; can't see it return (INFINITY);}// ComputeRPY.// Computes the roll/pitch/yaw of the flock boid based on its// latest velocity vector changes. Roll/pitch/yaw are stored in// the "ang" data boid as follows:// pitch is about the x axis// yaw is about the y axis// roll is about the z axis//// All calculations assume a right-handed coordinate system:// +x = through the left side of the object// +y = up// +z = through the nose of the model//// All angles are computed in radians.//// NOTE: This algorithm was generously provided by Christopher Kline, who originally// developed it for *his* flocking applications. Thanks Christopher!void CBoid::ComputeRPY (void){ float roll, pitch, yaw; // Determine the direction of the lateral acceleration. vector lateralDir = (m_vel % (m_vel - m_oldvel)) % m_vel; lateralDir.GetDirection(); // Set the lateral acceleration's magnitude. The magnitude is the vector // projection of the appliedAcceleration vector onto the direction of the // lateral acceleration). float lateralMag = (m_vel - m_oldvel) * lateralDir; // compute roll if (lateralMag == 0) { roll = 0.0f; } else { roll = (float) -atan2(GRAVITY, lateralMag) + HALF_PI; } // compute pitch pitch = (float) -atan(m_vel.y / sqrt((m_vel.z*m_vel.z) + (m_vel.x*m_vel.x))); // compute yaw yaw = (float) atan2(m_vel.x, m_vel.z); // store them m_ang.x = pitch; m_ang.y = yaw; m_ang.z = roll;#ifdef BOID_DEBUG myprintf(" roll = %f pitch = %f yaw = %f\n",roll, pitch, yaw);#endif}// SetNext.// Set the "next" pointer of an individual boid.void CBoid::SetNext (CBoid *ptr){ m_next = ptr;}// GetNext.// Returns the "next" pointer of the invoking boid.CBoid * CBoid::GetNext(){ return (m_next);}// SetPrev.// Set the "prev" pointer of an individual boid.void CBoid::SetPrev (CBoid *ptr){ m_prev = ptr;}// GetOrient.// Returns the orientation of the boid in question.vector * CBoid::GetOrient (void){ return (&m_ang);}// GetPos.// Returns the position of the boid in question.vector * CBoid::GetPos (void){ return (&m_pos);}// LinkOut.// Removes a boid from a list.void CBoid::LinkOut (){ // test location of boid if ((m_next == NULL) && (m_prev == NULL)) { SetNext(NULL); SetPrev(NULL); } else if (m_next == NULL) { m_prev->SetNext(NULL); } else if (m_prev == NULL) { m_next->SetPrev(NULL); } else { m_prev->SetNext(m_next); m_next->SetPrev(m_prev); }}// PrintData// Dumps all data describing a given boid.void CBoid::PrintData (void){ myprintf("===================\n"); myprintf("Data for boid = %d @ %x\n", m_id,this); myprintf(" perception_range = %f\n", m_perception_range); myprintf(" pos x, y, z = %f %f %f\n", m_pos.x, m_pos.y, m_pos.z); myprintf(" vel x, y, z = %f %f %f\n", m_vel.x, m_vel.y, m_vel.z); myprintf(" roll, pitch, yaw = %f %f %f\n", m_ang.z, m_ang.x, m_ang.y); myprintf(" speed = %f\n", m_speed); myprintf(" num_flockmates_seen = %d\n", m_num_flockmates_seen); myprintf(" nearest_flockmate = %x\n", m_nearest_flockmate); myprintf(" dist_to_nearest_flockmate = %f\n", m_dist_to_nearest_flockmate); myprintf(" num_enemies_seen = %d\n", m_num_enemies_seen); myprintf(" nearest_enemy = %x\n", m_nearest_enemy); myprintf(" dist_to_nearest_enemy = %f\n", m_dist_to_nearest_enemy);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -