多面体による球近似

正20面体を元に、多面体により球の近似を行なうためのユーティリティスクリプトです。
3DS MAX がインストールされているディレクトリ下の、Scripts\Startup へ登録してください。


-- *****************************************************************
--      正20面体と、それを基にした球近似多面体を生成する
--
--      Coded By Yoshiaki Tanaka
--      2000/03/13
-- *****************************************************************
utility Iconsahedron "正20面体生成"
(
--
-- ユーザーインターフェース定義
--
    spinner rspin "最大半径" range:[0.001,20000,50]
    button do_create20 "正20面体生成" Width:180
    button do_create80 "80面体生成"   Width:180
    button do_create120 "120面体生成"   Width:180
    button do_create180 "180面体生成"   Width:180
    button do_create320 "320面体生成"   Width:180
    button do_create720 "720面体生成"   Width:180

-- 正20面体のベース頂点セット --
    fn      set_20      faces verts   =
    (
        Local   i
        Local vertbase = #(  [  0,            0,            1             ] ,   \ -- 1
                     [  0.8944272,    0,            0.4472136     ] ,   \ -- 2
                     [  0.2763932,    0.8506508,    0.4472136     ] ,   \ -- 3
                     [ -0.7236069,    0.5257311,    0.4472136     ] ,   \ -- 4
                     [ -0.7236068,   -0.5257312,    0.4472136     ] ,   \ -- 5
                     [  0.2763933,   -0.8506508,    0.4472136     ] ,   \ -- 6
                     [  0.7236067,    0.5257311,   -0.4472136     ] ,   \ -- 7
                     [ -0.2763932,    0.8506507,   -0.4472136     ] ,   \ -- 8
                     [ -0.8944271,    0,           -0.4472136     ] ,   \ -- 9
                     [ -0.2763933,   -0.8506507,   -0.4472136     ] ,   \ -- 10
                     [  0.7236069,   -0.5257308,   -0.4472136     ] ,   \ -- 11
                     [  0,            0,           -1             ]     \ -- 12
                )
        -- 正20面体のフェースセット --
        Local facebase = #(                                                          \
                    [ 1,2,3 ],   [ 1,3,4 ],  [ 1,4,5 ],    [ 1,5,6 ],    [ 1,6,2 ],  \
                    [ 3,2,7 ],   [ 4,3,8 ],  [ 5,4,9 ],    [ 6,5,10 ],   [ 2,6,11 ], \
                    [ 3,7,8 ],   [ 4,8,9 ],  [ 5,9,10 ],   [ 6,10,11 ],  [ 2,11,7],  \
                    [ 8,7,12 ],  [ 9,8,12],  [ 10,9,12 ],  [ 11,10,12],  [ 7,11,12 ] \
                )
        for i = 1 to vertbase.count do
        (
            verts[i] = vertbase[i]
        )
        for i = 1 to facebase.count do
        (
            faces[i] = facebase[i]
        )

    )

-- 頂点重複チェック&埋め込み --
    fn  check_vert vert vertset  =
    (
        Local   li, temp
        for li = 1 to vertset.count do
        (
            temp = length (vertset[li] - vert)
            if temp < 0.01 do 
                return li                   -- 発見!
        )
        -- 見付からなかったので追加
        vertset[vertset.count+1] = vert
        vertset.count
    )

-- ポリゴン3分割 --
    fn  polygon_div3    faces verts nfaces nverts =
    (
        Local   i,p1,p2,p3,va,pa
        Local   fcount = 1
        -- 元の頂点をコピーしておく
        for i = 1 to verts.count do
        (
            nverts[i] = verts[i]
        )
        -- ポリゴン分割 --
        for i = 1 to faces.count do
        (
            -- 追加頂点計算 --
            p1 = faces[i].x
            p2 = faces[i].y
            p3 = faces[i].z
            va = normalize( (verts[p1] + verts[p2] + verts[p3]) / 3 )
            pa = check_vert va nverts
            --フェース3分割 --
            nfaces[fcount+0] = [p1, p2, pa]
            nfaces[fcount+1] = [pa, p2, p3]
            nfaces[fcount+2] = [p3, p1, pa]
            fcount = fcount + 3
        )
    )

