#include "ats_BoidGroup.h" #include "ats_Boid.h" #include using namespace std; using namespace ats; // コンストラクタ・デストラクタ ------------------------------------------------------------ BoidGroup::BoidGroup(BoundingFrame* f) { if(f){ m_bounding_frame = f; } else { throw boid_exception("BoidGroupのコンストラクタはnullポインタを受け付けません。"); } } BoidGroup::~BoidGroup() { for(list::iterator itr=Begin(); itr != End(); itr++){ delete *itr; } delete m_bounding_frame; } // 位置へのアクセッサ ---------------------------------------------------------------------- const Point3D& BoidGroup::Center() const { return m_center; } // 向きへのアクセッサ ------------------------------------------------------------------ const Point3D& BoidGroup::Muki() const { return m_muki; } void BoidGroup::Add(Obj3DD *a) { Group3DD::Add(a); // Boidであれば親と双方向にアクセスできるようにしておく。 Boid* b = dynamic_cast(a); if(b){ b->SetParent(this); } } // フレームアップデート --------------------------------------------------------------- void BoidGroup::UpdateTime(double time) { for(list::iterator itr=Begin(); itr != End(); itr++){ (*itr)->UpdateTime(time); } UpdateSelf(); // グループの平均を計算 } // グループの位置をアップデート ----------------------------------------------------- void BoidGroup::UpdateSelf() { // 位置と向きと速度を初期化 m_center.SetXYZ(0,0,0); m_muki.SetXYZ(0,0,0); // 登録されているオブジェクトの位置と向きを足し合わせる for(list::iterator itr=Begin(); itr != End(); itr++){ // Boidかどうかテスト // ポインタを指すイテレータであるから**で実体。 // 0ならばキャスト失敗 Boid* b = dynamic_cast(*itr); if(b){ m_center += b->GetCenter(); m_muki += b->GetMuki(); } } // 平均化 m_center /= Size(); m_muki /= Size(); // 正規化 m_muki.Normalize(); } const BoundingFrame& BoidGroup::GetBoundingFrame() const { return *m_bounding_frame; } void BoidGroup::SetBoundingFrame(BoundingFrame* a) { if(a){ // nullチェック delete m_bounding_frame; m_bounding_frame = a; } } // 中心を描画してあとは基底クラスに任せる -------------------------------------------------- void BoidGroup::Draw() { // 基底クラスに丸投げ Group3DD::Draw(); /* Point3D tmp(m_muki + m_center); // 描画するのは位置から方向(速度は無視) glDisable(GL_LIGHTING); glBegin(GL_LINES); //glColor3f(1,0,0); //glVertex3d(m_center.X(), m_center.Y(), m_center.Z()); glColor3f(0,0,0); glVertex3d(tmp.X(), tmp.Y(), tmp.Z()); glEnd(); glEnable(GL_LIGHTING); */ } // 最も近い同士を計算してやる ------------------------------------------------------------- // キャストの嵐・・・なんとかならない? /* template void BoidGroup::CalcNear() { // 各個体の知る"近い奴"の記録を初期化 for(list::iterator itr=Begin(); itr != End(); itr++){ if(typeid(TBOID) == typeid(**itr)){ dynamic_cast(*itr)->SetNear(0); } } int count = 0; for(itr=Begin(); itr != End(); itr++){ // すでに最も近い相手が見つかってれば飛ばす。 if(dynamic_cast(*itr)->IsNear() == false){ Obj3DD* min_obj = 0; for(list::iterator itr2=Begin(); itr2 != End(); itr2++){ // Boidかどうかテスト // ポインタを指すイテレータであるから**で実体。 if(typeid(TBOID) == typeid(**itr) && typeid(TBOID) == typeid(**itr2)){ double min = std::numeric_limits::infinity(); // 2点間の距離 (A-B).Length() double tmp = (dynamic_cast(*itr)->GetCenter()-dynamic_cast(*itr2)->GetCenter()).Length(); if(min > tmp){ min_obj = *itr2; // オブジェクトをセーブして min = tmp; // 距離もセーブする。 } } } // その上ダウンキャスト!いいのか? if(typeid(TBOID) == typeid(**itr) && typeid(TBOID) == typeid(*min_obj)){ dynamic_cast(*itr)->SetNear(dynamic_cast(min_obj)); // 最も近かったオブジェクトを記憶。 dynamic_cast(min_obj)->SetNear(dynamic_cast(*itr)); // 相手にも記憶。 } } } } */