読み込み中のアクセス違反について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
north

読み込み中のアクセス違反について

#1

投稿記事 by north » 10年前

いつもお世話になっております。
前回質問させていただいた後無事にコンパイルは通るようになったのですが、ファイルの読み込みの途中でアクセス違反が発生しその後
自分で原因を探ってみたのですが原因がわからず困っております。

記述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
記述2(メッシュクラスのcppファイル)

コード:

#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];
}
記述3(MyApplication(実際に描画を行うクラス)のヘッダ)

コード:

#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
記述4(MyApplication(実際に描画を行うクラス)のcppファイル)

コード:

#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();			// シーン終了
}
アクセス違反が発生するのは記述2の44行目のところです。
表示させようとしているモデルはLat式ミクVer2.31のLat式ミクVer2.31_Whiteエッジ無し専用.pmdです。

自分の使用している環境は
OS : Windows7
コンパイラ名 : VC++ 2008EE
DirectX SDK November2007
となります。
もしプログラム全体が必要でしたらファイルをアップいたします。
もし、明確にして欲しいところがありあましたらご指摘お願いします。
わかりにくい質問文で申し訳ありませんがよろしくお願いします。

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

Re: 読み込み中のアクセス違反について

#2

投稿記事 by h2so5 » 10年前

D3DXCreateMeshFVF等が成功しているかどうか、関数の戻り値をよくチェックしてください。

north

Re: 読み込み中のアクセス違反について

#3

投稿記事 by north » 10年前

ありがとうございます。
アクセス違反の箇所でそれぞれの値をチェックして見たところpmdのヘッダー部分に関しては値が入っていたので読み込みに成功しているとは思うのですがそれ以降の
pDevice,pMesh,pMeshMaterials,pMeshTexturesのところで「エラーです。式を評価できません」となっておりました。
xファイル読み込み時も同じエラーが出たのですがその時はデータの置き場所を間違えていたために単純にデータが読み込めていないだけだったのですが
今回についてはなぜ、ヘッダの部分が読み込めていてほかの箇所が読み込めていないのか分からないです・・・・・・

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

Re: 読み込み中のアクセス違反について

#4

投稿記事 by h2so5 » 10年前

ポインターの中身ではなくて関数の戻り値を見てください。

north

Re: 読み込み中のアクセス違反について

#5

投稿記事 by north » 10年前

申し訳ございません。
関数の戻り値を確認しようとしているのですがDirectXの関数のようでどのように戻り値をチェックすればいいのかわからないです。
初歩的な質問で申し訳ありません。

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

Re: 読み込み中のアクセス違反について

#6

投稿記事 by h2so5 » 10年前

D3DXCreateMeshFVF 関数

コード:

D3DERR error = D3DXCreateMeshFVF(...);
if (error != D3D_OK) std::cerr << "error: D3DXCreateMeshFVF() failed" << std::endl;

north

Re: 読み込み中のアクセス違反について

#7

投稿記事 by north » 10年前

ありがとうございます。
ブレークを置いて進めてみたところ返り値を定義したerror変数に格納するところでアクセス違反が発生しました。
error変数の中は-858993460と本来なら入ってこない変数が入っておりました。
ただ、なぜこうなってしまうのかはまだわかっていないです。
自分の方でも時間を見つけて調べてはいるのですが・・・・・・

north

Re: 読み込み中のアクセス違反について

#8

投稿記事 by north » 10年前

読み込みのコードについてはここのサイトのMMDモデルを表示を参考にさせていただきました。
http://www2.ocn.ne.jp/~mhage/PIC_Trap/
サンプルコードではコンストラクタの中で複雑な処理を行ったりしていたのでそれではバグが発生した場合のことを考えると怖いので
Init関数を別に作成しそこで初期化の処理を行うようにしたのですがもしかしたらそれが原因かなと今考えています。

north

Re: 読み込み中のアクセス違反について

#9

投稿記事 by north » 10年前

