You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

189 lines
4.6 KiB

#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 - 1];
mVertexBuffer->SetPosition(i, t[0], t[1], t[2]);
t = texcoord[vertices[i].texcoord - 1];
mVertexBuffer->SetTexcoord(i, t[0], t[1]);
t = normal[vertices[i].normal - 1];
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);
}