3Dでカメラが向いている方向に移動したい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sadora3
記事: 175
登録日時: 11年前

3Dでカメラが向いている方向に移動したい

#1

投稿記事 by sadora3 » 9年前

カメラの向いている方向に移動したいのですが、出来ません。というか、一応出来るのですがY軸の移動がおかしいです。上を向くほど早くなっていきます。
原因はtanを使っていることにあるのは分かっているのですが、他にやり方がわかりません。

言語:C
ライブラリ:DXライブラリ
コンパイラ:VisualStudio2010

カメラの旋回はマウス、カメラの移動はキーボードのWASDキーです。
Wキーを押せばカメラの向いている方向に前進。
Sキーを押せばカメラの向いている方向から後進。
Aキーを押せばカメラの向いている方向から左に移動。
Dキーを押せばカメラの向いている方向から右に移動です。
どうすればいいのでしょうか?

コード:

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

#define CAMERA_SPEED 10.0f
#define rad(a) (a * DX_PI_F / 180.0f)

int NewX = 0, NewY = 0;
int OldX = 0, OldY = 0;

typedef struct{
	float PosX, PosY, PosZ;
	float RotV, RotH;
}CameraStatus;

CameraStatus Camera = {800.0f, 0.0f, 800.0f, 0.0f, -135.0f};

void MoveCamera();
void DrawSp();
void Information();

int ProcessLoop(){
	if(ProcessMessage() != 0){	return -1;	}
	if(ClearDrawScreen() != 0){	return -1;	}
	return 0;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	ChangeWindowMode(TRUE);
	SetGraphMode(640, 480, 16);
	SetBackgroundColor(255,255,255);
	if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){	return -1;	}

	SetMousePoint(320,240);
	SetMouseDispFlag(FALSE);
	GetMousePoint(&OldX, &OldY);

	while(ProcessLoop() == 0 && !CheckHitKey(KEY_INPUT_ESCAPE)){
		MoveCamera();
		DrawFormatString(310, 230, GetColor(0,0,0), "( )");
		DrawSp();
		Information();
		ScreenFlip();
	}

	DxLib_End();
	return 0;
}

void MoveCamera(){
	if(CheckHitKey(KEY_INPUT_W) != 0){
		Camera.PosX += CAMERA_SPEED * sin(rad(Camera.RotH));
		Camera.PosZ += CAMERA_SPEED * cos(rad(Camera.RotH));
		Camera.PosY -= CAMERA_SPEED * tan(rad(Camera.RotV));
	}
	if(CheckHitKey(KEY_INPUT_S) != 0){
		Camera.PosX -= CAMERA_SPEED * sin(rad(Camera.RotH));
		Camera.PosZ -= CAMERA_SPEED * cos(rad(Camera.RotH));
		Camera.PosY += CAMERA_SPEED * tan(rad(Camera.RotV));
	}
	if(CheckHitKey(KEY_INPUT_D) != 0){
		Camera.PosX += CAMERA_SPEED * cos(rad(Camera.RotH));
		Camera.PosZ -= CAMERA_SPEED * sin(rad(Camera.RotH));
	}
	if(CheckHitKey(KEY_INPUT_A) != 0){
		Camera.PosX -= CAMERA_SPEED * cos(rad(Camera.RotH));
		Camera.PosZ += CAMERA_SPEED * sin(rad(Camera.RotH));
	}

	GetMousePoint(&NewX, &NewY);
	Camera.RotH += NewX - OldX;
	Camera.RotV += NewY - OldY;
	OldX = NewX; OldY = NewY;

	SetCameraPositionAndAngle(VGet(Camera.PosX, Camera.PosY, Camera.PosZ), rad(Camera.RotV) , rad(Camera.RotH), 0);
}

void DrawSp(){
	for(float x = 80.0f; x < 5000.0f; x += 80.0f){
		DrawSphere3D(VGet(x,0,0), 30, 8, GetColor(255,0,0), GetColor(255,255,255), FALSE);
	}
	for(float y = 80.0f; y < 5000; y += 80.0f){
		DrawSphere3D(VGet(0,y,0), 30, 8, GetColor(0,255,0), GetColor(255,255,255), FALSE);
	}
	for(float z = 80.0f; z < 5000; z += 80.0f){
		DrawSphere3D(VGet(0,0,z), 30, 8, GetColor(0,0,255), GetColor(255,255,255), FALSE);
	}
}

