Effekseerについて

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

Effekseerについて

#1

投稿記事 by Priest » 11年前

普段、C言語とDXライブラリを用いてTPSのゲームを作っている者です。

本日、Effekseerというエフェクトを作ってDXライブラリのゲームにも組み込める神ライブラリを知って早速組み込んでみたのですが、
その関数群をどう扱ったらよいのか理解するのに難航しております。

画像のように、撃った方向とは違う方向にレーザーが射出しているので、
多分どこかの値がミスっているのでしょうが、
心当たりが多すぎてもうどうしようか悩んでいます。
(ちなみに、Effekseer抜きでは上手く動かせるので、
おそらく、Effekseer側とDXライブラリ側のカメラの投影行列や座標系の同期とかがおかしいんだと思います。)
owata.png
このEffekseerのリファレンス(DXライブラリのリファレンスのように関数群の引数の意味とか使用例が詳しくのっているようなの)
はあるのでしょうか?
少し検索しても,情報が少ない気がします。

私がC++を十分に扱えないということも響いてると思います。
勢いで実装しています。

すみませんが、上記に関しましてよろしくお願い致します。
最後に編集したユーザー Priest on 2013年6月09日(日) 20:24 [ 編集 1 回目 ]

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: Effekseerについて

#2

投稿記事 by softya(ソフト屋) » 11年前

このエフェクトは方向をマトリクスで与えるんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#3

投稿記事 by Priest » 11年前

コード:

// エフェクト管理用インスタンスの生成
g_manager = ::Effekseer::Manager::Create( 2000 );

g_manager->SetLocation(g_handle, Pc.Pos.x,Pc.Pos.y,Pc.Pos.z);//位置
g_manager->SetRotation(g_handle, Bullet[i].Rot.x,Bullet[i].Rot.y,Bullet[i].Rot.z);//回転
g_manager->SetScale(g_handle,10.0f,10.0f,10.0f);//倍率
以上のように、各軸に対する回転角を受け付ける関数が用意されています。
(と、調べ回って見つけた開設ブログには書いてありました。)
行列が使える関数があるのかはまだ分かりません。

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: Effekseerについて

#4

投稿記事 by h2so5 » 11年前

ドキュメントが無いならソースを読めば良いのでは?

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#5

投稿記事 by Priest » 11年前

はい、それはごもっともで、少し覗いてみたのですが
ちょっとC++の解読が知識的に難ありだったので、何か文書の存在の情報があれば嬉しいなと思って投稿しました。

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: Effekseerについて

#6

投稿記事 by softya(ソフト屋) » 11年前

ダウンロードしてみたら、ヘッダにマトリクス関数SetMatrix()とかSetBaseMatrix()かありましたよ。
どっちを使うべきなのは試してみないと分かりませんが。

>ちょっとC++の解読が知識的に難ありだったので、何か文書の存在の情報があれば嬉しいなと思って投稿しました。
C++の難しいと頃では無いはずです。関数と引数を見るだけですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#7

投稿記事 by Priest » 11年前

ソースを覗いて、ヘッダ等で関数とその引数を確認した後に、じゃあこの関数は何やってるんだろ?ってcppの方を覗くと
Cerには見慣れないtemplateとかnewとか::とかバンバン出てきて、ドキッとしてしまいます.

行列も使用できるようですね.有難うございます.

今は分からないところが漠然としすぎてるので,ここ一点がわからん!ってなった時に改めて質問します.
もうちょっと試行錯誤します!

# 今までCで全部何とかなってきたので,言語の壁の厚さを感じたは初めてです.
# 使用を迫られてから学べばいいじゃん!と思っていましたが,ついにその日が訪れたのでしょうか.

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#8

投稿記事 by Priest » 11年前

きたああああああ!
hajimata.png
試行錯誤の末、ようやく角度が合いました。

原因は3点あり、そのうちの1つがかなり厄介でした。

1つ目は、Effekseer側とDXライブラリ側でカメラの視野角設定がずれていたこと。
2つ目は、Effekseer側とDXライブラリ側で座標系が違っていたこと。(しばらくeffekseer側は右手座標系設定でした)

3つ目についてですが、回転がうまくいかなかったことです。
先ほど行列を使うという案が出ていたので、それを使って変換をしたら動いたのですが、
それまでは、行列を使わずに、xyzそれぞれの軸に対して回転角度を指定して回転をしてくれる関数(Effekseer::Manager::SetRotation())を使用していました。
…が、これだけがうまく動作をしてくれませんでした。

コード:

  g_handle = g_manager->Play(g_effect,0.0f,0.0f,0.0f); // エフェクトの再生
  g_manager->SetLocation(g_handle,Bullet[i].Pos.x,Bullet[i].Pos.y,Bullet[i].Pos.z);//位置 ←位置設定が反映される
  g_manager->SetRotation(g_handle,Bullet[i].Rot.x,Bullet[i].Rot.y,Bullet[i].Rot.z);//回転 ← 回転が反映されない
  g_manager->SetScale(g_handle,10.0f,10.0f,10.0f);//拡大 ← 拡大が反映される
