ページ 11

DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月21日(金) 00:47
by BTCT_G
突然の投稿、失礼します。お世話になります。

現在、dxlibとC#を用いた3Dゲーム作成を志しているのですが、当たり判定の処理を作ることが出来ません。
MV1CollCheck_Sphereの使用方法が理解できない状態です。

MV1CollCheck_Sphereを使用するにあたって、MV1_COLL_RESULT_POLY_DIM型の変数へ戻り値を受けてやるところまではわかったのですが、
衝突しているポリゴンのデータをどう参照していいのかを理解できません。

MV1_COLL_RESULT_POLY_DIMの中身を確認したところ、
C++版のdxlibでは、

コード:

typedef struct tagMV1_COLL_RESULT_POLY_DIM
{
	int						HitNum ;							// ヒットしたポリゴンの数
	MV1_COLL_RESULT_POLY *	Dim ;								// ヒットしたポリゴンの配列( HitNum個分存在する )
} MV1_COLL_RESULT_POLY_DIM ;
とあり、衝突したポリゴンのデータ保存先であるMV1_COLL_RESULT_POLY型のポインタDimが確認できるのですが、
C#版のdxlibで同箇所を確認したところ、

コード:

		public struct MV1_COLL_RESULT_POLY_DIM
		{
			[FieldOffset(0)] public int  HitNum;
			[FieldOffset(4)] public uint  Dim;
		};
となっており、Dimがuint型となっております。

この値をどう使えば、衝突しているポリゴンのデータを保存している配列へたどり着けるのでしょうか。
ご教授願います。

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月21日(金) 10:46
by YuO
DxLibのVisual C#パッケージは,公式にも書いてあるように機械変換されたものです。
ただし,この機械変換の精度は決して高くありません。
e.g.) 過去の事例
このため,自分で必要な変換を書く必要があります。

また,構造体へのポインタを持つ構造体をマーシャリングするのは,非常に手間です。
http://msdn.microsoft.com/ja-jp/library ... .110).aspx
このあたりのマーシャリングを理解した上で,変換メソッドを書き直す必要があると思います。
# 戻り値もIntPtrで受けてMarshalクラス使って変換して……

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月21日(金) 19:11
by BTCT_G
To : YuO様

返信、ありがとうございます。
変換の関係で、そのままでは使用できなくなっていることを理解出来ました。

C#とdxlibを用いて3Dゲームを作っている方のアルゴリズムやサンプルコードを見たことがなくて恐縮なのですが、
C#を用いる場合、一般的に三次元物体同士はどのように当たり判定処理を行うものなのでしょうか。

今回想定しているのは、キャラクターと床及び壁ポリゴンの当たり判定についてなのですが、

・dxlib内部の構造体を構築しなおしMV1CollCheck_Sphereを使う
・別の、MV1_COLL_RESULT_POLY_DIM構造体を使用しない命令を使う
・衝突判定の命令を組み直す

などが考えられます。どの方法が無難でしょうか。

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月23日(日) 23:22
by BTCT_G
再度、質問をお許しください。

現在、教えていただいた情報を元に、MV1_COLL_RESULT_POLY_DIM型構造体を改造しようと試みていたのですが、
具体的にどのようなことをすればいいかを理解できず、途方にくれております。

今回使用しようとしているMV1CollCheck_Sphere命令は、MV1_COLL_RESULT_POLY_DIM構造体内で定義したMV1_COLL_RESULT_POLY型のポインタ変数Dimへポリゴン情報を書き込むものかと思うのですが、
Marshalクラスをどのように使用すればよいものでしょうか。
また、MV1_COLL_RESULT_POLY_DIMやMV1_COLL_RESULT_POLYをどのように改造する必要があるのでしょうか。

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月25日(火) 20:39
by Idra
MV1CollCheck_GetResultPolyは使ってみましたか?
uintは32bitなので32bit向けにビルドすれば期待通りの動きになるかもです。

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月26日(水) 00:48
by BTCT_G
To : Idra様
返信ありがとうございます。

早速命令を使用してみましたが、衝突したポリゴンの位置情報等のデータを取り出すことは出来ませんでした。
具体的には、衝突用モデルをどの位置においても、取り出すデータが[0,1,0]になるという現象が起きます。

該当命令であるMV1CollCheck_GetResultPolyの引数に、既にMV1_COLL_RESULT_POLY_DIM型構造体を使っているせいかと考えられます。
まずMV1_COLL_RESULT_POLY_DIM型構造体へデータを入れるために、MV1CollCheck_Sphere命令を使わねばならないようですが、
構造体自体がMV1CollCheck_Sphereのデータを受け取れないので、引き出す事もできないようです。

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月26日(水) 19:58
by Idra
プログラムと入出力データが明らかでないとコメントし辛いですね・・・

公式のMV1CollCheck_GetResultPolyの使用例がちょうどいい感じだったのでC#で書き直しました。
ぱっと見た感じ正常に動いていると思いますがどうですか?

