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.8 KiB
189 lines
4.8 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];
|
|
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);
|
|
}
|