diff options
| author | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
|---|---|---|
| committer | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
| commit | ca32c59a58d37c1822e185a2d5f3d0d3e8943593 (patch) | |
| tree | b06b9eec03f34344ef8fc31aa147b2714d3962ee /NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp | |
| parent | Forced rename of platform folders in cmake dir. Git didn't pick this up before. (diff) | |
| download | nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.tar.xz nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.zip | |
NvCloth 1.1.4 Release. (24070740)
Diffstat (limited to 'NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp')
| -rw-r--r-- | NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp b/NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp new file mode 100644 index 0000000..1abca2c --- /dev/null +++ b/NvCloth/samples/external/assimp-4.1.0/code/OgreMaterial.cpp @@ -0,0 +1,596 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + + +#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER + +#include "OgreImporter.h" +#include "TinyFormatter.h" +#include <assimp/material.h> +#include <assimp/scene.h> +#include <assimp/DefaultLogger.hpp> +#include "fast_atof.h" + +#include <vector> +#include <sstream> +#include <memory> + +using namespace std; + +namespace Assimp +{ +namespace Ogre +{ + +static const string partComment = "//"; +static const string partBlockStart = "{"; +static const string partBlockEnd = "}"; + +void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh) +{ + std::vector<aiMaterial*> materials; + + // Create materials that can be found and parsed via the IOSystem. + for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i) + { + SubMesh *submesh = mesh->GetSubMesh(i); + if (submesh && !submesh->materialRef.empty()) + { + aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef); + if (material) + { + submesh->materialIndex = static_cast<int>(materials.size()); + materials.push_back(material); + } + } + } + + AssignMaterials(pScene, materials); +} + +void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh) +{ + std::vector<aiMaterial*> materials; + + // Create materials that can be found and parsed via the IOSystem. + for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i) + { + SubMeshXml *submesh = mesh->GetSubMesh( static_cast<uint16_t>(i)); + if (submesh && !submesh->materialRef.empty()) + { + aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef); + if (material) + { + submesh->materialIndex = static_cast<int>(materials.size()); + materials.push_back(material); + } + } + } + + AssignMaterials(pScene, materials); +} + +void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials) +{ + pScene->mNumMaterials = static_cast<unsigned int>(materials.size()); + if (pScene->mNumMaterials > 0) + { + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + for(size_t i=0;i<pScene->mNumMaterials; ++i) { + pScene->mMaterials[i] = materials[i]; + } + } +} + +aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &materialName) +{ + if (materialName.empty()) { + return 0; + } + + // Full reference and examples of Ogre Material Script + // can be found from http://www.ogre3d.org/docs/manual/manual_14.html + + /*and here is another one: + + import * from abstract_base_passes_depth.material + import * from abstract_base.material + import * from mat_shadow_caster.material + import * from mat_character_singlepass.material + + material hero/hair/caster : mat_shadow_caster_skin_areject + { + set $diffuse_map "hero_hair_alpha_c.dds" + } + + material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights + { + set $diffuse_map "hero_hair_alpha_c.dds" + set $specular_map "hero_hair_alpha_s.dds" + set $normal_map "hero_hair_alpha_n.dds" + set $light_map "black_lightmap.dds" + + set $shadow_caster_material "hero/hair/caster" + } + */ + + stringstream ss; + + // Scope for scopre_ptr auto release + { + /* There are three .material options in priority order: + 1) File with the material name (materialName) + 2) File with the mesh files base name (pFile) + 3) Optional user defined material library file (m_userDefinedMaterialLibFile) */ + std::vector<string> potentialFiles; + potentialFiles.push_back(materialName + ".material"); + potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material"); + if (!m_userDefinedMaterialLibFile.empty()) + potentialFiles.push_back(m_userDefinedMaterialLibFile); + + IOStream *materialFile = 0; + for(size_t i=0; i<potentialFiles.size(); ++i) + { + materialFile = pIOHandler->Open(potentialFiles[i]); + if (materialFile) { + break; + } + DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist"); + } + if (!materialFile) + { + DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'"); + return 0; + } + + std::unique_ptr<IOStream> stream(materialFile); + if (stream->FileSize() == 0) + { + DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)"); + return 0; + } + + // Read bytes + vector<char> data(stream->FileSize()); + stream->Read(&data[0], stream->FileSize(), 1); + + // Convert to UTF-8 and terminate the string for ss + BaseImporter::ConvertToUTF8(data); + data.push_back('\0'); + + ss << &data[0]; + } + + DefaultLogger::get()->debug("Reading material '" + materialName + "'"); + + aiMaterial *material = new aiMaterial(); + m_textures.clear(); + + aiString ts(materialName); + material->AddProperty(&ts, AI_MATKEY_NAME); + + // The stringstream will push words from a line until newline. + // It will also trim whitespace from line start and between words. + string linePart; + ss >> linePart; + + const string partMaterial = "material"; + const string partTechnique = "technique"; + + while(!ss.eof()) + { + // Skip commented lines + if (linePart == partComment) + { + NextAfterNewLine(ss, linePart); + continue; + } + if (linePart != partMaterial) + { + ss >> linePart; + continue; + } + + ss >> linePart; + if (linePart != materialName) + { + //DefaultLogger::get()->debug(Formatter::format() << "Found material '" << linePart << "' that does not match at index " << ss.tellg()); + ss >> linePart; + continue; + } + + NextAfterNewLine(ss, linePart); + if (linePart != partBlockStart) + { + DefaultLogger::get()->error(Formatter::format() << "Invalid material: block start missing near index " << ss.tellg()); + return material; + } + + DefaultLogger::get()->debug("material '" + materialName + "'"); + + while(linePart != partBlockEnd) + { + // Proceed to the first technique + ss >> linePart; + + if (linePart == partTechnique) + { + string techniqueName = SkipLine(ss); + ReadTechnique(Trim(techniqueName), ss, material); + } + + // Read information from a custom material + /** @todo This "set $x y" does not seem to be a official Ogre material system feature. + Materials can inherit other materials and override texture units by using the (unique) + parent texture unit name in your cloned material. + This is not yet supported and below code is probably some hack from the original + author of this Ogre importer. Should be removed? */ + if (linePart=="set") + { + ss >> linePart; + if (linePart=="$specular")//todo load this values: + { + } + else if (linePart=="$diffuse") + { + } + else if (linePart=="$ambient") + { + } + else if (linePart=="$colormap") + { + ss >> linePart; + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + } + else if (linePart=="$normalmap") + { + ss >> linePart; + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); + } + else if (linePart=="$shininess_strength") + { + ss >> linePart; + float Shininess = fast_atof(linePart.c_str()); + material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH); + } + else if (linePart=="$shininess_exponent") + { + ss >> linePart; + float Shininess = fast_atof(linePart.c_str()); + material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS); + } + //Properties from Venetica: + else if (linePart=="$diffuse_map") + { + ss >> linePart; + if (linePart[0] == '"')// "file" -> file + linePart = linePart.substr(1, linePart.size()-2); + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + } + else if (linePart=="$specular_map") + { + ss >> linePart; + if (linePart[0] == '"')// "file" -> file + linePart = linePart.substr(1, linePart.size()-2); + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0)); + } + else if (linePart=="$normal_map") + { + ss >> linePart; + if (linePart[0]=='"')// "file" -> file + linePart = linePart.substr(1, linePart.size()-2); + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); + } + else if (linePart=="$light_map") + { + ss >> linePart; + if (linePart[0]=='"') { + linePart = linePart.substr(1, linePart.size() - 2); + } + aiString ts(linePart); + material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0)); + } + } + } + ss >> linePart; + } + + return material; +} + +bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material) +{ + string linePart; + ss >> linePart; + + if (linePart != partBlockStart) + { + DefaultLogger::get()->error(Formatter::format() << "Invalid material: Technique block start missing near index " << ss.tellg()); + return false; + } + + DefaultLogger::get()->debug(" technique '" + techniqueName + "'"); + + const string partPass = "pass"; + + while(linePart != partBlockEnd) + { + ss >> linePart; + + // Skip commented lines + if (linePart == partComment) + { + SkipLine(ss); + continue; + } + + /// @todo Techniques have other attributes than just passes. + if (linePart == partPass) + { + string passName = SkipLine(ss); + ReadPass(Trim(passName), ss, material); + } + } + return true; +} + +bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material) +{ + string linePart; + ss >> linePart; + + if (linePart != partBlockStart) + { + DefaultLogger::get()->error(Formatter::format() << "Invalid material: Pass block start missing near index " << ss.tellg()); + return false; + } + + DefaultLogger::get()->debug(" pass '" + passName + "'"); + + const string partAmbient = "ambient"; + const string partDiffuse = "diffuse"; + const string partSpecular = "specular"; + const string partEmissive = "emissive"; + const string partTextureUnit = "texture_unit"; + + while(linePart != partBlockEnd) + { + ss >> linePart; + + // Skip commented lines + if (linePart == partComment) + { + SkipLine(ss); + continue; + } + + // Colors + /// @todo Support alpha via aiColor4D. + if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive) + { + float r, g, b; + ss >> r >> g >> b; + const aiColor3D color(r, g, b); + + DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b); + + if (linePart == partAmbient) + { + material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT); + } + else if (linePart == partDiffuse) + { + material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE); + } + else if (linePart == partSpecular) + { + material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR); + } + else if (linePart == partEmissive) + { + material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE); + } + } + else if (linePart == partTextureUnit) + { + string textureUnitName = SkipLine(ss); + ReadTextureUnit(Trim(textureUnitName), ss, material); + } + } + return true; +} + +bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material) +{ + string linePart; + ss >> linePart; + + if (linePart != partBlockStart) + { + DefaultLogger::get()->error(Formatter::format() << "Invalid material: Texture unit block start missing near index " << ss.tellg()); + return false; + } + + DefaultLogger::get()->debug(" texture_unit '" + textureUnitName + "'"); + + const string partTexture = "texture"; + const string partTextCoordSet = "tex_coord_set"; + const string partColorOp = "colour_op"; + + aiTextureType textureType = aiTextureType_NONE; + std::string textureRef; + int uvCoord = 0; + + while(linePart != partBlockEnd) + { + ss >> linePart; + + // Skip commented lines + if (linePart == partComment) + { + SkipLine(ss); + continue; + } + + if (linePart == partTexture) + { + ss >> linePart; + textureRef = linePart; + + // User defined Assimp config property to detect texture type from filename. + if (m_detectTextureTypeFromFilename) + { + size_t posSuffix = textureRef.find_last_of("."); + size_t posUnderscore = textureRef.find_last_of("_"); + + if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) + { + string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); + DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'"); + + if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") + { + textureType = aiTextureType_NORMALS; + } + else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap") + { + textureType = aiTextureType_SPECULAR; + } + else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion") + { + textureType = aiTextureType_LIGHTMAP; + } + else if (identifier == "_disp" || identifier == "_displacement") + { + textureType = aiTextureType_DISPLACEMENT; + } + else + { + textureType = aiTextureType_DIFFUSE; + } + } + else + { + textureType = aiTextureType_DIFFUSE; + } + } + // Detect from texture unit name. This cannot be too broad as + // authors might give names like "LightSaber" or "NormalNinja". + else + { + string unitNameLower = Ogre::ToLower(textureUnitName); + if (unitNameLower.find("normalmap") != string::npos) + { + textureType = aiTextureType_NORMALS; + } + else if (unitNameLower.find("specularmap") != string::npos) + { + textureType = aiTextureType_SPECULAR; + } + else if (unitNameLower.find("lightmap") != string::npos) + { + textureType = aiTextureType_LIGHTMAP; + } + else if (unitNameLower.find("displacementmap") != string::npos) + { + textureType = aiTextureType_DISPLACEMENT; + } + else + { + textureType = aiTextureType_DIFFUSE; + } + } + } + else if (linePart == partTextCoordSet) + { + ss >> uvCoord; + } + /// @todo Implement + else if(linePart == partColorOp) + { + /* + ss >> linePart; + if("replace"==linePart)//I don't think, assimp has something for this... + { + } + else if("modulate"==linePart) + { + //TODO: set value + //material->AddProperty(aiTextureOp_Multiply) + } + */ + } + } + + if (textureRef.empty()) + { + DefaultLogger::get()->warn("Texture reference is empty, ignoring texture_unit."); + return false; + } + if (textureType == aiTextureType_NONE) + { + DefaultLogger::get()->warn("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit."); + return false; + } + + unsigned int textureTypeIndex = m_textures[textureType]; + m_textures[textureType]++; + + DefaultLogger::get()->debug(Formatter::format() << " texture '" << textureRef << "' type " << textureType + << " index " << textureTypeIndex << " UV " << uvCoord); + + aiString assimpTextureRef(textureRef); + material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex)); + material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex)); + + return true; +} + +} // Ogre +} // Assimp + +#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER |