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

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

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

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

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

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

Q&A

解決済

1回答

2478閲覧

opengl カメラの視点を等速で移動させる方法が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

OpenGL

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

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

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

0グッド

0クリップ

投稿2021/10/25 09:00

編集2021/10/25 10:25

提示コードのコメント部内部のコードですが提示画像のようにカメラの視点を回転させているのですが最初は早くて回転し続けるたびに少しずつ回転が遅くなるのですがこれはなぜでしょうか?

試したこと

x,y, をx = 10; としたところその場にカメラの視点が回転します。
camera.cppのコメント部を確認しました、がなぜ段々遅くなるのかわかりません。

イメージ説明

Camera.cpp
#include "../header/Camera.hpp" #include <glm/glm.hpp> #include <glm/gtx/transform.hpp> #include <glm/gtc/matrix_transform.hpp> #include "../header/Window.hpp" #include "../header/Init.hpp" std::shared_ptr<std::vector<FrameWork::D2::VertexAttribute>> FrameWork::Camera::vertex = std::make_shared<std::vector<FrameWork::D2::VertexAttribute>>(0); //頂点配列 glm::mat4 FrameWork::Camera::scale = glm::mat4(); //拡大縮小 glm::mat4 FrameWork::Camera::rotate = glm::mat4(); //回転 glm::mat4 FrameWork::Camera::translate = glm::mat4(); //平行移動 //描画行列 glm::vec3 FrameWork::Camera::position = glm::vec3(0,0,0); //座標 glm::vec3 FrameWork::Camera::vecLook = glm::vec3(0,0,-1); //向き(視線) glm::mat4 FrameWork::Camera::view = glm::lookAt(glm::vec3(position.x, position.y, position.z), vecLook, glm::vec3(0, 1, 0)); //ビュー行列 glm::mat4 FrameWork::Camera::projection = glm::perspective(glm::radians(90.0f), 4.0f / 3.0f, 0.1f, 10000.0f); //透視射形行列 // ##################################### 初期化 ##################################### void FrameWork::Camera::Init() { vertex->resize(6); //頂点配列を初期化 } // ##################################### 頂点属性を取得 ##################################### std::shared_ptr<std::vector<FrameWork::D2::VertexAttribute>> FrameWork::Camera::getVertexAttribute() { return vertex; } // ##################################### 座標を設定 ##################################### void FrameWork::Camera::setPosition(glm::vec3 p) { position = p; //座標 } /////////////////////////////////////////////////////////////////////////////////////////////////// // ##################################### 視線を設定 ##################################### void FrameWork::Camera::setLook(glm::vec3 l) { vecLook = l; //向き view = glm::lookAt(glm::vec3(position.x, position.y, position.z), vecLook, glm::vec3(0, 1, 0)); } ////////////////////////////////////////////////////////////////////////////////////////////////// // ##################################### 座標を取得 ##################################### glm::vec3 FrameWork::Camera::getPosition() { return position; } // ##################################### 視線を取得 ##################################### glm::vec3 FrameWork::Camera::getLook() { return vecLook; } // ##################################### 3D ビュー行列を取得 透視射形行列 ##################################### glm::mat4 FrameWork::Camera::getViewProjection() { return projection * view; } // ##################################### 2D ビュー行列を取得 正射形 ##################################### glm::mat4 FrameWork::Camera::getProjection_2D() { return glm::ortho(0.0f, FrameWork::windowContext->getSize().x, FrameWork::windowContext->getSize().y, 0.0f, -1.0f, 1.0f); } // ###################### デストラクタ ###################### FrameWork::Camera::~Camera() { }
Main.cpp
#include "../header/FrameWork.hpp" #include "../header/Resource.hpp" #include <iostream> #include "../header/Camera.hpp" int main() { FrameWork::Init(glm::ivec2(800, 600), glm::ivec2(4,2), "FrameWork"); // 初期化 FrameWork::Camera::Init(); //カメラ初期化 FrameWork::ObjFile cubeFile; FrameWork::D3::LoadObj("Model/Cube.obj",cubeFile); FrameWork::D3::Object cube(cubeFile); FrameWork::ObjFile groundFile; FrameWork::D3::LoadObj("Model/ground.obj",groundFile); FrameWork::D3::Object ground(groundFile); float y = 0; float x = 0; float angleY = 0; float angleX = 0; float vecSpeed = 10; while (*FrameWork::windowContext) { FrameWork::windowContext->FrameUpdate(glm::vec4(0,0,0,255)); if(FrameWork::windowContext->getKeyInput(GLFW_KEY_LEFT) > (short)0) { x += vecSpeed; // printf("left\n"); // printf("%f , %f \n",x,y); } else if(FrameWork::windowContext->getKeyInput(GLFW_KEY_RIGHT) > (short)0) { x += -vecSpeed; // printf("right\n"); // printf("%f , %f \n",x,y); } if(FrameWork::windowContext->getKeyInput(GLFW_KEY_UP) > (short)0) { y += vecSpeed; // printf("up\n"); // printf("%f , %f \n",x,y); } else if(FrameWork::windowContext->getKeyInput(GLFW_KEY_DOWN) > (short)0) { y += -vecSpeed; // printf("down\n"); // printf("%f , %f \n",x,y); } if(FrameWork::windowContext->getKeyInput(GLFW_KEY_A) > (short)0) { angleY = 0.001; cube.setRotate(glm::vec3(0,1,0),angleY); } else if(FrameWork::windowContext->getKeyInput(GLFW_KEY_D) > (short)0) { angleY = -0.001; cube.setRotate(glm::vec3(0,1,0),angleY); } else if(FrameWork::windowContext->getKeyInput(GLFW_KEY_W) > (short)0) { angleY = 0.001; cube.setRotate(glm::vec3(1,0,0),angleY); } else if(FrameWork::windowContext->getKeyInput(GLFW_KEY_S) > (short)0) { angleY = -0.001; cube.setRotate(glm::vec3(1,0,0),angleY); } ////////////////////////////////////////////////////////////////////////// FrameWork::Camera::setLook(glm::vec3(x,y,-1)); FrameWork::Camera::setPosition(glm::vec3(0,0,200.0f)); ////////////////////////////////////////////////////////////////////////// //Cube cube.shader->setEnable(); cube.setPosition(glm::vec3(0,10,0)); cube.setScale(glm::vec3(30,30,30)); cube.shader->setUniform4f("uFragment",FrameWork::GetGlColor(glm::vec4(0,0,100,255))); //cube.shader->setUniform3f("objectColor", glm::vec3(1.0f, 0.5f, 0.31f)); //cube.shader->setUniform3f("lightColor", glm::vec3(1.0f, 1.0f, 1.0f)); //cube.shader->setUniform3f("lightPos", glm::vec3(0,0,10.0f)); //cube.shader->setUniform3f("viewPos",FrameWork::Camera::getPosition()); cube.Renderer(); cube.shader->setDisable(); //Ground ground.shader->setEnable(); ground.setPosition(glm::vec3(0,-50,-5)); ground.setScale(glm::vec3(20,20,20)); //ground.shader->setUniform3f("objectColor", glm::vec3(1.0f, 0.5f, 0.31f)); //ground.shader->setUniform3f("lightColor", glm::vec3(1.0f, 1.0f, 1.0f)); //ground.shader->setUniform3f("lightPos", glm::vec3(0,0,10)); //ground.shader->setUniform3f("viewPos", FrameWork::Camera::getPosition()); ground.shader->setUniform4f("uFragment",FrameWork::GetGlColor(glm::vec4(0,100,0,255))); ground.Renderer(); ground.shader->setDisable(); FrameWork::windowContext->Wait(); FrameWork::windowContext->SwapBuffers(); } return 0; }

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

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

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

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

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

