The Shape

I was working on a project where I needed to arrange chairs around a pillar in a hotel or condo lobby. While I was contemplating the procedural layout, I thought it would be interesting to arrange objects based on various geometric shapes. I initially began with a circle and eventually developed concentric rings around a radius to create what could potentially be stadium seating.

 

Blueprint Node

Determined to streamline the process when it came to working in the blueprint graph, I created blueprint function library functions for different types of potential shapes, each with the appropriate structs for parameters that correspond to those shapes. I plan to encapsulate this functionality into a component where you can simply select the specific shape via an enumerator, and the relevant settings will be displayed accordingly. I intend to revisit this concept in the near future. The idea is to enable artists to add objects or actors to the world in the form of a 2D or 3D layout. Furthermore, artists will have the capability to add objects around specific vector points, but I’ll discuss that in more detail in a separate post.

For now this is the result that we’re shooting for.

 

  1. What are the uses
  2. Usage

Struct

USTRUCT(BlueprintType)
struct FCageVectorSphereParams
{
    GENERATED_BODY()
    UPROPERTY(BlueprintReadWrite, EditAnywhere)
    int32 LatitudeSegments;
    UPROPERTY(BlueprintReadWrite, EditAnywhere)
    int32 LongitudeSegments;
    UPROPERTY(BlueprintReadWrite, EditAnywhere)
    float Radius;
    UPROPERTY(BlueprintReadWrite, EditAnywhere)
    bool bTop;
    UPROPERTY(BlueprintReadWrite, EditAnywhere)
    bool bBottom;
};
/** Create Vector Sphere */
UFUNCTION(BlueprintCallable, BlueprintPure, meta=(DisplayName = "Create Vector Sphere"), Category="CageTools|Object Placement")
static TArray CreateVectorSphere(int32 LatitudeSegments, int32 LongitudeSegments, float Radius, bool bTop, bool bBottom);
}

C++

TArray UCageUtilities::CreateVectorSphere(int32 LatitudeSegments, int32 LongitudeSegments, float Radius, bool bTop, bool bBottom)
{
    TArray SphereTransforms;
    for (int32 lat = 0; lat <= LatitudeSegments; ++lat)
    {
        for (int32 lon = 0; lon <= LongitudeSegments; ++lon)
        {
            // Calculate the spherical coordinates
            float Theta = 2 * PI * float(lon) / float(LongitudeSegments);
            float Phi = PI * float(lat) / float(LatitudeSegments);
            // Convert to Cartesian coordinates
            float X = Radius * sin(Phi) * cos(Theta);
            float Y = Radius * sin(Phi) * sin(Theta);
            float Z = Radius * cos(Phi);
            FVector Vertex(X, Y, Z);
            if ((bTop && Vertex.Z >= 0.0f) || (bBottom && Vertex.Z <= 0.0f) || (!bTop && !bBottom))
            {
                // Create a transform with the forward vector pointing outward on the Z-axis
                FTransform Transform(FRotator(0.0f, 0.0f, 0.0f), Vertex);
                SphereTransforms.Add(Transform);
            }
        }
    }
    return SphereTransforms;
}
}