First working version of CarlaExporter after refactoring to use Chaos instead of PhysX

This commit is contained in:
Jorge Virgos 2024-10-01 18:29:02 +02:00
parent 76dfbb1244
commit 2cbb528874
1 changed files with 175 additions and 146 deletions

View File

@ -18,6 +18,8 @@
#include "LevelEditor.h"
#include "EngineUtils.h"
#include "PhysicsPublic.h"
#include "Chaos/Core.h"
#include "Chaos/TriangleMeshImplicitObject.h"
#include <fstream>
#include <sstream>
@ -191,8 +193,6 @@ void FCarlaExporterModule::PluginButtonClicked()
int32 FCarlaExporterModule::WriteObjectGeom(std::ofstream &f, FString ObjectName, UBodySetup *body, FTransform &CompTransform, AreaType Area, int32 Offset)
{
// @CARLAUE
#if 0
if (!body) return 0;
constexpr float TO_METERS = 0.01f;
@ -200,139 +200,169 @@ int32 FCarlaExporterModule::WriteObjectGeom(std::ofstream &f, FString ObjectName
int TotalVerticesAdded = 0;
bool Written = false;
// try to write the box collision if any
for (const auto &box: body->AggGeom.BoxElems)
{
// get data
const int32 nbVerts = 8;
TArray<FVector> boxVerts;
TArray<int32> indexBuffer;
FVector HalfExtent(box.X / 2.0f, box.Y / 2.0f, box.Z / 2.0f);
f << "o " << TCHAR_TO_ANSI(*(ObjectName +"_box")) << "\n";
// define the 8 vertices
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, -HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, -HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, +HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, +HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, -HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, -HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, +HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, +HalfExtent.Y, +HalfExtent.Z)));
// define the 12 faces (36 indices)
indexBuffer.Add(0); indexBuffer.Add(1); indexBuffer.Add(3);
indexBuffer.Add(0); indexBuffer.Add(3); indexBuffer.Add(2);
indexBuffer.Add(2); indexBuffer.Add(3); indexBuffer.Add(7);
indexBuffer.Add(2); indexBuffer.Add(7); indexBuffer.Add(6);
indexBuffer.Add(6); indexBuffer.Add(7); indexBuffer.Add(5);
indexBuffer.Add(6); indexBuffer.Add(5); indexBuffer.Add(4);
indexBuffer.Add(4); indexBuffer.Add(5); indexBuffer.Add(1);
indexBuffer.Add(4); indexBuffer.Add(1); indexBuffer.Add(0);
indexBuffer.Add(2); indexBuffer.Add(6); indexBuffer.Add(4);
indexBuffer.Add(2); indexBuffer.Add(4); indexBuffer.Add(0);
indexBuffer.Add(7); indexBuffer.Add(3); indexBuffer.Add(1);
indexBuffer.Add(7); indexBuffer.Add(1); indexBuffer.Add(5);
// write all vertex
for (int32 j=0; j<nbVerts; j++)
{
const FVector &v = boxVerts[j];
FVector vec(v.X, v.Y, v.Z);
FVector vec3 = CompTransform.TransformVector(vec);
FVector world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
f << "v " << std::fixed << world.X * TO_METERS << " " << world.Z * TO_METERS << " " << world.Y * TO_METERS << "\n";
}
// set the material in function of the area type
switch (Area)
{
case AreaType::ROAD: f << "usemtl road" << "\n"; break;
case AreaType::GRASS: f << "usemtl grass" << "\n"; break;
case AreaType::SIDEWALK: f << "usemtl sidewalk" << "\n"; break;
case AreaType::CROSSWALK: f << "usemtl crosswalk" << "\n"; break;
case AreaType::BLOCK: f << "usemtl block" << "\n"; break;
}
// write all faces
int k = 0;
for (int32 i=0; i<indexBuffer.Num()/3; ++i)
{
// inverse order for left hand
f << "f " << Offset + indexBuffer[k+2] << " " << Offset + indexBuffer[k+1] << " " << Offset + indexBuffer[k] << "\n";
k += 3;
}
TotalVerticesAdded += nbVerts;
Offset += nbVerts;
Written = true;
}
// try to write the simple collision mesh
for (const auto &convex : body->AggGeom.ConvexElems)
{
// get data
PxConvexMesh *mesh = convex.GetConvexMesh();
if (!mesh) continue;
int32 nbVerts = mesh->getNbVertices();
const PxVec3* convexVerts = mesh->getVertices();
const PxU8* indexBuffer = (PxU8 *) mesh->getIndexBuffer();
f << "o " << TCHAR_TO_ANSI(*(ObjectName +"_convex")) << "\n";
// write all vertex
for (int32 j=0; j<nbVerts; j++)
{
const PxVec3 &v = convexVerts[j];
FVector vec(v.x, v.y, v.z);
FVector vec3 = CompTransform.TransformVector(vec);
FVector world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
f << "v " << std::fixed << world.X * TO_METERS << " " << world.Z * TO_METERS << " " << world.Y * TO_METERS << "\n";
}
// set the material in function of the area type
switch (Area)
{
case AreaType::ROAD: f << "usemtl road" << "\n"; break;
case AreaType::GRASS: f << "usemtl grass" << "\n"; break;
case AreaType::SIDEWALK: f << "usemtl sidewalk" << "\n"; break;
case AreaType::CROSSWALK: f << "usemtl crosswalk" << "\n"; break;
case AreaType::BLOCK: f << "usemtl block" << "\n"; break;
}
// write all faces
for (PxU32 i=0; i<mesh->getNbPolygons(); ++i)
{
PxHullPolygon face;
bool status = mesh->getPolygonData(i, face);
const PxU8* faceIndices = indexBuffer + face.mIndexBase;
int faceNbVerts = face.mNbVerts;
for(int32 j=2; j<faceNbVerts; j++)
{
// inverse order for left hand
f << "f " << Offset + faceIndices[j-1] << " " << Offset + faceIndices[j] << " " << Offset + faceIndices[0] << "\n";
}
}
TotalVerticesAdded += nbVerts;
Offset += nbVerts;
Written = true;
}
if (!Written)
{
auto WriteComplexCollision = [&]() {
// write the mesh
for (const auto &mesh : body->TriMeshes)
for (const TSharedPtr<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe> &mesh : body->ChaosTriMeshes)
{
// get data
PxU32 nbVerts = mesh->getNbVertices();
const PxVec3* convexVerts = mesh->getVertices();
uint32_t nbVerts = mesh->Particles().Size();
const Chaos::TParticles<Chaos::FRealSingle, 3> &convexVerts = mesh->Particles();
const Chaos::FTrimeshIndexBuffer &convexIndices = mesh->Elements();
f << "o " << TCHAR_TO_ANSI(*(ObjectName +"_mesh")) << "\n";
// write all vertex
for (PxU32 j=0; j<nbVerts; j++)
for (uint32_t j=0; j < nbVerts; ++j)
{
const PxVec3 &v = convexVerts[j];
FVector vec(v.x, v.y, v.z);
const Chaos::FVec3 &v = convexVerts.X(j); //FVector(convexVerts.X(j*3), convexVerts.X(j*3+1), convexVerts.X(j*3+2));
Chaos::FVec3 vec(v.X, v.Y, v.Z);
Chaos::FVec3 vec3 = CompTransform.TransformVector(vec);
Chaos::FVec3 world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
f << "v " << std::fixed << world.X * TO_METERS << " " << world.Z * TO_METERS << " " << world.Y * TO_METERS << "\n";
}
// set the material in function of the area type
switch (Area)
{
case AreaType::ROAD: f << "usemtl road" << "\n"; break;
case AreaType::GRASS: f << "usemtl grass" << "\n"; break;
case AreaType::SIDEWALK: f << "usemtl sidewalk" << "\n"; break;
case AreaType::CROSSWALK: f << "usemtl crosswalk" << "\n"; break;
case AreaType::BLOCK: f << "usemtl block" << "\n"; break;
}
// write all faces
// triangle indices can be of 16 or 32 bits
if (!convexIndices.RequiresLargeIndices())
{
const TArray<Chaos::TVec3<uint16>>& Indices16 = convexIndices.GetIndexBuffer<uint16>();
for (int32 i=0; i < Indices16.Num(); ++i)
{
// inverse order for left hand
f << "f " << Offset + Indices16[i].Z << " " << Offset + Indices16[i].Y << " " << Offset + Indices16[i].X << "\n";
}
}
else
{
const TArray<Chaos::TVec3<int32>>& Indices32 = convexIndices.GetIndexBuffer<int32>();
for (int32 i=0; i < Indices32.Num(); ++i)
{
// inverse order for left hand
f << "f " << Offset + Indices32[i].Z << " " << Offset + Indices32[i].Y << " " << Offset + Indices32[i].X << "\n";
}
}
TotalVerticesAdded += nbVerts;
Offset += nbVerts;
Written = true;
}
};
auto WriteSimpleCollision = [&]() {
// try to write the simple collision mesh
for (const FKConvexElem &convex : body->AggGeom.ConvexElems)
{
// get data
//PxConvexMesh *mesh = convex.GetConvexMesh();
//if (!mesh) continue;
int32 nbVerts = convex.VertexData.Num();
TArray<FVector> convexVerts = convex.VertexData;
int32 nbIndices = convex.IndexData.Num();
TArray<int32> indexBuffer = convex.IndexData;
f << "o " << TCHAR_TO_ANSI(*(ObjectName +"_convex")) << "\n";
// write all vertex
for (int32 j=0; j<nbVerts; j++)
{
const FVector &v = convexVerts[j];
FVector vec(v.X, v.Y, v.Z);
FVector vec3 = CompTransform.TransformVector(vec);
FVector world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
f << "v " << std::fixed << world.X * TO_METERS << " " << world.Z * TO_METERS << " " << world.Y * TO_METERS << "\n";
}
// set the material in function of the area type
switch (Area)
{
case AreaType::ROAD: f << "usemtl road" << "\n"; break;
case AreaType::GRASS: f << "usemtl grass" << "\n"; break;
case AreaType::SIDEWALK: f << "usemtl sidewalk" << "\n"; break;
case AreaType::CROSSWALK: f << "usemtl crosswalk" << "\n"; break;
case AreaType::BLOCK: f << "usemtl block" << "\n"; break;
}
// write all faces
//TArray<FPlane> planes;
//convex->GetPlanes(planes);
// for (PxU32 i=0; i<mesh->getNbPolygons(); ++i) //planes.Num()
// {
// PxHullPolygon face; //planes[i]
// bool status = mesh->getPolygonData(i, face);
// const PxU8* faceIndices = indexBuffer + face.mIndexBase;
// int faceNbVerts = face.mNbVerts;
// for(int32 j=2; j<faceNbVerts; j++)
// {
// // inverse order for left hand
// f << "f " << Offset + faceIndices[j-1] << " " << Offset + faceIndices[j] << " " << Offset + faceIndices[0] << "\n";
// }
// }
int32 NumTriangles = convex.IndexData.Num() / 3;
for(int32 j=0; j<NumTriangles; ++j)
{
f << "f "
<< Offset + indexBuffer[3 * j] << " "
<< Offset + indexBuffer[3 * j + 1] << " "
<< Offset + indexBuffer[3 * j + 2] << "\n";
}
TotalVerticesAdded += nbVerts;
Offset += nbVerts;
Written = true;
}
};
auto WriteBoxCollision = [&]() {
// try to write the box collision if any
for (const FKBoxElem &box: body->AggGeom.BoxElems)
{
// get data
const int32 nbVerts = 8;
TArray<FVector> boxVerts;
TArray<int32> indexBuffer;
FVector HalfExtent(box.X / 2.0f, box.Y / 2.0f, box.Z / 2.0f);
f << "o " << TCHAR_TO_ANSI(*(ObjectName +"_box")) << "\n";
// define the 8 vertices
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, -HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, -HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, +HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(-HalfExtent.X, +HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, -HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, -HalfExtent.Y, +HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, +HalfExtent.Y, -HalfExtent.Z)));
boxVerts.Add(box.Center + box.Rotation.RotateVector(FVector(+HalfExtent.X, +HalfExtent.Y, +HalfExtent.Z)));
// define the 12 faces (36 indices)
indexBuffer.Add(0); indexBuffer.Add(1); indexBuffer.Add(3);
indexBuffer.Add(0); indexBuffer.Add(3); indexBuffer.Add(2);
indexBuffer.Add(2); indexBuffer.Add(3); indexBuffer.Add(7);
indexBuffer.Add(2); indexBuffer.Add(7); indexBuffer.Add(6);
indexBuffer.Add(6); indexBuffer.Add(7); indexBuffer.Add(5);
indexBuffer.Add(6); indexBuffer.Add(5); indexBuffer.Add(4);
indexBuffer.Add(4); indexBuffer.Add(5); indexBuffer.Add(1);
indexBuffer.Add(4); indexBuffer.Add(1); indexBuffer.Add(0);
indexBuffer.Add(2); indexBuffer.Add(6); indexBuffer.Add(4);
indexBuffer.Add(2); indexBuffer.Add(4); indexBuffer.Add(0);
indexBuffer.Add(7); indexBuffer.Add(3); indexBuffer.Add(1);
indexBuffer.Add(7); indexBuffer.Add(1); indexBuffer.Add(5);
// write all vertex
for (int32 j=0; j<nbVerts; j++)
{
const FVector &v = boxVerts[j];
FVector vec(v.X, v.Y, v.Z);
FVector vec3 = CompTransform.TransformVector(vec);
FVector world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
@ -349,31 +379,30 @@ int32 FCarlaExporterModule::WriteObjectGeom(std::ofstream &f, FString ObjectName
}
// write all faces
int k = 0;
// triangle indices can be of 16 or 32 bits
if (mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES)
for (int32 i=0; i<indexBuffer.Num()/3; ++i)
{
PxU16 *Indices16 = (PxU16 *) mesh->getTriangles();
for (PxU32 i=0; i<mesh->getNbTriangles(); ++i)
{
// inverse order for left hand
f << "f " << Offset + Indices16[k+2] << " " << Offset + Indices16[k+1] << " " << Offset + Indices16[k] << "\n";
k += 3;
}
}
else
{
PxU32 *Indices32 = (PxU32 *) mesh->getTriangles();
for (PxU32 i=0; i<mesh->getNbTriangles(); ++i)
{
// inverse order for left hand
f << "f " << Offset + Indices32[k+2] << " " << Offset + Indices32[k+1] << " " << Offset + Indices32[k] << "\n";
k += 3;
}
// inverse order for left hand
f << "f " << Offset + indexBuffer[k+2] << " " << Offset + indexBuffer[k+1] << " " << Offset + indexBuffer[k] << "\n";
k += 3;
}
TotalVerticesAdded += nbVerts;
Offset += nbVerts;
Written = true;
}
};
if(ObjectName.Contains(TEXT("Road"))){
WriteComplexCollision();
if(!Written) WriteSimpleCollision();
if(!Written) WriteBoxCollision();
}
else
{
WriteSimpleCollision();
if(!Written) WriteBoxCollision();
if(!Written) WriteComplexCollision();
}
return TotalVerticesAdded;
#else
return 0;