前回質問させていただいた後無事にコンパイルは通るようになったのですが、ファイルの読み込みの途中でアクセス違反が発生しその後
自分で原因を探ってみたのですが原因がわからず困っております。
記述1(メッシュクラスのヘッダ)
#ifndef MESH
#define MESH
#include <d3dx9.h>
#include <mmsystem.h>
#include <Dsound.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
using namespace std;
/// メッシュの頂点データ
struct Vertex {
D3DXVECTOR3 position; // 頂点位置
D3DXVECTOR3 normal; // 法線ベクトル
D3DXVECTOR2 texture; // テクスチャ座標
};
/// メッシュのポリゴンデータ
struct Face {
unsigned short indices[3]; // 3頂点のインデックス
unsigned long material_number; // 材料番号
};
// メッシュデータ一時保存用構造体。独自形式データは一度この構造体に格納し、Mesh::SetMesh()でMesh::pMeshにセットする。
struct MeshData {
vector<Vertex> vertices;
vector<Face> faces;
vector<D3DMATERIAL9> material;
vector<string> texture_filename;
};
/// メッシュのベース
class Mesh
{
protected:
LPDIRECT3DDEVICE9 pDevice; // Direct3Dデバイスオブジェクト
LPD3DXMESH pMesh; // メッシュ
D3DMATERIAL9* pMeshMaterials; // マテリアル配列
LPDIRECT3DTEXTURE9* pMeshTextures; // テクスチャ配列
DWORD dwNumMaterials; // マテリアル・テクスチャ配列の大きさ
void AddNormalVector(MeshData& meshData);// MeshDataに法線ベクトルを追加
void SetMesh(MeshData meshData); // MeshDataをpMeshにセット
public:
Mesh();
virtual ~Mesh();
virtual void InitMesh(LPDIRECT3DDEVICE9 pDevice);
virtual void Draw(D3DXVECTOR3 position, D3DXMATRIX rotation);
virtual LPD3DXMESH GetMesh();
virtual int GetNumMaterial();
};
/// Xファイルから読込んだメッシュ
class XFileMesh : public Mesh
{
public:
XFileMesh();
void InitXFile(LPCTSTR filename, LPDIRECT3DDEVICE9 pDevice);
};
/// PMDファイルから読込んだメッシュ
class PmdMesh : public Mesh
{
/// PMD構造体定義
#pragma pack(push,1) //アラインメント制御をオフ
struct PmdHeader
{
unsigned char magic[3];
float version;
unsigned char model_name[20];
unsigned char comment[256];
} pmdHeader;
struct PmdVertex
{
float pos[3];
float normal_vec[3];
float uv[2];
unsigned short bone_num[2];
unsigned char bone_weight;
unsigned char edge_flag;
};
struct PmdMaterial
{
float diffuse_color[3];
float alpha;
float specularity;
float specular_color[3];
float mirror_color[3];
unsigned char toon_index;
unsigned char edge_flag;
unsigned long face_vert_count; // この材料の面頂点数 → 材料番号iのポリゴン番号: pmdMaterial[i - 1].face_vert_count/3 ~ pmdMaterial[i].face_vert_count/3 - 1
char texture_file_name[20];
};
#pragma pack(pop)
void CopyMaterial(D3DMATERIAL9& material, PmdMaterial& pmdMaterial); // PmdMaterialからD3DMATERIAL9にデータをコピー
public:
PmdMesh();
void InitPmd(LPCTSTR filename, LPDIRECT3DDEVICE9 pDevice);
};
#endif
#include "Mesh.h"
#define SAFE_RELEASE(p){if(p) {(p)->Release(); (p) = NULL;}}
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
///// Meshクラス /////
Mesh::Mesh()
{}
Mesh::~Mesh()
{
SAFE_RELEASE(pMesh);
if (pMeshTextures) for (DWORD i = 0; i < dwNumMaterials; ++i) SAFE_RELEASE(pMeshTextures[i]);
SAFE_DELETE_ARRAY(pMeshTextures);
SAFE_DELETE_ARRAY(pMeshMaterials);
}
//------------------------------------------------------------------------------------------------------
void Mesh::InitMesh(LPDIRECT3DDEVICE9 pDev)
{
pDevice = pDev;
pMesh = 0;
pMeshTextures = 0;
pMeshMaterials = 0;
}
//------------------------------------------------------------------------------------------------------
void Mesh::AddNormalVector(MeshData& meshData)
{
for (unsigned int i = 0; i < meshData.vertices.size(); ++i) meshData.vertices[i].normal = D3DXVECTOR3(0, 0, 0);
for (unsigned int i = 0; i < meshData.faces.size(); ++i) {
D3DXVECTOR3 p[3];
for (unsigned int j = 0; j < 3; ++j) p[j] = meshData.vertices[meshData.faces[i].indices[j]].position;
D3DXPLANE plane;
D3DXPlaneFromPoints(&plane, &p[0], &p[1], &p[2]); // 抜き取りで確認する限り、planeは規格化されているっぽい
for (unsigned int j = 0; j < 3; ++j) meshData.vertices[meshData.faces[i].indices[j]].normal += D3DXVECTOR3(plane.a, plane.b, plane.c);
float l = D3DXVec3Length(&D3DXVECTOR3(plane.a, plane.b, plane.c));
}
for (unsigned int i = 0; i < meshData.vertices.size(); ++i) D3DXVec3Normalize(&meshData.vertices[i].normal, &meshData.vertices[i].normal);
}
//------------------------------------------------------------------------------------------------------
void Mesh::SetMesh(MeshData meshData)
{
D3DXCreateMeshFVF(meshData.faces.size(), meshData.vertices.size(), D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1, pDevice, &pMesh);
Vertex* vertexBuffer;
pMesh->LockVertexBuffer(0, (void**)&vertexBuffer);
for (unsigned int ii = 0; ii < meshData.vertices.size(); ii++)
{
vertexBuffer[ii].position = meshData.vertices[ii].position;
vertexBuffer[ii].normal = meshData.vertices[ii].normal;
vertexBuffer[ii].texture = meshData.vertices[ii].texture;
}
pMesh->UnlockVertexBuffer();
unsigned short* indexBuffer;
pMesh->LockIndexBuffer(0, (void**)&indexBuffer);
for (unsigned int ii = 0; ii < meshData.faces.size(); ii++)
{
for (unsigned int jj = 0; jj < 3; jj++)
{
indexBuffer[3*ii + jj] = meshData.faces[ii].indices[jj];
}
}
pMesh->UnlockIndexBuffer();
unsigned long* attributeBuffer;
pMesh->LockAttributeBuffer(0, &attributeBuffer);
for (unsigned int ii = 0; ii < meshData.faces.size(); ii++)
{
attributeBuffer[ii] = meshData.faces[ii].material_number;
}
pMesh->UnlockAttributeBuffer();
dwNumMaterials = meshData.material.size();
pMeshMaterials = new D3DMATERIAL9[dwNumMaterials];
pMeshTextures = new LPDIRECT3DTEXTURE9[dwNumMaterials];
for (DWORD ii = 0; ii < dwNumMaterials; ii++)
{
pMeshTextures[ii] = 0;
}
for (DWORD ii = 0; ii < dwNumMaterials; ii++)
{
pMeshMaterials[ii] = meshData.material[ii];
char tex_filename[256] = {0}; // UNICODE未対応テクスチャファイル名
TCHAR textureFilename[256] = {0}; // UNICODE/マルチバイト両対応テクスチャファイル名
if (strcpy_s(tex_filename, meshData.texture_filename[ii].c_str()))
{
throw TEXT("テクスチャの読み込みに失敗しました");
}
#ifdef UNICODE
if (strlen(tex_filename) > 0) MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, tex_filename, strlen(tex_filename), textureFilename, (sizeof textureFilename)/2);
#else
if (strlen(tex_filename) > 0) strcpy_s(textureFilename, tex_filename);
#endif
if (lstrlen(textureFilename) > 0) // UNICODE/マルチバイト両対応テクスチャファイル名からテクスチャを作成
if(FAILED(D3DXCreateTextureFromFileEx(pDevice, textureFilename, 0, 0, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, 0, 0, &pMeshTextures[ii]))) throw TEXT("テクスチャの読み込みに失敗しました");
}
}
//------------------------------------------------------------------------------------------------------
void Mesh::Draw(D3DXVECTOR3 position, D3DXMATRIX rotation)
{
D3DXMATRIX matWorld, matTrans;
D3DXMatrixTranslation(&matTrans, position.x, position.y, position.z);
matWorld = rotation*matTrans;
pDevice->SetTransform(D3DTS_WORLD, &matWorld);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); // ポリゴンのDiffuse色の透明度をテクスチャに反映させる
pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
for (DWORD ii = 0; ii < dwNumMaterials; ii++)
{
pDevice->SetMaterial(&pMeshMaterials[ii]);
pDevice->SetTexture(0, pMeshTextures[ii]);
pMesh->DrawSubset(ii);
}
}
//------------------------------------------------------------------------------------------------------
LPD3DXMESH Mesh::GetMesh()
{
return pMesh;
}
//------------------------------------------------------------------------------------------------------
int Mesh::GetNumMaterial()
{
return dwNumMaterials;
}
//------------------------------------------------------------------------------------------------------
XFileMesh::XFileMesh() : Mesh()
{}
//------------------------------------------------------------------------------------------------------
void XFileMesh::InitXFile(LPCTSTR filename, LPDIRECT3DDEVICE9 pDevice)
{
LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
if (FAILED( D3DXLoadMeshFromX(filename, D3DXMESH_SYSTEMMEM, pDevice, NULL, &pD3DXMtrlBuffer, NULL, &dwNumMaterials, &pMesh))) throw TEXT("Xファイルの読み込みに失敗しました");
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
pMeshMaterials = new D3DMATERIAL9[dwNumMaterials];
pMeshTextures = new LPDIRECT3DTEXTURE9[dwNumMaterials];
for (DWORD i = 0; i < dwNumMaterials; ++i) {
pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
pMeshTextures[i] = 0;
TCHAR textureFilename[256] = {0};
#ifdef UNICODE
if (d3dxMaterials[i].pTextureFilename) MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED, d3dxMaterials[i].pTextureFilename, strlen(d3dxMaterials[i].pTextureFilename), textureFilename, (sizeof textureFilename)/2);
#else
if (d3dxMaterials[i].pTextureFilename) strcpy_s(textureFilename, d3dxMaterials[i].pTextureFilename);
#endif
if (textureFilename != NULL && lstrlen(textureFilename) > 0)
if(FAILED(D3DXCreateTextureFromFileEx(pDevice, textureFilename, 0, 0, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, 0, 0, &pMeshTextures[i]))) throw TEXT("テクスチャの読み込みに失敗しました");
}
pD3DXMtrlBuffer->Release();
}
/// PmdMeshクラス
PmdMesh::PmdMesh() : Mesh()
{}
void PmdMesh::InitPmd(LPCTSTR filename, LPDIRECT3DDEVICE9 pDev)
{
// PMDファイルからPMDデータを抽出
std::ifstream ifs(filename, ios::binary);
if (ifs.fail())
{
throw TEXT("ファイルがありません");
}
ifs.read((char*)&pmdHeader, sizeof(pmdHeader));
unsigned long numPmdVertex;
ifs.read((char*)&numPmdVertex, sizeof(numPmdVertex));
PmdVertex* pmdVertices = new PmdVertex[numPmdVertex];
ifs.read((char*)pmdVertices, sizeof(PmdVertex)*numPmdVertex);
unsigned long numPmdFace;
ifs.read((char*)&numPmdFace, sizeof(numPmdFace));
unsigned short *pmdFaces = new unsigned short[numPmdFace];
ifs.read((char*)pmdFaces, sizeof(unsigned short)*numPmdFace);
unsigned long numPmdMaterial;
ifs.read((char*)&numPmdMaterial, sizeof(numPmdMaterial));
PmdMaterial* pmdMaterial = new PmdMaterial[numPmdMaterial];
ifs.read((char*)pmdMaterial, sizeof(PmdMaterial)*numPmdMaterial);
// PMDデータからMeshDataにコピー
MeshData meshData;
for (unsigned int ii = 0; ii < numPmdVertex; ii++)
{
Vertex v;
v.position = D3DXVECTOR3(pmdVertices[ii].pos[0], pmdVertices[ii].pos[1], pmdVertices[ii].pos[2]);
v.position *= 0.1f; // 倍率
v.normal= D3DXVECTOR3(pmdVertices[ii].normal_vec[0], pmdVertices[ii].normal_vec[1], pmdVertices[ii].normal_vec[2]);
v.texture = D3DXVECTOR2(pmdVertices[ii].uv[0], pmdVertices[ii].uv[1]);
meshData.vertices.push_back(v);
}
delete pmdVertices;
Face f;
for (unsigned int ii = 0; ii < numPmdFace; ii++)
{
f.indices[ii % 3] = pmdFaces[ii];
if (ii % 3 == 2) meshData.faces.push_back(f);
}
delete pmdFaces;
D3DMATERIAL9 material = {0};
unsigned int jj = 0, material_end = 0;
for (unsigned int ii = 0; ii < numPmdMaterial; ii++)
{
CopyMaterial(material, pmdMaterial[ii]);
meshData.material.push_back(material);
char tex[21] = {0}; // ファイル名が20byteのときのために最後に0を追加
memcpy(tex, pmdMaterial[ii].texture_file_name, 20);
string s(tex);
s = s.substr(0, s.find("*")); // temp
meshData.texture_filename.push_back(s);
material_end += pmdMaterial[ii].face_vert_count;
for (; jj < material_end; jj++)
{
meshData.faces[jj / 3].material_number = ii;
}
}
delete pmdMaterial;
// MeshDataをグラフィックボードのメモリにセット
SetMesh(meshData);
}
void PmdMesh::CopyMaterial(D3DMATERIAL9& material, PmdMaterial& pmdMaterial)
{
material.Ambient.a = pmdMaterial.alpha;
material.Ambient.r = pmdMaterial.mirror_color[0];
material.Ambient.g = pmdMaterial.mirror_color[1];
material.Ambient.b = pmdMaterial.mirror_color[2];
material.Diffuse.a = pmdMaterial.alpha;
material.Diffuse.r = pmdMaterial.diffuse_color[0];
material.Diffuse.g = pmdMaterial.diffuse_color[1];
material.Diffuse.b = pmdMaterial.diffuse_color[2];
material.Power = pmdMaterial.specularity;
material.Specular.a = pmdMaterial.alpha;
material.Specular.r = pmdMaterial.specular_color[0];
material.Specular.g = pmdMaterial.specular_color[1];
material.Specular.b = pmdMaterial.specular_color[2];
}
#ifndef MYAPPLICATION
#define MYAPPLICATION
#include "DirectXFramework.h"
#include "Mesh.h"
#include "Camera.h"
#include "Light.h"
/// アプリケーションの統括クラス
class MyApplication
{
private:
DirectXFramework* directXFramework;
XFileMesh* island;
PmdMesh* miku;
Light* light;
Camera* camera;
public:
/// コンストラクタ
MyApplication();
/// デストラクタ
~MyApplication();
//初期化関数
void InitMyApplication(HWND hWnd);
/// 1/60秒毎に行なう処理
void Run();
};
#endif
#include "MyApplication.h"
MyApplication::MyApplication()
{}
MyApplication::~MyApplication(void)
{
delete camera;
delete light;
delete island;
delete miku;
delete directXFramework;
}
//------------------------------------------------------------------------------------
void MyApplication::InitMyApplication(HWND hWnd)
{
directXFramework = new DirectXFramework();
directXFramework->DirectXInit(hWnd);
LPDIRECT3DDEVICE9 pDevice = directXFramework->GetD3DDevice();
light = new Light();
light->LightInit(pDevice);
camera = new Camera();
camera->CameraInit(pDevice);
island = new XFileMesh();
island->InitXFile(TEXT("batokin_island5.x"), pDevice);
miku = new PmdMesh();
miku->InitPmd(TEXT("Miku/WhiteMiku.pmd"), pDevice);
}
//------------------------------------------------------------------------------------
void MyApplication::Run()
{
directXFramework->BeginScene(0x0F, 0xFF , 0xFF);// シーン開始
static int t;
const D3DXVECTOR3 position(0, 0, 0), zeroVector(0, 0, 0);
D3DXMATRIX rotation, unitMatrix;
D3DXMatrixRotationY(&rotation, 0.01f*(t++));
//D3DXMatrixRotationY(&rotation, D3DX_PI*0.85f);
D3DXMatrixIdentity(&unitMatrix);
// ライト
D3DXVECTOR3 direction(-1, -1, -1); // 光の方向
light->Illume(direction); // 光をあてる
// カメラ
D3DXVECTOR3 eyePoint = D3DXVECTOR3(-0.2f, 0.3f, 1.5f); // 視点
D3DXVECTOR3 lookAtPoint = D3DXVECTOR3(0, 0.4f, 0); // 注視点
//D3DXVECTOR3 eyePoint = D3DXVECTOR3(-0.2f, 1.5f, 1.0f); // 視点
//D3DXVECTOR3 lookAtPoint = D3DXVECTOR3(0, 1.7f, 0); // 注視点
camera->Look(eyePoint, lookAtPoint); // 見る
// 描画
island->Draw(zeroVector, unitMatrix);
miku->Draw(position, rotation);
directXFramework->EndScene(); // シーン終了
}
表示させようとしているモデルはLat式ミクVer2.31のLat式ミクVer2.31_Whiteエッジ無し専用.pmdです。
自分の使用している環境は
OS : Windows7
コンパイラ名 : VC++ 2008EE
DirectX SDK November2007
となります。
もしプログラム全体が必要でしたらファイルをアップいたします。
もし、明確にして欲しいところがありあましたらご指摘お願いします。
わかりにくい質問文で申し訳ありませんがよろしくお願いします。