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

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

新規登録して質問してみよう
ただいま回答率
86.02%
C++

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

Q&A

受付中

クォータニオンを用いて物体を等速で回転させる方法が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

1回答

0グッド

0クリップ

381閲覧

投稿2022/11/02 02:16

提示コードのif文のキー入力部ですがクォータニオンを用いて立方体の回転を実装しているのですがキーを押しっぱなしにすると微妙に回転が遅くなって止まってしまうのですがこれはどう対処したらいいのでしょうか?等速で回転してくれません。

イメージ説明

transform

cpp

1/*############################################################################################ 2# 行列回転 取得 3############################################################################################*/ 4glm::mat4 FrameWork::Transform::getMatRotate()const 5{ 6 if( (rotateOrigin == glm::vec3(0,0,0)) || (rotateVector == glm::vec3(0,0,0)) ) 7 { 8 assert(0 && "Transform::setRotate() (origin == glm::vec3(0,0,0)) || (vec == glm::vec3(0,0,0)"); 9 } 10 11 return glm::mat4(RotationBetweenVectors(rotateOrigin,rotateVector)); 12} 13 14 15/*############################################################################################ 16# 2つのベクトルのなす角 17############################################################################################*/ 18glm::quat FrameWork::Transform::RotationBetweenVectors(glm::vec3 start, glm::vec3 dest)const 19{ 20 start = glm::normalize(start); 21 dest = glm::normalize(dest); 22 23 float cosTheta = glm::dot(start, dest); 24 glm::vec3 rotationAxis; 25 26 if (cosTheta < -1 + 0.001f) 27 { 28 rotationAxis = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), start); 29 if (glm::length2(rotationAxis) < 0.01) 30 { 31 rotationAxis = glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), start); 32 } 33 34 rotationAxis = glm::normalize(rotationAxis); 35 36 return glm::angleAxis(glm::radians(180.0f), rotationAxis); 37 } 38 39 rotationAxis = glm::cross(start, dest); 40 41 float s = glm::sqrt((1 + cosTheta) * 2); 42 float invs = 1 / s; 43 44 return glm::quat 45 ( 46 s * 0.5f, 47 rotationAxis.x * invs, 48 rotationAxis.y * invs, 49 rotationAxis.z * invs 50 ); 51} 52 53
Player.cpp

cpp

1#include "Player.hpp" 2#include "FrameWork_3D/FrameWork.hpp" 3#include <memory> 4 5Player::Player() 6{ 7 //FrameWork::Resource::LoadModel("asset/model/mesh.fbx"); 8 texture = FrameWork::Resource::LoadTexture("asset/texture/debug.png",aiTextureType_BASE_COLOR); 9 10 model = FrameWork::Resource::LoadModel("asset/model/mesh.fbx"); 11 //model.setVertexBuffer(); 12 13 shader = std::make_shared<FrameWork::Shader>(); 14 shader->Load("asset/shader/3D/texture/BasicTexture.vert", "asset/shader/3D/texture/BasicTexture.frag"); 15 //shader->Load("asset/shader/3D/Monochromatic/BasicMono.vert","asset/shader/3D/Monochromatic/BasicMono.frag"); 16 17// texture = FrameWork::LoadTexture("asset/texture/debug.png", glm::vec2(8, 8)); 18 19 rotate = glm::vec3(0, 1, 0); 20 transform.position = glm::vec3(0, 0, 0); 21 transform.scale = glm::vec3(1,1,1); 22 transform.rotateOrigin = glm::vec3(0,1,0); 23 transform.rotateVector = rotate; 24 25 //transform.rotateOrigin = glm::vec3(1, 0, 0); 26 //transform.rotateVector = glm::vec3(1, 0, 0); 27 28 shader->setVertexAttribute(model->vao,model->vbo, "vertexPosition", 3, sizeof(FrameWork::VertexAttribute), sizeof(float) * 0); 29 shader->setVertexAttribute(model->vao, model->vbo, "vertexUV", 2, sizeof(FrameWork::VertexAttribute), sizeof(float) * 3); 30// shader->setVertexAttribute(sprite.vao, sprite.vbo, "vertexNormal", 3, sizeof(FrameWork::VertexAttribute_Sprite), sizeof(float) * 5); 31 32 //sprite.shader = shader; 33} 34 35void Player::Render(const glm::mat4 view) 36{ 37 shader->setEnable(); 38 39 40 41 if (FrameWork::Window::windowContext->getKeyInput(GLFW_KEY_UP) == true) 42 { 43 rotate.z += 0.01; 44 } 45 46 if (FrameWork::Window::windowContext->getKeyInput(GLFW_KEY_DOWN ) == true) 47 { 48 rotate.z -= 0.01; 49 } 50 51 52 if (FrameWork::Window::windowContext->getKeyInput(GLFW_KEY_RIGHT) == true) 53 { 54 rotate.x += 0.01; 55 } 56 57 if (FrameWork::Window::windowContext->getKeyInput(GLFW_KEY_LEFT ) == true) 58 { 59 rotate.x -= 0.01; 60 } 61 62 std::cout << "rotate.x: " << rotate.x << std::endl; 63 std::cout << "rotate.z: " << rotate.z << std::endl; 64 std::cout <<std::endl; 65 66 67 68 transform.rotateVector = rotate; 69 70 shader->setUniformSampler2D("uImage", 0, texture.getID()); 71 //shader->setUniform4f("uFragment",glm::vec4(1.0,0.0,0.0,0.0)); 72 shader->setUniformMatrix4x4fv("uViewProjection", view); 73 shader->setUniformMatrix4x4fv("uScale", transform.getMatScale()); 74 shader->setUniformMatrix4x4fv("uTranslate", transform.getMatPosition()); 75 shader->setUniformMatrix4x4fv("uRotate", transform.getMatRotate()); 76 model->Render(); 77 78 shader->setDisable(); 79} 80 81void Player::Update() 82{ 83 //sprite.setTexture(0, texture.at(0)); 84} 85 86

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