ほかのSetLocation等は動作するのに何故か回転だけやってくれませんでした。

コード:

  Effekseer::Matrix43 Matrix,MatrixRot;
  MatrixRot.Indentity(); // 単位行列取得
  MatrixRot.RotationZXY(Bullet[i].Rot.z,Bullet[i].Rot.x,Bullet[i].Rot.y); // 回転行列生成

  g_handle = g_manager->Play(g_effect,0.0f,0.0f,0.0f); // エフェクトの再生
  Matrix = g_manager->GetBaseMatrix(g_handle); // 今のエフェクトの持つ行列を取得
  Matrix.SetSRT(DXLtoEFK(VGet(10.0f,10.0f,10.0f)),
                MatrixRot,
                DXLtoEFK(VGet(Bullet[i].Pos.x,Bullet[i].Pos.y,Bullet[i].Pos.z))); // 拡大、回転、移動行列を作成
  g_manager->SetBaseMatrix(g_handle,Matrix); // その行列をエフェクトに適用
  //DXLtoEFK()はDXライブラリのVECTOR型をEffekseerのそれに変換する関数
結局、↑な感じで行列を使って実装できました。
# SetBaseMatrixの方を使うようです。

SetRotationだけ謎です。

一応、情報掲示と結果報告まで!

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#9

投稿記事 by Priest » 11年前

無事、位置と角度は完璧に合わせてエフェクトを描画できるようになりました。

ただし、自分以外のキャラクタが、そのエフェクトを出現させた場合、
エフェクトの中心点がカメラの視野の外側に来てないと描画しないという現象が発生して困っています。
(エフェクトの中心点は発射位置です。)
以下のような感じです。
fail.zip
(3.34 MiB) ダウンロード数: 188 回

コード:

// エフェクト用
static ::Effekseer::Manager*			BManager = NULL;
static ::EffekseerRenderer::Renderer*	BRenderer = NULL;
static ::Effekseer::Effect*				BEffect[BENUM];

// VECTOR型⇔Vector3D型相互変換
Effekseer::Vector3D DXLtoEFK(DxLib::VECTOR v){
	return Effekseer::Vector3D(v.x,v.y,v.z);
}

// 弾エフェクトの初期化
void BEffectInit(void){

	// 描画用インスタンスの生成
	BRenderer = ::EffekseerRenderer::Renderer::Create( (LPDIRECT3DDEVICE9)GetUseDirect3DDevice9(), 30000 );
	
	// エフェクト管理用インスタンスの生成
	BManager = ::Effekseer::Manager::Create( 3000 );

	// 描画用インスタンスから描画機能を設定
	BManager->SetSpriteRenderer( BRenderer->CreateSpriteRenderer() );
	BManager->SetRibbonRenderer( BRenderer->CreateRibbonRenderer() );
	BManager->SetRingRenderer( BRenderer->CreateRingRenderer() );
	BManager->SetModelRenderer( BRenderer->CreateModelRenderer() );

	// 描画用インスタンスからテクスチャの読込機能を設定
	// 独自拡張可能、現在はファイルから読み込んでいる。
	BManager->SetTextureLoader( BRenderer->CreateTextureLoader() );
	BManager->SetModelLoader( BRenderer->CreateModelLoader() );
	BManager->SetCoordinateSystem( ::Effekseer::COORDINATE_SYSTEM_LH );

	// エフェクトの読込
	BEffect[BE_MASTERSPARK] = Effekseer::Effect::Create( BManager, (const EFK_CHAR*)L"Effect/MasterSpark.efk" );

	// 投影行列を設定
	// WINDOWWIDTH: ウィンドウの横幅 WINDOWHEIGHT: ウィンドウの縦幅
	BRenderer->SetProjectionMatrix(
		::Effekseer::Matrix44().PerspectiveFovLH(GetCameraFov(), (float)WINDOWWIDTH / (float)WINDOWHEIGHT, GetCameraNear(),GetCameraFar()) );

}

// 同期
void BEffectSync(void){

	// カメラ行列を設定
	// GetCameraPos(): カメラの座標を返す関数 GetCameraTar(): カメラの注視点を返す関数
	BRenderer->SetCameraMatrix(
		::Effekseer::Matrix44().LookAtLH(DXLtoEFK(GetCameraPos()), ::DXLtoEFK(GetCameraTar()), ::Effekseer::Vector3D( 0.0f, 1.0f, 0.0f ) ) );
}

