Files
2025-05-18 13:04:45 +08:00

113 lines
3.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "GetGroomAssetNode.h"
#include "GroomEdit.h"
#include "GroomInstance.h"
#include "GroomCollectionFacades.h"
#include "Dataflow/DataflowInputOutput.h"
#include "Dataflow/DataflowObjectInterface.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GetGroomAssetNode)
namespace UE::Groom::Private
{
template<typename FacadeType>
FORCEINLINE const UGroomAsset* BuildGroomCollection(Dataflow::FContext& Context, const UGroomAsset* NodeGroom, FManagedArrayCollection& GroomCollection, FEditableGroom& EditGroom)
{
const UGroomAsset* GroomAsset = NodeGroom;
if (!GroomAsset)
{
if (const Dataflow::FEngineContext* EngineContext = Context.AsType<Dataflow::FEngineContext>())
{
GroomAsset = Cast<UGroomAsset>(EngineContext->Owner);
}
}
if (GroomAsset)
{
ConvertFromGroomAsset(const_cast<UGroomAsset*>(GroomAsset), &EditGroom, false, false, false);
TArray<FVector3f> PointRestPositions;
TArray<int32> ObjectCurveOffsets;
TArray<int32> CurvePointOffsets;
TArray<FString> ObjectGroupNames;
uint32 GroupIndex = 0;
for(FEditableGroomGroup& GroomGroup : EditGroom.Groups)
{
for( const typename FacadeType::FEditableType& EditType : FacadeType::GetEditableGroom(GroomGroup))
{
for(auto& GuidePoint : EditType.ControlPoints)
{
PointRestPositions.Add(GuidePoint.Position);
}
CurvePointOffsets.Add(PointRestPositions.Num());
}
ObjectCurveOffsets.Add(CurvePointOffsets.Num());
const FString GroupName = GroomAsset->GetName() + TEXT("_") + FacadeType::GroupPrefix.ToString();
ObjectGroupNames.Add(GroupName);
++GroupIndex;
}
FacadeType CurvesFacade(GroomCollection);
CurvesFacade.InitGroomCollection(PointRestPositions, CurvePointOffsets, ObjectCurveOffsets, ObjectGroupNames);
const FString GroomName = GroomAsset->GetName();
return GroomAsset;
}
return nullptr;
}
}
void FGetGroomAssetDataflowNode::Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const
{
if (Out->IsA<FManagedArrayCollection>(&Collection))
{
FManagedArrayCollection GroomCollection;
FEditableGroom EditGroom;
const UGroomAsset* LocalGroom = nullptr;
if(CurvesType == EGroomCollectionType::Guides)
{
LocalGroom = UE::Groom::Private::BuildGroomCollection<UE::Groom::FGroomGuidesFacade>(
Context, GroomAsset, GroomCollection, EditGroom);
}
else if(CurvesType == EGroomCollectionType::Strands)
{
LocalGroom = UE::Groom::Private::BuildGroomCollection<UE::Groom::FGroomStrandsFacade>(
Context, GroomAsset, GroomCollection, EditGroom);
}
if(LocalGroom)
{
TArray<int32> ObjectPointSamples, CurveStrandIndices;
const TArray<FHairGroupsPhysics>& GroupsPhysics = LocalGroom->GetHairGroupsPhysics();
for(const FHairGroupsPhysics& GroupPhysics : GroupsPhysics)
{
ObjectPointSamples.Add(static_cast<uint8>(GroupPhysics.StrandsParameters.StrandsSize));
}
UE::Groom::FGroomGuidesFacade GuidesFacade(GroomCollection);
if(GroomCollection.NumElements(UE::Groom::FGroomGuidesFacade::ObjectsGroup) == 0)
{
GroomCollection.AddElements(ObjectPointSamples.Num(), UE::Groom::FGroomGuidesFacade::ObjectsGroup);
}
GuidesFacade.SetObjectPointSamples(ObjectPointSamples);
}
SetValue(Context, MoveTemp(GroomCollection), &Collection);
}
}
TArray<UE::Dataflow::FRenderingParameter> FGetGroomAssetDataflowNode::GetRenderParametersImpl() const
{
if(CurvesType == EGroomCollectionType::Guides)
{
return { {TEXT("GuidesRender"), FName("FGroomCollection"), {TEXT("Collection")}}};
}
else
{
return { {TEXT("StrandsRender"), FName("FGroomCollection"), {TEXT("Collection")}}};
}
}