shared_ptr<ModelMaterial> ModelMaterialProcessor::LoadModelMaterial(Model& model, aiMaterial& material) { InitializeTextureTypeMappings(); ModelMaterialData modelMaterialData; aiString name; material.Get(AI_MATKEY_NAME, name); modelMaterialData.Name = name.C_Str(); for (TextureType textureType = (TextureType)0; textureType < TextureType::End; textureType = (TextureType)(static_cast<int>(textureType) + 1)) { aiTextureType mappedTextureType = (aiTextureType)sTextureTypeMappings[textureType]; UINT textureCount = material.GetTextureCount(mappedTextureType); if (textureCount > 0) { vector<string>* textures = new vector<string>(); modelMaterialData.Textures.insert(pair<TextureType, vector<string>*>(textureType, textures)); textures->reserve(textureCount); for (UINT textureIndex = 0; textureIndex < textureCount; textureIndex++) { aiString path; if (material.GetTexture(mappedTextureType, textureIndex, &path) == AI_SUCCESS) { textures->push_back(path.C_Str()); } } } } return make_shared<ModelMaterial>(model, move(modelMaterialData)); }
// ------------------------------------------------------------------------------------------------ // Convert a 3DS texture to texture keys in an aiMaterial void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type) { // Setup the texture name aiString tex; tex.Set( texture.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); // Setup the texture blend factor if (is_not_qnan(texture.mTextureBlend)) mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); // Setup the texture mapping mode mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); // Mirroring - double the scaling values // FIXME: this is not really correct ... if (texture.mMapMode == aiTextureMapMode_Mirror) { texture.mScaleU *= 2.f; texture.mScaleV *= 2.f; texture.mOffsetU /= 2.f; texture.mOffsetV /= 2.f; } // Setup texture UV transformations mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); }
void AssimpLoader::fillMaterial(const aiMaterial& mat, Mesh& mesh) const { aiColor3D aiAmbient; aiColor3D aiDiffuse; aiColor3D aiSpecular; mat.Get(AI_MATKEY_COLOR_AMBIENT, aiAmbient); mesh.ambient = vec4(aiAmbient.r, aiAmbient.g, aiAmbient.b, 1.0f); mat.Get(AI_MATKEY_COLOR_DIFFUSE, aiDiffuse); mesh.diffuse = vec4(aiDiffuse.r, aiDiffuse.g, aiDiffuse.b, 1.0f); mat.Get(AI_MATKEY_COLOR_SPECULAR, aiSpecular); mesh.specular = vec4(aiSpecular.r, aiSpecular.g, aiSpecular.b, 1.0f); }
// ------------------------------------------------------------------------------------------------ // Convert a material from AC3DImporter::Material to aiMaterial void AC3DImporter::ConvertMaterial(const Object& object, const Material& matSrc, aiMaterial& matDest) { aiString s; if (matSrc.name.length()) { s.Set(matSrc.name); matDest.AddProperty(&s,AI_MATKEY_NAME); } if (object.texture.length()) { s.Set(object.texture); matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); // UV transformation if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y || object.texOffset.x || object.texOffset.y) { aiUVTransform transform; transform.mScaling = object.texRepeat; transform.mTranslation = object.texOffset; matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); } } matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE); matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT); matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE); matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR); int n; if (matSrc.shin) { n = aiShadingMode_Phong; matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS); } else n = aiShadingMode_Gouraud; matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL); float f = 1.f - matSrc.trans; matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY); }
bool assets::Material::loadFromDisk(const std::string& basePath, const aiMaterial& material, AssetManager& assetManager) { for (const auto& pair: { std::make_pair(0u, aiTextureType_EMISSIVE), std::make_pair(1u, aiTextureType_AMBIENT), std::make_pair(2u, aiTextureType_DIFFUSE), std::make_pair(3u, aiTextureType_SPECULAR), std::make_pair(4u, aiTextureType_HEIGHT)}) { aiString texturePath; material.GetTexture(pair.second, 0, &texturePath, nullptr, nullptr, nullptr, nullptr); const std::string fullPath = basePath + std::string(texturePath.C_Str()); if (0 < texturePath.length) textures[pair.first] = assetManager.getOrCreate<Texture>(std::string(texturePath.C_Str()), fullPath.c_str()); } aiColor3D emissive, ambient, diffuse, specular; float shininess; material.Get(AI_MATKEY_COLOR_EMISSIVE, emissive); material.Get(AI_MATKEY_COLOR_AMBIENT, ambient); material.Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); material.Get(AI_MATKEY_COLOR_SPECULAR, specular); material.Get(AI_MATKEY_SHININESS, shininess); this->emission = glm::vec4(emissive.r, emissive.g, emissive.b, 1.0f); this->ambient = glm::vec4(ambient.r, ambient.g, ambient.b, 1.0f); this->diffuse = glm::vec4(diffuse.r, diffuse.g, diffuse.b, 1.0f); this->specular = glm::vec4(specular.r, specular.g, specular.b, 1.0f); this->shininess = shininess; if (textures[2] && textures[2]->surface) translucent = textures[2]->surface->format->BytesPerPixel == 4; return true; }
// ------------------------------------------------------------------------------------------------ // Copy a texture from the ASE structs to the output material void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type) { // Setup the texture name aiString tex; tex.Set( texture.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); // Setup the texture blend factor if (is_not_qnan(texture.mTextureBlend)) mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); // Setup texture UV transformations mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); }
void bc_mesh_loader::convert_aimaterial(core::bc_content_loading_context& p_context, const aiMaterial& p_aimaterial, game::bc_render_material_description& p_material) { auto* l_content_manager = core::bc_get_service< core::bc_content_manager >(); aiColor3D l_diffuse; bcFLOAT l_alpha = 1; bcFLOAT l_specular_intensity = 1; bcFLOAT l_specular_power = 1; p_aimaterial.Get(AI_MATKEY_COLOR_DIFFUSE, l_diffuse); p_aimaterial.Get(AI_MATKEY_SHININESS_STRENGTH, l_specular_intensity); p_aimaterial.Get(AI_MATKEY_SHININESS, l_specular_power); p_aimaterial.Get(AI_MATKEY_OPACITY, l_alpha); p_material.m_diffuse = core::bc_vector4f(l_diffuse.r, l_diffuse.g, l_diffuse.b, l_alpha); p_material.m_specular_intensity = l_specular_intensity; p_material.m_specular_power = l_specular_power; aiString l_aistr; const core::bc_path l_file_path = core::bc_path(p_context.m_file_path.c_str()).set_filename(bcL("")); if (p_aimaterial.GetTexture(aiTextureType_DIFFUSE, 0, &l_aistr) == aiReturn_SUCCESS) { p_material.m_diffuse_map = l_content_manager->load< graphic::bc_texture2d_content > ( p_context.get_allocator_alloc_type(), core::bc_path(l_file_path).set_filename(core::bc_to_exclusive_wstring(l_aistr.C_Str()).c_str()).get_path().c_str(), core::bc_content_loader_parameter(p_context.m_parameter) ); } if (p_aimaterial.GetTexture(aiTextureType_NORMALS, 0, &l_aistr) == aiReturn_SUCCESS) { p_material.m_normal_map = l_content_manager->load< graphic::bc_texture2d_content > ( p_context.get_allocator_alloc_type(), core::bc_path(l_file_path).set_filename(core::bc_to_exclusive_wstring(l_aistr.C_Str()).c_str()).get_path().c_str(), core::bc_content_loader_parameter(p_context.m_parameter) ); } if (p_aimaterial.GetTexture(aiTextureType_SPECULAR, 0, &l_aistr) == aiReturn_SUCCESS) { p_material.m_specular_map = l_content_manager->load< graphic::bc_texture2d_content > ( p_context.get_allocator_alloc_type(), core::bc_path(l_file_path).set_filename(core::bc_to_exclusive_wstring(l_aistr.C_Str()).c_str()).get_path().c_str(), core::bc_content_loader_parameter(p_context.m_parameter) ); } }
// ------------------------------------------------------------------------------------------------ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags) { aiString path; aiTextureMapMode map_mode[2] = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; double blend = 1.0f; if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) { return; } // TODO: handle embedded textures properly if (path.data[0] == '*') { DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str())); return; } ChunkWriter chunk(writer, chunk_flags); { ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE); WriteString(path); } WritePercentChunk(blend); { ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING); uint16_t val = 0; // WRAP if (map_mode[0] == aiTextureMapMode_Mirror) { val = 0x2; } else if (map_mode[0] == aiTextureMapMode_Decal) { val = 0x10; } writer.PutU2(val); } // TODO: export texture transformation (i.e. UV offset, scale, rotation) }
// ------------------------------------------------------------------------------------------------ // Convert a 3DS material to an aiMaterial void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, aiMaterial& mat) { // NOTE: Pass the background image to the viewer by bypassing the // material system. This is an evil hack, never do it again! if (0 != mBackgroundImage.length() && bHasBG) { aiString tex; tex.Set( mBackgroundImage); mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); // Be sure this is only done for the first material mBackgroundImage = std::string(""); } // At first add the base ambient color of the scene to the material oldMat.mAmbient.r += mClrAmbient.r; oldMat.mAmbient.g += mClrAmbient.g; oldMat.mAmbient.b += mClrAmbient.b; aiString name; name.Set( oldMat.mName); mat.AddProperty( &name, AI_MATKEY_NAME); // Material colors mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); // Phong shininess and shininess strength if (D3DS::Discreet3DS::Phong == oldMat.mShading || D3DS::Discreet3DS::Metal == oldMat.mShading) { if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) { oldMat.mShading = D3DS::Discreet3DS::Gouraud; } else { mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); } } // Opacity mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); // Bump height scaling mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); // Two sided rendering? if (oldMat.mTwoSided) { int i = 1; mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED); } // Shading mode aiShadingMode eShading = aiShadingMode_NoShading; switch (oldMat.mShading) { case D3DS::Discreet3DS::Flat: eShading = aiShadingMode_Flat; break; // I don't know what "Wire" shading should be, // assume it is simple lambertian diffuse shading case D3DS::Discreet3DS::Wire: { // Set the wireframe flag unsigned int iWire = 1; mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); } case D3DS::Discreet3DS::Gouraud: eShading = aiShadingMode_Gouraud; break; // assume cook-torrance shading for metals. case D3DS::Discreet3DS::Phong : eShading = aiShadingMode_Phong; break; case D3DS::Discreet3DS::Metal : eShading = aiShadingMode_CookTorrance; break; // FIX to workaround a warning with GCC 4 who complained // about a missing case Blinn: here - Blinn isn't a valid // value in the 3DS Loader, it is just needed for ASE case D3DS::Discreet3DS::Blinn : eShading = aiShadingMode_Blinn; break; } mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); // DIFFUSE texture if( oldMat.sTexDiffuse.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE); // SPECULAR texture if( oldMat.sTexSpecular.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR); // OPACITY texture if( oldMat.sTexOpacity.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY); // EMISSIVE texture if( oldMat.sTexEmissive.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE); // BUMP texture if( oldMat.sTexBump.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT); // SHININESS texture if( oldMat.sTexShininess.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS); // REFLECTION texture if( oldMat.sTexReflective.mMapName.length() > 0) CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION); // Store the name of the material itself, too if( oldMat.mName.length()) { aiString tex; tex.Set( oldMat.mName); mat.AddProperty( &tex, AI_MATKEY_NAME); } }
void Model::assimp_material_add_texture(Material &material, aiMaterial &assimp_material, Model_Texture_Type type) { int texIndex = 0; aiString path; aiTextureType assimp_type; switch (type) { case MODEL_TEXTURE_DIFFUSE: assimp_type = aiTextureType_DIFFUSE; break; case MODEL_TEXTURE_NORMAL: assimp_type = aiTextureType_NORMALS; break; case MODEL_TEXTURE_HEIGHT: assimp_type = aiTextureType_HEIGHT; break; case MODEL_TEXTURE_ALPHA: assimp_type = aiTextureType_OPACITY; break; case MODEL_TEXTURE_SPECULAR: assimp_type = aiTextureType_SPECULAR; break; default: break; } aiReturn texFound = assimp_material.GetTexture(assimp_type, texIndex, &path); if (texFound == AI_SUCCESS) { if (texIndex > 0) { std::cout << "Fragmic warning: more then one texture of this type for material" << std::endl; std::cout << "NOT CURRENTLY SUPPORTED!" << std::endl; } //std::cout << "\tTexture file: " << path.data << std::endl; std::unique_ptr<Texture> texturePtr(new Texture()); Texture &texture = *texturePtr; texture.image_load(prefix + std::string(path.data)); switch (type) { case MODEL_TEXTURE_DIFFUSE: material.diffuse = std::move(texturePtr); break; case MODEL_TEXTURE_NORMAL: material.normal = std::move(texturePtr); break; case MODEL_TEXTURE_HEIGHT: material.height = std::move(texturePtr); break; case MODEL_TEXTURE_ALPHA: material.alpha = std::move(texturePtr); break; case MODEL_TEXTURE_SPECULAR: material.specular = std::move(texturePtr); break; default: break; } texIndex++; texFound = assimp_material.GetTexture(assimp_type, texIndex, &path); } }
void Exporter::exportMaterial(const aiMaterial& mtl) const { std::string diffTex; std::string normTex; std::string specColTex; std::string shininessTex; std::string dispTex; std::string emissiveTex; std::string metallicTex; aiString path; std::string name = getMaterialName(mtl); LOGI("Exporting material %s", name.c_str()); // Diffuse texture if(mtl.GetTextureCount(aiTextureType_DIFFUSE) > 0) { if(mtl.GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS) { diffTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Normal texture if(mtl.GetTextureCount(aiTextureType_NORMALS) > 0) { if(mtl.GetTexture(aiTextureType_NORMALS, 0, &path) == AI_SUCCESS) { normTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Specular color if(mtl.GetTextureCount(aiTextureType_SPECULAR) > 0) { if(mtl.GetTexture(aiTextureType_SPECULAR, 0, &path) == AI_SUCCESS) { specColTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Shininess color if(mtl.GetTextureCount(aiTextureType_SHININESS) > 0) { if(mtl.GetTexture(aiTextureType_SHININESS, 0, &path) == AI_SUCCESS) { shininessTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Height texture if(mtl.GetTextureCount(aiTextureType_DISPLACEMENT) > 0) { if(mtl.GetTexture(aiTextureType_DISPLACEMENT, 0, &path) == AI_SUCCESS) { dispTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Emissive texture if(mtl.GetTextureCount(aiTextureType_EMISSIVE) > 0) { if(mtl.GetTexture(aiTextureType_EMISSIVE, 0, &path) == AI_SUCCESS) { emissiveTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Metallic texture if(mtl.GetTextureCount(aiTextureType_REFLECTION) > 0) { if(mtl.GetTexture(aiTextureType_REFLECTION, 0, &path) == AI_SUCCESS) { metallicTex = getFilename(path.C_Str()); } else { ERROR("Failed to retrieve texture"); } } // Write file static const char* diffNormSpecFragTemplate = #include "templates/diffNormSpecFrag.h" ; static const char* simpleVertTemplate = #include "templates/simpleVert.h" ; static const char* tessVertTemplate = #include "templates/tessVert.h" ; static const char* readRgbFromTextureTemplate = R"( <operation> <id>%id%</id> <returnType>vec3</returnType> <function>readRgbFromTexture</function> <arguments> <argument>%map%</argument> <argument>out2</argument> </arguments> </operation>)"; static const char* readRFromTextureTemplate = R"( <operation> <id>%id%</id> <returnType>float</returnType> <function>readRFromTexture</function> <arguments> <argument>%map%</argument> <argument>out2</argument> </arguments> </operation>)"; // Compose full template // First geometry part std::string materialStr; materialStr = R"(<?xml version="1.0" encoding="UTF-8" ?>)"; materialStr += "\n<material>\n\t<programs>\n"; if(/*dispTex.empty()*/ 1) { materialStr += simpleVertTemplate; } else { materialStr += tessVertTemplate; } materialStr += "\n"; // Then fragment part materialStr += diffNormSpecFragTemplate; materialStr += "\n\t</programs>\t</material>"; // Replace strings if(!dispTex.empty()) { materialStr = replaceAllString(materialStr, "%dispMap%", m_texrpath + dispTex); } // Diffuse if(!diffTex.empty()) { materialStr = replaceAllString(materialStr, "%diffuseColorInput%", R"(<input><type>sampler2D</type><name>uDiffuseColor</name><value>)" + m_texrpath + diffTex + R"(</value></input>)"); materialStr = replaceAllString(materialStr, "%diffuseColorFunc%", readRgbFromTextureTemplate); materialStr = replaceAllString(materialStr, "%id%", "10"); materialStr = replaceAllString(materialStr, "%map%", "uDiffuseColor"); materialStr = replaceAllString(materialStr, "%diffuseColorArg%", "out10"); }