Problem with Alembic import: Error getting adding to initalShadingGroup.

huben_hb
Observer

Problem with Alembic import: Error getting adding to initalShadingGroup.

huben_hb
Observer
Observer

Hello everyone, please help me!

 

I attempted to export an Alembic file in Unreal Engine, as shown in the source code below. However, when I try to import this file into Maya, I receive an error message "Error: Error getting adding to initalShadingGroup."

 

However, when I import this Alembic file into Houdini or Blender, everything works fine. If I re-export the original Alembic file from Houdini and Blender, I can then successfully import it into Maya without any issues.

 

I've reviewed the sample code on this website: https://help.autodesk.com/view/MAYAUL/2022/ENU/?guid=Maya_SDK_cpp_ref_gpu_cache_2_cache_writer_alemb...

 

Is it possible that I've overlooked some settings for Alembic?

 

Thanks a lot!

 

huben_hb_0-1704853334395.png

 

 

bool UChaosCacheAbcExporter::ExportBinary(UObject* Object, const TCHAR* Type, FArchive& Archive, FFeedbackContext* Warn, int32 FileIndex, uint32 PortFlags)
{
	UChaosCacheCollection* ChaosCacheCollectionAsset = Cast<UChaosCacheCollection>(Object);
	if (!ChaosCacheCollectionAsset)
	{
		return false;
	}

	TArray<USkeletalMesh*> SkeletalMeshes;
	TArray<FString> NullSkeletalMeshRef;

	for(auto& Cache: ChaosCacheCollectionAsset->GetCaches())
	{
		if(USkeletalMesh* SkeletalMesh = LoadObject<USkeletalMesh>(nullptr, *Cache->RecordedSkeletalMeshRef))
		{
			SkeletalMeshes.Emplace(SkeletalMesh);
		}
		else if(Cache->RecordedSkeletalMeshRef != "")
		{
			NullSkeletalMeshRef.Emplace(Cache->RecordedSkeletalMeshRef);
		}
	}

	if(SkeletalMeshes.Num() == 0)
	{
		return false;
	}

	if(NullSkeletalMeshRef.Num() > 0)
	{
		FString NoSkeletalMeshTip = L"布料缓存SkeletalMesh不存在, 请确定以下资产存在后重试: \r\n\r\n";

		for(FString StringRef: NullSkeletalMeshRef)
		{
			NoSkeletalMeshTip += StringRef + "\r\n";
		}
		
		FMessageDialog::Open(EAppMsgCategory::Warning, EAppMsgType::Ok,
							FText::FromString(NoSkeletalMeshTip), FText::FromString(L"布料SkeletalMesh不存在"));
		
		return false;
	}
	
	Alembic::Abc::OArchive ChaosCacheArchive(Alembic::AbcCoreOgawa::WriteArchive(), TCHAR_TO_UTF8(*CurrentFilename));
	ChaosCacheArchive.setCompressionHint(-1);
	
	const int32 AbcFrameRate = ChaosCacheCollectionAsset->RecordedOriginFrameRate * ChaosCacheCollectionAsset->RecordedMultiPower;
	
	Alembic::Abc::TimeSamplingPtr TimeSampPtr = std::make_shared<Alembic::Abc::TimeSampling>(1.0 / AbcFrameRate, 0.0);
	int32 Tsi = ChaosCacheArchive.addTimeSampling(*TimeSampPtr);

	Alembic::Abc::OObject ChaosCacheObject(ChaosCacheArchive, Alembic::Abc::kTop, Tsi);
	
	const int32 SampleNum = ChaosCacheCollectionAsset->TotalRecordedFrames;

	std::vector<std::vector<Alembic::AbcGeom::OPolyMesh>> AllAbcPolyMeshes;
	// std::vector<Alembic::AbcMaterial::OMaterial> AbcPolyMeshesMaterials;
	std::vector<std::vector<std::vector<int>>> AllFaceIndices;
	std::vector<std::vector<std::vector<int>>> AllPolygonCounts;
	std::vector<std::vector<std::vector<Alembic::Abc::V3f>>> AllVerticesPoses;
	std::vector<std::vector<std::vector<Alembic::Abc::V2f>>> AllVerticesUVs;
	std::vector<std::vector<std::vector<Alembic::Abc::V3f>>> AllVerticesVelocities;
	std::vector<std::vector<std::vector<Alembic::Abc::N3f>>> AllVerticesNormals;

	// 获取mesh
	for(int MeshId = 0; MeshId < SkeletalMeshes.Num(); MeshId++)
	{
		std::vector<Alembic::AbcGeom::OPolyMesh> AbcPolyMeshes;
		std::vector<std::vector<int>> FaceIndices;
		std::vector<std::vector<int>> PolygonCounts;
		std::vector<std::vector<Alembic::Abc::V3f>> VerticesPoses;
		std::vector<std::vector<Alembic::Abc::V2f>> VerticesUVs;
		std::vector<std::vector<Alembic::Abc::V3f>> VerticesVelocities;
		std::vector<std::vector<Alembic::Abc::N3f>> VerticesNormals;
	
		TArray<UClothingAssetBase*> AssetsInUse;
		SkeletalMeshes[MeshId]->GetClothingAssetsInUse(AssetsInUse);
		const int32 NumMeshAssets = SkeletalMeshes[MeshId]->GetMeshClothingAssets().Num();

		for (int32 BaseAssetIndex = 0; BaseAssetIndex < NumMeshAssets; ++BaseAssetIndex)
		{
			UClothingAssetBase* const InAsset = SkeletalMeshes[MeshId]->GetMeshClothingAssets()[BaseAssetIndex];
			if (InAsset && AssetsInUse.Contains(InAsset))
			{
				AbcPolyMeshes.emplace_back(Alembic::AbcGeom::OPolyMesh(ChaosCacheObject, "cloth" + std::to_string(MeshId) + "_" + std::to_string(BaseAssetIndex), TimeSampPtr));
				// AbcPolyMeshesMaterials.emplace_back(Alembic::AbcMaterial::OMaterial(ChaosCacheObject, "mat" + std::to_string(BaseAssetIndex), TimeSampPtr));
				// Alembic::AbcCoreAbstract::MetaData MatMetaData;
				// Alembic::Abc::OStringProperty MaterialProp(AbcPolyMeshes.back().getSchema().getArbGeomParams(), "DefaultMat");
				// MaterialProp.set("lambert1");
				
				UClothingAssetCommon* const ClothAsset = Cast<UClothingAssetCommon>(InAsset);

				// vertex
				auto & VerticesPosArray = ClothAsset->LodData[0].PhysicalMeshData.Vertices;
				VerticesPoses.emplace_back(std::vector<Alembic::Abc::V3f>(VerticesPosArray.Num()));
				
				// velocity
				VerticesVelocities.emplace_back(std::vector<Alembic::Abc::V3f>(VerticesPosArray.Num()));

				// normal
				auto & VerticesNormalArray = ClothAsset->LodData[0].PhysicalMeshData.Normals;
				std::vector<Alembic::Abc::V3f> VerticesNormal(VerticesNormalArray.Num());
				for(int z = 0; z < VerticesNormalArray.Num(); z++)
				{
					VerticesNormal[z] = {VerticesNormalArray[z].X, VerticesNormalArray[z].Z, -VerticesNormalArray[z].Y};
				}
				VerticesNormals.emplace_back(VerticesNormal);

				// Indices
				auto & Indices = ClothAsset->LodData[0].PhysicalMeshData.Indices;
				std::vector<int> FaceIndice(Indices.Num());
				for(int z = 0; z < Indices.Num(); z++)
				{
					FaceIndice[z] = Indices[z];
				}
				FaceIndices.emplace_back(FaceIndice);
				PolygonCounts.emplace_back(std::vector<int>(FaceIndice.size() / 3, 3));
			}
		}

		AllAbcPolyMeshes.emplace_back(AbcPolyMeshes);
		AllFaceIndices.emplace_back(FaceIndices);
		AllPolygonCounts.emplace_back(PolygonCounts);
		AllVerticesPoses.emplace_back(VerticesPoses);
		AllVerticesVelocities.emplace_back(VerticesVelocities);
		AllVerticesNormals.emplace_back(VerticesNormals);
	}
	
	TArray<UChaosCache*>& ChaosCaches = ChaosCacheCollectionAsset->GetCaches();

	for(int i = 0; i < SampleNum; i++)
	{
		for(int CacheId = 0; CacheId < AllAbcPolyMeshes.size();  CacheId++)
		{
			auto& Cache = ChaosCaches[CacheId];
			auto& [VX] = Cache->ChannelsTracks["VelocityX"];
			auto& [VY] = Cache->ChannelsTracks["VelocityY"];
			auto& [VZ] = Cache->ChannelsTracks["VelocityZ"];
			auto& [PX] = Cache->ChannelsTracks["PositionX"];
			auto& [PY] = Cache->ChannelsTracks["PositionY"];
			auto& [PZ] = Cache->ChannelsTracks["PositionZ"];
			
			int32 PosStart = 0;
			for(int z = 0; z < AllAbcPolyMeshes[CacheId].size(); z++)
			{
				Alembic::AbcGeom::OPolyMeshSchema::Sample MeshSample;

				// Position
				for(int j = 0; j < AllVerticesPoses[CacheId][z].size(); j++)
				{
					const int32 jj = PosStart + j;
					AllVerticesPoses[CacheId][z][j] = {PX[jj].Keys[i].Value, PZ[jj].Keys[i].Value, -PY[jj].Keys[i].Value};
					AllVerticesVelocities[CacheId][z][j] = {VX[jj].Keys[i].Value, VZ[jj].Keys[i].Value, -VY[jj].Keys[i].Value,};
				}

				PosStart += AllVerticesPoses[CacheId][z].size();

				Alembic::Abc::P3fArraySample PosArraySample;
				const Alembic::Abc::V3f* PositionArray = AllVerticesPoses[CacheId][z].data();
				PosArraySample = Alembic::Abc::P3fArraySample(PositionArray, AllVerticesPoses[CacheId][z].size());
				MeshSample.setPositions(PosArraySample);

				// Velocity
				Alembic::Abc::P3fArraySample VelocityArraySample;
				const Alembic::Abc::V3f* VelocityArray = AllVerticesVelocities[CacheId][z].data();
				PosArraySample = Alembic::Abc::P3fArraySample(VelocityArray, AllVerticesVelocities[CacheId][z].size());
				MeshSample.setVelocities((VelocityArraySample));
			
				// Normal
				Alembic::AbcGeom::ON3fGeomParam::Sample NormalSample;
				NormalSample.setScope(Alembic::AbcGeom::kFacevaryingScope);
				const Alembic::Abc::N3f* NormalArray = AllVerticesNormals[CacheId][z].data();
				NormalSample.setVals(Alembic::AbcGeom::N3fArraySample(NormalArray, AllVerticesNormals[CacheId][z].size()));
				NormalSample.setIndices(Alembic::Abc::UInt32ArraySample(reinterpret_cast<const uint32_t*>(AllFaceIndices[CacheId][z].data()), AllFaceIndices[CacheId][z].size()));
				MeshSample.setNormals(NormalSample);
			
				// Triangle
				MeshSample.setFaceCounts(Alembic::Abc::Int32ArraySample(AllPolygonCounts[CacheId][z].data(), AllPolygonCounts[CacheId][z].size()));
				MeshSample.setFaceIndices(Alembic::Abc::Int32ArraySample(AllFaceIndices[CacheId][z].data(), AllFaceIndices[CacheId][z].size()));
		
				AllAbcPolyMeshes[CacheId][z].getSchema().set(MeshSample);
			}
		}
	}

	return true;
}

 

0 Likes
Reply
Accepted solutions (1)
777 Views
2 Replies
Replies (2)

cheng_xi_li
Autodesk Support
Autodesk Support
Accepted solution

Hi huben,

 

I think it was caused by how ABCImport was implemented.

 

When there is an animation in ABC, Maya will create an empty mesh and connect it with an Alembic node to provide animated mesh.

 

However, this routine in the ABCImport isn't working right now, the dagPath couldn't be acquired for setting shading group later. Fortunately, ABCImport is provided as a devkit sample, and we can try to fix it.

 

Find createPoly in the MeshHelper.cpp and replace the !schema.isConstant condition with following code:

 

    if (!schema.isConstant())
    {
        MFloatPointArray emptyPt;
        MIntArray emptyInt;
        MFnMesh fnMesh;
        fnMesh.create(0, 0, emptyPt, emptyInt, emptyInt, iParent);
        fnMesh.setName(name);
        obj = fnMesh.object();
    }

 

I've tested the modified ABCImport with Maya 2024.2, and it seems working fine. If this doesn't work, you can try to remove the animation checking and use the non-animated routine.

 

Hope it helps.

 

Yours,

Li

huben_hb
Observer
Observer
Thank you! And I think it will work!
0 Likes