Asset Loading
来源:互联网 发布:小米网络音响app连不上 编辑:程序博客网 时间:2024/03/28 18:04
Asset Loading
有了Model,Mesh以及ModelMaterial类的声明之后,就可以讨论如何把assets文件加载到这些类中。这正是要使用Open Asset Import Library的地方。Loading Models
在我们自己编写的模型系统中,Model类是顶层接口,与些类似,在Open Asset Import Library中,aiScene类是用于数据导入的顶层接口。通过调用Importer::ReadFile()函数可以构造一个aiScene对象,aiScene对象的成员变量提供了模型的meshes和model materials接口。所有assets文件的加载都在Model的构造函数中处理,并分别使用Mesh和ModelMaterial类加载模型的meshes和model materials。列表15.4列出了Model类的实现代码。列表15.4 The Model.cpp File
#include "Model.h"#include "Game.h"#include "GameException.h"#include "Mesh.h"#include "ModelMaterial.h"#include <assimp/Importer.hpp>#include <assimp/scene.h>#include <assimp/postprocess.h>namespace Library{ Model::Model(Game& game, const std::string& filename, bool flipUVs) : mGame(game), mMeshes(), mMaterials() { Assimp::Importer importer; UINT flags = aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_FlipWindingOrder; if (flipUVs) { flags |= aiProcess_FlipUVs; } const aiScene* scene = importer.ReadFile(filename, flags); if (scene == nullptr) { throw GameException(importer.GetErrorString()); } if (scene->HasMaterials()) { for (UINT i = 0; i < scene->mNumMaterials; i++) { mMaterials.push_back(new ModelMaterial(*this, scene->mMaterials[i])); } } if (scene->HasMeshes()) { for (UINT i = 0; i < scene->mNumMeshes; i++) { ModelMaterial* material = (mMaterials.size() > i ? mMaterials.at(i) : nullptr); Mesh* mesh = new Mesh(*this, *(scene->mMeshes[i])); mMeshes.push_back(mesh); } } } Model::~Model() { for (Mesh* mesh : mMeshes) { delete mesh; } for (ModelMaterial* material : mMaterials) { delete material; } } Game& Model::GetGame() { return mGame; } bool Model::HasMeshes() const { return (mMeshes.size() > 0); } bool Model::HasMaterials() const { return (mMaterials.size() > 0); } const std::vector<Mesh*>& Model::Meshes() const { return mMeshes; } const std::vector<ModelMaterial*>& Model::Materials() const { return mMaterials; }}
如果要开发一个编译期的content管线功能,需要把Model类的构造函数中加载assets文件所得到的数据保存为一个中间文件中。然后就可以增加一个构造函数用于反系列化这些中间文件,并在Library工程中去掉对Open Asset Import Library的调用。另外,纹理的垂直坐标翻转操作也应该在编译期的content管线中执行,并从运行时加载模型的代码中移除。
Loading Meshes
加载一个mesh需要读取真实的vertices,indices,normals等数据,因此Mesh类比Model类包含更多的代码。但是,加载的方式是一样的。在Open Asset Import Library中,aiMesh结构体的成员变量提供了所有需要示数据,只需要简单地把这些数据转移到Mesh类中。列表15.5中列出了Mesh类的部分实现代码,没有列出的部分都是只有一行代码的函数,用于访问私有成员变量。在本书的配套网站上可以找到完整的实现代码。列表15.5 The Mesh.cpp File (Abbreviated)
#include "Mesh.h"#include "Model.h"#include "Game.h"#include "GameException.h"#include <assimp/scene.h>namespace Library{Mesh::Mesh(Model& model, aiMesh& mesh): mModel(model), mMaterial(nullptr), mName(mesh.mName.C_Str()), mVertices(), mNormals(), mTangents(), mBiNormals(), mTextureCoordinates(), mVertexColors(), mFaceCount(0), mIndices(){mMaterial = mModel.Materials().at(mesh.mMaterialIndex);// VerticesmVertices.reserve(mesh.mNumVertices);for (UINT i = 0; i < mesh.mNumVertices; i++){mVertices.push_back(XMFLOAT3(reinterpret_cast<const float*>(&mesh.mVertices[i])));}// Normalsif (mesh.HasNormals()){mNormals.reserve(mesh.mNumVertices);for (UINT i = 0; i < mesh.mNumVertices; i++){mNormals.push_back(XMFLOAT3(reinterpret_cast<const float*>(&mesh.mNormals[i])));}}// Tangents and Binormalsif (mesh.HasTangentsAndBitangents()){mTangents.reserve(mesh.mNumVertices);mBiNormals.reserve(mesh.mNumVertices);for (UINT i = 0; i < mesh.mNumVertices; i++){mTangents.push_back(XMFLOAT3(reinterpret_cast<const float*>(&mesh.mTangents[i])));mBiNormals.push_back(XMFLOAT3(reinterpret_cast<const float*>(&mesh.mBitangents[i])));}}// Texture CoordinatesUINT uvChannelCount = mesh.GetNumUVChannels();for (UINT i = 0; i < uvChannelCount; i++){std::vector<XMFLOAT3>* textureCoordinates = new std::vector<XMFLOAT3>();textureCoordinates->reserve(mesh.mNumVertices);mTextureCoordinates.push_back(textureCoordinates);aiVector3D* aiTextureCoordinates = mesh.mTextureCoords[i];for (UINT j = 0; j < mesh.mNumVertices; j++){textureCoordinates->push_back(XMFLOAT3(reinterpret_cast<const float*>(&aiTextureCoordinates[j])));}}// Vertex ColorsUINT colorChannelCount = mesh.GetNumColorChannels();for (UINT i = 0; i < colorChannelCount; i++){std::vector<XMFLOAT4>* vertexColors = new std::vector<XMFLOAT4>();vertexColors->reserve(mesh.mNumVertices);mVertexColors.push_back(vertexColors);aiColor4D* aiVertexColors = mesh.mColors[i];for (UINT j = 0; j < mesh.mNumVertices; j++){vertexColors->push_back(XMFLOAT4(reinterpret_cast<const float*>(&aiVertexColors[j])));}}// Faces (note: could pre-reserve if we limit primitive types)if (mesh.HasFaces()){mFaceCount = mesh.mNumFaces;for (UINT i = 0; i < mFaceCount; i++){aiFace* face = &mesh.mFaces[i];for (UINT j = 0; j < face->mNumIndices; j++){mIndices.push_back(face->mIndices[j]);}}}}Mesh::~Mesh(){for (std::vector<XMFLOAT3>* textureCoordinates : mTextureCoordinates){delete textureCoordinates;}for (std::vector<XMFLOAT4>* vertexColors : mVertexColors){delete vertexColors;}}void Mesh::CreateIndexBuffer(ID3D11Buffer** indexBuffer){assert(indexBuffer != nullptr);D3D11_BUFFER_DESC indexBufferDesc;ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));indexBufferDesc.ByteWidth = sizeof(UINT) * mIndices.size();indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;D3D11_SUBRESOURCE_DATA indexSubResourceData;ZeroMemory(&indexSubResourceData, sizeof(indexSubResourceData));indexSubResourceData.pSysMem = &mIndices[0];if (FAILED(mModel.GetGame().Direct3DDevice()->CreateBuffer(&indexBufferDesc, &indexSubResourceData, indexBuffer))){throw GameException("ID3D11Device::CreateBuffer() failed.");}}}
完全理解Mesh构造函数中的具体语法可能需要仔细的阅读代码,但是大致的执行过程是非常简单的。只需要遍历aiMesh结构体中的变量,并把变量所表示的数据赋值给Mesh类的成员变量中即可。打开Open Asset Import Library的网站,查看aiMesh类的具体信息。
最后简单看一下Mesh::CrateIndexBuffer()函数,该函数的实现看起来非常熟悉,与在cube示例中创建一个index buffer的代码完全相同。把这段代码添加到Mesh类中是为了代码复用。
Loading Model Materials
在列表15.6中列出了ModelMaterial类的实现代码,这是在创建一个示例程序使用模型系统之前的最后一部分代码。在ModelMaterial的构造函数中,通过使用Open Asset Import Library的aiMaterial结构体对象获取材质数据。在该实现代码中,唯一需要考虑的是Open Asset Import Library中的纹理类型与ModelMaterial中自定义的TextureType枚举值一一对应。同样地,这么做也是为了避免在应用程序的其他地方调用Open Asset Import Library。在ModelMatrial::InitializeTextureTypeMappings()函数中初始化了静态成员变量sTextureTypeMappings。列表15.6 The ModelMaterial.cpp File
#include "ModelMaterial.h"#include "GameException.h"#include "Utility.h"#include <assimp/scene.h>namespace Library{ std::map<TextureType, UINT> ModelMaterial::sTextureTypeMappings; ModelMaterial::ModelMaterial(Model& model) : mModel(model), mTextures() { InitializeTextureTypeMappings(); } ModelMaterial::ModelMaterial(Model& model, aiMaterial* material) : mModel(model), mTextures() { InitializeTextureTypeMappings(); aiString name; material->Get(AI_MATKEY_NAME, name); mName = name.C_Str(); for (TextureType textureType = (TextureType)0; textureType < TextureTypeEnd; textureType = (TextureType)(textureType + 1)) { aiTextureType mappedTextureType = (aiTextureType)sTextureTypeMappings[textureType]; UINT textureCount = material->GetTextureCount(mappedTextureType); if (textureCount > 0) { std::vector<std::wstring>* textures = new std::vector<std::wstring>(); mTextures.insert(std::pair<TextureType, std::vector<std::wstring>*>(textureType, textures)); textures->reserve(textureCount); for (UINT textureIndex = 0; textureIndex < textureCount; textureIndex++) { aiString path; if (material->GetTexture(mappedTextureType, textureIndex, &path) == AI_SUCCESS) { std::wstring wPath; Utility::ToWideString(path.C_Str(), wPath); textures->push_back(wPath); } } } } } ModelMaterial::~ModelMaterial() { for (std::pair<TextureType, std::vector<std::wstring>*> textures : mTextures) { DeleteObject(textures.second); } } Model& ModelMaterial::GetModel() { return mModel; } const std::string& ModelMaterial::Name() const { return mName; } const std::map<TextureType, std::vector<std::wstring>*> ModelMaterial::Textures() const { return mTextures; } void ModelMaterial::InitializeTextureTypeMappings() { if (sTextureTypeMappings.size() != TextureTypeEnd) { sTextureTypeMappings[TextureTypeDifffuse] = aiTextureType_DIFFUSE; sTextureTypeMappings[TextureTypeSpecularMap] = aiTextureType_SPECULAR; sTextureTypeMappings[TextureTypeAmbient] = aiTextureType_AMBIENT; sTextureTypeMappings[TextureTypeHeightmap] = aiTextureType_HEIGHT; sTextureTypeMappings[TextureTypeNormalMap] = aiTextureType_NORMALS; sTextureTypeMappings[TextureTypeSpecularPowerMap] = aiTextureType_SHININESS; sTextureTypeMappings[TextureTypeDisplacementMap] = aiTextureType_DISPLACEMENT; sTextureTypeMappings[TextureTypeLightMap] = aiTextureType_LIGHTMAP; } }}
在列表15.6中缺少了ModleMatrial类的部分实现代码,具体的是一组用于匹配shader变量的键值对。在当前阶段故意没有实现添加这些代码,是因为还没有介绍一个完整的材质系统。在下章将会开发一个完整的材质系统。
0 0
- Asset Loading
- UE4 Asynchronous Asset Loading
- Loading asset data with source data from an external source
- Uncaught ReferenceError while loading asset file on android 4.4
- asset
- asset
- Loading.....
- loading...
- Loading
- loading
- loading
- loading
- Loading...
- Loading
- loading
- loading
- loading
- Loading...
- fastjson序列化 将Null设置为空字符串等问题
- Windows下安装Redis及开启php扩展
- ExpandableListView的使用,可展开的ListView
- poj 1654 area 简单多边形面积(简单题)
- Java 集合类(容器)
- Asset Loading
- js注意事项04
- 深入理解Windows X64调试
- Java 之 线程的生命周期(三)
- 【FJ 2013】继任者
- 杭电OJ 1015 Safecracker
- Bootstrap-折叠方法
- mini2440 linux 串口驱动异常问题
- 逻辑回归.感知器算法