m.ts10806

2021/10/25 10:03

自分で書いたコードではないのなら出典明示を(この指摘は1回や2回じゃないはず) そうでないならせめてきちんとデバッグしてから他人に聞いてください。
guest

回答1

0

ベストアンサー

提示画像のようにカメラの視点を回転させているのですが

まず,その画像を見ても,「視点が回転」しているという話を把握するのは無理でしょう.
(その絵が何を表しているのか?はあなたにしかわからない.)


さて,

視点を回転させている

に相当するコードというのが,コレ:

FrameWork::Camera::setLook(glm::vec3(x,y,-1));

だという話なのでしょうか?
コードを見るに,xy も,何やら キー操作によって増減させている様子ですが…?
キー操作で回転を達成したいのであれば,

  • 「回転」に必要な処理を実装する(所望の回転を達成するには,現実装では何かが足りない可能性もある)
  • 上手く操作する(どんな結果を生じるのかは,あなたのキー操作次第

というだけの話になりますね.


で,ここからは完全にエスパーな回答となりますが,
もしも「いずれかのキーを押し続けるような操作を行っている場合」(すなわち,x が増え続けるとかそういう状況下)の挙動の話をしているのだとしたら,
そもそもその処理は視点を 「回転」させているわけではない ので,いい感じに回転しないとしても当たり前の結果です.
x の値だけをどんどん増やしていくときに,視野がどのように変化していくのか? を考えてみればすぐにわかる話です.

投稿2021/10/26 01:45

fana

総合スコア11634

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

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

fana

2021/10/26 02:03

回答の末尾の話が素直に伝わらん気もするので,前もって補足を書いておく. > FrameWork::Camera::setLook(glm::vec3(x,y,-1)); > FrameWork::Camera::setPosition(glm::vec3(0,0,200.0f)); なる処理に関して, xだけが増えていく話の例を書いておく. 最初,x=0,y=0 であるから,カメラは位置(0,0,200)から座標(0,0,-1)を真正面に見る. ↓ xが増えていくとき… x=10 のとき : カメラは位置(0,0,200)から座標(10, 0, -1)を真正面に見る. x=100 のとき : カメラは位置(0,0,200)から座標(100, 0, -1)を真正面に見る. x=10000 のとき : カメラは位置(0,0,200)から座標(10000, 0, -1)を真正面に見る. … xだけを増やしていくならば,「カメラの真正面の方向」は,ある方向に漸近していく. 「カメラの真正面の方向」の変化速度は「だんだん遅くなる」. 「カメラの真正面の方向」を「回転」させたいならば,ふつーは素直に 座標(x,y,-1) を「回転」させるであろう.(「特定方向への並進」ではなく)
fana

2021/10/26 02:11

想定される未来に対するレスを先につけておく: > なるほど.では,座標(x,y,-1) を「回転」させるとはどうすればいいですか? 「カメラの真正面の方向」を示す単位ベクトルを, 角度θを用いて ( cosθ, 0, sinθ ) とかなんとか表現してみればどうでしょう. 変数θを設けてその初期値をてきとーに与えて,以降キー操作でθを増減させるという話ですぞ. FrameWork::Camera::setLook(); の引数には, 「このベクトルとカメラの位置ベクトルを加算したもの」を与えれば良いのではないかと見えますな. 例えば,カメラ位置が (0,0,200) で固定なのであれば,( cosθ, 0, sinθ + 200 ) とかになりますかな.
退会済みユーザー

退会済みユーザー

2021/10/28 00:46 編集

なるほど。以下のようにしたのですが全く回転されません。これはどうしたらいいのでしょうか? かけ算にしましたがこれはただしいのでしょうか? FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,sin(y) + 100,-1)); FrameWork::Camera::setPosition(glm::vec3(0,100,300));
fana