コードを全部見ているわけじゃなく「ぱっと見の雰囲気」での話だけど…

  • 2つのベクトルの成す角 を求めていて,何かわからんけどクォータニオンはその角度に対応したものが求められる.
  • 2つのベクトルの初期値はどちらも (0,1,0)
  • キー操作で一方の側のベクトルの1つの要素が増減される

という話だとしたら…

等速で回転するには「2つのベクトルの成す角」なる量が常に等量だけ増加していく必要があるのでは?
(そんなことが可能かどうかは知らんが)

何が悪いか,に関しては,例えば,キーを押し続けて rotate.x += 0.01; が複数回実施されていくとき,「2つのベクトルの成す角」がどのように変化していくのかを考えてみればよい.
かなりの時間キーを押し続けて一方のベクトルが (すっごい大きいx値,1,0) になったとして,他方がずっと(0,1,0)固定なのであれば,角度は90度に漸近していくだけだ.


どうすれば良いか? に関しては,(2つのベクトルとかいう奴らの役割がわからない側からすれば,)単に,やりたいことを素直にやればいいじゃない? と思う.
例えば,「キーを押している状況ではある一定の角度 θ だけ回転する」ということをしたいなら,「回転角度θに対応するクォータニオン」を計算して使ってればいいんじゃないの?

投稿2022/11/02 03:00

fana

総合スコア10681

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

fana

2022/11/02 03:03

> 角度は90度に漸近していくだけだ っていう話,昔もやったような気がするが,記憶違いか?
退会済みユーザー

退会済みユーザー

2022/11/02 03:04

質問ですが > 「キーを押している状況ではある一定の角度 θ だけ回転する」ということをしたいなら,「回転角度θに対応するクォータニオン」を計算 とありますが。これは何の値から計算すればいいのでしょうか?
fana

2022/11/02 03:07

「何の値」って何? あるキーを押したときに「どっち方向にどれだけ回したいか」っていう所望の変化量はあなたが決めるんじゃないの? どれだけ回したいか=角度θ が定数でいいなら定数で実装すればいいんじゃない?
fana

2022/11/04 03:06

退会しtail ! > shader->setUniformMatrix4x4fv("uRotate", transform.getMatRotate()); なる行から察するに,回転行列をシェーダのuniform変数に設定するんだろうから, 「回転行列そのもの あるいはそれを作り出せる何らかの情報」を保持しておいてキー押下時に更新すれば良いのだと思うよ. そしたら「その更新量とは何か」っていうだけの話になるよね. 押したキーに応じた方向に姿勢をちょっとだけ回す,ということをすればよいのであり,その「ちょっとだけ回す」角度のことを θ と述べたということである. (わざわざ言うまでも無いが,「ちょっとだけ回す」際の回転軸は押されたたキーから即決まるよね) で,「更新」ってのはマトリクスを左右どっちから乗じるのか?的な話もあり得たりするのだけど… まぁいいや.

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C++

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