00001 #ifndef PHPENALTY_H 00002 #define PHPENALTY_H 00003 #include "Physics.h" 00004 00005 namespace Spr{; 00006 00007 /** 2つのフレーム間の衝突を検出し,ペナルティを求め,力を加える. 00008 PHPenaltyEngine が持つ. */ 00009 class PHPenalty:public SGObject, public CDFramePairWithNormal{ 00010 SGOBJECTDEF(PHPenalty); 00011 float convertedMass; ///< 2剛体の換算質量.バネ係数を決めるために使用. 00012 float area; ///< 2つのフレーム間の接触領域の面積 00013 float dt; ///< delta t 00014 protected: 00015 public: 00016 UTRef<PHSolid> solid[2]; ///< 結果を反映させる剛体 00017 00018 public: 00019 /// 00020 PHPenalty(){ Init(); } 00021 /// 00022 PHPenalty(PHSolid* s1, PHSolid* s2){ Init(); Set(s1, s2); } 00023 ~PHPenalty(){ 00024 solid[0] = NULL; 00025 solid[1] = NULL; 00026 } 00027 /// detector を初期化する. 00028 void Init(); 00029 /// ロード後,参照が解決してから,convertedMass を計算する. 00030 void Loaded(SGScene* scene); 00031 /// Solidを設定 00032 void Set(PHSolid* s1, PHSolid* s2); 00033 /// dt だけシミュレーションを進める. 00034 void Step(SGScene* s); 00035 /// 摩擦のバネの表示 00036 void Draw(SGScene* s); 00037 /// 換算質量を計算 00038 void CalcConvertedMass(); 00039 /// solidやdetectorをNULLでクリアする.メモリリーク対策. 00040 void Clear(); 00041 /// 00042 bool operator < (const PHPenalty& p) const { 00043 if (solid[0] < p.solid[0]) return true; 00044 if (p.solid[0] < solid[0]) return false; 00045 if (solid[1] < p.solid[1]) return true; 00046 return false; 00047 } 00048 bool AddChildObject(SGObject* o, SGScene* s); 00049 protected: 00050 virtual CDConvexPair* CreateConvexPair(){ 00051 return new PHConvexPair; 00052 } 00053 virtual CDGeometryPair* CreateGeometryPair(){ 00054 return new PHGeometryPair; 00055 } 00056 friend class PHPenaltyLoader; 00057 friend class PHPenaltySaver; 00058 }; 00059 /// PHPenaltyの配列 00060 class PHPenalties:public std::vector< UTRef<PHPenalty> >{ 00061 }; 00062 /** ペナルティ法のエンジン. 00063 衝突判定を行い,ペナルティを求め,PHSolidに力を加える. */ 00064 class PHPenaltyEngine:public SGBehaviorEngine{ 00065 SGOBJECTDEF(PHPenaltyEngine); 00066 public: 00067 /// 2つの剛体のペナルティ計算 00068 PHPenalties penalties; 00069 bool AddChildObject(SGObject* o, SGScene* s); 00070 int GetPriority() const { return SGBP_PENALTYENGINE; } 00071 /// 時間を dt 進める 00072 virtual void Step(SGScene* s); 00073 /// ペナルティをクリアする. 00074 virtual void Clear(SGScene* s); 00075 virtual void Loaded(SGScene* scene){ 00076 for(PHPenalties::iterator it = penalties.begin(); it != penalties.end(); ++it){ 00077 (*it)->Loaded(scene); 00078 } 00079 } 00080 }; 00081 00082 00083 } 00084 #endif