Function convertToLinearSweptSphere
Synopsis
#include <Source/Falcor/Scene/Curves/CurveTessellation.h>
static SweptSphereResult convertToLinearSweptSphere(size_t strandCount, const int *vertexCountsPerStrand, const float3 *controlPoints, const float *widths, const float2 *UVs, uint32_t degree, uint32_t subdivPerSegment, const glm::mat4 &xform)
Description
Convert cubic B-splines to a couple of linear swept sphere segments.
- Parameters
[ in ]
strandCount
- Number of curve strands.[ in ]
vertexCountsPerStrand
- Number of control points per strand.[ in ]
controlPoints
- Array of control points.[ in ]
widths
- Array of curve widths, i.e., diameters of swept spheres.[ in ]
UVs
- Array of texture coordinates.[ in ]
degree
- Polynomial degree of strand (linear – cubic).[ in ]
subdivPerSegment
- Number of sub-segments within each cubic bspline segment (defined by 4 control points).[ in ]
xform
- Row-major 4x4 transformation matrix. We apply pre-transformation to curve geometry.- Returns
- Linear swept sphere segments.
Source
Lines 50-135 in Source/Falcor/Scene/Curves/CurveTessellation.cpp. Line 60 in Source/Falcor/Scene/Curves/CurveTessellation.h.
CurveTessellation::SweptSphereResult CurveTessellation::convertToLinearSweptSphere(size_t strandCount, const int* vertexCountsPerStrand, const float3* controlPoints, const float* widths, const float2* UVs, uint32_t degree, uint32_t subdivPerSegment, const glm::mat4& xform)
{
SweptSphereResult result;
// Only support linear tube segments now.
// TODO: Add quadratic or cubic tube segments if necessary.
assert(degree == 1);
result.degree = degree;
uint32_t pointCounts = 0;
uint32_t segCounts = 0;
for (uint32_t i = 0; i < strandCount; i++)
{
pointCounts += subdivPerSegment * (vertexCountsPerStrand[i] - 1) + 1;
segCounts += pointCounts - 1;
}
result.indices.reserve(segCounts);
result.points.reserve(pointCounts);
result.radius.reserve(pointCounts);
result.tangents.reserve(pointCounts);
result.normals.reserve(pointCounts);
result.texCrds.reserve(pointCounts);
uint32_t pointOffset = 0;
for (uint32_t i = 0; i < strandCount; i++)
{
CubicSpline strandPoints(controlPoints + pointOffset, vertexCountsPerStrand[i]);
CubicSpline strandWidths(widths + pointOffset, vertexCountsPerStrand[i]);
uint32_t resOffset = (uint32_t)result.points.size();
for (uint32_t j = 0; j < (uint32_t)vertexCountsPerStrand[i] - 1; j++)
{
for (uint32_t k = 0; k < subdivPerSegment; k++)
{
float t = (float)k / (float)subdivPerSegment;
result.indices.push_back((uint32_t)result.points.size());
// Pre-transform curve points.
float4 sph = transformSphere(xform, float4(strandPoints.interpolate(j, t), strandWidths.interpolate(j, t) * 0.5f));
result.points.push_back(sph.xyz);
result.radius.push_back(sph.w);
}
}
float4 sph = transformSphere(xform, float4(strandPoints.interpolate(vertexCountsPerStrand[i] - 2, 1.f), strandWidths.interpolate(vertexCountsPerStrand[i] - 2, 1.f) * 0.5f));
result.points.push_back(sph.xyz);
result.radius.push_back(sph.w);
// Compute tangents and normals.
for (uint32_t j = resOffset; j < result.points.size(); j++)
{
float3 fwd, s, t;
if (j < result.points.size() - 1)
{
fwd = normalize(result.points[j + 1] - result.points[j]);
}
else
{
fwd = normalize(result.points[j] - result.points[j - 1]);
}
buildFrame(fwd, s, t);
result.tangents.push_back(fwd);
result.normals.push_back(s);
}
// Texture coordinates.
if (UVs)
{
CubicSpline strandUVs(UVs + pointOffset, vertexCountsPerStrand[i]);
for (uint32_t j = 0; j < (uint32_t)vertexCountsPerStrand[i] - 1; j++)
{
for (uint32_t k = 0; k < subdivPerSegment; k++)
{
float t = (float)k / (float)subdivPerSegment;
result.texCrds.push_back(strandUVs.interpolate(j, t));
}
}
result.texCrds.push_back(strandUVs.interpolate(vertexCountsPerStrand[i] - 2, 1.f));
}
pointOffset += vertexCountsPerStrand[i];
}
return result;
}