コード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DxLib = DxLibDLL.DX;

namespace DxLibSample {

	public class CollCheckSample {

		public void Run() {
			int ModelHandle;
			int Add, y, i;
			DxLib.VECTOR SpherePos;
			DxLib.MV1_COLL_RESULT_POLY_DIM HitPolyDim;
			DxLib.MV1_COLL_RESULT_POLY HitPoly;

			// DXライブラリの初期化
			DxLib.ChangeWindowMode(DxLib.TRUE);
			if (DxLib.DxLib_Init() < 0) {
				// エラーが発生したら直ちに終了
				//return -1;
				return;
			}

			// 3Dモデルの読み込み
			ModelHandle = DxLib.MV1LoadModel("SimpleModel.mqo");

			// 3Dモデルを見える位置に移動する
			DxLib.MV1SetPosition(ModelHandle, DxLib.VGet(320.0f, 300.0f, 600.0f));

			// 描画先を裏画面に変更
			DxLib.SetDrawScreen(DxLib.DX_SCREEN_BACK);

			// モデル全体のコリジョン情報を構築
			DxLib.MV1SetupCollInfo(ModelHandle, -1, 8, 8, 8);

			// モデルの進行方向をセット
			Add = 8;

			// モデルの移動位置をセット
			y = 0;

			// ウインドウが閉じられるか何かキーが押されるまでループ
			while (DxLib.ProcessMessage() == 0 && DxLib.CheckHitKeyAll() == 0) {
				// 画面をクリア
				DxLib.ClearDrawScreen();

				// 3Dモデルの移動位置を上下に移動させる
				y += Add;
				if (y < 0 || y > 600)
					Add = -Add;

				// 3Dモデルの描画
				DxLib.MV1DrawModel(ModelHandle);

				// 当たり判定を行う球の位置をセット
				SpherePos = DxLib.VGet(250.0f, y, 600.0f);

				// モデルと球との当たり判定
				HitPolyDim = DxLib.MV1CollCheck_Sphere(ModelHandle, -1, SpherePos, 100.0f);

				// 球の描画
				DxLib.DrawSphere3D(SpherePos, 100.0f, 8, DxLib.GetColor(255, 255, 0), DxLib.GetColor(255, 255, 255), DxLib.FALSE);

				// 当たったかどうかで処理を分岐
				if (HitPolyDim.HitNum >= 1) {
					// 当たった場合は衝突の情報を描画する

					// 当たったポリゴンの数を描画
					//DxLib.DrawFormatString(0, 0, DxLib.GetColor(255, 255, 255), "Hit Poly Num   %d", HitPolyDim.HitNum);
					var polyCount = String.Format("Hit Poly Num   {0:d}", HitPolyDim.HitNum);
					DxLib.DrawString(0, 0, polyCount, DxLib.GetColor(255, 255, 255));

					// 当たったポリゴンの数だけ繰り返し
					for (i = 0; i < HitPolyDim.HitNum; i++) {
						// 当たったポリゴンとの最近点の座標を描画
						HitPoly = DxLib.MV1CollCheck_GetResultPoly(HitPolyDim, i);
						//DxLib.DrawFormatString(0, 16 + 16 * i, DxLib.GetColor(255, 255, 255), "Position   %f  %f  %f",
						//	HitPoly.HitPosition.x, HitPoly.HitPosition.y, HitPoly.HitPosition.z);
						var text = String.Format("Position   {0:f}  {1:f}  {2:f}", HitPoly.HitPosition.x, HitPoly.HitPosition.y, HitPoly.HitPosition.z);
						DxLib.DrawString(0, 16 + 16 * i, text, DxLib.GetColor(255, 255, 255));
					}
				}

				// 当たり判定情報の後始末
				DxLib.MV1CollResultPolyDimTerminate(HitPolyDim);

				// 裏画面の内容を表画面に反映
				DxLib.ScreenFlip();
			}

			// DXライブラリの後始末
			DxLib.DxLib_End();

			// ソフトの終了
			//return 0;
		}

	}

}

Re: DXlib + C#を用いた場合のMV1_COLL_RESULT_POLY_DIM型構造体の使用について

Posted: 2014年2月27日(木) 22:33
by BTCT_G
To : Idra様

返信、ありがとうございます。
いただいたソースをこちらでコンパイルしたところ、動作いたしました。

私の勘違いでして、取り出すデータを間違っていた様子です。
VECTOR型のNormalに、衝突座標が入るものだと思い込んでおり、そちらを参照しておりました。
衝突座標がVECTOR型のHitPositionに入ることを知らず、Normalの中身を見ていたせいで、[0,1,0]という値になっていたようです。
こちらの「当たったポリゴンの法線」というものも理解できていないので、勉強を進めます。

MV1CollCheck_GetResultPoly命令を使用することにより、当たり判定処理を作ることが出来そうです。
これにて本案件を解決とさせていただきます。
お世話になりました。ありがとうございました。