You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#proj core #branch UE4 #summary Rename Trunc, Round, Floor, Ceil to TruncToInt, RoundToInt, FloorToInt, CeilToInt. Added *ToFloat versions. Repeated for FGenericPlatformMath and all derived classes for all platforms wherever applicable. Corrected comment in Fractional and added Frac() which does HLSL-style fractional (x - floor(x)). Checked for compilation on all projects (with cooking levels wherever applicable). Didn't change Fractional to Frac, this will be done in second commit. #codereview robert.manuszewski [CL 2064306 by Mikolaj Sieluzycki in Main branch]
670 lines
21 KiB
C++
670 lines
21 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Engine.h"
|
|
#include "RawMesh.h"
|
|
#include "MeshUtilities.h"
|
|
|
|
#include "MeshSimplify.h"
|
|
|
|
class FQuadricSimplifierMeshReductionModule : public IMeshReductionModule
|
|
{
|
|
public:
|
|
// IModuleInterface interface.
|
|
virtual void StartupModule() OVERRIDE;
|
|
virtual void ShutdownModule() OVERRIDE;
|
|
|
|
// IMeshReductionModule interface.
|
|
virtual class IMeshReduction* GetMeshReductionInterface() OVERRIDE;
|
|
virtual class IMeshMerging* GetMeshMergingInterface() OVERRIDE;
|
|
};
|
|
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogQuadricSimplifier, Log, All);
|
|
IMPLEMENT_MODULE(FQuadricSimplifierMeshReductionModule, MeshSimplify);
|
|
|
|
template< uint32 NumTexCoords >
|
|
class TVertSimp
|
|
{
|
|
typedef TVertSimp< NumTexCoords > VertType;
|
|
public:
|
|
FVector Position;
|
|
FVector Normal;
|
|
FVector Tangents[2];
|
|
FVector2D TexCoords[ NumTexCoords ];
|
|
|
|
FVector& GetPos() { return Position; }
|
|
const FVector& GetPos() const { return Position; }
|
|
float* GetAttributes() { return (float*)&Normal; }
|
|
const float* GetAttributes() const { return (const float*)&Normal; }
|
|
|
|
void Correct()
|
|
{
|
|
Normal.Normalize();
|
|
Tangents[0] = Tangents[0] - ( Tangents[0] * Normal ) * Normal;
|
|
Tangents[1] = Tangents[1] - ( Tangents[1] * Normal ) * Normal;
|
|
Tangents[0].Normalize();
|
|
Tangents[1].Normalize();
|
|
}
|
|
|
|
bool operator==( const VertType& a ) const
|
|
{
|
|
return Position == a.Position &&
|
|
Normal == a.Normal &&
|
|
Tangents[0] == a.Tangents[0] &&
|
|
Tangents[1] == a.Tangents[1] &&
|
|
TexCoords == a.TexCoords;
|
|
}
|
|
|
|
VertType operator+( const VertType& a ) const
|
|
{
|
|
VertType v;
|
|
v.Position = Position + a.Position;
|
|
v.Normal = Normal + a.Normal;
|
|
v.Tangents[0] = Tangents[0] + a.Tangents[0];
|
|
v.Tangents[1] = Tangents[1] + a.Tangents[1];
|
|
|
|
for( uint32 i = 0; i < NumTexCoords; i++ )
|
|
{
|
|
v.TexCoords[i] = TexCoords[i] + a.TexCoords[i];
|
|
}
|
|
return v;
|
|
}
|
|
|
|
VertType operator-( const VertType& a ) const
|
|
{
|
|
VertType v;
|
|
v.Position = Position - a.Position;
|
|
v.Normal = Normal - a.Normal;
|
|
v.Tangents[0] = Tangents[0] - a.Tangents[0];
|
|
v.Tangents[1] = Tangents[1] - a.Tangents[1];
|
|
|
|
for( uint32 i = 0; i < NumTexCoords; i++ )
|
|
{
|
|
v.TexCoords[i] = TexCoords[i] - a.TexCoords[i];
|
|
}
|
|
return v;
|
|
}
|
|
|
|
VertType operator*( const float a ) const
|
|
{
|
|
VertType v;
|
|
v.Position = Position * a;
|
|
v.Normal = Normal * a;
|
|
v.Tangents[0] = Tangents[0] * a;
|
|
v.Tangents[1] = Tangents[1] * a;
|
|
|
|
for( uint32 i = 0; i < NumTexCoords; i++ )
|
|
{
|
|
v.TexCoords[i] = TexCoords[i] * a;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
VertType operator/( const float a ) const
|
|
{
|
|
float ia = 1.0f / a;
|
|
return (*this) * ia;
|
|
}
|
|
};
|
|
|
|
class FQuadricSimplifierMeshReduction : public IMeshReduction
|
|
{
|
|
public:
|
|
virtual const FString& GetVersionString() const OVERRIDE
|
|
{
|
|
static FString Version = TEXT("1.0");
|
|
return Version;
|
|
}
|
|
|
|
virtual void Reduce(
|
|
FRawMesh& OutReducedMesh,
|
|
float& OutMaxDeviation,
|
|
const FRawMesh& InMesh,
|
|
const FMeshReductionSettings& InSettings
|
|
)
|
|
{
|
|
#if 0
|
|
TMap<int32,int32> FinalVerts;
|
|
TArray<int32> DupVerts;
|
|
int32 NumFaces = InMesh.WedgeIndices.Num() / 3;
|
|
|
|
// Process each face, build vertex buffer and per-section index buffers.
|
|
for(int32 FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++)
|
|
{
|
|
int32 VertexIndices[3];
|
|
FVector CornerPositions[3];
|
|
|
|
for (int32 CornerIndex = 0; CornerIndex < 3; CornerIndex++)
|
|
{
|
|
CornerPositions[CornerIndex] = InMesh.VertexPositions[ InMesh.WedgeIndices[ FaceIndex * 3 + CornerIndex ] ];
|
|
}
|
|
|
|
// Don't process degenerate triangles.
|
|
if( PointsEqual(CornerPositions[0],CornerPositions[1], ComparisonThreshold) ||
|
|
PointsEqual(CornerPositions[1],CornerPositions[2], ComparisonThreshold) ||
|
|
PointsEqual(CornerPositions[2],CornerPositions[0], ComparisonThreshold) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (int32 CornerIndex = 0; CornerIndex < 3; CornerIndex++)
|
|
{
|
|
int32 WedgeIndex = FaceIndex * 3 + CornerIndex;
|
|
FStaticMeshBuildVertex ThisVertex = BuildStaticMeshVertex(InMesh, WedgeIndex);
|
|
|
|
int32 Index = INDEX_NONE;
|
|
for (int32 k = 0; k < DupVerts.Num(); k++)
|
|
{
|
|
if (DupVerts[k] >= WedgeIndex)
|
|
{
|
|
// the verts beyond me haven't been placed yet, so these duplicates are not relevant
|
|
break;
|
|
}
|
|
|
|
int32 *Location = FinalVerts.Find(DupVerts[k]);
|
|
if (Location != NULL
|
|
&& AreVerticesEqual(ThisVertex, OutVertices[*Location], ComparisonThreshold))
|
|
{
|
|
Index = *Location;
|
|
break;
|
|
}
|
|
}
|
|
if (Index == INDEX_NONE)
|
|
{
|
|
Index = OutVertices.Add(ThisVertex);
|
|
FinalVerts.Add(WedgeIndex,Index);
|
|
}
|
|
VertexIndices[CornerIndex] = Index;
|
|
}
|
|
|
|
// Reject degenerate triangles.
|
|
if( VertexIndices[0] == VertexIndices[1] ||
|
|
VertexIndices[1] == VertexIndices[2] ||
|
|
VertexIndices[2] == VertexIndices[0] )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Put the indices in the material index buffer.
|
|
int32 SectionIndex = FMath::Clamp(RawMesh.FaceMaterialIndices[FaceIndex], 0, OutPerSectionIndices.Num());
|
|
TArray<uint32>& SectionIndices = OutPerSectionIndices[SectionIndex];
|
|
for (int32 CornerIndex = 0; CornerIndex < 3; CornerIndex++)
|
|
{
|
|
SectionIndices.Add(VertexIndices[CornerIndex]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
uint32 NumVerts = 0;
|
|
uint32 NumIndexes = 0;
|
|
|
|
TVertSimp<1>* Verts = new TVertSimp<1>[ NumVerts ];
|
|
|
|
|
|
#if 0
|
|
int32 NumVertices = InMesh.VertexPositions.Num();
|
|
int32 NumWedges = InMesh.WedgeIndices.Num();
|
|
int32 NumTris = NumWedges / 3;
|
|
|
|
if (NumWedges == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for(int32 TexCoordIndex = 0; TexCoordIndex < MAX_MESH_TEXTURE_COORDS; ++TexCoordIndex)
|
|
{
|
|
if (RawMesh.WedgeTexCoords[TexCoordIndex].Num() == NumWedges)
|
|
{
|
|
GeometryData->AddTexCoords(TexCoordIndex);
|
|
SimplygonSDK::spRealArray TexCoords = GeometryData->GetTexCoords(TexCoordIndex);
|
|
check(TexCoords->GetTupleSize() == 2);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
TexCoords->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTexCoords[TexCoordIndex][WedgeIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RawMesh.WedgeColors.Num() == NumWedges)
|
|
{
|
|
GeometryData->AddColors(0);
|
|
SimplygonSDK::spRealArray LinearColors = GeometryData->GetColors(0);
|
|
check(LinearColors);
|
|
check(LinearColors->GetTupleSize() == 4);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
FLinearColor LinearColor(RawMesh.WedgeColors[WedgeIndex]);
|
|
LinearColors->SetTuple(WedgeIndex, (float*)&LinearColor);
|
|
}
|
|
}
|
|
|
|
if (InMesh.WedgeTangentZ.Num() == NumWedges)
|
|
{
|
|
if (InMesh.WedgeTangentX.Num() == NumWedges && InMesh.WedgeTangentY.Num() == NumWedges)
|
|
{
|
|
GeometryData->AddTangents(0);
|
|
SimplygonSDK::spRealArray Tangents = GeometryData->GetTangents(0);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Tangents->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentX[WedgeIndex]);
|
|
}
|
|
|
|
GeometryData->AddBitangents(0);
|
|
SimplygonSDK::spRealArray Bitangents = GeometryData->GetBitangents(0);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Bitangents->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentY[WedgeIndex]);
|
|
}
|
|
}
|
|
GeometryData->AddNormals();
|
|
SimplygonSDK::spRealArray Normals = GeometryData->GetNormals();
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Normals->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentZ[WedgeIndex]);
|
|
}
|
|
}
|
|
|
|
// Per-triangle data.
|
|
/*for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
MaterialIndices->SetItem(TriIndex, RawMesh.FaceMaterialIndices[TriIndex]);
|
|
GroupIds->SetItem(TriIndex, RawMesh.FaceSmoothingMasks[TriIndex]);
|
|
}*/
|
|
|
|
for( uint32 i = 0; i < NumVerts; i++ )
|
|
{
|
|
Verts[i].Position = InMesh.VertexPositions[i];
|
|
Verts[i].TexCoords[0] = tri->verts[i].st;
|
|
Verts[i].Normal = tri->verts[i].normal;
|
|
Verts[i].Tangents[0] = tri->verts[i].tangents[0];
|
|
Verts[i].Tangents[1] = tri->verts[i].tangents[1];
|
|
}
|
|
|
|
for( uint32 i = 0; i < NumVerts; i++ )
|
|
{
|
|
Verts[i].Position.x = 0.0625f * FMath::RoundToFloat( 16.0f * Verts[i].Position.X );
|
|
Verts[i].Position.y = 0.0625f * FMath::RoundToFloat( 16.0f * Verts[i].Position.Y );
|
|
Verts[i].Position.z = 0.0625f * FMath::RoundToFloat( 16.0f * Verts[i].Position.Z );
|
|
}
|
|
|
|
for( uint32 i = 0; i < NumVerts; i++ )
|
|
{
|
|
Verts[i].Normal = InMesh.WedgeTangentZ[i];
|
|
Verts[i].Tangents[0] = tri->verts[i].tangents[0];
|
|
Verts[i].Tangents[1] = tri->verts[i].tangents[1];
|
|
}
|
|
#endif
|
|
|
|
uint32* Indexes = new uint32[ NumIndexes ];
|
|
|
|
for( uint32 i = 0; i < NumIndexes; i++ )
|
|
{
|
|
Indexes[i] = InMesh.WedgeIndices[i];
|
|
}
|
|
|
|
const uint32 NumAttributes = ( sizeof( TVertSimp<1> ) - sizeof( FVector ) ) / sizeof(float);
|
|
TMeshSimplifier< TVertSimp<1>, NumAttributes >* MeshSimp = new TMeshSimplifier< TVertSimp<1>, NumAttributes >( Verts, NumVerts, Indexes, NumIndexes );
|
|
|
|
const float AttributeWeights[] =
|
|
{
|
|
16.0f, 16.0f, 16.0f, // Normal
|
|
0.1f, 0.1f, 0.1f, // Tangent[0]
|
|
0.1f, 0.1f, 0.1f, // Tangent[1]
|
|
0.5f, 0.5f, // TexCoord[0]
|
|
0.5f, 0.5f, // TexCoord[1]
|
|
0.5f, 0.5f, // TexCoord[2]
|
|
0.5f, 0.5f // TexCoord[3]
|
|
};
|
|
|
|
MeshSimp->SetAttributeWeights( AttributeWeights );
|
|
MeshSimp->SetBoundaryLocked();
|
|
MeshSimp->InitCosts();
|
|
|
|
int32 NumTris = NumIndexes / 3;
|
|
|
|
MeshSimp->SimplifyMesh( 200000.0f, NumTris * InSettings.PercentTriangles );
|
|
|
|
NumVerts = MeshSimp->GetNumVerts();
|
|
NumIndexes = MeshSimp->GetNumTris() * 3;
|
|
|
|
MeshSimp->OutputMesh( Verts, Indexes );
|
|
delete MeshSimp;
|
|
|
|
delete[] Verts;
|
|
delete[] Indexes;
|
|
|
|
// CreateRawMeshFromGeometry(OutReducedMesh, GeometryData, WINDING_Keep);
|
|
// OutMaxDeviation = ReductionProcessor->GetMaxDeviation();
|
|
}
|
|
|
|
virtual bool ReduceSkeletalMesh(
|
|
USkeletalMesh* SkeletalMesh,
|
|
int32 LODIndex,
|
|
const FSkeletalMeshOptimizationSettings& Settings,
|
|
bool bCalcLODDistance
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual bool IsSupported() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static FQuadricSimplifierMeshReduction* Create()
|
|
{
|
|
return new FQuadricSimplifierMeshReduction;
|
|
}
|
|
|
|
private:
|
|
#if 0
|
|
SimplygonSDK::spGeometryData CreateGeometryFromRawMesh(const FRawMesh& RawMesh)
|
|
{
|
|
int32 NumVertices = RawMesh.VertexPositions.Num();
|
|
int32 NumWedges = RawMesh.WedgeIndices.Num();
|
|
int32 NumTris = NumWedges / 3;
|
|
|
|
if (NumWedges == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SimplygonSDK::spGeometryData GeometryData = SDK->CreateGeometryData();
|
|
GeometryData->SetVertexCount(NumVertices);
|
|
GeometryData->SetTriangleCount(NumTris);
|
|
|
|
SimplygonSDK::spRealArray Positions = GeometryData->GetCoords();
|
|
for (int32 VertexIndex = 0; VertexIndex < NumVertices; ++VertexIndex)
|
|
{
|
|
Positions->SetTuple(VertexIndex, (float*)&RawMesh.VertexPositions[VertexIndex]);
|
|
}
|
|
|
|
SimplygonSDK::spRidArray Indices = GeometryData->GetVertexIds();
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Indices->SetItem(WedgeIndex, RawMesh.WedgeIndices[WedgeIndex]);
|
|
}
|
|
|
|
for(int32 TexCoordIndex = 0; TexCoordIndex < MAX_MESH_TEXTURE_COORDS; ++TexCoordIndex)
|
|
{
|
|
if (RawMesh.WedgeTexCoords[TexCoordIndex].Num() == NumWedges)
|
|
{
|
|
GeometryData->AddTexCoords(TexCoordIndex);
|
|
SimplygonSDK::spRealArray TexCoords = GeometryData->GetTexCoords(TexCoordIndex);
|
|
check(TexCoords->GetTupleSize() == 2);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
TexCoords->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTexCoords[TexCoordIndex][WedgeIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RawMesh.WedgeColors.Num() == NumWedges)
|
|
{
|
|
GeometryData->AddColors(0);
|
|
SimplygonSDK::spRealArray LinearColors = GeometryData->GetColors(0);
|
|
check(LinearColors);
|
|
check(LinearColors->GetTupleSize() == 4);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
FLinearColor LinearColor(RawMesh.WedgeColors[WedgeIndex]);
|
|
LinearColors->SetTuple(WedgeIndex, (float*)&LinearColor);
|
|
}
|
|
}
|
|
|
|
if (RawMesh.WedgeTangentZ.Num() == NumWedges)
|
|
{
|
|
if (RawMesh.WedgeTangentX.Num() == NumWedges && RawMesh.WedgeTangentY.Num() == NumWedges)
|
|
{
|
|
GeometryData->AddTangents(0);
|
|
SimplygonSDK::spRealArray Tangents = GeometryData->GetTangents(0);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Tangents->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentX[WedgeIndex]);
|
|
}
|
|
|
|
GeometryData->AddBitangents(0);
|
|
SimplygonSDK::spRealArray Bitangents = GeometryData->GetBitangents(0);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Bitangents->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentY[WedgeIndex]);
|
|
}
|
|
}
|
|
GeometryData->AddNormals();
|
|
SimplygonSDK::spRealArray Normals = GeometryData->GetNormals();
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Normals->SetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentZ[WedgeIndex]);
|
|
}
|
|
}
|
|
|
|
// Per-triangle data.
|
|
GeometryData->AddMaterialIds();
|
|
SimplygonSDK::spRidArray MaterialIndices = GeometryData->GetMaterialIds();
|
|
for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
MaterialIndices->SetItem(TriIndex, RawMesh.FaceMaterialIndices[TriIndex]);
|
|
}
|
|
|
|
GeometryData->AddGroupIds();
|
|
SimplygonSDK::spRidArray GroupIds = GeometryData->GetGroupIds();
|
|
for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
GroupIds->SetItem(TriIndex, RawMesh.FaceSmoothingMasks[TriIndex]);
|
|
}
|
|
|
|
return GeometryData;
|
|
}
|
|
|
|
void CreateRawMeshFromGeometry(FRawMesh& OutRawMesh, const SimplygonSDK::spGeometryData& GeometryData, EWindingMode WindingMode)
|
|
{
|
|
check(GeometryData);
|
|
|
|
SimplygonSDK::spRealArray Positions = GeometryData->GetCoords();
|
|
SimplygonSDK::spRidArray Indices = GeometryData->GetVertexIds();
|
|
SimplygonSDK::spRidArray MaterialIndices = GeometryData->GetMaterialIds();
|
|
SimplygonSDK::spRidArray GroupIds = GeometryData->GetGroupIds();
|
|
SimplygonSDK::spRealArray LinearColors = GeometryData->GetColors(0);
|
|
SimplygonSDK::spRealArray Normals = GeometryData->GetNormals();
|
|
SimplygonSDK::spRealArray Tangents = GeometryData->GetTangents(0);
|
|
SimplygonSDK::spRealArray Bitangents = GeometryData->GetBitangents(0);
|
|
|
|
check(Positions);
|
|
check(Indices);
|
|
|
|
FRawMesh& RawMesh = OutRawMesh;
|
|
const bool bReverseWinding = (WindingMode == WINDING_Reverse);
|
|
int32 NumTris = GeometryData->GetTriangleCount();
|
|
int32 NumWedges = NumTris * 3;
|
|
int32 NumVertices = GeometryData->GetVertexCount();
|
|
|
|
RawMesh.VertexPositions.Empty(NumVertices);
|
|
RawMesh.VertexPositions.AddUninitialized(NumVertices);
|
|
for (int32 VertexIndex = 0; VertexIndex < NumVertices; ++VertexIndex)
|
|
{
|
|
Positions->GetTuple(VertexIndex, (float*)&RawMesh.VertexPositions[VertexIndex]);
|
|
}
|
|
|
|
RawMesh.WedgeIndices.Empty(NumWedges);
|
|
RawMesh.WedgeIndices.AddUninitialized(NumWedges);
|
|
for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
for (int32 CornerIndex = 0; CornerIndex < 3; ++CornerIndex)
|
|
{
|
|
const uint32 DestIndex = bReverseWinding ? (2 - CornerIndex) : CornerIndex;
|
|
RawMesh.WedgeIndices[TriIndex * 3 + DestIndex] = Indices->GetItem(TriIndex * 3 + CornerIndex);
|
|
}
|
|
}
|
|
|
|
for(int32 TexCoordIndex = 0; TexCoordIndex < MAX_MESH_TEXTURE_COORDS; ++TexCoordIndex)
|
|
{
|
|
SimplygonSDK::spRealArray TexCoords = GeometryData->GetTexCoords(TexCoordIndex);
|
|
if (TexCoords)
|
|
{
|
|
RawMesh.WedgeTexCoords[TexCoordIndex].Empty(NumWedges);
|
|
RawMesh.WedgeTexCoords[TexCoordIndex].AddUninitialized(NumWedges);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
TexCoords->GetTuple(WedgeIndex, (float*)&RawMesh.WedgeTexCoords[TexCoordIndex][WedgeIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (LinearColors)
|
|
{
|
|
RawMesh.WedgeColors.Empty(NumWedges);
|
|
RawMesh.WedgeColors.AddUninitialized(NumWedges);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
FLinearColor LinearColor;
|
|
LinearColors->GetTuple(WedgeIndex, (float*)&LinearColor);
|
|
RawMesh.WedgeColors[WedgeIndex] = LinearColor.ToFColor(true);
|
|
}
|
|
}
|
|
|
|
if (Normals)
|
|
{
|
|
if (Tangents && Bitangents)
|
|
{
|
|
RawMesh.WedgeTangentX.Empty(NumWedges);
|
|
RawMesh.WedgeTangentX.AddUninitialized(NumWedges);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Tangents->GetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentX[WedgeIndex]);
|
|
}
|
|
|
|
RawMesh.WedgeTangentY.Empty(NumWedges);
|
|
RawMesh.WedgeTangentY.AddUninitialized(NumWedges);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Bitangents->GetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentY[WedgeIndex]);
|
|
}
|
|
}
|
|
|
|
RawMesh.WedgeTangentZ.Empty(NumWedges);
|
|
RawMesh.WedgeTangentZ.AddUninitialized(NumWedges);
|
|
for (int32 WedgeIndex = 0; WedgeIndex < NumWedges; ++WedgeIndex)
|
|
{
|
|
Normals->GetTuple(WedgeIndex, (float*)&RawMesh.WedgeTangentZ[WedgeIndex]);
|
|
if (!bReverseWinding)
|
|
{
|
|
RawMesh.WedgeTangentZ[WedgeIndex] = (-RawMesh.WedgeTangentZ[WedgeIndex]).SafeNormal();
|
|
}
|
|
}
|
|
}
|
|
|
|
RawMesh.FaceMaterialIndices.Empty(NumTris);
|
|
RawMesh.FaceMaterialIndices.AddZeroed(NumTris);
|
|
if (MaterialIndices)
|
|
{
|
|
for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
RawMesh.FaceMaterialIndices[TriIndex] = MaterialIndices->GetItem(TriIndex);
|
|
}
|
|
}
|
|
|
|
RawMesh.FaceSmoothingMasks.Empty(NumTris);
|
|
RawMesh.FaceSmoothingMasks.AddZeroed(NumTris);
|
|
if (GroupIds)
|
|
{
|
|
for (int32 TriIndex = 0; TriIndex < NumTris; ++TriIndex)
|
|
{
|
|
RawMesh.FaceSmoothingMasks[TriIndex] = GroupIds->GetItem(TriIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetReductionSettings(SimplygonSDK::spReductionSettings ReductionSettings, const FMeshReductionSettings& Settings, int32 NumTris)
|
|
{
|
|
float MaxDeviation = Settings.MaxDeviation > 0.0f ? Settings.MaxDeviation : FLT_MAX;
|
|
float MinReductionRatio = FMath::Max<float>(1.0f / NumTris, 0.05f);
|
|
float MaxReductionRatio = (Settings.MaxDeviation > 0.0f && Settings.PercentTriangles == 1.0f) ? MinReductionRatio : 1.0f;
|
|
float ReductionRatio = FMath::Clamp(Settings.PercentTriangles, MinReductionRatio, MaxReductionRatio);
|
|
|
|
unsigned int FeatureFlagsMask = SimplygonSDK::SG_FEATUREFLAGS_GROUP;
|
|
if (Settings.TextureImportance != EMeshFeatureImportance::Off)
|
|
{
|
|
FeatureFlagsMask |= (SimplygonSDK::SG_FEATUREFLAGS_TEXTURE0 | SimplygonSDK::SG_FEATUREFLAGS_MATERIAL);
|
|
}
|
|
if (Settings.ShadingImportance != EMeshFeatureImportance::Off)
|
|
{
|
|
FeatureFlagsMask |= SimplygonSDK::SG_FEATUREFLAGS_SHADING;
|
|
}
|
|
|
|
const float ImportanceTable[] =
|
|
{
|
|
0.0f, // OFF
|
|
0.125f, // Lowest
|
|
0.35f, // Low,
|
|
1.0f, // Normal
|
|
2.8f, // High
|
|
8.0f, // Highest
|
|
};
|
|
|
|
checkAtCompileTime( ARRAY_COUNT( ImportanceTable ) == (EMeshFeatureImportance::Highest+1), ImportanceTableSizeMismatch ); // -1 because of TEMP_BROKEN(?)
|
|
check(Settings.SilhouetteImportance < EMeshFeatureImportance::Highest+1); // -1 because of TEMP_BROKEN(?)
|
|
check(Settings.TextureImportance < EMeshFeatureImportance::Highest+1); // -1 because of TEMP_BROKEN(?)
|
|
check(Settings.ShadingImportance < EMeshFeatureImportance::Highest+1); // -1 because of TEMP_BROKEN(?)
|
|
|
|
ReductionSettings->SetFeatureFlags(FeatureFlagsMask);
|
|
ReductionSettings->SetMaxDeviation(MaxDeviation);
|
|
ReductionSettings->SetReductionRatio(ReductionRatio);
|
|
ReductionSettings->SetGeometryImportance(ImportanceTable[Settings.SilhouetteImportance]);
|
|
ReductionSettings->SetTextureImportance(ImportanceTable[Settings.TextureImportance]);
|
|
ReductionSettings->SetMaterialImportance(ImportanceTable[Settings.TextureImportance]);
|
|
ReductionSettings->SetShadingImportance( ImportanceTable[Settings.ShadingImportance]);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Calculates the view distance that a mesh should be displayed at.
|
|
* @param MaxDeviation - The maximum surface-deviation between the reduced geometry and the original. This value should be acquired from Simplygon
|
|
* @returns The calculated view distance
|
|
*/
|
|
float CalculateViewDistance( float MaxDeviation )
|
|
{
|
|
// We want to solve for the depth in world space given the screen space distance between two pixels
|
|
//
|
|
// Assumptions:
|
|
// 1. There is no scaling in the view matrix.
|
|
// 2. The horizontal FOV is 90 degrees.
|
|
// 3. The backbuffer is 1920x1080.
|
|
//
|
|
// If we project two points at (X,Y,Z) and (X',Y,Z) from view space, we get their screen
|
|
// space positions: (X/Z, Y'/Z) and (X'/Z, Y'/Z) where Y' = Y * AspectRatio.
|
|
//
|
|
// The distance in screen space is then sqrt( (X'-X)^2/Z^2 + (Y'-Y')^2/Z^2 )
|
|
// or (X'-X)/Z. This is in clip space, so PixelDist = 1280 * 0.5 * (X'-X)/Z.
|
|
//
|
|
// Solving for Z: ViewDist = (X'-X * 640) / PixelDist
|
|
|
|
const float ViewDistance = (MaxDeviation * 960.0f);
|
|
return ViewDistance;
|
|
}
|
|
};
|
|
TScopedPointer<FQuadricSimplifierMeshReduction> GQuadricSimplifierMeshReduction;
|
|
|
|
void FQuadricSimplifierMeshReductionModule::StartupModule()
|
|
{
|
|
GQuadricSimplifierMeshReduction = FQuadricSimplifierMeshReduction::Create();
|
|
}
|
|
|
|
void FQuadricSimplifierMeshReductionModule::ShutdownModule()
|
|
{
|
|
GQuadricSimplifierMeshReduction = NULL;
|
|
}
|
|
|
|
IMeshReduction* FQuadricSimplifierMeshReductionModule::GetMeshReductionInterface()
|
|
{
|
|
return GQuadricSimplifierMeshReduction;
|
|
}
|
|
|
|
IMeshMerging* FQuadricSimplifierMeshReductionModule::GetMeshMergingInterface()
|
|
{
|
|
return NULL;
|
|
}
|