【目标】

植被工具-刷Actor

【思路】

1 添加类型FFoliageMeshInfo.AddInstance 的函数

 

 

2 添加Instance就直接SpawnActor

 

 

3 类结构


 

4 修改的函数

FEdModeFoliage.AddInstancesForBrush.

 

FEdModeFoliage.AddFoliageMesh 

 

 

 

 

【步骤】

1 添加AcheType支持,添加FEdModeFoliage.AddFoliageAcheType 

 

 

2 添加一个AActor的表,用于记录ArcheType

 

  1. var    const native Map_MirrorFoliageArcheTypes{TMap<classAActor*,structFFoliageMeshInfo>};

     

 

 

 

MFoliageEditWindow.OnDrop,资源拖到面板上

 

  1. else
    {
    AActor*ArcheTypeActor=LoadObject<AActor>(NULL,*CurInfo.ObjectPathName, NULL, LOAD_None, NULL);
    if(ArcheTypeActor&&ArchetypeActor->HasAnyFlags(RF_ArchetypeObject))
    {
    FoliageEditSystem->AddFoliageAcheType(ArcheTypeActor);
    FoliageMeshesProperty->NotifyChanged();
    }
    }

     

 
MFoliageEditWindow.OnDragOver 过滤不支持的类型,添加Actor类型的支持
  1. for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter)
    {
    constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter;
    if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&CurInfo.ObjectClass!=AActor::StaticClass())
    {
    Args->Effects=DragDropEffects::None;
    break;
    }

     

还是拖不上去
在MFoliageEditWindow.OnDragEnter 中有
 
 
 
需要设置这个才能调试
 
 

 

MFoliageEditWindow.OnDragOver 改成 IsChildOf 判断

 

  1. voidOnDragOver(Object^Owner,DragEventArgs^Args)
    {
    Args->Effects=DragDropEffects::Copy;
    if(DroppedAssets.Get()!= NULL )
    {
    for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter)
    {
    constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter;
    if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&!CurInfo.ObjectClass->IsChildOf(AActor::StaticClass()))
    {
    Args->Effects=DragDropEffects::None;
    break;
    }
    }
    }
    Args->Handled= TRUE;
    }

     

 

 

 

5 目前拖上去没有效果显示,

MFoliageMeshWrapper 


列表和FEdModeFoliage.GetFoliageMeshList 绑定了,所以显示了FFoliageMeshUIInfo列表

 

 

6 添加FFoliageArcheTypeUIInfo 继承于FFoliageMeshUIInfo 

 

  1. 1 structFFoliageResourceUIInfo:publicFFoliageMeshUIInfo
    2 {
    3 AActor*ArcheTypeActor;
    4 FFoliageResourceUIInfo(UStaticMesh*InStaticMesh,AActor*InArcheTypeActor,FFoliageMeshInfo*InMeshInfo)
    5 :FFoliageMeshUIInfo(InStaticMesh,InMeshInfo)
    6 :ArcheTypeActor(InArcheTypeActor)
    7 {}
    8 };

     

 

 

 

FEdModeFoliage.GetFoliageMeshList 返回值

 

  1. 1 TArray<structFFoliageResourceUIInfo>&GetFoliageMeshList();

     

 

 

FEdModeFoliage.FoliageMeshList 

 

  1. // Placed level data
    TArray<structFFoliageResourceUIInfo>FoliageMeshList;

     

 

 

9

 

  1. 1 IMPLEMENT_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode,{return A.MeshInfo->Settings->DisplayOrder- B.MeshInfo->Settings->DisplayOrder;});
 

 

10 FEdModeFoliage.UpdateFoliageMeshList 

 

  1.  1 voidFEdModeFoliage::UpdateFoliageMeshList()
     2 {
     3 FoliageMeshList.Empty();
     4 AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor();
     5 for(TMap<classUStaticMesh*,structFFoliageMeshInfo>::TIteratorMeshIt(IFA->FoliageMeshes);MeshIt;++MeshIt)
     6 {
     7 new(FoliageMeshList)FFoliageResourceUIInfo(MeshIt.Key(),NULL,&MeshIt.Value());
     8 }
     9 for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt)
    10 {
    11 new(FoliageArcheTypeList)FFoliageResourceUIInfo(NULL,ArcheTypeIt.Key(),&ArcheTypeIt.Value());
    12 }
    13 Sort<USE_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode)>(&FoliageMeshList(0),FoliageMeshList.Num());
    14 }

     

 

 

