Created
January 2, 2016 21:14
-
-
Save MyGodIsHe/7f17408e1d33110167d0 to your computer and use it in GitHub Desktop.
UE4 procedural transformation from cube to sphere
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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