忍者ブログ

神戸電子専門学校ゲームソフト学科の生徒が運営するGESのブログです。

   

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

DirectX 9 スキンメッシュ アニメーション

(長文注意)
どーもpcgestです。
サイボウズLiveでuncleさんが

誰かGESブログ書いて…

という事を書いていたのを見て、

そういやブログ全然書いてなかったなー(笑)

、よし、たまには書くか!とか思ったので、自己紹介を除いて本日初投稿とさせていただきます。


拍手[2回]


ちなみに私は結構実力主義なところがありますので、基礎よりも応用技術を書くことが多くなると思います。
さて、本日は誰もがが頭を悩ませるであろうスキンメッシュに関しての記事を書くことにします。
全知全能といわれた事のある検索エンジンで「DirectX9 スキンメッシュ」と検索した事のある方は多いのではないでしょうか?
「あるにはあったけど分からない、サンプルプログラムが動かない」という方もまた多いと思います。
そもそもサンプル自体が少ないように感じました。
そこで今回は、2年の時に自身の作品に使用したゲームからスキンメッシュの部分
だけを取り出したサンプルコードを用意しました。
分かりやすいように、main一本書きにしております。
一応3年でも勉強はしますが、待ちきれない子のために用意します(笑)
就活にもかかわってくるだろうし…
さてスキンメッシュについてですが、皆さんがどこまで把握しているのかはわかりませんが、
要はボーンと呼ばれる頂点を作り、そこに属している頂点のみを動かす技術です。
やる事は実に単純で、行列かけていくだけです
以下にスキンメッシュのコードを実際に書きますので、規約を守れる方のみ参考にどうぞ(これがスキンメッシュの"ひな形"に当たります)
(これの元となったサンプルの規約には、
このサンプルがついている本の購入者は、このサンプルを自由に
扱っていい。
という事でしたので、いろいろ改変して配布させて頂きました)

--------------------------------
規約
--------------------------------
このサンプルについてですが、コピペして自身のソースコードに取り入れるのはOKとしますが、
再配布(第三者へこのソースコードを配布する行為)は禁止します。

が、ゲームなどの成果物に取り入れ、それを提出する際にはその限りではありません。

