ハーフベクトルを計算する

ハーフベクトルを計算することで、進行方向に対してカーブが左右のどちら向きに膨らんでいるか(外向きか内向きか)を判定できる。

前後のポイント座標で計算する

//
// ハーフベクトルを計算する(外側のベクトル)
// Run Over: Primitives
//
float angleThreshold = 0.1; // 閾値(°)、この角度以下は直線と判定する

int pts[] = primpoints(0, @primnum);
for(int i = 1; i < len(pts)-1; i++)
{
    int next = (i + 1) % len(pts);
    int prev = i - 1;
        
    // p0----->p1<-----p2
    vector p0 = point(0, "P", pts[prev]);
    vector p1 = point(0, "P", pts[i]);
    vector p2 = point(0, "P", pts[next]);
    
    vector v0 = normalize(p1 - p0);
    vector v1 = normalize(p1 - p2);
    
    if(acos(dot(v0, v1*-1)) < radians(angleThreshold))
    {
        setpointattrib(0, "__h", pts[i], set(0,0,0));
    }
    else
    {
        vector h = v0 + v1;
        setpointattrib(0, "__h", pts[i], h);
    }
}

パラメトリックUVで計算する

前後のポイント座標ではなく、任意の距離のポリライン上の座標で計算する。この場合、入力するポリラインはResampleされている必要がある。

//
// ポリラインのハーフベクトルを計算する
// (ポリラインはResampleされていることが望ましい)
//
// Run Over: Primitives
//
float step = 5.0;   // 計測する幅

float angleThreshold = 0.1; // 閾値(°)、この角度以下は直線と判定する

float curveLength = primintrinsic(0, "measuredperimeter", @primnum);

int pts[] = primpoints(0, @primnum);
for(int i = 1; i < len(pts)-1; i++)
{
    vector pos = point(0, "P", pts[i]);
    int index;
    vector uv;
    xyzdist(0, pos, index, uv);
    
    // 端はクランプする
    float prevU = clamp(uv.x - (step / curveLength), 0, 1);
    float nextU = clamp(uv.x + (step / curveLength), 0, 1);
    
    vector p0 = primuv(0, "P", index, set(prevU, 0));
    vector p1 = point(0, "P", pts[i]);
    vector p2 = primuv(0, "P", index, set(nextU, 0));
        
    // p0----->p1<-----p2
    vector v0 = normalize(p1 - p0);
    vector v1 = normalize(p1 - p2);
    
    // 角度の確認
    //setpointattrib(0, "angle", pts[i], degrees(acos(dot(v0, v1*-1))));
    
    if(acos(dot(v0, v1*-1)) < radians(angleThreshold))
    {
        setpointattrib(0, "__h", pts[i], set(0,0,0));
    }
    else
    {
        vector h = (v0 + v1);
        setpointattrib(0, "__h", pts[i], h);
    }
}

進行方向のレフトベクトルとハーフベクトルの内積を取ることで、カーブのふくらみが右側か左側かを判別できる。

// レフトベクトルとハーフベクトルの内積で進行方向に対して右か左かを判別する
vector left = cross(@up, @N);
float d = dot(left, v@__h);

if(d > 0) @Cd = set(0,1,0.5);
else if(d < 0) @Cd = set(1,1,0);
タイトルとURLをコピーしました