Nanashi-soft○プログラマ専用○DirectX11開発○
class lwo2{読み込んだ LWOデータを,GPUに送り込みます
public:
#pragma pack(push,1) //アラインメント制御をオフる
//ヘッダー
//頂点リスト
unsigned long ptns_count;
struct t_pnts_data{
float pos[3];
};
t_pnts_data *pnts_data;
//面頂点リスト
unsigned long pols_count;
unsigned short *pols_index;
#pragma pack(pop) //アラインメント制御エンド
//コンストラクタ
lwo2(char *);
//デストラクタ
~lwo2();
//ビッグエンディアンを強引にリトルエンディアンにする関数w
unsigned long tyousei_ulong(unsigned long);
unsigned short tyousei_ushort(unsigned short);
};
#include "lwo2.h"
#include <windows.h>
#include <stdio.h>
//コンストラクタ
lwo2::lwo2(char *filename)
{
FILE *hFP;
int FILESIZE;
unsigned char *data = NULL;
int fp = 0; //現在の読み込み位置
hFP = fopen(filename, "rb");
if(hFP != 0){
//ファイルサイズ取得
fpos_t fsize;
fseek(hFP, 0L, SEEK_END);
fgetpos(hFP, &fsize);
fseek(hFP, 0L, SEEK_SET);
FILESIZE = (unsigned int)fsize;
//ファイル読み込み
data = new unsigned char[FILESIZE];
fread(&data[0], 1, FILESIZE, hFP);
fclose(hFP);
while(fp < FILESIZE){
//タグ読み込み
char ID4[4];
memcpy(&ID4, &data[fp], sizeof(ID4));
fp += sizeof(ID4);
if((ID4[0] == 'F' && ID4[1] == 'O' && ID4[2] == 'R' && ID4[3] == 'M')) {
// == FORM ==
//全体のデータサイズが入っているが捨てる(ぉ
fp += sizeof(DWORD);
}else if((ID4[0] == 'G' && ID4[1] == 'S' && ID4[2] == 0x00 && ID4[3] == 0x00)){
// == GS (?) ==
//サブチャンクのデータサイズは2byte
WORD datalen;
memcpy(&datalen, &data[fp], sizeof(WORD));
fp += sizeof(WORD);
datalen = tyousei_ushort(datalen);
//サイズ分データ取得
// $char gs_data[datalen];
fp += datalen;
//サイズが奇数の時は偶数になるように埋められている
if(datalen % 2){
fp++;;
}
}else if((ID4[0] == 'L' && ID4[1] == 'W' && ID4[2] == 'O' && ID4[3] == '2')){
// == LWO2 ==
//サブチャンクのデータサイズは2byte
fp += sizeof(WORD);
//中身は全体をさすっぽい
}else if((ID4[0] == 'P' && ID4[1] == 'N' && ID4[2] == 'T' && ID4[3] == 'S')){
// == PNTS (頂点リスト) ==
//デフォルトデータサイズは4byte
DWORD datalen;
memcpy(&datalen, &data[fp], sizeof(DWORD));
fp += sizeof(DWORD);
datalen = tyousei_ulong(datalen); //エンディアン調整
//頂点データ数
ptns_count = datalen / 4 / 3;
//頂点データ読み込み
pnts_data = new t_pnts_data[ptns_count];
//リトルエンディアンにしながら1データずつ読み込む
//ややこしいからポインタぶん回すよ('-'*)
float *pdata = (float*)pnts_data;
for(int i=0; i < ptns_count * 3; i++){
unsigned long work;
memcpy(&work, &data[fp], 4);
fp += 4;
work = tyousei_ulong(work); //エンディアン調整
memcpy(pdata, &work, 4);
pdata++;
}
}else if((ID4[0] == 'P' && ID4[1] == 'O' && ID4[2] == 'L' && ID4[3] == 'S')){
// == POLS (フェイス) ==
//デフォルトデータサイズは4byte
DWORD datalen;
memcpy(&datalen, &data[fp], sizeof(DWORD));
fp += sizeof(DWORD);
datalen = tyousei_ulong(datalen); //エンディアン調整
//面頂点数
pols_count = datalen / 2;
//なんかFACEと文字列が入っている
fp += 4;
//フェイスデータ取得(2byte)
pols_index = new unsigned short[datalen];
//リトルエンディアンにしながら1データずつ読み込む
for(int i=0; i < pols_count; i++){
unsigned short work;
memcpy(&work, &data[fp], 2);
fp += 2;
work = tyousei_ushort(work); //エンディアン調整
pols_index[i] = work;
}
}else{
// == UNKNOWN ==
//未定義チャンク(スキップ処理)
//デフォルトデータサイズは4byte
DWORD datalen;
memcpy(&datalen, &data[fp], sizeof(DWORD));
fp += sizeof(DWORD);
datalen = tyousei_ulong(datalen); //エンディアン調整
//サイズ分データスキップ
fp += datalen;
//サイズが奇数の時は偶数になるように埋められている
if(datalen % 2){
fp++;
}
}
}
}else{
MessageBoxW(NULL, L"fopen", L"Err", MB_ICONSTOP);
}
delete [] data;
}
//デストラクタ
lwo2::~lwo2(void)
{
}
//ビッグエンディアンを強引にリトルエンディアンにする関数w
unsigned long lwo2::tyousei_ulong(unsigned long in){
unsigned char in_char[4];
unsigned char out_char[4];
unsigned long out;
//unsigned long変数を無理やり unsigned char変数にぶちこんで
memcpy(&in_char[0], &in, 4);
//バイト調整する
out_char[0] = in_char[3];
out_char[1] = in_char[2];
out_char[2] = in_char[1];
out_char[3] = in_char[0];
//また無理やり,unsigned char型を unsigned long型に戻す
memcpy(&out, &out_char[0], 4);
return out;
}
unsigned short lwo2::tyousei_ushort(unsigned short in){
unsigned char in_char[2];
unsigned char out_char[2];
unsigned short out;
//unsigned short変数を無理やり unsigned char変数にぶちこんで
memcpy(&in_char[0], &in, 2);
//バイト調整する
out_char[0] = in_char[1];
out_char[1] = in_char[0];
//また無理やり,unsigned char型を unsigned short型に戻す
memcpy(&out, &out_char[0], 2);
return out;
}
// =====================================================これを実行すると,頂点データのみ描画されます
//lwo2クラスを生成する。その際にコンストラクタにファイル名を教える
const int LWO2_DATA_MAX = 1;
char *lwo2file[] = {
"Patch ofGrass1.lwo",
};
//モデルデータ分を予めGPUにセットする
for(int mdcnt=0; mdcnt < LWO2_DATA_MAX; mdcnt++){
lwo2 *modeldata = new lwo2(lwo2file[mdcnt]);
// == LWO2データ読み込みここから ==
//頂点データを取得
int TYOUTEN = modeldata->ptns_count;
Vertex3D *hVectorData;
hVectorData = new Vertex3D[TYOUTEN];
for(int i=0; i < TYOUTEN; i++){
hVectorData[i].pos[0] = modeldata->pnts_data[i].pos[0];
hVectorData[i].pos[1] = modeldata->pnts_data[i].pos[1];
hVectorData[i].pos[2] = modeldata->pnts_data[i].pos[2];
hVectorData[i].col[0] = 1.0f;
hVectorData[i].col[1] = 1.0f;
hVectorData[i].col[2] = 1.0f;
hVectorData[i].col[3] = 1.0f;
hVectorData[i].tex[0] = 0.0f;
hVectorData[i].tex[1] = 0.0f;
hVectorData[i].nor[0] = 0.0f;
hVectorData[i].nor[1] = 0.0f;
hVectorData[i].nor[2] = 0.0f;
hVectorData[i].tan[0] = 0.0f;
hVectorData[i].tan[1] = 0.0f;
hVectorData[i].tan[2] = 0.0f;
hVectorData[i].bin[0] = 0.0f;
hVectorData[i].bin[1] = 0.0f;
hVectorData[i].bin[2] = 0.0f;
}
//インデックスデータを取得
int INDEXSU = modeldata->pols_count;
//LWO2のインデックスデータは,[頂点数,1,2,3]になっている
//このシステムでは頂点数は3しかサポートしていない
unsigned short *hIndexData;
hIndexData = new unsigned short[INDEXSU / 4 * 3];
int cnt = 0;
for(int i=0; i < INDEXSU; i++){
//頂点数の部分は捨てる
if(0 < (i % 4)){
hIndexData[cnt] = modeldata->pols_index[i];
cnt++;
}
}
// == LWO2データ読み込みここまで ==
//モデルデータクラスの状況取得
//次のオブジェ番号を取得
int hObjNum = hModelData->getObjMax();
//次の頂点バッファー番号を取得
int hVctBufNum = hModelData->getMaxVctBufNum();
//次のインデックスバッファー番号を取得
int hIdxBufNum = hModelData->getMaxIdxBufNum();
// == GPUにデータ送信 ==
//頂点バッファ作成
D3D11_BUFFER_DESC hBufferDesc;
hBufferDesc.ByteWidth = sizeof(Vertex3D) * TYOUTEN;
hBufferDesc.Usage = D3D11_USAGE_DEFAULT;
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
hBufferDesc.CPUAccessFlags = 0;
hBufferDesc.MiscFlags = 0;
hBufferDesc.StructureByteStride = sizeof(float);
D3D11_SUBRESOURCE_DATA hSubResourceData;
hSubResourceData.pSysMem = hVectorData;
hSubResourceData.SysMemPitch = 0;
hSubResourceData.SysMemSlicePitch = 0;
if(FAILED(hpDevice->CreateBuffer(&hBufferDesc, &hSubResourceData, &hModelData->vctBuf[hVctBufNum]))){
MessageBoxW(hWnd, L"CreateBuffer", L"Err", MB_ICONSTOP);
goto End;
}
//インデックスバッファ作成
hBufferDesc.ByteWidth = sizeof(unsigned short) * INDEXSU;
hBufferDesc.Usage = D3D11_USAGE_DEFAULT;
hBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
hBufferDesc.CPUAccessFlags = 0;
hBufferDesc.MiscFlags = 0;
hBufferDesc.StructureByteStride = sizeof(unsigned short);
hSubResourceData.pSysMem = hIndexData;
hSubResourceData.SysMemPitch = 0;
hSubResourceData.SysMemSlicePitch = 0;
if(FAILED(hpDevice->CreateBuffer(&hBufferDesc, &hSubResourceData, &hModelData->idxBuf[hIdxBufNum]))){
MessageBoxW(hWnd, L"CreateBuffer Index", L"Err", MB_ICONSTOP);
goto End;
}
// == モデルデータクラスにデータをセット ==
int hIdxStaWork = 0;
//モデルデータ保管を生成(LWO2は全体)
int hModelId = hModelData->newData();
//同一モデルとしてオブジェ番号をセット
hModelData->setObjNum(hModelId, hObjNum);
//頂点データはモデルデータ単位で同じ
hModelData->setVctCnt(hModelId, TYOUTEN);
hModelData->setVctBufNum(hModelId, hVctBufNum);
//インデックス数を取得(LWO2は全部)
int hIdxCnt = modeldata->pols_count;
//インデックス情報をセット
hModelData->setIdxCnt(hModelId, hIdxCnt);
hModelData->setIdxSta(hModelId, hIdxStaWork);
hModelData->setIdxBufNum(hModelId, hIdxBufNum);
//仮実装
hModelData->setPsNum(hModelId, 0); //PSにマテリアル描画をセット
//描画フラグをするに設定
hModelData->setDrawYes(hModelId, 1);
hVectorData = NULL;
}
// =====================================================