2021/10/28 01:09

> 全く回転されません とはどういうことでしょうか. どのような挙動になっているのかは別として,xやyの値が変化すれば,何かしら視野が変化するのではないかと思いますが,実際に何が起きているのですか? (トンボの目を回すためにトンボの前で回す人差し指みたいな回転になっていそうに想像しますが) (もしも,xやyの変分量が vecSpeed = 10; のままだとしたら,意味的には大きすぎます.cosやsinに突っ込む値に関して適度な変分量にしていますか?) > かけ算にしましたが 示された2行の中に かけ算 は見当たりませんが,何の話なのでしょう?
退会済みユーザー

退会済みユーザー

2021/10/28 01:15

なるほど。以下のようにしました。sin(y) * 100 の部分ですが足し算だと視線が回転しないのでかけ算にしたのですが一定までは回転しますがその後回転が逆に回転してしまい 360度回転できません。原因は sin()関数にあるのはわかるのですが。どうすれば全方位に回転できるのでしょうか? FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,sin(y) * 100,-1)); FrameWork::Camera::setPosition(glm::vec3(0,100,300));
fana

2021/10/28 01:39

まず,あなたの言うところの「全方位に回転」の意味を明確にせねばならないでしょう. 現在のところ,私は以下のような認識でいます. --- (A) 座標軸の向きについては,提示されている画像で言えば,上方向が Y軸正の向きである (B) 所望の「回転」とは,提示されている画像で言えば,左右に旋回する動作に相当する --- この2点があっていますか? もしあっているならば, 上記(B)の旋回を行う場合においては,setLook() で指定する座標のY座標値は変化させる必要が無いはずです. そのような考えの上で, > ( cosθ, 0, sinθ + 200 ) とか書いています.(回転角θによって変化するのは X と Z であり,Yは不変)
退会済みユーザー

退会済みユーザー

2021/10/28 01:57 編集

なるほど。以下のようにしたのでのですが上手く回転できません。横に360度回転させるにはどうすればいいのでしょうか?自分はBの回転を行いたいのですが現状は左右左右と戻ったり行ったりします。 sin()関数の問題だと思うのですがこの場合どうやって修正するのでしょうか? FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,100,sin(y) + 300)); FrameWork::Camera::setPosition(glm::vec3(0,100,300));
fana

