CARLA
 
载入中...
搜索中...
未找到
CustomTerrainPhysicsComponent.cpp
浏览该文件的文档.
1// Copyright (c) 2022 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#undef CreateDirectory
8
10#include "Runtime/Core/Public/Async/ParallelFor.h"
11#include "Engine/CollisionProfile.h"
12#include "Engine/StaticMeshActor.h"
13#include "StaticMeshResources.h"
14#include "CollisionQueryParams.h"
19
20#include "HAL/PlatformFilemanager.h"
21#include "HAL/RunnableThread.h"
22#include "Misc/Paths.h"
23#include "Engine/World.h"
24#include "Math/UnrealMathUtility.h"
25#include "Engine/World.h"
26#include "Landscape.h"
27#include "LandscapeHeightfieldCollisionComponent.h"
28#include "LandscapeComponent.h"
29
30#include "RHICommandList.h"
31#include "TextureResource.h"
32#include "Rendering/Texture2DResource.h"
33#include "GenericPlatform/GenericPlatformProcess.h"
34#include "Materials/MaterialParameterCollection.h"
35#include "Materials/MaterialParameterCollectionInstance.h"
36#include "Materials/MaterialInterface.h"
37#include "Materials/MaterialInstance.h"
38// #include <carla/pytorch/pytorch.h>
39
40#include "Components/SkinnedMeshComponent.h"
41#include "GenericPlatform/GenericPlatformFile.h"
42#include "Async/Async.h"
43#include "Async/Future.h"
44#include "LandscapeProxy.h"
45
46
48#include "HAL/PlatformFilemanager.h"
49#include "HAL/RunnableThread.h"
50#include "Misc/Paths.h"
51#include "Engine/World.h"
52#include "Math/UnrealMathUtility.h"
53#include "GenericPlatform/GenericPlatformFile.h"
54#include "Engine/Texture2D.h"
55#include "Engine/Texture.h"
56#include "Rendering/Texture2DResource.h"
57#include "Engine/TextureRenderTarget2D.h"
58#include "Components/PrimitiveComponent.h"
59#include "DrawDebugHelpers.h"
60#include "Kismet/KismetSystemLibrary.h"
61#include "CommandLine.h"
62#include "Components/LineBatchComponent.h"
63#include "Math/OrientedBox.h"
64#include "Misc/DateTime.h"
65#include "EngineUtils.h"
66#include <algorithm>
67#include <fstream>
68
69#include <thread>
70#include <chrono>
71
73#include "carla/rpc/String.h"
75
76
77constexpr float MToCM = 100.f;
78constexpr float CMToM = 0.01f;
79
80const int CacheExtraRadius = 10;
81
82#ifdef _WIN32
83 std::string _filesBaseFolder = std::string(getenv("USERPROFILE")) + "/carlaCache/";
84#else
85 std::string _filesBaseFolder = std::string(getenv("HOME")) + "/carlaCache/";
86#endif
87
88FVector SIToUEFrame(const FVector& In)
89{
90 return MToCM * FVector(In.X, -In.Y, In.Z);
91}
92float SIToUEFrame(const float& In) { return MToCM * In; }
93FVector SIToUEFrameDirection(const FVector& In)
94{
95 return FVector(In.X, -In.Y, In.Z);
96}
97
98FVector UEFrameToSI(const FVector& In)
99{
100 return CMToM*FVector(In.X, -In.Y, In.Z);
101}
102float UEFrameToSI(const float& In) { return CMToM * In; }
103FVector UEFrameToSIDirection(const FVector& In)
104{
105 return FVector(In.X, -In.Y, In.Z);
106}
107
109 UHeightMapDataAsset* DataAsset, FDVector Size, FDVector Origin,
110 FDVector Tile0, float ScaleZ)
111{
112 Tile0Position = Tile0;
113 WorldSize = Size;
114 Offset = Origin;
115 Size_X = DataAsset->SizeX;
116 Size_Y = DataAsset->SizeY;
117 // Pixels = DataAsset->HeightValues;
118 Pixels.clear();
119 Pixels.reserve(DataAsset->HeightValues.Num());
120 for (float Height : DataAsset->HeightValues)
121 {
122 Pixels.emplace_back(UEFrameToSI(Height));
123 }
124}
125
127{
129 uint32_t Coord_X = (Position.X / WorldSize.X) * Size_X;
130 uint32_t Coord_Y = (1.f - Position.Y / WorldSize.Y) * Size_Y;
131 Coord_X = std::min(Coord_X, Size_X-1);
132 Coord_Y = std::min(Coord_Y, Size_Y-1);
133 return Pixels[Coord_X*Size_Y + Coord_Y];
134}
135
137{
138 Pixels.clear();
139}
140
142 Particles.clear();
143 ParticlesHeightMap.clear();
144 TilePosition = FDVector(0.0,0.0,0.0);
145 SavePath = FString("NotValidPath");
147}
148
150 Particles.clear();
151 ParticlesHeightMap.clear();
152 ParticlesZOrdered.clear();
153 TilePosition = FDVector(0.0,0.0,0.0);
154 SavePath = FString("NotValidPath");
156}
157
166
168 TilePosition = Origin.TilePosition;
169 SavePath = Origin.SavePath;
171 Particles = std::move(Origin.Particles);
172 ParticlesHeightMap = std::move(Origin.ParticlesHeightMap);
173 ParticlesZOrdered = std::move(Origin.ParticlesZOrdered);
174}
175
177{
178 TilePosition = Origin.TilePosition;
179 SavePath = Origin.SavePath;
181 Particles = std::move(Origin.Particles);
182 ParticlesHeightMap = std::move(Origin.ParticlesHeightMap);
183 ParticlesZOrdered = std::move(Origin.ParticlesZOrdered);
184 return *this;
185 }
186
187void FDenseTile::InitializeTile(uint32_t TextureSize, float AffectedRadius, float ParticleSize, float Depth,
188 FDVector TileOrigin, FDVector TileEnd,
189 const FString& SavePath, const FHeightMapData &HeightMap)
190{
191
192 TileSize = (TileEnd.X - TileOrigin.X );
193 PartialHeightMapSize = TileSize * TextureSize / (2*AffectedRadius);
194 std::string FileName = std::string(TCHAR_TO_UTF8(*( SavePath + TileOrigin.ToString() + ".tile" ) ) );
195
196 //UE_LOG(LogCarla, Log, TEXT("Tile origin %s"), *TileOrigin.ToString() );
197 if( FPaths::FileExists(FString(FileName.c_str())) )
198 {
199
200 TRACE_CPUPROFILER_EVENT_SCOPE(DenseTile::InitializeTile::Read);
201 std::ifstream ReadStream(FileName);
202 FVector VectorToRead;
203 ReadFVector(ReadStream, VectorToRead );
204 TilePosition = FDVector(VectorToRead);
205 ReadStdVector<FParticle> (ReadStream, Particles);
206 //UE_LOG(LogCarla, Log, TEXT("Reading data, got %d particles"), Particles.size());
207 }
208 else
209 {
210 TRACE_CPUPROFILER_EVENT_SCOPE(DenseTile::InitializeTile::Create);
211
212 TilePosition = TileOrigin;
213 uint32_t NumParticles_X = (TileEnd.X - TileOrigin.X) / ParticleSize;
214 uint32_t NumParticles_Y = FMath::Abs(TileEnd.Y - TileOrigin.Y) / ParticleSize;
215 uint32_t NumParticles_Z = (Depth) / ParticleSize;
216 Particles = std::vector<FParticle>(NumParticles_X*NumParticles_Y*NumParticles_Z);
217
218 //UE_LOG(LogCarla, Log, TEXT("Initializing Tile with (%d,%d,%d) particles at location %s, size %f, depth %f, HeightMap at tile origin %f"),
219 // NumParticles_X,NumParticles_Y,NumParticles_Z, *TileOrigin.ToString(), ParticleSize, Depth, HeightMap.GetHeight(TileOrigin) );
220
221 for(uint32_t i = 0; i < NumParticles_X; i++)
222 {
223 for(uint32_t j = 0; j < NumParticles_Y; j++)
224 {
225 FDVector ParticleLocalPosition = FDVector(i*ParticleSize, j*ParticleSize, 0.0f);
226 FDVector ParticlePosition = TileOrigin + ParticleLocalPosition;
227 float Height = HeightMap.GetHeight(ParticlePosition);
228 for(uint32_t k = 0; k < NumParticles_Z; k++)
229 {
230 ParticlePosition.Z = TileOrigin.Z + Height - k*ParticleSize;
231 Particles[k*NumParticles_X*NumParticles_Y + j*NumParticles_X + i] =
232 {ParticlePosition, FVector(0), ParticleSize/2.f};
233 }
234 }
235 }
236
237 //UE_LOG(LogCarla, Log, TEXT("Building local heightMap of %d pixels"), PartialHeightMapSize);
238
239 }
241
242 for(float& Height : ParticlesHeightMap)
243 {
244 Height = 0;
245 }
246
249}
250
252{
253 {
254 TRACE_CPUPROFILER_EVENT_SCOPE(DenseTile::InitializeTile::ParticlesZOrdered);
255 ParticlesHeightMap.clear();
257 float InverseTileSize = 1.f/TileSize;
258 float Transformation = InverseTileSize * PartialHeightMapSize;
259
260 for (size_t i = 0; i < Particles.size(); i++)
261 {
262 const FParticle& P = Particles[i];
263 FDVector ParticleLocalPosition = P.Position - TilePosition;
264 // Recalculate position to get it into heightmap coords
265 FIntVector HeightMapCoords = FIntVector(
266 ParticleLocalPosition.X * Transformation,
267 ParticleLocalPosition.Y * Transformation, 0);
268
269 uint32_t Index = HeightMapCoords.Y * PartialHeightMapSize + HeightMapCoords.X;
270 // Compare to the current value, if higher replace
271 if(Index < ParticlesZOrdered.size() ){
272 ParticlesZOrdered[Index].insert(P.Position.Z);
273 }
274 }
275
276 }
279}
280
281// revise coordinates
282void FDenseTile::GetParticlesInRadius(FDVector Position, float Radius, std::vector<FParticle*> &ParticlesInRadius)
283{
284 TRACE_CPUPROFILER_EVENT_SCOPE(FDenseTile::GetParticlesInRadius);
285 for (FParticle& particle : Particles)
286 {
287 if((particle.Position - Position).SizeSquared() < Radius*Radius)
288 {
289 ParticlesInRadius.emplace_back(&particle);
290 }
291 }
292}
293// revise coordinates
294std::vector<FParticle*> FDenseTile::GetParticlesInRadius(FDVector Position, float Radius)
295{
296 TRACE_CPUPROFILER_EVENT_SCOPE(FDenseTile::GetParticlesInRadius);
297 std::vector<FParticle*> ParticlesInRadius;
298 for (FParticle& particle : Particles)
299 {
300 if((particle.Position - Position).SizeSquared() < Radius*Radius)
301 {
302 ParticlesInRadius.emplace_back(&particle);
303 }
304 }
305 return ParticlesInRadius;
306}
307
309 const FOrientedBox& OBox, std::vector<FParticle*> &ParticlesInRadius)
310{
311 TRACE_CPUPROFILER_EVENT_SCOPE(FDenseTile::GetParticlesInBox);
312 for (FParticle& Particle : Particles)
313 {
314 FVector PToCenter = SIToUEFrame(Particle.Position.ToFVector()) - OBox.Center;
315 if((FMath::Abs(FVector::DotProduct(PToCenter, OBox.AxisX)) < OBox.ExtentX) &&
316 (FMath::Abs(FVector::DotProduct(PToCenter, OBox.AxisY)) < OBox.ExtentY) &&
317 (FMath::Abs(FVector::DotProduct(PToCenter, OBox.AxisZ)) < OBox.ExtentZ))
318 {
319 ParticlesInRadius.emplace_back(&Particle);
320 }
321 }
322}
323
324void FDenseTile::GetAllParticles(std::vector<FParticle*> &ParticlesInRadius)
325{
326 for (FParticle& Particle : Particles)
327 {
328 ParticlesInRadius.emplace_back(&Particle);
329 }
330}
331
333{
335 TRACE_CPUPROFILER_EVENT_SCOPE(FDenseTile::UpdateLocalHeightmap);
336 for( uint32_t i = 0; i < ParticlesHeightMap.size() ; ++i ){
337 if( ParticlesZOrdered.size() == ParticlesHeightMap.size() ){
338 float Value = * ( ParticlesZOrdered[i].begin() );
339 ParticlesHeightMap[i] = Value;
340 }
341 }
343 }
344
345}
346
347// revise coordinates
348std::vector<FParticle*> FSparseHighDetailMap::
350{
351 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetParticlesInRadius);
352
353 uint64_t TileId = GetTileId(Position);
354 uint32_t Tile_X = (uint32_t)(TileId >> 32);
355 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
356
357 // FDenseTile& Tile = GetTile(TileId);
358 // return Tile.GetParticlesInRadius(Position, Radius);
359 std::vector<FParticle*> ParticlesInRadius;
360
361 GetTile(Tile_X-1, Tile_Y-1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
362 GetTile(Tile_X, Tile_Y-1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
363 GetTile(Tile_X+1, Tile_Y-1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
364 GetTile(Tile_X-1, Tile_Y).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
365 GetTile(Tile_X, Tile_Y).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
366 GetTile(Tile_X+1, Tile_Y).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
367 GetTile(Tile_X-1, Tile_Y+1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
368 GetTile(Tile_X, Tile_Y+1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
369 GetTile(Tile_X+1, Tile_Y+1).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
370
371 return ParticlesInRadius;
372}
373
374std::vector<FParticle*> FSparseHighDetailMap::
376{
377 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetParticlesInRadius);
378
379 uint64_t TileId = GetTileId(Position);
380 uint32_t Tile_X = (uint32_t)(TileId >> 32);
381 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
382
383 uint32_t RadiusInTiles = (Radius/TileSize);
384 uint32_t MinX,MinY,MaxX,MaxY = 0;
385
386 if( Tile_X < RadiusInTiles){
387 MinX = 0;
388 }else{
389 MinX = Tile_X - RadiusInTiles;
390 }
391
392 if( Tile_Y < RadiusInTiles){
393 MinY = 0;
394 }else{
395 MinY = Tile_Y - RadiusInTiles;
396 }
397
398 if( ((Extension.X) / TileSize - RadiusInTiles) < Tile_X ){
399 MaxX = (Extension.X) / TileSize;
400 }else{
401 MaxX = Tile_X + RadiusInTiles;
402 }
403
404 if( ((-Extension.Y) / TileSize) - RadiusInTiles < Tile_Y ){
405 MaxY = (-Extension.Y) / TileSize;
406 }else{
407 MaxY = Tile_Y + RadiusInTiles;
408 }
409 /*
410 UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::GetParticlesInTileRadius MinX %zu MaxX: %zu, MinY %zu MaxY %zu"),
411 MinX, MaxX, MinY, MaxY);
412 UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::GetParticlesInTileRadius Extension X: %f, Y %f"), Extension.X, Extension.Y);
413 UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::GetParticlesInTileRadius Position X: %f, Y %f"), Position.X, Position.Y);
414 UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::GetParticlesInTileRadius RadiusInTiles %d"), RadiusInTiles);
415 UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::GetParticlesInTileRadius TileId %lld TileX: %d, TileY %d"),
416 TileId, Tile_X, Tile_Y);
417
418
419 */
420 // FDenseTile& Tile = GetTile(TileId);
421 // return Tile.GetParticlesInRadius(Position, Radius);
422 std::vector<FParticle*> ParticlesInRadius;
423 for( uint32_t X = MinX; X <= MaxX; ++X )
424 {
425 for( uint32_t Y = MinY; Y <= MaxY; ++Y )
426 {
427 uint64_t CurrentTileId = GetTileId(X,Y);
428 if( Map.count(CurrentTileId) )
429 {
430 GetTile(X, Y).GetParticlesInRadius(Position, Radius, ParticlesInRadius);
431 }
432 }
433 }
434 return ParticlesInRadius;
435}
436
437std::vector<FParticle*> FSparseHighDetailMap::
438 GetParticlesInBox(const FOrientedBox& OBox)
439{
440 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetParticlesInBox);
441 std::vector<uint64_t> TilesToCheck = GetIntersectingTiles(OBox);
442
443 std::vector<FParticle*> ParticlesInRadius;
444 for(uint64_t TileId : TilesToCheck)
445 {
446 GetTile(TileId).GetParticlesInBox(OBox, ParticlesInRadius);
447 }
448 return ParticlesInRadius;
449}
450
452 const FOrientedBox& OBox)
453{
454TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetIntersectingTiles);
455 std::vector<uint64_t> IntersectingTiles;
456
457 FVector BoxCenter = UEFrameToSI(OBox.Center);
458 float ExtentX = UEFrameToSI(OBox.ExtentX);
459 float ExtentXSqr = ExtentX*ExtentX;
460 FVector AxisX = UEFrameToSIDirection(OBox.AxisX);
461 float ExtentY = UEFrameToSI(OBox.ExtentY);
462 float ExtentYSqr = ExtentY*ExtentY;
463 FVector AxisY = UEFrameToSIDirection(OBox.AxisY);
464
465 uint64_t CenterTileId = GetTileId(BoxCenter);
466 uint32_t CenterTile_X = (uint32_t)(CenterTileId >> 32);
467 uint32_t CenterTile_Y = (uint32_t)(CenterTileId & (uint32_t)(~0));
468 uint32_t TileRange = 1;
469 IntersectingTiles.emplace_back(CenterTileId);
470 FVector2D BoxVert0 = FVector2D(BoxCenter - AxisX*ExtentX - AxisY*ExtentY);
471 FVector2D BoxVert1 = FVector2D(BoxCenter + AxisX*ExtentX - AxisY*ExtentY);
472 FVector2D BoxVert2 = FVector2D(BoxCenter + AxisX*ExtentX + AxisY*ExtentY);
473 FVector2D BoxVert3 = FVector2D(BoxCenter - AxisX*ExtentX + AxisY*ExtentY);
474
475 // Use separate axis theorem to detect intersecting tiles with OBox
476 struct F2DRectangle
477 {
478 FVector2D V1, V2, V3, V4;
479 std::vector<FVector2D> ComputeNormals() const
480 {
481 FVector2D V12 = (V2 - V1).GetSafeNormal();
482 FVector2D V23 = (V3 - V2).GetSafeNormal();
483 return {FVector2D(-V12.Y, V12.X), FVector2D(-V23.Y, V23.X)};
484 }
485 };
486 auto SATtest = [&](const FVector2D& Axis, const F2DRectangle &Shape,
487 float &MinAlong, float &MaxAlong)
488 {
489 for (const FVector2D& Vert : {Shape.V1, Shape.V2, Shape.V3, Shape.V4})
490 {
491 float DotVal = FVector2D::DotProduct(Vert, Axis);
492 if( DotVal < MinAlong )
493 MinAlong = DotVal;
494 if( DotVal > MaxAlong )
495 MaxAlong = DotVal;
496 }
497 };
498 auto IsBetweenOrdered = [&]( float Val, float LowerBound, float UpperBound ) -> bool
499 {
500 return LowerBound <= Val && Val <= UpperBound ;
501 };
502 auto Overlaps = [&]( float Min1, float Max1, float Min2, float Max2 ) -> bool
503 {
504 return IsBetweenOrdered( Min2, Min1, Max1 ) || IsBetweenOrdered( Min1, Min2, Max2 ) ;
505 };
506 auto RectangleIntersect = [&](
507 const F2DRectangle& Rectangle1,
508 const F2DRectangle& Rectangle2) -> bool
509 {
510 for (const FVector2D& Normal : Rectangle1.ComputeNormals())
511 {
512 constexpr float LargeNumber = 10000000;
513 float Shape1Min = LargeNumber, Shape1Max = -LargeNumber;
514 float Shape2Min = LargeNumber, Shape2Max = -LargeNumber;
515 SATtest(Normal, Rectangle1, Shape1Min, Shape1Max);
516 SATtest(Normal, Rectangle2, Shape2Min, Shape2Max);
517 if (!Overlaps(Shape1Min, Shape1Max, Shape2Min, Shape2Max))
518 {
519 return false;
520 }
521 }
522 for (const FVector2D& Normal : Rectangle2.ComputeNormals())
523 {
524 constexpr float LargeNumber = 10000000;
525 float Shape1Min = LargeNumber, Shape1Max = -LargeNumber;
526 float Shape2Min = LargeNumber, Shape2Max = -LargeNumber;
527 SATtest(Normal, Rectangle1, Shape1Min, Shape1Max);
528 SATtest(Normal, Rectangle2, Shape2Min, Shape2Max);
529 if (!Overlaps(Shape1Min, Shape1Max, Shape2Min, Shape2Max))
530 {
531 return false;
532 }
533 }
534 return true;
535 };
536 // check surrounding tiles except CenterTile (as it is always included)
537 std::vector<std::pair<uint32_t, uint32_t>> TilesToCheck = {
538 {CenterTile_X-1, CenterTile_Y-1}, {CenterTile_X, CenterTile_Y-1},
539 {CenterTile_X+1, CenterTile_Y-1}, {CenterTile_X-1, CenterTile_Y},
540 {CenterTile_X+1, CenterTile_Y}, {CenterTile_X-1, CenterTile_Y+1},
541 {CenterTile_X, CenterTile_Y+1}, {CenterTile_X+1, CenterTile_Y+1}};
542 for (auto& TileIdPair : TilesToCheck)
543 {
544 uint32_t &Tile_X = TileIdPair.first;
545 uint32_t &Tile_Y = TileIdPair.second;
546 FVector2D V1 = FVector2D(GetTilePosition(Tile_X, Tile_Y).ToFVector());
547 FVector2D V2 = FVector2D(GetTilePosition(Tile_X+1, Tile_Y).ToFVector());
548 FVector2D V3 = FVector2D(GetTilePosition(Tile_X+1, Tile_Y+1).ToFVector());
549 FVector2D V4 = FVector2D(GetTilePosition(Tile_X, Tile_Y+1).ToFVector());
550 if (RectangleIntersect(
551 F2DRectangle{BoxVert0,BoxVert1,BoxVert2,BoxVert3},
552 F2DRectangle{V1,V2,V3,V4}))
553 {
554 IntersectingTiles.emplace_back(GetTileId(Tile_X, Tile_Y));
555 }
556 }
557
558 return IntersectingTiles;
559}
560
562{
563 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetLoadedTilesInRange);
564
565 uint64_t TileId = GetTileId(Position);
566 uint32_t Tile_X = (uint32_t)(TileId >> 32);
567 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
568
569 uint32_t RadiusInTiles = (Radius/TileSize);
570 uint32_t MinX = 0,MinY = 0,MaxX = 0,MaxY = 0;
571 {
572 TRACE_CPUPROFILER_EVENT_SCOPE(Comparisons);
573 if( Tile_X < RadiusInTiles){
574 MinX = 0;
575 }else{
576 MinX = Tile_X - RadiusInTiles;
577 }
578
579 if( Tile_Y < RadiusInTiles){
580 MinY = 0;
581 }else{
582 MinY = Tile_Y - RadiusInTiles;
583 }
584
585 MaxX = Tile_X + RadiusInTiles;
586 MaxY = Tile_Y + RadiusInTiles;
587 }
588
589 std::vector<uint64_t> LoadedTiles;
590 {
591 TRACE_CPUPROFILER_EVENT_SCOPE(Looping);
592 for( uint32_t X = MinX; X < MaxX; ++X )
593 {
594 for( uint32_t Y = MinY; Y < MaxY; ++Y )
595 {
596 uint64_t CurrentTileId = GetTileId(X,Y);
597 if( Map.find(CurrentTileId) != Map.end() )
598 {
599 LoadedTiles.emplace_back(CurrentTileId);
600 }
601 }
602 }
603 }
604 return LoadedTiles;
605}
606
607uint64_t FSparseHighDetailMap::GetTileId(uint32_t Tile_X, uint32_t Tile_Y)
608{
609 return (uint64_t) Tile_X << 32 | Tile_Y;
610}
611
613{
614 uint32_t Tile_X = static_cast<uint32_t>((Position.X - Tile0Position.X) / TileSize);
615 uint32_t Tile_Y = static_cast<uint32_t>((Position.Y - Tile0Position.Y) / TileSize);
616 // UE_LOG(LogCarla, Log, TEXT("Getting tile at location %s, (%d, %d)"), *Position.ToString(), Tile_X, Tile_Y);
617 return GetTileId(Tile_X, Tile_Y);
618}
619
621{
622 uint32_t Tile_X = (uint32_t)(TileId >> 32);
623 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
624 return GetTilePosition(Tile_X, Tile_Y);
625}
626
627FDVector FSparseHighDetailMap::GetTilePosition(uint32_t Tile_X, uint32_t Tile_Y)
628{
631 return Position;
632}
633
635{
636 uint64_t TileId = GetTileId(Position);
637 return GetTile(TileId);
638}
639
640FDenseTile& FSparseHighDetailMap::GetTile(uint32_t Tile_X, uint32_t Tile_Y)
641{
642 uint64_t TileId = GetTileId(Tile_X, Tile_Y);
643 return GetTile(TileId);
644}
646{
647 auto Iterator = Map.find(TileId);
648 if (Iterator == Map.end())
649 {
650 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::GetTile);
651 // FScopeLock Lock(&Lock_CacheMap);
652 Lock_GetTile.Lock();
653 bool bGotCacheLock = Lock_CacheMap.TryLock();
654 if(bGotCacheLock)
655 {
656 auto CacheIterator = CacheMap.find(TileId);
657 if (CacheIterator != CacheMap.end())
658 {
659 Map.emplace(TileId, std::move(CacheIterator->second));
660 CacheMap.erase(CacheIterator);
661 Lock_CacheMap.Unlock();
662 Lock_GetTile.Unlock();
663 return Map[TileId];
664 }
665 Lock_CacheMap.Unlock();
666 }
667 FDenseTile& Tile = Map[TileId];
668 Lock_GetTile.Unlock();
669 return InitializeRegion(TileId);
670 }
671 return Iterator->second;
672}
673
675{
676 uint32_t Tile_X = static_cast<uint32_t>((Position.X - Tile0Position.X) / TileSize);
677 uint32_t Tile_Y = static_cast<uint32_t>((Position.Y - Tile0Position.Y) / TileSize);
678 return FIntVector(Tile_X, Tile_Y, 0);
679}
680FIntVector FSparseHighDetailMap::GetVectorTileId(uint64_t TileId)
681{
682 uint32_t Tile_X = (uint32_t)(TileId >> 32);
683 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
684 return FIntVector(Tile_X, Tile_Y, 0);
685}
686
687FDenseTile& FSparseHighDetailMap::InitializeRegion(uint32_t Tile_X, uint32_t Tile_Y)
688{
689 uint64_t TileId = GetTileId(Tile_X, Tile_Y);
690 return InitializeRegion(TileId);
691}
692
694{
695 FDVector TileCenter = GetTilePosition(TileId);
696 FDenseTile& Tile = Map[TileId];
697 //UE_LOG(LogCarla, Log, TEXT("InitializeRegion Tile with (%f,%f,%f)"),
698 // TileCenter.X,TileCenter.Y,TileCenter.Z);
699 Tile.InitializeTile(
702 TileCenter, TileCenter + FDVector(TileSize, TileSize, 0.f),
704 return Tile;
705}
706
708{
709 FDVector TileCenter = GetTilePosition(TileId);
710 FDenseTile& Tile = CacheMap[TileId];
711 //UE_LOG(LogCarla, Log, TEXT("InitializeRegionInCache Tile with (%f,%f,%f)"),
712 // TileCenter.X,TileCenter.Y,TileCenter.Z);
713
714 Tile.InitializeTile(
717 TileCenter, TileCenter + FDVector(TileSize, TileSize, 0.f),
719 Lock_CacheMap.Unlock();
720 return Tile;
721}
722
724 FDVector Origin, FDVector MapSize, float Size, float ScaleZ)
725{
726 Tile0Position = Origin;
727 TileSize = Size;
728 Extension = MapSize;
730 DataAsset, Extension, Tile0Position,
731 Tile0Position, ScaleZ);
732 UE_LOG(LogCarla, Log,
733 TEXT("Sparse Map initialized"));
734 UE_LOG(LogCarla, Log,
735 TEXT("Map Extension %f %f %f"), MapSize.X, MapSize.Y, MapSize.Z );
736}
737
739 FDVector Origin, FDVector MapSize, float Size,
740 float ScaleZ)
741{
744 DataAsset, Extension, Origin,
745 Origin, ScaleZ);
746 UE_LOG(LogCarla, Log,
747 TEXT("Height map updated"));
748}
750{
752 Map.clear();
753}
754
756 FDVector Position, float RadiusX, float RadiusY, float CacheRadiusX, float CacheRadiusY)
757{
758 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::UpdateMaps);
759 double MinX = Position.X - RadiusX;
760 double MinY = Position.Y - RadiusY;
761 double MaxX = Position.X + RadiusX;
762 double MaxY = Position.Y + RadiusY;
763
764 FIntVector MinVector = GetVectorTileId(FDVector(MinX, MinY, 0));
765 FIntVector MaxVector = GetVectorTileId(FDVector(MaxX, MaxY, 0));
766
767 FIntVector CacheMinVector = GetVectorTileId(
768 FDVector(Position.X - CacheRadiusX, Position.Y - CacheRadiusY, 0));
769 FIntVector CacheMaxVector = GetVectorTileId(
770 FDVector(Position.X + CacheRadiusX, Position.Y + CacheRadiusY, 0));
771
772 auto IsInCacheRange = [&](int32_t Tile_X, int32_t Tile_Y) -> bool
773 {
774 return Tile_X >= CacheMinVector.X && Tile_X <= CacheMaxVector.X &&
775 Tile_Y >= CacheMinVector.Y && Tile_Y <= CacheMaxVector.Y;
776 };
777 auto IsInMapRange = [&](int32_t Tile_X, int32_t Tile_Y) -> bool
778 {
779 return Tile_X >= MinVector.X && Tile_X <= MaxVector.X &&
780 Tile_Y >= MinVector.Y && Tile_Y <= MaxVector.Y;
781 };
782 {
783 FScopeLock ScopeLock(&Lock_Map);
784 FScopeLock ScopeCacheLock(&Lock_CacheMap);
785 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateMap);
786 // unload extra tiles
787 std::vector<uint64_t> TilesToErase;
788 for (auto &Element : Map)
789 {
790 uint64_t TileId = Element.first;
791 FIntVector VectorTileId = GetVectorTileId(TileId);
792 if (!IsInMapRange(VectorTileId.X, VectorTileId.Y))
793 {
794 CacheMap.emplace(TileId, std::move(Element.second));
795 TilesToErase.emplace_back(TileId);
796 }
797 }
798 for (uint64_t TileId : TilesToErase)
799 {
800 Map.erase(TileId);
801 }
802 }
803 {
804 FScopeLock ScopeCacheLock(&Lock_CacheMap);
805 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateCache);
806
807 // unload extra tiles
808 std::vector<uint64_t> TilesToErase;
809 {
810 TRACE_CPUPROFILER_EVENT_SCOPE(GetTilesToErase);
811 for (auto &Element : CacheMap)
812 {
813 uint64_t TileId = Element.first;
814 FIntVector VectorTileId = GetVectorTileId(TileId);
815 if (!IsInCacheRange(VectorTileId.X, VectorTileId.Y))
816 {
817 TilesToErase.emplace_back(TileId);
818 }
819 }
820 }
821
822 {
823 TRACE_CPUPROFILER_EVENT_SCOPE(EraseTiles);
824 ParallelFor(TilesToErase.size(), [&](int32 Idx)
825 {
826 TRACE_CPUPROFILER_EVENT_SCOPE(SaveData);
827 uint64_t TileId = TilesToErase[Idx];
828 auto& Tile = CacheMap[TileId];
829 std::string FileToSavePath = std::string(
830 TCHAR_TO_UTF8(*( SavePath + Tile.TilePosition.ToString() + ".tile")));
831 std::ofstream OutputStream(FileToSavePath.c_str());
832 WriteFVector(OutputStream, Tile.TilePosition.ToFVector());
833 WriteStdVector<FParticle> (OutputStream, Tile.Particles);
834 OutputStream.close();
835 });
836 {
837 TRACE_CPUPROFILER_EVENT_SCOPE(CacheMap.erase);
838 for (uint64_t TileId : TilesToErase)
839 {
840 CacheMap.erase(TileId);
841 }
842 }
843 }
844 }
845
846}
847
848void FSparseHighDetailMap::Update(FVector Position, float RadiusX, float RadiusY)
849{
850 FVector PositionTranslated;
851 PositionTranslated.X = ( Position.X * 0.01 ) + (Extension.X * 0.5f);
852 PositionTranslated.Y = (-Position.Y * 0.01 ) + ( (-Extension.Y) * 0.5f);
853 PositionTranslated.Z = ( Position.Z * 0.01 ) + (Extension.Z * 0.5f);
854 PositionToUpdate = PositionTranslated;
855
856 double MinX = std::min( std::max( PositionTranslated.X - RadiusX, 0.0f) , static_cast<float>(Extension.X - 1.0f) );
857 double MinY = std::min( std::max( PositionTranslated.Y - RadiusY, 0.0f) , static_cast<float>(-Extension.Y + 1.0f) );
858 double MaxX = std::min( std::max( PositionTranslated.X + RadiusX, 0.0f) , static_cast<float>(Extension.X - 1.0f) );
859 double MaxY = std::min( std::max( PositionTranslated.Y + RadiusY, 0.0f) , static_cast<float>(-Extension.Y + 1.0f) );
860
861 FIntVector MinVector = GetVectorTileId(FDVector(std::floor(MinX), std::floor(MinY), 0));
862 FIntVector MaxVector = GetVectorTileId(FDVector(std::floor(MaxX), std::floor(MaxY), 0));
863
864 {
865 TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("FSparseHighDetailMap::WaitUntilProperTilesAreLoaded"));
866 for(int32_t X = MinVector.X; X < MaxVector.X; X++ )
867 {
868 for(int32_t Y = MinVector.Y; Y < MaxVector.Y; Y++ )
869 {
870 bool ConditionToStopWaiting = true;
871 // Check if tiles are already loaded
872 // If they are send position
873 // If not wait until loaded
874 while(ConditionToStopWaiting)
875 {
876 uint64_t CurrentTileID = GetTileId(X,Y);
877 {
878 TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("FSparseHighDetailMap::WaitUntilProperTilesAreLoaded::TimeLocked"));
879 ConditionToStopWaiting = Map.find(CurrentTileID) == Map.end();
880 }
881
882 }
883 }
884 }
885 }
886
887}
888
890{
891 UE_LOG(LogCarla, Warning, TEXT("Save directory %s"), *SavePath );
892 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::SaveMap);
893 ParallelFor(Map.size(), [this](int32 Idx)
894 {
895 std::pair<uint64_t, FDenseTile> it = *(std::next(this->Map.begin(), Idx) );
896 std::string FileToSavePath = std::string(TCHAR_TO_UTF8(*( this->SavePath + it.second.TilePosition.ToString() + ".tile")));
897 std::ofstream OutputStream(FileToSavePath.c_str());
898 WriteFVector(OutputStream, it.second.TilePosition.ToFVector());
899 WriteStdVector<FParticle> (OutputStream, it.second.Particles);
900 OutputStream.close();
901 });
902
903 ParallelFor(CacheMap.size(), [this](int32 Idx)
904 {
905 std::pair<uint64_t, FDenseTile> it = *(std::next(this->CacheMap.begin(), Idx) );
906 std::string FileToSavePath = std::string(TCHAR_TO_UTF8(*( this->SavePath + it.second.TilePosition.ToString() + ".tile")));
907 std::ofstream OutputStream(FileToSavePath.c_str());
908 WriteFVector(OutputStream, it.second.TilePosition.ToFVector());
909 WriteStdVector<FParticle> (OutputStream, it.second.Particles);
910 OutputStream.close();
911 });
912
913}
914
915void UCustomTerrainPhysicsComponent::UpdateTexture()
916{
917 UpdateLoadedTextureDataRegions();
918
919 ENQUEUE_RENDER_COMMAND(UpdateDynamicTextureCode)
920 (
921 [NewData=Data, Texture=TextureToUpdate](auto &InRHICmdList) mutable
922 {
923 TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UCustomTerrainPhysicsComponent::TickComponent Renderthread"));
924 FUpdateTextureRegion2D region;
925 region.SrcX = 0;
926 region.SrcY = 0;
927 region.DestX = 0;
928 region.DestY = 0;
929 region.Width = Texture->GetSizeX();
930 region.Height = Texture->GetSizeY();
931
932 FTexture2DResource* resource = (FTexture2DResource*)Texture->Resource;
933 RHIUpdateTexture2D(
934 resource->GetTexture2DRHI(), 0, region, region.Width * sizeof(uint8_t), &NewData[0]);
935 });
936}
937
938void UCustomTerrainPhysicsComponent::InitTexture(){
939 if( Data.Num() == 0 && TextureToUpdate ){
940 float LimitX = TextureToUpdate->GetSizeX();
941 float LimitY = TextureToUpdate->GetSizeY();
942 Data.Init(128, LimitX * LimitY);
943 }
944
945 if( LargeData.Num() == 0 && LargeTextureToUpdate ){
946 float LimitX = LargeTextureToUpdate->GetSizeX();
947 float LimitY = LargeTextureToUpdate->GetSizeY();
948 LargeData.Init(128, LimitX * LimitY);
949 }
950}
951
952void UCustomTerrainPhysicsComponent::UpdateLoadedTextureDataRegions()
953{
954 TRACE_CPUPROFILER_EVENT_SCOPE("UCustomTerrainPhysicsComponent::UpdateLoadedTextureDataRegions");
955 const int32_t TextureSizeX = TextureToUpdate->GetSizeX();
956 if ( TextureSizeX == 0) return;
957
958
959 FDVector TextureCenterPosition = UEFrameToSI(GetTileCenter(LastUpdatedPosition));
960
961 std::vector<uint64_t> LoadedTiles =
962 SparseMap.GetLoadedTilesInRange(TextureCenterPosition, TextureRadius );
963 FDVector TextureOrigin = TextureCenterPosition - FDVector(TextureRadius, TextureRadius, 0);
964 float GlobalTexelSize = (2.0f * TextureRadius) / TextureSizeX;
965 int32_t PartialHeightMapSize = std::floor( SparseMap.GetTileSize() * TextureSizeX / (2*TextureRadius) );
966
967 float LocalTexelSize = SparseMap.GetTileSize() / PartialHeightMapSize;
968 LocalTexelSize = std::floor( LocalTexelSize * 1000.0f ) / 1000.0f;
969
970 Data.Init( 128, Data.Num() );
971 float DisplacementRange = MaxDisplacement - MinDisplacement;
972 float InverseDisplacementRange = 1.0f / DisplacementRange;
973
974 for (uint64_t TileId : LoadedTiles)
975 {
976 FDenseTile& CurrentTile = SparseMap.GetTile(TileId);
977
978 if (!CurrentTile.bParticlesZOrderedInitialized)
979 {
980 continue;
981 }
982
983 FDVector& TilePosition = CurrentTile.TilePosition;
984 for (int32_t Local_Y = 0; Local_Y < PartialHeightMapSize; ++Local_Y)
985 {
986 for (int32_t Local_X = 0; Local_X < PartialHeightMapSize; ++Local_X)
987 {
988 int32_t LocalIndex = Local_Y * PartialHeightMapSize + Local_X;
989 float Height = CurrentTile.ParticlesHeightMap[LocalIndex];
990 FDVector LocalTexelPosition =
991 TilePosition + FDVector(Local_X*LocalTexelSize, Local_Y*LocalTexelSize, 0);
992 int32_t Coord_X = std::floor( (LocalTexelPosition.X - TextureOrigin.X ) / GlobalTexelSize );
993 int32_t Coord_Y = std::floor( (LocalTexelPosition.Y - TextureOrigin.Y ) / GlobalTexelSize );
994
995 if ( Coord_X >= 0 && Coord_X < TextureSizeX &&
996 Coord_Y >= 0 && Coord_Y < TextureToUpdate->GetSizeY() )
997 {
998 float OriginalHeight = SparseMap.GetHeight(LocalTexelPosition);
999 float Displacement = Height - OriginalHeight;
1000 float Fraction = (Displacement - MinDisplacement) * InverseDisplacementRange;
1001 Fraction = FMath::Clamp(Fraction, 0.f, 1.f) * 255;
1002 Data[Coord_X * TextureToUpdate->GetSizeY() + Coord_Y] = static_cast<uint8_t>(Fraction );
1003 }
1004 }
1005 }
1006 }
1007}
1008
1009void UCustomTerrainPhysicsComponent::UpdateLargeTexture()
1010{
1011 UpdateLargeTextureData();
1012
1013 ENQUEUE_RENDER_COMMAND(UpdateDynamicTextureCode)
1014 (
1015 [NewData=LargeData, Texture=LargeTextureToUpdate](auto &InRHICmdList) mutable
1016 {
1017 TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UCustomTerrainPhysicsComponent::TickComponent Renderthread"));
1018 FUpdateTextureRegion2D region;
1019 region.SrcX = 0;
1020 region.SrcY = 0;
1021 region.DestX = 0;
1022 region.DestY = 0;
1023 region.Width = Texture->GetSizeX();
1024 region.Height = Texture->GetSizeY();
1025
1026 FTexture2DResource* resource = (FTexture2DResource*)Texture->Resource;
1027 RHIUpdateTexture2D(
1028 resource->GetTexture2DRHI(), 0, region, region.Width * sizeof(uint8_t), &NewData[0]);
1029 });
1030}
1031
1032void UCustomTerrainPhysicsComponent::UpdateLargeTextureData()
1033{
1034 uint32_t NumberOfParticlesIn1AxisInLocalHeightmap = TextureToUpdate->GetSizeX() / (TextureRadius * 2) / TileSize;
1035 uint32_t NumberOfParticlesIn1AxisInLargeHeightmap = LargeTextureToUpdate->GetSizeX() / (CacheRadius.X * 2) / TileSize;
1036
1037 std::vector<float> ParticlesPositions;
1038 {
1039 TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UCustomTerrainPhysicsComponent::UpdateLargeTextureData::GettingHeightMaps"));
1040 FVector OriginPosition;
1041 OriginPosition.X = CachePosition.X + (WorldSize.X * 0.5f);
1042 OriginPosition.Y = -CachePosition.Y - (WorldSize.Y * 0.5f);
1043
1044 //UE_LOG(LogCarla, Log, TEXT("FSparseHighDetailMap::UpdateTextureData OriginPosition X: %f, Y %f"), OriginPosition.X, OriginPosition.Y);
1045 }
1046
1047 int32_t OffsetX = 0;
1048 int32_t OffsetY = 0;
1049 float* Ptr = &ParticlesPositions[0];
1050 while( OffsetY < LargeTextureToUpdate->GetSizeY() )
1051 {
1052 for(uint32_t y = 0; y < NumberOfParticlesIn1AxisInLocalHeightmap; y++)
1053 {
1054 float LocalYTransformed = std::floor(y / NumberOfParticlesIn1AxisInLocalHeightmap * NumberOfParticlesIn1AxisInLargeHeightmap);
1055 for(uint32_t x = 0; x < NumberOfParticlesIn1AxisInLocalHeightmap; x++)
1056 {
1057 uint32_t LocalIndex = x + y * NumberOfParticlesIn1AxisInLocalHeightmap;
1058 float LocalXTransformed = std::floor(x / NumberOfParticlesIn1AxisInLocalHeightmap * NumberOfParticlesIn1AxisInLargeHeightmap);
1059 //uint32_t AbsolutIndex = (LocalXTransformed + OffsetX) + (LocalYTransformed + OffsetY) *
1060
1061 }
1062 }
1063
1064 Ptr += (NumberOfParticlesIn1AxisInLocalHeightmap* NumberOfParticlesIn1AxisInLocalHeightmap);
1065
1066 OffsetX += NumberOfParticlesIn1AxisInLargeHeightmap;
1067 if( OffsetX >= LargeTextureToUpdate->GetSizeX() )
1068 {
1069 OffsetX = 0;
1070 OffsetY += NumberOfParticlesIn1AxisInLargeHeightmap;
1071 }
1072 }
1073}
1074
1075
1076UCustomTerrainPhysicsComponent::UCustomTerrainPhysicsComponent()
1077 : Super()
1078{
1079 PrimaryComponentTick.bCanEverTick = true;
1080}
1081
1082void UCustomTerrainPhysicsComponent::BeginPlay()
1083{
1084 TRACE_CPUPROFILER_EVENT_SCOPE(UCustomTerrainPhysicsComponent::BeginPlay);
1085 Super::BeginPlay();
1086 //GEngine->Exec( GetWorld(), TEXT( "Trace.Start default,gpu" ) );
1087
1088 SparseMap.Clear();
1089 RootComponent = Cast<UPrimitiveComponent>(GetOwner()->GetRootComponent());
1090 if (!RootComponent)
1091 {
1092 UE_LOG(LogCarla, Error,
1093 TEXT("UCustomTerrainPhysicsComponent: Root component is not a UPrimitiveComponent"));
1094 }
1095#ifndef WITH_EDITOR
1096 bUpdateParticles = true;
1097 DrawDebugInfo = false;
1098 bUseDynamicModel = false;
1099 bDisableVehicleGravity = false;
1100 NNVerbose = false;
1101 bUseImpulse = false;
1102 bUseMeanAcceleration = false;
1103 bShowForces = true;
1104 bBenchMark = false;
1105 bDrawHeightMap = false;
1106 ForceMulFactor = 1.f;
1107 ParticleForceMulFactor = 1.f;
1108 FloorHeight = 0.0;
1109 bDrawLoadedTiles = false;
1110 bUseSoilType = true;
1111 EffectMultiplayer = 200.0f;
1112 MinDisplacement = -10.0f;
1113 MaxDisplacement = 10.0f;
1114 bRemoveLandscapeColliders = false;
1115#endif
1116
1117 int IntValue;
1118 if (FParse::Value(FCommandLine::Get(), TEXT("-cuda-device="), IntValue))
1119 {
1120 CUDADevice = IntValue;
1121 }
1122 if (FParse::Value(FCommandLine::Get(), TEXT("-max-particles-per-wheel="), IntValue))
1123 {
1124 MaxParticlesPerWheel = IntValue;
1125 }
1126 float Value;
1127 if (FParse::Value(FCommandLine::Get(), TEXT("-particle-size="), Value))
1128 {
1129 ParticleDiameter = MToCM*Value;
1130 }
1131 if (FParse::Value(FCommandLine::Get(), TEXT("-terrain-depth="), Value))
1132 {
1133 TerrainDepth = MToCM*Value;
1134 }
1135 if (FParse::Value(FCommandLine::Get(), TEXT("-search-radius="), Value))
1136 {
1137 SearchRadius = MToCM*Value;
1138 }
1139 if (FParse::Value(FCommandLine::Get(), TEXT("-box-search-forward="), Value))
1140 {
1141 BoxSearchForwardDistance = MToCM*Value;
1142 }
1143 if (FParse::Value(FCommandLine::Get(), TEXT("-box-search-lateral="), Value))
1144 {
1145 BoxSearchLateralDistance = MToCM*Value;
1146 }
1147 if (FParse::Value(FCommandLine::Get(), TEXT("-box-search-depth="), Value))
1148 {
1149 BoxSearchDepthDistance = MToCM*Value;
1150 }
1151 if (FParse::Value(FCommandLine::Get(), TEXT("-force-mul-factor="), Value))
1152 {
1153 ForceMulFactor = Value;
1154 }
1155 if (FParse::Value(FCommandLine::Get(), TEXT("-defor-mul="), Value))
1156 {
1157 EffectMultiplayer = Value;
1158 }
1159 if (FParse::Value(FCommandLine::Get(), TEXT("-defor-res="), Value))
1160 {
1161 ChosenRes = static_cast<EDefResolutionType>(Value);
1162 }
1163 if (FParse::Value(FCommandLine::Get(), TEXT("-min-displacement="), Value))
1164 {
1165 MinDisplacement = Value;
1166 }
1167 if (FParse::Value(FCommandLine::Get(), TEXT("-max-displacement="), Value))
1168 {
1169 MaxDisplacement = Value;
1170 }
1171 if (FParse::Value(FCommandLine::Get(), TEXT("-particle-force-mul-factor="), Value))
1172 {
1173 ParticleForceMulFactor = Value;
1174 }
1175 if (FParse::Value(FCommandLine::Get(), TEXT("-max-force="), Value))
1176 {
1177 MaxForceMagnitude = MToCM*Value;
1178 }
1179 if (FParse::Value(FCommandLine::Get(), TEXT("-floor-height="), Value))
1180 {
1181 FloorHeight = MToCM*Value;
1182 }
1183 if (FParse::Value(FCommandLine::Get(), TEXT("-tile-size="), Value))
1184 {
1185 TileSize = Value;
1186 }
1187 if (FParse::Value(FCommandLine::Get(), TEXT("-tile-radius="), Value))
1188 {
1189 TileRadius = MToCM*FVector(Value, Value, 0.f);
1190 }
1191 if (FParse::Value(FCommandLine::Get(), TEXT("-cache-radius="), Value))
1192 {
1193 CacheRadius = MToCM*FVector(Value, Value, 0.f);
1194 }
1195 if (FParse::Param(FCommandLine::Get(), TEXT("-update-particles")))
1196 {
1197 bUpdateParticles = true;
1198 }
1199 if (FParse::Param(FCommandLine::Get(), TEXT("-draw-debug-info")))
1200 {
1201 DrawDebugInfo = true;
1202 }
1203 if (FParse::Param(FCommandLine::Get(), TEXT("-use-local-frame")))
1204 {
1205 bUseLocalFrame = true;
1206 }
1207 FString Path;
1208 if (FParse::Value(FCommandLine::Get(), TEXT("-network-path="), Path))
1209 {
1210 NeuralModelFile = Path;
1211 }
1212#ifndef WITH_EDITOR
1213 // if (Path == "")
1214 // {
1215 // NeuralModelFile = FPaths::ProjectContentDir() + NeuralModelFile;
1216 // }
1217#endif
1218 if (FParse::Param(FCommandLine::Get(), TEXT("-dynamic-model")))
1219 {
1220 bUseDynamicModel = true;
1221 }
1222 if (FParse::Param(FCommandLine::Get(), TEXT("-disable-gravity")))
1223 {
1224 bDisableVehicleGravity = true;
1225 }
1226 if (FParse::Param(FCommandLine::Get(), TEXT("-disable-nn-verbose")))
1227 {
1228 NNVerbose = false;
1229 }
1230 if (FParse::Param(FCommandLine::Get(), TEXT("-use-terrain-type")))
1231 {
1232 bUseSoilType = true;
1233 }
1234 if (FParse::Param(FCommandLine::Get(), TEXT("-use-impulse")))
1235 {
1236 bUseImpulse = true;
1237 }
1238 if (FParse::Param(FCommandLine::Get(), TEXT("-use-mean-acceleration")))
1239 {
1240 bUseMeanAcceleration = true;
1241 }
1242 if (FParse::Param(FCommandLine::Get(), TEXT("-hide-debug-forces")))
1243 {
1244 bShowForces = false;
1245 }
1246 if (FParse::Param(FCommandLine::Get(), TEXT("-benchmark")))
1247 {
1248 bBenchMark = true;
1249 }
1250 if (FParse::Param(FCommandLine::Get(), TEXT("-draw-loaded-tiles")))
1251 {
1252 bDrawLoadedTiles = true;
1253 }
1254 if (FParse::Param(FCommandLine::Get(), TEXT("-remove-colliders")))
1255 {
1256 bRemoveLandscapeColliders = true;
1257 }
1258 if (FParse::Param(FCommandLine::Get(), TEXT("-disable-terramechanics")))
1259 {
1260 SetComponentTickEnabled(false);
1261 return;
1262 }
1263
1264 if(bRemoveLandscapeColliders)
1265 {
1266 FWorldDelegates::LevelAddedToWorld.AddUObject(
1267 this, &UCustomTerrainPhysicsComponent::OnLevelAddedToWorld);
1268 }
1269
1270 LargeMapManager = UCarlaStatics::GetLargeMapManager(GetWorld());
1271 if( TexturesRes.Contains(ChosenRes) ){
1272 TextureToUpdate = TexturesRes[ChosenRes];
1273 }
1274
1275 {
1276 TRACE_CPUPROFILER_EVENT_SCOPE(InitializeDenseMap);
1277 SparseMap.Clear();
1278 UE_LOG(LogCarla, Warning,
1279 TEXT("ParticleDiameter %f"), ParticleDiameter);
1280
1281 SparseMap.Init(TextureToUpdate->GetSizeX(), TextureRadius, ParticleDiameter * CMToM, TerrainDepth * CMToM, FloorHeight * CMToM );
1282 RootComponent = Cast<UPrimitiveComponent>(GetOwner()->GetRootComponent());
1283 if(LargeMapManager)
1284 {
1285 FIntVector NumTiles = LargeMapManager->GetNumTilesInXY();
1286 // WorldSize = FVector(NumTiles) * LargeMap->GetTileSize();
1287 // UE_LOG(LogCarla, Log,
1288 // TEXT("World Size %s"), *(WorldSize.ToString()));
1289 }
1290 // SparseMap.InitializeMap(HeightMap, UEFrameToSI(Tile0Origin), UEFrameToSI(WorldSize),
1291 // 1.f, MinHeight, MaxHeight, HeightMapScaleFactor.Z);
1292 if (DataAsset)
1293 {
1294 SparseMap.InitializeMap(DataAsset, UEFrameToSI(Tile0Origin), UEFrameToSI(WorldSize),
1295 TileSize, HeightMapScaleFactor.Z);
1296 }
1297 }
1298#ifdef WITH_PYTORCH
1299 {
1300 TRACE_CPUPROFILER_EVENT_SCOPE(LoadNNModel);
1302 TerramechanicsModel.LoadModel(TCHAR_TO_ANSI(*NeuralModelFile), CUDADevice);
1303 }
1304#endif
1305
1306 FString LevelName = GetWorld()->GetMapName();
1307 LevelName.RemoveFromStart(GetWorld()->StreamingLevelsPrefix);
1308
1309 SavePath = FString(_filesBaseFolder.c_str()) + LevelName + "_Terrain/";
1310 SparseMap.SavePath = SavePath;
1311 // Creating the FileManager
1312 IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
1313 /*if( FileManager.CreateDirectory(*SavePath)){
1314 UE_LOG(LogCarla, Warning,
1315 TEXT("Folder was created at %s"), *SavePath);
1316 }else{
1317 UE_LOG(LogCarla, Error,
1318 TEXT("Folder was not created at %s"), *SavePath);
1319 }*/
1320
1321 if(bUseDeformationPlane){
1322 DeformationPlaneActor = GetWorld()->SpawnActor<AStaticMeshActor>();
1323
1324 if( DeformationPlaneActor )
1325 {
1326 DeformationPlaneActor->GetStaticMeshComponent()->SetStaticMesh( DeformationPlaneMesh );
1327 DeformationPlaneActor->GetStaticMeshComponent()->SetMaterial( 0, DeformationPlaneMaterial );
1328 DeformationPlaneActor->GetRootComponent()->SetMobility(EComponentMobility::Movable);
1329 }
1330 }
1331
1332 InitTexture();
1333
1334 UE_LOG(LogCarla, Log, TEXT("MainThread Data ArraySize %d "), Data.Num());
1335 UE_LOG(LogCarla, Log, TEXT("Map Size %d "), SparseMap.Map.size() );
1336
1337 if (TilesWorker == nullptr)
1338 {
1339 TilesWorker = new FTilesWorker(this, GetOwner()->GetActorLocation(), TileRadius.X, TileRadius.Y);
1340 Thread = FRunnableThread::Create(TilesWorker, TEXT("TilesWorker"));
1341 }
1342
1343}
1344
1345void UCustomTerrainPhysicsComponent::BuildLandscapeHeightMapDataAasset(ALandscapeProxy* Landscape,
1346 int Resolution, FVector MapSize, FString AssetPath, FString AssetName)
1347{
1348 TRACE_CPUPROFILER_EVENT_SCOPE(UCustomTerrainPhysicsComponent::BuildLandscapeHeightMapTexture);
1349 TArray<float> HeightMap;
1350 HeightMap.Reserve(Resolution*Resolution);
1351 FVector Origin = Landscape->GetActorLocation();
1352 float DeltaX = MapSize.X / Resolution;
1353 float DeltaY = MapSize.Y / Resolution;
1354 for (size_t i = 0; i < Resolution; ++i)
1355 {
1356 float PosX = Origin.X + i*DeltaX;
1357 for (size_t j = 0; j < Resolution; ++j)
1358 {
1359 float PosY = Origin.Y + j*DeltaY;
1360 FVector Location = FVector(PosX, PosY, 0);
1361 float Height = Landscape->GetHeightAtLocation(Location).Get(-1);
1362 HeightMap.Emplace(Height);
1363 }
1364 }
1365 int TextureWidth = Resolution;
1366 int TextureHeight = Resolution;
1367 FString PackageName = AssetPath;
1368 PackageName += AssetName;
1369 UPackage* Package = CreatePackage(NULL, *PackageName);
1370 Package->FullyLoad();
1371
1372 UHeightMapDataAsset* HeightMapAsset = NewObject<UHeightMapDataAsset>(Package, *AssetName, RF_Public | RF_Standalone | RF_MarkAsRootSet);
1373 HeightMapAsset->AddToRoot();
1374 HeightMapAsset->SizeX = TextureWidth;
1375 HeightMapAsset->SizeY = TextureHeight;
1376 HeightMapAsset->HeightValues = HeightMap;
1377
1378 Package->MarkPackageDirty();
1379 // FAssetRegistryModule::AssetCreated(NewTexture);
1380
1381 FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
1382 bool bSaved = UPackage::SavePackage(Package, HeightMapAsset, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);
1383}
1384
1385
1386float UCustomTerrainPhysicsComponent::GetHeightAtLocation(ALandscapeProxy * Landscape, FVector Location)
1387{
1388 TOptional<float> OptionalHeight = Landscape->GetHeightAtLocation(Location);
1389 if(OptionalHeight.IsSet())
1390 return OptionalHeight.GetValue();
1391 return -1;
1392}
1393
1394void UCustomTerrainPhysicsComponent::EndPlay(const EEndPlayReason::Type EndPlayReason){
1395 Super::EndPlay(EndPlayReason);
1396 if( Thread && TilesWorker){
1397 TilesWorker->bShouldContinue = false;
1398 Thread->WaitForCompletion();
1399 Thread->Kill(false);
1400 delete TilesWorker;
1401 TilesWorker = nullptr;
1402 }
1403
1404 TRACE_CPUPROFILER_EVENT_SCOPE(FSparseHighDetailMap::SaveMap);
1405 SparseMap.SaveMap();
1406}
1407
1408void UCustomTerrainPhysicsComponent::TickComponent(float DeltaTime,
1409 ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
1410{
1411 TRACE_CPUPROFILER_EVENT_SCOPE(UCustomTerrainPhysicsComponent::TickComponent);
1412 Super::TickComponent(DeltaTime,TickType,ThisTickFunction);
1413
1414 TArray<AActor*> VehiclesActors;
1415 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACarlaWheeledVehicle::StaticClass(), VehiclesActors);
1416 UCarlaEpisode* Episode = UCarlaStatics::GetCurrentEpisode(GetWorld());
1417 for (AActor* VehicleActor : VehiclesActors)
1418 {
1419
1420 ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle> (VehicleActor);
1421 FCarlaActor* CarlaActor = Episode->FindCarlaActor(Vehicle);
1422 if (!CarlaActor)
1423 {
1424 continue;
1425 }
1426 const FActorInfo* ActorInfo = CarlaActor->GetActorInfo();
1427 const FActorDescription& Description = ActorInfo->Description;
1428 const FActorAttribute* Attribute = Description.Variations.Find("terramechanics");
1429 // If the vehicle has terramechanics enabled
1430 if(!Attribute || !UActorBlueprintFunctionLibrary::ActorAttributeToBool(*Attribute, false))
1431 {
1432 continue;
1433 }
1434
1435 FVector GlobalLocation = Vehicle->GetActorLocation();
1436 if(LargeMapManager)
1437 {
1438 GlobalLocation = LargeMapManager->LocalToGlobalLocation(Vehicle->GetActorLocation());
1439
1440 uint64_t TileId = LargeMapManager->GetTileID(GlobalLocation);
1441 FIntVector CurrentTileId =
1442 LargeMapManager->GetTileVectorID(GlobalLocation);
1443 if(CurrentLargeMapTileId != CurrentTileId)
1444 {
1445 //load new height map
1446 FCarlaMapTile* LargeMapTile = LargeMapManager->GetCarlaMapTile(TileId);
1447 if(LargeMapTile)
1448 {
1449 CurrentLargeMapTileId = CurrentTileId;
1450 FString FullTileNamePath = LargeMapTile->Name;
1451 FString TileDirectory;
1452 FString TileName;
1453 FString Extension;
1454 FPaths::Split(FullTileNamePath, TileDirectory, TileName, Extension);
1455 FString AssetPath = TileDirectory + "/HeightMaps/" + TileName + "." + TileName;
1456 UE_LOG(LogCarla, Log, TEXT("Enter tile %s, %s \n %s \n %s \n %s"), *CurrentTileId.ToString(),
1457 *FullTileNamePath, *TileDirectory, *TileName, *Extension);
1458
1459 UObject* DataAssetObject = StaticLoadObject(UHeightMapDataAsset::StaticClass(), nullptr, *(AssetPath));
1460 if(DataAssetObject)
1461 {
1462 UHeightMapDataAsset* HeightMapDataAsset = Cast<UHeightMapDataAsset>(DataAssetObject);
1463 if (HeightMapDataAsset != nullptr)
1464 {
1465 FVector TilePosition = HeightMapOffset + LargeMapManager->GetTileLocation(CurrentLargeMapTileId) - 0.5f*FVector(LargeMapManager->GetTileSize(), -LargeMapManager->GetTileSize(), 0);
1466 UE_LOG(LogCarla, Log, TEXT("Updating height map to location %s in tile location %s"),
1467 *TilePosition.ToString(), *LargeMapManager->GetTileLocation(CurrentLargeMapTileId).ToString());
1468 TilePosition.Z += UEFrameToSI(FloorHeight) ;
1469 SparseMap.UpdateHeightMap(
1470 HeightMapDataAsset, UEFrameToSI(TilePosition), UEFrameToSI(FVector(
1471 LargeMapManager->GetTileSize(),-LargeMapManager->GetTileSize(), 0)),
1472 1.f, HeightMapScaleFactor.Z);
1473 }
1474 }
1475 }
1476 else
1477 {/*
1478 UE_LOG(LogCarla, Log, TEXT("Tile not found %s %s"),
1479 *GlobalLocation.ToString(), *CurrentTileId.ToString());
1480 */
1481 }
1482 }
1483 }
1484
1485 SparseMap.LockMutex();
1486 RunNNPhysicsSimulation(Vehicle, DeltaTime);
1487 LastUpdatedPosition = GlobalLocation;
1488 SparseMap.UnLockMutex();
1489
1490 if (bDrawLoadedTiles)
1491 {
1492 DrawTiles(GetWorld(), SparseMap.GetTileIdInMap(), GlobalLocation.Z + 300, FLinearColor(0.0,0.0,1.0,0.0));
1493 DrawTiles(GetWorld(), SparseMap.GetTileIdInCache(), GlobalLocation.Z + 300, FLinearColor(1.0,0.0,0.0,0.0));
1494 }
1495
1496 if( MPCInstance == nullptr )
1497 {
1498 if(MPC){
1499 MPCInstance = GetWorld()->GetParameterCollectionInstance( MPC );
1500 }
1501 }
1502
1503 if( MPCInstance ){
1504 MPCInstance->SetVectorParameterValue("PositionToUpdate", GetTileCenter(LastUpdatedPosition));
1505 // We set texture radius in cm as is UE4 default measure unit
1506 MPCInstance->SetScalarParameterValue("TextureRadius", TextureRadius * 100);
1507 MPCInstance->SetScalarParameterValue("LargeTextureRadius", TextureRadius * 100);
1508 MPCInstance->SetScalarParameterValue("EffectMultiplayer", EffectMultiplayer);
1509 MPCInstance->SetScalarParameterValue("MinDisplacement", MinDisplacement);
1510 MPCInstance->SetScalarParameterValue("MaxDisplacement", MinDisplacement);
1511 if(TextureToUpdate){
1512 MPCInstance->SetScalarParameterValue("TexSizeX", TextureToUpdate->GetSizeX());
1513 }
1514 }
1515
1516 if(bUseDeformationPlane){
1517 if( DeformationPlaneActor ){
1518 DeformationPlaneActor->SetActorLocation(LastUpdatedPosition, false, nullptr);
1519 }else{
1520 DeformationPlaneActor = GetWorld()->SpawnActor<AStaticMeshActor>();
1521
1522 if( DeformationPlaneActor )
1523 {
1524 DeformationPlaneActor->GetStaticMeshComponent()->SetStaticMesh( DeformationPlaneMesh );
1525 DeformationPlaneActor->GetStaticMeshComponent()->SetMaterial( 0, DeformationPlaneMaterial );
1526 DeformationPlaneActor->GetRootComponent()->SetMobility(EComponentMobility::Movable);
1527 }
1528 }
1529 }
1530 }
1531
1532 if (bDrawHeightMap)
1533 {
1534 TRACE_CPUPROFILER_EVENT_SCOPE(DrawHeightMap);
1535 float LifeTime = 0.3f;
1536 bool bPersistentLines = false;
1537 bool bDepthIsForeground = (0 == SDPG_Foreground);
1538 UWorld* World = GetWorld();
1539 ULineBatchComponent* LineBatcher =
1540 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
1541 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
1542 if (!LineBatcher)
1543 {
1544 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
1545 }
1546
1547 float DrawPos_X = DrawStart.X;
1548 float DrawPos_Y = DrawStart.Y;
1549 for (DrawPos_X = DrawStart.X; DrawPos_X < DrawEnd.X; DrawPos_X += DrawInterval.X)
1550 {
1551 for (DrawPos_Y = DrawStart.Y; DrawPos_Y < DrawEnd.Y; DrawPos_Y += DrawInterval.Y)
1552 {
1553 float Height = SparseMap.GetHeight(UEFrameToSI(FVector(DrawPos_X, DrawPos_Y, 0)));
1554 FVector Point = FVector(DrawPos_X, DrawPos_Y, SIToUEFrame(Height));
1555 if(LargeMapManager)
1556 {
1557 Point = LargeMapManager->GlobalToLocalLocation(Point);
1558 }
1559 LineBatcher->DrawPoint(Point,
1560 FLinearColor(1.f, 0.f, 0.f), 10.0, 0, LifeTime);
1561
1562 }
1563 }
1564 }
1565}
1566
1567void UCustomTerrainPhysicsComponent::DrawParticles(UWorld* World, std::vector<FParticle*>& Particles,
1568 FLinearColor Color)
1569{
1570 float LifeTime = 0.3f;
1571 bool bPersistentLines = false;
1572 bool bDepthIsForeground = (0 == SDPG_Foreground);
1573 ULineBatchComponent* LineBatcher =
1574 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
1575 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
1576 if (!LineBatcher)
1577 {
1578 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
1579 }
1580 for(FParticle* Particle : Particles)
1581 {
1582 // DrawDebugPoint(World, MToCM*Particle->Position.ToFVector(),
1583 // 1.0, FColor(255,0,0), false, 0.3, 0);
1584 FVector Point = SIToUEFrame(Particle->Position.ToFVector());
1585 if(LargeMapManager)
1586 {
1587 Point = LargeMapManager->GlobalToLocalLocation(Point);
1588 }
1589 LineBatcher->DrawPoint(Point,
1590 Color, 1.0, 0, LifeTime);
1591 }
1592}
1593
1594void UCustomTerrainPhysicsComponent::DrawParticlesArray(UWorld* World, TArray<float>& ParticlesArray,
1595 FLinearColor Color)
1596{
1597 float LifeTime = 0.3f;
1598 bool bPersistentLines = false;
1599 bool bDepthIsForeground = (0 == SDPG_Foreground);
1600 ULineBatchComponent* LineBatcher =
1601 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
1602 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
1603 if (!LineBatcher)
1604 {
1605 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
1606 }
1607 for(int i = 0; i < ParticlesArray.Num(); i+=3)
1608 {
1609 FVector Position = FVector(ParticlesArray[i+0], ParticlesArray[i+1], ParticlesArray[i+2]);
1610 // DrawDebugPoint(World, MToCM*Particle->Position.ToFVector(),
1611 // 1.0, FColor(255,0,0), false, 0.3, 0);
1612 FVector Point = SIToUEFrame(Position);
1613 LineBatcher->DrawPoint(Point,
1614 Color, 1.0, 0, LifeTime);
1615 }
1616}
1617
1618void UCustomTerrainPhysicsComponent::DrawOrientedBox(UWorld* World, const TArray<FOrientedBox>& Boxes)
1619{
1620 float LifeTime = 0.3f;
1621 bool bPersistentLines = false;
1622 bool bDepthIsForeground = (0 == SDPG_Foreground);
1623 float Thickness = 2.0f;
1624 ULineBatchComponent* LineBatcher =
1625 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
1626 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
1627 if (!LineBatcher)
1628 {
1629 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
1630 }
1631 for (const FOrientedBox& OBox : Boxes)
1632 {
1633 TArray<FVector> Vertices;
1634 Vertices.SetNum(8);
1635 OBox.CalcVertices(&Vertices[0]);
1636 if(LargeMapManager)
1637 {
1638 for(FVector& Point : Vertices)
1639 {
1640 Point = LargeMapManager->GlobalToLocalLocation(Point);
1641 }
1642 }
1643 LineBatcher->DrawLines({
1644 FBatchedLine(Vertices[0], Vertices[1],
1645 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1646 FBatchedLine(Vertices[0], Vertices[2],
1647 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1648 FBatchedLine(Vertices[2], Vertices[3],
1649 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1650 FBatchedLine(Vertices[3], Vertices[1],
1651 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1652
1653 FBatchedLine(Vertices[4], Vertices[5],
1654 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1655 FBatchedLine(Vertices[4], Vertices[6],
1656 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1657 FBatchedLine(Vertices[6], Vertices[7],
1658 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1659 FBatchedLine(Vertices[7], Vertices[5],
1660 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1661
1662 FBatchedLine(Vertices[0], Vertices[4],
1663 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1664 FBatchedLine(Vertices[1], Vertices[5],
1665 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1666 FBatchedLine(Vertices[2], Vertices[6],
1667 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0),
1668 FBatchedLine(Vertices[3], Vertices[7],
1669 FLinearColor(0.0,0.0,1.0), LifeTime, Thickness, 0)});
1670 }
1671}
1672
1673void UCustomTerrainPhysicsComponent::DrawTiles(UWorld* World, const std::vector<uint64_t>& TilesIds,float Height,
1674 FLinearColor Color)
1675{
1676 float LifeTime = 0.3f;
1677 bool bPersistentLines = false;
1678 bool bDepthIsForeground = (0 == SDPG_Foreground);
1679 float Thickness = 2.0f;
1680 ULineBatchComponent* LineBatcher =
1681 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
1682 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
1683 if (!LineBatcher)
1684 {
1685 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
1686 }
1687 // UE_LOG(LogCarla, Log, TEXT("Drawing %d Tiles"), TilesIds.size());
1688 for (const uint64_t& TileId : TilesIds)
1689 {
1690 FVector TileCenter = SparseMap.GetTilePosition(TileId).ToFVector();
1691 FVector V1 = SIToUEFrame(TileCenter);
1692 FVector V2 = SIToUEFrame(TileCenter + FVector(SparseMap.GetTileSize(),0,0));
1693 FVector V3 = SIToUEFrame(TileCenter + FVector(0,SparseMap.GetTileSize(),0));
1694 FVector V4 = SIToUEFrame(TileCenter + FVector(SparseMap.GetTileSize(),SparseMap.GetTileSize(),0));
1695 if(LargeMapManager)
1696 {
1697 V1 = LargeMapManager->GlobalToLocalLocation(V1);
1698 V2 = LargeMapManager->GlobalToLocalLocation(V2);
1699 V3 = LargeMapManager->GlobalToLocalLocation(V3);
1700 V4 = LargeMapManager->GlobalToLocalLocation(V4);
1701 }
1702 V1.Z = Height;
1703 V2.Z = Height;
1704 V3.Z = Height;
1705 V4.Z = Height;
1706 LineBatcher->DrawLines({
1707 FBatchedLine(V1, V2,
1708 Color, LifeTime, Thickness, 0),
1709 FBatchedLine(V2, V4,
1710 Color, LifeTime, Thickness, 0),
1711 FBatchedLine(V1, V3,
1712 Color, LifeTime, Thickness, 0),
1713 FBatchedLine(V3, V4,
1714 Color, LifeTime, Thickness, 0)});
1715 // UE_LOG(LogCarla, Log, TEXT("Drawing Tile %ld with verts %s, %s, %s, %s"),
1716 // TileId, *V1.ToString(), *V2.ToString(), *V3.ToString(), *V4.ToString());
1717 }
1718}
1719
1720void UCustomTerrainPhysicsComponent::LimitParticlesPerWheel(std::vector<FParticle*> &Particles)
1721{
1722 TRACE_CPUPROFILER_EVENT_SCOPE(LimitParticlesPerWheel);
1723 if (Particles.size() < MaxParticlesPerWheel)
1724 {
1725 return;
1726 }
1727 std::sort(Particles.begin(), Particles.end(), [&](FParticle* P1, FParticle* P2) -> bool
1728 {
1729 return P1->Position.Z > P2->Position.Z;
1730 });
1731 Particles.resize(MaxParticlesPerWheel);
1732}
1733
1734void UCustomTerrainPhysicsComponent::GenerateBenchmarkParticles(std::vector<FParticle>& BenchParticles,
1735 std::vector<FParticle*> &ParticlesWheel0, std::vector<FParticle*> &ParticlesWheel1,
1736 std::vector<FParticle*> &ParticlesWheel2, std::vector<FParticle*> &ParticlesWheel3,
1737 FOrientedBox &BboxWheel0, FOrientedBox &BboxWheel1,
1738 FOrientedBox &BboxWheel2, FOrientedBox &BboxWheel3)
1739{
1740 TRACE_CPUPROFILER_EVENT_SCOPE(GenerateBenchmarkParticles);
1741 BenchParticles.reserve(100000);
1742 auto GenerateBoxParticles = [&](FOrientedBox &BboxWheel, std::vector<FParticle*> &ParticlesWheel)
1743 {
1744 ParticlesWheel.clear();
1745 FVector TileOrigin = FVector(0,0,0);
1746 FVector BoxSize = FVector(2*BboxWheel.ExtentX, 2*BboxWheel.ExtentY, BboxWheel.ExtentZ);
1747 uint32_t NumParticles_X = BoxSize.X / ParticleDiameter;
1748 uint32_t NumParticles_Y = BoxSize.Y / ParticleDiameter;
1749 uint32_t NumParticles_Z = BoxSize.Z / ParticleDiameter;
1750 UE_LOG(LogCarla, Log, TEXT("Generating (%d,%d,%d) particles"),
1751 NumParticles_X,NumParticles_Y,NumParticles_Z);
1752 for(uint32_t i = 0; i < NumParticles_X; i++)
1753 {
1754 float XPos = i*ParticleDiameter;
1755 for(uint32_t j = 0; j < NumParticles_Y; j++)
1756 {
1757 float YPos = j*ParticleDiameter;
1758 for(uint32_t k = 0; k < NumParticles_Z; k++)
1759 {
1760 float ZPos = k*ParticleDiameter;
1761 FVector ParticlePosition = TileOrigin + FVector(XPos, YPos, ZPos);
1762 ParticlePosition = (ParticlePosition.X - BboxWheel.ExtentX) * BboxWheel0.AxisX +
1763 (ParticlePosition.Y - BboxWheel.ExtentY) * BboxWheel0.AxisY +
1764 (ParticlePosition.Z - BboxWheel.ExtentZ) * BboxWheel0.AxisZ + BboxWheel.Center;
1765 ParticlePosition = UEFrameToSI(ParticlePosition);
1766 BenchParticles.emplace_back(FParticle{ParticlePosition, FVector(0), ParticleDiameter/2.f});
1767 ParticlesWheel.emplace_back(&BenchParticles.back());
1768 }
1769 }
1770 }
1771 };
1772 GenerateBoxParticles(BboxWheel0, ParticlesWheel0);
1773 GenerateBoxParticles(BboxWheel1, ParticlesWheel1);
1774 GenerateBoxParticles(BboxWheel2, ParticlesWheel2);
1775 GenerateBoxParticles(BboxWheel3, ParticlesWheel3);
1776
1777 UE_LOG(LogCarla, Log, TEXT("Generated %d particles"), BenchParticles.size());
1778}
1779
1780void UCustomTerrainPhysicsComponent::RunNNPhysicsSimulation(
1781 ACarlaWheeledVehicle *Vehicle, float DeltaTime)
1782{
1783 TRACE_CPUPROFILER_EVENT_SCOPE(RunNNPhysicsSimulation);
1784 #ifdef WITH_PYTORCH
1785 FTransform VehicleTransform = Vehicle->GetTransform();
1786 FTransform WheelTransform0 = VehicleTransform;
1787 FTransform WheelTransform1 = VehicleTransform;
1788 FTransform WheelTransform2 = VehicleTransform;
1789 FTransform WheelTransform3 = VehicleTransform;
1790 FVector WheelPosition0 = VehicleTransform.TransformPosition(FVector(140, -70, 40));
1791 FVector WheelPosition1 = VehicleTransform.TransformPosition(FVector(140, 70, 40));
1792 FVector WheelPosition2 = VehicleTransform.TransformPosition(FVector(-140, -70, 40));
1793 FVector WheelPosition3 = VehicleTransform.TransformPosition(FVector(-140, 70, 40));
1794 WheelTransform0.SetLocation(WheelPosition0);
1795 WheelTransform1.SetLocation(WheelPosition1);
1796 WheelTransform2.SetLocation(WheelPosition2);
1797 WheelTransform3.SetLocation(WheelPosition3);
1798 if(LargeMapManager)
1799 {
1800 WheelPosition0 = LargeMapManager->LocalToGlobalLocation(WheelPosition0);
1801 WheelPosition1 = LargeMapManager->LocalToGlobalLocation(WheelPosition1);
1802 WheelPosition2 = LargeMapManager->LocalToGlobalLocation(WheelPosition2);
1803 WheelPosition3 = LargeMapManager->LocalToGlobalLocation(WheelPosition3);
1804 }
1805 FOrientedBox BboxWheel0;
1806 BboxWheel0.AxisX = VehicleTransform.GetUnitAxis(EAxis::X);
1807 BboxWheel0.AxisY = VehicleTransform.GetUnitAxis(EAxis::Y);
1808 BboxWheel0.AxisZ = VehicleTransform.GetUnitAxis(EAxis::Z);
1809 BboxWheel0.Center = WheelPosition0 + FVector(0,0,-TireRadius);
1810 BboxWheel0.ExtentX = BoxSearchForwardDistance;
1811 BboxWheel0.ExtentY = BoxSearchLateralDistance;
1812 BboxWheel0.ExtentZ = BoxSearchDepthDistance;
1813 FOrientedBox BboxWheel1 = BboxWheel0;
1814 BboxWheel1.Center = WheelPosition1 + FVector(0,0,-TireRadius);
1815 FOrientedBox BboxWheel2 = BboxWheel0;
1816 BboxWheel2.Center = WheelPosition2 + FVector(0,0,-TireRadius);
1817 FOrientedBox BboxWheel3 = BboxWheel0;
1818 BboxWheel3.Center = WheelPosition3 + FVector(0,0,-TireRadius);
1819 if (DrawDebugInfo)
1820 {
1821 DrawOrientedBox(GetWorld(), {BboxWheel0, BboxWheel1, BboxWheel2, BboxWheel3});
1822 }
1823
1824 std::vector<FParticle*> ParticlesWheel0, ParticlesWheel1, ParticlesWheel2, ParticlesWheel3;
1825 {
1826 TRACE_CPUPROFILER_EVENT_SCOPE(ParticleSearch);
1827 auto GetAndFilterParticlesInBox =
1828 [&] (FOrientedBox& OBox) -> std::vector<FParticle*>
1829 {
1830 std::vector<FParticle*> Particles;
1831 Particles = SparseMap.GetParticlesInBox(OBox);
1832 LimitParticlesPerWheel(Particles);
1833 return Particles;
1834 };
1835 auto FutureParticles0 = Async(EAsyncExecution::ThreadPool,
1836 [&]() {return GetAndFilterParticlesInBox(BboxWheel0);});
1837 auto FutureParticles2 = Async(EAsyncExecution::ThreadPool,
1838 [&]() {return GetAndFilterParticlesInBox(BboxWheel2);});
1839 auto FutureParticles1 = Async(EAsyncExecution::ThreadPool,
1840 [&]() {return GetAndFilterParticlesInBox(BboxWheel1);});
1841 auto FutureParticles3 = Async(EAsyncExecution::ThreadPool,
1842 [&]() {return GetAndFilterParticlesInBox(BboxWheel3);});
1843 ParticlesWheel0 = FutureParticles0.Get();
1844 ParticlesWheel2 = FutureParticles2.Get();
1845 ParticlesWheel1 = FutureParticles1.Get();
1846 ParticlesWheel3 = FutureParticles3.Get();
1847 }
1848
1849 std::vector<FParticle> BenchParticles;
1850 if(bBenchMark)
1851 {
1852 GenerateBenchmarkParticles(BenchParticles,
1853 ParticlesWheel0, ParticlesWheel1, ParticlesWheel2, ParticlesWheel3,
1854 BboxWheel0, BboxWheel1, BboxWheel2, BboxWheel3);
1855 UE_LOG(LogCarla, Log, TEXT("Generated %d particles"), BenchParticles.size());
1856 }
1857
1858 if(DrawDebugInfo)
1859 {
1860 DrawParticles(GetWorld(), ParticlesWheel0);
1861 DrawParticles(GetWorld(), ParticlesWheel1);
1862 DrawParticles(GetWorld(), ParticlesWheel2);
1863 DrawParticles(GetWorld(), ParticlesWheel3);
1864 DrawTiles(GetWorld(), SparseMap.GetIntersectingTiles(BboxWheel0), BboxWheel0.Center.Z);
1865 DrawTiles(GetWorld(), SparseMap.GetIntersectingTiles(BboxWheel1), BboxWheel1.Center.Z);
1866 DrawTiles(GetWorld(), SparseMap.GetIntersectingTiles(BboxWheel2), BboxWheel2.Center.Z);
1867 DrawTiles(GetWorld(), SparseMap.GetIntersectingTiles(BboxWheel3), BboxWheel3.Center.Z);
1868 }
1869
1870 TArray<float> ParticlePos0, ParticleVel0, ParticlePos1, ParticleVel1,
1871 ParticlePos2, ParticleVel2, ParticlePos3, ParticleVel3;
1872 TArray<float> WheelPos0, WheelOrient0, WheelLinVel0, WheelAngVel0;
1873 TArray<float> WheelPos1, WheelOrient1, WheelLinVel1, WheelAngVel1;
1874 TArray<float> WheelPos2, WheelOrient2, WheelLinVel2, WheelAngVel2;
1875 TArray<float> WheelPos3, WheelOrient3, WheelLinVel3, WheelAngVel3;
1876 {
1877 TRACE_CPUPROFILER_EVENT_SCOPE(SetUpArrays);
1878 SetUpParticleArrays(ParticlesWheel0, ParticlePos0, ParticleVel0, WheelTransform0);
1879 SetUpParticleArrays(ParticlesWheel1, ParticlePos1, ParticleVel1, WheelTransform1);
1880 SetUpParticleArrays(ParticlesWheel2, ParticlePos2, ParticleVel2, WheelTransform2);
1881 SetUpParticleArrays(ParticlesWheel3, ParticlePos3, ParticleVel3, WheelTransform3);
1882
1883 SetUpWheelArrays(Vehicle, 0, WheelPos0, WheelOrient0, WheelLinVel0, WheelAngVel0);
1884 SetUpWheelArrays(Vehicle, 1, WheelPos1, WheelOrient1, WheelLinVel1, WheelAngVel1);
1885 SetUpWheelArrays(Vehicle, 2, WheelPos2, WheelOrient2, WheelLinVel2, WheelAngVel2);
1886 SetUpWheelArrays(Vehicle, 3, WheelPos3, WheelOrient3, WheelLinVel3, WheelAngVel3);
1887 }
1888
1890 static_cast<int>(ParticlesWheel0.size()),
1891 ParticlePos0.GetData(), ParticleVel0.GetData(),
1892 WheelPos0.GetData(), WheelOrient0.GetData(),
1893 WheelLinVel0.GetData(), WheelAngVel0.GetData()};
1895 static_cast<int>(ParticlesWheel1.size()),
1896 ParticlePos1.GetData(), ParticleVel1.GetData(),
1897 WheelPos1.GetData(), WheelOrient1.GetData(),
1898 WheelLinVel1.GetData(), WheelAngVel1.GetData()};
1900 static_cast<int>(ParticlesWheel2.size()),
1901 ParticlePos2.GetData(), ParticleVel2.GetData(),
1902 WheelPos2.GetData(), WheelOrient2.GetData(),
1903 WheelLinVel2.GetData(), WheelAngVel2.GetData()};
1905 static_cast<int>(ParticlesWheel3.size()),
1906 ParticlePos3.GetData(), ParticleVel3.GetData(),
1907 WheelPos3.GetData(), WheelOrient3.GetData(),
1908 WheelLinVel3.GetData(), WheelAngVel3.GetData()};
1909
1910 const FVehicleControl& VehicleControl = Vehicle->GetVehicleControl();
1911 ASoilTypeManager* SoilTypeManagerActor = Cast<ASoilTypeManager>(UGameplayStatics::GetActorOfClass(GetWorld(), ASoilTypeManager::StaticClass()));
1912 if(SoilTypeManagerActor)
1913 {
1914 FSoilTerramechanicsProperties TerramechanicsProperties =
1915 SoilTypeManagerActor->GetTerrainPropertiesAtGlobalLocation(WheelPosition0);
1916
1917 switch(TerramechanicsProperties.TerrainType){
1919 SoilType = 0;
1920 break;
1922 SoilType = 1;
1923 break;
1924 default:
1925 SoilType = 0;
1926 }
1927
1928 }
1929 carla::learning::Inputs NNInput {Wheel0,Wheel1,Wheel2,Wheel3,
1930 VehicleControl.Steer, VehicleControl.Throttle, VehicleControl.Brake,
1931 SoilType, NNVerbose};
1932 if (!bUseSoilType)
1933 {
1934 NNInput.terrain_type = -1;
1935 }
1936 if (VehicleControl.bReverse)
1937 {
1938 NNInput.throttle *= -1;
1939 }
1940 TerramechanicsModel.SetInputs(NNInput);
1941 {
1942 TRACE_CPUPROFILER_EVENT_SCOPE(RunModel);
1943 if(bUseCUDAModel)
1944 {
1945 TerramechanicsModel.ForwardCUDATensors();
1946 }
1947 else if(bUseDynamicModel)
1948 {
1949 TerramechanicsModel.ForwardDynamic();
1950 }
1951 else
1952 {
1953 TerramechanicsModel.Forward();
1954 }
1955 }
1956 carla::learning::Outputs& Output = TerramechanicsModel.GetOutputs();
1957
1958 if(bUpdateParticles)
1959 {
1960 {
1961 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateParticles);
1962 FScopeLock ScopeLock(&SparseMap.Lock_Particles);
1963 auto UpdateFutureParticles =
1964 [&] (std::vector<FParticle*>& Particles, std::vector<float>& Forces, float DeltaTime,
1965 const FTransform& WheelTransform)
1966 {
1967 UpdateParticles( Particles, Forces, DeltaTime, WheelTransform );
1968 };
1969 UpdateFutureParticles(
1970 ParticlesWheel0, Output.wheel0._particle_forces, DeltaTime, WheelTransform0);
1971 UpdateFutureParticles(
1972 ParticlesWheel1, Output.wheel1._particle_forces, DeltaTime, WheelTransform1);
1973 UpdateFutureParticles(
1974 ParticlesWheel2, Output.wheel2._particle_forces, DeltaTime, WheelTransform2);
1975 UpdateFutureParticles(
1976 ParticlesWheel3, Output.wheel3._particle_forces, DeltaTime, WheelTransform3);
1977 }
1978 if (DrawDebugInfo)
1979 {
1980 FLinearColor Color(1.0,0.0,1.0,1.0);
1981 DrawParticles(GetWorld(), ParticlesWheel0, Color);
1982 DrawParticles(GetWorld(), ParticlesWheel1, Color);
1983 DrawParticles(GetWorld(), ParticlesWheel2, Color);
1984 DrawParticles(GetWorld(), ParticlesWheel3, Color);
1985 }
1986 }
1987
1988 if(bUseMeanAcceleration)
1989 {
1990 ApplyMeanAccelerationToVehicle(Vehicle,
1991 ForceMulFactor*SIToUEFrame(FVector(
1992 Output.wheel0.wheel_forces_x,
1993 Output.wheel0.wheel_forces_y,
1994 Output.wheel0.wheel_forces_z)),
1995 ForceMulFactor*SIToUEFrame(FVector(
1996 Output.wheel1.wheel_forces_x,
1997 Output.wheel1.wheel_forces_y,
1998 Output.wheel1.wheel_forces_z)),
1999 ForceMulFactor*SIToUEFrame(FVector(
2000 Output.wheel2.wheel_forces_x,
2001 Output.wheel2.wheel_forces_y,
2002 Output.wheel2.wheel_forces_z)),
2003 ForceMulFactor*SIToUEFrame(FVector(
2004 Output.wheel3.wheel_forces_x,
2005 Output.wheel3.wheel_forces_y,
2006 Output.wheel3.wheel_forces_z)));
2007 }
2008 else
2009 {
2010 ApplyForcesToVehicle(Vehicle,
2011 ForceMulFactor*SIToUEFrame(FVector(
2012 Output.wheel0.wheel_forces_x,
2013 Output.wheel0.wheel_forces_y,
2014 Output.wheel0.wheel_forces_z)),
2015 ForceMulFactor*SIToUEFrame(FVector(
2016 Output.wheel1.wheel_forces_x,
2017 Output.wheel1.wheel_forces_y,
2018 Output.wheel1.wheel_forces_z)),
2019 ForceMulFactor*SIToUEFrame(FVector(
2020 Output.wheel2.wheel_forces_x,
2021 Output.wheel2.wheel_forces_y,
2022 Output.wheel2.wheel_forces_z)),
2023 ForceMulFactor*SIToUEFrame(FVector(
2024 Output.wheel3.wheel_forces_x,
2025 Output.wheel3.wheel_forces_y,
2026 Output.wheel3.wheel_forces_z)),
2027 ForceMulFactor*MToCM*SIToUEFrame(FVector(
2028 Output.wheel0.wheel_torque_x,
2029 Output.wheel0.wheel_torque_y,
2030 Output.wheel0.wheel_torque_z)),
2031 ForceMulFactor*MToCM*SIToUEFrame(FVector(
2032 Output.wheel1.wheel_torque_x,
2033 Output.wheel1.wheel_torque_y,
2034 Output.wheel1.wheel_torque_z)),
2035 ForceMulFactor*MToCM*SIToUEFrame(FVector(
2036 Output.wheel2.wheel_torque_x,
2037 Output.wheel2.wheel_torque_y,
2038 Output.wheel2.wheel_torque_z)),
2039 ForceMulFactor*MToCM*SIToUEFrame(FVector(
2040 Output.wheel3.wheel_torque_x,
2041 Output.wheel3.wheel_torque_y,
2042 Output.wheel3.wheel_torque_z)));
2043 }
2044 #endif
2045}
2046
2047void UCustomTerrainPhysicsComponent::UpdateParticles(
2048 std::vector<FParticle*> Particles, std::vector<float> Forces,
2049 float DeltaTime, const FTransform& WheelTransform)
2050{
2051 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateParticles);
2052 //UE_LOG(LogCarla, Log, TEXT("%d vs %d"), Particles.size(), Forces.size()/3);
2053 if(bUseLocalFrame)
2054 {
2055 for (size_t i = 0; i < Particles.size(); i++)
2056 {
2057 FVector Force = FVector(Forces[3*i + 0], Forces[3*i + 1], Forces[3*i + 2]) * ParticleForceMulFactor;
2058 FVector LocalAcceleration = Force;
2059 FVector UELocalAcceleration = SIToUEFrame(LocalAcceleration);
2060 FVector UEGlobalAcceleration = WheelTransform.TransformVector(UELocalAcceleration);
2061 FVector Acceleration = UEFrameToSI(UEGlobalAcceleration);
2062 FParticle* P = Particles[i];
2063 P->Velocity = P->Velocity + Acceleration*DeltaTime;
2064 P->Position = P->Position + P->Velocity*DeltaTime;
2065 }
2066 }
2067 else
2068 {
2069 for (size_t i = 0; i < Particles.size(); i++)
2070 {
2071 FVector Force = FVector(Forces[3*i + 0], Forces[3*i + 1], Forces[3*i + 2]) * ParticleForceMulFactor;
2072 FParticle* P = Particles[i];
2073 FVector Acceleration = Force;
2074 P->Velocity = P->Velocity + Acceleration*DeltaTime;
2075 P->Position = P->Position + P->Velocity*DeltaTime;
2076 }
2077 }
2078}
2079
2080void UCustomTerrainPhysicsComponent::UpdateParticlesDebug( std::vector<FParticle*> Particles)
2081{
2082 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateParticles);
2083 float DeltaTime = GetWorld()->GetDeltaSeconds();
2084 for (size_t i = 0; i < Particles.size(); i++)
2085 {
2086 FVector Force = FVector( 0, 0, FMath::RandRange(-1.0f, 1.0f));
2087 FParticle* P = Particles[i];
2088 FVector Acceleration = Force;
2089 P->Velocity = P->Velocity + Acceleration*DeltaTime;
2090 P->Position = P->Position + P->Velocity*DeltaTime;
2091 }
2092}
2093
2094void UCustomTerrainPhysicsComponent::OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld)
2095{
2096 if( bRemoveLandscapeColliders )
2097 {
2098 for(auto CurrentActor : InLevel->Actors)
2099 {
2100 if( ALandscape* CurrentLandscape = Cast<ALandscape>( CurrentActor ) )
2101 {
2102 CurrentLandscape->BodyInstance.ReplaceResponseToChannels( ECollisionResponse::ECR_Block, ECollisionResponse::ECR_Ignore );
2103 CurrentLandscape->BodyInstance.ReplaceResponseToChannels( ECollisionResponse::ECR_Overlap, ECollisionResponse::ECR_Ignore );
2104 CurrentLandscape->BodyInstance.SetCollisionEnabled( ECollisionEnabled::Type::NoCollision, true);
2105
2106 for(auto CurrentCollision : CurrentLandscape->CollisionComponents){
2107 CurrentCollision->SetCollisionResponseToAllChannels( ECollisionResponse::ECR_Ignore );
2108 CurrentCollision->SetCollisionEnabled( ECollisionEnabled::Type::NoCollision );
2109
2110 }
2111
2112 for(auto CurrentComponent : CurrentLandscape->LandscapeComponents){
2113 CurrentComponent->SetCollisionResponseToAllChannels( ECollisionResponse::ECR_Ignore );
2114 CurrentComponent->SetCollisionEnabled( ECollisionEnabled::Type::NoCollision );
2115
2116 }
2117 }
2118 }
2119 }
2120}
2121
2122void UCustomTerrainPhysicsComponent::UpdateTilesHeightMaps(
2123 const std::vector<FParticle*>& Particles)
2124{
2125 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateTilesHeightMaps);
2126
2127 uint32_t PartialHeightMapSize =
2128 SparseMap.GetTileSize() * TextureToUpdate->GetSizeX() / (2*TextureRadius);
2129 float InverseTileSize = 1.f/SparseMap.GetTileSize();
2130 float Transformation = InverseTileSize * PartialHeightMapSize;
2131 float ParticlesInARowInHeightMap = TextureToUpdate->GetSizeX() / (TextureRadius * 2);
2132 for (size_t i = 0; i < Particles.size(); i++)
2133 {
2134 const FParticle* P = Particles[i];
2135 uint64_t TileId = SparseMap.GetTileId(P->Position);
2136 FDenseTile& CurrentTile = SparseMap.GetTile(TileId);
2137 FDVector TilePosition = CurrentTile.TilePosition;
2138 FDVector ParticleLocalPosition = P->Position - TilePosition;
2139 FIntVector HeightMapCoords = FIntVector(
2140 ParticleLocalPosition.X * Transformation,
2141 ParticleLocalPosition.Y * Transformation, 0);
2142
2143 HeightMapCoords.X = std::min( std::max( HeightMapCoords.X, 0) , static_cast<int>(PartialHeightMapSize-1));
2144 HeightMapCoords.Y = std::min( std::max( HeightMapCoords.Y, 0) , static_cast<int>(PartialHeightMapSize-1));
2145 uint32_t Index = HeightMapCoords.Y * PartialHeightMapSize + HeightMapCoords.X;
2146 // Compare to the current value, if higher replace
2147 if( P->Position.Z > CurrentTile.ParticlesHeightMap[Index] )
2148 CurrentTile.ParticlesHeightMap[Index] = P->Position.Z;
2149 }
2150}
2151
2152void UCustomTerrainPhysicsComponent::RemoveParticlesFromOrderedContainer(
2153 const std::vector<FParticle*>& Particles)
2154{
2155 TRACE_CPUPROFILER_EVENT_SCOPE(RemoveParticlesFromOrderedContainer);
2156
2157 uint32_t PartialHeightMapSize =
2158 SparseMap.GetTileSize() * TextureToUpdate->GetSizeX() / (2*TextureRadius);
2159 float InverseTileSize = 1.f/SparseMap.GetTileSize();
2160 float Transformation = InverseTileSize * PartialHeightMapSize;
2161 float ParticlesInARowInHeightMap = TextureToUpdate->GetSizeX() / (TextureRadius * 2);
2162 for (size_t i = 0; i < Particles.size(); i++)
2163 {
2164 const FParticle* P = Particles[i];
2165 uint64_t TileId = SparseMap.GetTileId(P->Position);
2166 FDenseTile& CurrentTile = SparseMap.GetTile(TileId);
2167 CurrentTile.bHeightmapNeedToUpdate = true;
2168 FDVector TilePosition = CurrentTile.TilePosition;
2169 FDVector ParticleLocalPosition = P->Position - TilePosition;
2170 FIntVector HeightMapCoords = FIntVector(
2171 ParticleLocalPosition.X * Transformation,
2172 ParticleLocalPosition.Y * Transformation, 0);
2173
2174 HeightMapCoords.X = std::min( std::max( HeightMapCoords.X, 0) , static_cast<int>(PartialHeightMapSize-1));
2175 HeightMapCoords.Y = std::min( std::max( HeightMapCoords.Y, 0) , static_cast<int>(PartialHeightMapSize-1));
2176 // uint32_t Index = std::floor(ParticleLocalPosition.Y) * PartialHeightMapSize + std::floor(ParticleLocalPosition.X);
2177 uint32_t Index = HeightMapCoords.Y * PartialHeightMapSize + HeightMapCoords.X;
2178
2179 if( Index < CurrentTile.ParticlesZOrdered.size() )
2180 {
2181 if( CurrentTile.ParticlesZOrdered[Index].size() > 1 )
2182 {
2183 auto it = CurrentTile.ParticlesZOrdered[Index].find(P->Position.Z );
2184 if( it != CurrentTile.ParticlesZOrdered[Index].end() )
2185 {
2186 CurrentTile.ParticlesZOrdered[Index].erase(it);
2187 }
2188 else
2189 {
2190 //UE_LOG(LogCarla, Error, TEXT("Cannot find in %d, position %f"), Index, P->Position.Z );
2191 }
2192 }
2193 else
2194 {
2195 UE_LOG(LogCarla, Error, TEXT("Cannot Remove more from %d, currentsize %d Tile : %s"), Index,CurrentTile.ParticlesZOrdered[Index].size(), *(TilePosition.ToString()) );
2196 }
2197 }
2198 else
2199 {
2200 UE_LOG(LogCarla, Error, TEXT("RemoveParticlesFromOrderedContainer Invalid Index %d ZOrderedSize %d Tile: %s"), Index,CurrentTile.ParticlesZOrdered.size(), *(TilePosition.ToString()) );
2201 }
2202 }
2203}
2204
2205void UCustomTerrainPhysicsComponent::AddParticlesToOrderedContainer(
2206 const std::vector<FParticle*>& Particles)
2207{
2208 TRACE_CPUPROFILER_EVENT_SCOPE(AddParticlesToOrderedContainer);
2209
2210 uint32_t PartialHeightMapSize =
2211 SparseMap.GetTileSize() * TextureToUpdate->GetSizeX() / (2*TextureRadius);
2212 float InverseTileSize = 1.f/SparseMap.GetTileSize();
2213 float Transformation = InverseTileSize * PartialHeightMapSize;
2214 float ParticlesInARowInHeightMap = TextureToUpdate->GetSizeX() / (TextureRadius * 2);
2215 for (size_t i = 0; i < Particles.size(); i++)
2216 {
2217 const FParticle* P = Particles[i];
2218 uint64_t TileId = SparseMap.GetTileId(P->Position);
2219 FDenseTile& CurrentTile = SparseMap.GetTile(TileId);
2220 CurrentTile.bHeightmapNeedToUpdate = true;
2221 FDVector TilePosition = CurrentTile.TilePosition;
2222 FDVector ParticleLocalPosition = P->Position - TilePosition;
2223 FIntVector HeightMapCoords = FIntVector(
2224 std::floor(ParticleLocalPosition.X * Transformation),
2225 std::floor(ParticleLocalPosition.Y * Transformation), 0);
2226 //HeightMapCoords.X = std::min( std::max( HeightMapCoords.X, 0) , static_cast<int>(PartialHeightMapSize-1));
2227 //HeightMapCoords.Y = std::min( std::max( HeightMapCoords.Y, 0) , static_cast<int>(PartialHeightMapSize-1));
2228 uint32_t Index = HeightMapCoords.Y * PartialHeightMapSize + HeightMapCoords.X;
2229 if( Index < CurrentTile.ParticlesZOrdered.size() )
2230 {
2231 float CurrentHeight = *( CurrentTile.ParticlesZOrdered[Index].begin() );
2232 if( P->Position.Z - CurrentHeight < UEFrameToSI( ParticleDiameter ) * 2.0f )
2233 {
2234 CurrentTile.ParticlesZOrdered[Index].insert(P->Position.Z);
2235 }
2236 }else{
2237 UE_LOG(LogCarla, Error, TEXT("RemoveParticlesFromOrderedContainer Invalid Index %d ZOrderedSize %d Tile: %s"), Index,CurrentTile.ParticlesZOrdered.size(), *(TilePosition.ToString()) );
2238
2239 }
2240 }
2241}
2242
2243void UCustomTerrainPhysicsComponent::FlagTilesToRedoOrderedContainer(
2244 const std::vector<FParticle*>& Particles)
2245{
2246 TRACE_CPUPROFILER_EVENT_SCOPE(AddParticlesToOrderedContainer);
2247
2248 uint32_t PartialHeightMapSize =
2249 SparseMap.GetTileSize() * TextureToUpdate->GetSizeX() / (2*TextureRadius);
2250 float InverseTileSize = 1.f/SparseMap.GetTileSize();
2251 float Transformation = InverseTileSize * PartialHeightMapSize;
2252 float ParticlesInARowInHeightMap = TextureToUpdate->GetSizeX() / (TextureRadius * 2);
2253 for (size_t i = 0; i < Particles.size(); i++)
2254 {
2255 const FParticle* P = Particles[i];
2256 uint64_t TileId = SparseMap.GetTileId(P->Position);
2257 FDenseTile& CurrentTile = SparseMap.GetTile(TileId);
2258 CurrentTile.bHeightmapNeedToUpdate = true;
2259 CurrentTile.bParticlesZOrderedInitialized = false;
2260 }
2261}
2262
2263
2264void UCustomTerrainPhysicsComponent::UpdateTilesHeightMapsInRadius(FDVector Position, uint32 Rad )
2265{
2266 TRACE_CPUPROFILER_EVENT_SCOPE(UpdateTilesHeightMapsInRadius);
2267
2268 uint64_t TileId = SparseMap.GetTileId( UEFrameToSI(Position.ToFVector() ) );
2269 uint32_t Tile_X = (uint32_t)(TileId >> 32);
2270 uint32_t Tile_Y = (uint32_t)(TileId & (uint32_t)(~0));
2271 uint32_t RadiusInTiles = (Rad/TileSize);
2272
2273 FDVector Extension = UEFrameToSI(WorldSize);
2274 uint32_t MinX = Tile_X - RadiusInTiles;
2275 uint32_t MinY = Tile_Y - RadiusInTiles;
2276 uint32_t MaxX = Tile_X + RadiusInTiles;
2277 uint32_t MaxY = Tile_Y + RadiusInTiles;
2278
2279 for( uint32_t X = MinX; X <= MaxX; ++X )
2280 {
2281 for( uint32_t Y = MinY; Y <= MaxY; ++Y )
2282 {
2283 uint64_t CurrentTileId = SparseMap.GetTileId(X,Y);
2284 if( SparseMap.Map.count(CurrentTileId) )
2285 {
2286 SparseMap.GetTile(X, Y).UpdateLocalHeightmap();
2287 }
2288 }
2289 }
2290}
2291
2292void UCustomTerrainPhysicsComponent::AddForceToSingleWheel( USkeletalMeshComponent* SkeletalMeshComponent, FVector WheelPosition, FVector WheelNormalForce )
2293{
2294 FVector WheelBottomLocation = WheelPosition - FVector(0,0, 0.337);
2295 float OriginalHeight = SparseMap.GetHeight(WheelPosition);
2296 float NewFloorHeight = OriginalHeight - UEFrameToSI(TerrainDepth);
2297
2298 if( WheelNormalForce.Size() == 0 ){
2299 WheelNormalForce = FVector::UpVector;
2300 }
2301
2302 float ForceFactor = ( WheelBottomLocation.Z - OriginalHeight ) / ( NewFloorHeight - OriginalHeight );
2303 if( ForceFactor < 0){
2304 ForceFactor = 0;
2305 }
2306
2307 SkeletalMeshComponent->AddForceAtLocationLocal(WheelPosition, SIToUEFrame(WheelNormalForce) * ( ForceFactor * NormalForceIntensity) );
2308}
2309
2310void UCustomTerrainPhysicsComponent::ApplyForcesToVehicle(
2312 FVector ForceWheel0, FVector ForceWheel1, FVector ForceWheel2, FVector ForceWheel3,
2313 FVector TorqueWheel0, FVector TorqueWheel1, FVector TorqueWheel2, FVector TorqueWheel3)
2314{
2315 TRACE_CPUPROFILER_EVENT_SCOPE(UCustomTerrainPhysicsComponent::ApplyForcesToVehicle);
2316
2317 FTransform VehicleTransform = Vehicle->GetTransform();
2318 FVector WheelPosition0 = VehicleTransform.TransformPosition(FVector(140, -70, 40));
2319 FVector WheelPosition1 = VehicleTransform.TransformPosition(FVector(140, 70, 40));
2320 FVector WheelPosition2 = VehicleTransform.TransformPosition(FVector(-140, -70, 40));
2321 FVector WheelPosition3 = VehicleTransform.TransformPosition(FVector(-140, 70, 40));
2322 UPrimitiveComponent* PrimitiveComponent =
2323 Cast<UPrimitiveComponent>(Vehicle->GetRootComponent());
2324 if(!PrimitiveComponent)
2325 {
2326 UE_LOG(LogCarla, Error, TEXT("ApplyForcesToVehicle Vehicle does not contain UPrimitiveComponent"));
2327 return;
2328 }
2329 if(bDisableVehicleGravity && PrimitiveComponent->IsGravityEnabled())
2330 {
2331 PrimitiveComponent->SetEnableGravity(false);
2332 }
2333 if(bUseLocalFrame)
2334 {
2335 ForceWheel0 = VehicleTransform.TransformVector(ForceWheel0);
2336 ForceWheel1 = VehicleTransform.TransformVector(ForceWheel1);
2337 ForceWheel2 = VehicleTransform.TransformVector(ForceWheel2);
2338 ForceWheel3 = VehicleTransform.TransformVector(ForceWheel3);
2339 }
2340 ForceWheel0 = ForceWheel0.GetClampedToMaxSize(MaxForceMagnitude);
2341 ForceWheel1 = ForceWheel1.GetClampedToMaxSize(MaxForceMagnitude);
2342 ForceWheel2 = ForceWheel2.GetClampedToMaxSize(MaxForceMagnitude);
2343 ForceWheel3 = ForceWheel3.GetClampedToMaxSize(MaxForceMagnitude);
2344
2345 if(bUseImpulse)
2346 {
2347 PrimitiveComponent->AddImpulseAtLocation(ForceWheel0, WheelPosition0);
2348 PrimitiveComponent->AddImpulseAtLocation(ForceWheel1, WheelPosition1);
2349 PrimitiveComponent->AddImpulseAtLocation(ForceWheel2, WheelPosition2);
2350 PrimitiveComponent->AddImpulseAtLocation(ForceWheel3, WheelPosition3);
2351 }
2352 else
2353 {
2354 PrimitiveComponent->AddForceAtLocationLocal(ForceWheel0, FVector(140, -70, 40));
2355 PrimitiveComponent->AddForceAtLocationLocal(ForceWheel1, FVector(140, 70, 40));
2356 PrimitiveComponent->AddForceAtLocationLocal(ForceWheel2, FVector(-140, -70, 40));
2357 PrimitiveComponent->AddForceAtLocationLocal(ForceWheel3, FVector(-140, 70, 40));
2358 }
2359
2360 PrimitiveComponent->AddTorqueInRadians(TorqueWheel0);
2361 PrimitiveComponent->AddTorqueInRadians(TorqueWheel1);
2362 PrimitiveComponent->AddTorqueInRadians(TorqueWheel2);
2363 PrimitiveComponent->AddTorqueInRadians(TorqueWheel3);
2364 if (DrawDebugInfo && bShowForces)
2365 {
2366 float LifeTime = 0.3f;
2367 bool bPersistentLines = false;
2368 bool bDepthIsForeground = (0 == SDPG_Foreground);
2369 UWorld * World = GetWorld();
2370 ULineBatchComponent* LineBatcher =
2371 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
2372 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
2373 if (!LineBatcher)
2374 {
2375 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
2376 }
2377 LineBatcher->DrawLine(WheelPosition0 + FVector(0,0,50),
2378 WheelPosition0 + FVector(0,0,50)+ ForceWheel0.GetSafeNormal()*(5 + ForceMulFactor*10*ForceWheel0.Size()),
2379 FLinearColor(0.0,1.0,0.0), 0, 3.0, 0.3);
2380 LineBatcher->DrawLine(WheelPosition1 + FVector(0,0,50),
2381 WheelPosition1 + FVector(0,0,50)+ ForceWheel1.GetSafeNormal()*(5 + ForceMulFactor*10*ForceWheel1.Size()),
2382 FLinearColor(0.0,1.0,0.0), 0, 3.0, 0.3);
2383 LineBatcher->DrawLine(WheelPosition2 + FVector(0,0,50),
2384 WheelPosition2 + FVector(0,0,50)+ ForceWheel2.GetSafeNormal()*(5 + ForceMulFactor*10*ForceWheel2.Size()),
2385 FLinearColor(0.0,1.0,0.0), 0, 3.0, 0.3);
2386 LineBatcher->DrawLine(WheelPosition3 + FVector(0,0,50),
2387 WheelPosition3 + FVector(0,0,50)+ ForceWheel3.GetSafeNormal()*(5 + ForceMulFactor*10*ForceWheel3.Size()),
2388 FLinearColor(0.0,1.0,0.0), 0, 3.0, 0.3);
2389 }
2390}
2391
2392void UCustomTerrainPhysicsComponent::ApplyMeanAccelerationToVehicle(
2394 FVector ForceWheel0, FVector ForceWheel1, FVector ForceWheel2, FVector ForceWheel3)
2395{
2396 TRACE_CPUPROFILER_EVENT_SCOPE(UCustomTerrainPhysicsComponent::ApplyForcesToVehicle);
2397 FVector MeanAcceleration = (ForceWheel0 + ForceWheel1 + ForceWheel2 + ForceWheel3)/4.f;
2398 UPrimitiveComponent* PrimitiveComponent =
2399 Cast<UPrimitiveComponent>(Vehicle->GetRootComponent());
2400 if (!PrimitiveComponent)
2401 {
2402 UE_LOG(LogCarla, Error, TEXT("ApplyMeanAccelerationToVehicle Vehicle does not contain UPrimitiveComponent"));
2403 return;
2404 }
2405 if(bDisableVehicleGravity && PrimitiveComponent->IsGravityEnabled())
2406 {
2407 PrimitiveComponent->SetEnableGravity(false);
2408 }
2409 if(bUseLocalFrame)
2410 {
2411 FTransform VehicleTransform = Vehicle->GetTransform();
2412 MeanAcceleration = VehicleTransform.TransformVector(MeanAcceleration);
2413 }
2414 PrimitiveComponent->AddForce(MeanAcceleration, FName(""), true);
2415
2416 if (DrawDebugInfo && bShowForces)
2417 {
2418 float LifeTime = 0.3f;
2419 bool bPersistentLines = false;
2420 bool bDepthIsForeground = (0 == SDPG_Foreground);
2421 UWorld * World = GetWorld();
2422 ULineBatchComponent* LineBatcher =
2423 (World ? (bDepthIsForeground ? World->ForegroundLineBatcher :
2424 (( bPersistentLines || (LifeTime > 0.f) ) ? World->PersistentLineBatcher : World->LineBatcher)) : nullptr);
2425 if (!LineBatcher)
2426 {
2427 UE_LOG(LogCarla, Error, TEXT("Missing linebatcher"));
2428 }
2429 LineBatcher->DrawLine(PrimitiveComponent->GetComponentLocation() + FVector(0,0,200),
2430 PrimitiveComponent->GetComponentLocation() + FVector(0,0,200)+ MeanAcceleration.GetSafeNormal()*(1 + MeanAcceleration.Size()),
2431 FLinearColor(0.0,1.0,0.0), 0, 3.0, 0.3);
2432 }
2433}
2434
2435TArray<FVector> UCustomTerrainPhysicsComponent::GetParticlesInRadius(FVector Position, float InRadius)
2436{
2437 std::vector<FParticle*> Particles = SparseMap.GetParticlesInRadius(UEFrameToSI(Position), InRadius*CMToM);
2438 TArray<FVector> ParticlePositions;
2439 for(FParticle* Particle : Particles)
2440 {
2441 ParticlePositions.Add(SIToUEFrame(Particle->Position.ToFVector()));
2442 }
2443 return ParticlePositions;
2444}
2445
2446TArray<FVector> UCustomTerrainPhysicsComponent::GetParticlesInTileRadius(FVector Position, float InRadius)
2447{
2448 std::vector<FParticle*> Particles = SparseMap.GetParticlesInTileRadius(UEFrameToSI(Position), InRadius*CMToM);
2449 TArray<FVector> ParticlePositions;
2450 for(FParticle* Particle : Particles)
2451 {
2452 ParticlePositions.Add(SIToUEFrame(Particle->Position.ToFVector()));
2453 }
2454 return ParticlePositions;
2455}
2456
2457
2458FVector UCustomTerrainPhysicsComponent::GetTileCenter(FVector Position)
2459{
2460 return SIToUEFrame(
2461 SparseMap.GetTilePosition(
2462 SparseMap.GetTileId(
2463 UEFrameToSI(Position))).ToFVector());
2464}
2465
2466void UCustomTerrainPhysicsComponent::SetUpParticleArrays(std::vector<FParticle*>& ParticlesIn,
2467 TArray<float>& ParticlePosOut,
2468 TArray<float>& ParticleVelOut,
2469 const FTransform &WheelTransform)
2470{
2471 ParticlePosOut.Empty();
2472 ParticleVelOut.Empty();
2473 ParticlePosOut.Reserve(ParticlesIn.size()*3);
2474 ParticleVelOut.Reserve(ParticlesIn.size()*3);
2475 if(bUseLocalFrame)
2476 {
2477 const FTransform InverseTransform = WheelTransform.Inverse();
2478 for(FParticle* Particle : ParticlesIn)
2479 {
2480 FVector UEPosition = SIToUEFrame(Particle->Position.ToFVector());
2481 FVector UELocalPosition = InverseTransform.TransformPosition(UEPosition);
2482 FVector Position = UEFrameToSI(UELocalPosition);
2483 ParticlePosOut.Add(static_cast<float>(Position.X));
2484 ParticlePosOut.Add(static_cast<float>(Position.Y));
2485 ParticlePosOut.Add(static_cast<float>(Position.Z));
2486 ParticleVelOut.Add(Particle->Velocity.X);
2487 ParticleVelOut.Add(Particle->Velocity.Y);
2488 ParticleVelOut.Add(Particle->Velocity.Z);
2489 }
2490 if(ParticlesIn.size() < MaxParticlesPerWheel)
2491 {
2492 for (int i = 0; i < (MaxParticlesPerWheel - ParticlesIn.size()); ++i)
2493 {
2494 ParticlePosOut.Add(0.f);
2495 ParticlePosOut.Add(0.f);
2496 ParticlePosOut.Add(0.f);
2497 ParticleVelOut.Add(0.f);
2498 ParticleVelOut.Add(0.f);
2499 ParticleVelOut.Add(0.f);
2500 }
2501 }
2502 }
2503 else
2504 {
2505 for(FParticle* Particle : ParticlesIn)
2506 {
2507 ParticlePosOut.Add(static_cast<float>(Particle->Position.X));
2508 ParticlePosOut.Add(static_cast<float>(Particle->Position.Y));
2509 ParticlePosOut.Add(static_cast<float>(Particle->Position.Z));
2510 ParticleVelOut.Add(Particle->Velocity.X);
2511 ParticleVelOut.Add(Particle->Velocity.Y);
2512 ParticleVelOut.Add(Particle->Velocity.Z);
2513 }
2514 if(ParticlesIn.size() < MaxParticlesPerWheel)
2515 {
2516 FVector WheelPosition = UEFrameToSI(WheelTransform.GetLocation());
2517 for (int i = 0; i < (MaxParticlesPerWheel - ParticlesIn.size()); ++i)
2518 {
2519 ParticlePosOut.Add(WheelPosition.X);
2520 ParticlePosOut.Add(WheelPosition.Y);
2521 ParticlePosOut.Add(WheelPosition.Z);
2522 ParticleVelOut.Add(0.f);
2523 ParticleVelOut.Add(0.f);
2524 ParticleVelOut.Add(0.f);
2525 }
2526 }
2527 }
2528}
2529
2530void UCustomTerrainPhysicsComponent::SetUpWheelArrays(ACarlaWheeledVehicle *Vehicle, int WheelIdx,
2531 TArray<float>& WheelPos,
2532 TArray<float>& WheelOrientation,
2533 TArray<float>& WheelLinearVelocity,
2534 TArray<float>& WheelAngularVelocity)
2535{
2536 FTransform VehicleTransform = Vehicle->GetTransform();
2537 FVector Position;
2538 //placeholder
2539 switch (WheelIdx)
2540 {
2541 case 0:
2542 Position = FVector(140, -70, 40);
2543 break;
2544 case 1:
2545 Position = FVector(140, 70, 40);
2546 break;
2547 case 2:
2548 Position = FVector(-140, -70, 40);
2549 break;
2550 case 3:
2551 default:
2552 Position = FVector(-140, 70, 40);
2553 break;
2554 }
2555 FVector PhysAngularVelocity = Vehicle->GetMesh()->GetPhysicsAngularVelocityInRadians();
2556 //UE_LOG(LogCarla, Log, TEXT("AngVel: %s"), *PhysAngularVelocity.ToString());
2557 if (bUseLocalFrame)
2558 {
2559 FTransform InverseTransform = VehicleTransform.Inverse();
2560 Position = FVector(0,0,0);
2561 FVector Velocity = UEFrameToSI(
2562 InverseTransform.TransformVector(Vehicle->GetVelocity()));
2563 WheelPos = {Position.X, Position.Y, Position.Z};
2564 // convert to SI
2565 WheelOrientation = {1.f, 0.f, 0.f, 0.f};
2566 WheelLinearVelocity = {Velocity.X, Velocity.Y, Velocity.Z};
2567 FVector LocalAngularVelocity = InverseTransform.TransformVector(PhysAngularVelocity);
2568 //UE_LOG(LogCarla, Log, TEXT("Local Total AngVel: %s"), *LocalAngularVelocity.ToString());
2569 float ForwardSpeed = Velocity.X;
2570 float AngularSpeed = (ForwardSpeed/(CMToM*TireRadius));
2571 WheelAngularVelocity = {
2572 LocalAngularVelocity.X,
2573 AngularSpeed + LocalAngularVelocity.Y,
2574 -LocalAngularVelocity.Z};
2575 }
2576 else
2577 {
2578 Position = VehicleTransform.TransformPosition(Position);
2579 if(LargeMapManager)
2580 {
2581 Position = LargeMapManager->LocalToGlobalLocation(Position);
2582 }
2584 float ForwardSpeed = FVector::DotProduct(
2585 Vehicle->GetVelocity(),VehicleTransform.GetRotation().GetForwardVector());
2586 FVector Velocity = UEFrameToSI(Vehicle->GetVelocity());
2587 WheelPos = {Position.X, Position.Y, Position.Z};
2588 FQuat Quat = VehicleTransform.GetRotation();
2589 //UE_LOG(LogCarla, Log, TEXT("Quat: %s"), *Quat.ToString());
2590 // convert to SI
2591 WheelOrientation = {Quat.W,Quat.X,-Quat.Y,Quat.Z};
2592 WheelLinearVelocity = {Velocity.X, Velocity.Y, Velocity.Z};
2593 float AngularSpeed = (ForwardSpeed)/(TireRadius);
2594 FVector GlobalAngulaSpeed = VehicleTransform.TransformVector(FVector(0, AngularSpeed, 0));
2595 PhysAngularVelocity = PhysAngularVelocity + GlobalAngulaSpeed;
2596 WheelAngularVelocity = {
2597 PhysAngularVelocity.X,
2598 PhysAngularVelocity.Y,
2599 -PhysAngularVelocity.Z};
2600 //UE_LOG(LogCarla, Log, TEXT("Total AngVel: %s"), *PhysAngularVelocity.ToString());
2601 }
2602}
2603
2604void UCustomTerrainPhysicsComponent::AddForces(
2605 const TArray<FForceAtLocation> &Forces)
2606{
2607 for (const FForceAtLocation& Force : Forces)
2608 {
2609 ForcesToApply.Add(Force);
2610 }
2611}
2612
2613void UCustomTerrainPhysicsComponent::ApplyForces()
2614{
2615 for (const FForceAtLocation& Force : ForcesToApply)
2616 {
2617 RootComponent->AddForceAtLocationLocal(Force.Force, Force.Location);
2618 }
2619 ForcesToApply.Empty();
2620}
2621
2622void UCustomTerrainPhysicsComponent::UpdateMaps(
2623 FVector Position, float RadiusX, float RadiusY, float CacheRadiusX, float CacheRadiusY)
2624{
2625 SparseMap.UpdateMaps(UEFrameToSI(Position), UEFrameToSI(RadiusX), UEFrameToSI(RadiusY),
2626 UEFrameToSI(CacheRadiusX), UEFrameToSI(CacheRadiusY));
2627}
2628
2629FTilesWorker::FTilesWorker(UCustomTerrainPhysicsComponent* TerrainComp, FVector NewPosition, float NewRadiusX, float NewRadiusY )
2630{
2631 CustomTerrainComp = TerrainComp;
2632 Position = NewPosition;
2633 RadiusX = NewRadiusX;
2634 RadiusY = NewRadiusY;
2635}
2636
2641
2642
2644
2645 FDateTime CacheCurrentTime = FDateTime::Now();
2646 FDateTime LoadTilesCurrentTime = FDateTime::Now();
2647 FDateTime UnloadTilesCurrentTime = FDateTime::Now();
2648
2649 while(bShouldContinue){
2650 FVector LastPosition = CustomTerrainComp->LastUpdatedPosition;
2651 if(Position != LastPosition)
2652 {
2653 Position = LastPosition;
2654 CustomTerrainComp->UpdateMaps(CustomTerrainComp->LastUpdatedPosition,
2655 CustomTerrainComp->TileRadius.X, CustomTerrainComp->TileRadius.Y,
2656 CustomTerrainComp->CacheRadius.X, CustomTerrainComp->CacheRadius.Y);
2657 }
2658 if(!bShouldContinue)
2659 {
2660 break;
2661 }
2662 }
2663
2664 return 0;
2665}
void ReadFVector(std::istream &InFile, FVector &OutObj)
constexpr float MToCM
FVector UEFrameToSI(const FVector &In)
const int CacheExtraRadius
constexpr float CMToM
FVector SIToUEFrame(const FVector &In)
FVector UEFrameToSIDirection(const FVector &In)
FVector SIToUEFrameDirection(const FVector &In)
std::string _filesBaseFolder
@ DESERT
@ FOREST
Base class for CARLA wheeled vehicles.
FSoilTerramechanicsProperties GetTerrainPropertiesAtGlobalLocation(FVector VehicleLocation)
A view over an actor and its properties.
Definition CarlaActor.h:25
const FActorInfo * GetActorInfo() const
Definition CarlaActor.h:101
FIntVector GetVectorTileId(FDVector Position)
FDenseTile & GetTile(uint32_t Tile_X, uint32_t Tile_Y)
FDenseTile & InitializeRegionInCache(uint64_t TileId)
FDenseTile & InitializeRegion(uint32_t Tile_X, uint32_t Tile_Y)
std::vector< FParticle * > GetParticlesInTileRadius(FDVector Position, float Radius)
void InitializeMap(UHeightMapDataAsset *DataAsset, FDVector Origin, FDVector MapSize, float Size, float ScaleZ)
std::vector< uint64_t > GetIntersectingTiles(const FOrientedBox &OBox)
void UpdateMaps(FDVector Position, float RadiusX, float RadiusY, float CacheRadiusX, float CacheRadiusY)
std::vector< uint64_t > GetLoadedTilesInRange(FDVector Position, float Radius)
std::unordered_map< uint64_t, FDenseTile > CacheMap
FDVector GetTilePosition(uint64_t TileId)
std::vector< FParticle * > GetParticlesInBox(const FOrientedBox &OBox)
uint64_t GetTileId(uint32_t Tile_X, uint32_t Tile_Y)
void Update(FVector Position, float RadiusX, float RadiusY)
std::vector< FParticle * > GetParticlesInRadius(FDVector Position, float Radius)
void UpdateHeightMap(UHeightMapDataAsset *DataAsset, FDVector Origin, FDVector MapSize, float Size, float ScaleZ)
std::unordered_map< uint64_t, FDenseTile > Map
static bool ActorAttributeToBool(const FActorAttribute &ActorAttribute, bool Default)
============================================================================
A simulation episode.
FCarlaActor * FindCarlaActor(FCarlaActor::IdType ActorId)
Find a Carla actor by id.
static ALargeMapManager * GetLargeMapManager(const UObject *WorldContextObject)
static UCarlaEpisode * GetCurrentEpisode(const UObject *WorldContextObject)
void test_learning()
Definition pytorch.cpp:27
geom::Location Location
std::vector< cg::Location > Path
An actor attribute, may be an intrinsic (non-modifiable) attribute of the actor or an user-defined ac...
A description of a Carla Actor with all its variation.
TMap< FString, FActorAttribute > Variations
User selected variations of the actor.
A view over an actor and its properties.
Definition ActorInfo.h:23
FActorDescription Description
Definition ActorInfo.h:26
double X
Definition DVector.h:13
double Z
Definition DVector.h:15
FString ToString() const
Definition DVector.h:52
double Y
Definition DVector.h:14
void GetParticlesInBox(const FOrientedBox &OBox, std::vector< FParticle * > &ParticlesInRadius)
std::vector< float > ParticlesHeightMap
std::vector< std::multiset< float, std::greater< float > > > ParticlesZOrdered
std::vector< FParticle > Particles
void InitializeTile(uint32_t TextureSize, float AffectedRadius, float ParticleSize, float Depth, FDVector TileOrigin, FDVector TileEnd, const FString &SavePath, const FHeightMapData &HeightMap)
void GetAllParticles(std::vector< FParticle * > &ParticlesInRadius)
std::vector< FParticle * > GetParticlesInRadius(FDVector Position, float Radius)
FDenseTile & operator=(FDenseTile &&Origin)
float GetHeight(FDVector Position) const
void InitializeHeightmap(UHeightMapDataAsset *DataAsset, FDVector Size, FDVector Origin, FDVector Tile0, float ScaleZ)
std::vector< float > Pixels
TEnumAsByte< ESoilTerramechanicsType > TerrainType
class UCustomTerrainPhysicsComponent * CustomTerrainComp
virtual uint32 Run() override
FTilesWorker(class UCustomTerrainPhysicsComponent *TerrainComp, FVector NewPosition, float NewRadiusX, float NewRadiusY)
std::vector< float > _particle_forces
Definition pytorch.h:50