三人称のカメラの動きについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ctyu

三人称のカメラの動きについて

#1

投稿記事 by ctyu » 4ヶ月前

今、DXライブラリの3D関連のところを勉強していて、
FPSのようにマウスを右に動かすと右に向き、
左にうごかすと左に向き、
上下にも向けるというプログラムをつくっています。

コード: 全て選択

#include <DxLib.h>
#include <math.h>

void rotate(float *x, float *y, const float ang, const float mx, const float my) {
const float ox = *x - mx, oy = *y - my;
*x = ox * cos(ang) + oy * sin(ang);
*y = -ox * sin(ang) + oy * cos(ang);
*x += mx;
*y += my;
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
ChangeWindowMode(FALSE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

int Handle = MV1LoadModel("3Dsample/dat/Lat式ミク/Lat式ミクVer2.3_Normal.pmd");
float camera_x = 0.0 , camera_y = 10.0, camera_z = -20.0;
float target_x = 0.0, target_y = 10.0, target_z = 0.0;
float x = 0.0, y = 0.0, z = 0.0;
int mouse_x_check = 0, mouse_y_check = 0;
float camera_speed_x = 0.0;
float camera_speed_y = 0.0;

SetCameraNearFar(0.1, 10000.0);
SetCameraPositionAndTarget_UpVecY(VGet(camera_x, camera_y, camera_z), VGet(target_x, target_y, target_z));

while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) {

GetMousePoint(&mouse_x_check, &mouse_y_check);	//マウス座標の更新
if (0 < mouse_x_check) {	//マウスの横移動の処理、マウスが右に移動したらカメラを右回転に設定
camera_speed_x = 0.05;
}
else {
if (0 > mouse_x_check) {	//マウスが左に移動したらカメラを左回転に設定
camera_speed_x = -0.05;
}
else {
camera_speed_x = 0.0;	//マウスが動いてなければカメラの横移動をキャンセル
}
}

if (10 > mouse_y_check) {	//マウスの横移動の処理、マウスが上に移動したらカメラを右回転に設定
camera_speed_y = 0.05;
}
else {
if (10 < mouse_y_check) {	//マウスが下に移動したらカメラを左回転に設定
camera_speed_y = -0.05;
}
else {
camera_speed_y = 0.0;	//マウスが動いてなければカメラの縦移動をキャンセル
}
}
SetMousePoint(0, 10);	//マウス座標リセット
rotate(&target_x, &target_z, camera_speed_x, camera_x, camera_z);	//カメラを回転
rotate(&target_y, &target_z, camera_speed_y, camera_y, camera_z);	//カメラを回転
//次のフレームでの比較のためのマウス座標の保存

if (CheckHitKey(KEY_INPUT_A)) {
camera_x -= 0.1;
}
if (CheckHitKey(KEY_INPUT_D)) {
camera_x += 0.1;
}
if (CheckHitKey(KEY_INPUT_W)) {
camera_z += 0.1;
}
if (CheckHitKey(KEY_INPUT_S)) {
camera_z -= 0.1;
}

SetCameraPositionAndTarget_UpVecY(VGet(camera_x, camera_y, camera_z), VGet(target_x, target_y,target_z));
MV1SetPosition(Handle, VGet(x, y, z));
MV1DrawModel(Handle);
DrawFormatString(10, 10, GetColor(0, 255, 0), "mouse_x_check = %d mouse_y_check = %d",mouse_x_check,mouse_y_check);
}
DxLib_End();
return 0;
}
こんな感じです。
左右は正常に動きますが、x軸上で上下にマウスを動かすとなぜかななめにカメラが動いてしまいます。
どうすればよいのでしょうか?

アバター
usao
記事: 1368
登録日時: 5年前

Re: 三人称のカメラの動きについて

#2

投稿記事 by usao » 4ヶ月前

http://dixq.net/forum/viewtopic.php?f=3&t=19796
同じ?

> どうすればよいのでしょうか?
問題だと思う現象が発生する原因を調べて,そうならないように対処すれば良いのでは?

ctyu

Re: 三人称のカメラの動きについて

#3

投稿記事 by ctyu » 4ヶ月前

本当にすいません。
原因が分からないです。
教えてください。

TKS

Re: 三人称のカメラの動きについて

#4

投稿記事 by TKS » 4ヶ月前

質問から時間が経っているので、その間に何を試してどういう結果になったかを書いたら、回答も得られやすくなるのでは無いでしょうか。

全くどこからも手が付かないようなら、
>x軸上で上下にマウスを動かすとなぜかななめにカメラが動いてしまいます。
この動作を行った際に、以下の手順で挙動を確認してみては如何でしょう。

0.カメラ回転に無関係な処理を切る
・この手順で、カメラ回転に原因があるのか確認します
・58~69行目が該当するかと思います

1.「mouse_x_check」「mouse_y_check」の値を確認する
・この手順で、マウス入力処理が正しく動いているか確認します
・74行目のDrawFormatString関数の内容が、そのまま使えると思います

2.左右回転処理を切る
・この手順で、縦回転処理が正しく動いているか確認します
・30~40、54行目の左右回転(?)を行っている処理を切って、縦回転処理のみ動かしてみましょう

3.54行目のrotate関数を復帰する
・この手順で、54行目のrotate関数が、55行目の処理に影響を与えていないか確認します
・30~40行目は切ってあるので「camera_speed_x」は常にゼロとなり、想定通りなら左右回転は発生しないはずです

