FBoxSphereBounds UPaperFlipbookComponent::CalcBounds(const FTransform& LocalToWorld) const { if (SourceFlipbook != nullptr) { // Graphics bounds. FBoxSphereBounds NewBounds = SourceFlipbook->GetRenderBounds().TransformBy(LocalToWorld); // Add bounds of collision geometry (if present). if (CachedBodySetup != nullptr) { const FBox AggGeomBox = CachedBodySetup->AggGeom.CalcAABB(LocalToWorld); if (AggGeomBox.IsValid) { NewBounds = Union(NewBounds, FBoxSphereBounds(AggGeomBox)); } } // Apply bounds scale NewBounds.BoxExtent *= BoundsScale; NewBounds.SphereRadius *= BoundsScale; return NewBounds; } else { return FBoxSphereBounds(LocalToWorld.GetLocation(), FVector::ZeroVector, 0.f); } }
void UGeometryCacheComponent::UpdateLocalBounds() { FBox LocalBox(0); for (const FTrackRenderData& Section : TrackSections) { // Use World matrix per section for correct bounding box LocalBox += (Section.MeshData->BoundingBox.TransformBy(Section.WorldMatrix)); } LocalBounds = LocalBox.IsValid ? FBoxSphereBounds(LocalBox) : FBoxSphereBounds(FVector(0, 0, 0), FVector(0, 0, 0), 0); // fallback to reset box sphere bounds UpdateBounds(); }
FBoxSphereBounds UParametricSurfaceComponent::CalcBounds(const FTransform& LocalToWorld) const { const auto Radius = 100.0f; const auto PosMax = FVector(Radius, Radius, Radius); const auto PosMin = -PosMax; const auto Center = (PosMin + PosMax) * 0.5f; const auto Extent = PosMax - PosMin; #if 0 const auto BSB = FBoxSphereBounds(Center, Extent, Extent.Size()).TransformBy(LocalToWorld); const auto Box = BSB.GetBox(); DrawDebugBox(GetWorld(), Box.GetCenter(), Box.GetExtent(), FColor::Green, true); return BSB; #else return FBoxSphereBounds(Center, Extent, Extent.Size()).TransformBy(LocalToWorld); #endif }
FBoxSphereBounds UPaperGroupedSpriteComponent::CalcBounds(const FTransform& BoundTransform) const { bool bHadAnyBounds = false; FBoxSphereBounds NewBounds(ForceInit); if (PerInstanceSpriteData.Num() > 0) { const FMatrix BoundTransformMatrix = BoundTransform.ToMatrixWithScale(); for (const FSpriteInstanceData& InstanceData : PerInstanceSpriteData) { if (InstanceData.SourceSprite != nullptr) { const FBoxSphereBounds RenderBounds = InstanceData.SourceSprite->GetRenderBounds(); const FBoxSphereBounds InstanceBounds = RenderBounds.TransformBy(InstanceData.Transform * BoundTransformMatrix); if (bHadAnyBounds) { NewBounds = NewBounds + InstanceBounds; } else { NewBounds = InstanceBounds; bHadAnyBounds = true; } } } } return bHadAnyBounds ? NewBounds : FBoxSphereBounds(BoundTransform.GetLocation(), FVector::ZeroVector, 0.f); }
FBoxSphereBounds UNavMeshRenderingComponent::CalcBounds(const FTransform& LocalToWorld) const { FBox BoundingBox(0); #if WITH_RECAST ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(GetOwner()); if (NavMesh) { BoundingBox = NavMesh->GetNavMeshBounds(); if (NavMesh->bDrawOctree) { const UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); const FNavigationOctree* NavOctree = NavSys ? NavSys->GetNavOctree() : NULL; if (NavOctree) { for (FNavigationOctree::TConstIterator<> NodeIt(*NavOctree); NodeIt.HasPendingNodes(); NodeIt.Advance()) { const FOctreeNodeContext& CorrentContext = NodeIt.GetCurrentContext(); BoundingBox += CorrentContext.Bounds.GetBox(); } } } } #endif return FBoxSphereBounds(BoundingBox); }
FBoxSphereBounds UPaperTerrainComponent::CalcBounds(const FTransform& LocalToWorld) const { // Determine the rendering bounds FBoxSphereBounds LocalRenderBounds; { FBox BoundingBox(ForceInit); for (const FPaperTerrainSpriteGeometry& DrawCall : GeneratedSpriteGeometry) { for (const FSpriteDrawCallRecord& Record : DrawCall.Records) { for (const FVector4& VertXYUV : Record.RenderVerts) { const FVector Vert((PaperAxisX * VertXYUV.X) + (PaperAxisY * VertXYUV.Y)); BoundingBox += Vert; } } } // Make the whole thing a single unit 'deep' const FVector HalfThicknessVector = 0.5f * PaperAxisZ; BoundingBox.Min -= HalfThicknessVector; BoundingBox.Max += HalfThicknessVector; LocalRenderBounds = FBoxSphereBounds(BoundingBox); } // Graphics bounds. FBoxSphereBounds NewBounds = LocalRenderBounds.TransformBy(LocalToWorld); // Add bounds of collision geometry (if present). if (CachedBodySetup != nullptr) { const FBox AggGeomBox = CachedBodySetup->AggGeom.CalcAABB(LocalToWorld); if (AggGeomBox.IsValid) { NewBounds = Union(NewBounds, FBoxSphereBounds(AggGeomBox)); } } // Apply bounds scale NewBounds.BoxExtent *= BoundsScale; NewBounds.SphereRadius *= BoundsScale; return NewBounds; }
FBoxSphereBounds UVoxelComponent::CalcBounds(const FTransform& LocalToWorld) const { FBoxSphereBounds Bounds = FBoxSphereBounds(ForceInit); for (auto* InstancedStaticMeshComponent : InstancedStaticMeshComponents) { Bounds = Bounds + InstancedStaticMeshComponent->CalcBounds(LocalToWorld); } return Bounds; }
FBoxSphereBounds UNavLinkRenderingComponent::CalcBounds(const FTransform& InLocalToWorld) const { AActor* LinkOwnerActor = Cast<AActor>(GetOwner()); INavLinkHostInterface* LinkOwnerHost = Cast<INavLinkHostInterface>(GetOwner()); if (LinkOwnerActor != NULL && LinkOwnerHost != NULL) { FBox BoundingBox(0); const FTransform LocalToWorld = LinkOwnerActor->ActorToWorld(); TArray<TSubclassOf<UNavLinkDefinition> > NavLinkClasses; TArray<FNavigationLink> SimpleLinks; TArray<FNavigationSegmentLink> DummySegmentLinks; if (LinkOwnerHost->GetNavigationLinksClasses(NavLinkClasses)) { for (int32 NavLinkClassIdx = 0; NavLinkClassIdx < NavLinkClasses.Num(); ++NavLinkClassIdx) { if (NavLinkClasses[NavLinkClassIdx] != NULL) { const TArray<FNavigationLink>& Links = UNavLinkDefinition::GetLinksDefinition(NavLinkClasses[NavLinkClassIdx]); for (const auto& Link : Links) { BoundingBox += Link.Left; BoundingBox += Link.Right; } } } } if (LinkOwnerHost->GetNavigationLinksArray(SimpleLinks, DummySegmentLinks)) { for (const auto& Link : SimpleLinks) { BoundingBox += Link.Left; BoundingBox += Link.Right; } } return FBoxSphereBounds(BoundingBox).TransformBy(LocalToWorld); } return FBoxSphereBounds(EForceInit::ForceInitToZero); }
FBoxSphereBounds UPaperTileMapRenderComponent::CalcBounds(const FTransform& LocalToWorld) const { //@TODO: Tile pivot issue //@TODO: Layer thickness issue const float HalfThickness = 2.0f; const FVector TopLeft((-0.5f)*TileWidth, -HalfThickness, -(MapHeight - 0.5f) * TileHeight); const FVector Dimenisons(MapWidth*TileWidth, 2*HalfThickness, MapHeight * TileHeight); const FBox Box(TopLeft, TopLeft + Dimenisons); return FBoxSphereBounds(Box.TransformBy(LocalToWorld)); }
FBoxSphereBounds UNavMeshRenderingComponent::CalcBounds(const FTransform & LocalToWorld) const { FBox BoundingBox(0); #if WITH_RECAST ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(GetOwner()); if (NavMesh) { BoundingBox = NavMesh->GetNavMeshBounds(); } #endif return FBoxSphereBounds(BoundingBox); }
FBoxSphereBounds UPaperTileMap::GetRenderBounds() const { const float Depth = SeparationPerLayer * (TileLayers.Num() - 1); const float HalfThickness = 2.0f; const float UnrealUnitsPerPixel = GetUnrealUnitsPerPixel(); const float TileWidthInUU = TileWidth * UnrealUnitsPerPixel; const float TileHeightInUU = TileHeight * UnrealUnitsPerPixel; switch (ProjectionMode) { case ETileMapProjectionMode::Orthogonal: default: { const FVector BottomLeft((-0.5f) * TileWidthInUU, -HalfThickness - Depth, -(MapHeight - 0.5f) * TileHeightInUU); const FVector Dimensions(MapWidth * TileWidthInUU, Depth + 2 * HalfThickness, MapHeight * TileHeightInUU); const FBox Box(BottomLeft, BottomLeft + Dimensions); return FBoxSphereBounds(Box); } case ETileMapProjectionMode::IsometricDiamond: { const FVector BottomLeft((-0.5f) * TileWidthInUU * MapWidth, -HalfThickness - Depth, -MapHeight * TileHeightInUU); const FVector Dimensions(MapWidth * TileWidthInUU, Depth + 2 * HalfThickness, (MapHeight + 1) * TileHeightInUU); const FBox Box(BottomLeft, BottomLeft + Dimensions); return FBoxSphereBounds(Box); } case ETileMapProjectionMode::HexagonalStaggered: case ETileMapProjectionMode::IsometricStaggered: { const int32 RoundedHalfHeight = (MapHeight + 1) / 2; const FVector BottomLeft((-0.5f) * TileWidthInUU, -HalfThickness - Depth, -(RoundedHalfHeight) * TileHeightInUU); const FVector Dimensions((MapWidth + 0.5f) * TileWidthInUU, Depth + 2 * HalfThickness, (RoundedHalfHeight + 1.0f) * TileHeightInUU); const FBox Box(BottomLeft, BottomLeft + Dimensions); return FBoxSphereBounds(Box); } } }
FBoxSphereBounds UCubiquityMeshComponent::CalcBounds(const FTransform & LocalToWorld) const { //UE_LOG(CubiquityLog, Log, TEXT("UCubiquityMeshComponent::CalcBounds")); /*FBoxSphereBounds NewBounds; NewBounds.Origin = FVector::ZeroVector; NewBounds.BoxExtent = FVector(HALF_WORLD_MAX, HALF_WORLD_MAX, HALF_WORLD_MAX); NewBounds.SphereRadius = FMath::Sqrt(3.0f * FMath::Square(HALF_WORLD_MAX)); return NewBounds;*/ //FVector BoxPoint = FVector(100, 100, 100); /*const FVector UnitV(1, 1, 1); const FBox VeryVeryBig(-UnitV * HALF_WORLD_MAX, UnitV * HALF_WORLD_MAX); return FBoxSphereBounds(VeryVeryBig);*/ return FBoxSphereBounds(FBox(FVector(-128, -128, -128), FVector(128, 128, 128))).TransformBy(LocalToWorld); //TODO check this for each node... }
FBoxSphereBounds UDestructibleComponent::CalcBounds(const FTransform& LocalToWorld) const { #if WITH_APEX if( ApexDestructibleActor == NULL ) { // Fallback if we don't have physics return Super::CalcBounds(LocalToWorld); } const PxBounds3& PBounds = ApexDestructibleActor->getBounds(); return FBoxSphereBounds( FBox( P2UVector(PBounds.minimum), P2UVector(PBounds.maximum) ) ); #else // #if WITH_APEX return Super::CalcBounds(LocalToWorld); #endif // #if WITH_APEX }
FBoxSphereBounds UTextRenderComponent::CalcBounds(const FTransform& LocalToWorld) const { if(!Text.IsEmpty() && Font) { FVector2D Size(FLT_MIN, 0); FVector2D LeftTop(FLT_MAX, FLT_MAX); float FirstLineHeight = -1; FTextIterator It(*Text.ToString()); float AdjustedXScale = WorldSize * XScale * InvDefaultSize; float AdjustedYScale = WorldSize * YScale * InvDefaultSize; while (It.NextLine()) { FVector2D LineSize = ComputeTextSize(It, Font, AdjustedXScale, AdjustedYScale, HorizSpacingAdjust); float LineLeft = ComputeHorizontalAlignmentOffset(LineSize, HorizontalAlignment); Size.X = FMath::Max(LineSize.X, Size.X); Size.Y += LineSize.Y > 0 ? LineSize.Y : Font->GetMaxCharHeight(); LeftTop.X = FMath::Min(LeftTop.X, LineLeft); if (FirstLineHeight < 0) { FirstLineHeight = LineSize.Y; } int32 Ch; while (It.NextCharacterInLine(Ch)); } LeftTop.Y = ComputeVerticalAlignmentOffset(Size.Y, VerticalAlignment, FirstLineHeight); FBox LocalBox(FVector(0, -LeftTop.X, -LeftTop.Y), FVector(0, -(LeftTop.X + Size.X), -(LeftTop.Y + Size.Y))); FBoxSphereBounds Ret(LocalBox.TransformBy(LocalToWorld)); Ret.BoxExtent *= BoundsScale; Ret.SphereRadius *= BoundsScale; return Ret; } else { return FBoxSphereBounds(ForceInit); } }
FBoxSphereBounds UDebugSkelMeshComponent::CalcBounds(const FTransform& LocalToWorld) const { FBoxSphereBounds Result = Super::CalcBounds(LocalToWorld); if (! IsUsingInGameBounds()) { // extend bounds by bones but without root bone FBox BoundingBox(0); for (int32 BoneIndex = 1; BoneIndex < SpaceBases.Num(); ++ BoneIndex) { BoundingBox += GetBoneMatrix(BoneIndex).GetOrigin(); } Result = Result + FBoxSphereBounds(BoundingBox); } return Result; }
/** * Sets up a projected shadow initializer for shadows from the entire scene. * @return True if the whole-scene projected shadow should be used. */ virtual bool GetWholeSceneProjectedShadowInitializer(const FSceneViewFamily& ViewFamily, TArray<FWholeSceneProjectedShadowInitializer, TInlineAllocator<6> >& OutInitializers) const override { FWholeSceneProjectedShadowInitializer& OutInitializer = *new(OutInitializers) FWholeSceneProjectedShadowInitializer; OutInitializer.PreShadowTranslation = -GetLightToWorld().GetOrigin(); OutInitializer.WorldToLight = GetWorldToLight().RemoveTranslation(); OutInitializer.Scales = FVector(1.0f,InvTanOuterCone,InvTanOuterCone); OutInitializer.FaceDirection = FVector(1,0,0); OutInitializer.SubjectBounds = FBoxSphereBounds( GetLightToWorld().RemoveTranslation().TransformPosition(FVector(Radius, 0, 0)), FVector(Radius, Radius, Radius), Radius ); OutInitializer.WAxis = FVector4(0,0,1,0); OutInitializer.MinLightW = 0.1f; OutInitializer.MaxDistanceToCastInLightW = Radius; OutInitializer.CascadeSettings.bRayTracedDistanceField = UseRayTracedDistanceFieldShadows() && DoesPlatformSupportDistanceFieldShadowing(ViewFamily.GetShaderPlatform()); return true; }
FBoxSphereBounds UPaperSprite::GetRenderBounds() const { FBox BoundingBox(ForceInit); for (int32 VertexIndex = 0; VertexIndex < BakedRenderData.Num(); ++VertexIndex) { const FVector4& VertXYUV = BakedRenderData[VertexIndex]; const FVector Vert((PaperAxisX * VertXYUV.X) + (PaperAxisY * VertXYUV.Y)); BoundingBox += Vert; } // Make the whole thing a single unit 'deep' const FVector HalfThicknessVector = 0.5f * PaperAxisZ; BoundingBox.Min -= HalfThicknessVector; BoundingBox.Max += HalfThicknessVector; return FBoxSphereBounds(BoundingBox); }
void UVoxelComponent::InitVoxel() { CellBounds = FBoxSphereBounds(FVector::ZeroVector, FVector(100.f, 100.f, 100.f), 100.f); Mesh.Empty(); Cell.Empty(); InstancedStaticMeshComponents.Empty(); if (Voxel) { CellBounds = Voxel->CellBounds; Mesh = Voxel->Mesh; Cell = Voxel->Voxel; for (int32 i = 0; i < Mesh.Num(); ++i) { UInstancedStaticMeshComponent* Proxy = NewObject<UInstancedStaticMeshComponent>(this, NAME_None, RF_Transactional); Proxy->SetStaticMesh(Mesh[i]); Proxy->AttachTo(GetOwner()->GetRootComponent(), NAME_None); InstancedStaticMeshComponents.Add(Proxy); } AddVoxel(); } }
/** Calc Bounds */ FBoxSphereBounds UFluidSurfaceComponent::CalcBounds( const FTransform& LocalToWorld ) const { FBoxSphereBounds NewBounds; /*if( BodySetup ) { FBox AggGeomBox = BodySetup->AggGeom.CalcAABB( LocalToWorld ); if( AggGeomBox.IsValid ) { NewBounds = FBoxSphereBounds( AggGeomBox ); } } else*/ { FBox NewBox = FBox( FVector( -( ( FluidXSize * FluidGridSpacing ) / 2.0f ), -( ( FluidYSize * FluidGridSpacing ) / 2.0f ), -10.0f ), FVector( ( FluidXSize * FluidGridSpacing ) / 2.0f, ( FluidYSize * FluidGridSpacing ) / 2.0f, 10.0f ) ); NewBounds = FBoxSphereBounds( NewBox ); NewBounds.Origin = GetComponentLocation( ); } return NewBounds; }
/** * Calculates a tight box-sphere bounds for the aggregate geometry; this is more expensive than CalcAABB * (tight meaning the sphere may be smaller than would be required to encompass the AABB, but all individual components lie within both the box and the sphere) * * @param Output The output box-sphere bounds calculated for this set of aggregate geometry * @param LocalToWorld Transform */ void FKAggregateGeom::CalcBoxSphereBounds(FBoxSphereBounds& Output, const FTransform& LocalToWorld) const { // Calculate the AABB const FBox AABB = CalcAABB(LocalToWorld); if ((SphereElems.Num() == 0) && (SphylElems.Num() == 0) && (BoxElems.Num() == 0)) { // For bounds that only consist of convex shapes (such as anything generated from a BSP model), // we can get nice tight bounds by considering just the points of the convex shape const FVector Origin = AABB.GetCenter(); float RadiusSquared = 0.0f; for (int32 i = 0; i < ConvexElems.Num(); i++) { const FKConvexElem& Elem = ConvexElems[i]; for (int32 j = 0; j < Elem.VertexData.Num(); ++j) { const FVector Point = LocalToWorld.TransformPosition(Elem.VertexData[j]); RadiusSquared = FMath::Max(RadiusSquared, (Point - Origin).SizeSquared()); } } // Push the resulting AABB and sphere into the output AABB.GetCenterAndExtents(Output.Origin, Output.BoxExtent); Output.SphereRadius = FMath::Sqrt(RadiusSquared); } else if ((SphereElems.Num() == 1) && (SphylElems.Num() == 0) && (BoxElems.Num() == 0) && (ConvexElems.Num() == 0)) { // For bounds that only consist of a single sphere, // we can be certain the box extents are the same as its radius AABB.GetCenterAndExtents(Output.Origin, Output.BoxExtent); Output.SphereRadius = Output.BoxExtent.X; } else { // Just use the loose sphere bounds that totally fit the AABB Output = FBoxSphereBounds(AABB); } }
void FSCSEditorViewportClient::RefreshPreviewBounds() { AActor* PreviewActor = GetPreviewActor(); if(PreviewActor) { // Compute actor bounds as the sum of its visible parts TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents; PreviewActor->GetComponents(PrimitiveComponents); PreviewActorBounds = FBoxSphereBounds(ForceInitToZero); for(auto CompIt = PrimitiveComponents.CreateConstIterator(); CompIt; ++CompIt) { // Aggregate primitive components that either have collision enabled or are otherwise visible components in-game UPrimitiveComponent* PrimComp = *CompIt; if(PrimComp->IsRegistered() && (!PrimComp->bHiddenInGame || PrimComp->IsCollisionEnabled()) && PrimComp->Bounds.SphereRadius < HALF_WORLD_MAX) { PreviewActorBounds = PreviewActorBounds + PrimComp->Bounds; } } } }
FBoxSphereBounds UShapeComponent::CalcBounds(const FTransform& LocalToWorld) const { check( false && "Subclass needs to Implement this" ); return FBoxSphereBounds(); }
FBoxSphereBounds UBoxComponent::CalcBounds(const FTransform& LocalToWorld) const { return FBoxSphereBounds( FBox( -BoxExtent, BoxExtent ) ).TransformBy(LocalToWorld); }
bool SetApexDestructibleAsset(UDestructibleMesh& DestructibleMesh, NxDestructibleAsset& ApexDestructibleAsset, FSkeletalMeshImportData* OutData, EDestructibleImportOptions::Type Options) { DestructibleMesh.PreEditChange(NULL); ExistingDestMeshData * ExistDestMeshDataPtr = SaveExistingDestMeshData(&DestructibleMesh); // The asset is going away, which will destroy any actors created from it. We must destroy the physics state of any destructible mesh components before we release the asset. for(TObjectIterator<UDestructibleComponent> It; It; ++It) { UDestructibleComponent* DestructibleComponent = *It; if(DestructibleComponent->SkeletalMesh == &DestructibleMesh && DestructibleComponent->IsPhysicsStateCreated()) { DestructibleComponent->DestroyPhysicsState(); } } // Release old NxDestructibleAsset if it exists if (DestructibleMesh.ApexDestructibleAsset != NULL && DestructibleMesh.ApexDestructibleAsset != &ApexDestructibleAsset) { GPhysCommandHandler->DeferredRelease(DestructibleMesh.ApexDestructibleAsset); } // BRGTODO - need to remove the render data from the ApexDestructibleAsset, no longer need it // Removing const cast ... we'll have to make it non-const anyway when we modify it DestructibleMesh.ApexDestructibleAsset = &ApexDestructibleAsset; if ( !(Options&EDestructibleImportOptions::PreserveSettings) ) { // Resize the depth parameters array to the appropriate size DestructibleMesh.DefaultDestructibleParameters.DepthParameters.Init(FDestructibleDepthParameters(), ApexDestructibleAsset.getDepthCount()); // Resize the fracture effects array to the appropriate size DestructibleMesh.FractureEffects.AddZeroed(ApexDestructibleAsset.getDepthCount()); // Load the UnrealEd-editable parameters from the destructible asset DestructibleMesh.LoadDefaultDestructibleParametersFromApexAsset(); } // Create body setup for the destructible mesh DestructibleMesh.CreateBodySetup(); #if 0 // BRGTODO // warning for missing smoothing group info CheckSmoothingInfo(FbxMesh); #endif FSkeletalMeshImportData TempData; // Fill with data from buffer FSkeletalMeshImportData* SkelMeshImportDataPtr = &TempData; if( OutData ) { SkelMeshImportDataPtr = OutData; } // Get all material names here ImportMaterialsForSkelMesh(*SkelMeshImportDataPtr, ApexDestructibleAsset); // Import animation hierarchy, although this is trivial for an Apex Destructible Asset CreateBones(*SkelMeshImportDataPtr, ApexDestructibleAsset); // Import graphics data bool bHaveNormals, bHaveTangents; if (!FillSkelMeshImporterFromApexDestructibleAsset(*SkelMeshImportDataPtr, ApexDestructibleAsset, bHaveNormals, bHaveTangents)) { return false; } #if 0 // BRGTODO - what is this? if( SkelMeshImportDataPtr->Materials.Num() == FbxMatList.Num() ) { // reorder material according to "SKinXX" in material name SetMaterialSkinXXOrder(*SkelMeshImportDataPtr, FbxMatList ); } #endif #if 0 // BRGTODO - what is this? if( ImportOptions->bSplitNonMatchingTriangles ) { DoUnSmoothVerts(*SkelMeshImportDataPtr); } #endif // process materials from import data ProcessImportMeshMaterials( DestructibleMesh.Materials,*SkelMeshImportDataPtr ); // process reference skeleton from import data int32 SkeletalDepth=0; if(!ProcessImportMeshSkeleton(DestructibleMesh.RefSkeleton, SkeletalDepth, *SkelMeshImportDataPtr)) { return false; } UE_LOG(LogApexDestructibleAssetImport, Warning, TEXT("Bones digested - %i Depth of hierarchy - %i"), DestructibleMesh.RefSkeleton.GetNum(), SkeletalDepth); // process bone influences from import data ProcessImportMeshInfluences(*SkelMeshImportDataPtr); FSkeletalMeshResource& DestructibleMeshResource = *DestructibleMesh.GetImportedResource(); check(DestructibleMeshResource.LODModels.Num() == 0); DestructibleMeshResource.LODModels.Empty(); new(DestructibleMeshResource.LODModels)FStaticLODModel(); DestructibleMesh.LODInfo.Empty(); DestructibleMesh.LODInfo.AddZeroed(); DestructibleMesh.LODInfo[0].LODHysteresis = 0.02f; // Create initial bounding box based on expanded version of reference pose for meshes without physics assets. Can be overridden by artist. FBox BoundingBox(SkelMeshImportDataPtr->Points.GetData(), SkelMeshImportDataPtr->Points.Num()); DestructibleMesh.Bounds= FBoxSphereBounds(BoundingBox); // Store whether or not this mesh has vertex colors DestructibleMesh.bHasVertexColors = SkelMeshImportDataPtr->bHasVertexColors; FStaticLODModel& LODModel = DestructibleMeshResource.LODModels[0]; // Pass the number of texture coordinate sets to the LODModel. Ensure there is at least one UV coord LODModel.NumTexCoords = FMath::Max<uint32>(1,SkelMeshImportDataPtr->NumTexCoords); // if( bCreateRenderData ) // We always create render data { // copy vertex data needed to generate skinning streams for LOD TArray<FVector> LODPoints; TArray<FMeshWedge> LODWedges; TArray<FMeshFace> LODFaces; TArray<FVertInfluence> LODInfluences; TArray<int32> LODPointToRawMap; SkelMeshImportDataPtr->CopyLODImportData(LODPoints,LODWedges,LODFaces,LODInfluences,LODPointToRawMap); IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities"); // Create actual rendering data. if (!MeshUtilities.BuildSkeletalMesh(DestructibleMeshResource.LODModels[0], DestructibleMesh.RefSkeleton, LODInfluences,LODWedges,LODFaces,LODPoints,LODPointToRawMap,false,!bHaveNormals,!bHaveTangents)) { DestructibleMesh.MarkPendingKill(); return false; } // Presize the per-section shadow casting array with the number of sections in the imported LOD. const int32 NumSections = LODModel.Sections.Num(); for ( int32 SectionIndex = 0 ; SectionIndex < NumSections ; ++SectionIndex ) { DestructibleMesh.LODInfo[0].TriangleSortSettings.AddZeroed(); } if (ExistDestMeshDataPtr) { RestoreExistingDestMeshData(ExistDestMeshDataPtr, &DestructibleMesh); delete ExistDestMeshDataPtr; ExistDestMeshDataPtr = NULL; } DestructibleMesh.CalculateInvRefMatrices(); DestructibleMesh.PostEditChange(); DestructibleMesh.MarkPackageDirty(); #if 0 // BRGTODO : Check, we don't need this, do we? // We have to go and fix any AnimSetMeshLinkup objects that refer to this skeletal mesh, as the reference skeleton has changed. for(TObjectIterator<UAnimSet> It;It;++It) { UAnimSet* AnimSet = *It; // Get DestructibleMesh path name FName SkelMeshName = FName( *DestructibleMesh.GetPathName() ); // See if we have already cached this Skeletal Mesh. const int32* IndexPtr = AnimSet->SkelMesh2LinkupCache.Find( SkelMeshName ); if( IndexPtr ) { AnimSet->LinkupCache( *IndexPtr ).BuildLinkup( &DestructibleMesh, AnimSet ); } } #endif // Now iterate over all skeletal mesh components re-initialising them. for(TObjectIterator<UDestructibleComponent> It; It; ++It) { UDestructibleComponent* DestructibleComponent = *It; if(DestructibleComponent->SkeletalMesh == &DestructibleMesh) { FComponentReregisterContext ReregisterContext(DestructibleComponent); } } } #if INVERT_Y_AND_V // Apply transformation for Y inversion const physx::PxMat44 MirrorY = physx::PxMat44(physx::PxVec4(1.0f, -1.0f, 1.0f, 1.0f)); #if !USE_TEMPORARY_TRANSFORMATION_FUNCTION ApexDestructibleAsset.applyTransformation(MirrorY, 1.0f); #else ApplyTransformationToApexDestructibleAsset( ApexDestructibleAsset, MirrorY ); #endif #endif return true; }
FBoxSphereBounds ULineBatchComponent::CalcBounds( const FTransform& LocalToWorld ) const { const FVector BoxExtent(HALF_WORLD_MAX); return FBoxSphereBounds(FVector::ZeroVector, BoxExtent, BoxExtent.Size()); }
FBoxSphereBounds UFuncTestRenderingComponent::CalcBounds(const FTransform& LocalToWorld) const { FBox BoundingBox = GetOwner()->GetComponentsBoundingBox(); return FBoxSphereBounds(BoundingBox); }
FBoxSphereBounds UCapsuleComponent::CalcBounds(const FTransform& LocalToWorld) const { FVector BoxPoint = FVector(CapsuleRadius,CapsuleRadius,CapsuleHalfHeight); return FBoxSphereBounds(FVector::ZeroVector, BoxPoint, BoxPoint.Size()).TransformBy(LocalToWorld); }
void ULightComponent::ReassignStationaryLightChannels(UWorld* TargetWorld, bool bAssignForLightingBuild) { TMap<FLightAndChannel*, TArray<FLightAndChannel*> > LightToOverlapMap; // Build an array of all static shadowing lights that need to be assigned for(TObjectIterator<ULightComponent> LightIt(RF_ClassDefaultObject|RF_PendingKill); LightIt; ++LightIt) { ULightComponent* const LightComponent = *LightIt; const bool bLightIsInWorld = LightComponent->GetOwner() && TargetWorld->ContainsActor(LightComponent->GetOwner()) && !LightComponent->GetOwner()->IsPendingKill(); if (bLightIsInWorld // Only operate on stationary light components (static shadowing only) && LightComponent->HasStaticShadowing() && !LightComponent->HasStaticLighting()) { if (LightComponent->bAffectsWorld && LightComponent->CastShadows && LightComponent->CastStaticShadows) { LightToOverlapMap.Add(new FLightAndChannel(LightComponent), TArray<FLightAndChannel*>()); } else { // Reset the preview channel of stationary light components that shouldn't get a channel // This is necessary to handle a light being newly disabled LightComponent->PreviewShadowMapChannel = INDEX_NONE; #if WITH_EDITOR LightComponent->UpdateLightSpriteTexture(); #endif } } } // Build an array of overlapping lights for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator It(LightToOverlapMap); It; ++It) { ULightComponent* CurrentLight = It.Key()->Light; TArray<FLightAndChannel*>& OverlappingLights = It.Value(); if (bAssignForLightingBuild) { // This should have happened during lighting invalidation at the beginning of the build anyway CurrentLight->ShadowMapChannel = INDEX_NONE; } for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator OtherIt(LightToOverlapMap); OtherIt; ++OtherIt) { ULightComponent* OtherLight = OtherIt.Key()->Light; if (CurrentLight != OtherLight // Testing both directions because the spotlight <-> spotlight test is just cone vs bounding sphere //@todo - more accurate spotlight <-> spotlight intersection && CurrentLight->AffectsBounds(FBoxSphereBounds(OtherLight->GetBoundingSphere())) && OtherLight->AffectsBounds(FBoxSphereBounds(CurrentLight->GetBoundingSphere()))) { OverlappingLights.Add(OtherIt.Key()); } } } // Sort lights with the most overlapping lights first LightToOverlapMap.ValueSort(FCompareLightsByArrayCount()); TMap<FLightAndChannel*, TArray<FLightAndChannel*> > SortedLightToOverlapMap; // Add directional lights to the beginning so they always get channels for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator It(LightToOverlapMap); It; ++It) { FLightAndChannel* CurrentLight = It.Key(); if (CurrentLight->Light->GetLightType() == LightType_Directional) { SortedLightToOverlapMap.Add(It.Key(), It.Value()); } } // Add everything else, which has been sorted by descending overlaps for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator It(LightToOverlapMap); It; ++It) { FLightAndChannel* CurrentLight = It.Key(); if (CurrentLight->Light->GetLightType() != LightType_Directional) { SortedLightToOverlapMap.Add(It.Key(), It.Value()); } } // Go through lights and assign shadowmap channels //@todo - retry with different ordering heuristics when it fails for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator It(SortedLightToOverlapMap); It; ++It) { bool bChannelUsed[4] = {0}; FLightAndChannel* CurrentLight = It.Key(); const TArray<FLightAndChannel*>& OverlappingLights = It.Value(); // Mark which channels have already been assigned to overlapping lights for (int32 OverlappingIndex = 0; OverlappingIndex < OverlappingLights.Num(); OverlappingIndex++) { FLightAndChannel* OverlappingLight = OverlappingLights[OverlappingIndex]; if (OverlappingLight->Channel != INDEX_NONE) { bChannelUsed[OverlappingLight->Channel] = true; } } // Use the lowest free channel for (int32 ChannelIndex = 0; ChannelIndex < ARRAY_COUNT(bChannelUsed); ChannelIndex++) { if (!bChannelUsed[ChannelIndex]) { CurrentLight->Channel = ChannelIndex; break; } } } // Go through the assigned lights and update their render state and icon for (TMap<FLightAndChannel*, TArray<FLightAndChannel*> >::TIterator It(SortedLightToOverlapMap); It; ++It) { FLightAndChannel* CurrentLight = It.Key(); if (CurrentLight->Light->PreviewShadowMapChannel != CurrentLight->Channel) { CurrentLight->Light->PreviewShadowMapChannel = CurrentLight->Channel; CurrentLight->Light->MarkRenderStateDirty(); } #if WITH_EDITOR CurrentLight->Light->UpdateLightSpriteTexture(); #endif if (bAssignForLightingBuild) { CurrentLight->Light->ShadowMapChannel = CurrentLight->Channel; if (CurrentLight->Light->ShadowMapChannel == INDEX_NONE) { FMessageLog("LightingResults").Error() ->AddToken(FUObjectToken::Create(CurrentLight->Light->GetOwner())) ->AddToken(FTextToken::Create( NSLOCTEXT("Lightmass", "LightmassError_FailedToAllocateShadowmapChannel", "Severe performance loss: Failed to allocate shadowmap channel for stationary light due to overlap - light will fall back to dynamic shadows!") ) ); } } delete CurrentLight; } }
FBoxSphereBounds UArrowComponent::CalcBounds(const FTransform & LocalToWorld) const { return FBoxSphereBounds(FBox(FVector(0,-ARROW_SCALE,-ARROW_SCALE),FVector(ArrowSize * ARROW_SCALE * 3.0f,ARROW_SCALE,ARROW_SCALE))).TransformBy(LocalToWorld); }
FBoxSphereBounds UEQSRenderingComponent::CalcBounds(const FTransform& LocalToWorld) const { static FBox BoundingBox(FVector(-HALF_WORLD_MAX), FVector(HALF_WORLD_MAX)); return FBoxSphereBounds(BoundingBox); }