XZ平面を基準としたポリラインに対して、進行ベクトルNとアップベクトルupを設定する。

ループしている場合の始点と終点
始点と終点が重なっている場合
16角形の円をつくる。インデックスは0~16で、0と16が同じ位置にある。
始点のインデックスは0で、終点は16。

int pts[] = primpoints(0, @primnum);
printf('pts[-1]:' + sprintf('%g', pts[-1]) + '\n');
printf('pts[-2]:' + sprintf('%g', pts[-2]) + '\n');
終点のインデックスは16でその一つ前は15になる。
始点と終点が結合している場合
Fuse SOPで始点と終点を結合すると、始点も終点もインデックスは0になる。

終点のインデックスは0でその一つ前は15になる。
First Edge
ポイントから次のポイントへのベクトルをNとする。upベクトルはNに直交させる。
//
// Custom Polyframe First Edge
// Run Over: Primitive
//
int pts[] = primpoints(0, @primnum);
vector start = point(0, "P", pts[0]);
vector end = point(0, "P", pts[-1]);
// ループフラグ
int isClosed = 0;
if(length(start - end) < 0.00001)
isClosed = 1;
for(int i = 0; i < len(pts); i++)
{
vector p0 = point(0, "P", pts[i]);
vector p1 = point(0, "P", pts[(i+1)%len(pts)]);
vector n = normalize(p1 - p0);
if(isClosed)
{
if(i == 0 || i == len(pts)-1)
{
// Two Edges
p0 = point(0, "P", pts[-2]);
p1 = point(0, "P", pts[0]);
vector p2 = point(0, "P", pts[1]);
n = normalize((p2 - p1) + (p1 - p0));
}
}
else
{
if(i == len(pts)-1)
{
p0 = point(0, "P", pts[i-1]);
p1 = point(0, "P", pts[i]);
n = normalize(p1 - p0);
}
}
// 始点または終点
if(i == 0 || i == len(pts)-1)
{
if(isClosed)
{
// Two Edges
p0 = point(0, "P", pts[-2]);
p1 = point(0, "P", pts[0]);
vector p2 = point(0, "P", pts[1]);
n = normalize((p2 - p1) + (p1 - p0));
}
}
vector up = set(0, 1, 0);
vector left = cross(up, n);
up = cross(n, left);
setpointattrib(0, "N", pts[i], n);
setpointattrib(0, "up", pts[i], up);
}
Two Edges
ポイントの乗っている2つのエッジの和をNとする。
始点と終点がFuseされている場合はインデックス[-1]のポイントは0になる。始点はインデックス[-2]のポイントを前のポイントとする必要がある。
//
// Custom Polyframe Two Edges
// Run Over: Primitive
//
int pts[] = primpoints(0, @primnum);
vector start = point(0, "P", pts[0]);
vector end = point(0, "P", pts[-1]);
// ループフラグ
int isClosed = 0;
if(length(start - end) < 0.00001)
isClosed = 1;
for(int i = 0; i < len(pts); i++)
{
vector p0 = point(0, "P", pts[i-1]);
vector p1 = point(0, "P", pts[i]);
vector p2 = point(0, "P", pts[(i+1)%len(pts)]);
// 始点または終点
if(i == 0 || i == len(pts)-1)
{
if(isClosed)
{
// Two Edges
p0 = point(0, "P", pts[-2]);
p1 = point(0, "P", pts[0]);
p2 = point(0, "P", pts[1]);
}
}
vector n = normalize((p2 - p1) + (p1 - p0));
vector up = set(0, 1, 0);
vector left = cross(up, n);
up = cross(n, left);
setpointattrib(0, "N", pts[i], n);
setpointattrib(0, "up", pts[i], up);
}