質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2445閲覧

座標系を変換したい。

oldstance

総合スコア11

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/05/18 04:52

お世話になっております。

座標系の変換についてお聞きしたいことがあり投函させて頂きました。
現座標系は、カメラから見て

  • +X:前方
  • +Y:右方向
  • +Z:上方向

となっており、地面相当の平面がXY平面、高さがZになっています。
これを、OpenGLの座標系である右手座標系にしたいのですが、単純に、例えば位置設定関数の場合ですと、

c++

1const float sz = 20.0f; 2for( int i = 0; i < MAX_PLANES; ++i ) 3{ 4 Object *obj = getObject(i); 5 //obj->setPosition( (float)i * 10, sz * 10.0f, 0.0f ); // 現座標系での指定 6 obj->setPosition( (float)i * 10.0f, 0.0f, sz * 10.0f ); // 右手座標系(こう記述したい) 7}

といった感じで強引に設定を変更しても、当然ですが思った通りの表示結果が得られません(この場合、高さ方向にオブジェクトが配置されます)。

あとは、Projectionマトリクス、Viewマトリクスの設定はどうするのかとか、LookAt関数的なのはどうしたら良いのか、何か見落としているのか、系の変更について現状を把握できていない状態です(ortho関数で水平、もしくは垂直の値を入れ替えれば良いと聞きましたが、これはちょっと違う気がします)。

座標系の変換において気をつけるべき部分等ございましたらご教授願います。
開発環境ですが、SDL2/OpenGL/C++を使用しています。OSは特に問いませんが、Windows上のVisualStudioを利用して開発を行っております。シェーダーは#330を利用しています(特に特殊なことはやっておりません)。
よく使うVector3的なのはクラスとして独自で用意しております。

かなりざっくりとした質問になってしまいましたが、返答の際に足りない情報がありましたら可能な限り対応致します。

以上、よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

お返事遅れました。
あれから試行錯誤を繰り返し、小手先の変換だけでは無理が生じるので、最初から使用したい系で動くように書き換えました。

ありがとうございました。

投稿2020/06/05 02:50

oldstance

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/06/05 02:57

> 最初から使用したい系で動くように書き換え 実際,これを行うことが可能である場合においては,これこそが上策であると思います.
guest

0

前とか右とかいうのはカメラ配置(と言うのか?)次第の話でしょうから
Viewマトリクスを然るべく与えれば良いかと思います.

右手系と左手系の間の変換に関しては,Modelマトリクスとして,例えば

//3*3で書きますが 1 0 0 0 1 0 0 0 -1

みたいなのをかけて,いずれかの軸を反転してやればどうでしょうか.
(「右ねじ~」とかで法線を決めてたりすると,そこらへんが逆になっちゃうかな?)

投稿2020/05/18 06:17

編集2020/05/18 06:19
fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/05/18 06:31

「最終結果 = 行列 * 行列 * 行列 * ... * モデル座標系での座標」 ということをしているときに,どこの段階でどういう世界になっていてほしいか(都合が良いか)次第で,どこで何の変換をやると良いかが変わる話かと思うので, この回答通りでなくても良い.
oldstance

2020/05/18 07:16

なるほど、座標系変換行列(?)を掛けて系を変更するのですね。今のソースコードにそれを導入できるかわかりませんが、やってみます。
fana

2020/05/18 08:10

ざっくり言って(?),「行列を掛ける=座標変換」ですからね. 例えば,「平行移動後座標 = 平行移動させる行列 * 座標」なら,これは「原点位置が異なる座標系への変換」. > 「最終結果 = 行列 * 行列 * 行列 * ... * モデル座標系での座標」 を, 「最終結果 = 行列3 * (行列2 * (行列1 * モデル座標系での座標))」 とか書いた時に, ・行列1による変換結果(一番内側の括弧内)というのはどういう世界(座標系)なのか ・行列2による変換結果(2重の括弧内)というのはどういう世界(座標系)なのか ・... という決め事をして,その世界になるように行列1とか行列2を用意して掛ける(あれはそれ相当の計算を行う)という話ですね.
oldstance

2020/05/19 01:26

おはようございます。 お教え頂いた変換行列の手法ですが、軸の方向は変換できても、軸の向きは変換できないのでは?と思いました(例えば、X軸とZ軸の入れ替え)。 現在は、XY平面高さZとして処理を行っている部分を洗い出しています(不毛かもしれませんが…)。
fana

2020/05/19 01:42

話が解りやすいように ある座標系の軸を{X軸,Y軸,Z軸}, 別の座標系の軸を{U軸,V軸,W軸}として,明示的に別の名前で呼ぶとしましょう. この2つの座標系の間の変換というのは, 「XYZ座標系の値で書かれた座標(X,Y,Z) を,UVW座標系の値で書いたらどうなるか?」(またはその逆)という計算です. > 例えば、X軸とZ軸の入れ替え を例にすれば,2つの座標系の軸方向の関係性が{U=Z, V=Y, W=X} という話かと思います. それを表す変換行列は, [0 0 1] [0 1 0] [1 0 0] とかになりませんか.
oldstance

2020/05/19 02:20

fana様、素早いコメントと丁寧な解説ありがとうございます。 私の頭では、軸変換行列を算出することはできませんでした。 が、この現座標系(XY平面/Zup)はBlenderが採用している座標系なのですね。知りませんでした。 よって、私がやりたいことは、Blenderの座標系である(XY平面/Zup)を、OpenGLの標準的な座標系(XZ平面/Yup)に変換する方法という感じで多少はスッキリしました。 > それを表す変換行列は, > [0 0 1] > [0 1 0] > [1 0 0] > とかになりませんか. これがよくわかりませんでした。飲み込みが悪くて大変申し訳無いです。 以上、よろしくお願い致します。
fana

2020/05/19 02:25

> これがよくわかりませんでした (U,V,W)^t = 前記の行列 * (X,Y,Z)^t ※ここで^tは転置の意 を計算すれば,その結果は{U=Z, V=Y, W=X}ですよね.
oldstance

2020/05/19 02:51

なるほど、転置なのですね。 もう少しコードを追ってみます。
fana

2020/05/19 03:16

> なるほど、転置なのですね。 (ちょっと応答として怪しい気が…??) > ※ここで^tは転置の意 ってのは,ここのコメント欄で縦ベクトルを [U] [V] [W] みたく書くのは{大変,面倒,式書くと表示がずれそうだし…}だから,かわりに (U,V,W)^t って書いたよー,ってだけですよ.
oldstance

2020/05/19 04:55

そういう意味だったのですね。勘違い失礼しました。 おこがましいお願いなのですが、コードもしくは変換行列を示していただくことは可能でしょうか? 自分の頭がついていけず、まず答えを知ってから過程を追いかけたいのです。
fana

2020/05/19 05:42

うーん,OpenGLでシェーダ使うのはちょっと触れた程度の経験しかないので,具体コードをぱっと書くのは無理ですが… 頂点シェーダへの入力を「Blenderの座標系」での頂点座標とするならば, 頂点シェーダで  出力 = Projection * View * Model * X * 入力 という処理を行うと考えてはどうでしょうか. ここで,Modelは「OpenGLの標準的な座標系」の上で考えたModelマトリクスなのだとして, 行列Xが「Blenderの座標系」から「OpenGLの標準的な座標系」へと変換する行列なのだとしましょう. このとき,Xの中身は,例えば [0 1 0 0] [0 0 1 0] [-1 0 0 0] [0 0 0 1] とかにしたら,何となくやりたいことになりませんか? 実際の実装においては,いくつかの行列をあらかじめ掛けた結果をシェーダで使う(:例えば ModelとXを掛けた結果をModelとして扱うとかする)だろうけど.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問