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));
	}
예제 #2
0
파일: 3DSConverter.cpp 프로젝트: RSATom/Qt
// ------------------------------------------------------------------------------------------------
// 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);

}
예제 #4
0
파일: ACLoader.cpp 프로젝트: jpgr87/assimp
// ------------------------------------------------------------------------------------------------
// 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);
}
예제 #5
0
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));
}
예제 #7
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)
			);
		}
	}
예제 #8
0
// ------------------------------------------------------------------------------------------------
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)
}
예제 #9
0
파일: 3DSConverter.cpp 프로젝트: RSATom/Qt
// ------------------------------------------------------------------------------------------------
// 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);
    }
}
예제 #10
0
파일: model.cpp 프로젝트: Toeplitz/poll
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);
  }

}
예제 #11
0
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");
	}