deblasipaste

Untitled

May 16th, 2024
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.59 KB | None | 0 0
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2.  
  3.  
  4. #include "Voxel/VoxelTerrainActor.h"
  5. #include "DrawDebugHelpers.h"
  6. #include "ProceduralMeshComponent.h"
  7. #include "KismetProceduralMeshLibrary.h"
  8. #include "Components/TextRenderComponent.h"
  9.  
  10. // Sets default values
  11. AVoxelTerrainActor::AVoxelTerrainActor()
  12. {
  13. // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
  14. PrimaryActorTick.bCanEverTick = true;
  15.  
  16. ProceduralMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("Procedural Mesh"));
  17. }
  18.  
  19. // Called when the game starts or when spawned
  20. void AVoxelTerrainActor::BeginPlay()
  21. {
  22. Super::BeginPlay();
  23.  
  24. Setup(1.0f);
  25.  
  26. FTimerHandle H{ };
  27. GetWorldTimerManager().SetTimer(H, [this]()
  28. {
  29. RemoveVoxel(Chunks[0]);
  30. }, 1.0f / 1.0f, true);
  31. }
  32.  
  33. void AVoxelTerrainActor::Setup(float Res)
  34. {
  35. #if !WITH_EDITOR
  36. this->Resolution = Res;
  37. #endif
  38.  
  39. for (int i = 0; i < 1; i++)
  40. {
  41. auto& Chunk = Chunks.AddDefaulted_GetRef();
  42. Chunk.Extent = FVector2D(NumVoxelsXY * VoxelSize, NumVoxelsXY * VoxelSize);
  43. SetupChunk(Chunk);
  44. }
  45. }
  46.  
  47. void AVoxelTerrainActor::SetupChunk(FChunk& Chunk)
  48. {
  49. for (float i = VoxelSize / 2 + Chunk.Origin.X; i < Chunk.Extent.X - Chunk.Origin.X; i += VoxelSize)
  50. for (float j = VoxelSize / 2 + Chunk.Origin.X; j < Chunk.Extent.Y - Chunk.Origin.Y; j += VoxelSize)
  51. {
  52. const float z = 15.0f;
  53. FVoxel V;
  54. V.Position = FVector(i, j, z);
  55.  
  56. if (i == VoxelSize / 2 + Chunk.Origin.X)
  57. V.PositionFlags |= ESurroundingVoxels::NegX;
  58. if (i + VoxelSize >= Chunk.Origin.X + Chunk.Extent.X)
  59. V.PositionFlags |= ESurroundingVoxels::PosX;
  60.  
  61. if (j == VoxelSize / 2 + Chunk.Origin.Y)
  62. V.PositionFlags |= ESurroundingVoxels::NegY;
  63. if (j + VoxelSize >= Chunk.Origin.Y + Chunk.Extent.Y)
  64. V.PositionFlags |= ESurroundingVoxels::PosY;
  65.  
  66. V.PositionFlags |= ESurroundingVoxels::Bottom | ESurroundingVoxels::Top;
  67.  
  68. Chunk.Voxels.Add(V.Position, V);
  69. }
  70.  
  71. BuildChunk(Chunk);
  72. }
  73.  
  74. void AVoxelTerrainActor::BuildChunk(FChunk& Chunk)
  75. {
  76. ProceduralMesh->ClearAllMeshSections();
  77.  
  78. int Index = 0;
  79. for (auto& P : Chunk.Voxels)
  80. {
  81. auto& V = P.Value;
  82. V.MeshIndex = Index;
  83. Index++;
  84.  
  85. TArray<FVector> Positions;
  86. TArray<int32> Indices;
  87. TArray<FVector2D> UVs;
  88.  
  89. TArray<FVector> Normals;
  90. TArray<FProcMeshTangent> Tangents;
  91.  
  92. // TOP
  93. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  94. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  95. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  96. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  97.  
  98. // BOTTOM
  99. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  100. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  101. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  102. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  103.  
  104. // POS X
  105. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  106. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  107. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  108. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  109.  
  110. // NEG X
  111. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  112. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  113. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  114. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  115.  
  116. // POS Y
  117. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  118. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  119. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  120. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y + (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  121.  
  122. // NEG Y
  123. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  124. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z + (VoxelSize / 2)));
  125. Positions.Add(FVector(V.Position.X + (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  126. Positions.Add(FVector(V.Position.X - (VoxelSize / 2), V.Position.Y - (VoxelSize / 2), V.Position.Z - (VoxelSize / 2)));
  127.  
  128. UVs.Add(FVector2D(0, 0));
  129. UVs.Add(FVector2D(0, 1));
  130. UVs.Add(FVector2D(1, 0));
  131. UVs.Add(FVector2D(1, 1));
  132.  
  133. UVs.Add(FVector2D(0, 0));
  134. UVs.Add(FVector2D(0, 1));
  135. UVs.Add(FVector2D(1, 0));
  136. UVs.Add(FVector2D(1, 1));
  137.  
  138. UVs.Add(FVector2D(0, 0));
  139. UVs.Add(FVector2D(0, 1));
  140. UVs.Add(FVector2D(1, 0));
  141. UVs.Add(FVector2D(1, 1));
  142.  
  143. UVs.Add(FVector2D(0, 0));
  144. UVs.Add(FVector2D(0, 1));
  145. UVs.Add(FVector2D(1, 0));
  146. UVs.Add(FVector2D(1, 1));
  147.  
  148. UVs.Add(FVector2D(0, 0));
  149. UVs.Add(FVector2D(0, 1));
  150. UVs.Add(FVector2D(1, 0));
  151. UVs.Add(FVector2D(1, 1));
  152.  
  153. UVs.Add(FVector2D(0, 0));
  154. UVs.Add(FVector2D(0, 1));
  155. UVs.Add(FVector2D(1, 0));
  156. UVs.Add(FVector2D(1, 1));
  157.  
  158. if (V.PositionFlags & ESurroundingVoxels::Top)
  159. {
  160. Indices.Add(1);
  161. Indices.Add(0);
  162. Indices.Add(2);
  163.  
  164. Indices.Add(1);
  165. Indices.Add(2);
  166. Indices.Add(3);
  167. }
  168. if (V.PositionFlags & ESurroundingVoxels::Bottom)
  169. {
  170. Indices.Add(4);
  171. Indices.Add(5);
  172. Indices.Add(6);
  173.  
  174. Indices.Add(6);
  175. Indices.Add(5);
  176. Indices.Add(7);
  177. }
  178. if (V.PositionFlags & ESurroundingVoxels::PosX)
  179. {
  180. Indices.Add(8);
  181. Indices.Add(9);
  182. Indices.Add(10);
  183.  
  184. Indices.Add(10);
  185. Indices.Add(9);
  186. Indices.Add(11);
  187. }
  188. if (V.PositionFlags & ESurroundingVoxels::NegX)
  189. {
  190. Indices.Add(13);
  191. Indices.Add(12);
  192. Indices.Add(14);
  193.  
  194. Indices.Add(13);
  195. Indices.Add(14);
  196. Indices.Add(15);
  197. }
  198. if (V.PositionFlags & ESurroundingVoxels::PosY)
  199. {
  200. Indices.Add(16);
  201. Indices.Add(17);
  202. Indices.Add(18);
  203.  
  204. Indices.Add(18);
  205. Indices.Add(17);
  206. Indices.Add(19);
  207. }
  208. if (V.PositionFlags & ESurroundingVoxels::NegY)
  209. {
  210. Indices.Add(21);
  211. Indices.Add(20);
  212. Indices.Add(22);
  213.  
  214. Indices.Add(21);
  215. Indices.Add(22);
  216. Indices.Add(23);
  217. }
  218.  
  219. UKismetProceduralMeshLibrary::CalculateTangentsForMesh(Positions, Indices, UVs, Normals, Tangents);
  220. ProceduralMesh->CreateMeshSection(V.MeshIndex, Positions, Indices, Normals, UVs, TArray<FColor>(), Tangents, true);
  221. if (Material)
  222. {
  223. ProceduralMesh->SetMaterial(V.MeshIndex, Material);
  224. }
  225. }
  226. }
  227.  
  228. void AVoxelTerrainActor::BuildVoxel(FVoxel& Voxel)
  229. {
  230. ProceduralMesh->ClearMeshSection(Voxel.MeshIndex);
  231.  
  232. TArray<FVector> Positions;
  233. TArray<int32> Indices;
  234. TArray<FVector2D> UVs;
  235.  
  236. TArray<FVector> Normals;
  237. TArray<FProcMeshTangent> Tangents;
  238.  
  239. // TOP
  240. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  241. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  242. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  243. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  244.  
  245. // BOTTOM
  246. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  247. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  248. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  249. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  250.  
  251. // POS X
  252. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  253. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  254. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  255. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  256.  
  257. // NEG X
  258. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  259. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  260. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  261. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  262.  
  263. // POS Y
  264. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  265. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  266. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  267. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y + (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  268.  
  269. // NEG Y
  270. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  271. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z + (VoxelSize / 2)));
  272. Positions.Add(FVector(Voxel.Position.X + (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  273. Positions.Add(FVector(Voxel.Position.X - (VoxelSize / 2), Voxel.Position.Y - (VoxelSize / 2), Voxel.Position.Z - (VoxelSize / 2)));
  274.  
  275. UVs.Add(FVector2D(0, 0));
  276. UVs.Add(FVector2D(0, 1));
  277. UVs.Add(FVector2D(1, 0));
  278. UVs.Add(FVector2D(1, 1));
  279.  
  280. UVs.Add(FVector2D(0, 0));
  281. UVs.Add(FVector2D(0, 1));
  282. UVs.Add(FVector2D(1, 0));
  283. UVs.Add(FVector2D(1, 1));
  284.  
  285. UVs.Add(FVector2D(0, 0));
  286. UVs.Add(FVector2D(0, 1));
  287. UVs.Add(FVector2D(1, 0));
  288. UVs.Add(FVector2D(1, 1));
  289.  
  290. UVs.Add(FVector2D(0, 0));
  291. UVs.Add(FVector2D(0, 1));
  292. UVs.Add(FVector2D(1, 0));
  293. UVs.Add(FVector2D(1, 1));
  294.  
  295. UVs.Add(FVector2D(0, 0));
  296. UVs.Add(FVector2D(0, 1));
  297. UVs.Add(FVector2D(1, 0));
  298. UVs.Add(FVector2D(1, 1));
  299.  
  300. UVs.Add(FVector2D(0, 0));
  301. UVs.Add(FVector2D(0, 1));
  302. UVs.Add(FVector2D(1, 0));
  303. UVs.Add(FVector2D(1, 1));
  304.  
  305. if (Voxel.PositionFlags & ESurroundingVoxels::Top)
  306. {
  307. Indices.Add(1);
  308. Indices.Add(0);
  309. Indices.Add(2);
  310.  
  311. Indices.Add(1);
  312. Indices.Add(2);
  313. Indices.Add(3);
  314. }
  315. if (Voxel.PositionFlags & ESurroundingVoxels::Bottom)
  316. {
  317. Indices.Add(4);
  318. Indices.Add(5);
  319. Indices.Add(6);
  320.  
  321. Indices.Add(6);
  322. Indices.Add(5);
  323. Indices.Add(7);
  324. }
  325. if (Voxel.PositionFlags & ESurroundingVoxels::PosX)
  326. {
  327. Indices.Add(8);
  328. Indices.Add(9);
  329. Indices.Add(10);
  330.  
  331. Indices.Add(10);
  332. Indices.Add(9);
  333. Indices.Add(11);
  334. }
  335. if (Voxel.PositionFlags & ESurroundingVoxels::NegX)
  336. {
  337. Indices.Add(13);
  338. Indices.Add(12);
  339. Indices.Add(14);
  340.  
  341. Indices.Add(13);
  342. Indices.Add(14);
  343. Indices.Add(15);
  344. }
  345. if (Voxel.PositionFlags & ESurroundingVoxels::PosY)
  346. {
  347. Indices.Add(16);
  348. Indices.Add(17);
  349. Indices.Add(18);
  350.  
  351. Indices.Add(18);
  352. Indices.Add(17);
  353. Indices.Add(19);
  354. }
  355. if (Voxel.PositionFlags & ESurroundingVoxels::NegY)
  356. {
  357. Indices.Add(21);
  358. Indices.Add(20);
  359. Indices.Add(22);
  360.  
  361. Indices.Add(21);
  362. Indices.Add(22);
  363. Indices.Add(23);
  364. }
  365.  
  366. UKismetProceduralMeshLibrary::CalculateTangentsForMesh(Positions, Indices, UVs, Normals, Tangents);
  367. ProceduralMesh->CreateMeshSection(Voxel.MeshIndex, Positions, Indices, Normals, UVs, TArray<FColor>(), Tangents, true);
  368. if (Material)
  369. {
  370. ProceduralMesh->SetMaterial(Voxel.MeshIndex, Material);
  371. }
  372. }
  373.  
  374. void AVoxelTerrainActor::RemoveVoxel(FChunk& Chunk)
  375. {
  376. TArray<FVector> VoxelPositions;
  377. Chunk.Voxels.GetKeys(VoxelPositions);
  378. auto P = VoxelPositions[0];
  379. auto& V = Chunk.Voxels[P];
  380. if (!(V.PositionFlags & ESurroundingVoxels::Top))
  381. {
  382. if (auto* FV = Chunk.Voxels.Find(FVector(P.X, P.Y, P.Z + VoxelSize)))
  383. {
  384. FV->PositionFlags |= ESurroundingVoxels::Bottom;
  385. BuildVoxel(*FV);
  386. }
  387. }
  388. if (!(V.PositionFlags & ESurroundingVoxels::Bottom))
  389. {
  390. if (auto* FV = Chunk.Voxels.Find(FVector(P.X, P.Y, P.Z - VoxelSize)))
  391. {
  392. FV->PositionFlags |= ESurroundingVoxels::Top;
  393. BuildVoxel(*FV);
  394. }
  395. }
  396. if (!(V.PositionFlags & ESurroundingVoxels::PosX))
  397. {
  398. if (auto* FV = Chunk.Voxels.Find(FVector(P.X + VoxelSize, P.Y, P.Z)))
  399. {
  400. FV->PositionFlags |= ESurroundingVoxels::NegX;
  401. BuildVoxel(*FV);
  402. }
  403. }
  404. if (!(V.PositionFlags & ESurroundingVoxels::NegX))
  405. {
  406. if (auto* FV = Chunk.Voxels.Find(FVector(P.X - VoxelSize, P.Y, P.Z)))
  407. {
  408. FV->PositionFlags |= ESurroundingVoxels::PosX;
  409. BuildVoxel(*FV);
  410. }
  411. }
  412. if (!(V.PositionFlags & ESurroundingVoxels::PosY))
  413. {
  414. if (auto* FV = Chunk.Voxels.Find(FVector(P.X, P.Y + VoxelSize, P.Z)))
  415. {
  416. FV->PositionFlags |= ESurroundingVoxels::NegY;
  417. BuildVoxel(*FV);
  418. }
  419. }
  420. if (!(V.PositionFlags & ESurroundingVoxels::NegY))
  421. {
  422. if (auto* FV = Chunk.Voxels.Find(FVector(P.X, P.Y - VoxelSize, P.Z)))
  423. {
  424. FV->PositionFlags |= ESurroundingVoxels::PosY;
  425. BuildVoxel(*FV);
  426. }
  427. }
  428.  
  429. ProceduralMesh->ClearMeshSection(V.MeshIndex);
  430. Chunk.Voxels.Remove(P);
  431.  
  432. //BuildChunk(Chunk);
  433. }
  434.  
  435. // Called every frame
  436. void AVoxelTerrainActor::Tick(float DeltaTime)
  437. {
  438. Super::Tick(DeltaTime);
  439. }
  440.  
  441.  
Add Comment
Please, Sign In to add comment