カメラ変換
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];
}
}
|