カメラ変換
struct FVECTOR3{ float x,y,z; }; |
Normalize() | 正規化 |
Cross(const FVECTOR3 &n); | 外積計算 |
struct FMATRIX{ float m[4][4]; }; |
Identity() | 単位行列を代入 |
Invert(); | 逆行列を求める |
struct EXP_CAMERA{ FVECTOR3 dir; FVECTOR3 up; FVECTOR3 pos; float dist; float fov; float nearz; float farz; int ortho; }; |
dir | 前方向 |
up | 上方向 |
pos | 位置 |
dist | 注視点までの距離 |
fov | 画角 |
nearz | ニア面 |
farz | ファー面 |
ortho | 1で平行投影 |
struct MQOSCENE{ FVECTOR3 pos; FVECTOR3 lookat; float pich; float head; float zoom2; int ortho; }; |
pos | 位置 |
lookat | 注視点 |
pich | ピッチ |
head | ヘッド |
zoom2 | ズーム |
ortho | 1で平行投影 |
/*============================================================= ; マトリクス3x3にピッチ、ヘッド回転設定 ; x,y軸回転(pich,head) =============================================================*/ static void SetRotXY(FMATRIX &mt,float rx,float ry){ float sx,cx,sy,cy; sx=sinf(rx); cx=cosf(rx); sy=sinf(ry); cy=cosf(ry); mt.m[0][0]= cy; mt.m[0][1]= sy*sx; mt.m[0][2]= sy*cx; mt.m[1][0]= 0.0f; mt.m[1][1]= cx; mt.m[1][2]=-sx; mt.m[2][0]= sy; mt.m[2][1]=-cy*sx; mt.m[2][2]=-cy*cx; } /*============================================================= ; メタセコカメラからマトリクスへ変換 ; in) mqoscene MQOシーンパラメータ ; ap アスペクト比 ; ret) vmt ビューマトリクス ; pmt プロジェクションマトリクス =============================================================*/ void ConvertMQCamera_ViewPers(FMATRIX &vmt,FMATRIX &pmt,const MQOSCENE *mqoscene,float ap){ FVECTOR pos =mqoscene->pos; FVECTOR lookat=mqoscene->lookat; float pich =mqoscene->pich; float head =mqoscene->head; float zoom2 =mqoscene->zoom2; int ortho =mqoscene->ortho; float dist =pos.z; //距離 float nearz =dist*0.15f; //ニア面 float farz =dist*(4.0f*PI); //ファー面 //vmt,pmt初期化 vmt.Identity(); pmt.Identity(); //ピッチ、ヘッド回転設定 SetRotXY(vmt,pich,head); //視点、注視点設定 FVECTOR v; v=vmt*(-lookat)+pos; vmt.m[3][0]=v.x; vmt.m[3][1]=v.y; vmt.m[3][2]=v.z; //FOV計算 const float fov_scl=0.001f; //FOV倍率 float ww=fov_scl*zoom2; float hh=ww*ap; if(ortho==0){ //Persの場合 pmt.m[0][0]=ww*dist; pmt.m[1][1]=hh*dist; pmt.m[2][2]=1.0f; pmt.m[3][2]=-nearz; pmt.m[2][3]=1.0f; }else{ //Orthoの場合 pmt.m[0][0]=ww; pmt.m[1][1]=hh; pmt.m[2][2]=1.0f/farz; pmt.m[3][2]=0.0f; pmt.m[2][3]=0.0f; } } |
/*============================================================= ; マトリクスからメタセコカメラへ変換 ; in) vmt ビューマトリクス ; pmt プロジェクションマトリクス ; ret) mqoscene MQOシーンパラメータ =============================================================*/ void ConvertViewPers_MQCamera(MQOSCENE *mqoscene,const FMATRIX &vmt,const FMATRIX &pmt){ FVECTOR pos,lookat; float dist,nearz,farz,zoom2,fov,pich,head; int ortho; const float fov_scl=0.001f; //FOV倍率 //FOV計算 float fov_ww=fabs(pmt.m[0][0]); float fov_hh=fabs(pmt.m[1][1]); if(fov_ww>fov_hh){ fov=fov_ww; }else{ fov=fov_hh; } //方向計算 pich=asinf(-vmt.m[1][2]); head=asinf( vmt.m[2][0]); // if(pmt.m[2][3]!=0.0f){ //pers ortho=0; nearz=-pmt.m[3][2]; dist =nearz/0.15f; farz =dist*(4.0f*PI); zoom2=fov/(dist*fov_scl); }else{ //ortho ortho=1; farz=1.0f/pmt.m[2][2]; dist=farz/(4.0f*PI); nearz=dist*0.15f; zoom2=fov/fov_scl; } //位置計算 lookat.x=0; lookat.y=0; lookat.z=-(vmt.m[3][2]-dist)/vmt.m[2][2]; pos.x=vmt.m[3][0]-(vmt.m[0][2]*(-lookat.z)); pos.y=vmt.m[3][1]-(vmt.m[1][2]*(-lookat.z)); pos.z=vmt.m[3][2]-(vmt.m[2][2]*(-lookat.z)); // mqoscene->pos=pos; mqoscene->lookat=lookat; mqoscene->zoom2=zoom2; mqoscene->head =head; mqoscene->pich =pich; mqoscene->ortho=ortho; } |
/*============================================================= ; 一般的なカメラからマトリクスへ変換 ; in) exp_camera 一般的なカメラ ; ap アスペクト比 ; ret) vmt ビューマトリクス ; pmt プロジェクションマトリクス =============================================================*/ void ConvertExpCamera_ViewPers(FMATRIX &vmt,FMATRIX &pmt,IEXP_CAMERA *exp_camera,float ap){ FVECTOR3 zd =exp_camera->dir; FVECTOR3 yd =exp_camera->up; FVECTOR3 pos=exp_camera->pos; float fov =exp_camera->fov; float dist =exp_camera->dist; float nearz =exp_camera->nearz; float farz =exp_camera->farz; int ortho =exp_camera->ortho; //方向設定 vmt.Identity(); pmt.Identity(); vmt.m[0][2]=zd.x; vmt.m[1][2]=zd.y; vmt.m[2][2]=zd.z; FVECTOR xd=zd.Cross(yd); xd.Normalize(); yd=xd.Cross(zd); yd.Normalize(); vmt.m[0][1]=yd.x; vmt.m[1][1]=yd.y; vmt.m[2][1]=yd.z; vmt.m[0][0]=xd.x; vmt.m[1][0]=xd.y; vmt.m[2][0]=xd.z; //位置設定 float x=-pos.x; float y=-pos.y; float z=-pos.z; vmt.m[3][0]=xd.x*x+xd.y*y+xd.z*z; vmt.m[3][1]=yd.x*x+yd.y*y+yd.z*z; vmt.m[3][2]=zd.x*x+zd.y*y+zd.z*z; //FOV設定 float fov_w=fov; float fov_h=fov*ap; float Q=1.0f; float w,h; w=1.0f/tanf(fov_w*0.5f); h=1.0f/tanf(fov_h*0.5f); if(ortho==0){ //Pers pmt.m[0][0]= w; pmt.m[1][1]= h; pmt.m[2][2]= Q; pmt.m[3][2]=-Q*nearz; pmt.m[2][3]=1.0f; }else{ //Ortho pmt.m[0][0]= w/dist; pmt.m[1][1]= h/dist; pmt.m[2][2]=1.0f/farz; pmt.m[3][2]=0.0f; pmt.m[2][3]=0.0f; } } |
/*============================================================= ; マトリクスから一般的なカメラへ変換 ; in) vmt ビューマトリクス ; pmt プロジェクションマトリクス ; ret) exp_camera 一般的なカメラ =============================================================*/ void ConvertViewPers_ExpCamera(EXP_CAMERA *exp_camera,const FMATRIX &vmt,const FMATRIX &pmt){ FVECTOR pos,zd,yd; float dist; //位置計算 pos.x= ( vmt.m[1][0]*vmt.m[2][1]*vmt.m[3][2] +vmt.m[1][1]*vmt.m[2][2]*vmt.m[3][0] +vmt.m[1][2]*vmt.m[2][0]*vmt.m[3][1] -vmt.m[1][0]*vmt.m[2][2]*vmt.m[3][1] -vmt.m[1][1]*vmt.m[2][0]*vmt.m[3][2] -vmt.m[1][2]*vmt.m[2][1]*vmt.m[3][0]); pos.y=-( vmt.m[0][0]*vmt.m[2][1]*vmt.m[3][2] +vmt.m[0][1]*vmt.m[2][2]*vmt.m[3][0] +vmt.m[0][2]*vmt.m[2][0]*vmt.m[3][1] -vmt.m[0][0]*vmt.m[2][2]*vmt.m[3][1] -vmt.m[0][1]*vmt.m[2][0]*vmt.m[3][2] -vmt.m[0][2]*vmt.m[2][1]*vmt.m[3][0]); pos.z= ( vmt.m[0][0]*vmt.m[1][1]*vmt.m[3][2] +vmt.m[0][1]*vmt.m[1][2]*vmt.m[3][0] +vmt.m[0][2]*vmt.m[1][0]*vmt.m[3][1] -vmt.m[0][0]*vmt.m[1][2]*vmt.m[3][1] -vmt.m[0][1]*vmt.m[1][0]*vmt.m[3][2] -vmt.m[0][2]*vmt.m[1][1]*vmt.m[3][0]); //方向計算 zd.x =vmt.m[0][2]; zd.y =vmt.m[1][2]; zd.z =vmt.m[2][2]; yd.x =vmt.m[0][1]; yd.y =vmt.m[1][1]; yd.z =vmt.m[2][1]; zd.Normalize(); yd.Normalize(); //距離 dist=vmt.m[3][2]; // exp_camera->pos =pos; exp_camera->dir =zd; exp_camera->up =yd; exp_camera->dist=dist; // if(pmt.m[2][3]!=0.0f){ //Pers float w=pmt.m[0][0]; float h=pmt.m[1][1]; float fov_w=atanf(1.0f/w)*2.0f; float fov_h=atanf(1.0f/h)*2.0f; exp_camera->ortho=0; exp_camera->fov =fov_w; exp_camera->nearz=-pmt.m[3][2]/pmt.m[2][2]; }else{ //Ortho float w=pmt.m[0][0]*dist; float h=pmt.m[1][1]*dist; float fov_w=atanf(1.0f/w)*2.0f; float fov_h=atanf(1.0f/h)*2.0f; exp_camera->ortho=1; exp_camera->fov =fov_w; exp_camera->farz =1.0f/pmt.m[2][2]; } } |