« どうしてだろう… ThinkingParticlesが使えるのにC4D PythonでインストールチェックをするとFalseになる。 | トップページ | C4D ベジエNURBSの三角形? »

C4D Python R12 テスト:utils.GeRayColliderのGetIntersection()を少し確認

前回のGeRayCollider()の記事は、
http://villager-and-c4d.cocolog-nifty.com/blog/2011/07/c4d-python-r1-5.html

今回は、ほんの少し付けたし…

番号を指定して交点を取得するメソッドGetIntersection()の確認。

GeRayCollide.GetIntersection(number) #0<= number < GetIntersectionCount()

今回はこんな形のポリゴンオブジェクトを使って試した。

Geraycollider_07

交点は4つ有る。
ポリゴン番号:2/0/6/4が交差している。

前回のスクリプトを少々変更しました。
GetIntersection()メソッドの結果をコンソールに表示する部分で、distance/face_id/backfaceのみを表示します。

前回同様、ヌルオブジェクトには、ユーザデータの2つのリンクを取り付けてある。

Geraycollider_09

Python
import c4d
from c4d import utils


#オブジェクトのポイントをグローバル座標へ変換
def GetGlobalPoint(obj):
    if not isinstance(obj, c4d.PointObject):return

    mg = obj.GetMg()
    pnt = obj.GetAllPoints()
    pnt_cnt = obj.GetPointCount()

    for id in xrange(pnt_cnt):
        pnt[id] = mg.__mul__(pnt[id])

    return pnt


#グローバル座標リストをオブジェクトのローカル座標へ変換
def GetLocalPoint(pnt, obj):
    if not isinstance(obj, c4d.BaseObject):return
    if type(pnt) != list:return

    mg = obj.GetMg()
    inv_mg = mg.__invert__()

    for id in xrange(len(pnt)):
        pnt[id] = inv_mg.__mul__(pnt[id])

    return pnt



def main():
    try:
        ray = op[c4d.ID_USERDATA, 1]
        if not isinstance(ray, c4d.SplineObject):return
        obj = op[c4d.ID_USERDATA, 2]
        if not isinstance(obj, c4d.PolygonObject):return
    except:return

    if ray.GetPointCount() != 2:return #スプラインのポイントが2個以外終了
    if obj.GetPolygonCount() == 0:return #ポリゴンが1枚も無ければ終了

    #スプラインオブジェクトのポイントをローカル座標からグローバル座標へ
    pnt = GetGlobalPoint(ray)

    #グローバル座標からポリゴンオブジェクトのローカル座標へ
    pnt = GetLocalPoint(pnt, obj)

    #GeRayColliderの線分の開始位置と方向、長さを求める
    start_pos = pnt[0]
    direct = pnt[1] - pnt[0]
    length = direct.GetLength()

    #GeRayColliderの設定
    rc = utils.GeRayCollider()
    rc.Init(obj)
    rc.Intersect(start_pos, direct, length)

    #交点の数を表示
    is_cnt = rc.GetIntersectionCount()
    print is_cnt

    #交点の表示
    for id in xrange(is_cnt):
        print id, 'distance', rc.GetIntersection(id)['distance'], 'face_id', rc.GetIntersection(id)['face_id'], 'backface', rc.GetIntersection(id)['backface']

        #球体を交点に配置する
        Intersection_obj = c4d.BaseObject(c4d.Osphere)
        Intersection_obj.MakeTag(c4d.Tphong)
        Intersection_obj[c4d.PRIM_SPHERE_RAD] = obj.GetRad().GetLength() * 0.05
        Intersection_obj[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_ALWAYS
        Intersection_obj[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1.0, 0.0, 0.0)
        Intersection_obj.SetAbsPos(rc.GetIntersection(id)['hitpos'])
        Intersection_obj.InsertUnder(obj)


    #最後に線分の開始位置に最も近い交点を取得するメソッドを試してみる
    print 'Nearest', rc.GetNearestIntersection()


    print 'ok'



if __name__=='__main__':
    main()
    c4d.EventAdd()
4
0 distance 0.545229932317 face_id 0 backface True
1 distance 0.284898555051 face_id 2 backface False
2 distance 0.901950953106 face_id 4 backface True
3 distance 0.724379077185 face_id 6 backface False
Nearest {'tri_face_id': -3, 'distance': 0.28489855505143113, 's_normal': Vector(-87229.63, 0, 9007.407), 'backface': False, 'hitpos': Vector(-396.647, 0, -85.678), 'f_normal': Vector(-87229.63, 0, 9007.407), 'face_id': 2, 'barrycoords': Vector(0.298, 0.202, 0.5)}
ok

コンソールの結果は上。
交点は4個。
GetIntersection()メソッドの結果は、交点の近い順ではなくてface_id(ポリゴン番号)順らしいね。近い順で欲しい場合は、リストに格納してソートをする必要がある。

エディタビューの結果は下。

Geraycollider_08

backfaceは、ポリゴンの裏判定。

このポリゴンオブジェクトのポリゴンの法線は全て外向き。要するに外側が表という事だ。
間違えなく、ポリゴン番号2/6がFalse(裏ではない)で、ポリゴン番号0/4はTrue(裏である)なのだ。

さてここで、ちょっとした疑問が…
交点がポリゴンのポイントと交わっていたら、それは交点になるのか?

こんなモデルで試してみた。

Geraycollider_10

ポリゴン0の右上のポイントを通過し、ポリゴン7の上のエッジを通過。更にポリゴン6の左上のポイントを通過。

さてこれで、先ほどのスクリプトを実行すると…

Geraycollider_11

5
0 distance 0.551102103886 face_id 0 backface True
1 distance 0.29197855858 face_id 2 backface False
2 distance 0.89812431937 face_id 4 backface True
3 distance 0.710442207973 face_id 6 backface False
4 distance 0.710442207973 face_id 6 backface False
Nearest {'tri_face_id': -3, 'distance': 0.29197855858046268, 's_normal': Vector(-87229.63, 0, 9007.407), 'backface': False, 'hitpos': Vector(-387.8, 0, 0), 'f_normal': Vector(-87229.63, 0, 9007.407), 'face_id': 2, 'barrycoords': Vector(0.495, 0.005, 0.5)}
ok

交点は5個になりました。
どう言う訳か、ポリゴン7の交点は検出されず、ポリゴン6が2回検出されています。

もしも、ポリゴン7のようなエッジを通過しているポリゴンが検出されると、backfaceの判定が裏なのか?裏じゃないのか?どちらになるんだろうね…

とりあえず結果は、ポリゴンのポイントも交点に含まれると言う事だろうね。

|

« どうしてだろう… ThinkingParticlesが使えるのにC4D PythonでインストールチェックをするとFalseになる。 | トップページ | C4D ベジエNURBSの三角形? »

コメント

コメントを書く



(ウェブ上には掲載しません)




« どうしてだろう… ThinkingParticlesが使えるのにC4D PythonでインストールチェックをするとFalseになる。 | トップページ | C4D ベジエNURBSの三角形? »