第三版本相较于前两个版本,添加了对 f 1//1 类型的支持(面 由点坐标和法向量组成),以及对mtl文件的读取。
准备工作,准备一个结构体来保存材质信息,然后由vector保存即可
struct mMaterial
{
float Ns; //shinness
float Ka[3];
float Kd[3];
float Ks[3];
string mTextureName;
GLuint mTextureId;
};
ka,kd,ks即相应的环境光,漫反射及镜面反射的参数,mTextureName保存着该材质的名称,由mtl文件读入,mTextureId即纹理贴图。
objModel类新加入一个成员变量mtlName,用于存储材质名称,方便从vector中查询材质信息。
class objModel :public List
{
public:
objModel() {}
void loadObjModel(const char*);
void print();
void objDraw();
private:
vector<Float3> normal, texcoord, position; //vector容器存储法线,纹理坐标及点的位置信息
vector<Face> face;
int vertnum;
int coordnum;
int nornum;
std::string mtlName;
};
修改loadObjModel函数,使其能够对mtl文件进行读写。定义一个全局变量来存储mtl信息,std::vector<mMaterial> mMtl;。
CreateTexture函数自己实现就好了。
void objModel::loadObjModel(const char* objFileName)
{
int nFileSize = 0;
unsigned char* fileContent = LoadFileContent(objFileName, nFileSize); //读取文件内容
if (fileContent == nullptr) //文件为空
{
return;
}
objModel* tempModel = new objModel;
stringstream ssFileContent((char*)fileContent); //流读取文件内容
string temp; //接受无关信息
char szoneLine[256]; //读取一行的数据
while (!ssFileContent.eof())
{
memset(szoneLine, 0, 256); // 每次循环初始化数组szoneLine
ssFileContent.getline(szoneLine, 256); //流读取一行
if (strlen(szoneLine) > 0) //该行不为空
{
if (szoneLine[0] == 'v') //v开头的数据
{
stringstream ssOneLine(szoneLine); //数据存储到流中 方便赋值
if (szoneLine[1] == 't') //纹理信息
{
ssOneLine >> temp; //接受标识符 vt
Float3 tempTexcoord;
ssOneLine >> tempTexcoord.Data[0] >> tempTexcoord.Data[1]; //数据存入临时变量中
tempModel->te