これぐらい試しても原因が分からなければ、もう少し具体的な解決策が提示されるのでは無いでしょうか

アバター
usao
記事: 1368
登録日時: 5年前

Re: 三人称のカメラの動きについて

#5

投稿記事 by usao » 4ヶ月前

> 原因が分からない
という言い方は,裏を返せば,演算内容の正当性に自信がある,ということなのでしょうかね.

このコードが「やっていること」の通りに
マッチ棒でもペンでも何でもいいので,実際に物を回してみたら何かわかったりしませんか?

ctyu

Re: 三人称のカメラの動きについて

#6

投稿記事 by ctyu » 4ヶ月前

いろいろやってみた結果、どうやらz軸回転をしてないのが原因のようでした。しかし、x軸回転をするかz軸回転をするかの判断の仕方が分かりません。カメラがx軸に沿って向いている時だけz軸回転をするというふうにしてみたのですが、動きがかくついて、不自然になってしまいます。どうすれば滑らかに動くように判断できるのでしょうか。

ctyu

Re: 三人称のカメラの動きについて

#7

投稿記事 by ctyu » 3ヶ月前

コード: 全て選択

#include <DxLib.h>
#include <math.h>

void rotate(float *x, float *y, const float ang, const float mx, const float my) {
	const float ox = *x - mx, oy = *y - my;
	*x = ox * cos(ang) + oy * sin(ang);
	*y = -ox * sin(ang) + oy * cos(ang);
	*x += mx;
	*y += my;
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	ChangeWindowMode(FALSE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

	int Handle = MV1LoadModel("3Dsample/dat/Lat式ミク/Lat式ミクVer2.3_Normal.pmd");
	float camera_x = 0.0 , camera_y = 10.0, camera_z = -20.0;
	float target_x = 0.0, target_y = 10.0, target_z = 0.0;
	float x = 0.0, y = 0.0, z = 0.0;
	int mouse_x_check = 0, mouse_y_check = 0;
	float camera_speed_x = 0.0;
	float camera_speed_y = 0.0;

	SetCameraNearFar(0.1, 10000.0);
	SetCameraPositionAndTarget_UpVecY(VGet(camera_x, camera_y, camera_z), VGet(target_x, target_y, target_z));

	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) {

		GetMousePoint(&mouse_x_check, &mouse_y_check);					//マウス座標の更新
		if (0 < mouse_x_check) {									//マウスの横移動の処理、マウスが右に移動したらカメラを右回転に設定
			camera_speed_x = 0.1;
		}
		else {
			if (0 > mouse_x_check) {								//マウスが左に移動したらカメラを左回転に設定
				camera_speed_x = -0.1;
			}
			else {
				camera_speed_x = 0.0;										//マウスが動いてなければカメラの横移動をキャンセル
			}
		}

		if (10 > mouse_y_check && camera_y > 3) {									//マウスの縦移動の処理、マウスが下に移動したらカメラを下回転に設定
			camera_speed_y = 0.1;
		}
		else {
			if (10 < mouse_y_check && camera_y < 28.0 ) {								//マウスが上に移動したらカメラを上回転に設定
				camera_speed_y = -0.1;
			}
			else {
				camera_speed_y = 0.0;										//マウスが動いてなければカメラの縦移動をキャンセル
			}
		}

		SetMousePoint(0, 10);								//マウス座標リセット
		rotate(&camera_x, &camera_z, camera_speed_x, target_x, target_z);	//カメラを回転
		rotate(&camera_y, &camera_x, camera_speed_y, target_y, target_x);	//カメラを回転
		rotate(&camera_z, &camera_y, camera_speed_y, target_z, target_y);	//カメラを回転
		

		if (CheckHitKey(KEY_INPUT_A)) {
			camera_x -= 0.1;
		}
		if (CheckHitKey(KEY_INPUT_D)) {
			camera_x += 0.1;
		}
		if (CheckHitKey(KEY_INPUT_W)) {
			camera_z += 0.1;
		}
		if (CheckHitKey(KEY_INPUT_S)) {
			camera_z -= 0.1;
		}
		
		SetCameraPositionAndTarget_UpVecY(VGet(camera_x, camera_y, camera_z), VGet(target_x, target_y,target_z));
		MV1SetPosition(Handle, VGet(x, y, z));
		MV1DrawModel(Handle);
		DrawFormatString(10, 10, GetColor(0, 255, 0), "x = %f y = %f z = %f speed = %f",camera_x,camera_y,camera_z,camera_speed_y);
	}
			DxLib_End();
			return 0;
	}
これでもだめでした
はやくも3Dゲームの制作をあきらめそうです...
どこをどうすればいいでしょうか?

アバター
usao
記事: 1368
登録日時: 5年前

Re: 三人称のカメラの動きについて

#8

投稿記事 by usao » 3ヶ月前

以前とは rotate() への引数の渡し具合が変わっているのですね.
(読み手としてはどのような変更が発生したのか不明ですから良いのか悪いのかもわかりませんが)


そのrotate()という関数を複数回使う場合(最初のコードでは2回,今回のコードでは3回連続で使われている),
適用順序によって結果が変わるという点は大丈夫でしょうか?
例えば,最初のコードでrotate()の順序を入れ替えたりしてみるとどうなりますか?

返信

“C言語何でも質問掲示板” へ戻る