Пример #1
0
	bool AssimpLoadMesh(const Ptr<MeshAsset> & asset, bool bFlipUV, bool bLeftHanded)
	{
		if (!Global::GetPlatform()->FileExists(asset->GetLoadPath()))
		{
			ToyGE_LOG(LT_WARNING, "Cannot open mesh file when reading! %s", asset->GetLoadPath().c_str());
			return false;
		}

		auto meshFullPath = asset->GetLoadFullPath();
		auto meshDirFullPath = ParentPath(meshFullPath);
		auto assetsFullBasePath = Global::GetPlatform()->GetPathFullName(Asset::GetAssetsBasePath());
		String meshDirRelativePath;
		if (!Global::GetPlatform()->GetRelativePath(assetsFullBasePath, true, meshDirFullPath, true, meshDirRelativePath))
		{
			ToyGE_LOG(LT_WARNING, "Cannot find relative path for mesh from %s to %s!", assetsFullBasePath.c_str(), meshDirFullPath.c_str());
			return false;
		}

		// Base path for mesh's resources
		String basePath = meshDirRelativePath;

		uint32_t processFlag = aiProcessPreset_TargetRealtime_Quality;// | aiProcess_MakeLeftHanded;
		if (bFlipUV)
			processFlag |= aiProcess_FlipUVs;
		if (bLeftHanded)
			processFlag |= aiProcess_MakeLeftHanded;

		Assimp::Importer importer;
		const aiScene *pAiScene = importer.ReadFile(asset->GetLoadPath(), processFlag);
		if (nullptr == pAiScene)
		{
			ToyGE_LOG(LT_WARNING, "Cannot load mesh! %s", asset->GetLoadPath().c_str());
			return false;
		}


		// Material
		std::vector<Ptr<MaterialAsset>> materials;

		for (uint32_t matIndex = 0; matIndex != pAiScene->mNumMaterials; ++matIndex)
		{
			Ptr<MaterialAsset> mat = std::make_shared<MaterialAsset>();
			const aiMaterial *pAiMat = pAiScene->mMaterials[matIndex];

			// Diffuse
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_DIFFUSE); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_DIFFUSE, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;

				if(basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_BASECOLOR, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_BASECOLOR, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			// Specular
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_SPECULAR); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_SPECULAR, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;
				//mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex);
				if (basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			// Normal
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_NORMALS); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_NORMALS, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;
				//mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex);
				if (basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			// Height
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_HEIGHT); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_HEIGHT, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;
				//mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex);
				if (basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			// Roughness
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_SHININESS); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_SHININESS, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;


				if (basePath.size() > 0)
				{
					auto roughnessPath = ShininessToRoughnessTex(basePath + "/" + path.C_Str());
					mat->AddTexture(MaterialTextureType::MAT_TEX_ROUGHNESS, Asset::Find<TextureAsset>(roughnessPath), static_cast<uint8_t>(uvIndex));
				}
				else
				{
					auto roughnessPath = ShininessToRoughnessTex(path.C_Str());
					mat->AddTexture(MaterialTextureType::MAT_TEX_ROUGHNESS, Asset::Find<TextureAsset>(roughnessPath), static_cast<uint8_t>(uvIndex));
				}
			}

			// Opacity
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_OPACITY); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_OPACITY, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;
				//mat->AddTexture(MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), 0);
				if (basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			// EMISSIVE
			for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_EMISSIVE); ++texIndex)
			{
				aiString path;
				uint32_t uvIndex;
				pAiMat->GetTexture(aiTextureType_EMISSIVE, texIndex, &path, 0, &uvIndex);
				if (uvIndex >= MaxNumTexCoord::NUM)
					uvIndex = 0;
				//mat->AddTexture(MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), 0);
				if (basePath.size() > 0)
					mat->AddTexture(MaterialTextureType::MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex));
				else
					mat->AddTexture(MaterialTextureType::MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex));
			}

			aiColor3D baseColor;
			pAiMat->Get(AI_MATKEY_COLOR_DIFFUSE, baseColor);
			mat->SetBaseColor(float3(baseColor.r, baseColor.g, baseColor.b));

			float opacity;
			pAiMat->Get(AI_MATKEY_OPACITY, opacity);
			mat->SetOpcacity(opacity);

			float shininess;
			pAiMat->Get(AI_MATKEY_SHININESS, shininess);
			mat->SetRoughness(pow(2.0f / (shininess + 2.0f), 0.25f));

			// Set material path
			aiString matName;
			pAiMat->Get(AI_MATKEY_NAME, matName);
			if (matName.length > 0)
			{
				if(basePath.size() > 0)
					mat->SetPath(basePath + "/Material/" + matName.C_Str() + MaterialAsset::GetExtension());
				else
					mat->SetPath(String("Material/") + matName.C_Str() + MaterialAsset::GetExtension());
			}
			else
			{
				if (basePath.size() > 0)
					mat->SetPath(basePath + "/Material/mat_" + std::to_string(matIndex) + MaterialAsset::GetExtension());
				else
					mat->SetPath(String("Material/mat_") + matName.C_Str() + MaterialAsset::GetExtension());
			}

			materials.push_back(mat);
		}


		// Mesh
		std::vector<Ptr<MeshElement>> meshElements;

		for (uint32_t meshIndex = 0; meshIndex != pAiScene->mNumMeshes; ++meshIndex)
		{
			Ptr<MeshElement> meshElement = std::make_shared<MeshElement>();
			const aiMesh *pAiMesh = pAiScene->mMeshes[meshIndex];

			meshElement->material = materials[pAiMesh->mMaterialIndex];

			auto vertexSlot = std::make_shared<MeshVertexSlotData>();
			//meshElement->vertexData = std::make_shared<MeshVertexData>();

			// Init vertex elements desc
			std::vector<MeshVertexElementDesc> & elementsDesc = vertexSlot->vertexDesc.elementsDesc;
			MeshVertexElementDesc elemDesc;
			int32_t bytesOffset = 0;
			if (pAiMesh->HasPositions())
			{
				elemDesc.signature = MeshVertexElementSignature::MVET_POSITION;
				elemDesc.signatureIndex = 0;
				elemDesc.bytesOffset = bytesOffset;
				elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3));
				elementsDesc.push_back(elemDesc);
				bytesOffset += elemDesc.bytesSize;
			}

			if (pAiMesh->GetNumUVChannels() > 0)
			{
				for (uint32_t uvChannel = 0; uvChannel != pAiMesh->GetNumUVChannels(); ++uvChannel)
				{
					elemDesc.signature = MeshVertexElementSignature::MVET_TEXCOORD;
					elemDesc.signatureIndex = static_cast<int32_t>(uvChannel);
					elemDesc.bytesOffset = bytesOffset;
					elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3));
					elementsDesc.push_back(elemDesc);
					bytesOffset += elemDesc.bytesSize;
				}
			}

			if (pAiMesh->HasNormals())
			{
				elemDesc.signature = MeshVertexElementSignature::MVET_NORMAL;
				elemDesc.signatureIndex = 0;
				elemDesc.bytesOffset = bytesOffset;
				elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3));
				elementsDesc.push_back(elemDesc);
				bytesOffset += elemDesc.bytesSize;
			}

			if (pAiMesh->HasTangentsAndBitangents())
			{
				elemDesc.signature = MeshVertexElementSignature::MVET_TANGENT;
				elemDesc.signatureIndex = 0;
				elemDesc.bytesOffset = bytesOffset;
				elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3));
				elementsDesc.push_back(elemDesc);
				bytesOffset += elemDesc.bytesSize;

				elemDesc.signature = MeshVertexElementSignature::MVET_BITANGENT;
				elemDesc.signatureIndex = 0;
				elemDesc.bytesOffset = bytesOffset;
				elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3));
				elementsDesc.push_back(elemDesc);
				bytesOffset += elemDesc.bytesSize;
			}

			vertexSlot->vertexDesc.bytesSize = bytesOffset;

			// Init vertex data
			int32_t stride = bytesOffset;
			vertexSlot->bufferSize = stride * static_cast<int32_t>(pAiMesh->mNumVertices);
			vertexSlot->rawBuffer = MakeBufferedDataShared(static_cast<size_t>(vertexSlot->bufferSize));

			bytesOffset = 0;
			uint8_t * data = vertexSlot->rawBuffer.get();
			if (pAiMesh->HasPositions())
			{
				for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex)
				{
					float3 pos;
					pos.x() = pAiMesh->mVertices[vertexIndex].x;
					pos.y() = pAiMesh->mVertices[vertexIndex].y;
					pos.z() = pAiMesh->mVertices[vertexIndex].z;
					memcpy(data, &pos, sizeof(pos));
					data += stride;
				}
				bytesOffset += static_cast<int32_t>(sizeof(float3));
			}

			if (pAiMesh->GetNumUVChannels() > 0)
			{
				data = vertexSlot->rawBuffer.get() + bytesOffset;
				for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex)
				{
					for (uint32_t uvChannel = 0; uvChannel != pAiMesh->GetNumUVChannels(); ++uvChannel)
					{
						auto & uvw = pAiMesh->mTextureCoords[uvChannel][vertexIndex];
						float3 texCoord(uvw.x, uvw.y, uvw.z);
						memcpy(data + sizeof(texCoord) * uvChannel, &texCoord, sizeof(texCoord));
					}
					data += stride;
				}
				bytesOffset += static_cast<int32_t>(sizeof(float3) * pAiMesh->GetNumUVChannels());
			}

			if (pAiMesh->HasNormals())
			{
				data = vertexSlot->rawBuffer.get() + bytesOffset;
				for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex)
				{
					float3 normal;
					normal.x() = pAiMesh->mNormals[vertexIndex].x;
					normal.y() = pAiMesh->mNormals[vertexIndex].y;
					normal.z() = pAiMesh->mNormals[vertexIndex].z;
					normal = normalize(normal);
					memcpy(data, &normal, sizeof(normal));
					data += stride;
				}
				bytesOffset += static_cast<int32_t>(sizeof(float3));
			}

			if (pAiMesh->HasTangentsAndBitangents())
			{
				data = vertexSlot->rawBuffer.get() + bytesOffset;
				for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex)
				{
					float3 tangent;
					tangent.x() = pAiMesh->mTangents[vertexIndex].x;
					tangent.y() = pAiMesh->mTangents[vertexIndex].y;
					tangent.z() = pAiMesh->mTangents[vertexIndex].z;
					memcpy(data, &tangent, sizeof(tangent));

					float3 bitangent;
					bitangent.x() = pAiMesh->mBitangents[vertexIndex].x;
					bitangent.y() = pAiMesh->mBitangents[vertexIndex].y;
					bitangent.z() = pAiMesh->mBitangents[vertexIndex].z;
					memcpy(data + sizeof(tangent), &bitangent, sizeof(bitangent));

					data += stride;
				}
				bytesOffset += static_cast<int32_t>(sizeof(float3));
			}
			meshElement->vertexData.push_back(vertexSlot);

			// Indices
			for (uint32_t faceIndex = 0; faceIndex != pAiMesh->mNumFaces; ++faceIndex)
			{
				aiFace &pAiFace = pAiMesh->mFaces[faceIndex];
				for (uint32_t index = 0; index != pAiFace.mNumIndices; ++index)
					meshElement->indices.push_back(pAiFace.mIndices[index]);
			}

			meshElements.push_back(meshElement);
		}
		asset->SetData(meshElements);

		return true;
	}