UE4 CableMesh
UE4 CableComponent
生成绳索效果的Mesh。
基本思路
给定起始点内插一系列点,然后物理模拟调整点的位置,最后在点周围生成一系列三角网。
生成三角网的代码如下:
/** The vertex type used for dynamic meshes. */
struct FDynamicMeshVertex
{
FDynamicMeshVertex() {}
FDynamicMeshVertex( const FVector& InPosition ):
Position(InPosition),
TangentX(FVector(1,0,0)),
TangentZ(FVector(0,0,1)),
Color(FColor(255,255,255))
{
//..............................
}
FDynamicMeshVertex(const FVector& InPosition, const FVector2D& InTexCoord, const FColor& InColor) :
Position(InPosition),
TangentX(FVector(1, 0, 0)),
TangentZ(FVector(0, 0, 1)),
Color(InColor)
{
//...................................
}
FDynamicMeshVertex(const FVector& InPosition,const FVector& InTangentX,const FVector& InTangentZ,const FVector2D& InTexCoord, const FColor& InColor):
Position(InPosition),
TangentX(InTangentX),
TangentZ(InTangentZ),
Color(InColor)
{
//.......................
}
FDynamicMeshVertex(const FVector& InPosition, const FVector& LayerTexcoords, const FVector2D& WeightmapTexcoords)
: Position(InPosition)
, TangentX(FVector(1, 0, 0))
, TangentZ(FVector(0, 0, 1))
, Color(FColor::White)
{
//...............
}
//顶点位置
FVector Position;
//纹理坐标
FVector2D TextureCoordinate[MAX_STATIC_TEXCOORDS];
//切线
FPackedNormal TangentX;
//法线
FPackedNormal TangentZ;
FColor Color;
};
void BuildCableMesh(const TArray<FVector>& InPoints, TArray<FDynamicMeshVertex>& OutVertices, TArray<int32>& OutIndices)
{
const FColor VertexColor(255,255,255);
const int32 NumPoints = InPoints.Num();
const int32 SegmentCount = NumPoints-1;
// Build vertices
// We double up the first and last vert of the ring, because the UVs are different
int32 NumRingVerts = NumSides+1;
// For each point along spline..
for(int32 PointIdx=0; PointIdx<NumPoints; PointIdx++)
{
const float AlongFrac = (float)PointIdx/(float)SegmentCount; // Distance along cable
// Find direction of cable at this point, by averaging previous and next points
const int32 PrevIndex = FMath::Max(0, PointIdx-1);
const int32 NextIndex = FMath::Min(PointIdx+1, NumPoints-1);
const FVector ForwardDir = (InPoints[NextIndex] - InPoints[PrevIndex]).GetSafeNormal();
// Find quat from up (Z) vector to forward
const FQuat DeltaQuat = FQuat::FindBetween(FVector(0, 0, -1), ForwardDir);
// Apply quat orth vectors
const FVector RightDir = DeltaQuat.RotateVector(FVector(0, 1, 0));
const FVector UpDir = DeltaQuat.RotateVector(FVector(1, 0, 0));
// Generate a ring of verts
for(int32 VertIdx = 0; VertIdx<NumRingVerts; VertIdx++)
{
const float AroundFrac = float(VertIdx)/float(NumSides);
// Find angle around the ring
const float RadAngle = 2.f * PI * AroundFrac;
// Find direction from center of cable to this vertex
const FVector OutDir = (FMath::Cos(RadAngle) * UpDir) + (FMath::Sin(RadAngle) * RightDir);
FDynamicMeshVertex Vert;
Vert.Position = InPoints[PointIdx] + (OutDir * 0.5f * CableWidth);
Vert.TextureCoordinate[0] = FVector2D(AlongFrac * TileMaterial, AroundFrac);
Vert.Color = VertexColor;
Vert.SetTangents(ForwardDir, OutDir ^ ForwardDir, OutDir);
OutVertices.Add(Vert);
}
}
// Build triangles
for(int32 SegIdx=0; SegIdx<SegmentCount; SegIdx++)
{
for(int32 SideIdx=0; SideIdx<NumSides; SideIdx++)
{
int32 TL = GetVertIndex(SegIdx, SideIdx);
int32 BL = GetVertIndex(SegIdx, SideIdx+1);
int32 TR = GetVertIndex(SegIdx+1, SideIdx);
int32 BR = GetVertIndex(SegIdx+1, SideIdx+1);
OutIndices.Add(TL);
OutIndices.Add(BL);
OutIndices.Add(TR);
OutIndices.Add(TR);
OutIndices.Add(BL);
OutIndices.Add(BR);
}
}
}
网友评论