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

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

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

Q&A

解決済

1回答

759閲覧

[OpengGL] FPSゲームのようなカメラワークを実装したい。

退会済みユーザー

退会済みユーザー

総合スコア0

0グッド

0クリップ

投稿2021/10/28 09:22

編集2021/10/29 04:51

提示コードのコメント部内部のコードですがFPSゲームで座標(0,0,0)の時に例えば左に向けている時に右キーを押すとワールド空間でいうところのZ軸マイナス方向に向かって進といった処理を実装したいのですがこれはどうすれば実装できるのでしょうか?ベクトルの求め方がわかりません。

※ 前が-Z 左が-X の上が+Y の座標形です。

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 z = 0; float x = 0; float angleY = 0; float angleX = 0; float vecSpeed = PI / 1000; float moveSpeed = 5; glm::ivec2 prevPos = FrameWork::windowContext->getMousePos(); glm::ivec2 nowPos; glm::vec3 cameraPos = glm::vec3(100, 0, 300); while (*FrameWork::windowContext) { FrameWork::windowContext->FrameUpdate(glm::vec4(0, 0, 0, 255)); nowPos = FrameWork::windowContext->getMousePos(); glm::vec2 vec = nowPos - prevPos; vec.x = vec.x * vecSpeed; vec.y = -vec.y * vecSpeed; glm::vec3 moveVec = glm::vec3(cos(vec.x) * cos(vec.y), sin(vec.y), sin(vec.x) * cos(vec.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); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// //カメラ移動 if (FrameWork::windowContext->getKeyInput(GLFW_KEY_LEFT) > (short)0) { x += -moveSpeed; cameraPos.x += moveVec.x * 10; cameraPos.z += moveVec.z * 10; // printf("left\n"); // printf("%f , %f \n",x,y); } else if (FrameWork::windowContext->getKeyInput(GLFW_KEY_RIGHT) > (short)0) { x += moveSpeed; // printf("right\n"); // printf("%f , %f \n",x,y); cameraPos.x += moveVec.x * 10; cameraPos.z += moveVec.z * 10; } if (FrameWork::windowContext->getKeyInput(GLFW_KEY_UP) > (short)0) { z += moveSpeed; // printf("up\n"); // printf("%f , %f \n",x,y); cameraPos.x += moveVec.x * 10; cameraPos.z += moveVec.z * 10; } else if (FrameWork::windowContext->getKeyInput(GLFW_KEY_DOWN) > (short)0) { z += -moveSpeed; // printf("down\n"); // printf("%f , %f \n",x,y); cameraPos.x += moveVec.x * 10; cameraPos.z += moveVec.z * 10; } else { } FrameWork::Camera::setLook(glm::vec3(cos(vec.x) * cos(vec.y), sin(vec.y), sin(vec.x) * cos(vec.y))); FrameWork::Camera::setPosition(cameraPos); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Cube cube.shader->setEnable(); cube.setPosition(glm::vec3(0, 70, 30)); 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, 0.0f)); cube.shader->setUniform3f("viewPos", FrameWork::Camera::getPosition()); cube.Renderer(); cube.shader->setDisable(); // Ground ground.shader->setEnable(); ground.setPosition(glm::vec3(0, 0, 0)); ground.setScale(glm::vec3(1, 1, 1)); 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, 0)); 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ページで確認できます。

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

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

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

fana

2021/10/29 04:48 編集

> 座標(0,0,0)の時に例えば左に向けている時に右キーを押すとワールド空間でいうところのZ軸マイナス方向に向かって進… 話の前提として 「あなたの考えている世界での座標軸の方向に関する定義」を まずは与える必要があるのではないでしょうか? また,「左」とか言われても何がなんだかわかりません. > Z軸マイナス方向に向かって という説明と同じように,XYZ軸の話で述べるべきでしょう.
guest

回答1

0

ベストアンサー

例えば左に向けている時に右キーを押すとワールド空間でいうところのZ軸マイナス方向に向かって進…

同じような言葉で書きますか.

「右キー」を押すと「右の方向」に進む,っていう話なんですよね?

そのゲームには同様に,「前方」に進むためのキーもあるだろうと思います.
仮にそのキーを「前キー」と呼ぶとしましょうか.

あなたのプログラムには,きっと,
【「前キー」を押したときに,ワールド空間でいうところの量としてどの方向に移動するのか?】
を表すためのベクトル量が存在するはずです.
話から察するに,移動はX-Z平面上で行われるのでしょうから,そのベクトルは

現在の前方を示すベクトル = ( FX, 0 FZ )

みたいなものかと推測します.

さて,必要なのは, 現在の右方向を示すベクトル ですよね?
以下にそれを得る手順を示します.

  1. 現在の前方を示すベクトル のX成分とZ成分を入れ替えたベクトルを用意します.

( FZ, 0, FX ) となりますね.
2. X成分とZ成分のうち,どちらか一方を -1倍 します.
( -FZ, 0, FX ) か,( FZ, 0, -FX ) です.

上記手順で得られた2つの候補のうち,一方が所望の 現在の右方向を示すベクトル であり,他方はその逆向きである 現在の左方向を示すベクトル になっています.
どちらが右でどちらが左なのか(すなわち,ステップ2でどちら側を-1倍すれば右が得られるのか)については,一度実際に計算結果を確認してみれば良いでしょう.
一方の側で試してみて,その結果が左だったならば他方の側が正解です.


簡潔な説明:

  • 「前方」を示すベクトルを,鉛直軸周りに90度回転させればよい.
  • 「前方」を示すベクトルと鉛直方向を示すベクトルの両方に直交するベクトルを求めればよい.→両者の外積でおk.

※結果がうっかり「左」になったならば逆が「右」だ.

投稿2021/10/29 05:15

編集2021/10/29 05:21
fana

総合スコア11996

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問