11 MFoliageMeshWrapper 类构造需要用新类FFoliageResourceUIInfo 

 

  1.  1 ref classMFoliageMeshWrapper:publicINotifyPropertyChanged
     2 {
     3 int index;
     4 FFoliageResourceUIInfo& mesh;
     5 UInstancedFoliageSettings* settings;
     6 BitmapSource^ bitmap;
     7 public:
     8 virtual event PropertyChangedEventHandler^PropertyChanged;
     9 MFoliageMeshWrapper( INT InIndex,FFoliageResourceUIInfo&InMesh)
    10 :    index(InIndex)
    11 ,    mesh(InMesh)
    12 ,    settings(mesh.MeshInfo->Settings)
    13 {
    14 if(mesh.StaticMesh)
    15 bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.StaticMesh);
    16 elseif(mesh.ArcheTypeActor)
    17 bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.ArcheTypeActor);
    18 }

     

 

 

12

 

  1. typedefMEnumerableTArrayWrapper<MFoliageMeshWrapper,FFoliageResourceUIInfo>MFoliageMeshes;

     

 
终于看到效果了
 

 

13 跟FFoliageMeshUIInfo.StaticMesh 相关的修改

MFoliageMeshWrapper.StaticMeshName.get  获取名字的

 

  1. 1 propertyString^StaticMeshName{
    2 String^ get()
    3 {
    4 FStringName= mesh.StaticMesh? mesh.StaticMesh->GetName()? mesh.ArcheTypeActor->GetName();
    5 returnCLRTools::ToString(Name);
    6 }
    7 }

     

 
MFoliageEditWindow.FoliageMeshRemoveButton_Click 
  1.  1 // Remove the current mesh
     2 voidFoliageMeshRemoveButton_Click(Object^Owner,ExecutedRoutedEventArgs^Args)
     3 {
     4 MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
     5 if(Mesh->GetStaticMesh())
     6 FoliageEditSystem->RemoveFoliageMesh(Mesh->GetStaticMesh());
     7 else
     8 FoliageEditSystem->RemoveFoliageAcheType(Mesh->GetArcheTypeActor());
     9 FoliageMeshesProperty->NotifyChanged();
    10 }

     

 
 

 

添加MFoliageMeshWrapper.GetStaticMesh 

 

  1. AActor*GetStaticMesh(){return mesh.ArcheTypeActor;}
 

 