申し訳ありません。
自己解決いたしました。
原因は親のMeshクラスの初期化を呼び出しておらずそこで初期化していた変数がすべて初期化されないまま継承先の初期化関数を呼び出していたのが原因でした。
ただ、このままだと毎回ファイルを読み込むたびに親の初期化関数も呼び出さないといけないので1度呼び出すだけで済む方法はないでしょうか?
また、サンプルについていたモデルは表示できたのですが、肝心のLat式ミクのモデルを呼び出す際に存在するテクスチャファイルがないといわれアクセス違反が起きてしまっています。
pmdデータはコードが置いてあるディレクトリに新たにモデル用のフォルダを作成しその中に必要なテクスチャとpmdファイルを入れてあります。
パスの指定は記述4の27行目で記述しているのですがDirectXではパスの通し方はこれでは間違っているのでしょうか?

north

Re: 読み込み中のアクセス違反について

#10

投稿記事 by north » 10年前

もしかしたら場所違いかもしれないですが下記の場所でも上記と同じ質問をさせていただきました。
http://hpcgi2.nifty.com/natupaji/bbs/pa ... ew&no=3310

旅路のきのこ

Re: 読み込み中のアクセス違反について

#11

投稿記事 by 旅路のきのこ » 10年前

何となく思ってみたんですが、pmdファイルのパスをMiku/WhiteMiku.pmdとするなら、テクスチャファイルを読み込むためのパスにもMiku/とつけなければならないのではないでしょうか?

north

Re: 読み込み中のアクセス違反について

#12

投稿記事 by north » 10年前

>旅路のきのこさん
DXライブラリを使用していた時はMiku/WhiteMiku.pmdという形で読み込めていたので今回もファイルと同じディレクトリにテクスチャ等のデータがあればいいのかなと思っておりました。
実際にやる場合は思いつくのはlstrcatを使って連結させる方法ですかね・・・・・
ただ、モデルをフォルダごとに分ける場合この方法だと何回もフォルダ名を変数に格納して連結させないといけないので他にもう少し効率の良い方法はありますでしょうか?

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

Re: 読み込み中のアクセス違反について

#13

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

どういう意味で効率的と言うかによりますね。
C++ですので、よりスマートに書くならsstreamなどを使うとか、専用のクラスを用意してリソース管理を一手に引き受けさせるとか開発するものに合わせた効率の良さがそれぞれあると思います。
そこを理解しているのはnorthさんだと思いますので、どういう効率性を望むか書かれてはどうでしょうか。
>lstrcat
C言語系なので避けたほうが良いかと思います。どうしても必要なら使っても良いですがバッファオーバーランのバグの危険が付きまといます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#14

投稿記事 by north » 10年前

〉softyaさん
ありがとうございます。
個人的にはDXライブラリーみたいにカレントディレクトリからの読み込みたいデータの相対パスを渡してそのパスをもとにPMDデータ及びそれに必要なテクスチャ関連のデータを読み込ませるようにしたいと思っております。
カレントディレクトリについてはチェックする関数を作成し、ソースコードが入っているフォルダまでは確認出来ております。
カレントディレクトリが取得出来ているのでこれを利用するようにするのもありなのかなと考えているのですが、どのようにテクスチャ側にパスを渡すようにしたらいいのか思い浮かばず悩んでおります。

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

Re: 読み込み中のアクセス違反について

#15

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

読み込みに必要なファイル名のリストをstd::listとしてとディレクトリパスをstringで受け渡せば良いかと思います。
pmdのテクスチャファイルの決定方法を知らないので、全部使う側が決めるとしてですが。
※ コードを見たらmemcpyとかC言語的な書き方がされているので、もっとC++に寄せたほうがシンプルになると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#16

投稿記事 by north » 10年前

ありがとうございます。Mesh.hとMesh.cppを以下のように編集してみました。
記述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:
	int error;
	LPDIRECT3DDEVICE9 pDevice;			// Direct3Dデバイスオブジェクト
	LPD3DXMESH pMesh;					// メッシュ
	D3DMATERIAL9* pMeshMaterials;		// マテリアル配列
	LPDIRECT3DTEXTURE9*	pMeshTextures;	// テクスチャ配列
	DWORD dwNumMaterials;				// マテリアル・テクスチャ配列の大きさ
	void AddNormalVector(MeshData& meshData);// MeshDataに法線ベクトルを追加
	void SetMesh(MeshData meshData, string Dir);	// MeshDataをpMeshにセット
