スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Pov-Ray各材質の表現 ODE連携

今週は引き続きPov-Rayの材質表現を追加したり,設定をファイルに保存できるようにする.

ウレタンゴム,カーボンの表現:


ウレタンゴムはSSLT(Subsurface Light Transport)による拡散透過表現.
pigment { color rgb<187/255,150/255,30/255> }

finish {diffuse 0.7 roughness 0.01 reflection 0.03
subsurface { translucency <1.0,1.0,1.0>*3.0 }}

interior { ior 1.50 }

カーボンはdifuseを下げたチェッカー模様+弱い鏡面反射設定でそれらしくなる.
pigment{checker color rgb<0.1,0.1,0.1> color rgb<0.3,0.3,0.3> scale 2}

finish {diffuse 0.1 specular 0.5 roughness 0.2 reflection 0.03}



材質設定は面倒な作業だが,少なくとも1回行えばファイルロードで2回目からは不要になるようにした.


次に材質設定をODEに反映させて物理シミュレーションが行えるようにする.
約1000個のランダムなサイズの積み木+鉄のブロックの衝突:



材料ごとの密度からポリゴンの体積,重量や重心,慣性モーメントは計算で求まるため,材質の割り当てのみで済む.
ODEでは直方体,球,円柱といった基本図形のほか,3角形ポリゴンの自由形状も扱うことができる.
3角形ポリゴンの体積は3角メッシュの頂点(vector_a1,vector_a2,vector_a3)と原点(vector_a4(0,0,0))で作られる微小3角錐の体積を総和して求める.
プログラム例:
struct Zahyo{
float x;
float y;
float z;
}
//***********3角ポリゴンと原点を結んでできる3角錐の体積を返す*****************
float Get_Volume_Triangular_Pyramid(Zahyo a1,Zahyo a2,Zahyo a3)
{
Zahyo v1;
float s;
v1.x=a1.y*a2.z-a1.z*a2.y; //a1xa2(外積)の計算
v1.y=a1.z*a2.x-a1.x*a2.z;
v1.z=a1.x*a2.y-a1.y*a2.x;
s=(v1.x*a3.x+v1.y*a3.y+v1.z*a3.z)/6.0; //a3をかける
return s;
}
//***********3角ポリゴンと原点を結んでできる3角錐の重心を返す*****************
Zahyo Get_Gpos_Triangular_Pyramid(Zahyo a1,Zahyo a2,Zahyo a3)
{
Zahyo v1;
v1.x=(a1.x+a2.x+a3.x)/4.0; //3点+原点を通る3角錐の重心
v1.y=(a1.y+a2.y+a3.y)/4.0; //3点+原点を通る3角錐の重心
v1.z=(a1.z+a2.z+a3.z)/4.0; //3点+原点を通る3角錐の重心
return v1;
}

//***********ポリゴンから簡易的に質量,重心を求める******************
void Set_STL_MASS_Param_Light(void)
{
int i,j,max_cnt;
float dv,vo;
Zahyo g_pos,sum_p;

Copy_Rocal_STL_DATA();//STLをロードした時の姿勢に復帰

for(j=0;j max_cnt=STL_FACE_NO[j];

vo=0;
g_pos.Reset_ZERO();
sum_p.Reset_ZERO();

for(i=0;i dv=Get_Volume_Triangular_Pyramid(STL_MULT[j][i].a,STL_MULT[j][i].b,STL_MULT[j][i].c); //微小体積を積算
vo+=dv;
g_pos=Get_Gpos_Triangular_Pyramid(STL_MULT[j][i].a,STL_MULT[j][i].b,STL_MULT[j][i].c); //微小三角錐の重心位置
sum_p.x+=g_pos.x*dv;
sum_p.y+=g_pos.y*dv;
sum_p.z+=g_pos.z*dv;
}

sum_p.x/=vo;
sum_p.y/=vo;
sum_p.z/=vo;
STL_COG[j]=sum_p; //重心座標[mm]
Part_Weight[j]=MAT_Density[MAT_NO[j]]*vo/1000.0; //重量[kg]
}
}


慣性モーメントはODEのAPIを使って求める.
dMass m;
m.mass=Part_Weight[i]; //重量=体積x密度
dMassSetTrimeshTotal(&m,Part_Weight[i],stl_plygons[i].geom); //慣性テンソル行列を取得
dGeomSetPosition(stl_plygons[i].geom, -m.c[0], -m.c[1], -m.c[2]);//ジオメトリを重心位置に動かす
dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);//重心位置をオフセット

これらのソフト間で形状データを受け渡す際の注意点として,座標軸の向きがある.
ODE,OpenGLは右手系 Pov-Rayは左手系である。また,初期のZ方向の向きなどが違う.
左右や天地が反転した画像が出力される場合,原因は座標系にある場合が多い.
平行移動だけでなく,3角メッシュの表裏を決定する3角形の頂点座標の回転順序も逆になるので要注意!

よってODEの結果をOpen_GL,Pov-Rayでレンダリングする際には物体の姿勢行列を入れ替える必要がある.
ODE⇒OpenGL
//********回転行列をODEのものからGL用の横型に変換する**********
void TransRate_RotMatrixGL(float rot_matrix[])
{
int i;
float rot_buf[16];
//**********ODEのマトリクス成分→OpenGLのマトリクス成分に変換********
rot_buf[0]=rot_matrix[0];
rot_buf[4]=rot_matrix[1];//
rot_buf[8]=rot_matrix[2];

rot_buf[12]=rot_matrix[3];

rot_buf[1]=rot_matrix[4];
rot_buf[5]=rot_matrix[5];//
rot_buf[9]=rot_matrix[6];

rot_buf[13]=rot_matrix[7];

rot_buf[2]=rot_matrix[8];
rot_buf[6]=rot_matrix[9];//
rot_buf[10]=rot_matrix[10];

rot_buf[14]=rot_matrix[11];
//*********ODEの行列は3×3***********
rot_buf[3]=0;
rot_buf[7]=0;
rot_buf[11]=0;
rot_buf[15]=1;

for(i=0;i<16;i++)
rot_matrix[i]=rot_buf[i];
}

OpenGL⇒Pov-Ray
物体を配置する際,以下の変換を行う.

rotate 90*x
matrix<
1,0,0,
0,-1,0,
0,0,1,
0,0,0>






スポンサーサイト

この記事へのコメント

トラックバック

URL :

プロフィール

もやね

Author:もやね
長野県在住の会社員(メカニカル・エンジニア).
ロボットは完全な趣味としてやってます.
E-mail:
mo_ya_ne[a]yahoo.co.jp
[a]⇒@

最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
カテゴリー
FC2カウンター
ブログ内検索
RSSフィード
リンク
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。