2021/10/28 01:59

> ( cosθ, 0, sinθ + 200 ) のように,単一の角度θを,XとZの座標計算に用います.
fana

2021/10/28 02:05

(cosθ + 0, 100, sinθ + 300) というのは (0, 100, 300) を中心とする半径1の円周上の座標です. カメラの注視点の座標を変更することで視野の方向を回転させるのであれば, カメラの周りを周回するように注視点を動かすべきでしょう.
退会済みユーザー

退会済みユーザー

2021/10/28 02:08

なるほど質問ですが カメラの周りを周回するように注視点を動かす するにはどうすればいいのでしょうか?
fana

2021/10/28 02:12

> FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,100,sin(y) + 300)); あなたは,xとyという2つの値を用いています. 対して私は,上述したように,単一の値θを用いています. とりあえず sin 側も x を使う形にしてみたらどうですか?
退会済みユーザー

退会済みユーザー

2021/10/28 02:25 編集

なるほど。一様できたのですが。なんか動きが速くなったり遅くなったりするのですがこれはどうしたらいいのでしょうか? FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,100,sin(x) + 300)); FrameWork::Camera::setPosition(glm::vec3(0,100,300));
fana

2021/10/28 02:42

> 動きが速くなったり遅くなったりする 現象の詳細がわからないので,何とも言えません. 「視野がある特定の方角を向いているときには常に旋回が 速い/遅い」みたいな法則性がある話なのでしょうか? それとも向いている方角と現象の発生具合は無関係に見えるのでしょうか? 前者側である場合(:明らかに視野の方向と旋回の速さとの間に相関が見られるという場合)には, 注視点の軌跡が偏心してしまうような何らかの要因が存在するのかもしれません.(が,それが何なのか?は私には不明です) 後者側である場合(:視野の方向と現象の具合との間には法則性がなさそうな場合)は… 何でしょう? 単にループの速度が一定でないだけなのかもしれませんし…?
退会済みユーザー

退会済みユーザー

2021/10/28 02:45

何かしらの原因はあるにしても提示コードだけではこれで正しいのでしょうか?
fana

2021/10/28 03:00

私が示した話を以下に纏めます. * 元々の話の要因を述べた: 視野の方向がある方向(初期の真正面を0度としたときの±90度)に漸近していくような処理になっていたことが要因. * 視野を左右に回転させるための方法論を示した: 注視点座標をカメラの周りを周回するように更新すればよい. 当初の問題に関しては,対応できているのではないかと考えます. --- で,現在生じている新たな問題(:旋回速度が一様でない)については私にはわかりません. > 提示コードだけではこれで正しいのでしょうか? 私は提示コードの全てを読解しているわけではないので,そこの判断まではできません.
退会済みユーザー

退会済みユーザー

2021/10/28 03:07

なるほど。質問ですがY軸の方向も設定したのですがこれは正しいのでしょうか? FrameWork::Camera::setLook(glm::vec3(cos(x) + 0,sin(y) + 100,sin(x) + 300)); FrameWork::Camera::setPosition(glm::vec3(0,100,300));
fana

2021/10/28 03:22

実際にやってみてください. > sin(y) + 100 とは,「回転」ではなくて,Y座標値をちょっと(sin(y)の分だけ)変化させているだけです. この形だと sin によって生じる挙動が意味不明となりそうですし,sinが取り得る値域とあなたの3Dの世界での縮尺の兼ね合いとかもあるので,ここでsinを使う意義はないでしょう. sinを取っ払って y+100 とかにした方がいくらかマシでしょう. ↓ そうすれば,質問当初の左右方向と同じ現象が上下方向に生じる形になるでしょう. すなわち, ある程度上下に視野の向きを変えることができるが,決して±90には行かず(真上/真下 に至らず), 上下角度が大きくなるにつれて上下角度の変化は遅くなる. といった挙動になるでしょう. (上下に少し視点を変えるだけなら簡易的な方法としては十分なのかもしれませんし,やはり挙動の具合が嫌かもしれません.それはあなた次第.)
fana

2021/10/28 03:28

上下にも「回転」したい,とかいう場合には, ちゃんと真面目に「回転姿勢」を扱う必要があります. glm::lookAt() を使わずに自前で行列 view の中身を計算する形の実装となるでしょうし, あなたにとってかなり面倒な話になるように思います. (FrameWork::Camera の仕様が変わっちゃいますしね)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問