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地址.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值