- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
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!
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;
}
Solved! Go to Solution.