MFoliageEditWindow.FoliageMeshCopySettings_Click 

 

  1. voidFoliageMeshUseSettings_Click(Object^Owner,ExecutedRoutedEventArgs^Args)
    {
    GCallbackEvent->Send(CALLBACK_LoadSelectedAssetsIfNeeded);
    USelection*SelectedSet=GEditor->GetSelectedSet(UInstancedFoliageSettings::StaticClass());
    UInstancedFoliageSettings*SelectedSettings=Cast<UInstancedFoliageSettings>(SelectedSet->GetTop(UInstancedFoliageSettings::StaticClass()));
    if(SelectedSettings!= NULL )
    {
    MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
    if(Mesh->GetStaticMesh())
    FoliageEditSystem->ReplaceSettingsObject(Mesh->GetStaticMesh(),SelectedSettings);
    else
    FoliageEditSystem->ReplaceSettingsObject(Mesh->GetArcheTypeActor(),SelectedSettings);

     

 
MFoliageEditWindow.FoliageMeshReplaceButton_Click 
  1. if(SelectedActor&&SelectedActor->HasAnyFlags(RF_ArchetypeObject))
    {
    MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter);
    FoliageEditSystem->ReplaceArchtypeActor(Mesh->GetArcheTypeActor(),SelectedActor);
    FoliageMeshesProperty->NotifyChanged();
    }

     

 

 

 

 

13 FEdModeFoliage.ReplaceArchtypeActor 

 

  1.  1 voidFEdModeFoliage::ReplaceArchtypeActor(AActor*OldArcheType,AActor*NewArcheType)
     2 {
     3 AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor();
     4 FFoliageMeshInfo*OldMeshInfo= IFA->FoliageArcheTypes.Find(OldArcheType);
     5 if(OldMeshInfo!= NULL &&OldArcheType!=NewArcheType&&NewArcheType->HasAnyFlags(RF_ArchetypeObject))
     6 {
     7 INT InstancesNum=OldMeshInfo->Instances.Num()-OldMeshInfo->FreeInstanceIndices.Num();
     8 // Look for the new mesh in the mesh list, and either create a new mesh or merge the instances.
     9 FFoliageMeshInfo*NewMeshInfo= IFA->FoliageArcheTypes.Find(NewArcheType);
    10 if(NewMeshInfo== NULL )
    11 {
    12 if(InstancesNum>0&&
    13 appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMesh"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes )
    14 {
    15 return;
    16 }
    17 GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction"));
    18 IFA->Modify();
    19 NewMeshInfo= IFA->AddArcheType(NewArcheType);
    20 NewMeshInfo->Settings->DisplayOrder=OldMeshInfo->Settings->DisplayOrder;
    21 NewMeshInfo->Settings->ShowNothing=OldMeshInfo->Settings->ShowNothing;
    22 NewMeshInfo->Settings->ShowPaintSettings=OldMeshInfo->Settings->ShowPaintSettings;
    23 NewMeshInfo->Settings->ShowInstanceSettings=OldMeshInfo->Settings->ShowInstanceSettings;
    24 }
    25 else
    26 if(InstancesNum>0&&
    27 appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMeshMerge"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes )
    28 {
    29 return;
    30 }
    31 else
    32 {
    33 GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction"));
    34 IFA->Modify();
    35 }
    36 if(InstancesNum>0)
    37 {
    38 // copy instances from old to new.
    39 for( INT Idx=0;Idx<OldMeshInfo->Instances.Num();Idx++)
    40 {
    41 if(OldMeshInfo->Instances(Idx).ClusterIndex!=-1)
    42 {
    43 NewMeshInfo->AddInstanceAT( IFA,NewArcheType,OldMeshInfo->Instances(Idx));
    44 }
    45 }
    46 }
    47 // Remove the old mesh.
    48 IFA->RemoveArcheType(OldArcheType);
    49 GEditor->EndTransaction();
    50 // Update mesh list.
    51 UpdateFoliageMeshList();
    52 }
    53 }

     

 

 

 

14 添加FFoliageMeshInfo.AddInstanceAT 

 

  1. 1 voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InActor,constFFoliageInstance&InNewInstance)
    2 {
    3 }

     

 

 

 

目前是刷不上Actor模型吗,主要是FEdModeFoliage.ApplyBrush 函数里没有处理

15 修改FEdModeFoliage.ApplyBrush 

 

  1.  1 // ArcheType
     2 for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt)
     3 {
     4 FFoliageMeshInfo&MeshInfo=ArcheTypeIt.Value();
     5 UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings;
     6 if(MeshSettings->IsSelected)
     7 {
     8 // Find the instances already in the area.
     9 TArray<INT>Instances;
    10 FSphereBrushSphere(BrushLocation,UISettings.GetRadius());
    11 MeshInfo.GetInstancesInsideSphere(BrushSphere,Instances);
    12 if(UISettings.GetLassoSelectToolSelected())
    13 {
    14 // Shift unpaints
    15 MeshInfo.SelectInstances( IFA,!IsShiftDown(ViewportClient->Viewport),Instances);
    16 }
    17 else
    18 if(UISettings.GetReapplyToolSelected())
    19 {
    20 if(MeshSettings->ReapplyDensity)
    21 {
    22 // Adjust instance density
    23 FMeshInfoSnapshot*SnapShot=InstanceATSnapshot.Find(ArcheTypeIt.Key());
    24 if(SnapShot)
    25 {
    26 // Use snapshot to determine number of instances at the start of the brush stroke
    27 INT NewInstanceCount= appRound((FLOAT)SnapShot->CountInstancesInsideSphere(BrushSphere)*MeshSettings->ReapplyDensityAmount);
    28 if(MeshSettings->ReapplyDensityAmount>1.f&&NewInstanceCount>Instances.Num())
    29 {
    30 AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,NewInstanceCount,Instances,Pressure);
    31 }
    32 else
    33 if(MeshSettings->ReapplyDensityAmount<1.f&&NewInstanceCount<Instances.Num())
    34 {
    35 RemoveInstancesForBrush( IFA,MeshInfo,NewInstanceCount,Instances,Pressure);
    36 }
    37 }
    38 }
    39 // Reapply any settings checked by the user
    40 ReapplyInstancesForBrush( IFA,MeshInfo,Instances);
    41 }
    42 else
    43 if(UISettings.GetPaintToolSelected())
    44 {
    45 // Shift unpaints
    46 if(IsShiftDown(ViewportClient->Viewport))
    47 {
    48 INT DesiredInstanceCount= appRound(BrushArea*MeshSettings->Density*UISettings.GetUnpaintDensity()/(1000.f*1000.f));
    49 if(DesiredInstanceCount<Instances.Num())
    50 {
    51 RemoveInstancesForBrush( IFA,MeshInfo,DesiredInstanceCount,Instances,Pressure);
    52 }
    53 }
    54 else
    55 {
    56 // This is the total set of instances disregarding parameters like slope, height or layer.
    57 FLOAT DesiredInstanceCountFloat=BrushArea*MeshSettings->Density*UISettings.GetPaintDensity()/(1000.f*1000.f);
    58 // Allow a single instance with a random chance, if the brush is smaller than the density
    59 INT DesiredInstanceCount=DesiredInstanceCountFloat>1.f? appRound(DesiredInstanceCountFloat): appFrand()<DesiredInstanceCountFloat?1:0;
    60 AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,DesiredInstanceCount,Instances,Pressure);
    61 }
    62 }
    63 }
    64 }

     

 

 

 

