#include "model.h" #include "utils.h" Model::Model() { mShader = new Shader; } void Model::Init(const char*modelPath) { int nFileSize = 0; fileContent = LoadFileContent(modelPath, nFileSize); if (fileContent == nullptr) { printf("load obj model fail\n"); exit; } //解析模型数据 parseModel(); delete fileContent; //填充VertexBuffer createVertexBuffer(); } void Model::parseModel() { std::stringstream ssObjFile((char*)fileContent); char szOneLine[256]; while (!ssObjFile.eof()) { memset(szOneLine, 0, 256); ssObjFile.getline(szOneLine, 256); if (strlen(szOneLine) > 0) { parseLine(szOneLine); } } } void Model::parseLine(const char * line) { if (line[0] == 'v') { if (line[1] == 't') { parseTexcoord(line); } else if (line[1] == 'n') { parseNormal(line); } else { parsePosition(line); } } if (line[0] == 'f') { parseFace(line); } } void Model::parseTexcoord(const char * line) { glm::float3 f3 = parseFloat(line); texcoord.push_back(f3); } void Model::parseNormal(const char * line) { glm::float3 f3 = parseFloat(line); normal.push_back(f3); } void Model::parsePosition(const char * line) { glm::float3 f3 = parseFloat(line); position.push_back(f3); } glm::float3 Model::parseFloat(const char * line) { std::string t; std::stringstream ssOneLine(line); ssOneLine >> t; glm::float3 f3; ssOneLine >> f3.x; ssOneLine >> f3.y; if (line[1] == 't') { f3.z = 0; } else { ssOneLine >> f3.z; } return f3; } void Model::parseFace(const char * line) { std::string temp; std::stringstream ssOneLine(line); ssOneLine >> temp; //去除 f std::string pointerIndexStr; for (int i = 0; i < 3; i++) { //解析每一个点 ssOneLine >> pointerIndexStr; VertexIndex vi = parseVertexIndex(pointerIndexStr); //把点加到vertices int index = addVertices(vi); } } VertexIndex Model::parseVertexIndex(std::string pointStr) { size_t pos = pointStr.find_first_of('/'); std::string positionIndexStr = pointStr.substr(0, pos); size_t pos2 = pointStr.find_first_of('/', pos + 1); std::string texcoordIndexStr = pointStr.substr(pos + 1, pos2 - pos - 1); std::string normalIndexStr = pointStr.substr(pos2 + 1, pointStr.length() - pos2 - 1); VertexIndex ret; ret.position = atoi(positionIndexStr.c_str()) - 1; ret.texcoord = atoi(texcoordIndexStr.c_str()) - 1; ret.normal = atoi(normalIndexStr.c_str()) - 1; return ret; } int Model::addVertices(VertexIndex indexes) { int currentIndex = -1; size_t currentVerticeCount = vertices.size(); currentIndex = vertices.size(); vertices.push_back(indexes); return currentIndex; } void Model::createVertexBuffer() { int vertexCount = (int)vertices.size(); mVertexBuffer = new VertexBuffer; glm::float3 t; mVertexBuffer->SetSize(vertexCount); for (int i = 0; i < vertexCount; ++i) { t = position[vertices[i].position]; mVertexBuffer->SetPosition(i, t[0], t[1], t[2]); t = texcoord[vertices[i].texcoord]; mVertexBuffer->SetTexcoord(i, t[0], t[1]); t = normal[vertices[i].normal]; mVertexBuffer->SetNormal(i, t[0], t[1], t[2]); } } void Model::Draw(glm::mat4 & viewMatrix, glm::mat4 projectionMatrix, float x, float y, float z) { mShader->SetVec4("U_CameraPos", x, y, z, 1.0); glEnable(GL_DEPTH_TEST); mVertexBuffer->Bind(); if (mShader->mProgram > 0) { mShader->Bind(glm::value_ptr(mModelMatrix), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatrix)); glm::mat4 it = glm::inverseTranspose(mModelMatrix); GLint itLocation = glGetUniformLocation(mShader->mProgram, "IT_ModelMatrix"); glUniformMatrix4fv(itLocation, 1, GL_FALSE, glm::value_ptr(it)); itLocation = glGetUniformLocation(mShader->mProgram, "LightViewMatrix"); if (itLocation >= 0 && mLightViewMatrix != nullptr) { glUniformMatrix4fv(itLocation, 1, GL_FALSE, mLightViewMatrix); } itLocation = glGetUniformLocation(mShader->mProgram, "LightProjectionMatrix"); if (itLocation >= 0 && mLightProjectionMatrix != nullptr) { glUniformMatrix4fv(itLocation, 1, GL_FALSE, mLightProjectionMatrix); } } glDrawArrays(GL_TRIANGLES, 0, mVertexBuffer->mVertexCount); mVertexBuffer->Unbind(); } void Model::SetPosition(float x, float y, float z) { mModelMatrix = glm::translate(x, y, z); } void Model::SetAmbientMaterial(float r, float g, float b, float a) { mShader->SetVec4("U_AmbientMaterial", r, g, b, a); } void Model::SetDiffuseMaterial(float r, float g, float b, float a) { mShader->SetVec4("U_DiffuseMaterial", r, g, b, a); } void Model::SetSpecularMaterial(float r, float g, float b, float a) { mShader->SetVec4("U_SpecularMaterial", r, g, b, a); } void Model::SetTexture(const char*imagePath) { mShader->SetTexture("U_Texture", imagePath); }