// エフェクトの描画
void DrawBEffect(void){

	// 頂点バッファに溜まった頂点データを吐き出す
	RenderVertex();

	// エフェクトの更新処理を行う
	BManager->Update();

	// エフェクトの描画開始処理
	BRenderer->BeginRendering();

	// エフェクトの描画
	BManager->Draw();

	// エフェクトの描画終了処理
	BRenderer->EndRendering();
}

// エフェクトの登録
void BEffectRegist(int BulletID, int BEID){

	// エフェクトの再生
	Bullet[BulletID].EHandle = BManager->Play(BEffect[BE_MASTERSPARK],0.0f,0.0f,1.0f);

	// 回転行列を取得
	Effekseer::Matrix43 Matrix,MatrixRot;
	MatrixRot.Indentity();
	MatrixRot.RotationZXY(Bullet[BulletID].Rot.z,Bullet[BulletID].Rot.x,Bullet[BulletID].Rot.y);

	// 拡大、回転、移動行列をエフェクトに適用
	Matrix = BManager->GetBaseMatrix(Bullet[BulletID].EHandle);
	Matrix.SetSRT(DXLtoEFK(VGet(100.0f,100.0f,100.0f)),MatrixRot,DXLtoEFK(VGet(Bullet[BulletID].Pos.x,Bullet[BulletID].Pos.y,Bullet[BulletID].Pos.z)));
	BManager->SetBaseMatrix(Bullet[BulletID].EHandle,Matrix);
}

// エフェクトの破棄
void BEffectUnregist(int BulletID, int BEID){
	
	// 停止
	BManager->StopEffect(Bullet[BulletID].EHandle);

}

void ManageMastersparkBullet(void){

	// まず最初に
	if(GameFrame==Bullet[i].StartFrame) BEffectRegist(i,BE_MASTERSPARK); // エフェクトのセット

	// 終わり直前
	if(GameFrame==Bullet[i].EndFrame) BEffectUnregist(i,BE_MASTERSPARK); // エフェクト破棄

}

main 関数{

	BEffectInit(); // 初期化

	while(いつまでもループ){

		…; // ゲームの進行(プレイヤやカメラの移動等)
		BEffectSync(); // …;でゲームが進行しているのでカメラ位置の同期を取る

		if(誰かがレーザーが撃っている間) ManageMastersparkBullet();

		DrawBEffect(); // ここで描画
	}

}

エフェクトに関するコードはこんな感じです。

まず、whileループに入る前に初期化を行います。
ここで、各種エフェクトを読み込んだり、それを描画するための準備を行います。
ループ内のBEffectSyncでDXライブラリとEffekseer側のカメラ等の同期を取ります。

レーザー発射ボタンを検知したら、ManageMastersparkBullet()内のBEffectRegist(i,BE_MASTERSPARK); でエフェクトをセットします。
iは弾の識別番号です。BE_MASTERSPARKはその弾がレーザーであることを示すためです。

BEffectRegist()内で、変数Bulletにエフェクトのハンドルを与えます。
そのハンドルを介してエフェクトの位置や角度を設定します。

DrawBEffect()で描画します。

以上のようなコーディングになっています。

問題点は、!CheckCameraViewClip(Bullet.Pos) を使用した時のように、カメラの視野に入っているかどうかで描画するかどうか決めるといった処理をしていないのに
そんな動作をしているところです。

解決案が分からず困っています。

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#10

投稿記事 by Priest » 11年前

No9の問題に対して、少し進展がありました。
調査の結果、キャラクタの描画を無くすと正常にエフェクトが再生されるようです。
(他のモデルデータ、地形などは描画おkでした。)

コード:

//キャラを描画
void DrawPlayer(void){
	for(int i=0;i<PCNUM;i++){
		if(!CheckCameraViewClip(Pc[i].Pos)){
			MV1SetPosition(Pc[i].Handle.Model,VGet(Pc[i].Pos.x,Pc[i].Pos.y,Pc[i].Pos.z));
			MV1SetRotationXYZ(Pc[i].Handle.Model,VGet(Pc[i].Rot.x,Pc[i].Rot.y,Pc[i].Rot.z));
			//MV1DrawModel(Pc[i].Handle.Model); ←ここをコメントアウトし、キャラクタを描画させない様にしてみる
		}
	}
}
以上のようにコメントアウトしたところ、
NoCharacterRenderering.png
のように正常動作しました。
キャラクタは映っていません。

mv1ファイルのモデルデータとの共存はなんらかの問題で無理ということでしょうか?

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: Effekseerについて

#11

投稿記事 by Priest » 11年前

さらに、もう一個有用な情報です。

mv1モデルデータに対して、モーションデータを取り除くと、正常に動作をすることが判明しました。
悪さをしているのは、モーションデータのような気がします。

ちょっと、私のレベルでは修正できないような問題の気がしております。

これら一連の現象に関して、なにか情報がありましたら、ぜひお願い致します。
NoMotionVer.png

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

閉鎖

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