VS2010+DX9+Assimp使用(1)

1.VS2010+DX9情况下加载模型

1.1 总体介绍

网格
绘制3D模型的方法

  • 使用顶点缓存和索引缓存进行绘制
    DrawPrimitive()、DrawIndexedPrimitive()
  • 使用网络进行绘制
    1.绘制几何体: D3DXCreateBox、D3DXCreateSphere、…
    2.手工创建网格: D3DXCreateMeshFVF
    3.使用Xfile文件创建网格

1.2主要介绍XFile 网格文件

在这里插入图片描述
相应代码如下
加载 XFile 文件
加载 XFile 材质和纹理


#include "d3dUtility.h"
//第1步,引入头文件
#include <fstream>
#include <vector>

//
// Globals
//

IDirect3DDevice9* Device = 0; 

const int Width  = 640;
const int Height = 480;
//第2步 网格文件指针,材质,贴图
ID3DXMesh* Mesh = 0;
std::vector<D3DMATERIAL9> Mtrls(0);
std::vector<IDirect3DTexture9*> Textures(0);

//
// Framework functions
//
bool Setup()
{
//第3步 网格文件指针,材质,贴图
	HRESULT hr = 0;

	ID3DXBuffer* adjBuffer = 0;
	ID3DXBuffer* mtrlBuffer = 0;
	DWORD numMtrls = 0;

	hr = D3DXLoadMeshFromX(
		"bigship1.x",
		//"1.x",
		//"car.x",
		D3DXMESH_MANAGED,//指定网格文件存入,托管的内存里
		Device,
		&adjBuffer,//保存每个三角形的邻接信息
		&mtrlBuffer,//保存材质
		0,
		&numMtrls,//保存材质数量
		&Mesh);
	if(FAILED(hr))
	{
		::MessageBox(0,"D3DXLoadMeshFromX() - Failed",0,0);
		return false;
	}
	//检查x文件中有没有材质部分,
	if(mtrlBuffer != 0 && numMtrls != 0)
	{
		D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();//有材质部分,就把它们提取出来
		for(int i=0; i<numMtrls; i++)
		{
			mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
			Mtrls.push_back(mtrls[i].MatD3D);
			if(mtrls[i].pTextureFilename != 0)
			{
				IDirect3DTexture9* tex = 0;
				D3DXCreateTextureFromFile(Device, mtrls[i].pTextureFilename, &tex);
				Textures.push_back(tex);
			}else{
				Textures.push_back(0);
			}
		}
	}
	d3d::Release<ID3DXBuffer*>(mtrlBuffer);

	hr = Mesh->OptimizeInplace( //使用OptimizeInplace()进行网格优化后,Mesh 的几何信息将按照属性进行排序,这样各个子集的顶点/索引将组成连续的块
		D3DXMESHOPT_ATTRSORT |
		D3DXMESHOPT_COMPACT |
		D3DXMESHOPT_VERTEXCACHE,
		(DWORD*)adjBuffer->GetBufferPointer(),
		0,0,0);
	d3d::Release<ID3DXBuffer*>(adjBuffer);

	if(FAILED(hr))
	{
		::MessageBox(0,"OptimizeInplace() - FAILED",0,0);
		return false;
	}
	

	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);4步 设置灯光
	D3DXVECTOR3 dir(1.0f, -1.0f, 1.0f);
	D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f);
	D3DLIGHT9 light = d3d::InitDirectionalLight(&dir, &col);

	Device->SetLight(0,&light);
	Device->LightEnable(0,true);
	Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, true);
	
	//
	// Set camera.
	//

	D3DXVECTOR3 pos(4.0f, 4.f, -13.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMATRIX V;
	D3DXMatrixLookAtLH(
		&V,
		&pos,
		&target,
		&up);

	Device->SetTransform(D3DTS_VIEW, &V);

	//
	// Set projection matrix.
	//

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
			&proj,
			D3DX_PI * 0.5f, // 90 - degree
			(float)Width / (float)Height,
			1.0f,
			1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{

}

bool Display(float timeDelta)
{
	if( Device )
	{
		//
		// Update: Rotate the cube.
		//

		D3DXMATRIX xRot;
		D3DXMatrixRotationX(&xRot, D3DX_PI * 0.2f);

		static float y = 0.0f;
		D3DXMATRIX yRot;
		D3DXMatrixRotationY(&yRot, y);
		y += timeDelta;

		if( y >= 6.28f )
			y = 0.0f;

		D3DXMATRIX World = xRot * yRot;

		Device->SetTransform(D3DTS_WORLD, &World);

		//
		// Render
		//

		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();5步 绘制材质和网格子集
		for(int i=0; i<Mtrls.size(); i++)
		{
			Device->SetMaterial(&Mtrls[i]);
			Device->SetTexture(0, Textures[i]);
			Mesh->DrawSubset(i);
		}

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
		
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
				   HINSTANCE prevInstance, 
				   PSTR cmdLine,
				   int showCmd)
{
	if(!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}
		
	if(!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}

	d3d::EnterMsgLoop( Display );

	Cleanup();

	Device->Release();

	return 0;
}



1.3 XFile 网格文件来源

3D 建模工具 ——》 XFile
Maya
3DS Max

例如:网上找到fbx文件利用3dmax转换为x文件

1.把fbx文件在3dmax2009 32位打开(文件-导入)
在这里插入图片描述
2.把fbx文件在3dmax2009 32位另存为1.max
在这里插入图片描述
3.为了能把max文件导出为.x文件,需要给3dsmax添加插件,把这个文件解压,拷贝到
在这里插入图片描述

在这里插入图片描述
4.把max文件导出为.x文件
在这里插入图片描述
5.导出的文件,拷贝到项目文件文件夹下
在这里插入图片描述
在这里插入图片描述
6.代码相应位置X文件替换
在这里插入图片描述

源代码

#pragma comment(lib,"d3d9.lib")	
#pragma comment(lib,"d3dx9.lib")	
#pragma comment(lib,"winmm.lib")	

#include "d3dUtility.h"
#include <fstream>
#include <vector>

//
// Globals
//

IDirect3DDevice9* Device = 0; 

const int Width  = 640;
const int Height = 480;
//第1步 网格文件指针,材质,贴图
//ID3DXMesh* Mesh = 0;
//std::vector<D3DMATERIAL9> Mtrls(0);
//std::vector<IDirect3DTexture9*> Textures(0);
LPD3DXMESH          Mesh     = NULL; // 网格对象
D3DMATERIAL9*       Materials    = NULL; // 网格的材质信息
LPDIRECT3DTEXTURE9* Textures     = NULL; // 网格的纹理信息
DWORD               NumMtrls    = 0;    // 材质的数目
//
// Framework functions
//
bool Setup()
{
	HRESULT hr = 0;

	ID3DXBuffer* adjBuffer = 0;//保存每个三角形的邻接信息
	ID3DXBuffer* mtrlBuffer = 0;//保存材质
	//DWORD numMtrls = 0;//保存材质数量

	hr = D3DXLoadMeshFromX(
		L"1.x",
		//"bigship1.x",
		//"car.x",
		D3DXMESH_MANAGED,//指定网格文件存入,托管的内存里
		Device,
		&adjBuffer,//保存每个三角形的邻接信息
		&mtrlBuffer,//保存材质
		0,
		&NumMtrls,//保存材质数量
		&Mesh);
	if(FAILED(hr))
	{
		::MessageBox(0,L"D3DXLoadMeshFromX() - Failed",0,0);
		return false;
	}
	检查x文件中有没有材质部分,
	//if(mtrlBuffer != 0 && numMtrls != 0)
	//{
	//	D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();//有材质部分,就把它们提取出来
	//	for(int i=0; i<numMtrls; i++)
	//	{
	//		mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
	//		Mtrls.push_back(mtrls[i].MatD3D);
	//		if(mtrls[i].pTextureFilename != 0)
	//		{
	//			IDirect3DTexture9* tex = 0;
	//			D3DXCreateTextureFromFile(Device, (LPCWSTR)mtrls[i].pTextureFilename, &tex);
	//			Textures.push_back(tex);
	//		}else{
	//			Textures.push_back(0);
	//		}
	//	}
	//}
	//d3d::Release<ID3DXBuffer*>(mtrlBuffer);

	//hr = Mesh->OptimizeInplace(
	//	D3DXMESHOPT_ATTRSORT |
	//	D3DXMESHOPT_COMPACT |
	//	D3DXMESHOPT_VERTEXCACHE,
	//	(DWORD*)adjBuffer->GetBufferPointer(),
	//	0,0,0);
	//d3d::Release<ID3DXBuffer*>(adjBuffer);

	//if(FAILED(hr))
	//{
	//	::MessageBox(0,L"OptimizeInplace() - FAILED",0,0);
	//	return false;
	//}
	//

	//Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	//Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	//Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	// 读取材质和纹理数据
	D3DXMATERIAL *pMtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); //创建一个D3DXMATERIAL结构体用于读取材质和纹理信息
	Materials = new D3DMATERIAL9[NumMtrls];
	Textures  = new LPDIRECT3DTEXTURE9[NumMtrls];
 
	for (DWORD i=0; i<NumMtrls; i++) 
	{
		//获取材质,并设置一下环境光的颜色值
		Materials [i] = pMtrls[i].MatD3D;
		Materials [i].Ambient = Materials[i].Diffuse;
 
		//创建一下纹理对象
		Textures[i]  = NULL;
		D3DXCreateTextureFromFileA(Device, pMtrls[i].pTextureFilename, &Textures[i]);
	}
 
    d3d::Release<ID3DXBuffer*>(mtrlBuffer);

		hr = Mesh->OptimizeInplace( //使用OptimizeInplace()进行网格优化后,Mesh 的几何信息将按照属性进行排序,这样各个子集的顶点/索引将组成连续的块
		D3DXMESHOPT_ATTRSORT |
		D3DXMESHOPT_COMPACT |
		D3DXMESHOPT_VERTEXCACHE,
		(DWORD*)adjBuffer->GetBufferPointer(),
		0,0,0);
	d3d::Release<ID3DXBuffer*>(adjBuffer);
	//灯光
	D3DXVECTOR3 dir(1.0f, -1.0f, 1.0f);
	D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f);
	D3DLIGHT9 light = d3d::InitDirectionalLight(&dir, &col);

	Device->SetLight(0,&light);
	Device->LightEnable(0,true);
	Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, true);
	
	//
	// Set camera.
	//

	D3DXVECTOR3 pos(0.0f, 10.0f, -50.0f);
	D3DXVECTOR3 target(0.0f, 10.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMATRIX V;
	D3DXMatrixLookAtLH(
		&V,
		&pos,
		&target,
		&up);

	Device->SetTransform(D3DTS_VIEW, &V);

	//
	// Set projection matrix.
	//

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
			&proj,
			D3DX_PI * 0.5f, // 90 - degree
			(float)Width / (float)Height,
			1.0f,
			1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{

}

bool Display(float timeDelta)
{
	if( Device )
	{

		//
		// Render
		//

		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		for(int i=0; i<NumMtrls; i++)
		{
			Device->SetMaterial(&Materials[i]);
			Device->SetTexture(0, Textures[i]);
			Mesh->DrawSubset(i);
		}

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
		
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
				   HINSTANCE prevInstance, 
				   PSTR cmdLine,
				   int showCmd)
{
	if(!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
		return 0;
	}
		
	if(!Setup())
	{
		::MessageBox(0, L"Setup() - FAILED", 0, 0);
		return 0;
	}

	d3d::EnterMsgLoop( Display );

	Cleanup();

	Device->Release();

	return 0;
}


注意点:这个源码是在Unicode下编码,所以有了相应修改

1.4 通过assimp加载模型

Assimp是Open Asset Import Library(开放的资产导入库)的缩写。Assimp能够导入很多种不同的模型文件格式(并也能够导出部分的格式),它会将所有的模型数据加载至Assimp的通用数据结构中。当Assimp加载完模型之后,我们就能够从Assimp的数据结构中提取我们所需的所有数据了。由于Assimp的数据结构保持不变,不论导入的是什么种类的文件格式,它都能够将我们从这些不同的文件格式中抽象出来,用同一种方式访问我们需要的数据。

Assimp模型加载库下载、编译、配置全过程参考下面网址

https://blog.csdn.net/derbi123123/article/details/105783048/

assimp3.1.1源码下载后,在cmake下为vs2010编译好lib和dll文件

生成成功后在你的build文件的code文件夹下会有Release文件夹,里面有.dll文件与.lib文件:

最终的配置和链接
终于弄完了,最后只需要配置和链接:

  • 把上面文件夹中的lib文件拷贝到vs安装目录的lib文件夹下,并在解决方案中链接它(在链接器的输入中的附加依赖项中输入assimp.lib)。
    在这里插入图片描述

  • 且记得把Assimp的头文件也复制到你的include目录中(头文件可以在从Assimp中的include目录里找到)。
    在这里插入图片描述

  • 还有把dll文件放到C:\Windows\System32和C:\Windows\SysWOW64中即可。
    在这里插入图片描述
    在这里插入图片描述

2.VS2010+DX9情况下加载动画模型

posted @ 2022-04-06 23:52  szmtjs10  阅读(150)  评论(0编辑  收藏  举报