16 添加Instance的函数FEdModeFoliage.AddInstancesATForBrush 

 

  1.   1 /** Add instances inside the brush to match DesiredInstanceCount */
      2 voidFEdModeFoliage::AddInstancesATForBrush(AInstancedFoliageActor* IFA,AActor*AchetypeActor,FFoliageMeshInfo&MeshInfo, INT DesiredInstanceCount,TArray<INT>&ExistingInstances, FLOAT Pressure)
      3 {
      4 UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings;
      5 if(DesiredInstanceCount>ExistingInstances.Num())
      6 {
      7 INT ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS];
      8 appMemzero(ExistingInstanceBuckets,sizeof(ExistingInstanceBuckets));
      9 // Cache store mapping between component and weight data
     10 TMap<ULandscapeComponent*,TArray<BYTE>>*LandscapeLayerCache= NULL;
     11 FNameLandscapeLayerName=MeshSettings->LandscapeLayer;
     12 if(LandscapeLayerName!= NAME_None )
     13 {
     14 LandscapeLayerCache=&LandscapeLayerCaches.FindOrAdd(LandscapeLayerName);
     15 // Find the landscape weights of existing ExistingInstances
     16 for( INT Idx=0;Idx<ExistingInstances.Num();Idx++)
     17 {
     18 FFoliageInstance&Instance=MeshInfo.Instances(ExistingInstances(Idx));
     19 ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Instance.Base);
     20 if(HitLandscapeCollision)
     21 {
     22 ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent();
     23 if(HitLandscape)
     24 {
     25 TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape);
     26 FLOAT HitWeight=HitLandscape->GetLayerWeightAtLocation(Instance.Location,LandscapeLayerName,LayerCache);
     27 // Add count to bucket.
     28 ExistingInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-1))]++;
     29 }
     30 }
     31 }
     32 }
     33 else
     34 {
     35 // When not tied to a layer, put all the ExistingInstances in the last bucket.
     36 ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS-1]=ExistingInstances.Num();
     37 }
     38 // We calculate a set of potential ExistingInstances for the brush area.
     39 TArray<FPotentialInstance>PotentialInstanceBuckets[NUM_INSTANCE_BUCKETS];
     40 appMemzero(PotentialInstanceBuckets,sizeof(PotentialInstanceBuckets));
     41 // Quick lookup of potential instance locations, used for overlapping check.
     42 TArray<FVector>PotentialInstanceLocations;
     43 FFoliageInstanceHashPotentialInstanceHash(7);// use 128x128 cell size, as the brush radius is typically small.
     44 PotentialInstanceLocations.Empty(DesiredInstanceCount);
     45 // Radius where we expect to have a single instance, given the density rules
     46 const FLOAT DensityCheckRadius=Max<FLOAT>( appSqrt((1000.f*1000.f)/(PI *MeshSettings->Density)),MeshSettings->Radius);
     47 for( INT DesiredIdx=0;DesiredIdx<DesiredInstanceCount;DesiredIdx++)
     48 {
     49 FVectorStart,End;
     50 GetRandomVectorInBrush(Start,End);
     51 FCheckResultHit;
     52 if(!GWorld->SingleLineCheck(Hit, NULL,End,Start, TRACE_World | TRACE_Level,FVector(0.f,0.f,0.f), NULL))
     53 {
     54 // Check filters
     55 if((Hit.Component&&
     56 (Hit.Component->GetOutermost()!=GWorld->CurrentLevel->GetOutermost()||
     57 (!UISettings.bFilterLandscape &&Hit.Component->IsA(ULandscapeHeightfieldCollisionComponent::StaticClass()))||
     58 (!UISettings.bFilterStaticMesh &&Hit.Component->IsA(UStaticMeshComponent::StaticClass()))||
     59 (!UISettings.bFilterTerrain &&Hit.Component->IsA(UTerrainComponent::StaticClass()))))||
     60 (Hit.Actor&&Hit.Actor->IsA(AWorldInfo::StaticClass())&&(!UISettings.bFilterBSP ||GWorld->Levels(Hit.LevelIndex)!=GWorld->CurrentLevel)))
     61 {
     62 continue;
     63 }
     64 if(!CheckLocationForPotentialInstance(MeshInfo,MeshSettings,DensityCheckRadius,Hit.Location,Hit.Normal,PotentialInstanceLocations,PotentialInstanceHash))
     65 {
     66 continue;
     67 }
     68 // Check landscape layer
     69 FLOAT HitWeight=1.f;
     70 if(LandscapeLayerName!= NAME_None )
     71 {
     72 ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Hit.Component);
     73 if(HitLandscapeCollision)
     74 {
     75 ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent();
     76 if(HitLandscape)
     77 {
     78 TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape);
     79 HitWeight=HitLandscape->GetLayerWeightAtLocation(Hit.Location,LandscapeLayerName,LayerCache);
     80 // Reject instance randomly in proportion to weight
     81 if(HitWeight<= appFrand())
     82 {
     83 continue;
     84 }
     85 }
     86 }
     87 }
     88 new(PotentialInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-1))])FPotentialInstance(Hit.Location,Hit.Normal,Hit.Component,HitWeight);
     89 }
     90 }
     91 for( INT BucketIdx=0;BucketIdx< NUM_INSTANCE_BUCKETS;BucketIdx++)
     92 {
     93 TArray<FPotentialInstance>&PotentialInstances=PotentialInstanceBuckets[BucketIdx];
     94 FLOAT BucketFraction=(FLOAT)(BucketIdx+1)/(FLOAT)NUM_INSTANCE_BUCKETS;
     95 // We use the number that actually succeeded in placement (due to parameters) as the target
     96 // for the number that should be in the brush region.
     97 INT AdditionalInstances=Clamp<INT>( appRound(BucketFraction*(FLOAT)(PotentialInstances.Num()-ExistingInstanceBuckets[BucketIdx])*Pressure),0,PotentialInstances.Num());
     98 for( INT Idx=0;Idx<AdditionalInstances;Idx++)
     99 {
    100 FFoliageInstanceInst=PotentialInstances(Idx).PlaceInstance(MeshSettings);
    101 MeshInfo.AddInstanceAT( IFA,AchetypeActor,Inst);
    102 }
    103 }
    104 }
    105 }

     

 
