BorrowTheProgrammer

lab6_7

Jun 21st, 2022 (edited)
378
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.07 KB | None | 0 0
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2.  
  3. #pragma once
  4.  
  5. #include "CoreMinimal.h"
  6. #include "GameFramework/Actor.h"
  7. #include "BallActor.generated.h"
  8.  
  9. UCLASS()
  10. class FORLR2_API ABallActor : public AActor
  11. {
  12.     GENERATED_BODY()
  13.    
  14. public:
  15.     // Sets default values for this actor's properties
  16.     ABallActor();
  17.     UStaticMeshComponent *Mesh;
  18.     UMaterialInstanceDynamic *BallActorMaterial;
  19.     void SetActorRadius(float Radius);
  20. };
  21. // Fill out your copyright notice in the Description page of Project Settings.
  22.  
  23.  
  24. #include "BallActor.h"
  25.  
  26. // Sets default values
  27. ABallActor::ABallActor()
  28. {
  29.     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
  30.     PrimaryActorTick.bCanEverTick = false;
  31.     PrimaryActorTick.bStartWithTickEnabled = false;
  32.    
  33.     Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Sphere"));
  34.     Mesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules(EAttachmentRule::SnapToTarget,
  35.         false));
  36.     ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
  37.    
  38.     static ConstructorHelpers::FObjectFinder<UMaterialInterface> ActorMaterial(
  39.         TEXT("Material'/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial'"));
  40.  
  41.     BallActorMaterial = UMaterialInstanceDynamic::Create(ActorMaterial.Object, nullptr);
  42.    
  43.     Mesh->SetStaticMesh(SphereMesh.Object);
  44.     Mesh->SetMaterial(0, BallActorMaterial);
  45.     Mesh->SetCastShadow(false);
  46.     Mesh->SetSimulatePhysics(true);
  47. }
  48.  
  49. void ABallActor::SetActorRadius(float Radius)
  50. {
  51.     float Scale = Radius / 100 * 2;
  52.    
  53.     // Установите масштаб мирового пространства Актера.
  54.     SetActorScale3D(FVector(Scale, Scale, Scale));
  55. }
  56. // Fill out your copyright notice in the Description page of Project Settings.
  57.  
  58.  
  59. #include "BallsMeshActor.h"
  60.  
  61. // Sets default values
  62. ABallsMeshActor::ABallsMeshActor()
  63. {
  64.     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
  65.     PrimaryActorTick.bCanEverTick = false;
  66.     PrimaryActorTick.bStartWithTickEnabled = false;
  67.  
  68.     static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh(
  69.         TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'")
  70.         );
  71.     Mesh = SphereMesh.Object;
  72. }
  73.  
  74. void ABallsMeshActor::InterruptMovement()
  75. {
  76.     float maxZ = BallsPosition.Z + OuterHeight;
  77.    
  78.     for (ABallActor *ball : Balls)
  79.     {
  80.         FVector BallLocation = ball->GetActorLocation();
  81.  
  82.         if (BallLocation.Z > maxZ
  83.             || BallLocation.Z < BallsPosition.Z
  84.             || FMath::Pow(BallLocation.X - BallsPosition.X, 2)
  85.             + FMath::Pow(BallLocation.Y - BallsPosition.Y, 2) > FMath::Pow(OuterRadius, 2))
  86.         {
  87.             ball->Destroy();
  88.         }
  89.         else
  90.         {
  91.             ball->DisableComponentsSimulatePhysics();
  92.         }
  93.     }
  94. }
  95.  
  96. void ABallsMeshActor::CreateBalls(float InnerR, float OuterR, float InnerH, float OuterH, FVector Position,
  97.     float Offset, float BallRadius, float BallDeltaR)
  98. {
  99.     // ссылка не текущую сцену
  100.     UWorld *MyWorld = GetWorld();
  101.  
  102.     // радиус внешней стенки
  103.     OuterRadius = OuterR;
  104.    
  105.     // радиус внутренней стенки
  106.     InnerRadius = InnerR;
  107.  
  108.     // высота внешней стенки
  109.     OuterHeight = OuterH;
  110.  
  111.     // высота внутренней стенки
  112.     InnerHeight = InnerH;
  113.     BallsPosition = Position;
  114.    
  115.     // объем цилиндра, рассчитываемый по внешней стенке
  116.     float OuterVolume = PI * FMath::Pow(OuterR, 2) * OuterH;
  117.    
  118.     // объем цилиндра, рассчитываемый по внутренней стене
  119.     float InnerVolume = PI * FMath::Pow(InnerR, 2) * InnerH;
  120.  
  121.     // разница объемов
  122.     const float TargetVolume = OuterVolume - InnerVolume;
  123.  
  124.     float FilledVolume = 0;
  125.     float ZPosition = OuterH + Offset;
  126.     float MinSpawnRadius = InnerR + BallRadius + BallDeltaR;
  127.     float MaxSpawnRadius = OuterR - BallRadius - BallDeltaR;
  128.     float SpawnRadius = MinSpawnRadius;
  129.     float AddingRadiusSpawn = (BallRadius + BallDeltaR) * 2 + 10;
  130.     float Angle = 0;
  131.     float AddingAngle = 2 * FMath::Asin((BallRadius + BallDeltaR + 10) / SpawnRadius);
  132.  
  133.     // Резервирует память таким образом, чтобы массив мог содержать по крайней мере числовые элементы.
  134.     Balls.Reserve(TargetVolume / 4.0 / 3.0 * PI * FMath::Pow(BallRadius, 3));
  135.  
  136.    
  137.  
  138.     while (FilledVolume < TargetVolume)
  139.     {
  140.         if (Angle > 2 * PI)
  141.         {
  142.             SpawnRadius += AddingRadiusSpawn;
  143.  
  144.             if (SpawnRadius > MaxSpawnRadius)
  145.             {
  146.                 SpawnRadius = MinSpawnRadius;
  147.                 ZPosition += 2 * (BallRadius + BallDeltaR) + 10;
  148.             }
  149.            
  150.             Angle = 0;
  151.             AddingAngle = 2 * FMath::Asin((BallRadius + BallDeltaR + 10) / SpawnRadius);
  152.         }
  153.        
  154.         float RandomBallR = FMath::RandRange(BallRadius - BallDeltaR, BallRadius + BallDeltaR);
  155.  
  156.         ABallActor *Ball = MyWorld->SpawnActor<ABallActor>(
  157.             Position + FVector(SpawnRadius * FMath::Cos(Angle),
  158.                 SpawnRadius * FMath::Sin(Angle), ZPosition), FRotator());
  159.  
  160.         Ball->SetActorRadius(RandomBallR);
  161.         Balls.Add(Ball);
  162.  
  163.         FilledVolume += 4.0 / 3.0 * PI * FMath::Pow(RandomBallR, 3);
  164.         Angle += AddingAngle;
  165.     }
  166. }
  167.  
  168. // Fill out your copyright notice in the Description page of Project Settings.
  169.  
  170. #pragma once
  171.  
  172. #include "CoreMinimal.h"
  173. #include "GameFramework/Actor.h"
  174. #include "ProceduralMeshComponent.h"
  175. #include "MyFilter.generated.h"
  176.  
  177. UCLASS()
  178. class FORLR2_API AMyFilter : public AActor
  179. {
  180.     GENERATED_BODY()
  181.    
  182. public:
  183.     // Sets default values for this actor's properties
  184.     AMyFilter();
  185.     UProceduralMeshComponent *Mesh;
  186.  
  187. protected:
  188.     void CreateFilterFloor(int Index, float Radius, int Discretization, bool isNormalized, FVector Offset = FVector());
  189.     void CreateFilterWall(int Index, float Radius, float Height, int Discretization, bool isNormalized,
  190.         FVector Offset = FVector());
  191.  
  192. public:
  193.     void ConstructFilter(float InnerR, float OuterR, float InnerH, float OuterH,
  194.         FVector Pos, int Discretization);
  195. };
  196. // Fill out your copyright notice in the Description page of Project Settings.
  197.  
  198.  
  199. #include "MyFilter.h"
  200.  
  201. // Sets default values
  202. AMyFilter::AMyFilter()
  203. {
  204.     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
  205.     PrimaryActorTick.bStartWithTickEnabled = false;
  206.     PrimaryActorTick.bCanEverTick = false;
  207.  
  208.     Mesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("TriangleMesh"));
  209.     Mesh->AttachToComponent(GetRootComponent(),
  210.         FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false));
  211.  
  212.     // Определяет, следует ли выполнять физическую обработку вне игрового потока
  213.     Mesh->bUseAsyncCooking = true;
  214.     Mesh->SetCastShadow(false);
  215. }
  216.  
  217. void AMyFilter::CreateFilterWall(int Index, float Radius, float Height, int Discretization, bool isNormalized,
  218.                                  FVector Offset)
  219. {
  220.     TArray<FVector> Vertices;
  221.     TArray<int> Triangles;
  222.     TArray<FVector> Normals;
  223.     TArray<FVector2D> UVs;
  224.     TArray<FLinearColor> Colors;
  225.     TArray<FProcMeshTangent> Tangens;
  226.  
  227.     Vertices.Reserve(Discretization * 2 + 2);
  228.     Triangles.Reserve(Discretization * 2 * 3);
  229.     Normals.Reserve(Discretization * 2 + 2);
  230.     UVs.Reserve(Discretization * 2 + 2);
  231.     Tangens.Reserve(Discretization * 2 + 2);
  232.     Colors.Init(FLinearColor(0.7, 0.7, 1), Discretization * 2 + 2);
  233.  
  234.     float Angle = 0;
  235.     float DPhi = FMath::DegreesToRadians(360.0 / Discretization);
  236.  
  237.     for (int i = 0; i < Discretization + 1; ++i)
  238.     {
  239.         Vertices.Add(FVector(Radius * FMath::Cos(Angle), Radius * FMath::Sin(Angle), 0) + Offset);
  240.         Angle += DPhi;
  241.     }
  242.  
  243.     for (int i = 0; i < Discretization + 1; ++i)
  244.     {
  245.         Vertices.Add(FVector(Radius * FMath::Cos(Angle), Radius * FMath::Sin(Angle), Height) + Offset);
  246.         Angle += DPhi;
  247.     }
  248.     if (isNormalized)
  249.     {
  250.         for (int i = 0;  i < Discretization + 1; ++i)
  251.         {
  252.             Triangles.Add((i + 1) % (Discretization + 1));
  253.             Triangles.Add(i + (Discretization + 1));
  254.             Triangles.Add(i);
  255.             Triangles.Add(i + (Discretization + 1));
  256.             Triangles.Add((i + 1) % (Discretization + 1));
  257.             Triangles.Add((i + 1) % (Discretization + 1) + (Discretization + 1));
  258.         }
  259.     } else
  260.     {
  261.         for (int i = 0; i < Discretization + 1; ++i)
  262.         {
  263.             Triangles.Add(i);
  264.             Triangles.Add(i + (Discretization + 1));
  265.             Triangles.Add((i + 1) % (Discretization + 1));
  266.             Triangles.Add((i + 1) % (Discretization + 1) + (Discretization + 1));
  267.             Triangles.Add((i + 1) % (Discretization + 1));
  268.             Triangles.Add(i + (Discretization + 1));
  269.  
  270.         }
  271.     }
  272.    
  273.     Angle = 0;
  274.  
  275.     if (isNormalized)
  276.     {
  277.         for (int i = 0; i < Discretization + 1; ++i)
  278.         {
  279.             Normals.Add(FVector(FMath::Cos(Angle), FMath::Sin(Angle), 0).GetSafeNormal());
  280.             Angle += DPhi;
  281.         }
  282.     } else
  283.     {
  284.         for (int i = 0; i < Discretization + 1; ++i)
  285.         {
  286.             Normals.Add(FVector(-FMath::Cos(Angle), -FMath::Sin(Angle), 0).GetSafeNormal());
  287.             Angle += DPhi;
  288.         }
  289.     }
  290.  
  291.     for (int i = 0; i < Discretization + 1; ++i)
  292.     {
  293.         UVs.Add(FVector2D(i / (Discretization + 1), 0));
  294.     }
  295.    
  296.     for (int i = 0; i < Discretization + 1; ++i)
  297.     {
  298.         UVs.Add(FVector2D(i / (Discretization + 1), 1));
  299.     }
  300.  
  301.     Angle = 0;
  302.  
  303.     for (int i = 0; i < 2; ++i)
  304.     {
  305.         Angle = 0;
  306.         for (int j = 0; j < Discretization + 1; ++j)
  307.         {
  308.             FVector Normal = FVector(FMath::Cos(Angle), FMath::Sin(Angle), 0).GetSafeNormal();
  309.             Tangens.Add(FProcMeshTangent(Normal.X, Normal.Y, Normal.Z));
  310.             Angle += DPhi;
  311.         }
  312.        
  313.     }
  314.  
  315.     Mesh->CreateMeshSection_LinearColor(Index, Vertices, Triangles, Normals, UVs, Colors, Tangens, true);
  316. }
  317.  
  318. void AMyFilter::CreateFilterFloor(int Index, float Radius, int Discretization, bool isNormalized, FVector Offset)
  319. {
  320.     TArray<FVector> Vertices;
  321.     TArray<int> Triangles;
  322.     TArray<FVector> Normals;
  323.     TArray<FVector2D> UVs;
  324.     TArray<FLinearColor> Colors;
  325.     TArray<FProcMeshTangent> Tangents;
  326.  
  327.     Vertices.Reserve(Discretization + 1);
  328.     Triangles.Reserve((Discretization - 2) * 3);
  329.    
  330.     float Angle = 0;
  331.     float DPhi = FMath::DegreesToRadians(360.0 / Discretization);
  332.  
  333.     for (int i = 0; i < Discretization + 1; ++i)
  334.     {
  335.         Vertices.Add(FVector(Radius * FMath::Cos(Angle), Radius * FMath::Sin(Angle), 0) + Offset);
  336.         Angle += DPhi;
  337.     }
  338.  
  339.     if(isNormalized)
  340.     {
  341.         for (int i = 0; i < Discretization - 1; ++i)
  342.         {
  343.             Triangles.Add(0);
  344.             Triangles.Add(i + 1);
  345.             Triangles.Add(i + 2);
  346.         }
  347.     } else
  348.     {
  349.         for (int i = 0; i < Discretization - 1; ++i)
  350.         {
  351.             Triangles.Add(i + 2);
  352.             Triangles.Add(i + 1);
  353.             Triangles.Add(0);
  354.         }
  355.     }
  356.    
  357.     Normals.Init(FVector(0, 0, (isNormalized ? -1 : 1)), Discretization + 1);
  358.    
  359.     UVs.Reserve(Discretization + 1);
  360.  
  361.     Angle = 0;
  362.  
  363.     for(int i = 0; i < Discretization + 1; ++i)
  364.     {
  365.         UVs.Add(FVector2D(0.5 + FMath::Cos(Angle) / 2, 0.5 + FMath::Sin(Angle) / 2));
  366.         Angle += DPhi;
  367.     }
  368.  
  369.     Colors.Init(FLinearColor(0.7, 0,7, 0.7), Discretization + 1);
  370.     Tangents.Reserve(Discretization + 1);
  371.     Angle = 0;
  372.  
  373.     for (int i = 0; i < Discretization + 1; ++i)
  374.     {
  375.         FVector Normal = FVector(FMath::Cos(Angle), FMath::Sin(Angle), 0).GetSafeNormal();
  376.         Tangents.Add(FProcMeshTangent(Normal.X, Normal.Y, Normal.Z));
  377.         Angle += DPhi;
  378.     }
  379.  
  380.     Mesh->CreateMeshSection_LinearColor(
  381.         Index, Vertices, Triangles, Normals, UVs, Colors, Tangents, true);
  382.    
  383. }
  384.  
  385. void AMyFilter::ConstructFilter(float InnerR, float OuterR, float InnerH, float OuterH, FVector Pos, int Discretization)
  386. {
  387.     SetActorLocation(Pos);
  388.  
  389.     CreateFilterFloor(0, OuterR, Discretization, false, FVector(0, 0, 0));
  390.     CreateFilterFloor(1, InnerR, Discretization, true, FVector(0, 0, InnerH));
  391.     CreateFilterFloor(2, InnerR, Discretization, false, FVector(0, 0, OuterH));
  392.  
  393.     CreateFilterWall(3, OuterR, OuterH, Discretization, true,
  394.         FVector(0, 0, 0));
  395.     CreateFilterWall(4, InnerR, OuterH - InnerH, Discretization, false,
  396.         FVector(0, 0, InnerH));
  397. }
  398.  
  399. // Fill out your copyright notice in the Description page of Project Settings.
  400.  
  401. #pragma once
  402.  
  403. #include "CoreMinimal.h"
  404. #include "BallsMeshActor.h"
  405. #include "MyFilter.h"
  406. #include "GameFramework/Actor.h"
  407. #include "MainComponent.generated.h"
  408.  
  409. UCLASS()
  410. class FORLR2_API AMainComponent : public AActor
  411. {
  412.     GENERATED_BODY()
  413.    
  414. public:
  415.     // Sets default values for this actor's properties
  416.     AMainComponent();
  417.  
  418.     // внешний радиус цилиндра
  419.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  420.     float OuterRadius;
  421.  
  422.     // высота внешней стенки цилиндра
  423.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  424.     float OuterHeight;
  425.    
  426.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  427.     float DeltaHeight;
  428.  
  429.     // внешний радиус цининдра
  430.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  431.     float InnerRadius;
  432.    
  433.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  434.     int Discretization;
  435.    
  436.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  437.     float ActorBallRadius;
  438.  
  439.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  440.     float BallsOffsetZ;
  441.    
  442.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  443.     float BallDeltaRadius;
  444.  
  445.     ABallsMeshActor *Balls;
  446.  
  447.     AMyFilter *MyFilter;
  448.     bool IsActorStopped;
  449.    
  450. protected:
  451.     // Called when the game starts or when spawned
  452.     virtual void BeginPlay() override;
  453.  
  454. public:
  455.     void InterruptSimulation();
  456.    
  457.     // Called every frame
  458.     virtual void Tick(float DeltaTime) override;
  459.  
  460. };
  461. // Fill out your copyright notice in the Description page of Project Settings.
  462.  
  463. #pragma once
  464.  
  465. #include "CoreMinimal.h"
  466. #include "BallsMeshActor.h"
  467. #include "MyFilter.h"
  468. #include "GameFramework/Actor.h"
  469. #include "MainComponent.generated.h"
  470.  
  471. UCLASS()
  472. class FORLR2_API AMainComponent : public AActor
  473. {
  474.     GENERATED_BODY()
  475.    
  476. public:
  477.     // Sets default values for this actor's properties
  478.     AMainComponent();
  479.  
  480.     // внешний радиус цилиндра
  481.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  482.     float OuterRadius;
  483.  
  484.     // высота внешней стенки цилиндра
  485.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  486.     float OuterHeight;
  487.    
  488.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  489.     float DeltaHeight;
  490.  
  491.     // внешний радиус цининдра
  492.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  493.     float InnerRadius;
  494.    
  495.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cylinder")
  496.     int Discretization;
  497.    
  498.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  499.     float ActorBallRadius;
  500.  
  501.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  502.     float BallsOffsetZ;
  503.    
  504.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Ball")
  505.     float BallDeltaRadius;
  506.  
  507.     ABallsMeshActor *Balls;
  508.  
  509.     AMyFilter *MyFilter;
  510.     bool IsActorStopped;
  511.    
  512. protected:
  513.     // Called when the game starts or when spawned
  514.     virtual void BeginPlay() override;
  515.  
  516. public:
  517.     void InterruptSimulation();
  518.    
  519.     // Called every frame
  520.     virtual void Tick(float DeltaTime) override;
  521.  
  522. };
  523.  
  524. // Fill out your copyright notice in the Description page of Project Settings.
  525.  
  526.  
  527. #include "MainComponent.h"
  528.  
  529. // Sets default values
  530. AMainComponent::AMainComponent()
  531. {
  532.     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
  533.     PrimaryActorTick.bCanEverTick = true;
  534.     PrimaryActorTick.bStartWithTickEnabled = true;
  535.  
  536.     SetRootComponent(
  537.         CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent")));
  538.  
  539. }
  540.  
  541. void AMainComponent::InterruptSimulation()
  542. {
  543.     IsActorStopped = true;
  544. }
  545.  
  546. // Called when the game starts or when spawned
  547. void AMainComponent::BeginPlay()
  548. {
  549.     Super::BeginPlay();
  550.  
  551.     if (Discretization < 3)
  552.     {
  553.         return;
  554.     }
  555.  
  556.     UWorld *World = GetWorld();
  557.  
  558.     MyFilter = World->SpawnActor<AMyFilter>(AMyFilter::StaticClass());
  559.     MyFilter->ConstructFilter(InnerRadius, OuterRadius, DeltaHeight, OuterHeight,
  560.         GetActorLocation(), Discretization);
  561.  
  562.     Balls = World->SpawnActor<ABallsMeshActor>(ABallsMeshActor::StaticClass());
  563.     Balls->CreateBalls(InnerRadius, OuterRadius, OuterHeight - DeltaHeight, OuterHeight, GetActorLocation(),
  564.         BallsOffsetZ, ActorBallRadius, BallDeltaRadius);
  565.    
  566. }
  567.  
  568. // Called every frame
  569. void AMainComponent::Tick(float DeltaTime)
  570. {
  571.     Super::Tick(DeltaTime);
  572.  
  573.     if (IsActorStopped)
  574.     {
  575.         Balls->InterruptMovement();
  576.     }
  577.  
  578. }
  579.  
  580.  
Add Comment
Please, Sign In to add comment