public:
	Mesh();
	virtual ~Mesh();
	virtual void InitMesh(LPDIRECT3DDEVICE9 pDevice);
	virtual void Draw(D3DXVECTOR3 position, D3DXMATRIX rotation);
	virtual LPD3DXMESH GetMesh();
	virtual int GetNumMaterial();
	std::string getCurrentDirectory();
};

/// 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(string filename, LPDIRECT3DDEVICE9 pDevice);
};
#endif
記述2(メッシュクラスのcppファイル)

コード:

#include "Mesh.h"

#define ADD_DELETE_INDEX (1)
#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, string Dir) 
{
	error = D3DXCreateMeshFVF(meshData.faces.size(), meshData.vertices.size(), D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1, pDevice, &pMesh);
	if(error != D3D_OK) 
	{
		std::cerr << "error: D3DXCreateMeshFVF() failed" << std::endl;
	}

	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;
	}
	char tex_filename[256] = {0};		// UNICODE未対応テクスチャファイル名
	strcpy_s(tex_filename, Dir.c_str());
	int PathOffset = strlen(tex_filename); //コピー先のインデックスを記憶
	for (DWORD ii = 0; ii < dwNumMaterials; ii++)
	{ 
		std::string dir = getCurrentDirectory();	//カレントディレクトリのチェック
		pMeshMaterials[ii] = meshData.material[ii];
		//char tex_filename[256] = {0};		// UNICODE未対応テクスチャファイル名
		TCHAR textureFilename[256] = {0};	// UNICODE/マルチバイト両対応テクスチャファイル名
		if(strcpy_s(&tex_filename[PathOffset], 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; 
}
//カレントディレクトリチェック用関数
std::string Mesh::getCurrentDirectory()
{
	std::string dir;
    unsigned long len = GetCurrentDirectory(0, 0);  // GETTING PATH LENGTH
    if (len > 0) {
        try {
            LPTSTR buf = new TCHAR[len];
            GetCurrentDirectory(len, buf);
            dir = buf;
            delete[] buf;
        } catch (std::bad_alloc) {
            throw std::domain_error("getting current directory failed.");
        }
    }
    return dir;
}


//------------------------------------------------------------------------------------------------------
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(string filename, LPDIRECT3DDEVICE9 pDev)
{
	// PMDファイルからPMDデータを抽出
	std::ifstream ifs(filename.c_str(), 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;
	string::size_type index = filename.find("/");
	index += ADD_DELETE_INDEX;
	filename.erase(index);
	// MeshDataをグラフィックボードのメモリにセット
	SetMesh(meshData, filename);
}
//--------------------------------------------------------------------------------
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];
}
この方法はどうでしょうか?一応欲しいディレクトリ(Lat/)の部分が取得できているのは確認できました。
しかし記述2の91行目の部分if (strcpy_s(tex_filename, meshData.texture_filename[ii].c_str()))をコンパイル時に
if(strcpy_s(&tex_filename[PathOffset], meshData.texture_filename[ii].c_str()))に修正したら
コンパイルエラー「error C2660: 'strcpy_s' : 関数に 2 個の引数を指定できません。」と指摘されその原因がわからず困っております。
このように修正した理由はファイル名をコピーする処理でオフセット分ずらした位置からコピーしたかったからです。

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

Re: 読み込み中のアクセス違反について

#17

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

あちらこちらにC言語風のmemcpyなどが混在しているのが気になりますが、ご本人が効率が良いというのなら細かいことは言いません。C++で書けばスッキする気もしますが。

それとstrcpy_sは引数が3つ必要なはずです。バッファの長さ引数が足らないのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: 読み込み中のアクセス違反について

#18

投稿記事 by YuO » 10年前

north さんが書きました:

コード:

void PmdMesh::InitPmd(string filename, LPDIRECT3DDEVICE9 pDev)
{
/* 引用者省略 */
	PmdVertex* pmdVertices = new PmdVertex[numPmdVertex];
	ifs.read((char*)pmdVertices, sizeof(PmdVertex)*numPmdVertex);
/* 引用者省略 */
	delete pmdVertices;
/* 引用者省略 */
}
これはnewとdeleteの対応が正しくないですね。
本来なら,

コード:

std::unique_ptr<PmdVertex[]> pmdVertices(new PmdVertex[numPmdVertex]);
ifs.read((char*)&pmdVertices[0], sizeof(PmdVertex)*numPmdVertex);
のようにstd::unique_ptrを使うのがベストですが,VC++2008のようにstd::unique_ptrに対応していないならば

コード:

std::vector<PmdVertex> pmdVertices(numPmdVertex);
ifs.read((char*)&pmdVertices[0], sizeof(PmdVertex)*numPmdVertex);
のようにstd::vectorを使うべきです。
上記の標準ライブラリを使った自動メモリ管理を行わないにしても,せめて

コード:

	delete[] pmdVertices;
のような,配列のdeleteを使う必要があります。
オフトピック
C++ならRAII使おうよ,と思うのですけどね。
deleteがソースコードに出てくるなんて基本的に間違っているよ,と。

north

Re: 読み込み中のアクセス違反について

#19

投稿記事 by north » 10年前

ありがとうございます。
memcpyはやはり慣れているというのもあるので使っております。この関数1回でできるというのもあるので・・・・・
場合によっては使用できないというのもわかっているのでやはり統一した方がいいんですかね・・・・・
コンパイルエラーについては

コード:

if(strcpy_s(&tex_filename[PathOffset], sizeof(tex_filename), meshData.texture_filename[ii].c_str()))
に修正することでコンパイルエラーはとれました。
しかし、またアクセス違反が発生し今度は
「D3DX: Lat/: アクセスが拒否されました。」
と言われてしまいました。
Latフォルダのプロティから確認したのですがすべてフルコントロールできるようになっておりなぜこうなってしまっているのか困っております・・・・・・
何度も申し訳ありません。
今までDXライブラリに頼っていた部分もあるので今回を機にDirextX、3Dの読み込みについて勉強しなおす必要性を感じております。

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

Re: 読み込み中のアクセス違反について

#20

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

> 今までDXライブラリに頼っていた部分もあるので今回を機にDirextX、3Dの読み込みについて勉強しなおす必要性を感じております。

別にゲーム業界の就職とかなら今の時代は必須では無いですよ。ゲーム会社でライブラリ周りをやりたいとか、とにかく勉強したいならどんどんやってかまいませんが。

>「D3DX: Lat/: アクセスが拒否されました。」

DirectXは関係ないですよね。
親のフォルダのアクセス権もご確認ください。 少し訂正。

> memcpyはやはり慣れているというのもあるので使っております。この関数1回でできるというのもあるので・・・・・
> 場合によっては使用できないというのもわかっているのでやはり統一した方がいいんですかね・・・・・

目指すスタンスによって違うというか就職を考えるなら悪い癖なので直した方が良いと思います。
アマチュアならご自由にといった処でしょうか。ただ、バグの追跡が面倒になる可能性は高いです。

コード:

if(strcpy_s(&tex_filename[PathOffset], sizeof(tex_filename), meshData.texture_filename[ii].c_str()))
これサイズが間違っていますね。PathOffsetで許容サイズが可変するのでバッファーオーバーランのガードできていないです。
こういうミスがstrcpyやらmemcpyには付きまといます。

【補足】
YuOさんの回答にもコメントしてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#21

投稿記事 by north » 10年前

>YuOさん
ご指摘ありがとうございます。

コード:

delete[] pmdVertices;
と修正することで対応いたしました。
一応ゲーム業界でプログラマーとして働いていたのですが(去年入社の新卒だったのでコードはほとんど書かせてもらえませんでしたが)その時にあまりC++の標準ライブラリ
を使用していなかったのでそれの影響だと思います。
deleteを配列にしていなかったのは完全に自分のミスです。見落としておりました。
激務と上司が合わなかったので(後者は甘えかもしれませんが)体と精神を壊してしまい、休んでいた間のリハビリと再就職のための応募用作品を作成するのに最初はDXライブラリを使おうと思っていたのですが(新卒の会社はそれを使った作品で入社いたしました)DXライブラリを使うと不利になるみたいな話をネットで見たのとシェーダー3.0をつかいエフェクトを使ってみたかったので今回のような形をとることにしました。
ただ、あまりにも厳しそうだったらDXライブラリを使用した作品にしようかなとも考えております。

先ほどのアクセスできないと言われたのはもしかしたらPMD独自のスフィアテクスチャファイルが入っているのでそれが原因かもしくは
meshData.texture_filename[]のリストにテクスチャ名が入っていない箇所が4か所ほどあったのでそれが原因かなと考えておりますがどうでしょうか?

north

Re: 読み込み中のアクセス違反について

#22

投稿記事 by north » 10年前

> softya(ソフト屋) さん
ありがとうございます。親フォルダもチェックして見ましたがすべてフルコントロールできるようになっておりました。
ただ、Latフォルダが読み取り専用になっていましたがそれは関係ないですよね・・・・・・
ご指摘の通り確かにPathOffsetで許容サイズが変化してしまいますね・・・・・・
ここはchar tex_filename[256]で定義した256にしてしまうのがよろしいのでしょうか?

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

Re: 読み込み中のアクセス違反について

#23

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

north さんが書きました:> softya(ソフト屋) さん
ありがとうございます。親フォルダもチェックして見ましたがすべてフルコントロールできるようになっておりました。
ただ、Latフォルダが読み取り専用になっていましたがそれは関係ないですよね・・・・・・
ご指摘の通り確かにPathOffsetで許容サイズが変化してしまいますね・・・・・・
ここはchar tex_filename[256]で定義した256にしてしまうのがよろしいのでしょうか?
許容サイズはバッファオーバーランを防ぐためにあるので、sizeof(tex_filename)-PathOffsetが正しいです。
ただ、こんなことをいちいち書いていると面倒でミスが生じます。既存クラスの利用、クラスの作成を考えるべきです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#24

投稿記事 by north » 10年前

>softya(ソフト屋) さん
ありがとうございます。
確かにいちいちこうして書いていると書き忘れ等といったミスでバグが生じる可能性もありますね・・・・・
今は読み込みはXファイル、pmdのみですが今後対応するファイルを増やす可能性も考えると確かにクラスの利用を考えた方がいいかもしれないですね・・・・・・

アクセスできない原因ですがYuOさんへのコメントにも記述させていただきましたがもしかしたらPMD独自のスフィアテクスチャファイルが入っているのでそれが原因かもしくは
meshData.texture_filename[]のリストにテクスチャ名が入っていない箇所が4か所ほどあったのでそれが原因かなと考えております。
またYuOさんへのコメントにも記述させていただいた事情もありますが厳しそうでしたらせめてピクセルシェーダーの勉強も兼ねてDXライブラリの使用も視野に考えてみたいと思います。

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

Re: 読み込み中のアクセス違反について

#25

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

> meshData.texture_filename[]のリストにテクスチャ名が入っていない箇所が4か所ほどあったのでそれが原因かなと考えております。

それが原因かと思いますが、確認できませんでしょうか?
そういうデバッグ能力は結構重要です。

> またYuOさんへのコメントにも記述させていただいた事情もありますが厳しそうでしたらせめてピクセルシェーダーの勉強も兼ねてDXライブラリの使用も視野に考えてみたいと思います。

業界関係者としての再就職なるので、コードに対するチェックも厳しくなりそうですね。
ちゃんとエラーを予防できるコードや、適切なコメント、クラスの適切な利用など細かい所に気をつける必要がありますね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#26

投稿記事 by north » 10年前

>softya(ソフト屋)さん
先程、PMDEditerで確認したところ該当箇所のところにはテクスチャははりつけられていませんでした。
また、このモデルにはトゥーン系のテクスチャが使われており、もしかしたらこれのせいかもしれないです。
使用しているモデルは下記のものです。
http://swatmare.deviantart.com/art/MMD- ... -417888172
PMDEditerで確認したところ該当箇所のところにはテクスチャははりつけられていませんでしたが
この中の
・toon_g
・toon_hada
・toon_huku
・toon_kami
・toon_mahu
といったトゥーン系のbmpファイル使われており、それがリストには含まれておりませんでした。
トゥーン系のテクスチャももしかしてPMD独自の仕様なのでしょうか?
また、スフィアファイルも含まれており、自分がサンプルで読み込んだファイルにはそういったトゥーン系やスフィアファイルはありませんでした。
しかし解決方法が未だに思い浮かばないのでDXライブラリの使用も検討してみようと思います。
ただ、リンクでも貼ってありますようにDXライブラリの掲示板でも質問させていただいているのでそちらの回答も待ってみようかなと思います。

>業界関係者としての再就職なるので、コードに対するチェックも厳しくなりそうですね。
全くその通りだと思います。DXライブラリを使うにしろその辺はしっかりとコーディングしないといけないと思います。
会社でもコードをチェックしていただいた際によく指摘されておりました。
全く関係ない話なのですがDXライブラリを使うと不利になる・・・というのは実際どうなのでしょうか?
話しでは面倒くさいリソースの管理などをすべてDXライブラリが裏でやってくれているので実力を確認しにくいということでした。
会社ごとに独自のライブラリやエンジンがあるのは知っているのでその辺も含めてどうなのだろうと思ったことと、実際に新卒の際にDXライブラリを使用しましたと明記した上で
作品を提出し内定までいたりましたので本当なのかな?と思った部分もありますので・・・・・

north

Re: 読み込み中のアクセス違反について

#27

投稿記事 by north » 10年前

今までご回答してくださりありがとうございます。
単純なモデルについては読み込めるようになったのですが、やはりPMD独自のものが加わってくるとダメみたいです。
最初の問題については解決いたしましたので、一応解決とさせていただきたいと思います。
使い慣れたDXライブラリの使用も視野に入れてもう一度考えたいと思います。
本当にありがとうございました。

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

Re: 読み込み中のアクセス違反について

#28

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

ISLeさんからtwitterで突っ込まれたので念の為に書いておきますが、DXライブラリでシェーダ3.0の機能が使えるのはご存知ですよね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#29

投稿記事 by north » 10年前

> softya(ソフト屋)さん
3.0までいけるのですか!
DXライブラリの仕様を調べたときは2.0まで対応と書かれていましたのでてっきり2.0までだと思っておりました。
自分が見たのは古い情報だったのですか。
確かDXライブラリ付属のツールでfxファイルをコンパイルしvso,psoファイルに変換して読み込む仕様になっているというのはあっておりますでしょうか?
3.0が使えるとは知りませんでした。ありがとうございます。
3.0が使えるのでしたらDirectXにこだわる必要性がなくなりそうです。
元々3Dの描画の仕組み、HLSLの勉強もしたかったので最初は簡単なエフェクトから入り徐々に難しいのに挑戦していきたいと思います。
(ちょうどDirectXシェーダープログラミングという書籍にその辺りが書かれていたというのもありましたので)
ただ、やはりPMDのDirectXによる読み込みにつきましては疑問に残る部分がありますので場所違いかもしれないですがDXライブラリの掲示板でご質問させていただきたいと思います。
貴重な情報を本当にありがとうございます。

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

Re: 読み込み中のアクセス違反について

#30

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

3Dサンプルに3.0まで有るのが分かると思います。
「DXライブラリ置き場 サンプルプログラム3D編」
http://homepage2.nifty.com/natupaji/DxL ... am_3D.html
あとpmdの読み込みは公開されているDXライブラリのソースコードを参考にすると言う手もあります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

north

Re: 読み込み中のアクセス違反について

#31

投稿記事 by north » 10年前

>softya(ソフト屋)さん
本当ですね。
わざわざサンプル先のURLまでありがとうございます。
こちらのサンプルコードも参考にさせていただきたいと思います。
DXライブラリのソースコードは確かに見たことがなかったですね。
一度そちらダウンロードしてみてどこにそれらしきコードが記載されているか探してみたいと思います。
とりあえず3.0まで対応ということですのでDXライブラリを使用させていただき、再就職用の応募作品を作成したいと思います。
本当に貴重な情報をありがとうございます。

閉鎖

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