2017年1月16日月曜日

最も近いメッシュのトランスフォームを取得するテスト

最も近いメッシュのトランスフォームを取得

// AInstancedFoliageActorから最も近いメッシュのトランスフォームを取得するテスト
bool AThirdPersonCppCharacter::FindClosestMeshTransform(FTransform& TM)
{
 bool bFound = false;

// float fMinDist = FLT_MAX;
// float fMinDist = WORLD_MAX;  // Runtime\Engine\Public\EngineDefines.h
 float fMinDist = MAX_flt;  // Runtime\Core\Public\Math\NumericLimits.h

 float fRadius = 50.0 * 100.0f; // 50m
 FVector ActorLocation = GetActorLocation();

 DrawDebugSphere(GWorld, ActorLocation, fRadius, 8, FColor::White, false, 5.0f);

 bool bWorldSpace = true;

 ULevel* Level = GetLevel();
 if(!Level) return false;

 AInstancedFoliageActor* IFA = AInstancedFoliageActor::GetInstancedFoliageActorForLevel(Level);

 for (auto It = IFA->FoliageMeshes.CreateConstIterator(); It; ++It)
 {
  //UFoliageType* Key = It.Key();
  //FFoliageMeshInfo& Value = It.Value();
  FFoliageMeshInfo const* MeshInfo = &*It.Value();

  if (!MeshInfo) {
   continue;
  }
  if(!MeshInfo->Component) {
   continue;
  }

  UHierarchicalInstancedStaticMeshComponent* HISMComponent = MeshInfo->Component;

  TArray<int32> IdxArray = HISMComponent->GetInstancesOverlappingSphere(ActorLocation, fRadius, bWorldSpace);

  for(int32 i = 0; i < IdxArray.Num(); i++)
  {
   FTransform OutInstanceTransform;
    
   if(HISMComponent->GetInstanceTransform(IdxArray[i], OutInstanceTransform, bWorldSpace))
   {
    const FVector& MeshLocation = OutInstanceTransform.GetLocation();

    if(!IsForward(MeshLocation, 0.707f))
    {
     continue;
    }

    float Dist = FVector::Dist(OutInstanceTransform.GetLocation(), ActorLocation);
    if(Dist < fMinDist)
    {
     fMinDist = Dist;
     TM = OutInstanceTransform;

     bFound = true;
    }
   }
  }
 }

 return bFound;
}

球内のフォリッジメッシュを判定

球内のフォリッジメッシュを判定

void AThirdPersonCppCharacter::TestFoliageMeshInSideSphere()
{
 ULevel* Level = GetLevel();

 // フォリッジアクターを取得
 AInstancedFoliageActor* IFA = AInstancedFoliageActor::GetInstancedFoliageActorForLevel(Level);

 FVector vPos = GetActorLocation();
 float fRadius = 10000.0f; // 100m

 FSphere SearchSphere(vPos, fRadius);

 // 球を描画
 DrawDebugSphere(GWorld, vPos, fRadius, 8, FColor::White, false, 5.0f);

 // TMap<UFoliageType*, TUniqueObj<FFoliageMeshInfo>> FoliageMeshes;
 for (auto It = IFA->FoliageMeshes.CreateConstIterator(); It; ++It)
 {
  UFoliageType* Key = It.Key();
  //FFoliageMeshInfo& Value = It.Value();
  FFoliageMeshInfo const* MeshInfo = &*It.Value();

  if (MeshInfo && MeshInfo->Component)
  {
   UHierarchicalInstancedStaticMeshComponent* HISMComponent = MeshInfo->Component;

   for(int32 i = 0; i < HISMComponent->PerInstanceSMData.Num(); i++)
   {
    FVector MeshPos = HISMComponent->PerInstanceSMData[i].Transform.GetOrigin();

    bool bInside = SearchSphere.IsInside(MeshPos);

    FColor color = FColor::Red;
    if(bInside)
    {
     color = FColor::Green;
    }
    DrawDebugLine(GWorld, MeshPos, MeshPos + FVector(0, 0, 10000.0f), color, false, 5.0f);
   }
  }
 } 
}

ターゲットが前か右か判定

ターゲットが前か右か判定

bool AThirdPersonCppCharacter::IsForward(const FVector& vTarget)
{
 bool bForward = false;

 FVector vDir = vTarget - GetActorLocation();
 vDir.Normalize();
 FVector vFwd = GetActorForwardVector();
 float fDot = FVector::DotProduct(vFwd, vDir);
 if ( fDot >= 0.f )
 {
  bForward = true;
 }
 return bForward;
}


bool AThirdPersonCppCharacter::IsRight(const FVector& vTarget)
{
 bool bRight = false;

 FVector vDir = vTarget - GetActorLocation();
 vDir.Normalize();
 FVector vRight = GetActorRightVector();
 float fDot = FVector::DotProduct(vRight, vDir);
 if ( fDot >= 0.f )
 {
  bRight = true;
 }
 return bRight;
}

2017年1月15日日曜日

アクタをターゲット方向に回転

アクタをターゲット方向に回転させるテスト

// fAlpha は FMath::InterpEaseInOut(0.0f, 1.0f, fAlpha, fExp); などで補間

void AThirdPersonCppCharacter::Rot2Target(const FVector& vTarget, float fAlpha)
{
 // Zをゼロにする
 FVector vPos = GetActorLocation();
 FVector vFwd = GetActorForwardVector();
 vFwd.Z = 0.0f;
 vFwd.Normalize();

 FQuat qFwd(vFwd.Rotation());

 FVector vDir = vTarget - vPos;
 vDir.Z = 0.0f;
 vDir.Normalize();

 FQuat qTarget(vDir.Rotation());

 FQuat qResult = FQuat::Slerp(qFwd, qTarget, fAlpha);

 SetActorRotation(qResult);

}