-- ポリゴン4分割 --
    fn  polygon_div4    faces verts nfaces nverts =
    (
        Local   i,p1,p2,p3,va,vb,vc,pa,pb,pc
        Local   fcount = 1
        -- 元の頂点をコピーしておく
        for i = 1 to verts.count do
        (
            nverts[i] = verts[i]
        )
        -- ポリゴン分割 --
        for i = 1 to faces.count do
        (
            -- 追加頂点計算 --
            p1 = faces[i].x
            p2 = faces[i].y
            p3 = faces[i].z
            va = normalize( (verts[p1] + verts[p2]) / 2 )
            pa = check_vert va nverts
            vb = normalize( (verts[p2] + verts[p3]) / 2 )
            pb = check_vert vb nverts
            vc = normalize( (verts[p3] + verts[p1]) / 2 )
            pc = check_vert vc nverts
            --フェース4分割 --
            nfaces[fcount+0] = [pa, pb, pc]
            nfaces[fcount+1] = [p1, pa, pc]
            nfaces[fcount+2] = [p2, pb, pa]
            nfaces[fcount+3] = [p3, pc, pb]
            fcount = fcount + 4
        )
    )

-- ポリゴン6分割 --
    fn  polygon_div6    faces verts nfaces nverts =
    (
        Local   i,p1,p2,p3,v,pa,pb,pc,pd
        Local   fcount = 1
        -- 元の頂点をコピーしておく
        for i = 1 to verts.count do
        (
            nverts[i] = verts[i]
        )
        -- ポリゴン分割 --
        for i = 1 to faces.count do
        (
            -- 追加頂点計算 --
            p1 = faces[i].x
            p2 = faces[i].y
            p3 = faces[i].z
            v = normalize( (verts[p1] + verts[p2] + verts[p3]) / 3 )
            pa = check_vert v nverts
            v = normalize( (verts[p1] + verts[p2]) / 2 )
            pb = check_vert v nverts
            v = normalize( (verts[p2] + verts[p3]) / 2 )
            pc = check_vert v nverts
            v = normalize( (verts[p3] + verts[p1]) / 2 )
            pd = check_vert v nverts
            --フェース6分割 --
            nfaces[fcount+0] = [pa, p1, pb]
            nfaces[fcount+1] = [pa, pb, p2]
            nfaces[fcount+2] = [pa, p2, pc]
            nfaces[fcount+3] = [pa, pc, p3]
            nfaces[fcount+4] = [pa, p3, pd]
            nfaces[fcount+5] = [pa, pd, p1]
            fcount = fcount + 6
        )
    )


-- ポリゴン9分割 --
    fn  polygon_div9    faces verts nfaces nverts =
    (
        Local   fcount = 1
        Local   pa,pb,pc,pd,pe,pf,pg,p1,p2,p3,v
        Local   i
        -- 頂点をコピーしておく
        for i = 1 to verts.count do
        (
            nverts[i] = verts[i]
        )
        fcount = 1
        -- ポリゴン分割 --
        for i = 1 to faces.count do
        (
            -- 追加頂点計算 --
            p1 = faces[i].x
            p2 = faces[i].y
            p3 = faces[i].z
            v = normalize( verts[p1] + (verts[p2] - verts[p1]) / 3 )
            pa = check_vert v nverts
            v = normalize( verts[p2] + (verts[p1] - verts[p2]) / 3 )
            pb = check_vert v nverts
            v = normalize( verts[p1] + (verts[p3] - verts[p1]) / 3 )
            pc = check_vert v nverts
            v = normalize( verts[p1] + verts[p2] + verts[p3] )
            pd = check_vert v nverts
            v = normalize( verts[p2] + (verts[p3] - verts[p2]) / 3 )
            pe = check_vert v nverts
            v = normalize( verts[p3] + (verts[p1] - verts[p3]) / 3 )
            pf = check_vert v nverts
            v = normalize( verts[p3] + (verts[p2] - verts[p3]) / 3 )
            pg = check_vert v nverts
            --フェース9分割 --
            nfaces[fcount+0] = [p1, pa, pc]
            nfaces[fcount+1] = [pc, pa, pd]
            nfaces[fcount+2] = [pc, pd, pf]
            nfaces[fcount+3] = [pf, pd, pg]
            nfaces[fcount+4] = [p3, pf, pg]
            nfaces[fcount+5] = [pa, pb, pd]
            nfaces[fcount+6] = [pd, pb, pe]
            nfaces[fcount+7] = [pd, pe, pg]
            nfaces[fcount+8] = [p2, pe, pb]
            fcount = fcount + 9
        )
    )

