You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #rnx #jira none #preflight 60a7e75e7d6b060001c61f47 [CL 16428413 by Ryan Schmidt in ue5-main branch]
273 lines
9.5 KiB
C++
273 lines
9.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "MeshDescription.h"
|
|
#include "StaticMeshAttributes.h"
|
|
#include "Spatial/MeshAABBTree3.h"
|
|
#include "MeshAdapter.h"
|
|
|
|
|
|
/**
|
|
* Basic struct to adapt a FMeshDescription for use by GeometryProcessing classes that template the mesh type and expect a standard set of basic accessors
|
|
* For example, this adapter will let you use a FMeshDescription with GeometryProcessing's TMeshAABBTree3
|
|
* See also the Editable version below
|
|
*
|
|
* Usage example -- given some const FMeshDescription* Mesh:
|
|
* FMeshDescriptionAABBAdapter MeshAdapter(Mesh); // adapt the mesh
|
|
* TMeshAABBTree3<const FMeshDescriptionTriangleMeshAdapter> AABBTree(&MeshAdapter); // provide the adapter to a templated class like TMeshAABBTree3
|
|
*/
|
|
struct /*MESHCONVERSION_API*/ FMeshDescriptionTriangleMeshAdapter
|
|
{
|
|
using FIndex3i = UE::Geometry::FIndex3i;
|
|
protected:
|
|
const FMeshDescription* Mesh;
|
|
TVertexAttributesConstRef<FVector3f> VertexPositions;
|
|
TVertexInstanceAttributesConstRef<FVector3f> VertexInstanceNormals;
|
|
|
|
FVector3d BuildScale = FVector3d::One();
|
|
bool bScaleNormals = false;
|
|
|
|
public:
|
|
FMeshDescriptionTriangleMeshAdapter(const FMeshDescription* MeshIn) : Mesh(MeshIn)
|
|
{
|
|
FStaticMeshConstAttributes Attributes(*MeshIn);
|
|
VertexPositions = Attributes.GetVertexPositions();
|
|
VertexInstanceNormals = Attributes.GetVertexInstanceNormals();
|
|
// @todo: can we hold TArrayViews of the attribute arrays here? Do we guarantee not to mutate the mesh description for the duration of this object?
|
|
}
|
|
|
|
void SetBuildScale(const FVector3d& BuildScaleIn, bool bScaleNormalsIn)
|
|
{
|
|
BuildScale = BuildScaleIn;
|
|
bScaleNormals = bScaleNormalsIn;
|
|
}
|
|
|
|
bool IsTriangle(int32 TID) const
|
|
{
|
|
return TID >= 0 && TID < Mesh->Triangles().Num();
|
|
}
|
|
bool IsVertex(int32 VID) const
|
|
{
|
|
return VID >= 0 && VID < Mesh->Vertices().Num();
|
|
}
|
|
// ID and Count are the same for MeshDescription because it's compact
|
|
int32 MaxTriangleID() const
|
|
{
|
|
return Mesh->Triangles().Num();
|
|
}
|
|
int32 TriangleCount() const
|
|
{
|
|
return Mesh->Triangles().Num();
|
|
}
|
|
int32 MaxVertexID() const
|
|
{
|
|
return Mesh->Vertices().Num();
|
|
}
|
|
int32 VertexCount() const
|
|
{
|
|
return Mesh->Vertices().Num();
|
|
}
|
|
int32 GetShapeTimestamp() const
|
|
{
|
|
// MeshDescription doesn't provide any mechanism to know if it's been modified so just return 0
|
|
// and leave it to the caller to not build an aabb and then change the underlying mesh
|
|
return 0;
|
|
}
|
|
FIndex3i GetTriangle(int32 IDValue) const
|
|
{
|
|
TArrayView<const FVertexID> TriVertIDs = Mesh->GetTriangleVertices(FTriangleID(IDValue));
|
|
return FIndex3i(TriVertIDs[0].GetValue(), TriVertIDs[1].GetValue(), TriVertIDs[2].GetValue());
|
|
}
|
|
FVector3d GetVertex(int32 IDValue) const
|
|
{
|
|
const FVector& Position = VertexPositions[FVertexID(IDValue)];
|
|
return FVector3d(BuildScale.X * (double)Position.X, BuildScale.Y * (double)Position.Y, BuildScale.Z * (double)Position.Z);
|
|
}
|
|
|
|
inline void GetTriVertices(int32 IDValue, FVector3d& V0, FVector3d& V1, FVector3d& V2) const
|
|
{
|
|
TArrayView<const FVertexID> TriVertIDs = Mesh->GetTriangleVertices(FTriangleID(IDValue));
|
|
const FVector& A = VertexPositions[TriVertIDs[0]];
|
|
V0 = FVector3d(BuildScale.X * (double)A.X, BuildScale.Y * (double)A.Y, BuildScale.Z * (double)A.Z);
|
|
const FVector& B = VertexPositions[TriVertIDs[1]];
|
|
V1 = FVector3d(BuildScale.X * (double)B.X, BuildScale.Y * (double)B.Y, BuildScale.Z * (double)B.Z);
|
|
const FVector& C = VertexPositions[TriVertIDs[2]];
|
|
V2 = FVector3d(BuildScale.X * (double)C.X, BuildScale.Y * (double)C.Y, BuildScale.Z * (double)C.Z);
|
|
}
|
|
|
|
template<typename VectorType>
|
|
inline void GetTriVertices(int32 IDValue, VectorType& V0, VectorType& V1, VectorType& V2) const
|
|
{
|
|
TArrayView<const FVertexID> TriVertIDs = Mesh->GetTriangleVertices(FTriangleID(IDValue));
|
|
const FVector& A = VertexPositions[TriVertIDs[0]];
|
|
V0 = VectorType(BuildScale.X * (double)A.X, BuildScale.Y * (double)A.Y, BuildScale.Z * (double)A.Z);
|
|
const FVector& B = VertexPositions[TriVertIDs[1]];
|
|
V1 = VectorType(BuildScale.X * (double)B.X, BuildScale.Y * (double)B.Y, BuildScale.Z * (double)B.Z);
|
|
const FVector& C = VertexPositions[TriVertIDs[2]];
|
|
V2 = VectorType(BuildScale.X * (double)C.X, BuildScale.Y * (double)C.Y, BuildScale.Z * (double)C.Z);
|
|
}
|
|
|
|
inline bool HasNormals() const
|
|
{
|
|
return VertexInstanceNormals.IsValid();
|
|
}
|
|
inline bool IsNormal(int32 NID) const
|
|
{
|
|
return HasNormals() && NID >= 0 && NID < NormalCount();
|
|
}
|
|
inline int32 MaxNormalID() const
|
|
{
|
|
return HasNormals() ? VertexInstanceNormals.GetNumElements() : 0;
|
|
}
|
|
inline int32 NormalCount() const
|
|
{
|
|
return HasNormals() ? VertexInstanceNormals.GetNumElements() : 0;
|
|
}
|
|
FVector3f GetNormal(int32 IDValue) const
|
|
{
|
|
const FVector& InstanceNormal = VertexInstanceNormals[FVertexInstanceID(IDValue)];
|
|
return (!bScaleNormals) ? FVector3f(InstanceNormal) :
|
|
UE::Geometry::Normalized(FVector3f(InstanceNormal.X/BuildScale.X, InstanceNormal.Y/BuildScale.Y, InstanceNormal.Z/BuildScale.Z));
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Non-const version of the adapter, with non-const storage and setters
|
|
* TODO: try to be smarter about sharing code w/ the above const version
|
|
*/
|
|
struct /*MESHCONVERSION_API*/ FMeshDescriptionEditableTriangleMeshAdapter
|
|
{
|
|
using FIndex3i = UE::Geometry::FIndex3i;
|
|
protected:
|
|
FMeshDescription* Mesh;
|
|
TVertexAttributesRef<FVector3f> VertexPositions;
|
|
TVertexInstanceAttributesRef<FVector3f> VertexInstanceNormals;
|
|
|
|
public:
|
|
FMeshDescriptionEditableTriangleMeshAdapter(FMeshDescription* MeshIn) : Mesh(MeshIn)
|
|
{
|
|
FStaticMeshAttributes Attributes(*MeshIn);
|
|
VertexPositions = Attributes.GetVertexPositions();
|
|
VertexInstanceNormals = Attributes.GetVertexInstanceNormals();
|
|
}
|
|
|
|
bool IsTriangle(int32 TID) const
|
|
{
|
|
return TID >= 0 && TID < Mesh->Triangles().Num();
|
|
}
|
|
bool IsVertex(int32 VID) const
|
|
{
|
|
return VID >= 0 && VID < Mesh->Vertices().Num();
|
|
}
|
|
// ID and Count are the same for MeshDescription because it's compact
|
|
int32 MaxTriangleID() const
|
|
{
|
|
return Mesh->Triangles().Num();
|
|
}
|
|
int32 TriangleCount() const
|
|
{
|
|
return Mesh->Triangles().Num();
|
|
}
|
|
int32 MaxVertexID() const
|
|
{
|
|
return Mesh->Vertices().Num();
|
|
}
|
|
int32 VertexCount() const
|
|
{
|
|
return Mesh->Vertices().Num();
|
|
}
|
|
int32 GetShapeTimestamp() const
|
|
{
|
|
// MeshDescription doesn't provide any mechanism to know if it's been modified so just return 0
|
|
// and leave it to the caller to not build an aabb and then change the underlying mesh
|
|
return 0;
|
|
}
|
|
FIndex3i GetTriangle(int32 IDValue) const
|
|
{
|
|
TArrayView<const FVertexID> TriVertIDs = Mesh->GetTriangleVertices(FTriangleID(IDValue));
|
|
return FIndex3i(TriVertIDs[0].GetValue(), TriVertIDs[1].GetValue(), TriVertIDs[2].GetValue());
|
|
}
|
|
FVector3d GetVertex(int32 IDValue) const
|
|
{
|
|
return FVector3d(VertexPositions[FVertexID(IDValue)]);
|
|
}
|
|
void SetVertex(int32 IDValue, const FVector3d& NewPos)
|
|
{
|
|
VertexPositions[FVertexID(IDValue)] = (FVector)NewPos;
|
|
}
|
|
|
|
inline void GetTriVertices(int32 IDValue, FVector3d& V0, FVector3d& V1, FVector3d& V2) const
|
|
{
|
|
TArrayView<const FVertexID> TriVertIDs = Mesh->GetTriangleVertices(FTriangleID(IDValue));
|
|
V0 = FVector3d(VertexPositions[TriVertIDs[0]]);
|
|
V1 = FVector3d(VertexPositions[TriVertIDs[1]]);
|
|
V2 = FVector3d(VertexPositions[TriVertIDs[2]]);
|
|
}
|
|
|
|
|
|
inline bool HasNormals() const
|
|
{
|
|
return VertexInstanceNormals.IsValid();
|
|
}
|
|
inline bool IsNormal(int32 NID) const
|
|
{
|
|
return HasNormals() && NID >= 0 && NID < NormalCount();
|
|
}
|
|
inline int32 MaxNormalID() const
|
|
{
|
|
return HasNormals() ? VertexInstanceNormals.GetNumElements() : 0;
|
|
}
|
|
inline int32 NormalCount() const
|
|
{
|
|
return HasNormals() ? VertexInstanceNormals.GetNumElements() : 0;
|
|
}
|
|
FVector3f GetNormal(int32 IDValue) const
|
|
{
|
|
return FVector3f(VertexInstanceNormals[FVertexInstanceID(IDValue)]);
|
|
}
|
|
void SetNormal(int32 IDValue, const FVector3f& Normal)
|
|
{
|
|
VertexInstanceNormals[FVertexInstanceID(IDValue)] = (FVector)Normal;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* TTriangleMeshAdapter version of FMeshDescriptionTriangleMeshAdapter
|
|
*/
|
|
struct FMeshDescriptionMeshAdapterd : public UE::Geometry::TTriangleMeshAdapter<double>
|
|
{
|
|
FMeshDescriptionTriangleMeshAdapter ParentAdapter;
|
|
|
|
FMeshDescriptionMeshAdapterd(const FMeshDescription* MeshIn) : ParentAdapter(MeshIn)
|
|
{
|
|
IsTriangle = [&](int index) { return ParentAdapter.IsTriangle(index);};
|
|
IsVertex = [&](int index) { return ParentAdapter.IsVertex(index); };
|
|
MaxTriangleID = [&]() { return ParentAdapter.MaxTriangleID();};
|
|
MaxVertexID = [&]() { return ParentAdapter.MaxVertexID();};
|
|
TriangleCount = [&]() { return ParentAdapter.TriangleCount();};
|
|
VertexCount = [&]() { return ParentAdapter.VertexCount();};
|
|
GetShapeTimestamp = [&]() { return ParentAdapter.GetShapeTimestamp();};
|
|
GetTriangle = [&](int32 TriangleID) { return ParentAdapter.GetTriangle(TriangleID); };
|
|
GetVertex = [&](int32 VertexID) { return ParentAdapter.GetVertex(VertexID); };
|
|
}
|
|
|
|
FMeshDescriptionMeshAdapterd(FMeshDescriptionTriangleMeshAdapter ParentAdapterIn) : ParentAdapter(ParentAdapterIn)
|
|
{
|
|
IsTriangle = [&](int index) { return ParentAdapter.IsTriangle(index);};
|
|
IsVertex = [&](int index) { return ParentAdapter.IsVertex(index); };
|
|
MaxTriangleID = [&]() { return ParentAdapter.MaxTriangleID();};
|
|
MaxVertexID = [&]() { return ParentAdapter.MaxVertexID();};
|
|
TriangleCount = [&]() { return ParentAdapter.TriangleCount();};
|
|
VertexCount = [&]() { return ParentAdapter.VertexCount();};
|
|
GetShapeTimestamp = [&]() { return ParentAdapter.GetShapeTimestamp();};
|
|
GetTriangle = [&](int32 TriangleID) { return ParentAdapter.GetTriangle(TriangleID); };
|
|
GetVertex = [&](int32 VertexID) { return ParentAdapter.GetVertex(VertexID); };
|
|
}
|
|
|
|
};
|