[[Spr1の使い方/マニュアル]]
*目次 [#xcb39032]
#contents
*概要 [#id2655f5]
接触判定,接触力の計算は,それぞれCDCollisionEngine, PHContactEngine で行う.PHPenaltyEngineというのもあるが古いので使わないで欲しい.

剛体が接触したか知りたい場合,PHContactEngineの方が便利なことが多い.[[接触力を調べるには>#contact]]を参照して欲しい.

*衝突判定 [#oc9a0516]
**判定エンジン CDCollisionEngine [#z0d35b59]
衝突判定を行うCDCollisionEngineは,判定対象のフレームを持ち,
毎ステップ全組み合わせの衝突判定を行う.

判定は,
+BoundingBoxに基づいて,X軸にソート.接触の可能性があるフレームを見つける.
+凸形状のペアごとに,Mesh形状に基づいた接触判定を行う.(メッシュの凹みは埋まっているものとして接触判定を行う)
+最近傍点(最侵入点),法線を求める.このとき履歴を使う.
+必要があれば,接触部分の形状を求める.求めた形状はリスナの中だけで有効.

の手順で行う.判定前(Before),接触部分の形状を求めたあと(Analyzed),判定後(After)に
リスナ(コールバック)を呼び出す.

**判定結果の受け取り方 [#z72fb9e6]
まず,
 CDCollisionEngine* ce;
 scene->GetBehaviors().Find(ce);
で ce に衝突判定エンジンへのポインタが得られる.判定を知る方法はいくつかあるので,
簡単な方法から紹介する.
***接触点,接触の法線,接触した部分が分かればよい場合 [#o60359ab]
+CDCollisionEngine::GetFramePair()を呼び出して,CDFramePairのオブジェクトを取得する.
+衝突点についての情報が CDFramePair::intersections に入るのでそれを参照する.
衝突がなければ intersections.size() は0になる.

***接触(交差)部分の形状が知りたい場合や衝突が起こったときに何か処理をしたい場合 [#y46e0dbc]
+CDCollisionListener の派生クラスを作る.
++Before, Analayzed, After のうち,処理をしたい関数を実装する.
+作成したクラスを handle = CDCollisionEngine::AddListener() を呼び出して登録する.
これで接触が起こるたびに,関数が呼ばれるようになる.~

一部の物体だけについて衝突判定する場合は,あらかじめ,
AddActive(SGFrame* f1, SGFrame* f2, int handle)を呼び出す.
すると,呼び出されたフレームのペアについてだけ関数が呼ばれるようになる.

ほとんどの物体について衝突判定する場合は,あらかじめ,
AddInactive(SGFrame* f1, SGFrame* f2, int handle)を呼び出す.
すると,呼び出されたフレームのペアに以外について関数が呼ばれるようになる.

***フレーム,フレーム対,凸形状対ごとにデータが必要な場合 [#cc80f4f1]
Before, Analayzed, After のなかなどで,物体ごとにデータを用意して使いたい場合
(たとえば,前回接触していたかのチェックなど),独自のクラスへの自動ポインタを持たせることができる.
独自のクラスは,CDUserRecordを継承していれば,何でも良い.
|データをもたせたいもの|自動ポインタをもつ変数|場所を確保して pos を返す関数|h
|フレーム|CDFrame::records[pos]|ReserveFrameRecord()|
|フレーム対|CDFramePairWithRecord::records[pos]|ReserveFramePairRecord()|
|凸形状対|CDConvexPairWithRecord::records[pos]|ReserveConvexPairRecord()|
確保した場所は,最初はNULLになっているので,ユーザが自分で作ったクラスのオブジェクトを
登録できる.自動ポインタなので,delete は CDCollisionEngine がなくなるときに自動的に行われる.

*接触力計算 [#kdeb3cd1]
**接触力エンジン PHContactEngine [#x4b3c473]
'''PHPenaltyEngineは古いものです.使わないでください'''~
接触力の計算を行う PHContactEngine は,通常のエンジンのStepでは何もしない.
PHContectEngineは,CDCollisionListenerを継承しており,CDCollisionEngine 
が接触を検出するたびに呼び出され(「判定結果の受け取り方」を参照)接触力の計算が行われる.
計算は,
+ Beforeで初期化と前計算
+ Analyzedで接触力のための分布バネダンパモデル,分布摩擦モデルが発生する力を積分
+ Afterで接触面積に基づく調節,摩擦力の計算,PHSolidに接触力を加える.
の順に行われる.

**&aname(contact){接触力を調べるには}; [#gd41a716]
接触力は PHContactEngine::FramePairRecord,PHContactEngine::ConvexPairRecord
に記録される.これらを参照することで,2つのフレーム間,2つの凸形状間に働く接触力を
調べることができる.
FramePairRecordは,PHContactEngine::GetFramePairRecord(SGFrame* fr1, SGFrame* fr2)で,
簡単に取得できる.

また,接触力は剛体(PHSolid)に加えられる.
PHSolidを参照し,剛体にかかった力を調べることができるが,剛体には重力や関節の拘束力など
他の力も加わるので,接触力を区別して取り出すことは出来ない.

**関節エンジンと接触力 [#n03b0845]
関節エンジン Joint などを使って複数の剛体を組み合わせた場合,
関節を通して剛体に加わる力は接触力ではないので読み出せない.~
関節の拘束力(関節を壊すような力)は,計算されないので速度の変化(加速度)から逆算するしかない.~
関節を回す力は,関節に直接働くトルク(GetTorque()で読み出せる)と接触力によるトルクの和になる.