Skip to content

Instantly share code, notes, and snippets.

@MyGodIsHe
Created January 2, 2016 21:14
Show Gist options
  • Save MyGodIsHe/7f17408e1d33110167d0 to your computer and use it in GitHub Desktop.
Save MyGodIsHe/7f17408e1d33110167d0 to your computer and use it in GitHub Desktop.
UE4 procedural transformation from cube to sphere
void UExtendProceduralMeshLibrary::GenerateBoxMesh(FVector BoxSize, FIntVector BoxSegments, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FProcMeshTangent>& Tangents)
{
BoxSize.X = abs(BoxSize.X); // width
BoxSize.Y = abs(BoxSize.Y); // height
BoxSize.Z = abs(BoxSize.Z); // depth
BoxSegments.X = BoxSegments.X < 1 ? 1 : BoxSegments.X;
BoxSegments.Y = BoxSegments.Y < 1 ? 1 : BoxSegments.Y;
BoxSegments.Z = BoxSegments.Z < 1 ? 1 : BoxSegments.Z;
float width_half = BoxSize.X / 2;
float height_half = BoxSize.Y / 2;
float depth_half = BoxSize.Z / 2;
// Generate triangles (from quads)
Triangles.Reset();
int32 NumVerts;
{
int32 x = BoxSegments.X ;
int32 y = BoxSegments.Y;
int32 z = BoxSegments.Z;
NumVerts = (x * y + x * z + y * z) * 2 * 4; // 6 faces * segments * 4 verts
}
Vertices.Reset();
Vertices.AddUninitialized(NumVerts);
Normals.Reset();
Normals.AddUninitialized(NumVerts);
Tangents.Reset();
Tangents.AddUninitialized(NumVerts);
UVs.Reset();
UVs.AddUninitialized(NumVerts);
// Create Planes
struct Plane
{
Axis u;
Axis v;
Axis w;
float udir;
float vdir;
float width;
float height;
float depth;
};
Plane planes[]
{
{ Axis::Z, Axis::Y, Axis::X, -1.0, -1.0, BoxSize.Z, BoxSize.Y, width_half }, // px
{ Axis::Z, Axis::Y, Axis::X, 1.0, -1.0, BoxSize.Z, BoxSize.Y, -width_half }, // nx
{ Axis::X, Axis::Z, Axis::Y, 1.0, 1.0, BoxSize.X, BoxSize.Z, height_half }, // py
{ Axis::X, Axis::Z, Axis::Y, 1.0, -1.0, BoxSize.X, BoxSize.Z, -height_half }, // ny
{ Axis::X, Axis::Y, Axis::Z, 1.0, -1.0, BoxSize.X, BoxSize.Y, depth_half }, // pz
{ Axis::X, Axis::Y, Axis::Z, -1.0, -1.0, BoxSize.X, BoxSize.Y, -depth_half } // nz
};
int32 offset = 0;
for (int32 pi = 0; pi < 6; pi++)
{
Plane &plane = planes[pi];
int32 gridX = BoxSegments[static_cast<short>(plane.u)];
int32 gridY = BoxSegments[static_cast<short>(plane.v)];
float width_half = plane.width / 2.0;
float height_half = plane.height / 2.0;
int32 gridX1 = gridX + 1;
int32 gridY1 = gridY + 1;
float segment_width = plane.width / gridX;
float segment_height = plane.height / gridY;
FVector normal = FVector(0.0);
normal[static_cast<short>(plane.w)] = plane.depth > 0.0 ? 1.0 : -1.0;
// Generate verts
std::vector<FVector> BoxVerts;
{
BoxVerts.resize(gridY1 * gridX1);
for (int32 iy = 0; iy < gridY1; iy++)
{
for (int32 ix = 0; ix < gridX1; ix++)
{
FVector vector = FVector(0.0);
vector[static_cast<short>(plane.u)] = (ix * segment_width - width_half) * plane.udir;
vector[static_cast<short>(plane.v)] = (iy * segment_height - height_half) * plane.vdir;
vector[static_cast<short>(plane.w)] = plane.depth;
BoxVerts[ix + gridX1 * iy] = vector;
}
}
}
for (int32 iy = 0; iy < gridY; iy++)
{
for (int32 ix = 0; ix < gridX; ix++)
{
int32 oVC = (offset + ix + gridX * iy) * 4;
Vertices[oVC + 0] = BoxVerts[ix + gridX1 * iy];
Vertices[oVC + 1] = BoxVerts[ix + gridX1 * (iy + 1)];
Vertices[oVC + 2] = BoxVerts[(ix + 1) + gridX1 * (iy + 1)];
Vertices[oVC + 3] = BoxVerts[(ix + 1) + gridX1 * iy];
ConvertQuadToTriangles(Triangles, oVC + 3, oVC + 2, oVC + 1, oVC + 0);
Normals[oVC + 0] = Normals[oVC + 1] = Normals[oVC + 2] = Normals[oVC + 3] = normal;
FVector tangent = FVector(0.0);
tangent[static_cast<short>(plane.u)] = plane.udir;
Tangents[oVC + 0] = Tangents[oVC + 1] = Tangents[oVC + 2] = Tangents[oVC + 3] = FProcMeshTangent(tangent, false);
UVs[oVC + 0] = FVector2D(float(ix) / gridX, float(iy) / gridY);
UVs[oVC + 1] = FVector2D(float(ix) / gridX, float(iy + 1) / gridY);
UVs[oVC + 2] = FVector2D(float(ix + 1) / gridX, float(iy + 1) / gridY);
UVs[oVC + 3] = FVector2D(float(ix + 1) / gridX, float(iy) / gridY);
}
}
offset += gridX * gridY;
}
}
TArray<FVector> UExtendProceduralMeshLibrary::ConvertBoxToSphere(TArray<FVector> Vertices)
{
for (FVector &v : Vertices)
{
float x2 = v.X * v.X;
float y2 = v.Y * v.Y;
float z2 = v.Z * v.Z;
v.X *= sqrt(1 - y2 / 2 - z2 / 2 + y2 * z2 / 3);
v.Y *= sqrt(1 - z2 / 2 - x2 / 2 + z2 * x2 / 3);
v.Z *= sqrt(1 - x2 / 2 - y2 / 2 + x2 * y2 / 3);
}
return Vertices;
}
void UExtendProceduralMeshLibrary::Lerp(const TArray<FVector>& A, const TArray<FVector>& B, TArray<FVector>& ReturnValue, float Alpha)
{
ReturnValue.Reset();
int32 NumVerts = A.Num();
if (NumVerts > 0 && NumVerts == B.Num())
{
ReturnValue.AddUninitialized(NumVerts);
for (int32 i = 0; i < NumVerts; i++)
{
ReturnValue[i] = FMath::Lerp(A[i], B[i], Alpha);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment