SplineMeshComponentでSetStartAndEndを使う際のパラメータの求め方について

以下のようなコードでMeshの長さをあまり大きく変えないようにSplineMeshを作成しようとしています。

もととなるスプラインのポイントの間隔がメッシュに比べて大きい場合は複数に分割するようにしています。

GetTangentAtDistanceAlongSplineで求めたタンジェントにDivLengthをかけているのはネットでそのような例を見かけたからなのですが、正しいやり方ではないのかもとのスプラインと生成されたメッシュが微妙にずれてしまいます。

そこで質問なのですが、こういう場合のSetStartAndEndに渡すタンジェントの値はどのように求めればよいのでしょうか?

<br/>

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

{

for (int j = 0; j < Spline->GetNumberOfSplinePoints()-1; ++j) {

float d0 = Spline->GetDistanceAlongSplineAtSplinePoint(j);

float d1 = Spline->GetDistanceAlongSplineAtSplinePoint(j+1);

float d = d1 - d0;

int DivNum = FMath::RoundToInt(d / MeshLength);

if (DivNum <= 0) DivNum = 1;

float DivLength = d / DivNum;

TArray<UPrimitiveComponent*> SplineMeshes;

for (int i = 0; i < DivNum; ++i) {

USplineMeshComponent* SplineMesh = Cast< USplineMeshComponent >(UElpisEditorUtilityFunction::AddSceneComponent(this->RootComponent, USplineMeshComponent::StaticClass()));

SplineMesh->SetForwardAxis(ESplineMeshAxis::X);

SplineMesh->SetStaticMesh(GrindActor->GetSplineMeshObject());

FVector StartPos = Spline->GetLocationAtDistanceAlongSpline(d0+DivLength * i, ESplineCoordinateSpace::Local);

FVector StartTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * i, ESplineCoordinateSpace::Local).GetSafeNormal()* DivLength;

FVector EndPos = Spline->GetLocationAtDistanceAlongSpline(d0+DivLength * (i + 1), ESplineCoordinateSpace::Local);

FVector EndTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * (i + 1), ESplineCoordinateSpace::Local).GetSafeNormal()* DivLength;

SplineMesh->SetStartAndEnd(StartPos, StartTan, EndPos, EndTan);

<br/>

SplineMeshes.Add(SplineMesh);

}

}

}

お世話になっております。

本件ですが

頂いたソースコードを使用させて頂き実装をしてみた所、ズレる等の事象は確認されませんでした。

こちら再現可能なプロジェクトを用意して頂く事は可能でしょうか?

大変お手数おかけしますが、ご確認の方何卒よろしくお願い申し上げます。

お世話になっております。

こちら再現可能なプロジェクトをUE5.6環境でBPで作成しなおしてみたのですが、どのようにお渡しすればよろしいでしょうか?

[Image Removed]

お世話になっております。

プロジェクトを圧縮したzipファイルをアップロードさせていただきました。

BPのUpdateMeshを実行していただければメッシュが作成されます

よろしくお願いします

[Image Removed]

確認ありがとうございます。

お渡ししたプロジェクトだとMeshLengthの値が1600と比較的大きな値となっているため、Normalizeせずにそのままの値を使用するとずれが小さくなるですが、MeshLengthの値を100などある程度小さな値にするとNormalizeしてDivLengthをかけたほうがずれが小さくなります。

添付した画像はMeshLengthの値を100でTangentの値はそのままのものを使用したものです

MeshLengthの値は使用される場面(使用したいメッシュ)によりますので、どちらのケースでもうまく処理できる計算式を知りたいという感じです。

よろしくお願いします

[Image Removed]

お世話になっております。

提示していただいたコードを参考に修正したところ、ずれが発生しなくなりました。

とても助かりました。

ありがとうございます

お世話になっております。

ご協力頂きありがとうございます。

プロジェクトを圧縮して頂いて本ページに添付して頂ければと存じます。

圧縮方法および圧縮の際のトラブルシューティングの記事は下記になります。

https://ue5study.com/how/ue5\-packaging\-error\-windows/

お世話になっております。

こちら確認させて頂きました。

BP_SplineTestのUpdateMesh関数内のローカル変数

StartTanとEndTanの解を求める計算で

GetTangentAtDistanceAlongSplineの戻り値をNormalizeせずそのまま代入したらズレは生じなくなりました。

従ってC++は

FVector StartTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * i, ESplineCoordinateSpace::Local).GetSafeNormal()* DivLength;

の実装ではなく

FVector StartTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * i, ESplineCoordinateSpace::Local);

になります。

参考に画像の方を添付させて頂きます。

[Image Removed]お手数をおかけしますがご確認の方何卒よろしくお願い申し上げます。

お世話になっております。

媒介変数(Time)の変化量がスプラインの切片と生成される SplineMeshComponent とで異なるため、これに応じた Tangent の補正が必要です。

最初に添付して頂いたコードを元にサンプルを作成しました。

必要な変更を行った部分に //+ としてコメントしてあります。

他にも少し変更点がありますが、それらはこちらで動作させるために調整した部分ですので気にしなくても大丈夫です。

また、C++ で記述しましたが BP でも同等の処理は可能です。

`{
const int NumSegments = Spline->GetNumberOfSplineSegments(); //+

for (int j = 0; j < Spline->GetNumberOfSplinePoints() - 1; ++j)
{
float d0 = Spline->GetDistanceAlongSplineAtSplinePoint(j);
float d1 = Spline->GetDistanceAlongSplineAtSplinePoint(j + 1);
float d = d1 - d0;
int DivNum = FMath::RoundToInt(d / MeshLength);
if (DivNum <= 0) DivNum = 1;
float DivLength = d / DivNum;
TArray<UPrimitiveComponent*> SplineMeshes;
for (int i = 0; i < DivNum; ++i)
{
USplineMeshComponent* SplineMesh = NewObject(this);// Cast< USplineMeshComponent >(UElpisEditorUtilityFunction::AddSceneComponent(this->RootComponent, USplineMeshComponent::StaticClass()));
SplineMesh->SetupAttachment(RootComponent);
SplineMesh->RegisterComponent();

SplineMesh->SetForwardAxis(ESplineMeshAxis::X);
SplineMesh->SetStaticMesh(SplineMeshObject);

//+ 切片中における Time の変化量(DeltaT)を算出
float StartT = Spline->GetTimeAtDistanceAlongSpline(d0 + DivLength * i);
float EndT = Spline->GetTimeAtDistanceAlongSpline(d0 + DivLength * (i + 1));
float DeltaT = EndT - StartT;

FVector StartPos = Spline->GetLocationAtDistanceAlongSpline(d0 + DivLength * i, ESplineCoordinateSpace::Local);
FVector StartTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * i, ESplineCoordinateSpace::Local) * DeltaT * NumSegments; //+ 末尾の係数が変わっています
FVector EndPos = Spline->GetLocationAtDistanceAlongSpline(d0 + DivLength * (i + 1), ESplineCoordinateSpace::Local);
FVector EndTan = Spline->GetTangentAtDistanceAlongSpline(d0 + DivLength * (i + 1), ESplineCoordinateSpace::Local) * DeltaT * NumSegments; //+ 末尾の係数が変わっています
SplineMesh->SetStartAndEnd(StartPos, StartTan, EndPos, EndTan);
SplineMeshes.Add(SplineMesh);
}
}
}`

よろしくお願いいたします。

ご確認ありがとうございます。

本件はクローズいたします。

また何かありましたらお問い合わせ下さい。