17 在FFoliageInstanceCluster 上添加Actor列表成员

 

 

  1.  1 structFFoliageInstanceCluster
     2 {
     3 UInstancedStaticMeshComponent*ClusterComponent;
     4 TArray<AActor*>ActorInstances;
     5 FFoliageInstanceCluster.GetInstanceCount 
     6 INT GetInstanceCount()
     7 {
     8 INT TotalCount=0;
     9 if(ClusterComponent)
    10 TotalCount+=ClusterComponent->PerInstanceSMData.Num();
    11 TotalCount+=ActorInstances.Num();
    12 }

     

 
 

 

 

18 添加FFoliageMeshInfo.AddInstanceAT 

  1.  1 voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InArchetypeActor,constFFoliageInstance&InNewInstance)
     2 {
     3 InIFA->Modify();
     4 // Add the instance taking either a free slot or adding a new item.
     5 INT InstanceIndex=FreeInstanceIndices.Num()>0?FreeInstanceIndices.Pop():Instances.Add();
     6 FFoliageInstance&AddedInstance=Instances(InstanceIndex);
     7 AddedInstance=InNewInstance;
     8 // Add the instance to the hash
     9 InstanceHash->InsertInstance(InNewInstance.Location,InstanceIndex);
    10 FFoliageComponentHashInfo&ComponentHashInfo=ComponentHash.FindOrAddKey(InNewInstance.Base);
    11 ComponentHashInfo.Instances.Add(InstanceIndex);
    12 // Find the best cluster to allocate the instance to.
    13 FFoliageInstanceCluster*BestCluster= NULL;
    14 INT BestClusterIndex= INDEX_NONE;
    15 FLOAT BestClusterDistSq= FLT_MAX;
    16 INT MaxInstancesPerCluster=Settings->MaxInstancesPerCluster;
    17 FLOAT MaxClusterRadiusSq=Square(Settings->MaxClusterRadius);
    18 for( INT ClusterIdx=0;ClusterIdx<InstanceClusters.Num();ClusterIdx++)
    19 {
    20 FFoliageInstanceCluster&Cluster=InstanceClusters(ClusterIdx);
    21 if(Cluster.InstanceIndices.Num()<MaxInstancesPerCluster)
    22 {
    23 FLOAT DistSq=(Cluster.Bounds.Origin-InNewInstance.Location).SizeSquared();
    24 if(DistSq<BestClusterDistSq&&DistSq<MaxClusterRadiusSq)
    25 {
    26 BestCluster=&Cluster;
    27 BestClusterIndex=ClusterIdx;
    28 BestClusterDistSq=DistSq;
    29 }
    30 }
    31 }
    32 // Calculate transform for the instance
    33 FMatrixInstanceTransform=InNewInstance.GetInstanceTransform();
    34 if(BestCluster== NULL )
    35 {
    36 BestClusterIndex=InstanceClusters.Num();
    37 BestCluster=new(InstanceClusters)FFoliageInstanceCluster(
    38 NULL,
    39 FBoxSphereBounds()// LWF_TODO
    40 );
    41 //ApplyInstancedFoliageSettings( BestCluster->ClusterComponent );
    42 }
    43 else
    44 {
    45 // BestCluster->ClusterComponent->Modify();
    46 // BestCluster->ClusterComponent->InvalidateLightingCache();
    47 // BestCluster->Bounds = BestCluster->Bounds + InMesh->Bounds.TransformBy(InstanceTransform);
    48 }
    49 BestCluster->InstanceIndices.AddItem(InstanceIndex);
    50 // Save the cluster index
    51 AddedInstance.ClusterIndex=BestClusterIndex;
    52 // Add the instance to the ActorList
    53 AActor* pActor =GWorld->SpawnActor(InArchetypeActor->GetClass(), NAME_None,InNewInstance.Location,InNewInstance.Rotation,InArchetypeActor);// Spawn Actor
    54 BestCluster->ActorInstances.AddItem(pActor);
    55 // FInstancedStaticMeshInstanceData* NewInstanceData = new(BestCluster->ClusterComponent->PerInstanceSMData) FInstancedStaticMeshInstanceData();
    56 if(BestCluster->ClusterComponent->SelectedInstances.Num()>0)
    57 {
    58 BestCluster->ClusterComponent->SelectedInstances.AddItem(FALSE);
    59 }
    60 // NewInstanceData->Transform = InstanceTransform;
    61 // NewInstanceData->LightmapUVBias = FVector2D( -1.0f, -1.0f );
    62 // NewInstanceData->ShadowmapUVBias = FVector2D( -1.0f, -1.0f );
    63 // BestCluster->ClusterComponent->bNeedsReattach = TRUE;
    64 #if _DEBUG
    65 CheckValid();
    66 #endif
    67 InIFA->ConditionalUpdateComponents();
    68 }

     

 

 

 

 

18 修改所有FFoliageInstanceCluster.ClusterComponent 的地方

太多地方了

 

FFoliageMeshInfo.CheckValid 

 

终于能刷出东西来了


 

 



posted on 2016-08-30 11:07  维尔福  阅读(1006)  评论(0编辑  收藏  举报