天天看点

OpenGL模型加载三 opengl 加载模型Model

一、.h

#pragma once

#include

#include

#include

#include

#include <assimp/Importer.hpp>

#include <assimp/scene.h>

#include <assimp/postprocess.h>

#include “Mesh.h”

//#include “stb_image.h”

using std::vector;

using std::string;

using std::map;

class Model

{

public:

Model(string path);

~Model();

vector meshes;

string directory;

void Draw(Shader* shader);

private:

map<string, Texture> textures_loaded;

void loadModel(string path);

void processNode(aiNode* node, const aiScene* scene);

Mesh processMesh(aiMesh* mesh, const aiScene* scene);

vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName);

unsigned int TextureFromFile(string path, const string& directory);

};

二、.cpp

#include “Model.h”

#include “stb_image.h”

Model::Model(string path)

{

loadModel(path);

}

Model::~Model()

{

}

void Model::Draw(Shader* shader)

{

for (size_t i = 0; i < meshes.size(); i++)

{

meshes[i].Draw(shader);

}

}

void Model::loadModel(string path)

{

//read file via ASSIMP

Assimp::Importer importer;

const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);

//check for error

if (!scene || (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) || !scene->mRootNode) {

std::cout << “Assimp error:” << importer .GetErrorString()<< std::endl;

return;

}

directory = path.substr(0, path.find_last_of(’\’));

//std::cout << directory << std::endl;

processNode(scene->mRootNode, scene);

}

void Model::processNode(aiNode* node, const aiScene* scene)

{

std::cout << node->mName.data << std::endl;

for (unsigned int i = 0; i < node->mNumMeshes; i++)

{

aiMesh* curMesh = scene->mMeshes[node->mMeshes[i]];

meshes.push_back(processMesh(curMesh, scene));

}

for (unsigned int i = 0; i < node->mNumChildren; i++)

{

processNode(node->mChildren[i], scene);

}

}

Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)

{

//顶点信息

vector tmpVertices;

//索引信息

vector tmpIndices;

//贴图信息

vector tmpTexture;

for (size_t i = 0; i < mesh->mNumVertices; i++)
{
	//vertex
	Vertex vertex;
	//postion
	vertex.Position.x = mesh->mVertices[i].x;
	vertex.Position.y = mesh->mVertices[i].y;
	vertex.Position.z = mesh->mVertices[i].z;
	//normal
	vertex.Normal.x = mesh->mNormals[i].x;
	vertex.Normal.y = mesh->mNormals[i].y;
	vertex.Normal.z = mesh->mNormals[i].z;
	//texcoord
	if (mesh->mTextureCoords[0]) {
		vertex.TexCoord.x = mesh->mTextureCoords[0][i].x;
		vertex.TexCoord.y = mesh->mTextureCoords[0][i].y;
	}
	else {
		vertex.TexCoord = glm::vec2(0.0f, 0.0f);
	}
	// tangent
	vertex.Tangent.x = mesh->mTangents[i].x;
	vertex.Tangent.y = mesh->mTangents[i].y;
	vertex.Tangent.z = mesh->mTangents[i].z;
	// bitangent
	vertex.Bitangent.x = mesh->mBitangents[i].x;
	vertex.Bitangent.y = mesh->mBitangents[i].y;
	vertex.Bitangent.z = mesh->mBitangents[i].z;
	tmpVertices.push_back(vertex);
}

//indices
for (size_t i = 0; i < mesh->mNumFaces; i++)
{
	aiFace face = mesh->mFaces[i];

	for (size_t j = 0; j < face.mNumIndices; j++)
	{
		tmpIndices.push_back(face.mIndices[j]);
	}
}
//Texture Maps
	
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// 1. diffuse maps
vector<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
tmpTexture.insert(tmpTexture.end(), diffuseMaps.begin(), diffuseMaps.end());
// 2. specular maps
vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
tmpTexture.insert(tmpTexture.end(), specularMaps.begin(), specularMaps.end());
// 3. normal maps
std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
tmpTexture.insert(tmpTexture.end(), normalMaps.begin(), normalMaps.end());
// 4. height maps
std::vector<Texture> heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height");
tmpTexture.insert(tmpTexture.end(), heightMaps.begin(), heightMaps.end());



return Mesh(tmpVertices, tmpIndices, tmpTexture);
           

}

vector Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName)

{

vector textures;

for (size_t i = 0; i < mat->GetTextureCount(type); i++)

{

aiString str;

mat->GetTexture(type, i, &str);

if (textures_loaded.find(str.data) != textures_loaded.end()) {
		textures.push_back(textures_loaded[str.data]);
	}
	else {
		Texture texture;
		texture.id = TextureFromFile(str.C_Str(), directory);
		texture.type = typeName;
		texture.path = str.data;
		textures.push_back(texture);
		textures_loaded[str.data] = texture;
	}
}
return textures;
           

}

unsigned int Model::TextureFromFile(string path,const string& directory)

{

string filename = path;

filename = directory + ‘\’ + filename;

unsigned int textureID;
glGenTextures(1, &textureID);

int width, height, nrComponents;
unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
if (data)
{
	GLenum format;
	if (nrComponents == 1)
		format = GL_RED;
	else if (nrComponents == 3)
		format = GL_RGB;
	else if (nrComponents == 4)
		format = GL_RGBA;

	glBindTexture(GL_TEXTURE_2D, textureID);
	glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
	glGenerateMipmap(GL_TEXTURE_2D);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	stbi_image_free(data);
}
else
{
	std::cout << "Texture failed to load at path: " << path << std::endl;
	stbi_image_free(data);
}

return textureID;
           

}

三、Model类的作用

1、void Model::loadModel(string path);

加载指定路径Model对象,使用ASSIMP库的Importerd的ReadFile读取模型

2、void Model::processNode(aiNode* node, const aiScene* scene)

通过递归处理场景中的每个节点aiNode对象,每个节点包含多个aiMesh

3、Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)

读取aiMesh对象,解析aiMesh总的

方位数据 VBO数据(pos normal textcoord )

EBO数据 indices

贴图数据 texture

然后实现由aiMesh生成Mesh 对象

4、void Model::Draw(Shader* shader)

循环调用Mesh的Draw方法绘制出Model

代码Git地址.

上一篇: setbuf与fflush
下一篇: fscanf和fgets

继续阅读