[[Spr1の使い方/マニュアル]]
*目次 [#pc308a5e]
#contents
*準備 [#e08ec593]
ソースを読むために,基本のクラスをいくつか覚える必要があります.
**UTRef<T> [[参照カウンタ]]と参照ポインタ [#cc8174f9]
参照カウンタ式のスマートポインタ.
UTRef<クラス名>が参照ポインタ.UTRefCountが[[参照カウンタ]]です.
UTRefCountを基本クラスにもつクラスAがあるとして,次にように使えます.
UTRef<A> p;
for(int i=0; i10; ++i){
p = new A;
p->Aのメソッド()
}
new したのにdeleteしていません.さらに,pに10回もnewして代入しています.
でもメモリリークは起きません. 詳しくは[[参照カウンタ]]を見てください.
**線形代数 [#x02328c0]
***[[Spr::Vec3f ( Spr::TVec3<float> ) / Spr::Vec3d ( Spr::TVec3<double> ):http://springhead.info/src/html/ja/classSpr_1_1TVec3.html]] [#h24f9b5e]
-3次元のベクトル。
-DirectX周りではVec3f、物理エンジン周りではVec3dが使われてる.物理には精度が必要なんだ.
Spr::Vec3f vec(x, y, z); //初期化。
Spr::Vec3f vec= Spr::Vec3f(x, y, z); //上と同じ意味。
vec[0]= x2; //各要素に代入。添え字は0,1,2。
Spr::Vec3f vec2= vec+Spr::Vec3f(x, y, z); //足し算とか。
size()はベクトルの次元.norm()がノルム(大きさ).square()がノルム^2.
unit()で正規化(0割注意)..X() .Y() .Z() で要素にアクセス.~
実は任意サイズのベクトル[[class PTM::TVector<N, T>:http://springhead.info/src/html/ja/classPTM_1_1TVector.html]]の親戚.他にも[[VVector:http://springhead.info/src/html/ja/classPTM_1_1VVector.html]]とか[[EVector:http://springhead.info/src/html/ja/classPTM_1_1ConstEVector.html]]がある.
***[[Spr::Affinef ( Spr::TAffine<float> ):http://springhead.info/src/html/ja/classSpr_1_1TAffine.html]] [#wcc64f12]
-Affine行列(4*4行列)。
Spr::Affinef trn= Spr::Affinef::Trn(x, y, z); //平行移動を表すAffine行列。
Spr::Affinef rot= Spr::Affinef::Rot(rad, 'x'); //X軸周りの回転を表すAffine行列。
Spr::Affinef aff= trn*rot; //Affine行列同士の掛け算。
aff.Pos()= Spr::Vec3f(x, y, z); //平行移動成分に代入。
aff.Rot()= Spr::Matrix3f(xx,xy,xz,yx,yy,yz,zx,zy,zz); //回転成分の代入.
aff[0][0]= 1.0; //各要素に代入。添え字は0,1,2,3.
aff.Ex() = Vec3f(1,0,0); 回転行列部のx軸基底(縦ベクトル)に代入.
aff.ExX() = 2.0f; Ex().X() と同じ.
Spr::Vec3f vec1= …;
Spr::Vec3f vec2= aff*vec1; // 3次ベクトルをAffine変換.vec1[3]は1と仮定して演算.
:[[LookAt(to), LookAt(to, up), LookAtGL(to), LookAtGL(to, up):http://springhead.info/src/html/ja/classSpr_1_1TAffine.html]] |toを見て,upが上になるような視点行列になるように自分を回転させる.
:[[static Unit(), Trn (px, py, pz), Rot(th, axis), Scale (sx, sy, sz):http://springhead.info/src/html/ja/classSpr_1_1TAffine.html]]|単位行列,平行移動行列,回転行列,拡大行列を返す.Affinef af=Affinef::Trn(1,2,3) のように使う.
:[[static ProjectionGL (Vec3f screen, Vec2f size, front=1.0f, back=10000.0f), ProjectionD3D(..):http://springhead.info/src/html/ja/classSpr_1_1TAffine.html]]|OpenGL, Direct3Dのプロジェクション行列を返す.screenが視点から見たスクリーンの位置,sizeがスクリーンのサイズ.front, back はクリッピングプレーン.
[[逆行列inv(), 転置trans(), 行列式det(), 方程式の解 solve(), ガウスの消去法 gauss(), コレスキー法 cholesky() :http://springhead.info/src/html/ja/classPTM_1_1MatrixImp.html]]~
実は任意サイズの行列[[PTM::TMatrixCol< H, W, T, Z, U >:http://springhead.info/src/html/ja/classPTM_1_1TMatrixCol.html]]の親戚.他にも[[VMatrixCol:http://springhead.info/src/html/ja/classPTM_1_1VMatrixCol.html]]や[[EMatrixCol:http://springhead.info/src/html/ja/classPTM_1_1EMatrixCol.html]]がある.
***[[Spr::Quaternionf (TQuaternion<float>):http://springhead.info/src/html/ja/classSpr_1_1TQuaternion.html]] [#nce99749]
- Quaternion 4元数.
- 回転をあらわす方法の一つ.Matrix3fの変わりに使える.
Qutaternionf qt;
qt.from_matrix(Matrix3f::Rot(Rad(30), 'y')); // 行列から初期化できる.
Vec3f r = qt.rotation(); // 回転ベクトル(unit:回転軸, norm:回転角)
Vec3f p = qt * Vec3f(1,0,0); // 位置ベクトルを回転させる.
4次元ベクトル [[TVector<4, float>:http://springhead.info/src/html/ja/classPTM_1_1TVector.html]] の親戚.
*シーングラフ上のオブジェクト [#u5aad312]
SpringheadのSceneGraphは次のような構造になっている.
+Scene // シーンオブジェクト(FWD3DApp app; (Viewが持っています)のメンバ)
+Frame // 物のデータ
+Frame
+CDMesh // 衝突判定用
+D3Mesh // 描画用
+GRMesh // 元のメッシュデータ
+Light // 光源
+BehaviorEngines // 物の振る舞いについての記述
+PHSolidContainer // 剛体の入れ物,自由物体の積分もここでやっています.
+PHSolid solid1
+PHSolid solid2
+PHSolid solid3
+PHContactEngine // 接触エンジン
+floor
+solid1
+solid2
+solid3
+PHJointEngine // ジョイントエンジン
+PHJoint root // ルートジョイント
+PHJoint joint1 // ジョイント1
+solid1
+joint2
+solid2
+joint2
+solid3
これらへのポインタを手に入れて,メンバメソッドを呼び出したり,メンバ変数を
書き換えることで,物を動かしたり,関節に力を加えたり出来る.
*剛体に力を加える. [#xc0f7f92]
力を加えるときは剛体に力を加えます.
Vec3d f, Vec3d r;
PHSolid* so;
scene->FindObject(so, "solid1"); // 名前からオブジェクトのポインタを得る
if (so) so->AddForec(f, r); //< 力fを 位置r(World系) に加える
**どこで呼び出すか [#b64c1d98]
BehaviorEngineには,実行の優先順位があり,SceneGraph/SGBehaviorEngine.h にあるように,
enum SGBehaviorPriority{
//初期化モジュール
SGBP_INITIALIZER = 100,
SGBP_CLEARFORCE,
//力生成モジュール
SGBP_FORCEGENERATOR = 200,
SGBP_GRAVITYENGINE,
SGBP_COLLISIONENGINE,
SGBP_PENALTYENGINE,
//積分の対象
SGBP_DYNAMICALSYSTEM = 300,
SGBP_JOINTENGINE,
SGBP_SOLIDCONTAINER,
//
SGBP_MOTION = 400,
SGBP_CHANGEOBJECT,
SGBP_CONSTRAINT,
//他のエンジンのリスナ
SGBP_LISTENER = 500,
SGBP_CONTACTENGINE,
SGBP_STICKENGINE,
SGBP_WARPENGINE,
};
となっています.scene には,全部のエンジンを呼び出す
/// シーンの時刻を進める ClearForce(); GenerateForce(); Integrate(); と同じ
void Step();
以外に,個別に呼び出す
/// シーンの時刻を進める(力のクリア)
void ClearForce();
/// シーンの時刻を進める(力の生成)
void GenerateForce();
/// シーンの時刻を進める(力と速度を積分して,速度と位置を更新)
void Integrate();
があります.プログラムで力を加えるためには,個別に呼び出して,
タイミングよく(たとえばGenerateForce()の直後で)力を加えなければなりません.
DynaHapticが使っている,FWD3DApp app の app.Step()は,
scene->Step()を呼び出してしまいます.
FWD3DAppを派生させてMyAppを作ってFWD3DAppの代わりに使い,
MyApp::Step()の中で,個別に呼び出したり,力を加えるのが良いと思います.
*BehaviorEngineのポインタの取得 [#gb86863f]
PHContactEngine* ce=NULL;
scene->GetBehaviors().Find(ce);
if(ce) ce->bDraw = true;
これで,ce にシーングラフのなかの PHContactEngineを取得して,bDraw フラグを true にしています.
関節エンジンも,
PHJointEngine* je=NULL;
scene->GetBehaviors().Find(je);
でとれますが,目当てのJointへのポインタを手に入れるためには,そのあと階層を追って,
GetChildObject(int)を呼び出さなければなりません.
こんなときは,名前をつけておくと簡単です.特定の名前のジョイントと接続するには,
PHJoint1D* jnt1;
scene->FindObject(jnt1, "jnt1");
PHJointPid* pid1 = PHJointPid::Find(jnt1, scene);
static double th=0.0;
th = th += 0.1;
pid1->goal = Rad(th);
のようにすればできます.