Пример #1
0
//MTL PARSER INSPIRED FROM KIXOR.NET "objloader" (http://www.kixor.net/dev/objloader/)
bool ccMaterialSet::ParseMTL(QString path, const QString& filename, ccMaterialSet &materials, QStringList& errors)
{
	//open mtl file
	QFile file(path+QString('/')+filename);
	if (!file.open(QFile::ReadOnly))
	{
		errors << QString("Error reading file: %1").arg(filename);
		return false;
	}
	QTextStream stream(&file);

	QString currentLine = stream.readLine();
	unsigned currentLineIndex = 0;
	int currentMatIndex = -1;
	ccMaterial currentMaterial;
	while( !currentLine.isNull() )
	{
		++currentLineIndex;

		QStringList tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts);

		//skip comments & empty lines
		if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) )
		{
			currentLine = stream.readLine();
			continue;
		}

		//start material
		if (tokens.front() == "newmtl")
		{
			//push the precedent material
			if (currentMatIndex >= 0)
				materials.addMaterial(currentMaterial);

			++currentMatIndex;
			currentMaterial = ccMaterial();
			//materials.resize(materials.size()+1);
			// get the name
			currentMaterial.name = (tokens.size()>1 ? tokens[1] : "undefined");

		}
		else if (currentMatIndex>=0) //we already have a "current" material
		{
			//ambient
			if (tokens.front() == "Ka")
			{
				if (tokens.size() > 3)
				{
					currentMaterial.ambient[0] = tokens[1].toFloat();
					currentMaterial.ambient[1] = tokens[2].toFloat();
					currentMaterial.ambient[2] = tokens[3].toFloat();
				}
			}

			//diff
			else if (tokens.front() == "Kd")
			{
				if (tokens.size() > 3)
				{
					currentMaterial.diffuseFront[0] = tokens[1].toFloat();
					currentMaterial.diffuseFront[1] = tokens[2].toFloat();
					currentMaterial.diffuseFront[2] = tokens[3].toFloat();
					//duplicate
					memcpy(currentMaterial.diffuseBack,currentMaterial.diffuseFront,sizeof(float)*3);
				}
			}

			//specular
			else if (tokens.front() == "Ks")
			{
				if (tokens.size() > 3)
				{
					currentMaterial.specular[0] = tokens[1].toFloat();
					currentMaterial.specular[1] = tokens[2].toFloat();
					currentMaterial.specular[2] = tokens[3].toFloat();
				}
			}
			//shiny
			else if (tokens.front() == "Ns")
			{
				if (tokens.size() > 1)
					currentMaterial.setShininess(tokens[1].toFloat());
			}
			//transparent
			else if (tokens.front() == "d" || tokens.front() == "Tr")
			{
				if (tokens.size() > 1)
					currentMaterial.setTransparency(tokens[1].toFloat());
			}
			//reflection
			else if (tokens.front() == "r")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial.reflect = tokens[1].toFloat();
			}
			//glossy
			else if (tokens.front() == "sharpness")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial.glossy = tokens[1].toFloat();
			}
			//refract index
			else if (tokens.front() == "Ni")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial.refract_index = tokens[1].toFloat();
			}
			// illumination type
			else if (tokens.front() == "illum")
			{
				//ignored
			}
			// texture map
			else if (tokens.front() == "map_Ka"
					|| tokens.front() == "map_Kd"
					|| tokens.front() == "map_Ks")
			{
				QString texture_filename = currentLine.mid(7).trimmed();
				QString fullTexName = path+QString('/')+texture_filename;
				QImage image;
				if (!image.load(fullTexName))
				{
					errors << QString("Failed to load texture file: %1").arg(fullTexName);
				}
				else
				{
					currentMaterial.texture = image.mirrored(); //mirrored = WTF?!
				}
			}
			else
			{
				errors << QString("Unknown command '%1' at line %2").arg(tokens.front()).arg(currentLineIndex);
			}
		}

		currentLine = stream.readLine();
	}

	file.close();

	//push the last material
	if (currentMatIndex >= 0)
		materials.addMaterial(currentMaterial);

	return true;
}
Пример #2
0
//MTL PARSER INSPIRED FROM KIXOR.NET "objloader" (http://www.kixor.net/dev/objloader/)
bool ccMaterialSet::ParseMTL(QString path, const QString& filename, ccMaterialSet &materials, QStringList& errors)
{
	//open mtl file
	QString fullPathFilename = path + QString('/') + filename;
	QFile file(fullPathFilename);
	if (!file.open(QFile::ReadOnly))
	{
		errors << QString("Error reading file: %1").arg(filename);
		return false;
	}

	//update path (if the input filename has already a relative path)
	path = QFileInfo(fullPathFilename).absolutePath();
	
	QTextStream stream(&file);

	QString currentLine = stream.readLine();
	unsigned currentLineIndex = 0;
	ccMaterial::Shared currentMaterial(0);
	while( !currentLine.isNull() )
	{
		++currentLineIndex;

		QStringList tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts);

		//skip comments & empty lines
		if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) )
		{
			currentLine = stream.readLine();
			continue;
		}

		//start material
		if (tokens.front() == "newmtl")
		{
			//push the previous material (if any)
			if (currentMaterial)
			{
				materials.addMaterial(currentMaterial);
				currentMaterial = ccMaterial::Shared(0);
			}

			// get the name
			QString materialName = currentLine.mid(7).trimmed(); //we must take the whole line! (see OBJ filter)
			if (materialName.isEmpty())
				materialName = "undefined";
			currentMaterial = ccMaterial::Shared(new ccMaterial(materialName));

		}
		else if (currentMaterial) //we already have a "current" material
		{
			//ambient
			if (tokens.front() == "Ka")
			{
				if (tokens.size() > 3)
				{
					ccColor::Rgbaf ambient(	tokens[1].toFloat(),
											tokens[2].toFloat(),
											tokens[3].toFloat(),
											1.0f);
					currentMaterial->setAmbient(ambient);
				}
			}

			//diff
			else if (tokens.front() == "Kd")
			{
				if (tokens.size() > 3)
				{
					ccColor::Rgbaf diffuse(	tokens[1].toFloat(),
											tokens[2].toFloat(),
											tokens[3].toFloat(),
											1.0f);
					currentMaterial->setDiffuse(diffuse);
				}
			}

			//specular
			else if (tokens.front() == "Ks")
			{
				if (tokens.size() > 3)
				{
					ccColor::Rgbaf specular(tokens[1].toFloat(),
											tokens[2].toFloat(),
											tokens[3].toFloat(),
											1.0f);
					currentMaterial->setSpecular(specular);
				}
			}
			//shiny
			else if (tokens.front() == "Ns")
			{
				if (tokens.size() > 1)
					currentMaterial->setShininess(tokens[1].toFloat());
			}
			//transparent
			else if (tokens.front() == "d" || tokens.front() == "Tr")
			{
				if (tokens.size() > 1)
					currentMaterial->setTransparency(tokens[1].toFloat());
			}
			//reflection
			else if (tokens.front() == "r")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial->reflect = tokens[1].toFloat();
			}
			//glossy
			else if (tokens.front() == "sharpness")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial->glossy = tokens[1].toFloat();
			}
			//refract index
			else if (tokens.front() == "Ni")
			{
				//ignored
				//if (tokens.size() > 1)
				//	currentMaterial->refract_index = tokens[1].toFloat();
			}
			// illumination type
			else if (tokens.front() == "illum")
			{
				//ignored
			}
			// texture map
			else if (tokens.front() == "map_Ka"
					|| tokens.front() == "map_Kd"
					|| tokens.front() == "map_Ks")
			{
				//DGM: in case there's hidden or space characters at the beginning of the line...
				int shift = currentLine.indexOf("map_K",0);
				QString textureFilename = (shift + 7 < currentLine.size() ? currentLine.mid(shift+7).trimmed() : QString());
				QString fullTexName = path + QString('/') + textureFilename;
				if (!currentMaterial->loadAndSetTexture(fullTexName))
				{
					errors << QString("Failed to load texture file: %1").arg(fullTexName);
				}
			}
			else
			{
				errors << QString("Unknown command '%1' at line %2").arg(tokens.front()).arg(currentLineIndex);
			}
		}

		currentLine = stream.readLine();
	}

	file.close();

	//don't forget to push the last material!
	if (currentMaterial)
		materials.addMaterial(currentMaterial);

	return true;
}