3Dの描画
3Dの描画
開発環境はDev-C++4.9.9.2、gcc3.4.2です。
3Dの座標を2Dに描画しようとして、プログラムを組んでみました。
実行すると、draw3dlineでエラーが出ているようです。
たぶんhenkan3dzahyou内のエラーだと思います。
henkan3dzahyouの仕組みは
1.カメラが向いている方向のベクトルを計算します
2.変換したい座標からカメラが向いている方向の直線に下ろした垂線のベクトルを計算します
(変換したい座標が終点)
同時にカメラから垂線の足までのベクトルも用意します
3.カメラの横方向と縦方向のベクトルを用意します(描画する際の方向の基準です)
4.それぞれのベクトルのなす角のコサインを計算します
msin:基準の横方向と垂線のなす角のコサイン
scos:垂線と基準の縦方向のなす角のコサイン
dcos:カメラと求めたい座標を結ぶ線とカメラが向いている方向のなす角のコサイン
この時dcosが負だったら、座標がカメラの後ろにあるとしてエラーにします
5.コサインから必要なサインやタンジェントを計算します
6.実際に描画する中央の点と描画する点との距離を計算します
7.その距離と角度のサイン・コサインから実際に描画する座標を計算します
解決法がわかる方がいらっしゃいましたら教えていただければ幸いです。
よろしくお願いします。
3Dの座標を2Dに描画しようとして、プログラムを組んでみました。
実行すると、draw3dlineでエラーが出ているようです。
たぶんhenkan3dzahyou内のエラーだと思います。
henkan3dzahyouの仕組みは
1.カメラが向いている方向のベクトルを計算します
2.変換したい座標からカメラが向いている方向の直線に下ろした垂線のベクトルを計算します
(変換したい座標が終点)
同時にカメラから垂線の足までのベクトルも用意します
3.カメラの横方向と縦方向のベクトルを用意します(描画する際の方向の基準です)
4.それぞれのベクトルのなす角のコサインを計算します
msin:基準の横方向と垂線のなす角のコサイン
scos:垂線と基準の縦方向のなす角のコサイン
dcos:カメラと求めたい座標を結ぶ線とカメラが向いている方向のなす角のコサイン
この時dcosが負だったら、座標がカメラの後ろにあるとしてエラーにします
5.コサインから必要なサインやタンジェントを計算します
6.実際に描画する中央の点と描画する点との距離を計算します
7.その距離と角度のサイン・コサインから実際に描画する座標を計算します
解決法がわかる方がいらっしゃいましたら教えていただければ幸いです。
よろしくお願いします。
- 添付ファイル
-
- 3dtest.zip
- プログラムです。
- (13.97 KiB) ダウンロード数: 242 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
これってGDBとかでトレースしたんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
すいません、GDBって何ですか?softya(ソフト屋) さんが書きました:これってGDBとかでトレースしたんでしょうか?
[hr]とりあえず描画はされるようになりました。
しかし、x方向にカメラの首を振ると、描画がおかしくなってしまいました。
どこを直せばいいかわかりましたら教えていただければ幸いです。
よろしくお願いします。
- 添付ファイル
-
- 3dtest(2).zip
- プログラムです。
- (15.64 KiB) ダウンロード数: 222 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
GDBはデバッガです。
もしかしてDev-C++だと統合環境として内部で動くGDBは隠蔽されているのかな?
と言う事で、Dev-C++でデバッガでトレースしましたか?
>しかし、x方向にカメラの首を振ると、描画がおかしくなってしまいました。
>どこを直せばいいかわかりましたら教えていただければ幸いです。
この件は、Dev-C++をインストールして確認してみるのでちょっと待ってくださいね。
もしかしてDev-C++だと統合環境として内部で動くGDBは隠蔽されているのかな?
と言う事で、Dev-C++でデバッガでトレースしましたか?
>しかし、x方向にカメラの首を振ると、描画がおかしくなってしまいました。
>どこを直せばいいかわかりましたら教えていただければ幸いです。
この件は、Dev-C++をインストールして確認してみるのでちょっと待ってくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
とりあえずhenkan3dzahyou関数をこれに差し替えると(直ってはいませんが)改善した気がします。
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera) {
double dx,dy,dz;/*カメラが向いている方向*/
double hx,hy,hz;/*カメラが向いている方向への垂線*/
double kx,ky,kz;/*基準の方向*/
double sx,sy,sz;/*基準と垂直の方向*/
double x1,y1,z1,k;/*垂線計算用*/
double length;/*垂線の長さ*/
double mcos,scos,dcos;/*コサインの値*/
double msin;/*サインの値*/
double dtan;/*タンジェントの値*/
double klength;/*視野角ぎりぎりの時の長さ*/
double dlength;/*描画に使う長さ*/
debuginit;
printstr("henkan3dzahyou開始");
printbekutoru("カメラの座標",camera->x,camera->y,camera->z);
printbekutoru("カメラの回転",camera->cx,camera->cy,camera->cz);
printnum("カメラの視野(ピクセル)",camera->genkai);
printnum("カメラの視野(角度)",camera->genkaiangle);
printnum("カメラの描画の中心x",camera->centerx);
printnum("カメラの描画の中心y",camera->centery);
printbekutoru("変換する座標",x,y,z);
/*カメラが向いている方向を計算*/
dy=cos(camera->cy);
dz=sin(camera->cy);
dx=dy*sin(camera->cx);
dy=dy*cos(camera->cx);
printbekutoru("カメラの方向",dx,dy,dz);
/*垂線を計算*/
x1=x-camera->x;
y1=y-camera->y;
z1=z-camera->z;
k=(x1*dx+y1*dy+z1*dz)/(dx*dx+dy*dy+dz*dz);
hx=x1-k*dx;
hy=y1-k*dy;
hz=z1-k*dz;
length=sqrt(hx*hx+hy*hy+hz*hz);
printbekutoru("カメラから座標へ",x1,y1,z1);
printnum("k",k);
printbekutoru("垂線",hx,hy,hz);
printnum("垂線の長さ",length);
/*基準の方向を計算*/
ky=-sin(camera->cx);
kx=cos(camera->cx);
ky=ky*cos(camera->cy);
kz=ky*sin(camera->cy);
printbekutoru("基準(横)",kx,ky,kz);
/*回転は未実装*/
/*基準と垂直の方向を計算*/
sy=-sin(camera->cy);
sz=cos(camera->cy);
sy=sy*cos(camera->cx);
sx=sy*sin(camera->cx);
printbekutoru("基準(縦)",sx,sy,sz);
/*回転は未実装*/
/*コサインの値を計算*/
mcos=(hx*kx+hy*ky+hz*kz)?
(hx*kx+hy*ky+hz*kz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(kx*kx+ky*ky+kz*kz))/*大きさの積*/
:0;
scos=(hx*sx+hy*sy+hz*sz)?
(hx*sx+hy*sy+hz*sz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(sx*sx+sy*sy+sz*sz))/*大きさの積*/
:0;
dcos=(x1*dx+y1*dy+z1*dz)?
(x1*dx+y1*dy+z1*dz)/*内積*/
/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(dx*dx+dy*dy+dz*dz))/*大きさの積*/
:0;
printnum("mcos",mcos);
printnum("scos",scos);
printnum("dcos",dcos);
#ifdef DEBUG
if(dcos<0) {
printstr("エラー");
debugend;
return 0;
}
#else
if(dcos<0)return 0;
#endif
/*サインの値を計算*/
msin=sqrt(1-mcos*mcos)*(scos>=0?1:-1);
printnum("msin",msin);
/*タンジェントの値を計算*/
dtan=sqrt(1/(dcos*dcos)-1);
printnum("dtan",dtan);
/*基準の長さを計算*/
klength=camera->genkai/tan(camera->genkaiangle);
printnum("klength",klength);
/*描画に使う長さを計算*/
dlength=klength*dtan;
printnum("dlength",dlength);
/*実際に描画する座標を計算*/
*ox=camera->centerx+dlength*mcos;
*oy=camera->centery-dlength*msin;
printnum("描画x",*ox);
printnum("描画y",*oy);
printstr("henkan3dzahyou終了");
debugend;
return 1;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
申し訳ない行列を使わない透視変換は何十年ぶりなので、ソースの解読に時間がかかりそうです。
行列の透視変換に変えてもOKでしょうか?
もし、このままが良いならもう少し時間を下さい。
あとご自分でカメラ45度とか分かりやすい数値で机上計算してみて、実際に動かした値と違うか付きあわせてみる手もありますよ。
行列の透視変換に変えてもOKでしょうか?
もし、このままが良いならもう少し時間を下さい。
あとご自分でカメラ45度とか分かりやすい数値で机上計算してみて、実際に動かした値と違うか付きあわせてみる手もありますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
行列はわからないのでこのままでお願いします。
とりあえず回転のアルゴリズムを変えてみました。
改善しません。
とりあえず回転のアルゴリズムを変えてみました。
改善しません。
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera) {
double dx,dy,dz;/*カメラが向いている方向*/
double hx,hy,hz;/*カメラが向いている方向への垂線*/
double kx,ky,kz;/*基準の方向*/
double sx,sy,sz;/*基準と垂直の方向*/
double x1,y1,z1,k;/*垂線計算用*/
double length;/*垂線の長さ*/
double mcos,scos,dcos;/*コサインの値*/
double msin;/*サインの値*/
double dtan;/*タンジェントの値*/
double klength;/*視野角ぎりぎりの時の長さ*/
double dlength;/*描画に使う長さ*/
debuginit;
printstr("henkan3dzahyou開始");
printbekutoru("カメラの座標",camera->x,camera->y,camera->z);
printbekutoru("カメラの回転",camera->cx,camera->cy,camera->cz);
printnum("カメラの視野(ピクセル)",camera->genkai);
printnum("カメラの視野(角度)",camera->genkaiangle);
printnum("カメラの描画の中心x",camera->centerx);
printnum("カメラの描画の中心y",camera->centery);
printbekutoru("変換する座標",x,y,z);
/*カメラが向いている方向を計算*/
dy=cos(camera->cx);
dx=sin(camera->cx);
dz=sin(camera->cy);
dy=dy*cos(camera->cy);
dx=dx*cos(camera->cy);
printbekutoru("カメラの方向",dx,dy,dz);
/*垂線を計算*/
x1=x-camera->x;
y1=y-camera->y;
z1=z-camera->z;
k=(x1*dx+y1*dy+z1*dz)/(dx*dx+dy*dy+dz*dz);
hx=x1-k*dx;
hy=y1-k*dy;
hz=z1-k*dz;
length=sqrt(hx*hx+hy*hy+hz*hz);
printbekutoru("カメラから座標へ",x1,y1,z1);
printnum("k",k);
printbekutoru("垂線",hx,hy,hz);
printnum("垂線の長さ",length);
/*基準の方向を計算*/
ky=-sin(camera->cx);
kx=cos(camera->cx);
printbekutoru("基準(横)",kx,ky,kz);
/*回転は未実装*/
/*基準と垂直の方向を計算*/
sy=-sin(camera->cy);
sz=cos(camera->cy);
printbekutoru("基準(縦)",sx,sy,sz);
/*回転は未実装*/
/*コサインの値を計算*/
mcos=(hx*kx+hy*ky+hz*kz)?
(hx*kx+hy*ky+hz*kz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(kx*kx+ky*ky+kz*kz))/*大きさの積*/
:0;
scos=(hx*sx+hy*sy+hz*sz)?
(hx*sx+hy*sy+hz*sz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(sx*sx+sy*sy+sz*sz))/*大きさの積*/
:0;
dcos=(x1*dx+y1*dy+z1*dz)?
(x1*dx+y1*dy+z1*dz)/*内積*/
/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(dx*dx+dy*dy+dz*dz))/*大きさの積*/
:0;
printnum("mcos",mcos);
printnum("scos",scos);
printnum("dcos",dcos);
#ifdef DEBUG
if(dcos<0) {
printstr("エラー");
debugend;
return 0;
}
#else
if(dcos<0)return 0;
#endif
/*サインの値を計算*/
msin=sqrt(1-mcos*mcos)*(scos>=0?1:-1);
printnum("msin",msin);
/*タンジェントの値を計算*/
dtan=sqrt(1/(dcos*dcos)-1);
printnum("dtan",dtan);
/*基準の長さを計算*/
klength=camera->genkai/tan(camera->genkaiangle);
printnum("klength",klength);
/*描画に使う長さを計算*/
dlength=klength*dtan;
printnum("dlength",dlength);
/*実際に描画する座標を計算*/
*ox=camera->centerx+dlength*mcos;
*oy=camera->centery-dlength*msin;
printnum("描画x",*ox);
printnum("描画y",*oy);
printstr("henkan3dzahyou終了");
debugend;
return 1;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
んじゃ、こっちで一旦行列で組んでそれを展開したものを作ってみます。
展開したものは、ほとんど同じになると思いますので。
それと値を突き合わせれば、何処の透視変換の式の部分に問題があるか分かってくると思います。
あと、この透視変換はオリジナルですか、それとも何処かのサイトや本を参考にされましたか?
展開したものは、ほとんど同じになると思いますので。
それと値を突き合わせれば、何処の透視変換の式の部分に問題があるか分かってくると思います。
あと、この透視変換はオリジナルですか、それとも何処かのサイトや本を参考にされましたか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
これは自分なりに考えて作っています。
カメラの向いている方向に垂直な基準の平面を置き、
カメラと対象の座標を結ぶ線とその平面の交点の座標を返そうとしています。
カメラの向いている方向に垂直な基準の平面を置き、
カメラと対象の座標を結ぶ線とその平面の交点の座標を返そうとしています。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
分かりました。みけCAT さんが書きました:これは自分なりに考えて作っています。
カメラの向いている方向に垂直な基準の平面を置き、
カメラと対象の座標を結ぶ線とその平面の交点の座標を返そうとしています。
透視投影変換の基本通りですね。
ところで画角が150度と定義されているので、もしこのとおり働いていると超広角レンズな値ですがこのままでよろしいですか?
http://ja.wikipedia.org/wiki/%E7%94%BB%E8%A7%92
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
その値は適切な値がわからなかったので、適当に入れておきました。softya(ソフト屋) さんが書きました:ところで画角が150度と定義されているので、もしこのとおり働いていると超広角レンズな値ですがこのままでよろしいですか?
リンク先を見たところ、50度くらいがいいということですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
人間の目に近い画角の50度ぐらいが適度な値だと思います。みけCAT さんが書きました:その値は適切な値がわからなかったので、適当に入れておきました。softya(ソフト屋) さんが書きました:ところで画角が150度と定義されているので、もしこのとおり働いていると超広角レンズな値ですがこのままでよろしいですか?
リンク先を見たところ、50度くらいがいいということですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
だいぶいい感じになってきました。
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera) {
double dx,dy,dz;/*カメラが向いている方向*/
double hx,hy,hz;/*カメラが向いている方向への垂線*/
double kx,ky,kz;/*基準の方向*/
double sx,sy,sz;/*基準と垂直の方向*/
double x1,y1,z1,k;/*垂線計算用*/
double length;/*垂線の長さ*/
double mcos,scos,dcos;/*コサインの値*/
double msin;/*サインの値*/
double dtan;/*タンジェントの値*/
double klength;/*視野角ぎりぎりの時の長さ*/
double dlength;/*描画に使う長さ*/
debuginit;
printstr("henkan3dzahyou開始");
printbekutoru("カメラの座標",camera->x,camera->y,camera->z);
printbekutoru("カメラの回転",camera->cx,camera->cy,camera->cz);
printnum("カメラの視野(ピクセル)",camera->genkai);
printnum("カメラの視野(角度)",camera->genkaiangle);
printnum("カメラの描画の中心x",camera->centerx);
printnum("カメラの描画の中心y",camera->centery);
printbekutoru("変換する座標",x,y,z);
/*カメラが向いている方向を計算*/
dy=cos(camera->cx);
dx=sin(camera->cx);
dz=sin(camera->cy);
dy=dy*cos(camera->cy);
dx=dx*cos(camera->cy);
printbekutoru("カメラの方向",dx,dy,dz);
/*垂線を計算*/
x1=x-camera->x;
y1=y-camera->y;
z1=z-camera->z;
k=(x1*dx+y1*dy+z1*dz)/(dx*dx+dy*dy+dz*dz);
hx=x1-k*dx;
hy=y1-k*dy;
hz=z1-k*dz;
length=sqrt(hx*hx+hy*hy+hz*hz);
printbekutoru("カメラから座標へ",x1,y1,z1);
printnum("k",k);
printbekutoru("垂線",hx,hy,hz);
printnum("垂線の長さ",length);
/*基準の方向を計算*/
ky=-sin(camera->cx);
kx=cos(camera->cx);
kz=0;
/*kz=sin(camera->cz);
ky=ky*cos(camera->cz);
kx=kx*cos(camera->cz);*/
printbekutoru("基準(横)",kx,ky,kz);
/*基準と垂直の方向を計算*/
sy=-sin(camera->cy);
sz=cos(camera->cy);
sx=sy*sin(camera->cx);
sy=sy*cos(camera->cx);
printbekutoru("基準(縦)",sx,sy,sz);
/*コサインの値を計算*/
mcos=(hx*kx+hy*ky+hz*kz)?
(hx*kx+hy*ky+hz*kz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(kx*kx+ky*ky+kz*kz))/*大きさの積*/
:0;
scos=(hx*sx+hy*sy+hz*sz)?
(hx*sx+hy*sy+hz*sz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(sx*sx+sy*sy+sz*sz))/*大きさの積*/
:0;
dcos=(x1*dx+y1*dy+z1*dz)?
(x1*dx+y1*dy+z1*dz)/*内積*/
/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(dx*dx+dy*dy+dz*dz))/*大きさの積*/
:0;
printnum("mcos",mcos);
printnum("scos",scos);
printnum("dcos",dcos);
#ifdef DEBUG
if(dcos<0) {
printstr("エラー");
debugend;
return 0;
}
#else
if(dcos<0)return 0;
#endif
/*サインの値を計算*/
msin=sqrt(1-mcos*mcos)*(scos>=0?1:-1);
printnum("msin",msin);
/*タンジェントの値を計算*/
dtan=sqrt(1/(dcos*dcos)-1);
printnum("dtan",dtan);
/*基準の長さを計算*/
klength=camera->genkai/tan(camera->genkaiangle);
printnum("klength",klength);
/*描画に使う長さを計算*/
dlength=klength*dtan;
printnum("dlength",dlength);
/*実際に描画する座標を計算*/
*ox=camera->centerx+dlength*mcos;
*oy=camera->centery-dlength*msin;
printnum("描画x",*ox);
printnum("描画y",*oy);
printstr("henkan3dzahyou終了");
debugend;
return 1;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 3Dの描画
カメラの回転を実装してみましたが、どこかがおかしいようです。
どこが間違っているでしょうか?
どこが間違っているでしょうか?
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera) {
double dx,dy,dz;/*カメラが向いている方向*/
double hx,hy,hz;/*カメラが向いている方向への垂線*/
double kx,ky,kz;/*基準の方向*/
double sx,sy,sz;/*基準と垂直の方向*/
double x1,y1,z1,k;/*垂線計算用*/
double length;/*垂線の長さ*/
double mcos,scos,dcos;/*コサインの値*/
double msin;/*サインの値*/
double dtan;/*タンジェントの値*/
double klength;/*視野角ぎりぎりの時の長さ*/
double dlength;/*描画に使う長さ*/
debuginit;
printstr("henkan3dzahyou開始");
printbekutoru("カメラの座標",camera->x,camera->y,camera->z);
printbekutoru("カメラの回転",camera->cx,camera->cy,camera->cz);
printnum("カメラの視野(ピクセル)",camera->genkai);
printnum("カメラの視野(角度)",camera->genkaiangle);
printnum("カメラの描画の中心x",camera->centerx);
printnum("カメラの描画の中心y",camera->centery);
printbekutoru("変換する座標",x,y,z);
/*カメラが向いている方向を計算*/
dy=cos(camera->cx);
dx=sin(camera->cx);
dz=sin(camera->cy);
dy=dy*cos(camera->cy);
dx=dx*cos(camera->cy);
printbekutoru("カメラの方向",dx,dy,dz);
/*垂線を計算*/
x1=x-camera->x;
y1=y-camera->y;
z1=z-camera->z;
k=(x1*dx+y1*dy+z1*dz)/(dx*dx+dy*dy+dz*dz);
hx=x1-k*dx;
hy=y1-k*dy;
hz=z1-k*dz;
length=sqrt(hx*hx+hy*hy+hz*hz);
printbekutoru("カメラから座標へ",x1,y1,z1);
printnum("k",k);
printbekutoru("垂線",hx,hy,hz);
printnum("垂線の長さ",length);
/*基準の方向を計算*/
ky=-sin(camera->cx);
kx=cos(camera->cx);
kz=sin(camera->cz);
ky=ky*cos(camera->cz);
kx=kx*cos(camera->cz);
printbekutoru("基準(横)",kx,ky,kz);
/*基準と垂直の方向を計算*/
/*sy=-sin(camera->cy);
sz=cos(camera->cy);
sx=sy*sin(camera->cx);
sy=sy*cos(camera->cx);*/
/*ベクトルの外積を使ってみる*/
sx=ky*dz-dy*kz;
sy=kz*dx-dz*kx;
sz=kx*dy-dx*ky;
printbekutoru("基準(縦)",sx,sy,sz);
/*コサインの値を計算*/
mcos=(hx*kx+hy*ky+hz*kz)?
(hx*kx+hy*ky+hz*kz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(kx*kx+ky*ky+kz*kz))/*大きさの積*/
:0;
scos=(hx*sx+hy*sy+hz*sz)?
(hx*sx+hy*sy+hz*sz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(sx*sx+sy*sy+sz*sz))/*大きさの積*/
:0;
dcos=(x1*dx+y1*dy+z1*dz)?
(x1*dx+y1*dy+z1*dz)/*内積*/
/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(dx*dx+dy*dy+dz*dz))/*大きさの積*/
:0;
printnum("mcos",mcos);
printnum("scos",scos);
printnum("dcos",dcos);
#ifdef DEBUG
if(dcos<0) {
printstr("エラー");
debugend;
return 0;
}
#else
if(dcos<0)return 0;
#endif
/*サインの値を計算*/
msin=sqrt(1-mcos*mcos)*(scos>=0?1:-1);
printnum("msin",msin);
/*タンジェントの値を計算*/
dtan=sqrt(1/(dcos*dcos)-1);
printnum("dtan",dtan);
/*基準の長さを計算*/
klength=camera->genkai/tan(camera->genkaiangle);
printnum("klength",klength);
/*描画に使う長さを計算*/
dlength=klength*dtan;
printnum("dlength",dlength);
/*実際に描画する座標を計算*/
*ox=camera->centerx+dlength*mcos;
*oy=camera->centery-dlength*msin;
printnum("描画x",*ox);
printnum("描画y",*oy);
printstr("henkan3dzahyou終了");
debugend;
return 1;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 3Dの描画
一旦プロジェクト全体を上げます。
- 添付ファイル
-
- 3dtest(3).zip
- プログラムです。
- (16.13 KiB) ダウンロード数: 226 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 3Dの描画
計算方法を変えて少しは改善しましたが、完全ではありません。
「どこが悪いか」というより、基準のベクトルを計算するところが間違っていると思います。
どう直せばいいか教えていただきたいです。
y方向の回転がPI/2を超えると、画像の向きが逆になってしまうようです。
よろしくお願いします。
「どこが悪いか」というより、基準のベクトルを計算するところが間違っていると思います。
どう直せばいいか教えていただきたいです。
y方向の回転がPI/2を超えると、画像の向きが逆になってしまうようです。
よろしくお願いします。
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera) {
double dx,dy,dz;/*カメラが向いている方向*/
double hx,hy,hz;/*カメラが向いている方向への垂線*/
double kx,ky,kz;/*基準の方向*/
double sx,sy,sz;/*基準と垂直の方向*/
double kdx,kdy,kdz;/*基準の方向計算用*/
double x1,y1,z1,k;/*垂線計算用*/
double length;/*垂線の長さ*/
double mcos,scos,dcos;/*コサインの値*/
double msin;/*サインの値*/
double dtan;/*タンジェントの値*/
double klength;/*視野角ぎりぎりの時の長さ*/
double dlength;/*描画に使う長さ*/
debuginit;
printstr("henkan3dzahyou開始");
printbekutoru("カメラの座標",camera->x,camera->y,camera->z);
printbekutoru("カメラの回転",camera->cx,camera->cy,camera->cz);
printnum("カメラの視野(ピクセル)",camera->genkai);
printnum("カメラの視野(角度)",camera->genkaiangle);
printnum("カメラの描画の中心x",camera->centerx);
printnum("カメラの描画の中心y",camera->centery);
printbekutoru("変換する座標",x,y,z);
/*カメラが向いている方向を計算*/
dy=cos(camera->cx);
dx=sin(camera->cx);
dz=sin(camera->cy);
dy=dy*cos(camera->cy);
dx=dx*cos(camera->cy);
printbekutoru("カメラの方向",dx,dy,dz);
/*垂線を計算*/
x1=x-camera->x;
y1=y-camera->y;
z1=z-camera->z;
k=(x1*dx+y1*dy+z1*dz)/(dx*dx+dy*dy+dz*dz);
hx=x1-k*dx;
hy=y1-k*dy;
hz=z1-k*dz;
length=sqrt(hx*hx+hy*hy+hz*hz);
printbekutoru("カメラから座標へ",x1,y1,z1);
printnum("k",k);
printbekutoru("垂線",hx,hy,hz);
printnum("垂線の長さ",length);
/*基準の方向を計算*/
/*ky=-sin(camera->cx);
kx=cos(camera->cx);
kz=sin(camera->cz);
ky=ky*cos(camera->cz);
kx=kx*cos(camera->cz);*/
kdx=sin(camera->cz);
kdz=-cos(camera->cz);
kdx=kdx*cos(camera->cx);
kdy=-kdx*sin(camera->cx);
if(dx==0 && dy==0) {/*真上か真下だったら*/
kz=0;
kx=cos(camera->cz);
ky=sin(camera->cz)*(dz>0?-1:1);
} else {/*外積の利用*/
kx=kdx*dz-dy*kdz;
ky=kdz*dx-dz*kdx;
kz=kdx*dy-dx*kdy;
}
printbekutoru("基準(横)",kx,ky,kz);
/*基準と垂直の方向を計算*/
/*sy=-sin(camera->cy);
sz=cos(camera->cy);
sx=sy*sin(camera->cx);
sy=sy*cos(camera->cx);*/
/*ベクトルの外積を使ってみる*/
sx=ky*dz-dy*kz;
sy=kz*dx-dz*kx;
sz=kx*dy-dx*ky;
printbekutoru("基準(縦)",sx,sy,sz);
/*コサインの値を計算*/
mcos=(hx*kx+hy*ky+hz*kz)?
(hx*kx+hy*ky+hz*kz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(kx*kx+ky*ky+kz*kz))/*大きさの積*/
:0;
scos=(hx*sx+hy*sy+hz*sz)?
(hx*sx+hy*sy+hz*sz)/*内積*/
/(sqrt(hx*hx+hy*hy+hz*hz)*sqrt(sx*sx+sy*sy+sz*sz))/*大きさの積*/
:0;
dcos=(x1*dx+y1*dy+z1*dz)?
(x1*dx+y1*dy+z1*dz)/*内積*/
/(sqrt(x1*x1+y1*y1+z1*z1)*sqrt(dx*dx+dy*dy+dz*dz))/*大きさの積*/
:0;
printnum("mcos",mcos);
printnum("scos",scos);
printnum("dcos",dcos);
#ifdef DEBUG
if(dcos<0) {
printstr("エラー");
debugend;
return 0;
}
#else
if(dcos<0)return 0;
#endif
/*サインの値を計算*/
msin=sqrt(1-mcos*mcos)*(scos>=0?1:-1);
printnum("msin",msin);
/*タンジェントの値を計算*/
dtan=sqrt(1/(dcos*dcos)-1);
printnum("dtan",dtan);
/*基準の長さを計算*/
klength=camera->genkai/tan(camera->genkaiangle);
printnum("klength",klength);
/*描画に使う長さを計算*/
dlength=klength*dtan;
printnum("dlength",dlength);
/*実際に描画する座標を計算*/
*ox=camera->centerx+dlength*mcos;
*oy=camera->centery-dlength*msin;
printnum("描画x",*ox);
printnum("描画y",*oy);
printstr("henkan3dzahyou終了");
debugend;
return 1;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
ごめんなさい。
完全に3Dの生の処理を度忘れしていて時間がかかりました。
あと、行列の展開はやろうと思いましたが、やはり死にそうなので勘弁して下さい。
とりあえず、正しく動く例ということで参考にしてもらえばと思います。
変更したところ。
・行列演算にした。
・回転軸がx,yで逆だったので本来の回転軸にした。
・立方体の位置をdraw3dlineで補正している。
完全に3Dの生の処理を度忘れしていて時間がかかりました。
あと、行列の展開はやろうと思いましたが、やはり死にそうなので勘弁して下さい。
とりあえず、正しく動く例ということで参考にしてもらえばと思います。
変更したところ。
・行列演算にした。
・回転軸がx,yで逆だったので本来の回転軸にした。
・立方体の位置をdraw3dlineで補正している。
#include <math.h>
#include "3d.h"
#if 1
#define DEBUG
#endif
#ifdef DEBUG
#include <stdio.h>
FILE* fpdebug=NULL;
void _debuginit(void) {
fpdebug=fopen("debug.txt","a");
}
void _debugend(void) {
fclose(fpdebug);
fpdebug=NULL;
}
void _printstr(const char* str) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s\n",str);
}
void _printbekutoru(const char* exp,double x,double y,double z) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=(%f,%f,%f)\n",exp,x,y,z);
}
void _printnum(const char* exp,double num) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=%f\n",exp,num);
}
#define debuginit _debuginit()
#define debugend _debugend()
#define printstr(s) _printstr(s)
#define printbekutoru(e,x,y,z) _printbekutoru(e,x,y,z)
#define printnum(e,n) _printnum(e,n)
#else
#define debuginit
#define debugend
#define printstr(s)
#define printbekutoru(e,x,y,z)
#define printnum(e,n)
#endif
// マトリクスの設定
void setMatrix( double matrix[][4],
double mat00, double mat01, double mat02, double mat03,
double mat10, double mat11, double mat12, double mat13,
double mat20, double mat21, double mat22, double mat23,
double mat30, double mat31, double mat32, double mat33 )
{
matrix[0][0]=mat00; matrix[0][1]=mat01; matrix[0][2]=mat02; matrix[0][3]=mat03;
matrix[1][0]=mat10; matrix[1][1]=mat11; matrix[1][2]=mat12; matrix[1][3]=mat13;
matrix[2][0]=mat20; matrix[2][1]=mat21; matrix[2][2]=mat22; matrix[2][3]=mat23;
matrix[3][0]=mat30; matrix[3][1]=mat31; matrix[3][2]=mat32; matrix[3][3]=mat33;
}
// マトリックス・ポイント計算
void calcMatrixPoint( double matrix[][4],double out[],double in[])
{
int i,j;
// 行列の演算。
for( i=0 ; i<4; i++ ) {
out[i] = 0;
for( j=0 ; j<4; j++ ) {
out[i] += in[j] * matrix[j][i];
}
}
}
// コピーマトリックス
void copyMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j;
// コピー
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
dstMat[i][j] = srcMat[i][j];
}
}
}
// マトリックス計算
void calcMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j,k;
double matrix[4][4];
// クリア
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
matrix[i][j] = 0;
}
}
// 行列の演算。
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
for( k=0 ; k<4; k++ ) {
matrix[i][j] += dstMat[i][k] * srcMat[k][j];
}
}
}
// コピー
copyMatrix(dstMat,matrix);
}
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera)
{
double Mmatrix[4][4];//移動変換行列
double Pmatrix[4][4];//射影変換行列
double point3D[4]; //変換前座標
double Mpoint3D[4]; //移動変換後座標
double Ppoint3D[4]; //射影変換後座標
int i,j;
// 3D座標値を設定する。
point3D[0] = x;
point3D[1] = y;
point3D[2] = z;
point3D[3] = 1;
// カメラビュー変換。
{
double Umatrix[4][4];//単位行列
double RXmatrix[4][4];//X回転行列
double RYmatrix[4][4];//Y回転行列
double RZmatrix[4][4];//Z回転行列
// 単位マトリックス
setMatrix( Umatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// X回転マトリックス
setMatrix( RXmatrix,
1, 0, 0, 0,
0, cos(camera->cx), sin(camera->cx), 0,
0, -sin(camera->cx), cos(camera->cx), 0,
0, 0, 0, 1 );
// Y回転マトリックス
setMatrix( RYmatrix,
cos(camera->cy),0, -sin(camera->cy), 0,
0, 1, 0, 0,
sin(camera->cy),0, cos(camera->cy), 0,
0, 0, 0, 1 );
// Z回転マトリックス
setMatrix( RZmatrix,
cos(camera->cz),sin(camera->cz), 0, 0,
-sin(camera->cz),cos(camera->cz), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// 平行移動マトリックス
setMatrix( Mmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
camera->x, camera->y, camera->z, 1 );
// マトリックスの合成
calcMatrix(Umatrix,RXmatrix);
calcMatrix(Umatrix,RYmatrix);
calcMatrix(Umatrix,RZmatrix);
calcMatrix(Umatrix,Mmatrix);
copyMatrix(Mmatrix,Umatrix);
}
// 行列の演算。
calcMatrixPoint(Mmatrix,Mpoint3D,point3D);
// 射影変換行列を設定する。
{
double depth,ctan;
double cnear,cfar,width,height;
cnear = 0.1;
cfar = 1000.0;
ctan = tan(camera->genkaiangle*0.5);
width = 1.0 / ctan;
height = 1.0 / ctan;
depth = cfar / (cfar - cnear);
setMatrix( Pmatrix,
width, 0, 0, 0,
0, height, 0, 0,
0, 0, depth, 1,
0, 0, -depth * cnear, 0 );
}
// 行列の演算。
calcMatrixPoint(Pmatrix,Ppoint3D,Mpoint3D);
// スクリーン座標変換。アスペクトは1:1
*ox = camera->centery * Ppoint3D[0] / Ppoint3D[2] + camera->centerx;
*oy = camera->centery * Ppoint3D[1] / Ppoint3D[2] + camera->centery;
return 1;
}
int draw3dline(HDC hdc,double x1,double y1,double z1,
double x2,double y2,double z2,const camera_t* camera,char *info) {
double hx1,hy1,hx2,hy2;
y1 -= 300;
y2 -= 300;
z1 += 200;
z2 += 200;
if(!henkan3dzahyou(&hx1,&hy1,x1,y1,z1,camera))return 0;
if(!henkan3dzahyou(&hx2,&hy2,x2,y2,z2,camera))return 0;
if(!MoveToEx(hdc,(int)hx1,(int)hy1,NULL))return 0;
if(!LineTo(hdc,(int)hx2,(int)hy2))return 0;
if( info != NULL ) {
wsprintf(info,"ライン座標(%d,%d)-(%d,%d)",(int)hx1,(int)hy1,(int)hx2,(int)hy2);
}
return 1;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
使ってみたのですが、いくつか気になる点があります。
・カメラの座標が他の描画の座標と逆(x,y,z全て)な気がします。
・立方体の中に入った時に目茶苦茶な線が描画されます。(添付のスクリーンショット参照)
HSPのEasy3Dのヘルプでは
少なくともソースを見た限りでは、henkan3dzahyou関数は0を返さない(エラーを返さない)ように見えます。
少しソースを書き変えたのですが、そこがまずかったですか?
・カメラの座標が他の描画の座標と逆(x,y,z全て)な気がします。
・立方体の中に入った時に目茶苦茶な線が描画されます。(添付のスクリーンショット参照)
HSPのEasy3Dのヘルプでは
となるのですが、このエラーは起きないのですか?システム変数 stat が 0 の場合、位置がカメラの後ろとなるため座標変換できなかったことを表します。
少なくともソースを見た限りでは、henkan3dzahyou関数は0を返さない(エラーを返さない)ように見えます。
少しソースを書き変えたのですが、そこがまずかったですか?
- 添付ファイル
-
- スクリーンショットです。
- 3dmechakucha.jpg (38.49 KiB) 閲覧数: 12173 回
-
- 3dtest_2.zip
- プログラムです。
- (18.04 KiB) ダウンロード数: 215 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
[修正]回転も直しました。みけCAT さんが書きました:使ってみたのですが、いくつか気になる点があります。
・カメラの座標が他の描画の座標と逆(x,y,z全て)な気がします。
・立方体の中に入った時に目茶苦茶な線が描画されます。(添付のスクリーンショット参照)
HSPのEasy3Dのヘルプではとなるのですが、このエラーは起きないのですか?システム変数 stat が 0 の場合、位置がカメラの後ろとなるため座標変換できなかったことを表します。
少なくともソースを見た限りでは、henkan3dzahyou関数は0を返さない(エラーを返さない)ように見えます。
少しソースを書き変えたのですが、そこがまずかったですか?
カメラが内部に入るときに戻り値処理が抜けていたので追加しました。
#include <math.h>
#include "3d.h"
#if 1
#define DEBUG
#endif
#ifdef DEBUG
#include <stdio.h>
FILE* fpdebug=NULL;
void _debuginit(void) {
fpdebug=fopen("debug.txt","a");
}
void _debugend(void) {
fclose(fpdebug);
fpdebug=NULL;
}
void _printstr(const char* str) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s\n",str);
}
void _printbekutoru(const char* exp,double x,double y,double z) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=(%f,%f,%f)\n",exp,x,y,z);
}
void _printnum(const char* exp,double num) {
if(fpdebug==NULL)return;
fprintf(fpdebug,"%s=%f\n",exp,num);
}
#define debuginit _debuginit()
#define debugend _debugend()
#define printstr(s) _printstr(s)
#define printbekutoru(e,x,y,z) _printbekutoru(e,x,y,z)
#define printnum(e,n) _printnum(e,n)
#else
#define debuginit
#define debugend
#define printstr(s)
#define printbekutoru(e,x,y,z)
#define printnum(e,n)
#endif
// マトリクスの設定
void setMatrix( double matrix[][4],
double mat00, double mat01, double mat02, double mat03,
double mat10, double mat11, double mat12, double mat13,
double mat20, double mat21, double mat22, double mat23,
double mat30, double mat31, double mat32, double mat33 )
{
matrix[0][0]=mat00; matrix[0][1]=mat01; matrix[0][2]=mat02; matrix[0][3]=mat03;
matrix[1][0]=mat10; matrix[1][1]=mat11; matrix[1][2]=mat12; matrix[1][3]=mat13;
matrix[2][0]=mat20; matrix[2][1]=mat21; matrix[2][2]=mat22; matrix[2][3]=mat23;
matrix[3][0]=mat30; matrix[3][1]=mat31; matrix[3][2]=mat32; matrix[3][3]=mat33;
}
// マトリックス・ポイント計算
void calcMatrixPoint( double matrix[][4],double out[],double in[])
{
int i,j;
// 行列の演算。
for( i=0 ; i<4; i++ ) {
out[i] = 0;
for( j=0 ; j<4; j++ ) {
out[i] += in[j] * matrix[j][i];
}
}
}
// コピーマトリックス
void copyMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j;
// コピー
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
dstMat[i][j] = srcMat[i][j];
}
}
}
// マトリックス計算
void calcMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j,k;
double matrix[4][4];
// クリア
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
matrix[i][j] = 0;
}
}
// 行列の演算。
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
for( k=0 ; k<4; k++ ) {
matrix[i][j] += dstMat[i][k] * srcMat[k][j];
}
}
}
// コピー
copyMatrix(dstMat,matrix);
}
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera)
{
double Mmatrix[4][4];//移動変換行列
double Pmatrix[4][4];//射影変換行列
double point3D[4]; //変換前座標
double Mpoint3D[4]; //移動変換後座標
double Ppoint3D[4]; //射影変換後座標
int i,j;
// 3D座標値を設定する。
point3D[0] = x;
point3D[1] = y;
point3D[2] = z;
point3D[3] = 1;
// カメラビュー変換。
{
double RXmatrix[4][4];//X回転行列
double RYmatrix[4][4];//Y回転行列
double RZmatrix[4][4];//Z回転行列
double MVmatrix[4][4];//平行移動行列
double rot;
// 単位マトリックスを設定
setMatrix( Mmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// X回転マトリックス
rot = -camera->cx;
setMatrix( RXmatrix,
1, 0, 0, 0,
0, cos(rot), sin(rot), 0,
0, -sin(rot), cos(rot), 0,
0, 0, 0, 1 );
// Y回転マトリックス
rot = -camera->cy;
setMatrix( RYmatrix,
cos(rot), 0, -sin(rot), 0,
0, 1, 0, 0,
sin(rot), 0, cos(rot), 0,
0, 0, 0, 1 );
// Z回転マトリックス
rot = -camera->cz;
setMatrix( RZmatrix,
cos(rot), sin(rot), 0, 0,
-sin(rot), cos(rot), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// 平行移動マトリックス
setMatrix( MVmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
-camera->x, camera->y, -camera->z, 1 );
// マトリックスの合成
calcMatrix(Mmatrix,RXmatrix);
calcMatrix(Mmatrix,RYmatrix);
calcMatrix(Mmatrix,RZmatrix);
calcMatrix(Mmatrix,MVmatrix);
}
// 行列の演算。
calcMatrixPoint(Mmatrix,Mpoint3D,point3D);
// 射影変換行列を設定する。
{
double depth,ctan;
double cnear,cfar,width,height;
cnear = 0.1;
cfar = 1000.0;
ctan = tan(camera->genkaiangle*0.5);
width = 1.0 / ctan;
height = 1.0 / ctan;
depth = cfar / (cfar - cnear);
setMatrix( Pmatrix,
width, 0, 0, 0,
0, height, 0, 0,
0, 0, depth, 1,
0, 0, -depth * cnear, 0 );
}
// 行列の演算。
calcMatrixPoint(Pmatrix,Ppoint3D,Mpoint3D);
// 投影できないかチェック
if( Ppoint3D[2] < 0 ) {
return 0;
}
// スクリーン座標変換。アスペクトは1:1
*ox = camera->centery * Ppoint3D[0] / Ppoint3D[2] + camera->centerx;
*oy = camera->centery * Ppoint3D[1] / Ppoint3D[2] + camera->centery;
return 1;
}
int draw3dline(HDC hdc,double x1,double y1,double z1,
double x2,double y2,double z2,const camera_t* camera,char *info) {
double hx1,hy1,hx2,hy2;
y1 -= 300;
y2 -= 300;
z1 += 200;
z2 += 200;
if(!henkan3dzahyou(&hx1,&hy1,x1,y1,z1,camera))return 0;
if(!henkan3dzahyou(&hx2,&hy2,x2,y2,z2,camera))return 0;
if(!MoveToEx(hdc,(int)hx1,(int)hy1,NULL))return 0;
if(!LineTo(hdc,(int)hx2,(int)hy2))return 0;
if( info != NULL ) {
wsprintf(info,"ライン座標(%d,%d)-(%d,%d)",(int)hx1,(int)hy1,(int)hx2,(int)hy2);
}
return 1;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
とりあえず変な線が出る問題は直りました。
それからもう一点、現在のプログラムでは、カメラを回転させたときに、
カメラが首を振るというよりもむしろ(0,0,0)を中心として描画する位置が回転するようになっているように思われます。
よろしくお願いします。
[hr]
添付したサンプルについて
従来のサンプルに比べ、立方体に色がついた点が変わっています。
座標軸も表示しています。
また、3Dグラフの表示のサンプルに切り替えることもできます。
キーボードの2キー(テンキーではない)を押してください。
1を押すと直方体の表示に戻ります。
[hr]
自分のデバッグ用のコードは使われていないようなので、はずしていただけませんか?
描画コードの方を修正したので、draw3dline内での補正は不要です。
それからもう一点、現在のプログラムでは、カメラを回転させたときに、
カメラが首を振るというよりもむしろ(0,0,0)を中心として描画する位置が回転するようになっているように思われます。
よろしくお願いします。
[hr]
添付したサンプルについて
従来のサンプルに比べ、立方体に色がついた点が変わっています。
座標軸も表示しています。
また、3Dグラフの表示のサンプルに切り替えることもできます。
キーボードの2キー(テンキーではない)を押してください。
1を押すと直方体の表示に戻ります。
[hr]
自分のデバッグ用のコードは使われていないようなので、はずしていただけませんか?
描画コードの方を修正したので、draw3dline内での補正は不要です。
- 添付ファイル
-
- 3dtest_2(2).zip
- プログラムです。
- (20.49 KiB) ダウンロード数: 196 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 3Dの描画
とりあえず対症療法的に書き換えてみたのですが、あっているでしょうか?
- 添付ファイル
-
- 3dtest_2(3).zip
- プログラムです。
- (20.56 KiB) ダウンロード数: 202 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 3Dの描画
x方向とz方向のカメラの移動は直っていますが、y方向は直っていないように思います。softya(ソフト屋) さんが書きました:[修正]回転も直しました。
肝心の回転も直っていないように思います。
描画されている(0,0,0)の位置が回転しても変わりません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
新しいコードを元に直しました。みけCAT さんが書きました:とりあえず変な線が出る問題は直りました。
それからもう一点、現在のプログラムでは、カメラを回転させたときに、
カメラが首を振るというよりもむしろ(0,0,0)を中心として描画する位置が回転するようになっているように思われます。
よろしくお願いします。
[hr]
添付したサンプルについて
従来のサンプルに比べ、立方体に色がついた点が変わっています。
座標軸も表示しています。
また、3Dグラフの表示のサンプルに切り替えることもできます。
キーボードの2キー(テンキーではない)を押してください。
1を押すと直方体の表示に戻ります。
[hr]
自分のデバッグ用のコードは使われていないようなので、はずしていただけませんか?
たしかに立方体のローカル系で回転してましたので修正しました(行列のかけ合わせの順番の問題でした)
#include <math.h>
#include "3d.h"
// マトリクスの設定
static void setMatrix( double matrix[][4],
double mat00, double mat01, double mat02, double mat03,
double mat10, double mat11, double mat12, double mat13,
double mat20, double mat21, double mat22, double mat23,
double mat30, double mat31, double mat32, double mat33 )
{
matrix[0][0]=mat00; matrix[0][1]=mat01; matrix[0][2]=mat02; matrix[0][3]=mat03;
matrix[1][0]=mat10; matrix[1][1]=mat11; matrix[1][2]=mat12; matrix[1][3]=mat13;
matrix[2][0]=mat20; matrix[2][1]=mat21; matrix[2][2]=mat22; matrix[2][3]=mat23;
matrix[3][0]=mat30; matrix[3][1]=mat31; matrix[3][2]=mat32; matrix[3][3]=mat33;
}
// マトリックス・ポイント計算
static void calcMatrixPoint( double matrix[][4],double out[],double in[])
{
int i,j;
// 行列の演算。
for( i=0 ; i<4; i++ ) {
out[i] = 0;
for( j=0 ; j<4; j++ ) {
out[i] += in[j] * matrix[j][i];
}
}
}
// コピーマトリックス
static void copyMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j;
// コピー
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
dstMat[i][j] = srcMat[i][j];
}
}
}
// マトリックス計算
static void calcMatrix( double dstMat[][4],double srcMat[][4])
{
int i,j,k;
double matrix[4][4];
// クリア
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
matrix[i][j] = 0;
}
}
// 行列の演算。
for( i=0 ; i<4; i++ ) {
for( j=0 ; j<4; j++ ) {
for( k=0 ; k<4; k++ ) {
matrix[i][j] += dstMat[i][k] * srcMat[k][j];
}
}
}
// コピー
copyMatrix(dstMat,matrix);
}
int henkan3dzahyou(double* ox,double* oy,
double x,double y,double z,const camera_t* camera)
{
double Mmatrix[4][4];//移動変換行列
double Pmatrix[4][4];//射影変換行列
double point3D[4]; //変換前座標
double Mpoint3D[4]; //移動変換後座標
double Ppoint3D[4]; //射影変換後座標
int i,j;
// 3D座標値を設定する。
point3D[0] = x;
point3D[1] = y;
point3D[2] = z;
point3D[3] = 1;
// カメラビュー変換。
{
double RXmatrix[4][4];//X回転行列
double RYmatrix[4][4];//Y回転行列
double RZmatrix[4][4];//Z回転行列
double MVmatrix[4][4];//平行移動行列
double rot;
// 単位マトリックスを設定
setMatrix( Mmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// X回転マトリックス
rot = -camera->cx;
setMatrix( RXmatrix,
1, 0, 0, 0,
0, cos(rot), sin(rot), 0,
0, -sin(rot), cos(rot), 0,
0, 0, 0, 1 );
// Y回転マトリックス
rot = -camera->cy;
setMatrix( RYmatrix,
cos(rot), 0, -sin(rot), 0,
0, 1, 0, 0,
sin(rot), 0, cos(rot), 0,
0, 0, 0, 1 );
// Z回転マトリックス
rot = -camera->cz;
setMatrix( RZmatrix,
cos(rot), sin(rot), 0, 0,
-sin(rot), cos(rot), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 );
// 平行移動マトリックス
setMatrix( MVmatrix,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
-camera->x, -camera->y, -camera->z, 1 );
// マトリックスの合成
calcMatrix(Mmatrix,MVmatrix);
calcMatrix(Mmatrix,RXmatrix);
calcMatrix(Mmatrix,RYmatrix);
calcMatrix(Mmatrix,RZmatrix);
}
// 行列の演算。
calcMatrixPoint(Mmatrix,Mpoint3D,point3D);
// 射影変換行列を設定する。
{
double depth,ctan;
double cnear,cfar,width,height;
cnear = 0.1;
cfar = 1000.0;
ctan = tan(camera->genkaiangle*0.5);
width = 1.0 / ctan;
height = 1.0 / ctan;
depth = cfar / (cfar - cnear);
setMatrix( Pmatrix,
width, 0, 0, 0,
0, height, 0, 0,
0, 0, depth, 1,
0, 0, -depth * cnear, 0 );
}
// 行列の演算。
calcMatrixPoint(Pmatrix,Ppoint3D,Mpoint3D);
// 投影できないかチェック
if( Ppoint3D[2] < 0 ) {
return 0;
}
// スクリーン座標変換。アスペクトは1:1
*ox = camera->centery * Ppoint3D[0] / Ppoint3D[2] + camera->centerx;
*oy = camera->centery * Ppoint3D[1] / Ppoint3D[2] + camera->centery;
return 1;
}
#ifdef ENABLE_INFO
int draw3dline(HDC hdc,double sx,double sy,double sz,
double dx,double dy,double dz,const camera_t* camera,char *info) {
#else
int draw3dline(HDC hdc,double sx,double sy,double sz,
double dx,double dy,double dz,const camera_t* camera) {
#endif
double hx1,hy1,hx2,hy2;
if(!henkan3dzahyou(&hx1,&hy1,sx,sy,sz,camera))return 0;
if(!henkan3dzahyou(&hx2,&hy2,dx,dy,dz,camera))return 0;
if(!MoveToEx(hdc,(int)hx1,(int)hy1,NULL))return 0;
if(!LineTo(hdc,(int)hx2,(int)hy2))return 0;
#ifdef ENABLE_INFO
if( info != NULL ) {
wsprintf(info,"ライン座標(%d,%d)-(%d,%d)",(int)hx1,(int)hy1,(int)hx2,(int)hy2);
}
#endif
return 1;
}
int draw3dtext(HDC hdc,double x,double y,double z,
const char* text,const camera_t* camera) {
double hx,hy;
if(!henkan3dzahyou(&hx,&hy,x,y,z,camera))return 0;
if(!TextOut(hdc,(int)hx,(int)hy,text,lstrlen(text)))return 0;
return 1;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
うまく動きました。ありがとうございます。
ところで、このプログラムを自分のソフトに組み込む(ソース添付あり/なし)ときは、
ライセンス表記などは必要でしょうか?
必要なら、どのようにすればいいでしょうか?
[hr]
3Dグラフの種類が増えました。
1~4番まで使えます。
5~9と0番は何も描画されません。
ところで、このプログラムを自分のソフトに組み込む(ソース添付あり/なし)ときは、
ライセンス表記などは必要でしょうか?
必要なら、どのようにすればいいでしょうか?
[hr]
3Dグラフの種類が増えました。
1~4番まで使えます。
5~9と0番は何も描画されません。
- 添付ファイル
-
- 3dtest_2(4).zip
- プログラムです。
- (20.99 KiB) ダウンロード数: 210 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
別に表記してもらう必要はありませんよ。自由にお使いください。
ただ、線分クリッピングとかしていないので、色々やると支障が出るかも知れません。
行列は、まだ習われていないかも知れませんが、この機会に勉強されてはどうでしょか?
とりあえず使い方だけってのもありです。
参考。
「高校数学の基本問題」
http://www.geisya.or.jp/~mwm48961/koukou/index_m.htm
「3D座標変換 - ゲームプログラミングWiki」
http://www.c3.club.kyutech.ac.jp/gamewi ... A%D1%B4%B9
ただ、線分クリッピングとかしていないので、色々やると支障が出るかも知れません。
行列は、まだ習われていないかも知れませんが、この機会に勉強されてはどうでしょか?
とりあえず使い方だけってのもありです。
参考。
「高校数学の基本問題」
http://www.geisya.or.jp/~mwm48961/koukou/index_m.htm
「3D座標変換 - ゲームプログラミングWiki」
http://www.c3.club.kyutech.ac.jp/gamewi ... A%D1%B4%B9
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
ありがとうございます。
解決にさせていただきます。
[hr]
「サンプルを共有するコミュニティ」http://dixq.net/forum/viewforum.php?f=83
の方に転載させていただいてもいいですか?
もしくは自分で投稿していただけるとありがたいですが。
解決にさせていただきます。
[hr]
「サンプルを共有するコミュニティ」http://dixq.net/forum/viewforum.php?f=83
の方に転載させていただいてもいいですか?
もしくは自分で投稿していただけるとありがたいですが。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: 3Dの描画
転記の方はお願いしてよろしいでしょうか。みけCAT さんが書きました:ありがとうございます。
解決にさせていただきます。
[hr]
「サンプルを共有するコミュニティ」http://dixq.net/forum/viewforum.php?f=83
の方に転載させていただいてもいいですか?
もしくは自分で投稿していただけるとありがたいですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 3Dの描画
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)