改変とかもどんどんしちゃって下さい(その方が実際にプログラムをいじるので覚えやすいです)。
//--- main.cpp -------------------------------------------------------------
//アノテーションコメントについて
//------------------------------------------
//キーワード : 内容
//------------------------------------------
//todo : 後にコードを調整もしくは追加する
//fixme : 破損しているため修正が必要
//optimize : アプリケーションのパフォーマンス(動作)を最適化(軽く)する事が可能
//hack : 後にリファクタリング(コードの整理)する
//review : 後にレビューが必要
//------------------------------------------
//---標準ライブラリ指定-------
#include<windows.h>
#include<stdio.h>
#include<d3dx9.h>
#include<time.h>
//---外部ライブラリ指定----
//例 #pragma comment(lib, "lib\\○○○.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "winmm.lib")
//ライブラリのインクルード
#include <iostream> //.hは不要
#include <string> //.hは不要
#include <vector> //.hは不要
#include <sstream> //.hは不要
#include <sstream> //.hは不要
// シンボル定義及びマクロ
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
#define SCRW 640 // Width
#define SCRH 480 // Height
//////////////////////////////////////////////
// ビューポートのデータを定義 ----------------
//////////////////////////////////////////////
const D3DVIEWPORT9 view[] = { { 0, 0, SCRW / 2, SCRH / 2, 0.f, 1.f }
//右上
, { SCRW / 2, 0, SCRW / 2, SCRH / 2, 0.f, 1.f }
//左下
, { 0, SCRH / 2, SCRW / 2, SCRH / 2, 0.f, 1.f }
//右下
, { SCRW / 2, SCRH / 2, SCRW / 2, SCRH / 2, 0.f, 1.f } };
//FPS(1秒 = 1000/FPSミリ秒)
#define FPS 60
//アニメーションコントローラーのスピード
#define SKIN_ANIME_SPEED 60.0f / 4800.0f
//派生フレーム構造体 (それぞれのメッシュ用の最終ワールド行列を追加する)
struct MYFRAME : public D3DXFRAME
{
D3DXMATRIX CombinedTransformationMatrix;
// オフセット行列(インデックス付描画用)
D3DXMATRIX OffsetMat;
// 行列テーブルのインデックス番号(インデックス付用)
DWORD OffsetID;
};
//派生メッシュコンテナー構造体(
//コンテナーがテクスチャを複数持てるようにポインターのポインターを追加する)
struct MYMESHCONTAINER : public D3DXMESHCONTAINER
{
LPDIRECT3DTEXTURE9*  ppTextures;
DWORD dwWeight; //重みの個数(重みとは頂点への影響。)
DWORD dwBoneNum; //ボーンの数
LPD3DXBUFFER pBoneBuffer; //ボーン・テーブル
D3DXMATRIX** ppBoneMatrix; //全てのボーンのワールド行列の先頭ポインター
D3DXMATRIX* pBoneOffsetMatrices; //フレームとしてのボーンのワールド行列のポインター
LPD3DXMESH pOriMesh; //オリジナルメッシュ用
DWORD NumPaletteEntries; //パレットサイズ
// Work用
std::vector<D3DXMATRIX> m_WorkBoneMatArray;
// 影響するフレームへの参照配列。描画時にこのフレームの行列を使う。
std::vector<MYFRAME*> BoneFrameArray;
MYMESHCONTAINER(){
ppBoneMatrix = NULL;
pBoneOffsetMatrices = NULL;
}
};
//Xファイル内のアニメーション階層を読み下してくれるクラスを派生させる。
//ID3DXAllocateHierarchyは派生すること想定して設計されている。
class MY_HIERARCHY : public ID3DXAllocateHierarchy
{
public:
MY_HIERARCHY(){}
STDMETHOD(CreateFrame)(THIS_ LPCSTR, LPD3DXFRAME *);
STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR, CONST D3DXMESHDATA*, CONST D3DXMATERIAL*,
CONST D3DXEFFECTINSTANCE*, DWORD, CONST DWORD *, LPD3DXSKININFO, LPD3DXMESHCONTAINER *);
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME);
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER);
private:
};
//フレームを作成する
HRESULT MY_HIERARCHY::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame)
{
HRESULT hr = S_OK;
MYFRAME *pFrame;
//新しいフレームアドレス格納用変数を初期化
*ppNewFrame = NULL;
//フレームの領域確保
pFrame = new MYFRAME;
//領域確保の失敗時の処理
if (pFrame == NULL)
{
return E_OUTOFMEMORY;
}
//フレーム名格納用領域確保
pFrame->Name = new TCHAR[lstrlen(Name) + 1];
//領域確保の失敗時の処理
if (!pFrame->Name)
{
return E_FAIL;
}
// strcpy(pFrame->Name,Name);
//フレーム名格納
strcpy_s(pFrame->Name, lstrlen(Name) + 1, Name);
//行列の初期化
D3DXMatrixIdentity(&pFrame->TransformationMatrix);
D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
//追加:オフセット関係初期化
pFrame->OffsetID = 0xFFFFFFFF;
D3DXMatrixIdentity(&(pFrame->OffsetMat));
//新規フレームのメッシュコンテナ初期化
pFrame->pMeshContainer = NULL;
//新規フレームの兄弟フレームアドレス格納用変数初期化
pFrame->pFrameSibling = NULL;
//新規フレームの子フレームアドレス格納用変数初期化
pFrame->pFrameFirstChild = NULL;
//外部の新規フレームアドレス格納用変数に、作成したフレームのアドレスを格納
*ppNewFrame = pFrame;
return S_OK;
}
//
//HRESULT MY_HIERARCHY::CreateMeshContainer
//メッシュコンテナーを作成する
HRESULT MY_HIERARCHY::CreateMeshContainer(LPCSTR Name, CONST D3DXMESHDATA* pMeshData,
CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances,
DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppMeshContainer)
{
//    HRESULT hr;
//ローカル生成用
MYMESHCONTAINER *pMeshContainer = NULL;
//メッシュの面の数を格納
int iFacesAmount;
//forループで使用
int iMaterial;
//一時的なDirectXデバイス取得用
LPDIRECT3DDEVICE9 pDevice = NULL;
//一時的なメッシュデータ格納用
LPD3DXMESH pMesh = NULL;
//メッシュコンテナ格納用変数初期化
*ppMeshContainer = NULL;
//ボーンの数格納用変数初期化
DWORD dwBoneNum = 0;
//pMeshに"外部引数の"メッシュアドレスを格納
pMesh = pMeshData->pMesh;
//メッシュコンテナ領域の動的確保
pMeshContainer = new MYMESHCONTAINER;
//領域確保失敗時
if (pMeshContainer == NULL)
{
return E_OUTOFMEMORY;
}
//メッシュコンテナを初期化
ZeroMemory(pMeshContainer, sizeof(MYMESHCONTAINER));
//メッシュコンテナの名前格納用領域を動的確保
pMeshContainer->Name = new TCHAR[lstrlen(Name) + 1];
//失敗時の処理
if (!pMeshContainer->Name)
{
return E_FAIL;
}
//確保した領域にメッシュコンテナ名を格納
strcpy_s(pMeshContainer->Name, lstrlen(Name) + 1, Name);
//DirectXデバイス取得
pMesh->GetDevice(&pDevice);
//メッシュの面の数を取得
iFacesAmount = pMesh->GetNumFaces();
//- メッシュのマテリアル設定 -//
//メッシュのマテリアル数を格納(最大で1つ)
pMeshContainer->NumMaterials = max(1, NumMaterials);
//メッシュコンテナの、マテリアルデータ格納領域を動的確保
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
//メッシュコンテナの、テクスチャデータ格納領域を動的確保
pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
//メッシュコンテナの、面ごとに持つ3つの隣接性情報が格納されたDWORD型のアドレス格納用(ポインタ)変数
pMeshContainer->pAdjacency = new DWORD[iFacesAmount * 3];
//領域確保の失敗時の処理
if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
{
return E_FAIL;
}
//外部引数の隣接性情報をメッシュコンテナに格納
memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount * 3);
//テクスチャデータ格納用領域を初期化(memsetを使用して0で中身を埋める)
memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
//引数のマテリアル数が0じゃない場合
if (NumMaterials > 0)
{
//外部引数のマテリアルデータアドレスをメッシュコンテナに格納
memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
//マテリアル数分ループさせる
for (iMaterial = 0; (DWORD)iMaterial < NumMaterials; iMaterial++)
{
//テクスチャのファイル名がNULLでなければ(テクスチャデータがあれば)
if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
{
//テクスチャのファイルパス保存用変数
TCHAR strTexturePath[MAX_PATH];
//テクスチャのファイルパスを保存(再読み込み時に必要)
strcpy_s(strTexturePath, lstrlen(pMeshContainer->pMaterials[iMaterial].pTextureFilename) + 1, pMeshContainer->pMaterials[iMaterial].pTextureFilename);
//テクスチャ情報の読み込み
if (FAILED(D3DXCreateTextureFromFile(pDevice, strTexturePath,
&pMeshContainer->ppTextures[iMaterial])))
{
//失敗時の処理
//テクスチャファイル名格納用
CHAR TexMeshPass[255];
//追記
//もしなければ、Graphフォルダを調べる
//注)ファイル名の結合時に、必ず両方にファイル名がある事を確認してから
//  strcpy_sとstrcat_sを使うようにする(この場合は、上にある 
//    テクスチャのファイルがあり、さらにそのファイル名の長さが0でなければ の所のif文)。
//  TexMeshPassに、Xファイルがある場所と同じディレクトリと、テクスチャのファイル名を
//  結合したものを格納
// strcpy_s( TexMeshPass, sizeof( TexMeshPass ) , "./../Source/Graph/" );
strcpy_s(TexMeshPass, sizeof(TexMeshPass), "./Graph/");
strcat_s(TexMeshPass, sizeof(TexMeshPass) - strlen(TexMeshPass) - strlen(strTexturePath) - 1, strTexturePath);
//テクスチャ情報の読み込み
if (FAILED(D3DXCreateTextureFromFile(pDevice, TexMeshPass,
&pMeshContainer->ppTextures[iMaterial])))
{
pMeshContainer->ppTextures[iMaterial] = NULL;
}
//テクスチャのファイルパスをNULLにする
pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
}
}
}
}
else
{
//- マテリアルなしの場合 -//
//テクスチャファイル名をNULLに
pMeshContainer->pMaterials[0].pTextureFilename = NULL;
//マテリアルデータ初期化(memsetを使用して中身を0で埋める)
memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
//マテリアルカラーを0.5に設定
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
//スペキュラも0.5に設定(上で設定したマテリアルカラーの0.5の設定をコピー)
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
}
//メッシュ情報を格納(今回は通常メッシュと完全に分けているためすべてスキンメッシュ情報となる)
pMeshContainer->pSkinInfo = pSkinInfo;
//参照カウンタ
pSkinInfo->AddRef();
//ボーンの数を取得
dwBoneNum = pSkinInfo->GetNumBones();
//フレーム(ボーン)単位でのワールド行列格納用領域の動的確保
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[dwBoneNum];
//ボーンの数だけループさせる
for (DWORD i = 0; i < dwBoneNum; i++)
{
//角フレーム(ボーン)のオフセット行列を取得して格納
memcpy(&pMeshContainer->pBoneOffsetMatrices[i],
pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX));
}
//- 変換作業 -//
//メッシュコンテナにオリジナルのpMesh情報を格納
D3DVERTEXELEMENT9 Decl[MAX_FVF_DECL_SIZE];
pMesh->GetDeclaration(&Decl[0]);
pMesh->CloneMesh(pMesh->GetOptions(), &Decl[0], pDevice, &pMeshContainer->pOriMesh);
//メッシュのタイプを定義
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
//- 固定パイプライン描画用に変換 -//
//シェーダで描画する場合は別途変換が必要
//頂点単位でのブレンドの重みとボーンの組み合わせテーブルを適応した新しいメッシュを返す。
if (FAILED(pMeshContainer->pSkinInfo->ConvertToBlendedMesh(
pMeshContainer->pOriMesh, //元のメッシュデータアドレス
NULL, //オプション(現在は使われていないためNULLでいい)
pMeshContainer->pAdjacency, //元のメッシュの隣接性情報
NULL, //出力メッシュの隣接性情報
NULL, //各面の新しいインデックス値格納用変数のアドレス
NULL, //角頂点の新しいインデックス値格納用変数のアドレス
&pMeshContainer->dwWeight, //ボーンの影響の一面当たりの最大数格納用変数のアドレス
&pMeshContainer->dwBoneNum, //ボーンの組み合わせテーブルに含まれるボーン数格納用変数のアドレス
&pMeshContainer->pBoneBuffer, //ボーンの組み合わせテーブルへのポインタ
&pMeshContainer->MeshData.pMesh //出力されるメッシュアドレス格納用変数のアドレス(固定パイプライン用)
)))
{
return E_FAIL;
}
//ローカルに生成したメッシュコンテナーを呼び出し側にコピーする
*ppMeshContainer = pMeshContainer;
//参照カウンタを増やしたので減らす
SAFE_RELEASE(pDevice);
return S_OK;
}
//
//HRESULT MY_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree) 
//フレームを破棄する
HRESULT MY_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
//2銃解放防止
// if (pFrameToFree == NULL)return S_FALSE;
SAFE_DELETE_ARRAY(pFrameToFree->Name);
if (pFrameToFree->pFrameFirstChild)
{
DestroyFrame(pFrameToFree->pFrameFirstChild);
}
if (pFrameToFree->pFrameSibling)
{
DestroyFrame(pFrameToFree->pFrameSibling);
}
SAFE_DELETE(pFrameToFree);
return S_OK;
}
//
//HRESULT MY_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
//メッシュコンテナーを破棄する
HRESULT MY_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
int iMaterial;
MYMESHCONTAINER *pMeshContainer = (MYMESHCONTAINER*)pMeshContainerBase;
SAFE_DELETE_ARRAY(pMeshContainer->Name);
SAFE_RELEASE(pMeshContainer->pSkinInfo);
SAFE_DELETE_ARRAY(pMeshContainer->pAdjacency);
SAFE_DELETE_ARRAY(pMeshContainer->pMaterials);
SAFE_DELETE_ARRAY(pMeshContainer->ppBoneMatrix);
if (pMeshContainer->ppTextures != NULL)
{
for (iMaterial = 0; (DWORD)iMaterial < pMeshContainer->NumMaterials; iMaterial++)
{
//テクスチャ解放
SAFE_RELEASE(pMeshContainer->ppTextures[iMaterial]);
}
}
SAFE_DELETE_ARRAY(pMeshContainer->ppTextures);
SAFE_RELEASE(pMeshContainer->MeshData.pMesh);
SAFE_RELEASE(pMeshContainer->pOriMesh);
if (pMeshContainer->pBoneBuffer != NULL)
{
SAFE_RELEASE(pMeshContainer->pBoneBuffer);
SAFE_DELETE_ARRAY(pMeshContainer->pBoneOffsetMatrices);
}
SAFE_DELETE(pMeshContainer);
pMeshContainerBase = NULL;
return S_OK;
}
// スキンメッシュクラス
class CSkinMesh
{
public:
//メッシュクラスの初期化
// VOID InitBase(SMESH_DATA_FILE* _pSMeshData);
//メッシュの現在のMatrixデータ取得
D3DXMATRIX GetMatrix();
CSkinMesh();
~CSkinMesh(){
Release();
}
//スキンメッシュ内部処理
HRESULT Init(LPDIRECT3DDEVICE9 lpD3DDevice, LPSTR pMeshPass);
HRESULT AllocateBoneMatrix(LPD3DXFRAME pFrameRoot, LPD3DXMESHCONTAINER pMeshContainerBase);
HRESULT AllocateAllBoneMatrices(LPD3DXFRAME pFrameRoot, LPD3DXFRAME pFrameBase);
VOID RenderMeshContainer(LPDIRECT3DDEVICE9 lpD3DDevice, MYMESHCONTAINER*, MYFRAME*);
VOID UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix);
VOID DrawFrame(PDIRECT3DDEVICE9 lpD3DDevice, LPD3DXFRAME);
//フレーム解放
VOID FreeAnim(LPD3DXFRAME pFrame);
//解放処理
VOID Release();
//更新処理
VOID Update(D3DXMATRIX);
//描画処理
VOID Draw(LPDIRECT3DDEVICE9 lpD3DDevice);
//オブジェクトのアニメーション変更( メッシュオブジェクトの操作用番号, 変更するアニメーション番号 )
VOID ChangeAnim(DWORD NewAnimNum);
//現在のアニメーション番号取得
DWORD GetAnimTrack(){ return m_CurrentTrack; }
//現在のアニメーションタイム(アニメーション開始からの時間)を取得
DWORD GetAnimTime(){ return m_AnimeTime; }
//アニメーション速度を取得
FLOAT GetAnimSpeed(){ return m_AnimSpeed; }
//アニメーション速度を設定
VOID SetAnimSpeed(FLOAT _AnimSpeed){ m_AnimSpeed = _AnimSpeed; }
private:
//対象のボーンを検索
MYFRAME* SearchBoneFrame(LPSTR _BoneName, D3DXFRAME* _pFrame);
public:
//ボーンのマトリックス取得( ボーンの名前 )
D3DXMATRIX GetBoneMatrix(LPSTR _BoneName);
//ボーンのマトリックスポインタ取得( ボーンの名前 )
D3DXMATRIX* GetpBoneMatrix(LPSTR _BoneName);
private:
//追加
//すべてのフレームポインタ格納処理関数
VOID CreateFrameArray(LPD3DXFRAME _pFrame);
// フレーム参照用配列
std::vector<MYFRAME*> m_FrameArray; // 全フレーム参照配列
std::vector<MYFRAME*> m_IntoMeshFrameArray;// メッシュコンテナありのフレーム参照配列
//ボーン情報
LPD3DXFRAME m_pFrameRoot;
//アニメーションコントローラ
LPD3DXANIMATIONCONTROLLER m_pAnimController;
//ヒエラルキークラス変数
MY_HIERARCHY m_cHierarchy;
//アニメーションデータ格納用変数(ここは可変に変更したほうがいい)
LPD3DXANIMATIONSET m_pAnimSet[20];
//現在のアニメーションが開始されてからの時間(1/60秒)
DWORD m_AnimeTime;
//アニメーションスピード
FLOAT m_AnimSpeed;
//現在のアニメーショントラック
DWORD m_CurrentTrack;
//現在のアニメーションデータトラック
D3DXTRACK_DESC m_CurrentTrackDesc;
//進行方向
D3DXMATRIX m_World;
//メッシュのマテリアル関係
//マテリアル変更フラグ
BOOL m_MaterialFlg;
//マテリアルデータ
D3DMATERIAL9 m_Material;
};
CSkinMesh::CSkinMesh(){
//マテリアル変更フラグ
m_MaterialFlg = FALSE;
//マテリアルデータ
ZeroMemory(&m_Material, sizeof(D3DMATERIAL9));
//単位行列化
D3DXMatrixIdentity(&(this->m_World));
//アニメーション時間初期化
m_AnimeTime = 0;
//アニメーションスピード初期化
m_AnimSpeed = SKIN_ANIME_SPEED; //固定
//現在のアニメーショントラック初期化
m_CurrentTrack = 0;
//アニメーションデータトラック初期化
//有効にする
m_CurrentTrackDesc.Enable = TRUE;
//影響度100%
m_CurrentTrackDesc.Weight = 1;
//開始位置初期化
m_CurrentTrackDesc.Position = 0;
//速度
m_CurrentTrackDesc.Speed = 1;
}
VOID CSkinMesh::Release(){
if (m_pFrameRoot != NULL){
//ボーンフレーム関係解放
FreeAnim(m_pFrameRoot);
//その他情報(テクスチャの参照データなど)の解放
m_cHierarchy.DestroyFrame(m_pFrameRoot);
m_pFrameRoot = NULL;
}
//アニメーションコントローラー解放
SAFE_RELEASE(m_pAnimController);
//すべてのフレーム参照変数の要素を削除
m_FrameArray.clear();
//メッシュコンテナありのフレーム参照変数の要素を削除
m_IntoMeshFrameArray.clear();
}
HRESULT CSkinMesh::AllocateBoneMatrix(LPD3DXFRAME pFrameRoot, LPD3DXMESHCONTAINER pMeshContainerBase)
{
MYFRAME *pFrame = NULL;
DWORD dwBoneNum = 0;
//メッシュコンテナの型をオリジナルの型として扱う
//(メッシュコンテナ生成時にオリジナルの型として作っているので問題はないが、
//基本ダウンキャストは危険なので多用は避けるべき)
MYMESHCONTAINER *pMeshContainer = (MYMESHCONTAINER*)pMeshContainerBase;
//スキンメッシュでなければ
if (pMeshContainer->pSkinInfo == NULL)
{
return S_OK;
}
//ボーンの数取得
dwBoneNum = pMeshContainer->pSkinInfo->GetNumBones();
//各ボーンのワールド行列格納用領域を確保
SAFE_DELETE(pMeshContainer->ppBoneMatrix);
pMeshContainer->ppBoneMatrix = new D3DXMATRIX*[dwBoneNum];
//ボーンの数だけループ
for (DWORD i = 0; i<dwBoneNum; i++)
{
//子フレーム(ボーン)のアドレスを検索してpFrameに格納
pFrame = (MYFRAME*)D3DXFrameFind(pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName(i));
//子フレームがなければ処理を終了する
if (pFrame == NULL)
{
return E_FAIL;
}
//各ボーンのワールド行列格納用変数に最終行列を格納
pMeshContainer->ppBoneMatrix[i] = &pFrame->CombinedTransformationMatrix;
}
return S_OK;
}
//
//HRESULT AllocateAllBoneMatrices( THING* pThing,LPD3DXFRAME pFrame )
//
//ボーン行列の初期化
HRESULT CSkinMesh::AllocateAllBoneMatrices(LPD3DXFRAME pFrameRoot, LPD3DXFRAME pFrame)
{
//階層の走査(メモリを確保したメッシュコンテナ領域を探す処理)
if (pFrame->pMeshContainer != NULL)
{
//ボーン行列の初期化処理
if (FAILED(AllocateBoneMatrix(pFrameRoot, pFrame->pMeshContainer)))
{
return E_FAIL;
}
}
//再起判断処理
if (pFrame->pFrameSibling != NULL)
{
if (FAILED(AllocateAllBoneMatrices(pFrameRoot, pFrame->pFrameSibling)))
{
return E_FAIL;
}
}
if (pFrame->pFrameFirstChild != NULL)
{
if (FAILED(AllocateAllBoneMatrices(pFrameRoot, pFrame->pFrameFirstChild)))
{
return E_FAIL;
}
}
return S_OK;
}
//VOID RenderMeshContainer(LPDIRECT3DDEVICE9 pDevice,MYMESHCONTAINER* pMeshContainer, MYFRAME* pFrame)
//フレーム内のそれぞれのメッシュをレンダリングする
VOID CSkinMesh::RenderMeshContainer(LPDIRECT3DDEVICE9 pDevice, MYMESHCONTAINER* pMeshContainer, MYFRAME* pFrame)
{
DWORD i, k;
DWORD dwBlendMatrixNum;
DWORD dwPrevBoneID;
LPD3DXBONECOMBINATION pBoneCombination;
UINT iMatrixIndex;
D3DXMATRIX mStack;
//スキンメッシュの描画
if (pMeshContainer->pSkinInfo != NULL)
{
//ボーンテーブルからバッファの先頭アドレスを取得
pBoneCombination = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneBuffer->GetBufferPointer());
//dwPrevBoneIDにUINT_MAXの値(0xffffffff)を格納
dwPrevBoneID = UINT_MAX;
//スキニング計算
for (i = 0; i < pMeshContainer->dwBoneNum; i++)
{
dwBlendMatrixNum = 0;
//影響している行列数取得
for (k = 0; k< pMeshContainer->dwWeight; k++)
{
//UINT_MAX(-1)
if (pBoneCombination[i].BoneId[k] != UINT_MAX)
{
//現在影響を受けているボーンの数
dwBlendMatrixNum = k;
}
}
//ジオメトリブレンディングを使用するために行列の個数を指定
pDevice->SetRenderState(D3DRS_VERTEXBLEND, dwBlendMatrixNum);
//影響している行列の検索
for (k = 0; k < pMeshContainer->dwWeight; k++)
{
//iMatrixIndexに1度の呼び出しで描画出来る各ボーンを識別する値を格納
//( このBoneID配列の長さはメッシュの種類によって異なる
//( インデックスなしであれば = 頂点ごとの重み であり
// インデックスありであれば = ボーン行列パレットのエントリ数)
//現在のボーン(i番目)からみてk番目のボーンid
iMatrixIndex = pBoneCombination[i].BoneId[k];
//行列の情報があれば
if (iMatrixIndex != UINT_MAX)
{
//mStackにオフセット行列*ボーン行列を格納
mStack = pMeshContainer->pBoneOffsetMatrices[iMatrixIndex] * (*pMeshContainer->ppBoneMatrix[iMatrixIndex]);
//行列スタックに格納
pDevice->SetTransform(D3DTS_WORLDMATRIX(k), &mStack);
}
}
D3DMATERIAL9 TmpMat = pMeshContainer->pMaterials[pBoneCombination[i].AttribId].MatD3D;
TmpMat.Emissive.a = TmpMat.Diffuse.a = TmpMat.Ambient.a = 1.0f;
pDevice->SetMaterial(&TmpMat);
pDevice->SetTexture(0, pMeshContainer->ppTextures[pBoneCombination[i].AttribId]);
//dwPrevBoneIDに属性テーブルの識別子を格納
dwPrevBoneID = pBoneCombination[i].AttribId;
//メッシュの描画
pMeshContainer->MeshData.pMesh->DrawSubset(i);
}
}
//通常メッシュの場合
else
{
MessageBox(NULL, "スキンメッシュXファイルの描画に失敗しました。", NULL, MB_OK);
exit(EOF);
}
}
//
//VOID DrawFrame(LPDIRECT3DDEVICE9 pDevice,LPD3DXFRAME pFrameBase)
//フレームをレンダリングする。
VOID CSkinMesh::DrawFrame(LPDIRECT3DDEVICE9 pDevice, LPD3DXFRAME pFrameBase)
{
MYFRAME* pFrame = (MYFRAME*)pFrameBase;
MYMESHCONTAINER* pMeshContainer = (MYMESHCONTAINER*)pFrame->pMeshContainer;
while (pMeshContainer != NULL)
{
//SHADER_KIND a = GetpShader()->GetShaderKind();
////シェーダを使用しているのなら専用の描画関数に飛ばす
//if( GetpShader() != NULL && GetpShader()->GetShaderKind() == SHADER_KIND_LAMBERT ){
// ShaderDraw( pDevice, ControlNum, pMeshContainer, pFrame ); 
//}else{
RenderMeshContainer(pDevice, pMeshContainer, pFrame);
// }
//次のメッシュコンテナへアクティブを移す
pMeshContainer = (MYMESHCONTAINER*)pMeshContainer->pNextMeshContainer;
}
if (pFrame->pFrameSibling != NULL)
{
DrawFrame(pDevice, pFrame->pFrameSibling);
}
if (pFrame->pFrameFirstChild != NULL)
{
DrawFrame(pDevice, pFrame->pFrameFirstChild);
}
}
//
//VOID UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
//フレーム内のメッシュ毎にワールド変換行列を更新する
VOID CSkinMesh::UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
{
MYFRAME *pFrame = (MYFRAME*)pFrameBase;
if (pParentMatrix != NULL)
{
//CombinedTransformationMatrixに最終行列を格納
D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);
}
else
{
//CombinedTransformationMatrixに最終行列を格納
pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;
}
if (pFrame->pFrameSibling != NULL)
{
UpdateFrameMatrices(pFrame->pFrameSibling, pParentMatrix);
}
if (pFrame->pFrameFirstChild != NULL)
{
UpdateFrameMatrices(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);
}
}
//全ての階層フレームを解放する
VOID CSkinMesh::FreeAnim(LPD3DXFRAME pFrame)
{
if (pFrame->pMeshContainer != NULL){
m_cHierarchy.DestroyMeshContainer(pFrame->pMeshContainer);
pFrame->pMeshContainer = NULL;
}
if (pFrame->pFrameSibling != NULL)
FreeAnim(pFrame->pFrameSibling);
if (pFrame->pFrameFirstChild != NULL)
FreeAnim(pFrame->pFrameFirstChild);
}
HRESULT CSkinMesh::Init(LPDIRECT3DDEVICE9 lpD3DDevice, LPSTR pMeshPass){
CHAR TmpMeshPass[255];
strcpy_s(TmpMeshPass, sizeof(TmpMeshPass) - 1, pMeshPass);
// Xファイルからアニメーションメッシュを読み込み作成する
if (FAILED(
D3DXLoadMeshHierarchyFromX(TmpMeshPass, D3DXMESH_MANAGED, lpD3DDevice, &m_cHierarchy,
NULL,
&m_pFrameRoot,
&m_pAnimController)))
{
MessageBox(NULL, "Xファイルの読み込みに失敗しました", TmpMeshPass, MB_OK);
return E_FAIL;
}
//ボーン行列初期化
AllocateAllBoneMatrices(m_pFrameRoot, m_pFrameRoot);
//アニメーショントラックの取得
for (DWORD i = 0; i<m_pAnimController->GetNumAnimationSets(); i++)
{
//アニメーション取得
m_pAnimController->GetAnimationSet(i, &(m_pAnimSet[i]));
}
//すべてのフレーム参照変数の生成
m_FrameArray.clear();
m_IntoMeshFrameArray.clear();
CreateFrameArray(m_pFrameRoot);
//フレーム配列にオフセット情報作成
for (DWORD i = 0; i<m_IntoMeshFrameArray.size(); i++){
MYMESHCONTAINER* pMyMeshContainer = (MYMESHCONTAINER*)m_IntoMeshFrameArray[i]->pMeshContainer;
while (pMyMeshContainer){
//スキン情報
if (pMyMeshContainer->pSkinInfo){
DWORD cBones = pMyMeshContainer->pSkinInfo->GetNumBones();
for (DWORD iBone = 0; iBone<cBones; iBone++){
//フレーム内から同じ名前のフレームを検索
for (DWORD Idx = 0; Idx<m_FrameArray.size(); Idx++){
if (strcmp(pMyMeshContainer->pSkinInfo->GetBoneName(iBone), m_FrameArray[Idx]->Name) == 0){
pMyMeshContainer->BoneFrameArray.push_back(m_FrameArray[Idx]);
//Offset行列
m_FrameArray[Idx]->OffsetMat = *(pMyMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
m_FrameArray[Idx]->OffsetID = Idx;
break;
}
}
}
}
//次へ
pMyMeshContainer = (MYMESHCONTAINER *)pMyMeshContainer->pNextMeshContainer;
}
}
return S_OK;
}
//すべてのフレームポインタ格納処理関数
VOID CSkinMesh::CreateFrameArray(LPD3DXFRAME _pFrame){
if (_pFrame == NULL){ return; }
//フレームアドレス格納
MYFRAME* pMyFrame = (MYFRAME*)_pFrame;
m_FrameArray.push_back(pMyFrame);
//メッシュコンテナがある場合はIntoMeshFrameArrayにアドレスを格納
if (pMyFrame->pMeshContainer != NULL){
m_IntoMeshFrameArray.push_back(pMyFrame);
}
//子フレーム検索
if (pMyFrame->pFrameFirstChild != NULL){
CreateFrameArray(pMyFrame->pFrameFirstChild);
}
//兄弟フレーム検索
if (pMyFrame->pFrameSibling != NULL){
CreateFrameArray(pMyFrame->pFrameSibling);
}
}
//- 更新処理 -//
VOID CSkinMesh::Update(D3DXMATRIX _World){
//押しっぱなしによる連続切り替え防止
static bool PushFlg = false; //ここでは仮でフラグを使用するが、本来はメンバ変数などにする
//アニメーション変更チェック
if ((GetAsyncKeyState(VK_LEFT) & 0x8000) || (GetAsyncKeyState(VK_RIGHT) & 0x8000)){
if (GetAsyncKeyState(VK_LEFT) & 0x8000){
if (PushFlg == false){
int Num = GetAnimTrack() - 1;
if (Num < 0)Num = 0;
ChangeAnim(Num);
}
}
if (GetAsyncKeyState(VK_RIGHT) & 0x8000){
if (PushFlg == false){
int Num = GetAnimTrack() + 1;
if ((DWORD)Num > m_pAnimController->GetNumAnimationSets())Num = m_pAnimController->GetNumAnimationSets();
ChangeAnim(Num);
}
}
PushFlg = true;
}
else{
PushFlg = false;
}
//マトリックス行列反映
m_World = _World;
//アニメーション時間を更新
m_AnimeTime++;
}
//スキンメッシュの描画
VOID CSkinMesh::Draw(LPDIRECT3DDEVICE9 lpD3DDevice){
//現在のアニメーション番号を適応
m_pAnimController->SetTrackAnimationSet(0, m_pAnimSet[m_CurrentTrack]);
//0(再生中の)トラックからトラックデスクをセットする
m_pAnimController->SetTrackDesc(0, &(m_CurrentTrackDesc));
//アニメーション時間データの更新
m_pAnimController->AdvanceTime(m_AnimSpeed, NULL);
//アニメーションデータを更新
UpdateFrameMatrices(m_pFrameRoot, &m_World);
//アニメーション描画
DrawFrame(lpD3DDevice, m_pFrameRoot);
//0(再生中の)トラックから更新したトラックデスクを取得する
m_pAnimController->GetTrackDesc(0, &m_CurrentTrackDesc);
}
//オブジェクトのアニメーション変更( 変更するアニメーション番号 )
VOID CSkinMesh::ChangeAnim(DWORD _NewAnimNum){
//新規アニメーションに変更
m_CurrentTrack = _NewAnimNum;
//アニメーションタイムを初期化
m_AnimeTime = 0;
//アニメーションを最初の位置から再生させる
m_pAnimController->GetTrackDesc(0, &m_CurrentTrackDesc);
m_CurrentTrackDesc.Position = 0;
m_pAnimController->SetTrackDesc(0, &m_CurrentTrackDesc);
}
//対象のボーンを検索
MYFRAME* CSkinMesh::SearchBoneFrame(LPSTR _BoneName, D3DXFRAME* _pFrame){
MYFRAME* pFrame = (MYFRAME*)_pFrame;
if (strcmp(pFrame->Name, _BoneName) == 0){
return pFrame;
}
if (_pFrame->pFrameSibling != NULL)
{
pFrame = SearchBoneFrame(_BoneName, _pFrame->pFrameSibling);
if (pFrame != NULL){
return pFrame;
}
}
if (_pFrame->pFrameFirstChild != NULL)
{
pFrame = SearchBoneFrame(_BoneName, _pFrame->pFrameFirstChild);
if (pFrame != NULL){
return pFrame;
}
}
return NULL;
}
//ボーンのマトリックス取得( ボーンの名前 )
D3DXMATRIX CSkinMesh::GetBoneMatrix(LPSTR _BoneName){
MYFRAME* pFrame = SearchBoneFrame(_BoneName, m_pFrameRoot);
//ボーンが見つかれば
if (pFrame != NULL){
//ボーン行列を返す
return pFrame->CombinedTransformationMatrix;
}
//ボーンが見つからなければ
else{
//単位行列を返す
D3DXMATRIX TmpMatrix;
D3DXMatrixIdentity(&TmpMatrix);
return TmpMatrix;
}
}
//ボーンのマトリックスポインタ取得( ボーンの名前 )
D3DXMATRIX* CSkinMesh::GetpBoneMatrix(LPSTR _BoneName){
/////////////////////////////////////
//注意)RokDeBone用に設定(対象ボーンの一つ先の行列をとってくる)
MYFRAME* pFrame = SearchBoneFrame(_BoneName, m_pFrameRoot);
//ボーンが見つかれば
if (pFrame != NULL){
return &pFrame->CombinedTransformationMatrix;
}
//ボーンが見つからなければ
else{
//NULLを返す
return NULL;
}
}
//--- コールバック関数 ---//
LRESULT APIENTRY WndFunc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
//メイン関数
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,
  LPSTR lpszCmdParam,int nCmdshow)
{
// CLS_MAIN GameMain;
//-----------------------------------------------
//宣言
//-----------------------------------------------
//ウィンドウズ関係
MSG msg;
HWND hWnd;
WNDCLASS wc;
//ゲームループフラグ
BOOL g_LoopFlg;
LPDIRECT3D9 lpD3D = NULL; //Direct3Dインターフェイス
LPDIRECT3DDEVICE9 lpD3DDevice = NULL; //Direct3DDeviceインターフェイス
LPDIRECT3DSURFACE9 lpBackbuffer = NULL; //バックバッファ用
//フルスクリーンフラグ
BOOL FullScreenFlg = false;
D3DPRESENT_PARAMETERS d3dpp; //プレゼントパラメータ(ウィンドウモード)
int adapter;
//スキンメッシュ用クラス
CSkinMesh m_CSkinMesh;
//-----------------------------------------------
//初期化
//-----------------------------------------------
//ウィンドウズ作成
char szAppName[] = "SkinMeshApp";
//タイトル
LPSTR sGameTitle = "←か→でアニメーション変更";
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = WndFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
//-- 2重起動チェック --//
if (FindWindow(szAppName, sGameTitle) != NULL){
MessageBox(NULL, "すでに起動しています!", "2重起動確認", MB_OK);
exit(EOF);
}
RegisterClass(&wc);
hWnd = CreateWindowEx(
0,
szAppName,
sGameTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
SCRW, SCRH,
NULL, NULL, hInst,
NULL);
if (!hWnd) exit(-1);
ShowWindow(hWnd, nCmdshow);
UpdateWindow(hWnd);
SetFocus(hWnd);
if (FullScreenFlg){
ShowCursor(false);
}
else{
RECT rc = { 0, 0, SCRW, SCRH };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER);
}
g_LoopFlg = TRUE;
//---------------------DirectX Graphics関連-----------------------
// Direct3D オブジェクトを作成
SAFE_RELEASE(lpD3D);
lpD3D = Direct3DCreate9(D3D_SDK_VERSION);
// オブジェクトの作成失敗
if (!lpD3D)
{
// オブジェクト作成失敗メッセージを表示
MessageBox(hWnd, "Direct3D の作成に失敗しました。", "ERROR", MB_OK | MB_ICONSTOP);
// 終了する
exit(-1);
}
// 使用するアダプタ番号
adapter = 0;
// ウインドウの作成が完了したので、Direct3D を初期化する
ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
// Direct3D 初期化パラメータの設定
if (FullScreenFlg)
{
// フルスクリーン
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
}
else
{
// ウインドウタイプ
D3DDISPLAYMODE Disp;
// 現在の画面モードを取得
lpD3D->GetAdapterDisplayMode(adapter, &Disp);
// 現在の画面モードを使用
d3dpp.BackBufferFormat = Disp.Format;
}
// 表示領域サイズの設定
d3dpp.BackBufferWidth = SCRW;
d3dpp.BackBufferHeight = SCRH;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
if (!FullScreenFlg)
{
// ウインドウモード
d3dpp.Windowed = 1;
}
// Z バッファの自動作成
d3dpp.EnableAutoDepthStencil = 1;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
//バックバッファをロック可能にする(GetDCも可能になる)
d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
SAFE_RELEASE(lpD3DDevice);
// デバイスの作成 - T&L HAL
if (FAILED(lpD3D->CreateDevice(adapter, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &d3dpp, &lpD3DDevice)))
{
// 失敗したので HAL で試行
if (FAILED(lpD3D->CreateDevice(adapter, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &d3dpp, &lpD3DDevice)))
{
// 失敗したので REF で試行
if (FAILED(lpD3D->CreateDevice(adapter, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &d3dpp, &lpD3DDevice)))
{
// 結局失敗した
MessageBox(hWnd, "DirectX9が初期化できません。\n未対応のパソコンと思われます。", "ERROR", MB_OK | MB_ICONSTOP);
lpD3D->Release();
// 終了する
exit(-1);
}
}
}
// レンダリング・ステートを設定
// Z バッファ有効化->前後関係の計算を正確にしてくれる
lpD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
lpD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
// アルファブレンディング有効化
lpD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
// アルファブレンディング方法を設定
lpD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
lpD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
// レンダリング時のアルファ値の計算方法の設定
lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
// テクスチャの色を使用
lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
// 頂点の色を使用
lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
// レンダリング時の色の計算方法の設定
lpD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
//裏面カリング(ポリゴンの裏面を描画しない)
lpD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// フィルタ設定
lpD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
lpD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
lpD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
//ライトを無効にする
lpD3DDevice->LightEnable(0, FALSE);
// ライトの計算処理をしない
lpD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
//マテリアルの設定
lpD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
//単位行列
D3DXMATRIX mIden;
D3DXMatrixIdentity(&mIden);
//データをロードさせる
m_CSkinMesh.Init(lpD3DDevice, "EnemyBoss01.x");
//ゲームループ
while (g_LoopFlg){
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage(&msg, NULL, 0, 0))break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
//-----------------------------------------------
//更新処理
//-----------------------------------------------
m_CSkinMesh.Update(mIden);
//-----------------------------------------------
//カメラ更新
//-----------------------------------------------
D3DXMATRIX m_View, m_Proj;
// 視点行列の設定
D3DXMatrixLookAtLH(&m_View,
&D3DXVECTOR3(0, 2, -5), //カメラの位置
&D3DXVECTOR3(0, 0, 0), //カメラが見る方向
&D3DXVECTOR3(0, 1, 0) //カメラの傾き(カメラから見た上方向ベクトル)
);
// 投影行列の設定
D3DXMatrixPerspectiveFovLH(&m_Proj, D3DXToRadian(60), (float)SCRW / (float)SCRH, 0.1f, 1200.f);
//行列設定
lpD3DDevice->SetTransform(D3DTS_VIEW, &m_View);
lpD3DDevice->SetTransform(D3DTS_PROJECTION, &m_Proj);
//バックバッファ&Zバッファのクリア
lpD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
//-----------------------------------------------
//描画開始
//-----------------------------------------------
if (lpD3DDevice->BeginScene() == S_OK){
//-----------------------------------------------
//ここから下に描画処理を書く
//-----------------------------------------------
//ゲームモード毎の描画処理
m_CSkinMesh.Draw(lpD3DDevice);
//描画終了
lpD3DDevice->EndScene();
}
//バックバッファ反映(フロントバッファとバックバッファを入れ替える)とデバイスロストチェック
if (lpD3DDevice->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
{
//再構築不可能であれば終了
if (lpD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST){
exit(EOF);
}
else{
//再構成失敗時には終了
if (lpD3DDevice->Reset(&d3dpp) != D3D_OK){
exit(EOF);
}
}
}
}
}
//解放
//メッシュオブジェクト管理クラス初期化管理
m_CSkinMesh.Release();
//バックバッファ解放
SAFE_RELEASE(lpBackbuffer);
// Direct3D オブジェクトを解放
SAFE_RELEASE(lpD3DDevice);
//ラストメモリリークチェック(あと解放するのはlpD3D1つだけなので、Release()後に1になっていればOK)
int a = lpD3D->AddRef();
a = lpD3D->Release();
// Direct3D オブジェクトを解放
SAFE_RELEASE(lpD3D);
timeEndPeriod(1);
return msg.wParam;
}
//--- コールバック関数 ---//
LRESULT APIENTRY WndFunc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg){
case WM_DESTROY:
//アプリケーション終了
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch(wParam){
case VK_ESCAPE:
break;
}
}
return DefWindowProc( hwnd, msg, wParam, lParam);
}
以上です
m_CSkinMesh.Init()の所で、アニメーションXファイルを指定します。
ちなみにXファイルにアニメーションをつける場合、
RokDeBone2というソフトでつけることが出来ます。
(http://ochakkolab.moo.jp/menu_RDB2.html)
PR

COMMENT

NAME
TITLE
MAIL(非公開)
URL
EMOJI
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
COMMENT
PASS(コメント編集に必須です)
SECRET
管理人のみ閲覧できます

ブログ内検索

最新コメント

[01/29 人面犬]
[10/01 8ch]
[09/12 uncle]
[09/10 某卒業生]
[06/07 uncle]

カレンダー

03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

テスト

Copyright ©  -- GESブログ --  All Rights Reserved
Design by CriCri / Photo by Geralt / powered by NINJA TOOLS / 忍者ブログ / [PR]