-- メッシュの生成 --
    fn  meshcreate face vert  =
    (
        Local   i
        -- 半径に応じて拡大・縮小 --
        for i = 1 to vert.count do
        (
            vert[i] = vert[i] * rspin.value
        )
        Local tobj = mesh vertices:vert  faces:face
        for i = 1 to tobj.numfaces do
        (
            setFaceSmoothGroup tobj i 1 
        )
        update tobj
    )

--
-- アクション定義
--

---------- 正20面体生成 ----------
    on do_create20 pressed do
    (
        Local vert20
        Local face20

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        meshcreate  face20 vert20
    )
---------- 正20面体を基礎とした80面体を生成 ----------
    on do_create80 pressed do
    (
        Local   vert20, vert80
        Local   face20, face80

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert80 = #()
        face80 = #()
        -- ポリゴン分割 --
        polygon_div4    face20 vert20 face80 vert80
        meshcreate  face80 vert80
    )
---------- 正20面体を基礎とした120面体を生成 ----------
    on do_create120 pressed do
    (
        Local   vert20, vert120
        Local   face20, face120

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert120 = #()
        face120 = #()
        -- ポリゴン分割 --
        polygon_div6    face20 vert20 face120 vert120
        meshcreate  face120 vert120
    )
---------- 正20面体を基礎とした180面体を生成 ----------
    on do_create180 pressed do
    (
        Local   vert20, vert180
        Local   face20, face180

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert180 = #()
        face180 = #()
        -- ポリゴン分割 --
        polygon_div9    face20 vert20 face180 vert180
        meshcreate  face180 vert180
    )
---------- 正20面体を基礎とした240面体を生成 ----------
    on do_create240 pressed do
    (
        Local   vert20, vert80, vert240
        Local   face20, face80, face240

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert80 = #()
        face80 = #()
        vert240 = #()
        face240 = #()
        -- ポリゴン分割 --
        polygon_div4    face20 vert20 face80 vert80
        polygon_div3    face80 vert80 face240 vert240
        meshcreate  face240 vert240
    )
---------- 正20面体を基礎とした320面体を生成 ----------
    on do_create320 pressed do
    (
        Local   vert20, vert80, vert320
        Local   face20, face80, face320

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert80 = #()
        face80 = #()
        vert320 = #()
        face320 = #()
        -- ポリゴン分割 --
        polygon_div4    face20 vert20 face80 vert80
        polygon_div4    face80 vert80 face320 vert320
        meshcreate  face320 vert320
    )
---------- 正20面体を基礎とした720面体を生成 ----------
    on do_create720 pressed do
    (
        Local   vert20, vert180, vert720
        Local   face20, face180, face720

        -- 基本法線設定 --
        vert20 = #()
        face20 = #()
        set_20  face20 vert20
        vert180 = #()
        face180 = #()
        vert720 = #()
        face720 = #()
        -- ポリゴン分割 --
        polygon_div9    face20 vert20 face180 vert180
        polygon_div4    face180 vert180 face720 vert720
        meshcreate  face720 vert720
    )
)