I tried another pass where I increased the amount of spline point, but it still results in flipped forward vectors.
void UCannonSplineComponent::CreateSplineMeshesWithOffset()
{
const int32 NumSplinePoints = GetNumberOfSplinePoints();
if (IsValid(SplineMesh))
{
for (int32 i = 0; i < NumSplinePoints - 1; i++)
{
USplineMeshComponent* SplineMeshComponent = NewObject<USplineMeshComponent>(this);
SplineMeshComponent->SetMobility(EComponentMobility::Movable);
FVector StartPos, StartTangent, EndPos, EndTangent;
GetLocationAndTangentAtSplinePoint(i, StartPos, StartTangent, ESplineCoordinateSpace::Local);
GetLocationAndTangentAtSplinePoint(i + 1, EndPos, EndTangent, ESplineCoordinateSpace::Local);
// Apply the forward X offset only to the X component of the start and end positions
StartPos.X += ForwardOffset;
EndPos.X += ForwardOffset;
// Set the static mesh for this spline mesh component
SplineMeshComponent->SetStaticMesh(SplineMesh);
// Set the start and end positions for the spline mesh with the applied X offset
SplineMeshComponent->SetStartAndEnd(StartPos, StartTangent, EndPos, EndTangent);
SplineMeshComponent->SetForwardAxis(SplineForwardAxis, true);
if (SplineUpDirections.IsValidIndex(i))
{
SplineMeshComponent->SetSplineUpDir(SplineUpDirections[i], true);
}
else
{
SplineMeshComponent->SetSplineUpDir(SplineUpDir, true);
}
SplineMeshComponent->RegisterComponent();
SplineMeshComponent->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform);
// Add the spline mesh to the array for later reference
SplineMeshes.Add(SplineMeshComponent);
}
// Handle the case for a closed loop by connecting the last point to the first point
if (IsClosedLoop())
{
USplineMeshComponent* SplineMeshComponent = NewObject<USplineMeshComponent>(this);
SplineMeshComponent->SetMobility(EComponentMobility::Movable);
FVector StartPos, StartTangent, EndPos, EndTangent;
// Last spline point
GetLocationAndTangentAtSplinePoint(NumSplinePoints - 1, StartPos, StartTangent, ESplineCoordinateSpace::Local);
// First spline point (closing the loop)
GetLocationAndTangentAtSplinePoint(0, EndPos, EndTangent, ESplineCoordinateSpace::Local);
// Apply the forward X offset only to the X component of the start and end positions
StartPos.X += ForwardOffset;
EndPos.X += ForwardOffset;
// Set the static mesh for this spline mesh component
SplineMeshComponent->SetStaticMesh(SplineMesh);
// Set the start and end positions for the spline mesh with the applied X offset
SplineMeshComponent->SetStartAndEnd(StartPos, StartTangent, EndPos, EndTangent);
if (SplineUpDirections.IsValidIndex(NumSplinePoints - 1))
{
SplineMeshComponent->SetSplineUpDir(SplineUpDirections[NumSplinePoints - 1], true);
}
else
{
SplineMeshComponent->SetSplineUpDir(SplineUpDir, true);
}
SplineMeshComponent->RegisterComponent();
SplineMeshComponent->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform);
// Add the spline mesh to the array for later reference
SplineMeshes.Add(SplineMeshComponent);
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("SplineMesh is not set! Cannot create spline meshes."));
}
}
void UCannonSplineComponent::CreateCircleSplinePoints(USplineComponent* SplineComponent, float SplineRadius)
{
if (!SplineComponent) return;
// Clear existing spline points
SplineComponent->ClearSplinePoints(false);
// Add spline points in a circle, constrained to Y and Z axes, with tangents for a perfect circle
const int32 NumberOfPoints = 16; // Equivalent to the 16 points for a proper circle
const float AngleIncrement = 2.0f * PI / NumberOfPoints;
for (int32 i = 0; i < NumberOfPoints; ++i)
{
float Angle = i * AngleIncrement;
float Y = SplineRadius * FMath::Cos(Angle);
float Z = SplineRadius * FMath::Sin(Angle);
float X = 0.0f; // X remains constant
FVector Position(X, Y, Z);
FVector Tangent = FVector(0.0f, -SplineRadius * FMath::Sin(Angle), SplineRadius * FMath::Cos(Angle));
SplineComponent->AddSplinePoint(Position, ESplineCoordinateSpace::Local, true);
SplineComponent->SetTangentAtSplinePoint(i, Tangent, ESplineCoordinateSpace::Local, true);
}
SplineComponent->UpdateSpline();
}