void Information(){
	DrawFormatString(0, 0, GetColor(0,0,0), "ESCキーで終了します");
	DrawFormatString(0, 20, GetColor(0,0,0), "Wキーで前進");
	DrawFormatString(0, 40, GetColor(0,0,0), "Sキーで後進");
	DrawFormatString(0, 60, GetColor(0,0,0), "Aキーで左移動");
	DrawFormatString(0, 80, GetColor(0,0,0), "Sキーで右移動");
}



アバター
usao
記事: 1889
登録日時: 11年前

Re: 3Dでカメラが向いている方向に移動したい

#2

投稿記事 by usao » 9年前

(1)
>カメラの向いている方向
を表す 単位方向ベクトルV を算出し,

(2)
カメラの座標に CAMERA_SPEED*V  を加算する


ということをやりたいのだと思いますが,
(1)が現状のコードになっているのはどのような計算の結果によるのでしょうか?

51,52行目などを見た感じだと,VのX成分とZ成分だけで既に長さが1になっていますが
そこにさらにYの成分が(RotVから算出される値として)加えられていますから
RotVの値によって移動量が増減してしまうのは当然ではないでしょうか.

座標軸の取り方もCameraStatus型で持っているパラメタの意味も説明されていないのでやりたいことに合致するかわかりませんが,
・RotV=RotH=0のときの単位方向ベクトルV0を用意 : (V0=(0,0,1)とか?)
・RotVの影響でV0を回転させた結果のベクトルVvを算出
・VvをさらにRotHの影響で回転させた結果のベクトルが求めたいV
という感じに段階的に算出してみてはいかがでしょうか.

アバター
usao
記事: 1889
登録日時: 11年前

Re: 3Dでカメラが向いている方向に移動したい

#3

投稿記事 by usao » 9年前

DXライブラリ を使っているのであれば,算術演算関数があるみたいですね
http://homepage2.nifty.com/natupaji/DxL ... html#R12N4
オフトピック
まぁ「これらの関数をどう組み合わせるのか」というところまでは演算内容を理解する必要があるでしょうし
そこまでわかっているなら
”三角関数を自分で書かなくて済む” 程度の恩恵しかないのかもしれませんが.

ISLe()

Re: 3Dでカメラが向いている方向に移動したい

#4

投稿記事 by ISLe() » 9年前

過去ログにこんなトピックがありました。
カメラの向いている方向にカメラを移動させたい

参考になるでしょうか。

Yunix

Re: 3Dでカメラが向いている方向に移動したい

#5

投稿記事 by Yunix » 9年前

初めて作ってみたのですが、こんな感じでしょうか?
if文の条件は各自変えてください。
私の仕様上カーソルキーでカメラの角度移動。
WASDでカメラの座標移動です。
どうぞ参考にしてください。

使用した変数は
VECTOR Pos;//カメラの座標
VECTOR UpMove;//W移動のベクトル
VECTOR DownMove;//S移動
VECTOR LeftMove;//A移動
VECTOR RightMove;//D移動
float VRotate;//カメラアングルX
float HRotate;//カメラアングルY
float TRotate;//カメラアングルZ

コード:

void init(){
	VRotate = 0.0f;
	HRotate = 0.0f;
	TRotate = 0.0f;
	SetCameraNearFar(1.0f,1000.0f);//見える範囲
	Pos = VGet(0.0f,0.0f,0.0f);
}
void Update(){	//MoveCamera
	Rotate();	//カメラの角度を変える
	if(kb.W){ //W移動
		UpMove = VNorm(VTransform(VGet(0.0f,0.0f, 0.1f),MMult(MMult(MGetRotZ(TRotate),MGetRotX(VRotate)), MGetRotY(HRotate))));	//前へのベクトル取得
		UpMove = VNorm(UpMove);		//単位ベクトルにする
		UpMove = VScale(UpMove,0.5f);//移動速度調整
		Pos = VAdd(Pos, UpMove);	//カメラ座標に加算
	}
	if(kb.A){ //A移動
		LeftMove = VNorm(VTransform(VGet(0.0f,0.0f, 0.1f),MMult(MMult(MGetRotZ(TRotate),MGetRotX(VRotate)), MGetRotY(HRotate))));	//左へのベクトル取得
		LeftMove = VCross(LeftMove,VGet(0.0f,1.0f,0.0f));
		LeftMove = VNorm(LeftMove);
		LeftMove = VScale(LeftMove,0.5f);
		Pos = VAdd(Pos, LeftMove);
	}
	if(kb.S){ //S移動
		DownMove = VNorm(VTransform(VGet(0.0f,0.0f, -0.1f),MMult(MMult(MGetRotZ(TRotate),MGetRotX(VRotate)), MGetRotY(HRotate))));	//後ろベクトル取得
		DownMove = VNorm(DownMove);
		DownMove = VScale(DownMove,0.5f);
		Pos = VAdd(Pos, DownMove);
	}
	if(kb.D){ //D移動
		RightMove = VNorm(VTransform(VGet(0.0f,0.0f, -0.1f),MMult(MMult(MGetRotZ(TRotate),MGetRotX(VRotate)), MGetRotY(HRotate))));	//右ベクトル取得
		RightMove = VCross(RightMove,VGet(0.0f,1.0f,0.0f));
		RightMove = VNorm(RightMove);
		RightMove = VScale(RightMove,0.5f);
		Pos = VAdd(Pos, RightMove);
	}
	SetCameraPositionAndAngle( Pos, VRotate, HRotate, TRotate ) ;//カメラセット
}
void Rotate(){//カメラアングル
	if(kb.UP)			VRotate -= 1/ 60.0f;
	if(kb.DOWN)		VRotate += 1/ 60.0f;
	if(kb.Left)			HRotate -= 1/ 60.0f;
	if(kb.Right)		HRotate += 1/ 60.0f;
	if(VRotate < -1)	VRotate = -1;
	if(VRotate > 1)		VRotate = 1;
}


Yunix

Re: 3Dでカメラが向いている方向に移動したい

#6

投稿記事 by Yunix » 9年前

連続書き込みすみません。
無駄に2度VNorm()を使用していますね。VNorm()を1回だけ使用するように省いてお使いください。

sadora3
記事: 175
登録日時: 11年前

Re: 3Dでカメラが向いている方向に移動したい

#7

投稿記事 by sadora3 » 9年前

皆さん回答ありがとうございます。
忙しくて中々プライベートの時間が作れずに困っています。
Yunixさんのプログラムを動かしたらまさに私がしたかったことが出来ました。
今このソースコードを理解しているところです。
そこで、すこし疑問があるのですが、

float VRotate;//カメラアングルX
float HRotate;//カメラアングルY
float TRotate;//カメラアングルZ
と、あるのですが、VはVertical、HはHorizonですよね?
ではTはなんでしょうか?

あと、このソースコードを理解するには行列を勉強する必要がありますよね・・・。
行列が分かりやすくまとめられているサイトはありませんか?
あと、行列の何を勉強すればいいのでしょうか?回転行列ですか?3次元行列ですか?

Yunix

Re: 3Dでカメラが向いている方向に移動したい

#8

投稿記事 by Yunix » 9年前

TはTwist(ねじれ)のつもりで書きました。

行列が解らない場合、とりあえずまずは行列の計算方法を知る必要があります。
和、差、積、などの。
その後に、回転行列について勉強してください。
私が勉強した手順は、
2次元行列の基本的な計算の勉強→2次元行列の回転行列の勉強→3次元行列の勉強→3次元行列の回転行列の勉強

行列がまとめられているサイト(分かりやすいかはちょっと分からないです)
行列
回転行列

勉強手順がいまいち分からないのなら、教材を買って順番に勉強していくという手もありますね。個人的にはこれがおススメかなーと思います。

sadora3
記事: 175
登録日時: 11年前

Re: 3Dでカメラが向いている方向に移動したい

#9

投稿記事 by sadora3 » 9年前

>>Yunixさん
なるほどです。
ここまでしてくださって大変感謝しています。
これから行列の勉強頑張ろうと思います。

閉鎖

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